Ticket #10194: srt_formatting_v2.patch

File srt_formatting_v2.patch, 25.6 KB (added by Jim Stichnoth <stichnot@…>, 8 years ago)

Remove redundant code for setting font size and attributes.

  • mythtv/libs/libmythtv/subtitlescreen.cpp

    diff --git a/mythtv/libs/libmythtv/subtitlescreen.cpp b/mythtv/libs/libmythtv/subtitlescreen.cpp
    index 9f6820c..e36fde9 100644
    a b void SubtitleScreen::DisplayTextSubtitles(void) 
    354354    if (vo)
    355355    {
    356356        QRect oldsafe = m_safeArea;
    357         m_safeArea = m_player->GetVideoOutput()->GetSafeRect();
    358         if (oldsafe != m_safeArea)
    359         {
    360             changed = true;
    361             int height = (m_safeArea.height() * m_textFontZoom) / 1800;
    362             gTextSubFont->GetFace()->setPixelSize(height);
    363             gTextSubFont->GetFace()->setItalic(false);
    364             gTextSubFont->GetFace()->setUnderline(false);
    365             gTextSubFont->SetColor(Qt::white);
    366         }
     357        m_safeArea = vo->GetSafeRect();
     358        changed = (oldsafe != m_safeArea);
    367359    }
    368360    else
    369361    {
    void SubtitleScreen::DisplayTextSubtitles(void) 
    423415        return;
    424416    }
    425417
    426     OptimiseTextSubs(rawsubs);
    427418    subs->Unlock();
    428419    DrawTextSubtitles(rawsubs, 0, 0);
    429420}
    void SubtitleScreen::DisplayRawTextSubtitles(void) 
    439430        return;
    440431
    441432    VideoOutput *vo = m_player->GetVideoOutput();
    442     if (vo)
    443     {
    444         QRect oldsafe = m_safeArea;
    445         m_safeArea = m_player->GetVideoOutput()->GetSafeRect();
    446         if (oldsafe != m_safeArea)
    447         {
    448             int height = (m_safeArea.height() * m_textFontZoom) / 1800;
    449             gTextSubFont->GetFace()->setPixelSize(height);
    450             gTextSubFont->GetFace()->setItalic(false);
    451             gTextSubFont->GetFace()->setUnderline(false);
    452             gTextSubFont->SetColor(Qt::white);
    453         }
    454     }
    455     else
     433    if (!vo)
    456434        return;
    457435
    458436    VideoFrame *currentFrame = vo->GetLastShownFrame();
    void SubtitleScreen::DisplayRawTextSubtitles(void) 
    461439
    462440    // delete old subs that may still be on screen
    463441    DeleteAllChildren();
    464     OptimiseTextSubs(subs);
    465442    DrawTextSubtitles(subs, currentFrame->timecode, duration);
    466443}
    467444
    468 void SubtitleScreen::OptimiseTextSubs(QStringList &rawsubs)
    469 {
    470     QFontMetrics font(*(gTextSubFont->GetFace()));
    471     int maxwidth = m_safeArea.width();
    472     QStringList wrappedsubs;
    473     QString wrappedtext = "";
    474     int i = 0;
    475     while ((i < rawsubs.size()) || !wrappedtext.isEmpty())
    476     {
    477         QString nextline = wrappedtext;
    478         if (i < rawsubs.size())
    479             nextline += rawsubs[i].remove((const QRegExp&) m_removeHTML);
    480         wrappedtext = "";
    481 
    482         while (font.width(nextline) > maxwidth)
    483         {
    484             QString word = nextline.section(" ", -1, -1,
    485                                             QString::SectionSkipEmpty);
    486             if (word.isEmpty() || font.width(word) > maxwidth)
    487                 break;
    488             wrappedtext = word + " " + wrappedtext;
    489             nextline.chop(word.size() + 1);
    490         }
    491         if (!nextline.isEmpty())
    492             wrappedsubs.append(nextline);
    493         i++;
    494     }
    495     rawsubs = wrappedsubs;
    496 }
    497 
    498445void SubtitleScreen::DrawTextSubtitles(QStringList &wrappedsubs,
    499446                                       uint64_t start, uint64_t duration)
    500447{
    501     QFontMetrics font(*(gTextSubFont->GetFace()));
    502     int height = font.height() * (1 + PAD_HEIGHT);
    503     int pad_width = font.maxWidth() * PAD_WIDTH;
    504     int y = m_safeArea.height() - (height * wrappedsubs.size());
    505     int centre = m_safeArea.width() / 2;
    506     QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern);
    507     foreach (QString subtitle, wrappedsubs)
    508     {
    509         if (subtitle.isEmpty())
    510             continue;
    511         int width = font.width(subtitle) + pad_width * 2;
    512         int x = centre - (width / 2) - pad_width;
    513         QRect rect(x, y, width, height);
    514 
    515         if (m_useBackground)
    516         {
    517             MythUIShape *shape = new MythUIShape(this,
    518                 QString("tsubbg%1%2").arg(x).arg(y));
    519             shape->SetFillBrush(bgfill);
    520             shape->SetArea(MythRect(rect));
    521             if (duration > 0)
    522                 m_expireTimes.insert(shape, start + duration);
    523         }
    524         MythUISimpleText* text = new MythUISimpleText
    525                                  (subtitle, *gTextSubFont, rect,
    526                                   Qt::AlignCenter, this,
    527                                   QString("tsub%1%2").arg(x).arg(y));
    528         y += height;
    529         LOG(VB_PLAYBACK, LOG_INFO, LOC + subtitle);
    530         m_refreshArea = true;
    531 
    532         if (duration > 0)
    533         {
    534             m_expireTimes.insert(text, start + duration);
    535             LOG(VB_PLAYBACK, LOG_INFO, LOC +
    536                 QString("Display text subtitle for %1 ms").arg(duration));
    537         }
    538     }
     448    FormattedTextSubtitle fsub(m_safeArea);
     449    fsub.InitFromSRT(wrappedsubs, m_textFontZoom);
     450    fsub.WrapLongLines();
     451    fsub.Draw(this);
     452    m_refreshArea = true;
    539453}
    540454
    541455void SubtitleScreen::DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos)
    void SubtitleScreen::DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos) 
    604518/// are corresondingly updated (and the control character is stripped).
    605519static QString extract_cc608(
    606520    QString &text, bool teletextmode, int &color,
    607     bool &isItalic, bool &isUnderline, bool &showedNonControl)
     521    bool &isItalic, bool &isUnderline)
    608522{
    609523    QString result;
    610524    QString orig(text);
    static QString extract_cc608( 
    613527    {
    614528        result = text;
    615529        text = QString::null;
    616         showedNonControl = true;
    617530        return result;
    618531    }
    619532
    static QString extract_cc608( 
    651564    {
    652565        result = text;
    653566        text = QString::null;
    654         showedNonControl = true;
    655567    }
    656568    else
    657569    {
    static QString extract_cc608( 
    664576        if (text[nextControl] < (0x7000 + 0x10))
    665577            result += " ";
    666578        text = text.mid(nextControl);
    667         if (nextControl > 0)
    668             showedNonControl = true;
    669579    }
    670580
    671581    return result;
    static QString extract_cc608( 
    673583
    674584void SubtitleScreen::DisplayCC608Subtitles(void)
    675585{
    676     static const QColor clr[8] =
    677     {
    678         Qt::white,   Qt::green,   Qt::blue,    Qt::cyan,
    679         Qt::red,     Qt::yellow,  Qt::magenta, Qt::white,
    680     };
    681 
    682586    if (!InitialiseFont(m_fontStretch) || !m_608reader)
    683587        return;
    684588
    void SubtitleScreen::DisplayCC608Subtitles(void) 
    715619        return;
    716620    }
    717621
    718     vector<CC608Text*>::iterator i = textlist->buffers.begin();
    719     bool teletextmode = (*i)->teletextmode;
    720     int xscale = teletextmode ? 40 : 36;
    721     int yscale = teletextmode ? 25 : 17;
    722     gTextSubFont->GetFace()->setPixelSize(m_safeArea.height() / (yscale * 1.2));
    723     QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern);
    724 
    725     for (; i != textlist->buffers.end(); ++i)
    726     {
    727         CC608Text *cc = (*i);
    728         int color = 0;
    729         bool isItalic = false, isUnderline = false;
    730         bool first = true;
    731         bool showedNonControl = false;
    732         int x = 0, width = 0;
    733         QString text(cc->text);
    734 
    735         for (int chunk = 0; text != QString::null; first = false, chunk++)
    736         {
    737             QString captionText =
    738                 extract_cc608(text, cc->teletextmode,
    739                               color, isItalic, isUnderline,
    740                               showedNonControl);
    741             gTextSubFont->GetFace()->setItalic(isItalic);
    742             gTextSubFont->GetFace()->setUnderline(isUnderline);
    743             gTextSubFont->SetColor(clr[min(max(0, color), 7)]);
    744             QFontMetrics font(*(gTextSubFont->GetFace()));
    745             // XXX- could there be different heights across the same line?
    746             int height = font.height() * (1 + PAD_HEIGHT);
    747             if (first)
    748             {
    749                 x = teletextmode ? cc->y : (cc->x + 3);
    750                 x = (int)(((float)x / (float)xscale) *
    751                           (float)m_safeArea.width());
    752             }
    753             else
    754             {
    755                 x += width; // bump x by the previous width
    756             }
    757 
    758             int pad_width = font.maxWidth() * PAD_WIDTH;
    759             width = font.width(captionText) + pad_width;
    760             int y = teletextmode ? cc->x : cc->y;
    761             y = (int)(((float)y / (float)yscale) * (float)m_safeArea.height());
    762             // Sometimes a line of caption text begins with a mid-row
    763             // format control like italics or a color change.  The
    764             // spec says the mid-row control also includes a space
    765             // character.  But this looks clumsy when using a
    766             // background, so we suppress it after the placement is
    767             // calculated.
    768             if (!showedNonControl)
    769                 continue;
    770             QRect rect(x, y, width, height);
    771 
    772             if (!teletextmode && m_useBackground)
    773             {
    774                 MythUIShape *shape = new MythUIShape(this,
    775                     QString("cc608bg%1%2%3").arg(cc->x).arg(cc->y).arg(width));
    776                 shape->SetFillBrush(bgfill);
    777                 QRect bgrect(x - pad_width, y, width + pad_width, height);
    778                 shape->SetArea(MythRect(bgrect));
    779             }
    780 
    781             new MythUISimpleText(captionText, *gTextSubFont, rect,
    782                                  Qt::AlignLeft, (MythUIType*)this,
    783                                  QString("cc608txt%1%2%3%4")
    784                                      .arg(cc->x).arg(cc->y)
    785                                      .arg(width).arg(chunk));
    786 
    787             m_refreshArea = true;
    788 
    789             LOG(VB_VBI, LOG_INFO,
    790                 QString("x %1 y %2 uline=%4 ital=%5 "
    791                         "color=%6 coord=%7,%8 String: '%3'")
    792                 .arg(cc->x).arg(cc->y).arg(captionText)
    793                 .arg(isUnderline).arg(isItalic).arg(color).arg(x).arg(y));
    794         }
    795     }
     622    FormattedTextSubtitle fsub(m_safeArea);
     623    fsub.InitFromCC608(textlist->buffers);
     624    fsub.Draw(this);
     625    m_refreshArea = true;
    796626    textlist->lock.unlock();
    797627}
    798628
    MythFontProperties* SubtitleScreen::Get708Font(CC708CharacterAttribute attr) 
    11891019    return mythfont;
    11901020}
    11911021
     1022void FormattedTextChunk::ComputeSize(void)
     1023{
     1024    QFont *font = gTextSubFont->GetFace();
     1025    font->setItalic(isItalic);
     1026    font->setBold(isBold);
     1027    font->setUnderline(isUnderline);
     1028    QFontMetrics fm(*font);
     1029    width = fm.width(text) + fm.maxWidth() * PAD_WIDTH;
     1030    height = fm.height() * (1 + PAD_HEIGHT);
     1031}
     1032
     1033void FormattedTextSubtitle::InitFromCC608(vector<CC608Text*> &buffers)
     1034{
     1035    static const QColor clr[8] =
     1036    {
     1037        Qt::white,   Qt::green,   Qt::blue,    Qt::cyan,
     1038        Qt::red,     Qt::yellow,  Qt::magenta, Qt::white,
     1039    };
     1040
     1041    if (buffers.empty())
     1042        return;
     1043    vector<CC608Text*>::iterator i = buffers.begin();
     1044    bool teletextmode = (*i)->teletextmode;
     1045    m_useBackground = m_useBackground && !teletextmode;
     1046    int xscale = teletextmode ? 40 : 36;
     1047    int yscale = teletextmode ? 25 : 17;
     1048    m_pixelSize = m_safeArea.height() / (yscale * 1.2);
     1049
     1050    for (; i != buffers.end(); ++i)
     1051    {
     1052        CC608Text *cc = (*i);
     1053        int color = 0;
     1054        bool isItalic = false, isUnderline = false;
     1055        const bool isBold = false;
     1056        QString text(cc->text);
     1057
     1058        int orig_x = teletextmode ? cc->y : (cc->x + 3);
     1059        int x = (int)(((float)orig_x / (float)xscale) * (float)m_safeArea.width());
     1060        int orig_y = teletextmode ? cc->x : cc->y;
     1061        int y = (int)(((float)orig_y / (float)yscale) * (float)m_safeArea.height());
     1062        FormattedTextLine line(x, y);
     1063        for (int chunk = 0; text != QString::null; chunk++)
     1064        {
     1065            QString captionText =
     1066                extract_cc608(text, cc->teletextmode,
     1067                              color, isItalic, isUnderline);
     1068            FormattedTextChunk chunk(captionText,
     1069                                     isItalic, isBold, isUnderline,
     1070                                     clr[min(max(0, color), 7)],
     1071                                     orig_x, orig_y);
     1072            line.chunks += chunk;
     1073            LOG(VB_VBI, LOG_INFO,
     1074                QString("Adding cc608 chunk: x=%1 y=%2 "
     1075                        "uline=%3 ital=%4 color=%5 text='%6'")
     1076                .arg(cc->x).arg(cc->y)
     1077                .arg(isUnderline).arg(isItalic).arg(color).arg(captionText));
     1078        }
     1079        m_lines += line;
     1080    }
     1081}
     1082
     1083void FormattedTextSubtitle::InitFromSRT(QStringList &subs, int textFontZoom)
     1084{
     1085    // Does a simplistic parsing of HTML tags from the strings.
     1086    // Nesting is not implemented.  Stray whitespace may cause
     1087    // legitimate tags to be ignored.  All other HTML tags are
     1088    // stripped and ignored.
     1089    //
     1090    // <i> - enable italics
     1091    // </i> - disable italics
     1092    // <b> - enable boldface
     1093    // </b> - disable boldface
     1094    // <u> - enable underline
     1095    // </u> - disable underline
     1096    // <font color="#xxyyzz"> - change font color
     1097    // </font> - reset font color to white
     1098
     1099    m_pixelSize = (m_safeArea.height() * textFontZoom) / 1800;
     1100
     1101    bool isItalic = false;
     1102    bool isBold = false;
     1103    bool isUnderline = false;
     1104    QColor color(Qt::white);
     1105    QRegExp htmlTag("</?.+>");
     1106    QString htmlPrefix("<font color=\""), htmlSuffix("\">");
     1107    htmlTag.setMinimal(true);
     1108    foreach (QString subtitle, subs)
     1109    {
     1110        FormattedTextLine line;
     1111        QString text(subtitle);
     1112        while (!text.isEmpty())
     1113        {
     1114            int pos = text.indexOf(htmlTag);
     1115            if (pos != 0) // don't add a zero-length string
     1116            {
     1117                FormattedTextChunk chunk(text.left(pos),
     1118                                         isItalic, isBold, isUnderline,
     1119                                         color, -1, -1);
     1120                line.chunks += chunk;
     1121                text = (pos < 0 ? "" : text.mid(pos));
     1122                LOG(VB_VBI, LOG_INFO, QString("Adding SRT chunk '%1'").arg(chunk.text));
     1123            }
     1124            if (pos >= 0)
     1125            {
     1126                int htmlLen = htmlTag.matchedLength();
     1127                QString html = text.left(htmlLen).toLower();
     1128                text = text.mid(htmlLen);
     1129                if (html == "<i>")
     1130                    isItalic = true;
     1131                else if (html == "</i>")
     1132                    isItalic = false;
     1133                else if (html.startsWith(htmlPrefix) &&
     1134                         html.endsWith(htmlSuffix))
     1135                {
     1136                    int colorLen = html.length() -
     1137                        (htmlPrefix.length() + htmlSuffix.length());
     1138                    QString colorString(html.mid(htmlPrefix.length(), colorLen));
     1139                    QColor newColor(colorString);
     1140                    if (newColor.isValid())
     1141                        color = newColor;
     1142                    else
     1143                        LOG(VB_VBI, LOG_INFO,
     1144                            QString("Ignoring invalid SRT color specification: "
     1145                                    "'%1'").arg(colorString));
     1146                }
     1147                else if (html == "</font>")
     1148                    color = Qt::white;
     1149                else if (html == "<b>")
     1150                    isBold = true;
     1151                else if (html == "</b>")
     1152                    isBold = false;
     1153                else if (html == "<u>")
     1154                    isUnderline = true;
     1155                else if (html == "</u>")
     1156                    isUnderline = false;
     1157                else
     1158                    LOG(VB_VBI, LOG_INFO,
     1159                        QString("Ignoring unknown SRT formatting: '%1'").arg(html));
     1160
     1161                LOG(VB_VBI, LOG_INFO,
     1162                    QString("SRT formatting change '%1', "
     1163                            "new ital=%2 bold=%3 uline=%4 color=(%5,%6,%7)")
     1164                    .arg(html).arg(isItalic).arg(isBold).arg(isUnderline)
     1165                    .arg(color.red(),   2, 16, QLatin1Char('0'))
     1166                    .arg(color.green(), 2, 16, QLatin1Char('0'))
     1167                    .arg(color.blue(),  2, 16, QLatin1Char('0')));
     1168            }
     1169        }
     1170        m_lines += line;
     1171    }
     1172}
     1173
     1174bool FormattedTextChunk::Split(FormattedTextChunk &newChunk)
     1175{
     1176    LOG(VB_VBI, LOG_INFO,
     1177        QString("Attempting to split chunk '%1'").arg(text));
     1178    int lastSpace = text.lastIndexOf(' ', -2); // -2 to ignore trailing space
     1179    if (lastSpace < 0)
     1180    {
     1181        LOG(VB_VBI, LOG_INFO,
     1182            QString("Failed to split chunk '%1'").arg(text));
     1183        return false;
     1184    }
     1185    newChunk.isItalic = isItalic;
     1186    newChunk.isBold = isBold;
     1187    newChunk.isUnderline = isUnderline;
     1188    newChunk.color = color;
     1189    newChunk.debug_x = debug_x;
     1190    newChunk.debug_y = debug_y;
     1191    newChunk.text = text.mid(lastSpace + 1).trimmed() + ' ';
     1192    text = text.left(lastSpace).trimmed();
     1193    newChunk.ComputeSize();
     1194    ComputeSize();
     1195    LOG(VB_VBI, LOG_INFO,
     1196        QString("Split chunk into '%1' + '%2'").arg(text).arg(newChunk.text));
     1197    return true;
     1198}
     1199
     1200void FormattedTextSubtitle::WrapLongLines(void)
     1201{
     1202    int maxWidth = m_safeArea.width();
     1203    QList<FormattedTextLine>::iterator i = m_lines.begin();
     1204    while (i != m_lines.end())
     1205    {
     1206        int width = (*i).Width();
     1207        // Move entire chunks to the next line as necessary.  Leave at
     1208        // least one chunk on the current line.
     1209        while (width > maxWidth && (*i).chunks.size() > 1)
     1210        {
     1211            width -= (*i).chunks.back().width;
     1212            // Make sure there's a next line to wrap into.
     1213            if (i + 1 == m_lines.end())
     1214                m_lines += FormattedTextLine((*i).x_indent, (*i).y_indent);
     1215            (*(i+1)).chunks.prepend((*i).chunks.takeLast());
     1216            LOG(VB_VBI, LOG_INFO,
     1217                QString("Wrapping chunk to next line: '%1'")
     1218                .arg((*(i+1)).chunks[0].text));
     1219        }
     1220        // Split the last chunk until width is small enough or until
     1221        // no more splits are possible.
     1222        bool isSplitPossible = true;
     1223        while (width > maxWidth && isSplitPossible)
     1224        {
     1225            FormattedTextChunk newChunk;
     1226            isSplitPossible = (*i).chunks.back().Split(newChunk);
     1227            if (isSplitPossible)
     1228            {
     1229                // Make sure there's a next line to split into.
     1230                if (i + 1 == m_lines.end())
     1231                    m_lines += FormattedTextLine((*i).x_indent, (*i).y_indent);
     1232                (*(i+1)).chunks.prepend(newChunk);
     1233                width = (*i).Width();
     1234            }
     1235        }
     1236        ++i;
     1237    }
     1238}
     1239
     1240void FormattedTextSubtitle::Draw(SubtitleScreen *parent,
     1241                                 uint64_t start, uint64_t duration) const
     1242{
     1243    bool useBackground = m_useBackground && parent->GetUseBackground();
     1244    gTextSubFont->GetFace()->setPixelSize(m_pixelSize);
     1245    QFontMetrics font(*(gTextSubFont->GetFace()));
     1246    int pad_width = font.maxWidth() * PAD_WIDTH;
     1247    QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern);
     1248
     1249    int lineNum = 0;
     1250    QList<FormattedTextLine>::const_iterator line = m_lines.constBegin();
     1251    for (; line != m_lines.constEnd(); ++line, ++lineNum)
     1252    {
     1253        int x = (*line).x_indent;
     1254        if (x < 0) // centering
     1255            x = (m_safeArea.width() - (*line).Width()) / 2;
     1256        int y = (*line).y_indent;
     1257        if (y < 0) // stack lines at bottom
     1258            y = m_safeArea.height() -
     1259                (m_lines.size() - lineNum) * (*line).Height();
     1260
     1261        if (useBackground)
     1262        {
     1263            QRect bgrect(x - pad_width, y,
     1264                         (*line).Width() + pad_width, (*line).Height());
     1265            // Special case.  If the first chunk is entirely
     1266            // whitespace, don't put a black background behind that
     1267            // chunk.
     1268            //
     1269            // This often happens when a line of cc608 caption text
     1270            // begins with a mid-row format control like italics or a
     1271            // color change.  The spec says the mid-row control
     1272            // implies a space character, which needs to be preserved
     1273            // so that the rest of the text is accurately laid out.  A
     1274            // leading space looks clumsy against the black
     1275            // background, so we adjust the background accordingly.
     1276            if (!(*line).chunks.isEmpty() &&
     1277                (*line).chunks[0].text.trimmed().isEmpty())
     1278            {
     1279                bgrect.setLeft(bgrect.left() + (*line).chunks[0].width);
     1280            }
     1281            MythUIShape *shape =
     1282                new MythUIShape(parent, QString("subbg%1_%2").arg(x).arg(y));
     1283            shape->SetFillBrush(bgfill);
     1284            shape->SetArea(MythRect(bgrect));
     1285            if (duration > 0)
     1286                parent->RegisterExpiration(shape, start + duration);
     1287        }
     1288        QList<FormattedTextChunk>::const_iterator chunk;
     1289        for (chunk = (*line).chunks.constBegin();
     1290             chunk != (*line).chunks.constEnd();
     1291             ++chunk)
     1292        {
     1293            // If the chunk starts with whitespace, the leading
     1294            // whitespace ultimately gets lost due to the
     1295            // text.trimmed() operation in the MythUISimpleText
     1296            // constructor.  To compensate, we manually indent the
     1297            // chunk accordingly.
     1298            int count = 0;
     1299            while (count < (*chunk).text.length() && (*chunk).text.at(count) == ' ')
     1300                ++count;
     1301            int x_adjust = count * font.width(" ");
     1302            gTextSubFont->GetFace()->setItalic((*chunk).isItalic);
     1303            gTextSubFont->GetFace()->setBold((*chunk).isBold);
     1304            gTextSubFont->GetFace()->setUnderline((*chunk).isUnderline);
     1305            gTextSubFont->SetColor((*chunk).color);
     1306            QRect rect(x + x_adjust, y, (*chunk).width - x_adjust, (*chunk).height);
     1307
     1308            MythUISimpleText *text =
     1309                new MythUISimpleText((*chunk).text, *gTextSubFont, rect,
     1310                                     Qt::AlignLeft, (MythUIType*)parent,
     1311                                     QString("subtxt%1x%2@%3,%4")
     1312                                     .arg((*chunk).width).arg((*chunk).height)
     1313                                     .arg(x).arg(y));
     1314            if (duration > 0)
     1315                parent->RegisterExpiration(text, start + duration);
     1316
     1317            LOG(VB_VBI, LOG_INFO,
     1318                QString("Drawing chunk at (%1,%2) with "
     1319                        "ital=%3 bold=%4 uline=%5 color=(%6,%7,%8) "
     1320                        "text='%9'")
     1321                .arg(x).arg(y)
     1322                .arg((*chunk).isItalic)
     1323                .arg((*chunk).isBold)
     1324                .arg((*chunk).isUnderline)
     1325                .arg((*chunk).color.red(),   2, 16, QLatin1Char('0'))
     1326                .arg((*chunk).color.green(), 2, 16, QLatin1Char('0'))
     1327                .arg((*chunk).color.blue(),  2, 16, QLatin1Char('0'))
     1328                .arg((*chunk).text));
     1329
     1330            x += (*chunk).width;
     1331        }
     1332    }
     1333}
     1334
    11921335#ifdef USING_LIBASS
    11931336static void myth_libass_log(int level, const char *fmt, va_list vl, void *ctx)
    11941337{
  • mythtv/libs/libmythtv/subtitlescreen.h

    diff --git a/mythtv/libs/libmythtv/subtitlescreen.h b/mythtv/libs/libmythtv/subtitlescreen.h
    index f233220..7b72e42 100644
    a b class SubtitleScreen : public MythScreenType 
    3232    void ExpireSubtitles(void);
    3333    void DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos);
    3434
     35    void RegisterExpiration(MythUIType *shape, long long endTime) {
     36        m_expireTimes.insert(shape, endTime);
     37    }
     38
     39    bool GetUseBackground(void) { return m_useBackground; }
     40
    3541    // MythScreenType methods
    3642    virtual bool Create(void);
    3743    virtual void Pulse(void);
    class SubtitleScreen : public MythScreenType 
    4147    void DisplayAVSubtitles(void);
    4248    void DisplayTextSubtitles(void);
    4349    void DisplayRawTextSubtitles(void);
    44     void OptimiseTextSubs(QStringList &list);
    4550    void DrawTextSubtitles(QStringList &wrappedsubs, uint64_t start,
    4651                           uint64_t duration);
    4752    void DisplayCC608Subtitles(void);
    class SubtitleScreen : public MythScreenType 
    8590#endif // USING_LIBASS
    8691};
    8792
     93struct FormattedTextChunk
     94{
     95    FormattedTextChunk(const QString &t, bool ital, bool bold, bool uline,
     96                       QColor clr, int dx, int dy)
     97        : text(t), isItalic(ital), isBold(bold), isUnderline(uline),
     98          color(clr), debug_x(dx), debug_y(dy) {
     99        ComputeSize();
     100    }
     101    FormattedTextChunk(void) {}
     102    void ComputeSize(void);
     103    bool Split(FormattedTextChunk &newChunk);
     104    QString text;
     105    bool isItalic;
     106    bool isBold;
     107    bool isUnderline;
     108    QColor color;
     109    int width;
     110    int height;
     111    int debug_x, debug_y;
     112};
     113
     114struct FormattedTextLine
     115{
     116    FormattedTextLine(int x = -1, int y = -1) : x_indent(x), y_indent(y) {}
     117    int Height(void) const {
     118        int result = 0;
     119        QList<FormattedTextChunk>::const_iterator it;
     120        for (it = chunks.constBegin(); it != chunks.constEnd(); ++it)
     121            result = max(result, (*it).height);
     122        return result;
     123    }
     124    int Width(void) const {
     125        int result = 0;
     126        QList<FormattedTextChunk>::const_iterator it;
     127        for (it = chunks.constBegin(); it != chunks.constEnd(); ++it)
     128            result += (*it).width;
     129        return result;
     130    }
     131    QList<FormattedTextChunk> chunks;
     132    int x_indent; // -1 means TBD i.e. centered
     133    int y_indent; // -1 means TBD i.e. relative to bottom
     134};
     135
     136class FormattedTextSubtitle
     137{
     138public:
     139    FormattedTextSubtitle(const QRect &safearea)
     140        : m_safeArea(safearea), m_useBackground(true) {}
     141    void InitFromCC608(vector<CC608Text*> &buffers);
     142    void InitFromSRT(QStringList &subs, int textFontZoom);
     143    void WrapLongLines(void);
     144    void Draw(SubtitleScreen *parent,
     145              uint64_t start = 0, uint64_t duration = 0) const;
     146private:
     147    QList<FormattedTextLine> m_lines;
     148    const QRect m_safeArea;
     149    bool m_useBackground;
     150    int m_pixelSize;
     151};
     152
    88153#endif // SUBTITLESCREEN_H