Skip to content
Permalink
Browse files

Fixes #9772. Applies patch by Jim Stichnoth to for CEA-608 to add col…

…or, italic and underline support.
  • Loading branch information
daniel-kristjansson committed Aug 11, 2011
1 parent 6bd5d1e commit 11adb5bf74bbf0326691f40b8c588e01d73febe2
@@ -43,6 +43,7 @@ CC608Decoder::CC608Decoder(CC608Input *ccr)
memset(lastrow, 0, sizeof(lastrow));
memset(newrow, 0, sizeof(newrow));
memset(newcol, 0, sizeof(newcol));
memset(newattr, 0, sizeof(newattr));
memset(timecode, 0, sizeof(timecode));
memset(row, 0, sizeof(row));
memset(col, 0, sizeof(col));
@@ -259,11 +260,27 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
newrow[mode] = lastrow[mode] + 1;

if (b2 & 0x10) //row contains indent flag
{
newcol[mode] = (b2 & 0x0E) << 1;
// Encode as 0x7020 or 0x7021 depending on the
// underline flag.
newattr[mode] = (b2 & 0x1) + 0x20;
LOG(VB_VBI, LOG_INFO,
QString("cc608 preamble indent, b2=%1")
.arg(b2, 2, 16));
}
else
{
newcol[mode] = 0;
newattr[mode] = (b2 & 0xf) + 0x10;
// Encode as 0x7010 through 0x702f for the 16 possible
// values of b2.
LOG(VB_VBI, LOG_INFO,
QString("cc608 preamble color change, b2=%1")
.arg(b2, 2, 16));
}

// row, indent settings are not final
// row, indent, attribute settings are not final
// until text code arrives
}
else
@@ -283,8 +300,12 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
switch (b2 & 0x70)
{
case 0x20: //midrow attribute change
// TODO: we _do_ want colors, is that an attribute?
ccbuf[mode] += ' ';
LOG(VB_VBI, LOG_INFO,
QString("cc608 mid-row color change, b2=%1")
.arg(b2, 2, 16));
// Encode as 0x7000 through 0x700f for the
// 16 possible values of b2.
ccbuf[mode] += QChar(0x7000 + (b2 & 0xf));
len = ccbuf[mode].length();
col[mode]++;
break;
@@ -421,6 +442,7 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
{
newrow[mode] = 1;
newcol[mode] = 0;
newattr[mode] = 0;
}
style[mode] = CC_STYLE_ROLLUP;
break;
@@ -483,6 +505,7 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
// TXT starts at row 1
newrow[mode] = 1;
newcol[mode] = 0;
newattr[mode] = 0;
style[mode] = CC_STYLE_ROLLUP;
break;

@@ -667,7 +690,8 @@ void CC608Decoder::BufferCC(int mode, int len, int clr)
int i = 0;
while (i < dispbuf.length()) {
QChar cp = dispbuf.at(i);
switch (cp.unicode())
int cpu = cp.unicode();
switch (cpu)
{
case 0x2120 : vbuf += "(SM)"; break;
case 0x2122 : vbuf += "(TM)"; break;
@@ -681,7 +705,10 @@ void CC608Decoder::BufferCC(int mode, int len, int clr)
case 0x2588 : vbuf += "[]"; break;
case 0x266A : vbuf += "o/~"; break;
case '\b' : vbuf += "\\b"; break;
default : vbuf += QString(cp.toLatin1());
default :
if (cpu >= 0x7000 && cpu < 0x7000 + 0x30)
vbuf += QString("[%1]").arg(cpu - 0x7000, 2, 16);
else vbuf += QString(cp.toLatin1());
}
i++;
}
@@ -787,13 +814,23 @@ int CC608Decoder::NewRowCC(int mode, int len)
lastrow[mode] = newrow[mode];
newrow[mode] = 0;

for (int x = 0; x < newcol[mode]; x++)
int limit = (newattr[mode] ? newcol[mode] - 1 : newcol[mode]);
for (int x = 0; x < limit; x++)
{
ccbuf[mode] += ' ';
len++;
col[mode]++;
}

if (newattr[mode])
{
ccbuf[mode] += QChar(newattr[mode] + 0x7000);
len++;
col[mode]++;
}

newcol[mode] = 0;
newattr[mode] = 0;

return len;
}
@@ -98,6 +98,7 @@ class CC608Decoder
int lastrow[8];
int newrow[8];
int newcol[8];
int newattr[8]; // color+italic+underline
int timecode[8];
int row[8];
int col[8];
@@ -97,8 +97,8 @@ CC608Buffer *CC608Reader::GetOutputText(bool &changed, int &streamIdx)
memcpy(&st, inpos, sizeof(st));
inpos += sizeof(st);

