Ticket #10194: srt_cc708_v1.patch
File srt_cc708_v1.patch, 51.1 KB (added by , 12 years ago) |
---|
-
mythtv/libs/libmythtv/avformatdecoder.cpp
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp index 40e2d39..199ddf5 100644
a b AvFormatDecoder::AvFormatDecoder(MythPlayer *parent, 321 321 322 322 cc608_build_parity_table(cc608_parity_table); 323 323 324 if (gCoreContext->GetNumSetting("CCBackground", 0))325 CC708Window::forceWhiteOnBlackText = true;326 327 324 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("PlayerFlags: 0x%1") 328 325 .arg(playerFlags, 0, 16)); 329 326 } -
mythtv/libs/libmythtv/cc708window.cpp
diff --git a/mythtv/libs/libmythtv/cc708window.cpp b/mythtv/libs/libmythtv/cc708window.cpp index e133eae..b1d7c43 100644
a b const uint k708AttrOpacityFlash = 1; 106 106 const uint k708AttrOpacityTranslucent = 2; 107 107 const uint k708AttrOpacityTransparent = 3; 108 108 109 bool CC708Window::forceWhiteOnBlackText = false;110 111 109 CC708Window::CC708Window() 112 110 : priority(0), visible(0), 113 111 anchor_point(0), relative_pos(0), … … void CC708Window::DefineWindow(int _priority, int _visible, 175 173 for (uint i = 0; i < old_row * old_col; i++) 176 174 new_text[i] = text[i]; 177 175 for (uint i = old_row * old_col; i < num; i++) 178 {179 176 new_text[i].attr = pen.attr; 180 if (forceWhiteOnBlackText)181 {182 new_text[i].attr.fg_opacity = k708AttrOpacityTransparent;183 new_text[i].attr.bg_opacity = k708AttrOpacityTransparent;184 }185 }186 177 delete [] text; 187 178 text = new_text; 188 179 } … … void CC708Window::DefineWindow(int _priority, int _visible, 200 191 pen.column = 0; 201 192 pen.row = 0; 202 193 for (uint i = 0; i < num; i++) 203 {204 194 text[i].attr = pen.attr; 205 if (forceWhiteOnBlackText)206 {207 text[i].attr.fg_opacity = k708AttrOpacityTransparent;208 text[i].attr.bg_opacity = k708AttrOpacityTransparent;209 }210 }211 195 } 212 196 213 197 exists = true; … … void CC708Window::Clear(void) 241 225 { 242 226 text[i].character = QChar(' '); 243 227 text[i].attr = pen.attr; 244 if (forceWhiteOnBlackText)245 {246 text[i].attr.fg_opacity = k708AttrOpacityTransparent;247 text[i].attr.bg_opacity = k708AttrOpacityTransparent;248 }249 228 } 250 229 changed = true; 251 230 } … … void CC708Window::AddChar(QChar ch) 370 349 } 371 350 372 351 GetCCChar().attr = pen.attr; 373 if (forceWhiteOnBlackText)374 {375 GetCCChar().attr.fg_color = k708AttrColorWhite;376 GetCCChar().attr.fg_opacity = k708AttrOpacitySolid;377 GetCCChar().attr.bg_color = k708AttrColorBlack;378 GetCCChar().attr.bg_opacity = k708AttrOpacityTranslucent;379 GetCCChar().attr.edge_color = k708AttrColorWhite;380 }381 352 GetCCChar().character = ch; 382 353 int c = pen.column; 383 354 int r = pen.row; … … void CC708Pen::SetPenStyle(uint style) 534 505 attr.font_tag = style2font[style]; 535 506 attr.italics = 0; 536 507 attr.underline = 0; 508 attr.boldface = 0; 537 509 attr.edge_type = 0; 538 510 attr.fg_color = k708AttrColorWhite; 539 511 attr.fg_opacity = k708AttrOpacitySolid; … … void CC708Pen::SetPenStyle(uint style) 541 513 attr.bg_opacity = (style<6) ? 542 514 k708AttrOpacitySolid : k708AttrOpacityTransparent; 543 515 attr.edge_color = k708AttrColorBlack; 516 attr.override_fg_color = false; 544 517 } 545 518 546 519 CC708Character::CC708Character(const CC708Window &win) 547 520 { 548 521 attr = win.pen.attr; 549 if (CC708Window::forceWhiteOnBlackText)550 {551 attr.fg_opacity = k708AttrOpacityTransparent;552 attr.bg_opacity = k708AttrOpacityTransparent;553 }554 522 character = ' '; 555 523 } 556 524 … … bool CC708CharacterAttribute::operator==( 573 541 574 542 QColor CC708CharacterAttribute::ConvertToQColor(uint c) 575 543 { 576 //int X[4] = {0, 85, 170, 255}; RGB( X[(c>>4)&3], X[(c>>2)&3], X[c&3] )577 return QColor( (c & 0x30) << 2, (c & 0x0c) << 4, (c & 0x3) << 6);544 static int X[] = {0, 96, 255, 255}; 545 return QColor(X[(c>>4)&3], X[(c>>2)&3], X[c&3]); 578 546 } -
mythtv/libs/libmythtv/cc708window.h
diff --git a/mythtv/libs/libmythtv/cc708window.h b/mythtv/libs/libmythtv/cc708window.h index 2c1db0a..ce064ee 100644
a b using namespace std; 13 13 14 14 #include "mythtvexp.h" 15 15 16 extern const uint k708JustifyLeft; 17 extern const uint k708JustifyRight; 18 extern const uint k708JustifyCenter; 19 extern const uint k708JustifyFull; 20 21 extern const uint k708EffectSnap; 22 extern const uint k708EffectFade; 23 extern const uint k708EffectWipe; 24 25 extern const uint k708BorderNone; 26 extern const uint k708BorderRaised; 27 extern const uint k708BorderDepressed; 28 extern const uint k708BorderUniform; 29 extern const uint k708BorderShadowLeft; 30 extern const uint k708BorderShadowRight; 31 32 extern const uint k708DirLeftToRight; 33 extern const uint k708DirRightToLeft; 34 extern const uint k708DirTopToBottom; 35 extern const uint k708DirBottomToTop; 36 37 extern const uint k708AttrSizeSmall; 38 extern const uint k708AttrSizeStandard; 39 extern const uint k708AttrSizeLarge; 40 41 extern const uint k708AttrOffsetSubscript; 42 extern const uint k708AttrOffsetNormal; 43 extern const uint k708AttrOffsetSuperscript; 44 45 extern const uint k708AttrFontDefault; 46 extern const uint k708AttrFontMonospacedSerif; 47 extern const uint k708AttrFontProportionalSerif; 48 extern const uint k708AttrFontMonospacedSansSerif; 49 extern const uint k708AttrFontProportionalSansSerif; 50 extern const uint k708AttrFontCasual; 51 extern const uint k708AttrFontCursive; 52 extern const uint k708AttrFontSmallCaps; 53 54 extern const uint k708AttrEdgeNone; 55 extern const uint k708AttrEdgeRaised; 56 extern const uint k708AttrEdgeDepressed; 57 extern const uint k708AttrEdgeUniform; 58 extern const uint k708AttrEdgeLeftDropShadow; 59 extern const uint k708AttrEdgeRightDropShadow; 60 61 extern const uint k708AttrColorBlack; 62 extern const uint k708AttrColorWhite; 63 64 extern const uint k708AttrOpacitySolid; 65 extern const uint k708AttrOpacityFlash; 66 extern const uint k708AttrOpacityTranslucent; 67 extern const uint k708AttrOpacityTransparent; 68 16 69 class CC708CharacterAttribute 17 70 { 18 71 public: … … class CC708CharacterAttribute 25 78 uint edge_type; 26 79 uint underline; 27 80 uint italics; 81 uint boldface; 28 82 29 83 uint fg_color; 30 84 uint fg_opacity; … … class CC708CharacterAttribute 32 86 uint bg_opacity; 33 87 uint edge_color; 34 88 89 bool override_fg_color; // for a color not in the 6-bit palette 90 QColor actual_fg_color; 91 92 CC708CharacterAttribute(bool isItalic, bool isBold, bool isUnderline, 93 QColor fgColor, bool hasBackground) : 94 pen_size(k708AttrSizeStandard), 95 offset(k708AttrOffsetNormal), 96 text_tag(0), // "dialog", ignored 97 font_tag(0), // system font 98 edge_type(k708AttrEdgeNone), 99 underline(isUnderline), 100 italics(isItalic), 101 boldface(isBold), 102 fg_color(k708AttrColorWhite), // will be overridden 103 fg_opacity(k708AttrOpacitySolid), // solid 104 bg_color(k708AttrColorBlack), 105 bg_opacity(hasBackground ? k708AttrOpacitySolid : 106 k708AttrOpacityTransparent), 107 edge_color(k708AttrColorBlack), 108 override_fg_color(true), 109 actual_fg_color(fgColor) 110 {} 111 CC708CharacterAttribute(void) : override_fg_color(false) {} 112 35 113 // remove this 36 114 uint FontIndex(void) const 37 115 { … … class CC708CharacterAttribute 41 119 static QColor ConvertToQColor(uint eia708color); 42 120 QColor GetFGColor(void) const 43 121 { 44 QColor fg = ConvertToQColor(fg_color); 122 QColor fg = (override_fg_color ? 123 actual_fg_color : ConvertToQColor(fg_color)); 45 124 fg.setAlpha(GetFGAlpha()); 46 125 return fg; 47 126 } … … class CC708Pen 88 167 attr.edge_type = edge_type; 89 168 attr.underline = underline; 90 169 attr.italics = italics; 170 attr.boldface = 0; 91 171 } 92 172 public: 93 173 CC708CharacterAttribute attr; … … class CC708Service 215 295 CC708Window windows[8]; 216 296 }; 217 297 218 extern const uint k708JustifyLeft;219 extern const uint k708JustifyRight;220 extern const uint k708JustifyCenter;221 extern const uint k708JustifyFull;222 223 extern const uint k708EffectSnap;224 extern const uint k708EffectFade;225 extern const uint k708EffectWipe;226 227 extern const uint k708BorderNone;228 extern const uint k708BorderRaised;229 extern const uint k708BorderDepressed;230 extern const uint k708BorderUniform;231 extern const uint k708BorderShadowLeft;232 extern const uint k708BorderShadowRight;233 234 extern const uint k708DirLeftToRight;235 extern const uint k708DirRightToLeft;236 extern const uint k708DirTopToBottom;237 extern const uint k708DirBottomToTop;238 239 extern const uint k708AttrSizeSmall;240 extern const uint k708AttrSizeStandard;241 extern const uint k708AttrSizeLarge;242 243 extern const uint k708AttrOffsetSubscript;244 extern const uint k708AttrOffsetNormal;245 extern const uint k708AttrOffsetSuperscript;246 247 extern const uint k708AttrFontDefault;248 extern const uint k708AttrFontMonospacedSerif;249 extern const uint k708AttrFontProportionalSerif;250 extern const uint k708AttrFontMonospacedSansSerif;251 extern const uint k708AttrFontProportionalSansSerif;252 extern const uint k708AttrFontCasual;253 extern const uint k708AttrFontCursive;254 extern const uint k708AttrFontSmallCaps;255 256 extern const uint k708AttrEdgeNone;257 extern const uint k708AttrEdgeRaised;258 extern const uint k708AttrEdgeDepressed;259 extern const uint k708AttrEdgeUniform;260 extern const uint k708AttrEdgeLeftDropShadow;261 extern const uint k708AttrEdgeRightDropShadow;262 263 extern const uint k708AttrColorBlack;264 extern const uint k708AttrColorWhite;265 266 extern const uint k708AttrOpacitySolid;267 extern const uint k708AttrOpacityFlash;268 extern const uint k708AttrOpacityTranslucent;269 extern const uint k708AttrOpacityTransparent;270 271 298 #endif // _CC708_WINDOW_ -
mythtv/libs/libmythtv/mythccextractorplayer.cpp
diff --git a/mythtv/libs/libmythtv/mythccextractorplayer.cpp b/mythtv/libs/libmythtv/mythccextractorplayer.cpp index 5173256..6ac17dc 100644
a b using namespace std; 28 28 #include "teletextextractorreader.h" 29 29 #include "mythccextractorplayer.h" 30 30 #include "avformatdecoder.h" 31 #include "subtitlescreen.h" 31 32 #include "srtwriter.h" 32 33 33 34 … … void MythCCExtractorPlayer::Ingest608Captions(void) 319 320 continue; 320 321 } 321 322 322 QStringList content; 323 vector<CC608Text*>::iterator bit = textlist->buffers.begin(); 324 for (; bit != textlist->buffers.end(); ++bit) 325 content += CC608Decoder::ToASCII((*bit)->text, true); 323 FormattedTextSubtitle fsub; 324 fsub.InitFromCC608(textlist->buffers); 325 QStringList content = fsub.ToSRT(); 326 326 327 327 textlist->lock.unlock(); 328 328 … … void MythCCExtractorPlayer::Ingest708Captions(void) 411 411 if (win.visible) 412 412 strings = win.GetStrings(); 413 413 Ingest708Caption(it.key(), serviceIdx, windowIdx, 414 win.pen.row, win.pen.column, strings);414 win.pen.row, win.pen.column, win, strings); 415 415 while (!strings.empty()) 416 416 { 417 417 delete strings.back(); … … void MythCCExtractorPlayer::Ingest708Captions(void) 427 427 void MythCCExtractorPlayer::Ingest708Caption( 428 428 uint streamId, uint serviceIdx, 429 429 uint windowIdx, uint start_row, uint start_column, 430 const CC708Window &win, 430 431 const vector<CC708String*> &content) 431 432 { 432 bool empty = true; 433 QStringList winContent; 434 435 vector<CC708String*>::const_iterator it = content.begin(); 436 for (; it != content.end(); ++it) 437 { 438 QString tmp = (*it)->str.trimmed(); 439 if (!tmp.isEmpty()) 440 winContent += tmp; 441 empty &= tmp.isEmpty(); 442 } 433 FormattedTextSubtitle fsub; 434 fsub.InitFromCC708(win, windowIdx, content); 435 QStringList winContent = fsub.ToSRT(); 443 436 444 437 QMap<int, Window> &cc708win = m_cc708_windows[streamId][serviceIdx]; 445 438 cc708win[windowIdx].row = start_row; -
mythtv/libs/libmythtv/mythccextractorplayer.h
diff --git a/mythtv/libs/libmythtv/mythccextractorplayer.h b/mythtv/libs/libmythtv/mythccextractorplayer.h index 88d7983..5660f39 100644
a b class MTV_PUBLIC MythCCExtractorPlayer : public MythPlayer 139 139 void Ingest708Captions(void); 140 140 void Ingest708Caption(uint streamId, uint serviceIdx, uint windowIdx, 141 141 uint start_row, uint start_column, 142 const CC708Window &win, 142 143 const vector<CC708String*> &content); 143 144 void Process708Captions(uint flags); 144 145 -
mythtv/libs/libmythtv/subtitlescreen.cpp
diff --git a/mythtv/libs/libmythtv/subtitlescreen.cpp b/mythtv/libs/libmythtv/subtitlescreen.cpp index f85c2b8..24a91c5 100644
a b 14 14 #define PAD_WIDTH 0.20 15 15 #define PAD_HEIGHT 0.04 16 16 17 static MythFontProperties* gTextSubFont; 17 static const float LINE_SPACING = 1.1765f; 18 18 19 static QHash<int, MythFontProperties*> gCC708Fonts; 20 int SubtitleScreen::g_708fontSizes[4] = {36, 45, 60}; 19 21 20 22 SubtitleScreen::SubtitleScreen(MythPlayer *player, const char * name, 21 23 int fontStretch) : … … SubtitleScreen::SubtitleScreen(MythPlayer *player, const char * name, 26 28 m_textFontZoom(100), m_refreshArea(false), 27 29 m_fontStretch(fontStretch) 28 30 { 29 m_708fontSizes[0] = 36;30 m_708fontSizes[1] = 45;31 m_708fontSizes[2] = 60;32 31 m_removeHTML.setMinimal(true); 33 32 34 33 #ifdef USING_LIBASS … … void SubtitleScreen::DisplayAVSubtitles(void) 346 345 347 346 void SubtitleScreen::DisplayTextSubtitles(void) 348 347 { 349 if (!Initialise Font(m_fontStretch) || !m_player || !m_subreader)348 if (!Initialise708Fonts(m_fontStretch) || !m_player || !m_subreader) 350 349 return; 351 350 352 351 bool changed = false; … … void SubtitleScreen::DisplayTextSubtitles(void) 421 420 422 421 void SubtitleScreen::DisplayRawTextSubtitles(void) 423 422 { 424 if (!Initialise Font(m_fontStretch) || !m_player || !m_subreader)423 if (!Initialise708Fonts(m_fontStretch) || !m_player || !m_subreader) 425 424 return; 426 425 427 426 uint64_t duration; … … void SubtitleScreen::DisplayRawTextSubtitles(void) 445 444 void SubtitleScreen::DrawTextSubtitles(QStringList &wrappedsubs, 446 445 uint64_t start, uint64_t duration) 447 446 { 448 FormattedTextSubtitle fsub(m_safeArea );447 FormattedTextSubtitle fsub(m_safeArea, m_useBackground); 449 448 fsub.InitFromSRT(wrappedsubs, m_textFontZoom); 450 449 fsub.WrapLongLines(); 451 fsub. Draw(this);452 m_refreshArea = true;450 fsub.Layout(); 451 m_refreshArea = m_refreshArea || fsub.Draw(this, 0, start, duration); 453 452 } 454 453 455 454 void SubtitleScreen::DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos) … … static QString extract_cc608( 583 582 584 583 void SubtitleScreen::DisplayCC608Subtitles(void) 585 584 { 586 if (!Initialise Font(m_fontStretch) || !m_608reader)585 if (!Initialise708Fonts(m_fontStretch) || !m_608reader) 587 586 return; 588 587 589 588 bool changed = false; … … void SubtitleScreen::DisplayCC608Subtitles(void) 619 618 return; 620 619 } 621 620 622 FormattedTextSubtitle fsub(m_safeArea );621 FormattedTextSubtitle fsub(m_safeArea, m_useBackground); 623 622 fsub.InitFromCC608(textlist->buffers); 624 fsub. Draw(this);625 m_refreshArea = true;623 fsub.Layout(); 624 m_refreshArea = m_refreshArea || fsub.Draw(this); 626 625 textlist->lock.unlock(); 627 626 } 628 627 … … void SubtitleScreen::DisplayCC708Subtitles(void) 643 642 for (uint i = 0; i < 8; i++) 644 643 cc708service->windows[i].changed = true; 645 644 int size = (m_safeArea.height() * m_textFontZoom) / 2000; 646 m_708fontSizes[1] = size;647 m_708fontSizes[0] = size * 32 / 42;648 m_708fontSizes[2] = size * 42 / 32;645 g_708fontSizes[1] = size; 646 g_708fontSizes[0] = size * 32 / 42; 647 g_708fontSizes[2] = size * 42 / 32; 649 648 } 650 649 } 651 650 else … … void SubtitleScreen::DisplayCC708Subtitles(void) 669 668 QMutexLocker locker(&win.lock); 670 669 vector<CC708String*> list = win.GetStrings(); 671 670 if (!list.empty()) 672 Display708Strings(win, i, video_aspect, list); 671 { 672 FormattedTextSubtitle fsub(m_safeArea, m_useBackground); 673 fsub.InitFromCC708(win, i, list, video_aspect, m_textFontZoom); 674 fsub.Layout(); 675 // Draw the window background after calculating bounding 676 // rectangle in Layout() 677 if (win.GetFillAlpha()) // TODO border? 678 { 679 QBrush fill(win.GetFillColor(), Qt::SolidPattern); 680 MythUIShape *shape = 681 new MythUIShape(this, QString("cc708bg%1").arg(i)); 682 shape->SetFillBrush(fill); 683 shape->SetArea(MythRect(fsub.m_bounds)); 684 m_708imageCache[i].append(shape); 685 m_refreshArea = true; 686 } 687 m_refreshArea = 688 m_refreshArea || fsub.Draw(this, &m_708imageCache[i]); 689 } 673 690 for (uint j = 0; j < list.size(); j++) 674 691 delete list[j]; 675 692 win.changed = false; … … void SubtitleScreen::Clear708Cache(int num) 686 703 } 687 704 } 688 705 689 void SubtitleScreen::Display708Strings(const CC708Window &win, int num,690 float aspect, vector<CC708String*> &list)691 {692 LOG(VB_VBI, LOG_INFO,LOC +693 QString("Display Win %1, Anchor_id %2, x_anch %3, y_anch %4, "694 "relative %5")695 .arg(num).arg(win.anchor_point).arg(win.anchor_horizontal)696 .arg(win.anchor_vertical).arg(win.relative_pos));697 698 bool display = false;699 MythFontProperties *mythfont;700 uint max_row_width = 0;701 uint total_height = 0;702 uint i = 0;703 for (uint row = 0; (row < win.true_row_count) && (i < list.size()); row++)704 {705 uint row_width = 0, max_row_height = 0;706 for (; (i < list.size()) && list[i] && (list[i]->y <= row); i++)707 {708 if (list[i]->y < row)709 continue;710 711 mythfont = Get708Font(list[i]->attr);712 if (!mythfont)713 continue;714 715 QString text = list[i]->str.trimmed();716 if (!text.isEmpty())717 display = true;718 719 QFontMetrics font(*(mythfont->GetFace()));720 uint height = (uint)font.height() * (1 + PAD_HEIGHT);721 722 row_width += font.width(list[i]->str) +723 (font.maxWidth() * PAD_WIDTH * 2);724 max_row_height = max(max_row_height, height);725 }726 727 max_row_width = max(max_row_width, row_width);728 total_height += max_row_height;729 }730 731 if (!display)732 return;733 734 float xrange = win.relative_pos ? 100.0f :735 (aspect > 1.4f) ? 210.0f : 160.0f;736 float yrange = win.relative_pos ? 100.0f : 75.0f;737 float xmult = (float)m_safeArea.width() / xrange;738 float ymult = (float)m_safeArea.height() / yrange;739 uint anchor_x = (uint)(xmult * (float)win.anchor_horizontal);740 uint anchor_y = (uint)(ymult * (float)win.anchor_vertical);741 742 if (win.anchor_point % 3 == 1)743 anchor_x -= (((int)max_row_width) / 2);744 if (win.anchor_point % 3 == 2)745 anchor_x -= (int)max_row_width;746 if (win.anchor_point / 3 == 1)747 anchor_y -= (((int)total_height) / 2);748 if (win.anchor_point / 3 == 2)749 anchor_y -= (int)total_height;750 751 if (win.GetFillAlpha()) // TODO border?752 {753 QRect bg(anchor_x, anchor_y, max_row_width, total_height);754 QBrush fill(win.GetFillColor(), Qt::SolidPattern);755 MythUIShape *shape = new MythUIShape(this,756 QString("cc708bg%1").arg(num));757 shape->SetFillBrush(fill);758 shape->SetArea(MythRect(bg));759 m_708imageCache[num].append(shape);760 m_refreshArea = true;761 }762 763 i = 0;764 int y = anchor_y;765 for (uint row = 0; (row < win.true_row_count) && (i < list.size()); row++)766 {767 uint maxheight = 0;768 int x = anchor_x;769 bool first = true;770 for (; (i < list.size()) && list[i] && (list[i]->y <= row); i++)771 {772 bool last = ((i + 1) == list.size());773 if (!last)774 last = (list[i + 1]->y > row);775 776 QString rawstring = list[i]->str;777 mythfont = Get708Font(list[i]->attr);778 779 if ((list[i]->y < row) || !mythfont || rawstring.isEmpty())780 continue;781 782 QString trimmed = rawstring.trimmed();783 if (!trimmed.size() && last)784 continue;785 786 QFontMetrics font(*(mythfont->GetFace()));787 uint height = (uint)font.height() * (1 + PAD_HEIGHT);788 maxheight = max(maxheight, height);789 uint spacewidth = font.width(QString(" "));790 uint textwidth = font.width(trimmed);791 792 int leading = 0;793 int trailing = 0;794 if (trimmed.size() != rawstring.size())795 {796 if (trimmed.size())797 {798 leading = rawstring.indexOf(trimmed.at(0));799 trailing = rawstring.size() - trimmed.size() - leading;800 }801 else802 {803 leading = rawstring.size();804 }805 leading *= spacewidth;806 trailing *= spacewidth;807 }808 809 if (!leading)810 textwidth += spacewidth * PAD_WIDTH;811 if (!trailing)812 textwidth += spacewidth * PAD_WIDTH;813 814 bool background = list[i]->attr.GetBGAlpha();815 QBrush bgfill = QBrush((list[i]->attr.GetBGColor(), Qt::SolidPattern));816 817 if (leading && background && !first)818 {819 // draw background for leading space820 QRect space(x, y, leading, height);821 MythUIShape *shape = new MythUIShape(this,822 QString("cc708shape%1x%2lead").arg(row).arg(i));823 shape->SetFillBrush(bgfill);824 shape->SetArea(MythRect(space));825 m_708imageCache[num].append(shape);826 m_refreshArea = true;827 }828 829 x += leading;830 QRect rect(x, y, textwidth, height);831 832 if (trimmed.size() && textwidth && background)833 {834 MythUIShape *shape = new MythUIShape(this,835 QString("cc708shape%1x%2main").arg(row).arg(i));836 shape->SetFillBrush(bgfill);837 shape->SetArea(MythRect(rect));838 m_708imageCache[num].append(shape);839 m_refreshArea = true;840 }841 842 if (trimmed.size() && textwidth)843 {844 MythUISimpleText *text = new MythUISimpleText845 (list[i]->str, *mythfont,846 rect, Qt::AlignCenter,847 (MythUIType*)this,848 QString("cc708text%1x%2").arg(row).arg(i));849 m_708imageCache[num].append(text);850 m_refreshArea = true;851 }852 853 x += textwidth;854 855 if (trailing && background && !last)856 {857 // draw background for trailing space858 QRect space(x, y, trailing, height);859 MythUIShape *shape = new MythUIShape(this,860 QString("cc708shape%1x%2trail").arg(row).arg(i));861 shape->SetFillBrush(bgfill);862 shape->SetArea(MythRect(space));863 m_708imageCache[num].append(shape);864 m_refreshArea = true;865 }866 867 x += trailing;868 first = false;869 LOG(VB_VBI, LOG_INFO, QString("Win %1 row %2 String '%3'")870 .arg(num).arg(row).arg(list[i]->str));871 }872 y += maxheight;873 }874 }875 876 706 void SubtitleScreen::AddScaledImage(QImage &img, QRect &pos) 877 707 { 878 708 VideoOutput *vo = m_player->GetVideoOutput(); … … void SubtitleScreen::AddScaledImage(QImage &img, QRect &pos) 904 734 } 905 735 } 906 736 907 bool SubtitleScreen::InitialiseFont(int fontStretch)908 {909 static bool initialised = false;910 QString font = gCoreContext->GetSetting("OSDSubFont", "FreeSans");911 if (initialised)912 {913 if (gTextSubFont->face().family() == font &&914 gTextSubFont->face().stretch() == fontStretch)915 {916 return true;917 }918 delete gTextSubFont;919 }920 921 MythFontProperties *mythfont = new MythFontProperties();922 if (mythfont)923 {924 QFont newfont(font);925 newfont.setStretch(fontStretch);926 font.detach();927 mythfont->SetFace(newfont);928 mythfont->SetOutline(true, Qt::black, 2, 255);929 gTextSubFont = mythfont;930 }931 else932 return false;933 934 initialised = true;935 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Loaded main subtitle font '%1'")936 .arg(font));937 return true;938 }939 940 737 bool SubtitleScreen::Initialise708Fonts(int fontStretch) 941 738 { 942 739 static bool initialised = false; … … bool SubtitleScreen::Initialise708Fonts(int fontStretch) 950 747 LOG(VB_GENERAL, LOG_INFO, "Initialise708Fonts()"); 951 748 952 749 QStringList fonts; 953 fonts.append("Droid Sans Mono"); // default 750 QString defaultFont = gCoreContext->GetSetting("OSDSubFont", "FreeSans"); 751 fonts.append(defaultFont); // default 954 752 fonts.append("FreeMono"); // mono serif 955 753 fonts.append("DejaVu Serif"); // prop serif 956 754 fonts.append("Droid Sans Mono"); // mono sans … … MythFontProperties* SubtitleScreen::Get708Font(CC708CharacterAttribute attr) 986 784 return NULL; 987 785 988 786 mythfont->GetFace()->setItalic(attr.italics); 989 mythfont->GetFace()->setPixelSize( m_708fontSizes[attr.pen_size & 0x3]);787 mythfont->GetFace()->setPixelSize(g_708fontSizes[attr.pen_size & 0x3]); 990 788 mythfont->GetFace()->setUnderline(attr.underline); 789 mythfont->GetFace()->setBold(attr.boldface); 991 790 mythfont->SetColor(attr.GetFGColor()); 992 791 993 int off = m_708fontSizes[attr.pen_size & 0x3] / 20;792 int off = g_708fontSizes[attr.pen_size & 0x3] / 20; 994 793 QPoint shadowsz(off, off); 995 794 QColor colour = attr.GetEdgeColor(); 996 795 int alpha = attr.GetFGAlpha(); … … MythFontProperties* SubtitleScreen::Get708Font(CC708CharacterAttribute attr) 1019 818 return mythfont; 1020 819 } 1021 820 1022 void FormattedTextChunk::GetSize(int pixelSize, int &width, int &height) const 821 static QString srtColorString(QColor color) 1023 822 { 1024 QFont *font = gTextSubFont->GetFace(); 1025 font->setItalic(isItalic); 1026 font->setBold(isBold); 1027 font->setUnderline(isUnderline); 1028 font->setPixelSize(pixelSize); 823 return QString("#%1%2%3") 824 .arg(color.red(), 2, 16, QLatin1Char('0')) 825 .arg(color.green(), 2, 16, QLatin1Char('0')) 826 .arg(color.blue(), 2, 16, QLatin1Char('0')); 827 } 828 829 void FormattedTextChunk::GetSize(int &width, int &height) const 830 { 831 QFont *font = SubtitleScreen::Get708Font(format)->GetFace(); 1029 832 QFontMetrics fm(*font); 1030 833 width = fm.width(text) + fm.maxWidth() * PAD_WIDTH; 1031 834 height = fm.height() * (1 + PAD_HEIGHT); … … void FormattedTextSubtitle::InitFromCC608(vector<CC608Text*> &buffers) 1043 846 return; 1044 847 vector<CC608Text*>::iterator i = buffers.begin(); 1045 848 bool teletextmode = (*i)->teletextmode; 1046 m_useBackground = m_useBackground && !teletextmode;849 bool useBackground = m_useBackground && !teletextmode; 1047 850 int xscale = teletextmode ? 40 : 36; 1048 851 int yscale = teletextmode ? 25 : 17; 1049 m_pixelSize = m_safeArea.height() / (yscale * 1.1765f); 852 int pixelSize = m_safeArea.height() / (yscale * LINE_SPACING); 853 SubtitleScreen::g_708fontSizes[k708AttrSizeStandard] = pixelSize; 1050 854 1051 855 for (; i != buffers.end(); ++i) 1052 856 { … … void FormattedTextSubtitle::InitFromCC608(vector<CC608Text*> &buffers) 1060 864 int x = (int)(((float)orig_x / (float)xscale) * (float)m_safeArea.width()); 1061 865 int orig_y = teletextmode ? cc->x : cc->y; 1062 866 int y = (int)(((float)orig_y / (float)yscale) * (float)m_safeArea.height()); 1063 FormattedTextLine line(x, y );867 FormattedTextLine line(x, y, orig_x, orig_y); 1064 868 for (int chunk = 0; text != QString::null; chunk++) 1065 869 { 1066 870 QString captionText = 1067 871 extract_cc608(text, cc->teletextmode, 1068 872 color, isItalic, isUnderline); 1069 FormattedTextChunk chunk(captionText, 1070 isItalic, isBold, isUnderline, 1071 clr[min(max(0, color), 7)]); 873 CC708CharacterAttribute attr(isItalic, isBold, isUnderline, 874 clr[min(max(0, color), 7)], 875 useBackground); 876 FormattedTextChunk chunk(captionText, attr); 1072 877 line.chunks += chunk; 1073 878 LOG(VB_VBI, LOG_INFO, 1074 879 QString("Adding cc608 chunk: x=%1 y=%2 " … … void FormattedTextSubtitle::InitFromCC608(vector<CC608Text*> &buffers) 1080 885 } 1081 886 } 1082 887 888 void FormattedTextSubtitle::InitFromCC708(const CC708Window &win, int num, 889 const vector<CC708String*> &list, 890 float aspect, 891 int textFontZoom) 892 { 893 int pixelSize = (m_safeArea.height() * textFontZoom) / 2000; 894 SubtitleScreen::g_708fontSizes[k708AttrSizeSmall] = pixelSize * 32 / 42; 895 SubtitleScreen::g_708fontSizes[k708AttrSizeStandard] = pixelSize; 896 SubtitleScreen::g_708fontSizes[k708AttrSizeLarge] = pixelSize * 42 / 32; 897 898 float xrange = win.relative_pos ? 100.0f : 899 (aspect > 1.4f) ? 210.0f : 160.0f; 900 float yrange = win.relative_pos ? 100.0f : 75.0f; 901 float xmult = (float)m_safeArea.width() / xrange; 902 float ymult = (float)m_safeArea.height() / yrange; 903 uint anchor_x = (uint)(xmult * (float)win.anchor_horizontal); 904 uint anchor_y = (uint)(ymult * (float)win.anchor_vertical); 905 m_xAnchorPoint = win.anchor_point % 3; 906 m_yAnchorPoint = win.anchor_point / 3; 907 m_xAnchor = anchor_x; 908 m_yAnchor = anchor_y; 909 910 for (uint i = 0; i < list.size(); i++) 911 { 912 if (list[i]->y >= (uint)m_lines.size()) 913 m_lines.resize(list[i]->y + 1); 914 if (m_useBackground) 915 { 916 list[i]->attr.bg_color = k708AttrColorBlack; 917 list[i]->attr.bg_opacity = k708AttrOpacitySolid; 918 } 919 FormattedTextChunk chunk(list[i]->str, list[i]->attr); 920 m_lines[list[i]->y].chunks += chunk; 921 LOG(VB_VBI, LOG_INFO, QString("Adding 708 chunk '%1'").arg(chunk.text)); 922 } 923 } 924 1083 925 void FormattedTextSubtitle::InitFromSRT(QStringList &subs, int textFontZoom) 1084 926 { 1085 927 // Does a simplistic parsing of HTML tags from the strings. … … void FormattedTextSubtitle::InitFromSRT(QStringList &subs, int textFontZoom) 1096 938 // <font color="#xxyyzz"> - change font color 1097 939 // </font> - reset font color to white 1098 940 1099 m_pixelSize = (m_safeArea.height() * textFontZoom) / 2000; 941 int pixelSize = (m_safeArea.height() * textFontZoom) / 2000; 942 SubtitleScreen::g_708fontSizes[k708AttrSizeStandard] = pixelSize; 943 m_xAnchorPoint = 1; // center 944 m_yAnchorPoint = 2; // bottom 945 m_xAnchor = m_safeArea.width() / 2; 946 m_yAnchor = m_safeArea.height(); 1100 947 1101 948 bool isItalic = false; 1102 949 bool isBold = false; … … void FormattedTextSubtitle::InitFromSRT(QStringList &subs, int textFontZoom) 1114 961 int pos = text.indexOf(htmlTag); 1115 962 if (pos != 0) // don't add a zero-length string 1116 963 { 1117 FormattedTextChunk chunk(text.left(pos), 1118 isItalic, isBold, isUnderline, color); 964 CC708CharacterAttribute attr(isItalic, isBold, isUnderline, 965 color, m_useBackground); 966 FormattedTextChunk chunk(text.left(pos), attr); 1119 967 line.chunks += chunk; 1120 968 text = (pos < 0 ? "" : text.mid(pos)); 1121 969 LOG(VB_VBI, LOG_INFO, QString("Adding SRT chunk '%1'").arg(chunk.text)); … … void FormattedTextSubtitle::InitFromSRT(QStringList &subs, int textFontZoom) 1159 1007 1160 1008 LOG(VB_VBI, LOG_INFO, 1161 1009 QString("SRT formatting change '%1', " 1162 "new ital=%2 bold=%3 uline=%4 color= #%5%6%7)")1010 "new ital=%2 bold=%3 uline=%4 color=%5)") 1163 1011 .arg(html).arg(isItalic).arg(isBold).arg(isUnderline) 1164 .arg(color.red(), 2, 16, QLatin1Char('0')) 1165 .arg(color.green(), 2, 16, QLatin1Char('0')) 1166 .arg(color.blue(), 2, 16, QLatin1Char('0'))); 1012 .arg(srtColorString(color))); 1167 1013 } 1168 1014 } 1169 1015 m_lines += line; … … bool FormattedTextChunk::Split(FormattedTextChunk &newChunk) 1181 1027 QString("Failed to split chunk '%1'").arg(text)); 1182 1028 return false; 1183 1029 } 1184 newChunk.isItalic = isItalic; 1185 newChunk.isBold = isBold; 1186 newChunk.isUnderline = isUnderline; 1187 newChunk.color = color; 1030 newChunk.format = format; 1188 1031 newChunk.text = text.mid(lastSpace + 1).trimmed() + ' '; 1189 1032 text = text.left(lastSpace).trimmed(); 1190 1033 LOG(VB_VBI, LOG_INFO, … … void FormattedTextSubtitle::WrapLongLines(void) 1197 1040 int maxWidth = m_safeArea.width(); 1198 1041 for (int i = 0; i < m_lines.size(); i++) 1199 1042 { 1200 int width = m_lines[i].Width( m_pixelSize);1043 int width = m_lines[i].Width(); 1201 1044 // Move entire chunks to the next line as necessary. Leave at 1202 1045 // least one chunk on the current line. 1203 1046 while (width > maxWidth && m_lines[i].chunks.size() > 1) 1204 1047 { 1205 width -= m_lines[i].chunks.back().Width( m_pixelSize);1048 width -= m_lines[i].chunks.back().Width(); 1206 1049 // Make sure there's a next line to wrap into. 1207 1050 if (m_lines.size() == i + 1) 1208 1051 m_lines += FormattedTextLine(m_lines[i].x_indent, … … void FormattedTextSubtitle::WrapLongLines(void) 1226 1069 m_lines += FormattedTextLine(m_lines[i].x_indent, 1227 1070 m_lines[i].y_indent); 1228 1071 m_lines[i+1].chunks.prepend(newChunk); 1229 width = m_lines[i].Width( m_pixelSize);1072 width = m_lines[i].Width(); 1230 1073 } 1231 1074 } 1232 1075 } 1233 1076 } 1234 1077 1235 void FormattedTextSubtitle::Draw(SubtitleScreen *parent, 1078 // Resolves any TBD x_indent and y_indent values in FormattedTextLine 1079 // objects. Calculates m_bounds. Prunes most leading and all 1080 // trailing whitespace from each line so that displaying with a black 1081 // background doesn't look clumsy. 1082 void FormattedTextSubtitle::Layout(void) 1083 { 1084 // Calculate dimensions of bounding rectangle 1085 int anchor_width = 0; 1086 int anchor_height = 0; 1087 for (int i = 0; i < m_lines.size(); i++) 1088 { 1089 int width = m_lines[i].Width(); 1090 int height = m_lines[i].Height(); 1091 anchor_width = max(anchor_width, width); 1092 anchor_height += height * LINE_SPACING; 1093 } 1094 1095 // Adjust the anchor point according to actual width and height 1096 int anchor_x = m_xAnchor; 1097 int anchor_y = m_yAnchor; 1098 if (m_xAnchorPoint == 1) 1099 anchor_x -= anchor_width / 2; 1100 else if (m_xAnchorPoint == 2) 1101 anchor_x -= anchor_width; 1102 if (m_yAnchorPoint == 1) 1103 anchor_y -= anchor_height / 2; 1104 else if (m_yAnchorPoint == 2) 1105 anchor_y -= anchor_height; 1106 1107 m_bounds = QRect(anchor_x, anchor_y, anchor_width, anchor_height); 1108 1109 // Fill in missing coordinates 1110 int y = anchor_y; 1111 for (int i = 0; i < m_lines.size(); i++) 1112 { 1113 if (m_lines[i].x_indent < 0) 1114 m_lines[i].x_indent = anchor_x; 1115 if (m_lines[i].y_indent < 0) 1116 m_lines[i].y_indent = y; 1117 y += m_lines[i].Height() * LINE_SPACING; 1118 // Prune leading all-whitespace chunks. 1119 while (!m_lines[i].chunks.isEmpty() && 1120 m_lines[i].chunks.first().text.trimmed().isEmpty()) 1121 { 1122 m_lines[i].x_indent += m_lines[i].chunks.first().Width(); 1123 m_lines[i].chunks.removeFirst(); 1124 } 1125 // Prune trailing all-whitespace chunks. 1126 while (!m_lines[i].chunks.isEmpty() && 1127 m_lines[i].chunks.last().text.trimmed().isEmpty()) 1128 { 1129 m_lines[i].chunks.removeLast(); 1130 } 1131 // Trim trailing whitespace from last chunk. (Trimming 1132 // leading whitespace from the first chunk is handled in 1133 // the Draw() routine.) 1134 if (!m_lines[i].chunks.isEmpty()) 1135 { 1136 QString *str = &m_lines[i].chunks.last().text; 1137 int idx = str->length() - 1; 1138 while (idx >= 0 && str->at(idx) == ' ') 1139 --idx; 1140 str->truncate(idx + 1); 1141 } 1142 } 1143 } 1144 1145 // Returns true if anything new was drawn, false if not. The caller 1146 // should call SubtitleScreen::OptimiseDisplayedArea() if true is 1147 // returned. 1148 bool FormattedTextSubtitle::Draw(SubtitleScreen *parent, 1149 QList<MythUIType*> *imageCache, 1236 1150 uint64_t start, uint64_t duration) const 1237 1151 { 1238 bool useBackground = m_useBackground && parent->GetUseBackground(); 1239 gTextSubFont->GetFace()->setPixelSize(m_pixelSize); 1240 QFontMetrics font(*(gTextSubFont->GetFace())); 1241 int pad_width = font.maxWidth() * PAD_WIDTH; 1242 QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern); 1152 bool result = false; 1243 1153 1244 1154 for (int i = 0; i < m_lines.size(); i++) 1245 1155 { 1246 1156 int x = m_lines[i].x_indent; 1247 if (x < 0) // centering1248 x = (m_safeArea.width() - m_lines[i].Width(m_pixelSize)) / 2;1249 1157 int y = m_lines[i].y_indent; 1250 if (y < 0) // stack lines at bottom1251 y = m_safeArea.height() -1252 (m_lines.size() - i) * m_lines[i].Height(m_pixelSize) * 1.1765f;1253 1158 1254 if (useBackground) 1255 { 1256 QRect bgrect(x - pad_width, y, 1257 m_lines[i].Width(m_pixelSize) + pad_width, 1258 m_lines[i].Height(m_pixelSize)); 1259 // Special case. If the first chunk is entirely 1260 // whitespace, don't put a black background behind that 1261 // chunk. 1262 // 1263 // This often happens when a line of cc608 caption text 1264 // begins with a mid-row format control like italics or a 1265 // color change. The spec says the mid-row control 1266 // implies a space character, which needs to be preserved 1267 // so that the rest of the text is accurately laid out. A 1268 // leading space looks clumsy against the black 1269 // background, so we adjust the background accordingly. 1270 if (!m_lines[i].chunks.isEmpty() && 1271 m_lines[i].chunks[0].text.trimmed().isEmpty()) 1272 { 1273 bgrect.setLeft(bgrect.left() + 1274 m_lines[i].chunks[0].Width(m_pixelSize)); 1275 } 1276 MythUIShape *shape = 1277 new MythUIShape(parent, QString("subbg%1_%2").arg(x).arg(y)); 1278 shape->SetFillBrush(bgfill); 1279 shape->SetArea(MythRect(bgrect)); 1280 if (duration > 0) 1281 parent->RegisterExpiration(shape, start + duration); 1282 } 1159 int height = m_lines[i].Height(); 1283 1160 QList<FormattedTextChunk>::const_iterator chunk; 1161 bool first = true; 1284 1162 for (chunk = m_lines[i].chunks.constBegin(); 1285 1163 chunk != m_lines[i].chunks.constEnd(); 1286 1164 ++chunk) 1287 1165 { 1166 MythFontProperties *mythfont = 1167 SubtitleScreen::Get708Font((*chunk).format); 1168 if (!mythfont) 1169 continue; 1170 QFontMetrics font(*(mythfont->GetFace())); 1171 int pad_width = font.maxWidth() * PAD_WIDTH; 1172 bool background = (*chunk).format.GetBGAlpha(); 1173 QBrush bgfill = QBrush((*chunk).format.GetBGColor(), Qt::SolidPattern); 1288 1174 // If the chunk starts with whitespace, the leading 1289 1175 // whitespace ultimately gets lost due to the 1290 1176 // text.trimmed() operation in the MythUISimpleText … … void FormattedTextSubtitle::Draw(SubtitleScreen *parent, 1295 1181 (*chunk).text.at(count) == ' ') 1296 1182 ++count; 1297 1183 int x_adjust = count * font.width(" "); 1298 gTextSubFont->GetFace()->setItalic((*chunk).isItalic); 1299 gTextSubFont->GetFace()->setBold((*chunk).isBold); 1300 gTextSubFont->GetFace()->setUnderline((*chunk).isUnderline); 1301 gTextSubFont->SetColor((*chunk).color); 1184 if (background) 1185 { 1186 QRect bgrect(x, y, (*chunk).Width(), height); 1187 if (first) 1188 bgrect.setLeft(bgrect.left() + x_adjust - pad_width); 1189 MythUIShape *bgshape = new MythUIShape(parent, 1190 QString("subbg%1x%2@%3,%4") 1191 .arg((*chunk).Width()) 1192 .arg(height) 1193 .arg(x).arg(y)); 1194 bgshape->SetFillBrush(bgfill); 1195 bgshape->SetArea(MythRect(bgrect)); 1196 if (imageCache) 1197 imageCache->append(bgshape); 1198 if (duration > 0) 1199 parent->RegisterExpiration(bgshape, start + duration); 1200 result = true; 1201 } 1302 1202 QRect rect(x + x_adjust, y, 1303 (*chunk).Width( m_pixelSize) - x_adjust,1304 (*chunk).Height(m_pixelSize));1203 (*chunk).Width() - x_adjust, 1204 height); 1305 1205 1306 1206 MythUISimpleText *text = 1307 new MythUISimpleText((*chunk).text, * gTextSubFont, rect,1207 new MythUISimpleText((*chunk).text, *mythfont, rect, 1308 1208 Qt::AlignLeft, (MythUIType*)parent, 1309 1209 QString("subtxt%1x%2@%3,%4") 1310 .arg((*chunk).Width( m_pixelSize))1311 .arg( (*chunk).Height(m_pixelSize))1210 .arg((*chunk).Width()) 1211 .arg(height) 1312 1212 .arg(x).arg(y)); 1213 if (imageCache) 1214 imageCache->append(text); 1313 1215 if (duration > 0) 1314 1216 parent->RegisterExpiration(text, start + duration); 1217 result = true; 1315 1218 1316 1219 LOG(VB_VBI, LOG_INFO, 1317 1220 QString("Drawing chunk at (%1,%2) with " 1318 "ital=%3 bold=%4 uline=%5 color=#%6 %7%8"1319 "text='% 9'")1221 "ital=%3 bold=%4 uline=%5 color=#%6 " 1222 "text='%7'") 1320 1223 .arg(x).arg(y) 1321 .arg((*chunk).isItalic) 1322 .arg((*chunk).isBold) 1323 .arg((*chunk).isUnderline) 1324 .arg((*chunk).color.red(), 2, 16, QLatin1Char('0')) 1325 .arg((*chunk).color.green(), 2, 16, QLatin1Char('0')) 1326 .arg((*chunk).color.blue(), 2, 16, QLatin1Char('0')) 1327 .arg((*chunk).text)); 1328 1329 x += (*chunk).Width(m_pixelSize); 1224 .arg((*chunk).format.italics) 1225 .arg((*chunk).format.boldface) 1226 .arg((*chunk).format.underline) 1227 .arg(srtColorString((*chunk).format.GetFGColor())) 1228 .arg((*chunk).text.mid(count))); 1229 1230 x += (*chunk).Width(); 1231 first = false; 1330 1232 } 1331 1233 } 1234 return result; 1235 } 1236 1237 QStringList FormattedTextSubtitle::ToSRT(void) const 1238 { 1239 QStringList result; 1240 for (int i = 0; i < m_lines.size(); i++) 1241 { 1242 QString line; 1243 if (m_lines[i].orig_x > 0) 1244 line.fill(' ', m_lines[i].orig_x); 1245 QList<FormattedTextChunk>::const_iterator chunk; 1246 for (chunk = m_lines[i].chunks.constBegin(); 1247 chunk != m_lines[i].chunks.constEnd(); 1248 ++chunk) 1249 { 1250 const QString &text = (*chunk).text; 1251 LOG(VB_GENERAL, LOG_INFO, QString("JMS chunk '%1'").arg(text)); 1252 const CC708CharacterAttribute &attr = (*chunk).format; 1253 bool isBlank = !attr.underline && text.trimmed().isEmpty(); 1254 if (!isBlank) 1255 { 1256 if (attr.boldface) 1257 line += "<b>"; 1258 if (attr.italics) 1259 line += "<i>"; 1260 if (attr.underline) 1261 line += "<u>"; 1262 if (attr.GetFGColor() != Qt::white) 1263 line += QString("<font color=\"%1\">") 1264 .arg(srtColorString(attr.GetFGColor())); 1265 } 1266 line += text; 1267 if (!isBlank) 1268 { 1269 if (attr.GetFGColor() != Qt::white) 1270 line += QString("</font>"); 1271 if (attr.underline) 1272 line += "</u>"; 1273 if (attr.italics) 1274 line += "</i>"; 1275 if (attr.boldface) 1276 line += "</b>"; 1277 } 1278 } 1279 if (!line.trimmed().isEmpty()) 1280 { 1281 LOG(VB_GENERAL, LOG_INFO, QString("JMS line '%1'").arg(line)); 1282 result += line; 1283 } 1284 } 1285 return result; 1332 1286 } 1333 1287 1334 1288 #ifdef USING_LIBASS -
mythtv/libs/libmythtv/subtitlescreen.h
diff --git a/mythtv/libs/libmythtv/subtitlescreen.h b/mythtv/libs/libmythtv/subtitlescreen.h index da3ae19..02971c2 100644
a b extern "C" { 15 15 16 16 class SubtitleScreen : public MythScreenType 17 17 { 18 static bool InitialiseFont(int fontStretch = QFont::Unstretched);19 18 static bool Initialise708Fonts(int fontStretch = QFont::Unstretched); 20 19 21 20 public: … … class SubtitleScreen : public MythScreenType 42 41 virtual bool Create(void); 43 42 virtual void Pulse(void); 44 43 44 static int g_708fontSizes[4]; 45 static MythFontProperties* Get708Font(CC708CharacterAttribute attr); 46 45 47 private: 46 48 void OptimiseDisplayedArea(void); 47 49 void DisplayAVSubtitles(void); … … class SubtitleScreen : public MythScreenType 53 55 void DisplayCC708Subtitles(void); 54 56 void AddScaledImage(QImage &img, QRect &pos); 55 57 void Clear708Cache(int num); 56 void Display708Strings(const CC708Window &win, int num,57 float aspect, vector<CC708String*> &list);58 MythFontProperties* Get708Font(CC708CharacterAttribute attr);59 58 60 59 MythPlayer *m_player; 61 60 SubtitleReader *m_subreader; … … class SubtitleScreen : public MythScreenType 66 65 QRegExp m_removeHTML; 67 66 int m_subtitleType; 68 67 QHash<MythUIType*, long long> m_expireTimes; 69 int m_708fontSizes[3]; 70 int m_textFontZoom; 68 int m_textFontZoom; // valid for 708 & text subs 71 69 bool m_refreshArea; 72 70 QHash<int,QList<MythUIType*> > m_708imageCache; 73 71 int m_fontStretch; … … class SubtitleScreen : public MythScreenType 92 90 93 91 struct FormattedTextChunk 94 92 { 95 FormattedTextChunk(const QString &t, bool ital, bool bold, bool uline, 96 QColor clr) 97 : text(t), isItalic(ital), isBold(bold), isUnderline(uline), 98 color(clr) {} 93 FormattedTextChunk(const QString &t, CC708CharacterAttribute formatting) 94 : text(t), format(formatting) {} 99 95 FormattedTextChunk(void) {} 100 int Width( int pixelSize) const {96 int Width(void) const { 101 97 int width, height; 102 GetSize( pixelSize,width, height);98 GetSize(width, height); 103 99 return width; 104 100 } 105 int Height( int pixelSize) const {101 int Height(void) const { 106 102 int width, height; 107 GetSize( pixelSize,width, height);103 GetSize(width, height); 108 104 return height; 109 105 } 110 106 bool Split(FormattedTextChunk &newChunk); 111 107 QString text; 112 bool isItalic; 113 bool isBold; 114 bool isUnderline; 115 QColor color; 108 CC708CharacterAttribute format; 116 109 private: 117 void GetSize(int pixelSize, int&width, int &height) const;110 void GetSize(int &width, int &height) const; 118 111 }; 119 112 120 113 struct FormattedTextLine 121 114 { 122 FormattedTextLine(int x = -1, int y = -1) : x_indent(x), y_indent(y) {} 123 int Height(int pixelSize) const { 115 FormattedTextLine(int x = -1, int y = -1, int o_x = -1, int o_y = -1) 116 : x_indent(x), y_indent(y), orig_x(o_x), orig_y(o_y) {} 117 int Height(void) const { 124 118 int result = 0; 125 119 QList<FormattedTextChunk>::const_iterator it; 126 120 for (it = chunks.constBegin(); it != chunks.constEnd(); ++it) { 127 int height = (*it).Height( pixelSize);121 int height = (*it).Height(); 128 122 result = max(result, height); 129 123 } 130 124 return result; 131 125 } 132 int Width( int pixelSize) const {126 int Width(void) const { 133 127 int result = 0; 134 128 QList<FormattedTextChunk>::const_iterator it; 135 129 for (it = chunks.constBegin(); it != chunks.constEnd(); ++it) { 136 int width = (*it).Width( pixelSize);130 int width = (*it).Width(); 137 131 result += width; 138 132 } 139 133 return result; … … struct FormattedTextLine 141 135 QList<FormattedTextChunk> chunks; 142 136 int x_indent; // -1 means TBD i.e. centered 143 137 int y_indent; // -1 means TBD i.e. relative to bottom 138 int orig_x, orig_y; // original, unscaled coordinates 144 139 }; 145 140 146 141 class FormattedTextSubtitle 147 142 { 148 143 public: 149 FormattedTextSubtitle(const QRect &safearea) 150 : m_safeArea(safearea), m_useBackground(true) {} 144 FormattedTextSubtitle(const QRect &safearea, bool useBackground) 145 : m_safeArea(safearea), m_useBackground(useBackground) {} 146 FormattedTextSubtitle(void) 147 : m_safeArea(QRect(0, 0, 640, 360)), m_useBackground(false) {} 151 148 void InitFromCC608(vector<CC608Text*> &buffers); 149 void InitFromCC708(const CC708Window &win, int num, 150 const vector<CC708String*> &list, 151 float aspect = 1.77777f, 152 int textFontZoom = 100); 152 153 void InitFromSRT(QStringList &subs, int textFontZoom); 153 154 void WrapLongLines(void); 154 void Draw(SubtitleScreen *parent, 155 void Layout(void); 156 bool Draw(SubtitleScreen *parent, 157 QList<MythUIType*> *imageCache = 0, 155 158 uint64_t start = 0, uint64_t duration = 0) const; 159 QStringList ToSRT(void) const; 160 QRect m_bounds; 156 161 private: 157 162 QVector<FormattedTextLine> m_lines; 158 163 const QRect m_safeArea; 159 bool m_useBackground; 160 int m_pixelSize; 164 const bool m_useBackground; 165 int m_xAnchorPoint; // 0=left, 1=center, 2=right 166 int m_yAnchorPoint; // 0=top, 1=center, 2=bottom 167 int m_xAnchor; // pixels from left 168 int m_yAnchor; // pixels from top 161 169 }; 162 170 163 171 #endif // SUBTITLESCREEN_H