2020-09-06 16:47:38 +01:00
|
|
|
/*
|
2021-12-31 21:40:36 +00:00
|
|
|
* Copyright (C) 2020-2022 Gavin MacGregor
|
2020-09-06 16:47:38 +01:00
|
|
|
*
|
|
|
|
|
* This file is part of QTeletextMaker.
|
|
|
|
|
*
|
|
|
|
|
* QTeletextMaker is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* QTeletextMaker is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with QTeletextMaker. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
#include <QBitmap>
|
2020-09-06 16:47:38 +01:00
|
|
|
#include <QPainter>
|
2022-04-02 22:38:38 +01:00
|
|
|
#include <QPixmap>
|
2020-09-06 16:47:38 +01:00
|
|
|
|
|
|
|
|
#include "render.h"
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
#include "decode.h"
|
|
|
|
|
|
2021-06-23 11:23:11 +01:00
|
|
|
int TeletextFontBitmap::s_instances = 0;
|
|
|
|
|
|
|
|
|
|
QBitmap *TeletextFontBitmap::s_fontBitmap = nullptr;
|
|
|
|
|
|
|
|
|
|
TeletextFontBitmap::TeletextFontBitmap()
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2021-06-23 11:23:11 +01:00
|
|
|
if (s_instances == 0)
|
|
|
|
|
s_fontBitmap = new QBitmap(":/images/teletextfont.png");
|
|
|
|
|
s_instances++;
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2021-06-23 11:23:11 +01:00
|
|
|
TeletextFontBitmap::~TeletextFontBitmap()
|
|
|
|
|
{
|
|
|
|
|
s_instances--;
|
|
|
|
|
if (s_instances == 0)
|
|
|
|
|
delete s_fontBitmap;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
|
2021-06-23 11:23:11 +01:00
|
|
|
TeletextPageRender::TeletextPageRender()
|
|
|
|
|
{
|
2020-09-06 16:47:38 +01:00
|
|
|
for (int i=0; i<6; i++)
|
|
|
|
|
m_pagePixmap[i] = new QPixmap(864, 250);
|
|
|
|
|
m_pagePixmap[0]->fill(Qt::transparent);
|
2022-04-02 22:38:38 +01:00
|
|
|
|
|
|
|
|
m_reveal = false;
|
|
|
|
|
m_mix = false;
|
|
|
|
|
m_showControlCodes = false;
|
|
|
|
|
m_flashBuffersHz = 0;
|
|
|
|
|
|
|
|
|
|
for (int r=0; r<25; r++)
|
|
|
|
|
for (int c=0; c<40; c++)
|
|
|
|
|
m_controlCodeCache[r][c] = 0x7f;
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TeletextPageRender::~TeletextPageRender()
|
|
|
|
|
{
|
|
|
|
|
for (int i=0; i<6; i++)
|
|
|
|
|
delete m_pagePixmap[i];
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
void TeletextPageRender::setDecoder(TeletextPageDecode *decoder)
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2022-04-02 22:38:38 +01:00
|
|
|
m_decoder = decoder;
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
inline void TeletextPageRender::drawFromFontBitmap(QPainter &pixmapPainter, int r, int c, unsigned char characterCode, int characterSet, TeletextPageDecode::CharacterFragment characterFragment)
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2022-04-02 22:38:38 +01:00
|
|
|
switch (characterFragment) {
|
|
|
|
|
case TeletextPageDecode::NormalSize:
|
|
|
|
|
pixmapPainter.drawPixmap(c*12, r*10, *m_fontBitmap.rawBitmap(), (characterCode-32)*12, characterSet*10, 12, 10);
|
|
|
|
|
break;
|
|
|
|
|
case TeletextPageDecode::DoubleHeightTopHalf:
|
|
|
|
|
pixmapPainter.drawPixmap(c*12, r*10, 12, 10, *m_fontBitmap.rawBitmap(), (characterCode-32)*12, characterSet*10, 12, 5);
|
|
|
|
|
break;
|
|
|
|
|
case TeletextPageDecode::DoubleHeightBottomHalf:
|
|
|
|
|
pixmapPainter.drawPixmap(c*12, r*10, 12, 10, *m_fontBitmap.rawBitmap(), (characterCode-32)*12, characterSet*10+5, 12, 5);
|
|
|
|
|
break;
|
|
|
|
|
case TeletextPageDecode::DoubleWidthLeftHalf:
|
|
|
|
|
pixmapPainter.drawPixmap(c*12, r*10, 12, 10, *m_fontBitmap.rawBitmap(), (characterCode-32)*12, characterSet*10, 6, 10);
|
|
|
|
|
break;
|
|
|
|
|
case TeletextPageDecode::DoubleWidthRightHalf:
|
|
|
|
|
pixmapPainter.drawPixmap(c*12, r*10, 12, 10, *m_fontBitmap.rawBitmap(), (characterCode-32)*12+6, characterSet*10, 6, 10);
|
|
|
|
|
break;
|
|
|
|
|
case TeletextPageDecode::DoubleSizeTopLeftQuarter:
|
|
|
|
|
pixmapPainter.drawPixmap(c*12, r*10, 12, 10, *m_fontBitmap.rawBitmap(), (characterCode-32)*12, characterSet*10, 6, 5);
|
|
|
|
|
break;
|
|
|
|
|
case TeletextPageDecode::DoubleSizeTopRightQuarter:
|
|
|
|
|
pixmapPainter.drawPixmap(c*12, r*10, 12, 10, *m_fontBitmap.rawBitmap(), (characterCode-32)*12+6, characterSet*10, 6, 5);
|
|
|
|
|
break;
|
|
|
|
|
case TeletextPageDecode::DoubleSizeBottomLeftQuarter:
|
|
|
|
|
pixmapPainter.drawPixmap(c*12, r*10, 12, 10, *m_fontBitmap.rawBitmap(), (characterCode-32)*12, characterSet*10+5, 6, 5);
|
|
|
|
|
break;
|
|
|
|
|
case TeletextPageDecode::DoubleSizeBottomRightQuarter:
|
|
|
|
|
pixmapPainter.drawPixmap(c*12, r*10, 12, 10, *m_fontBitmap.rawBitmap(), (characterCode-32)*12+6, characterSet*10+5, 6, 5);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
inline void TeletextPageRender::drawCharacter(QPainter &pixmapPainter, int r, int c, unsigned char characterCode, int characterSet, int characterDiacritical, TeletextPageDecode::CharacterFragment characterFragment)
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2022-04-02 22:38:38 +01:00
|
|
|
const bool dontUnderline = characterCode == 0x00;
|
|
|
|
|
if (dontUnderline)
|
|
|
|
|
characterCode = 0x20;
|
|
|
|
|
|
|
|
|
|
// If either foreground or background is set to transparent
|
|
|
|
|
// tinker with the QPainter settings so we get the desired result
|
|
|
|
|
if (!pixmapPainter.background().isOpaque()) {
|
|
|
|
|
if (pixmapPainter.pen().color().alpha() == 0) {
|
|
|
|
|
// Transparent foreground and background
|
|
|
|
|
pixmapPainter.setCompositionMode(QPainter::CompositionMode_Clear);
|
|
|
|
|
pixmapPainter.eraseRect(c*12, r*10, 12, 10);
|
|
|
|
|
pixmapPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
return;
|
|
|
|
|
} else
|
|
|
|
|
// Transparent background, opaque foreground
|
|
|
|
|
pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);
|
|
|
|
|
} else if (pixmapPainter.pen().color().alpha() == 0) {
|
|
|
|
|
// Transparent foreground, opaque background
|
|
|
|
|
// Deal with optimising G1 solid 7/F blocks and spaces now
|
|
|
|
|
// otherwise the same optimisations later on won't work with
|
|
|
|
|
// our tinkered QPainter settings
|
|
|
|
|
if (characterCode == 0x7f && characterSet == 24) {
|
|
|
|
|
pixmapPainter.setCompositionMode(QPainter::CompositionMode_Clear);
|
|
|
|
|
pixmapPainter.eraseRect(c*12, r*10, 12, 10);
|
|
|
|
|
pixmapPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
pixmapPainter.fillRect(c*12, r*10, 12, 10, m_decoder->cellBackgroundQColor(r, c));
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (characterCode == 0x20 && characterSet < 25 && characterDiacritical == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pixmapPainter.setBackground(QColor(0, 0, 0, 0));
|
|
|
|
|
pixmapPainter.setPen(QColor(255, 255, 255, 255));
|
|
|
|
|
pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (characterCode == 0x20 && characterSet < 25 && characterDiacritical == 0)
|
|
|
|
|
pixmapPainter.fillRect(c*12, r*10, 12, 10, pixmapPainter.background().color());
|
|
|
|
|
else if (characterCode == 0x7f && characterSet == 24)
|
|
|
|
|
pixmapPainter.fillRect(c*12, r*10, 12, 10, pixmapPainter.pen().color());
|
2020-09-06 16:47:38 +01:00
|
|
|
else
|
2022-04-02 22:38:38 +01:00
|
|
|
drawFromFontBitmap(pixmapPainter, r, c, characterCode, characterSet, characterFragment);
|
|
|
|
|
|
|
|
|
|
if (m_decoder->cellUnderlined(r, c) && !dontUnderline)
|
|
|
|
|
switch (characterFragment) {
|
|
|
|
|
case TeletextPageDecode::NormalSize:
|
|
|
|
|
case TeletextPageDecode::DoubleWidthLeftHalf:
|
|
|
|
|
case TeletextPageDecode::DoubleWidthRightHalf:
|
|
|
|
|
pixmapPainter.drawLine(c*12, r*10+9, c*12+11, r*10+9);
|
|
|
|
|
break;
|
|
|
|
|
case TeletextPageDecode::DoubleHeightBottomHalf:
|
|
|
|
|
case TeletextPageDecode::DoubleSizeBottomLeftQuarter:
|
|
|
|
|
case TeletextPageDecode::DoubleSizeBottomRightQuarter:
|
|
|
|
|
pixmapPainter.drawRect(c*12, r*10+8, 11, 1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (characterDiacritical != 0) {
|
|
|
|
|
pixmapPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
|
|
|
|
pixmapPainter.setBackgroundMode(Qt::TransparentMode);
|
|
|
|
|
drawFromFontBitmap(pixmapPainter, r, c, characterDiacritical+64, 7, characterFragment);
|
|
|
|
|
pixmapPainter.setBackgroundMode(Qt::OpaqueMode);
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (pixmapPainter.compositionMode() != QPainter::CompositionMode_SourceOver)
|
|
|
|
|
pixmapPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
void TeletextPageRender::renderPage(bool force)
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2022-04-02 22:38:38 +01:00
|
|
|
QPainter pixmapPainter[6];
|
|
|
|
|
int previousFlashBuffersHz = m_flashBuffersHz;
|
|
|
|
|
|
|
|
|
|
// If force-rendering (such as showing a new or different subpage) then
|
|
|
|
|
// we don't render flashing cells initially as it greatly speeds things up
|
|
|
|
|
// when rendering on top of an already flashing page.
|
|
|
|
|
// At the end of this method, if flashing cells are present then this method
|
|
|
|
|
// recursively calls itself with force=false to render the flashing cells.
|
|
|
|
|
if (force) {
|
|
|
|
|
m_flashBuffersHz = 0;
|
|
|
|
|
previousFlashBuffersHz = 0;
|
|
|
|
|
emit flashChanged(0);
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
pixmapPainter[0].begin(m_pagePixmap[0]);
|
|
|
|
|
pixmapPainter[0].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
if (m_flashBuffersHz != 0) {
|
|
|
|
|
pixmapPainter[3].begin(m_pagePixmap[3]);
|
|
|
|
|
pixmapPainter[3].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
if (m_flashBuffersHz == 2) {
|
|
|
|
|
pixmapPainter[1].begin(m_pagePixmap[1]);
|
|
|
|
|
pixmapPainter[1].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
pixmapPainter[2].begin(m_pagePixmap[2]);
|
|
|
|
|
pixmapPainter[2].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
pixmapPainter[4].begin(m_pagePixmap[4]);
|
|
|
|
|
pixmapPainter[4].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
pixmapPainter[5].begin(m_pagePixmap[5]);
|
|
|
|
|
pixmapPainter[5].setBackgroundMode(Qt::OpaqueMode);
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int r=0; r<25; r++)
|
2022-04-02 22:38:38 +01:00
|
|
|
for (int c=0; c<72; c++) {
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
bool controlCodeChanged = false;
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
// Ensure that shown control codes are refreshed
|
|
|
|
|
if (m_showControlCodes && c < 40 && (m_controlCodeCache[r][c] != 0x7f || m_decoder->teletextPage()->character(r, c) < 0x20)) {
|
|
|
|
|
controlCodeChanged = m_controlCodeCache[r][c] != m_decoder->teletextPage()->character(r, c);
|
|
|
|
|
if (controlCodeChanged) {
|
|
|
|
|
if (m_decoder->teletextPage()->character(r, c) < 0x20)
|
|
|
|
|
m_controlCodeCache[r][c] = m_decoder->teletextPage()->character(r, c);
|
2020-09-06 16:47:38 +01:00
|
|
|
else
|
2022-04-02 22:38:38 +01:00
|
|
|
m_controlCodeCache[r][c] = 0x7f;
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (m_decoder->refresh(r, c) || force || controlCodeChanged) {
|
|
|
|
|
unsigned char characterCode;
|
|
|
|
|
int characterSet, characterDiacritical;
|
|
|
|
|
|
|
|
|
|
if (!m_reveal && m_decoder->cellConceal(r, c)) {
|
|
|
|
|
characterCode = 0x20;
|
|
|
|
|
characterSet = 0;
|
|
|
|
|
characterDiacritical = 0;
|
|
|
|
|
} else {
|
|
|
|
|
characterCode = m_decoder->cellCharacterCode(r, c);
|
|
|
|
|
characterSet = m_decoder->cellCharacterSet(r, c);
|
|
|
|
|
characterDiacritical = m_decoder->cellCharacterDiacritical(r, c);
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
// QSet::insert won't insert a duplicate value already in the set
|
|
|
|
|
// QSet::remove doesn't mind if we try to remove a value that's not there
|
|
|
|
|
if (m_flashBuffersHz == 0 && m_decoder->cellFlashMode(r, c) != 0) {
|
|
|
|
|
if (m_decoder->cellFlashRatePhase(r, c) == 0)
|
|
|
|
|
m_flash1HzCells.insert(qMakePair(r, c));
|
|
|
|
|
else
|
|
|
|
|
m_flash2HzCells.insert(qMakePair(r, c));
|
|
|
|
|
if (!force)
|
|
|
|
|
updateFlashBuffers();
|
|
|
|
|
} else if (m_decoder->cellFlashMode(r, c) == 0) {
|
|
|
|
|
m_flash1HzCells.remove(qMakePair(r, c));
|
|
|
|
|
m_flash2HzCells.remove(qMakePair(r, c));
|
|
|
|
|
if (!force)
|
|
|
|
|
updateFlashBuffers();
|
|
|
|
|
} else if (m_decoder->cellFlashRatePhase(r, c) == 0) {
|
|
|
|
|
m_flash1HzCells.insert(qMakePair(r, c));
|
|
|
|
|
m_flash2HzCells.remove(qMakePair(r, c));
|
|
|
|
|
if (!force)
|
|
|
|
|
updateFlashBuffers();
|
|
|
|
|
} else {
|
|
|
|
|
m_flash1HzCells.remove(qMakePair(r, c));
|
|
|
|
|
m_flash2HzCells.insert(qMakePair(r, c));
|
|
|
|
|
if (!force)
|
|
|
|
|
updateFlashBuffers();
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
// If flash rate has gone up, prepare painters for the other buffers
|
|
|
|
|
if (m_flashBuffersHz > previousFlashBuffersHz) {
|
|
|
|
|
if (previousFlashBuffersHz == 0) {
|
|
|
|
|
pixmapPainter[3].begin(m_pagePixmap[3]);
|
|
|
|
|
pixmapPainter[3].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
}
|
|
|
|
|
if (m_flashBuffersHz == 2) {
|
|
|
|
|
pixmapPainter[1].begin(m_pagePixmap[1]);
|
|
|
|
|
pixmapPainter[1].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
pixmapPainter[2].begin(m_pagePixmap[2]);
|
|
|
|
|
pixmapPainter[2].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
pixmapPainter[4].begin(m_pagePixmap[4]);
|
|
|
|
|
pixmapPainter[4].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
pixmapPainter[5].begin(m_pagePixmap[5]);
|
|
|
|
|
pixmapPainter[5].setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
|
}
|
|
|
|
|
previousFlashBuffersHz = m_flashBuffersHz;
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
// If flash rate has gone down, end the painters so we don't crash
|
|
|
|
|
// if the pixmaps get copied due to the flash rate going up again
|
|
|
|
|
if (m_flashBuffersHz < previousFlashBuffersHz) {
|
|
|
|
|
if (previousFlashBuffersHz == 2) {
|
|
|
|
|
pixmapPainter[1].end();
|
|
|
|
|
pixmapPainter[2].end();
|
|
|
|
|
pixmapPainter[4].end();
|
|
|
|
|
pixmapPainter[5].end();
|
|
|
|
|
}
|
|
|
|
|
if (m_flashBuffersHz == 0)
|
|
|
|
|
pixmapPainter[3].end();
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
previousFlashBuffersHz = m_flashBuffersHz;
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (m_flashBuffersHz == 0) {
|
|
|
|
|
pixmapPainter[0].setPen(m_decoder->cellForegroundQColor(r, c));
|
|
|
|
|
if (!m_mix || m_decoder->cellBoxed(r, c))
|
|
|
|
|
pixmapPainter[0].setBackground(m_decoder->cellBackgroundQColor(r, c));
|
|
|
|
|
else
|
|
|
|
|
pixmapPainter[0].setBackground(Qt::transparent);
|
|
|
|
|
drawCharacter(pixmapPainter[0], r, c, characterCode, characterSet, characterDiacritical, m_decoder->cellCharacterFragment(r, c));
|
|
|
|
|
} else {
|
|
|
|
|
for (int i=0; i<6; i++) {
|
|
|
|
|
if (m_flashBuffersHz == 1 && (i == 1 || i == 2 || i == 4 || i == 5))
|
|
|
|
|
continue;
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
bool phaseOn;
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (m_decoder->cellFlashRatePhase(r, c) == 0)
|
|
|
|
|
phaseOn = (i < 3) ^ (m_decoder->cellFlashMode(r, c) == 2);
|
|
|
|
|
else
|
|
|
|
|
phaseOn = ((i == m_decoder->cellFlash2HzPhaseNumber(r, c)-1) || (i == m_decoder->cellFlash2HzPhaseNumber(r, c)+2)) ^ (m_decoder->cellFlashMode(r, c) == 2);
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (!m_mix || m_decoder->cellBoxed(r, c))
|
|
|
|
|
pixmapPainter[i].setBackground(m_decoder->cellBackgroundQColor(r, c));
|
|
|
|
|
else
|
|
|
|
|
pixmapPainter[i].setBackground(Qt::transparent);
|
|
|
|
|
if (m_decoder->cellFlashMode(r, c) == 3 && !phaseOn)
|
|
|
|
|
pixmapPainter[i].setPen(m_decoder->cellFlashForegroundQColor(r, c));
|
|
|
|
|
else
|
|
|
|
|
pixmapPainter[i].setPen(m_decoder->cellForegroundQColor(r, c));
|
|
|
|
|
if ((m_decoder->cellFlashMode(r, c) == 1 || m_decoder->cellFlashMode(r, c) == 2) && !phaseOn)
|
|
|
|
|
// Character 0x00 draws space without underline
|
|
|
|
|
drawCharacter(pixmapPainter[i], r, c, 0x00, 0, 0, m_decoder->cellCharacterFragment(r, c));
|
|
|
|
|
else
|
|
|
|
|
drawCharacter(pixmapPainter[i], r, c, characterCode, characterSet, characterDiacritical, m_decoder->cellCharacterFragment(r, c));
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (m_showControlCodes && c < 40 && m_decoder->teletextPage()->character(r, c) < 0x20) {
|
|
|
|
|
pixmapPainter[0].setBackground(QColor(0, 0, 0, 128));
|
|
|
|
|
pixmapPainter[0].setPen(QColor(255, 255, 255, 224));
|
|
|
|
|
pixmapPainter[0].drawPixmap(c*12, r*10, *m_fontBitmap.rawBitmap(), (m_decoder->teletextPage()->character(r, c)+32)*12, 250, 12, 10);
|
|
|
|
|
if (m_flashBuffersHz == 1) {
|
|
|
|
|
pixmapPainter[3].setBackground(QColor(0, 0, 0, 128));
|
|
|
|
|
pixmapPainter[3].setPen(QColor(255, 255, 255, 224));
|
|
|
|
|
pixmapPainter[3].drawPixmap(c*12, r*10, *m_fontBitmap.rawBitmap(), (m_decoder->teletextPage()->character(r, c)+32)*12, 250, 12, 10);
|
|
|
|
|
} else if (m_flashBuffersHz == 2)
|
|
|
|
|
for (int i=1; i<6; i++) {
|
|
|
|
|
pixmapPainter[i].setBackground(QColor(0, 0, 0, 128));
|
|
|
|
|
pixmapPainter[i].setPen(QColor(255, 255, 255, 224));
|
|
|
|
|
pixmapPainter[i].drawPixmap(c*12, r*10, *m_fontBitmap.rawBitmap(), (m_decoder->teletextPage()->character(r, c)+32)*12, 250, 12, 10);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (!force || m_decoder->cellFlashMode(r, c) == 0)
|
|
|
|
|
m_decoder->setRefresh(r, c, false);
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
pixmapPainter[0].end();
|
|
|
|
|
if (m_flashBuffersHz != 0) {
|
|
|
|
|
pixmapPainter[3].end();
|
|
|
|
|
if (m_flashBuffersHz == 2) {
|
|
|
|
|
pixmapPainter[1].end();
|
|
|
|
|
pixmapPainter[2].end();
|
|
|
|
|
pixmapPainter[4].end();
|
|
|
|
|
pixmapPainter[5].end();
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (force && (!m_flash1HzCells.isEmpty() || !m_flash2HzCells.isEmpty()))
|
|
|
|
|
renderPage();
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
void TeletextPageRender::updateFlashBuffers()
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2022-04-02 22:38:38 +01:00
|
|
|
int highestFlashHz;
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (!m_flash2HzCells.isEmpty())
|
|
|
|
|
highestFlashHz = 2;
|
|
|
|
|
else
|
|
|
|
|
highestFlashHz = !m_flash1HzCells.isEmpty();
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (highestFlashHz == m_flashBuffersHz)
|
2020-09-06 16:47:38 +01:00
|
|
|
return;
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
if (highestFlashHz > m_flashBuffersHz) {
|
|
|
|
|
if (m_flashBuffersHz == 0)
|
|
|
|
|
*m_pagePixmap[3] = m_pagePixmap[0]->copy();
|
|
|
|
|
if (highestFlashHz == 2) {
|
|
|
|
|
*m_pagePixmap[1] = m_pagePixmap[0]->copy();
|
|
|
|
|
*m_pagePixmap[2] = m_pagePixmap[0]->copy();
|
|
|
|
|
*m_pagePixmap[4] = m_pagePixmap[3]->copy();
|
|
|
|
|
*m_pagePixmap[5] = m_pagePixmap[3]->copy();
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
m_flashBuffersHz = highestFlashHz;
|
|
|
|
|
emit flashChanged(m_flashBuffersHz);
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
void TeletextPageRender::colourChanged(int index)
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2022-04-02 22:38:38 +01:00
|
|
|
for (int r=0; r<25; r++)
|
|
|
|
|
for (int c=0; c<72; c++) {
|
|
|
|
|
if (m_decoder->cellForegroundCLUT(r, c) == index || m_decoder->cellBackgroundCLUT(r, c) == index || m_decoder->cellForegroundCLUT(r, c) == 8 || m_decoder->cellBackgroundCLUT(r, c) == 8)
|
|
|
|
|
m_decoder->setRefresh(r, c, true);
|
|
|
|
|
if (m_decoder->cellFlashMode(r, c) == 3 && ((m_decoder->cellForegroundCLUT(r, c) ^ 8) == index || (m_decoder->cellForegroundCLUT(r, c) ^ 8) == 8))
|
|
|
|
|
m_decoder->setRefresh(r, c, true);
|
|
|
|
|
}
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
void TeletextPageRender::setReveal(bool reveal)
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2022-04-02 22:38:38 +01:00
|
|
|
if (reveal == m_reveal)
|
2020-09-06 16:47:38 +01:00
|
|
|
return;
|
2021-01-31 11:54:45 +00:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
m_reveal = reveal;
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
for (int r=0; r<25; r++)
|
|
|
|
|
for (int c=0; c<72; c++)
|
|
|
|
|
if (m_decoder->cellConceal(r, c))
|
|
|
|
|
m_decoder->setRefresh(r, c, true);
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
void TeletextPageRender::setMix(bool mix)
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2022-04-02 22:38:38 +01:00
|
|
|
if (mix == m_mix)
|
|
|
|
|
return;
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
m_mix = mix;
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
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);
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
void TeletextPageRender::setShowControlCodes(bool showControlCodes)
|
2020-09-06 16:47:38 +01:00
|
|
|
{
|
2022-04-02 22:38:38 +01:00
|
|
|
if (showControlCodes == m_showControlCodes)
|
2020-09-06 16:47:38 +01:00
|
|
|
return;
|
|
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
m_showControlCodes = showControlCodes;
|
2020-09-06 16:47:38 +01:00
|
|
|
|
2022-04-02 22:38:38 +01:00
|
|
|
for (int r=0; r<25; r++)
|
|
|
|
|
for (int c=0; c<40; c++)
|
|
|
|
|
if (m_decoder->teletextPage()->character(r, c) < 0x20)
|
|
|
|
|
m_decoder->setRefresh(r, c, true);
|
2020-09-06 16:47:38 +01:00
|
|
|
}
|