CC608Text *cc = new CC608Text(QString((const char*) inpos),
st.row, st.col, st.fg, true);
CC608Text *cc = new CC608Text(
QString((const char*) inpos), st.row, st.col, true);

m_state[streamIdx].m_output.lock.lock();
m_state[streamIdx].m_output.buffers.push_back(cc);
@@ -234,7 +234,7 @@ int CC608Reader::Update(unsigned char *inpos)
tmpcc = new CC608Text(
m_state[streamIdx].m_outputText,
m_state[streamIdx].m_outputCol,
m_state[streamIdx].m_outputRow, 0, false);
m_state[streamIdx].m_outputRow, false);
ccbuf->push_back(tmpcc);
#if 0
if (ccbuf->size() > 4)
@@ -15,12 +15,11 @@
class CC608Text
{
public:
CC608Text(QString T, int X, int Y, int C, int TT)
: text(T), x(X), y(Y), color(C), teletextmode(TT) {}
CC608Text(QString T, int X, int Y, int TT) :
text(T), x(X), y(Y), teletextmode(TT) {}
QString text;
int x;
int y;
int color;
bool teletextmode;
};

@@ -339,6 +339,8 @@ void SubtitleScreen::DisplayTextSubtitles(void)
changed = true;
int height = (m_safeArea.height() * m_textFontZoom) / 1800;
gTextSubFont->GetFace()->setPixelSize(height);
gTextSubFont->GetFace()->setItalic(false);
gTextSubFont->GetFace()->setUnderline(false);
gTextSubFont->SetColor(Qt::white);
}
}
@@ -424,6 +426,8 @@ void SubtitleScreen::DisplayRawTextSubtitles(void)
{
int height = (m_safeArea.height() * m_textFontZoom) / 1800;
gTextSubFont->GetFace()->setPixelSize(height);
gTextSubFont->GetFace()->setItalic(false);
gTextSubFont->GetFace()->setUnderline(false);
gTextSubFont->SetColor(Qt::white);
}
}
@@ -572,12 +576,86 @@ void SubtitleScreen::DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos)
AddScaledImage(bg_image, rect);
}

/// Extract everything from the text buffer up until the next format
/// control character. Return that substring, and remove it from the
/// input string. Bogus control characters are left unchanged. If the
/// buffer starts with a valid control character, the output parameters
/// are corresondingly updated (and the control character is stripped).
static QString extract_cc608(
QString &text, bool teletextmode, int &color,
bool &isItalic, bool &isUnderline, bool &showedNonControl)
{
QString result;
QString orig(text);

if (teletextmode)
{
result = text;
text = QString::null;
showedNonControl = true;
return result;
}

// Handle an initial control sequence.
if (text.length() >= 1 && text[0] >= 0x7000)
{
int op = text[0].unicode() - 0x7000;
isUnderline = (op & 0x1);
switch (op & ~1)
{
case 0x0e:
// color unchanged
isItalic = true;
break;
case 0x1e:
color = op >> 1;
isItalic = true;
break;
case 0x20:
// color unchanged
// italics unchanged
break;
default:
color = (op & 0xf) >> 1;
isItalic = false;
break;
}
text = text.mid(1);
}

// Copy the string into the result, up to the next control
// character.
int nextControl = text.indexOf(QRegExp("[\\x7000-\\x7fff]"));
if (nextControl < 0)
{
result = text;
text = QString::null;
showedNonControl = true;
}
else
{
result = text.left(nextControl);
// Print the space character before handling the next control
// character, otherwise the space character will be lost due
// to the text.trimmed() operation in the MythUIText
// constructor, combined with the left-justification of
// captions.
if (text[nextControl] < (0x7000 + 0x10))
result += " ";
text = text.mid(nextControl);
if (nextControl > 0)
showedNonControl = true;
}

return result;
}

