diff --git a/src/qteletextdecoder/render.cpp b/src/qteletextdecoder/render.cpp index 486f536..4ec8509 100644 --- a/src/qteletextdecoder/render.cpp +++ b/src/qteletextdecoder/render.cpp @@ -60,7 +60,7 @@ TeletextPageRender::TeletextPageRender() m_pageImage[i] = new QImage(864, 250, QImage::Format_ARGB32_Premultiplied); m_reveal = false; - m_mix = false; + m_renderMode = RenderNormal; m_showControlCodes = false; m_flashBuffersHz = 0; @@ -226,6 +226,13 @@ inline void TeletextPageRender::drawBoldOrItalicCharacter(QPainter &painter, int void TeletextPageRender::renderPage(bool force) { + if (m_renderMode == RenderWhiteOnBlack) { + m_foregroundQColor = Qt::white; + m_backgroundQColor = Qt::black; + } else if (m_renderMode == RenderBlackOnWhite) { + m_foregroundQColor = Qt::black; + m_backgroundQColor = Qt::white; + } for (int r=0; r<25; r++) renderRow(r, 0, force); } @@ -253,9 +260,11 @@ void TeletextPageRender::renderRow(int r, int ph, bool force) } } - if (ph == 0) { + // Second part of "if" suppresses all flashing on monochrome render modes + if (ph == 0 && m_renderMode < RenderWhiteOnBlack) { if (m_decoder->cellFlashMode(r, c) != 0) flashingRow = qMax(flashingRow, (m_decoder->cellFlashRatePhase(r, c) == 0) ? 1 : 2); +// } else if (!force) } else force = m_decoder->cellFlashMode(r, c) != 0; @@ -278,36 +287,38 @@ void TeletextPageRender::renderRow(int r, int ph, bool force) characterDiacritical = m_decoder->cellCharacterDiacritical(r, c); } - if (m_decoder->cellFlashMode(r, c) == 0) - m_foregroundQColor = m_decoder->cellForegroundQColor(r, c); - else { - // Flashing cell, decide if phase in this cycle is on or off - bool phaseOn; - - if (m_decoder->cellFlashRatePhase(r, c) == 0) - phaseOn = (ph < 3) ^ (m_decoder->cellFlashMode(r, c) == 2); - else - phaseOn = ((ph == m_decoder->cellFlash2HzPhaseNumber(r, c)-1) || (ph == m_decoder->cellFlash2HzPhaseNumber(r, c)+2)) ^ (m_decoder->cellFlashMode(r, c) == 2); - - // If flashing to adjacent CLUT select the appropriate foreground colour - if (m_decoder->cellFlashMode(r, c) == 3 && !phaseOn) - m_foregroundQColor = m_decoder->cellFlashForegroundQColor(r, c); - else + if (m_renderMode < RenderWhiteOnBlack) { + if (m_decoder->cellFlashMode(r, c) == 0) m_foregroundQColor = m_decoder->cellForegroundQColor(r, c); + else { + // Flashing cell, decide if phase in this cycle is on or off + bool phaseOn; - // If flashing mode is Normal or Invert, draw a space instead of a character on phase - if ((m_decoder->cellFlashMode(r, c) == 1 || m_decoder->cellFlashMode(r, c) == 2) && !phaseOn) { - // Character 0x00 draws space without underline - characterCode = 0x00; - characterSet = 0; - characterDiacritical = 0; + if (m_decoder->cellFlashRatePhase(r, c) == 0) + phaseOn = (ph < 3) ^ (m_decoder->cellFlashMode(r, c) == 2); + else + phaseOn = ((ph == m_decoder->cellFlash2HzPhaseNumber(r, c)-1) || (ph == m_decoder->cellFlash2HzPhaseNumber(r, c)+2)) ^ (m_decoder->cellFlashMode(r, c) == 2); + + // If flashing to adjacent CLUT select the appropriate foreground colour + if (m_decoder->cellFlashMode(r, c) == 3 && !phaseOn) + m_foregroundQColor = m_decoder->cellFlashForegroundQColor(r, c); + else + m_foregroundQColor = m_decoder->cellForegroundQColor(r, c); + + // If flashing mode is Normal or Invert, draw a space instead of a character on phase + if ((m_decoder->cellFlashMode(r, c) == 1 || m_decoder->cellFlashMode(r, c) == 2) && !phaseOn) { + // Character 0x00 draws space without underline + characterCode = 0x00; + characterSet = 0; + characterDiacritical = 0; + } } - } - if (!m_mix || m_decoder->cellBoxed(r, c)) - m_backgroundQColor = m_decoder->cellBackgroundQColor(r, c); - else - m_backgroundQColor = Qt::transparent; + if (m_renderMode != RenderMix || m_decoder->cellBoxed(r, c)) + m_backgroundQColor = m_decoder->cellBackgroundQColor(r, c); + else + m_backgroundQColor = Qt::transparent; + } drawCharacter(painter, r, c, characterCode, characterSet, characterDiacritical, m_decoder->cellCharacterFragment(r, c)); @@ -439,17 +450,16 @@ void TeletextPageRender::setReveal(bool reveal) m_decoder->setRefresh(r, c, true); } -void TeletextPageRender::setMix(bool mix) +void TeletextPageRender::setRenderMode(RenderMode renderMode) { - if (mix == m_mix) + if (renderMode == m_renderMode) return; - m_mix = mix; + m_renderMode = renderMode; for (int r=0; r<25; r++) for (int c=0; c<72; c++) - if (!m_decoder->cellBoxed(r, c)) - m_decoder->setRefresh(r, c, true); + m_decoder->setRefresh(r, c, true); } diff --git a/src/qteletextdecoder/render.h b/src/qteletextdecoder/render.h index 225cc06..6c468aa 100644 --- a/src/qteletextdecoder/render.h +++ b/src/qteletextdecoder/render.h @@ -49,11 +49,13 @@ class TeletextPageRender : public QObject Q_OBJECT public: + enum RenderMode { RenderNormal, RenderMix, RenderWhiteOnBlack, RenderBlackOnWhite }; + TeletextPageRender(); ~TeletextPageRender(); QImage* image(int i) const { return m_pageImage[i]; }; - bool mix() const { return m_mix; }; + RenderMode renderMode() const { return m_renderMode; }; void setDecoder(TeletextPageDecode *decoder); void renderPage(bool force=false); bool showControlCodes() const { return m_showControlCodes; }; @@ -61,7 +63,7 @@ public: public slots: void colourChanged(int index); void setReveal(bool reveal); - void setMix(bool mix); + void setRenderMode(RenderMode renderMode); void setShowControlCodes(bool showControlCodes); signals: @@ -71,7 +73,8 @@ protected: TeletextFontBitmap m_fontBitmap; QImage* m_pageImage[6]; unsigned char m_controlCodeCache[25][40]; - bool m_reveal, m_mix, m_showControlCodes; + RenderMode m_renderMode; + bool m_reveal, m_showControlCodes; int m_flashBuffersHz; int m_flashingRow[25]; diff --git a/src/qteletextmaker/mainwidget.cpp b/src/qteletextmaker/mainwidget.cpp index ac13f40..b304250 100644 --- a/src/qteletextmaker/mainwidget.cpp +++ b/src/qteletextmaker/mainwidget.cpp @@ -161,18 +161,18 @@ void TeletextWidget::setReveal(bool reveal) update(); } -void TeletextWidget::setMix(bool mix) -{ - m_pageRender.setMix(mix); - update(); -} - void TeletextWidget::setShowControlCodes(bool showControlCodes) { m_pageRender.setShowControlCodes(showControlCodes); update(); } +void TeletextWidget::setRenderMode(TeletextPageRender::RenderMode renderMode) +{ + m_pageRender.setRenderMode(renderMode); + update(); +} + void TeletextWidget::setControlBit(int bitNumber, bool active) { m_levelOnePage->setControlBit(bitNumber, active); @@ -705,19 +705,34 @@ void LevelOneScene::updateSelection() m_selectionRectItem->setVisible(true); } -void LevelOneScene::setMix(bool mix) +void LevelOneScene::setRenderMode(TeletextPageRender::RenderMode renderMode) { - if (mix) { - m_fullScreenTopRectItem->setBrush(Qt::transparent); - m_fullScreenBottomRectItem->setBrush(Qt::transparent); - for (int r=0; r<25; r++) { - m_fullRowLeftRectItem[r]->setBrush(Qt::transparent); - m_fullRowRightRectItem[r]->setBrush(Qt::transparent); - } - } else { - setFullScreenColour(static_cast(m_levelOneProxyWidget->widget())->pageDecode()->fullScreenQColor()); - for (int r=0; r<25; r++) - setFullRowColour(r, static_cast(m_levelOneProxyWidget->widget())->pageDecode()->fullRowQColor(r)); + static_cast(m_levelOneProxyWidget->widget())->setRenderMode(renderMode); + + QColor fullColour; + + switch (renderMode) { + case TeletextPageRender::RenderNormal: + setFullScreenColour(static_cast(m_levelOneProxyWidget->widget())->pageDecode()->fullScreenQColor()); + for (int r=0; r<25; r++) + setFullRowColour(r, static_cast(m_levelOneProxyWidget->widget())->pageDecode()->fullRowQColor(r)); + return; + case TeletextPageRender::RenderMix: + fullColour = Qt::transparent; + break; + case TeletextPageRender::RenderWhiteOnBlack: + fullColour = Qt::black; + break; + case TeletextPageRender::RenderBlackOnWhite: + fullColour = Qt::white; + break; + } + + m_fullScreenTopRectItem->setBrush(fullColour); + m_fullScreenBottomRectItem->setBrush(fullColour); + for (int r=0; r<25; r++) { + m_fullRowLeftRectItem[r]->setBrush(fullColour); + m_fullRowRightRectItem[r]->setBrush(fullColour); } } @@ -782,7 +797,7 @@ void LevelOneScene::keyReleaseEvent(QKeyEvent *keyEvent) void LevelOneScene::setFullScreenColour(const QColor &newColor) { - if (!static_cast(m_levelOneProxyWidget->widget())->pageRender()->mix()) { + if (static_cast(m_levelOneProxyWidget->widget())->pageRender()->renderMode() == TeletextPageRender::RenderNormal) { m_fullScreenTopRectItem->setBrush(newColor); m_fullScreenBottomRectItem->setBrush(newColor); } @@ -790,7 +805,7 @@ void LevelOneScene::setFullScreenColour(const QColor &newColor) void LevelOneScene::setFullRowColour(int row, const QColor &newColor) { - if (!static_cast(m_levelOneProxyWidget->widget())->pageRender()->mix()) { + if (static_cast(m_levelOneProxyWidget->widget())->pageRender()->renderMode() == TeletextPageRender::RenderNormal) { m_fullRowLeftRectItem[row]->setBrush(newColor); m_fullRowRightRectItem[row]->setBrush(newColor); } diff --git a/src/qteletextmaker/mainwidget.h b/src/qteletextmaker/mainwidget.h index 7fe654b..7538f33 100644 --- a/src/qteletextmaker/mainwidget.h +++ b/src/qteletextmaker/mainwidget.h @@ -65,8 +65,8 @@ public slots: void subPageSelected(); void refreshPage(); void setReveal(bool reveal); - void setMix(bool mix); void setShowControlCodes(bool showControlCodes); + void setRenderMode(TeletextPageRender::RenderMode renderMode); void updateFlashTimer(int newFlashTimer); void pauseFlash(bool pauseNow); @@ -120,7 +120,7 @@ public: public slots: void updateCursor(); void updateSelection(); - void setMix(bool mix); + void setRenderMode(TeletextPageRender::RenderMode renderMode); void toggleGrid(bool gridOn); void hideGUIElements(bool hidden); void setFullScreenColour(const QColor &newColor); diff --git a/src/qteletextmaker/mainwindow.cpp b/src/qteletextmaker/mainwindow.cpp index 359cf68..d688b0a 100644 --- a/src/qteletextmaker/mainwindow.cpp +++ b/src/qteletextmaker/mainwindow.cpp @@ -189,11 +189,9 @@ void MainWindow::exportPNG() m_textWidget->pauseFlash(true); m_textScene->hideGUIElements(true); // Disable exporting in Mix mode as it corrupts the background - bool reMix = m_textWidget->pageRender()->mix(); - if (reMix) { - m_textWidget->setMix(false); - m_textScene->setMix(false); - } + bool reMix = m_textWidget->pageRender()->renderMode() == TeletextPageRender::RenderMix; + if (reMix) + m_textScene->setRenderMode(TeletextPageRender::RenderNormal); // Extract the image from the scene QImage interImage = QImage(m_textScene->sceneRect().size().toSize(), QImage::Format_RGB32); @@ -205,10 +203,8 @@ void MainWindow::exportPNG() // Now we've extracted the image we can put the GUI things back m_textScene->hideGUIElements(false); - if (reMix) { - m_textWidget->setMix(true); - m_textScene->setMix(true); - } + if (reMix) + m_textScene->setRenderMode(TeletextPageRender::RenderMix); m_textWidget->pauseFlash(false); // Now scale the extracted image to the selected aspect ratio @@ -503,13 +499,6 @@ void MainWindow::createActions() revealAct->setStatusTip(tr("Toggle reveal")); connect(revealAct, &QAction::toggled, m_textWidget, &TeletextWidget::setReveal); - QAction *mixAct = viewMenu->addAction(tr("&Mix")); - mixAct->setCheckable(true); - mixAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_M)); - mixAct->setStatusTip(tr("Toggle mix")); - connect(mixAct, &QAction::toggled, m_textWidget, &TeletextWidget::setMix); - connect(mixAct, &QAction::toggled, m_textScene, &LevelOneScene::setMix); - QAction *gridAct = viewMenu->addAction(tr("&Grid")); gridAct->setCheckable(true); gridAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_G)); @@ -524,6 +513,17 @@ void MainWindow::createActions() viewMenu->addSeparator(); + QMenu *renderModeSubMenu = viewMenu->addMenu(tr("Render mode")); + QAction *renderModeActs[4]; + renderModeActs[0] = renderModeSubMenu->addAction(tr("Normal")); + renderModeActs[0]->setStatusTip(tr("Render page normally")); + renderModeActs[1] = renderModeSubMenu->addAction(tr("Mix")); + renderModeActs[1]->setStatusTip(tr("Render page in mix mode")); + renderModeActs[2] = renderModeSubMenu->addAction(tr("White on black")); + renderModeActs[2]->setStatusTip(tr("Render page with white foreground on black background")); + renderModeActs[3] = renderModeSubMenu->addAction(tr("Black on white")); + renderModeActs[3]->setStatusTip(tr("Render page with black foreground on white background")); + QMenu *borderSubMenu = viewMenu->addMenu(tr("Border")); m_borderActs[0] = borderSubMenu->addAction(tr("None")); m_borderActs[0]->setStatusTip(tr("View with no border")); @@ -542,18 +542,26 @@ void MainWindow::createActions() m_aspectRatioActs[3] = aspectRatioSubMenu->addAction(tr("Pixel 1:2")); m_aspectRatioActs[3]->setStatusTip(tr("View with 1:2 pixel mapping")); + QActionGroup *renderModeGroup = new QActionGroup(this); QActionGroup *borderGroup = new QActionGroup(this); QActionGroup *aspectRatioGroup = new QActionGroup(this); for (int i=0; i<=3; i++) { + renderModeActs[i]->setCheckable(true); + connect(renderModeActs[i], &QAction::triggered, [=]() { m_textScene->setRenderMode(static_cast(i)); }); + renderModeGroup->addAction(renderModeActs[i]); + m_aspectRatioActs[i]->setCheckable(true); connect(m_aspectRatioActs[i], &QAction::triggered, [=]() { setAspectRatio(i); }); aspectRatioGroup->addAction(m_aspectRatioActs[i]); + if (i == 3) break; + m_borderActs[i]->setCheckable(true); connect(m_borderActs[i], &QAction::triggered, [=]() { setBorder(i); }); borderGroup->addAction(m_borderActs[i]); } + renderModeActs[0]->setChecked(true); viewMenu->addSeparator();