void SubtitleScreen::DisplayCC608Subtitles(void)
{
static const QColor clr[8] =
{
Qt::white, Qt::red, Qt::green, Qt::yellow,
Qt::blue, Qt::magenta, Qt::cyan, Qt::white,
Qt::white, Qt::green, Qt::blue, Qt::cyan,
Qt::red, Qt::yellow, Qt::magenta, Qt::white,
};

if (!InitialiseFont(m_fontStretch) || !m_608reader)
@@ -621,22 +699,53 @@ void SubtitleScreen::DisplayCC608Subtitles(void)
int xscale = teletextmode ? 40 : 36;
int yscale = teletextmode ? 25 : 17;
gTextSubFont->GetFace()->setPixelSize(m_safeArea.height() / (yscale * 1.2));
QFontMetrics font(*(gTextSubFont->GetFace()));
QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern);
int height = font.height() * (1 + PAD_HEIGHT);
int pad_width = font.maxWidth() * PAD_WIDTH;

for (; i != textlist->buffers.end(); i++)
{
CC608Text *cc = (*i);
int color = 0;
bool isItalic = false, isUnderline = false;
bool first = true;
bool showedNonControl = false;
int x = 0, width = 0;
QString text(cc->text);

if (cc && (cc->text != QString::null))
for (int chunk = 0; text != QString::null; first = false, chunk++)
{
int width = font.width(cc->text) + pad_width;
int x = teletextmode ? cc->y : (cc->x + 3);
QString captionText =
extract_cc608(text, cc->teletextmode,
color, isItalic, isUnderline,
showedNonControl);
gTextSubFont->GetFace()->setItalic(isItalic);
gTextSubFont->GetFace()->setUnderline(isUnderline);
gTextSubFont->SetColor(clr[min(max(0, color), 7)]);
QFontMetrics font(*(gTextSubFont->GetFace()));
// XXX- could there be different heights across the same line?
int height = font.height() * (1 + PAD_HEIGHT);
if (first)
{
x = teletextmode ? cc->y : (cc->x + 3);
x = (int)(((float)x / (float)xscale) *
(float)m_safeArea.width());
}
else
{
x += width; // bump x by the previous width
}

int pad_width = font.maxWidth() * PAD_WIDTH;
width = font.width(captionText) + pad_width;
int y = teletextmode ? cc->x : cc->y;
x = (int)(((float)x / (float)xscale) * (float)m_safeArea.width());
y = (int)(((float)y / (float)yscale) * (float)m_safeArea.height());
// Sometimes a line of caption text begins with a mid-row
// format control like italics or a color change. The
// spec says the mid-row control also includes a space
// character. But this looks clumsy when using a
// background, so we suppress it after the placement is
// calculated.
if (!showedNonControl)
continue;
QRect rect(x, y, width, height);

if (!teletextmode && m_useBackground)
@@ -648,15 +757,20 @@ void SubtitleScreen::DisplayCC608Subtitles(void)
shape->SetArea(MythRect(bgrect));
}

gTextSubFont->SetColor(clr[min(max(0, cc->color), 7)]);
MythUIText *text = new MythUIText(
cc->text, *gTextSubFont, rect, rect, (MythUIType*)this,
QString("cc608txt%1%2%3").arg(cc->x).arg(cc->y).arg(width));
captionText, *gTextSubFont, rect, rect, (MythUIType*)this,
QString("cc608txt%1%2%3%4").arg(cc->x).arg(cc->y)
.arg(width).arg(chunk));
if (text)
text->SetJustification(Qt::AlignLeft);

m_refreshArea = true;
LOG(VB_VBI, LOG_INFO, QString("x %1 y %2 String: '%3'")
.arg(cc->x).arg(cc->y).arg(cc->text));

LOG(VB_VBI, LOG_INFO,
QString("x %1 y %2 uline=%4 ital=%5 "
"color=%6 coord=%7,%8 String: '%3'")
.arg(cc->x).arg(cc->y).arg(captionText)
.arg(isUnderline).arg(isItalic).arg(color).arg(x).arg(y));
}
}
textlist->lock.unlock();

0 comments on commit 11adb5b

Please sign in to comment.
You can’t perform that action at this time.