Ticket #10194: srt_cc708_v6.patch
File srt_cc708_v6.patch, 51.8 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 0ff837d..5e948be 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::forceBlackBackground = 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 e6a57cc..420137d 100644
a b const uint k708AttrOpacityFlash = 1; 106 106 const uint k708AttrOpacityTranslucent = 2; 107 107 const uint k708AttrOpacityTransparent = 3; 108 108 109 bool CC708Window::forceBlackBackground = 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 (forceBlackBackground)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 (forceBlackBackground)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 (forceBlackBackground)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 (forceBlackBackground)374 {375 GetCCChar().attr.bg_color = k708AttrColorBlack;376 GetCCChar().attr.bg_opacity = k708AttrOpacityTranslucent;377 }378 352 GetCCChar().character = ch; 379 353 int c = pen.column; 380 354 int r = pen.row; … … void CC708Pen::SetPenStyle(uint style) 531 505 attr.font_tag = style2font[style]; 532 506 attr.italics = 0; 533 507 attr.underline = 0; 508 attr.boldface = 0; 534 509 attr.edge_type = 0; 535 510 attr.fg_color = k708AttrColorWhite; 536 511 attr.fg_opacity = k708AttrOpacitySolid; … … void CC708Pen::SetPenStyle(uint style) 538 513 attr.bg_opacity = (style<6) ? 539 514 k708AttrOpacitySolid : k708AttrOpacityTransparent; 540 515 attr.edge_color = k708AttrColorBlack; 516 attr.override_fg_color = false; 541 517 } 542 518 543 519 CC708Character::CC708Character(const CC708Window &win) 544 520 { 545 521 attr = win.pen.attr; 546 if (CC708Window::forceBlackBackground)547 {548 attr.fg_opacity = k708AttrOpacityTransparent;549 attr.bg_opacity = k708AttrOpacityTransparent;550 }551 522 character = ' '; 552 523 } 553 524 -
mythtv/libs/libmythtv/cc708window.h
diff --git a/mythtv/libs/libmythtv/cc708window.h b/mythtv/libs/libmythtv/cc708window.h index ccce79e..c5657db 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 } 112 CC708CharacterAttribute(void) : override_fg_color(false) {} 113 35 114 // remove this 36 115 uint FontIndex(void) const 37 116 { … … class CC708CharacterAttribute 41 120 static QColor ConvertToQColor(uint eia708color); 42 121 QColor GetFGColor(void) const 43 122 { 44 QColor fg = ConvertToQColor(fg_color); 123 QColor fg = (override_fg_color ? 124 actual_fg_color : ConvertToQColor(fg_color)); 45 125 fg.setAlpha(GetFGAlpha()); 46 126 return fg; 47 127 } … … class CC708Pen 88 168 attr.edge_type = edge_type; 89 169 attr.underline = underline; 90 170 attr.italics = italics; 171 attr.boldface = 0; 91 172 } 92 173 public: 93 174 CC708CharacterAttribute attr; … … class MTV_PUBLIC CC708Window 200 281 bool exists; 201 282 bool changed; 202 283 203 static bool forceBlackBackground;204 205 284 mutable QMutex lock; 206 285 }; 207 286 … … class CC708Service 215 294 CC708Window windows[8]; 216 295 }; 217 296 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 297 #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 c9b951e..0ead516 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; 19 20 20 21 SubtitleScreen::SubtitleScreen(MythPlayer *player, const char * name, … … SubtitleScreen::SubtitleScreen(MythPlayer *player, const char * name, 26 27 m_textFontZoom(100), m_refreshArea(false), 27 28 m_fontStretch(fontStretch) 28 29 { 29 m_708fontSizes[0] = 36;30 m_708fontSizes[1] = 45;31 m_708fontSizes[2] = 60;32 30 m_removeHTML.setMinimal(true); 33 31 34 32 #ifdef USING_LIBASS … … void SubtitleScreen::DisplayAVSubtitles(void) 346 344 347 345 void SubtitleScreen::DisplayTextSubtitles(void) 348 346 { 349 if (!Initialise Font(m_fontStretch) || !m_player || !m_subreader)347 if (!Initialise708Fonts(m_fontStretch) || !m_player || !m_subreader) 350 348 return; 351 349 352 350 bool changed = false; … … void SubtitleScreen::DisplayTextSubtitles(void) 421 419 422 420 void SubtitleScreen::DisplayRawTextSubtitles(void) 423 421 { 424 if (!Initialise Font(m_fontStretch) || !m_player || !m_subreader)422 if (!Initialise708Fonts(m_fontStretch) || !m_player || !m_subreader) 425 423 return; 426 424 427 425 uint64_t duration; … … void SubtitleScreen::DisplayRawTextSubtitles(void) 445 443 void SubtitleScreen::DrawTextSubtitles(QStringList &wrappedsubs, 446 444 uint64_t start, uint64_t duration) 447 445 { 448 FormattedTextSubtitle fsub(m_safeArea );446 FormattedTextSubtitle fsub(m_safeArea, m_useBackground, this); 449 447 fsub.InitFromSRT(wrappedsubs, m_textFontZoom); 450 448 fsub.WrapLongLines(); 451 fsub. Draw(this);452 m_refreshArea = true;449 fsub.Layout(); 450 m_refreshArea = m_refreshArea || fsub.Draw(0, start, duration); 453 451 } 454 452 455 453 void SubtitleScreen::DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos) … … static QString extract_cc608( 583 581 584 582 void SubtitleScreen::DisplayCC608Subtitles(void) 585 583 { 586 if (!Initialise Font(m_fontStretch) || !m_608reader)584 if (!Initialise708Fonts(m_fontStretch) || !m_608reader) 587 585 return; 588 586 589 587 bool changed = false; … … void SubtitleScreen::DisplayCC608Subtitles(void) 619 617 return; 620 618 } 621 619 622 FormattedTextSubtitle fsub(m_safeArea );620 FormattedTextSubtitle fsub(m_safeArea, m_useBackground, this); 623 621 fsub.InitFromCC608(textlist->buffers); 624 fsub. Draw(this);625 m_refreshArea = true;622 fsub.Layout(); 623 m_refreshArea = m_refreshArea || fsub.Draw(); 626 624 textlist->lock.unlock(); 627 625 } 628 626 … … void SubtitleScreen::DisplayCC708Subtitles(void) 646 644 m_708fontSizes[1] = size; 647 645 m_708fontSizes[0] = size * 32 / 42; 648 646 m_708fontSizes[2] = size * 42 / 32; 647 m_708fontSizes[3] = 1; // just to be safe 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, this); 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(&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 … … bool SubtitleScreen::Initialise708Fonts(int fontStretch) 980 778 } 981 779 982 780 MythFontProperties* SubtitleScreen::Get708Font(CC708CharacterAttribute attr) 781 const 983 782 { 984 783 MythFontProperties *mythfont = gCC708Fonts[attr.font_tag & 0x7]; 985 784 if (!mythfont) … … MythFontProperties* SubtitleScreen::Get708Font(CC708CharacterAttribute attr) 988 787 mythfont->GetFace()->setItalic(attr.italics); 989 788 mythfont->GetFace()->setPixelSize(m_708fontSizes[attr.pen_size & 0x3]); 990 789 mythfont->GetFace()->setUnderline(attr.underline); 790 mythfont->GetFace()->setBold(attr.boldface); 991 791 mythfont->SetColor(attr.GetFGColor()); 992 792 993 793 int off = m_708fontSizes[attr.pen_size & 0x3] / 20; … … MythFontProperties* SubtitleScreen::Get708Font(CC708CharacterAttribute attr) 1019 819 return mythfont; 1020 820 } 1021 821 1022 QSize FormattedTextChunk::CalcSize(int pixelSize) const 822 static QString srtColorString(QColor color) 1023 823 { 1024 QFont *font = gTextSubFont->GetFace(); 1025 font->setItalic(isItalic); 1026 font->setBold(isBold); 1027 font->setUnderline(isUnderline); 1028 font->setPixelSize(pixelSize); 1029 QFontMetrics fm(*font); 1030 int width = fm.width(text) + fm.maxWidth() * PAD_WIDTH; 1031 int height = fm.height() * (1 + PAD_HEIGHT); 1032 return QSize(width, height); 824 return QString("#%1%2%3") 825 .arg(color.red(), 2, 16, QLatin1Char('0')) 826 .arg(color.green(), 2, 16, QLatin1Char('0')) 827 .arg(color.blue(), 2, 16, QLatin1Char('0')); 1033 828 } 1034 829 1035 830 void FormattedTextSubtitle::InitFromCC608(vector<CC608Text*> &buffers) … … void FormattedTextSubtitle::InitFromCC608(vector<CC608Text*> &buffers) 1044 839 return; 1045 840 vector<CC608Text*>::iterator i = buffers.begin(); 1046 841 bool teletextmode = (*i)->teletextmode; 1047 m_useBackground = m_useBackground && !teletextmode;842 bool useBackground = m_useBackground && !teletextmode; 1048 843 int xscale = teletextmode ? 40 : 36; 1049 844 int yscale = teletextmode ? 25 : 17; 1050 m_pixelSize = m_safeArea.height() / (yscale * 1.1765f); 845 int pixelSize = m_safeArea.height() / (yscale * LINE_SPACING); 846 if (parent) 847 parent->SetFontSizes(pixelSize, pixelSize, pixelSize); 1051 848 1052 849 for (; i != buffers.end(); ++i) 1053 850 { … … void FormattedTextSubtitle::InitFromCC608(vector<CC608Text*> &buffers) 1063 860 int orig_y = teletextmode ? cc->x : cc->y; 1064 861 int y = (int)(((float)orig_y / (float)yscale) * 1065 862 (float)m_safeArea.height()); 1066 FormattedTextLine line(x, y );863 FormattedTextLine line(x, y, orig_x, orig_y); 1067 864 for (int chunk = 0; text != QString::null; chunk++) 1068 865 { 1069 866 QString captionText = 1070 867 extract_cc608(text, cc->teletextmode, 1071 868 color, isItalic, isUnderline); 1072 FormattedTextChunk chunk(captionText, 1073 isItalic, isBold, isUnderline, 1074 clr[min(max(0, color), 7)]); 869 CC708CharacterAttribute attr(isItalic, isBold, isUnderline, 870 clr[min(max(0, color), 7)], 871 useBackground); 872 FormattedTextChunk chunk(captionText, attr, parent); 1075 873 line.chunks += chunk; 1076 874 LOG(VB_VBI, LOG_INFO, 1077 QString("Adding cc608 chunk: x=%1 y=%2 " 1078 "uline=%3 ital=%4 color=%5 text='%6'") 1079 .arg(cc->x).arg(cc->y) 1080 .arg(isUnderline).arg(isItalic).arg(color).arg(captionText)); 875 QString("Adding cc608 chunk (%1,%2): %3") 876 .arg(cc->x).arg(cc->y).arg(chunk.ToLogString())); 1081 877 } 1082 878 m_lines += line; 1083 879 } 1084 880 } 1085 881 882 void FormattedTextSubtitle::InitFromCC708(const CC708Window &win, int num, 883 const vector<CC708String*> &list, 884 float aspect, 885 int textFontZoom) 886 { 887 LOG(VB_VBI, LOG_INFO,LOC + 888 QString("Display Win %1, Anchor_id %2, x_anch %3, y_anch %4, " 889 "relative %5") 890 .arg(num).arg(win.anchor_point).arg(win.anchor_horizontal) 891 .arg(win.anchor_vertical).arg(win.relative_pos)); 892 int pixelSize = (m_safeArea.height() * textFontZoom) / 2000; 893 if (parent) 894 parent->SetFontSizes(pixelSize * 32 / 42, pixelSize, pixelSize * 42 / 32); 895 896 float xrange = win.relative_pos ? 100.0f : 897 (aspect > 1.4f) ? 210.0f : 160.0f; 898 float yrange = win.relative_pos ? 100.0f : 75.0f; 899 float xmult = (float)m_safeArea.width() / xrange; 900 float ymult = (float)m_safeArea.height() / yrange; 901 uint anchor_x = (uint)(xmult * (float)win.anchor_horizontal); 902 uint anchor_y = (uint)(ymult * (float)win.anchor_vertical); 903 m_xAnchorPoint = win.anchor_point % 3; 904 m_yAnchorPoint = win.anchor_point / 3; 905 m_xAnchor = anchor_x; 906 m_yAnchor = anchor_y; 907 908 for (uint i = 0; i < list.size(); i++) 909 { 910 if (list[i]->y >= (uint)m_lines.size()) 911 m_lines.resize(list[i]->y + 1); 912 if (m_useBackground) 913 { 914 list[i]->attr.bg_color = k708AttrColorBlack; 915 list[i]->attr.bg_opacity = k708AttrOpacitySolid; 916 } 917 FormattedTextChunk chunk(list[i]->str, list[i]->attr, parent); 918 m_lines[list[i]->y].chunks += chunk; 919 LOG(VB_VBI, LOG_INFO, QString("Adding cc708 chunk: win %1 row %2: %3") 920 .arg(num).arg(i).arg(chunk.ToLogString())); 921 } 922 } 923 1086 924 void FormattedTextSubtitle::InitFromSRT(QStringList &subs, int textFontZoom) 1087 925 { 1088 926 // Does a simplistic parsing of HTML tags from the strings. … … void FormattedTextSubtitle::InitFromSRT(QStringList &subs, int textFontZoom) 1099 937 // <font color="#xxyyzz"> - change font color 1100 938 // </font> - reset font color to white 1101 939 1102 m_pixelSize = (m_safeArea.height() * textFontZoom) / 2000; 940 int pixelSize = (m_safeArea.height() * textFontZoom) / 2000; 941 if (parent) 942 parent->SetFontSizes(pixelSize, pixelSize, pixelSize); 943 m_xAnchorPoint = 1; // center 944 m_yAnchorPoint = 2; // bottom 945 m_xAnchor = m_safeArea.width() / 2; 946 m_yAnchor = m_safeArea.height(); 1103 947 1104 948 bool isItalic = false; 1105 949 bool isBold = false; … … void FormattedTextSubtitle::InitFromSRT(QStringList &subs, int textFontZoom) 1117 961 int pos = text.indexOf(htmlTag); 1118 962 if (pos != 0) // don't add a zero-length string 1119 963 { 1120 FormattedTextChunk chunk( 1121 text.left(pos), isItalic, isBold, isUnderline, color); 964 CC708CharacterAttribute attr(isItalic, isBold, isUnderline, 965 color, m_useBackground); 966 FormattedTextChunk chunk(text.left(pos), attr, parent); 1122 967 line.chunks += chunk; 1123 968 text = (pos < 0 ? "" : text.mid(pos)); 1124 LOG(VB_VBI, LOG_INFO, QString("Adding SRT chunk '%1'")1125 .arg(chunk. text));969 LOG(VB_VBI, LOG_INFO, QString("Adding SRT chunk: %1") 970 .arg(chunk.ToLogString())); 1126 971 } 1127 972 if (pos >= 0) 1128 973 { … … void FormattedTextSubtitle::InitFromSRT(QStringList &subs, int textFontZoom) 1171 1016 1172 1017 LOG(VB_VBI, LOG_INFO, 1173 1018 QString("SRT formatting change '%1', " 1174 "new ital=%2 bold=%3 uline=%4 color= #%5%6%7)")1019 "new ital=%2 bold=%3 uline=%4 color=%5)") 1175 1020 .arg(html).arg(isItalic).arg(isBold).arg(isUnderline) 1176 .arg(color.red(), 2, 16, QLatin1Char('0')) 1177 .arg(color.green(), 2, 16, QLatin1Char('0')) 1178 .arg(color.blue(), 2, 16, QLatin1Char('0'))); 1021 .arg(srtColorString(color))); 1179 1022 } 1180 1023 } 1181 1024 m_lines += line; … … bool FormattedTextChunk::Split(FormattedTextChunk &newChunk) 1193 1036 QString("Failed to split chunk '%1'").arg(text)); 1194 1037 return false; 1195 1038 } 1196 newChunk.isItalic = isItalic; 1197 newChunk.isBold = isBold; 1198 newChunk.isUnderline = isUnderline; 1199 newChunk.color = color; 1039 newChunk.format = format; 1200 1040 newChunk.text = text.mid(lastSpace + 1).trimmed() + ' '; 1201 1041 text = text.left(lastSpace).trimmed(); 1202 1042 LOG(VB_VBI, LOG_INFO, … … bool FormattedTextChunk::Split(FormattedTextChunk &newChunk) 1204 1044 return true; 1205 1045 } 1206 1046 1047 QString FormattedTextChunk::ToLogString(void) const 1048 { 1049 QString str(""); 1050 str += QString("fg=%1.%2 ") 1051 .arg(srtColorString(format.GetFGColor())) 1052 .arg(format.GetFGAlpha()); 1053 str += QString("bg=%1.%2 ") 1054 .arg(srtColorString(format.GetBGColor())) 1055 .arg(format.GetBGAlpha()); 1056 str += QString("edge=%1.%2 ") 1057 .arg(srtColorString(format.GetEdgeColor())) 1058 .arg(format.edge_type); 1059 str += QString("off=%1 pensize=%2 ") 1060 .arg(format.offset) 1061 .arg(format.pen_size); 1062 str += QString("it=%1 ul=%2 bf=%3 ") 1063 .arg(format.italics) 1064 .arg(format.underline) 1065 .arg(format.boldface); 1066 str += QString("font=%1 ").arg(format.font_tag); 1067 str += QString(" text='%1'").arg(text); 1068 return str; 1069 } 1070 1207 1071 void FormattedTextSubtitle::WrapLongLines(void) 1208 1072 { 1209 1073 int maxWidth = m_safeArea.width(); 1210 1074 for (int i = 0; i < m_lines.size(); i++) 1211 1075 { 1212 int width = m_lines[i].CalcSize( m_pixelSize).width();1076 int width = m_lines[i].CalcSize().width(); 1213 1077 // Move entire chunks to the next line as necessary. Leave at 1214 1078 // least one chunk on the current line. 1215 1079 while (width > maxWidth && m_lines[i].chunks.size() > 1) 1216 1080 { 1217 width -= m_lines[i].chunks.back().CalcSize( m_pixelSize).width();1081 width -= m_lines[i].chunks.back().CalcSize().width(); 1218 1082 // Make sure there's a next line to wrap into. 1219 1083 if (m_lines.size() == i + 1) 1220 1084 m_lines += FormattedTextLine(m_lines[i].x_indent, … … void FormattedTextSubtitle::WrapLongLines(void) 1238 1102 m_lines += FormattedTextLine(m_lines[i].x_indent, 1239 1103 m_lines[i].y_indent); 1240 1104 m_lines[i+1].chunks.prepend(newChunk); 1241 width = m_lines[i].CalcSize( m_pixelSize).width();1105 width = m_lines[i].CalcSize().width(); 1242 1106 } 1243 1107 } 1244 1108 } 1245 1109 } 1246 1110 1247 void FormattedTextSubtitle::Draw(SubtitleScreen *parent, 1248 uint64_t start, uint64_t duration) const 1111 // Resolves any TBD x_indent and y_indent values in FormattedTextLine 1112 // objects. Calculates m_bounds. Prunes most leading and all 1113 // trailing whitespace from each line so that displaying with a black 1114 // background doesn't look clumsy. 1115 void FormattedTextSubtitle::Layout(void) 1249 1116 { 1250 bool useBackground = m_useBackground && parent->GetUseBackground(); 1251 gTextSubFont->GetFace()->setPixelSize(m_pixelSize); 1252 QFontMetrics font(*(gTextSubFont->GetFace())); 1253 int pad_width = font.maxWidth() * PAD_WIDTH; 1254 QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern); 1117 // Calculate dimensions of bounding rectangle 1118 int anchor_width = 0; 1119 int anchor_height = 0; 1120 for (int i = 0; i < m_lines.size(); i++) 1121 { 1122 QSize sz = m_lines[i].CalcSize(); 1123 anchor_width = max(anchor_width, sz.width()); 1124 anchor_height += sz.height() * LINE_SPACING; 1125 } 1255 1126 1127 // Adjust the anchor point according to actual width and height 1128 int anchor_x = m_xAnchor; 1129 int anchor_y = m_yAnchor; 1130 if (m_xAnchorPoint == 1) 1131 anchor_x -= anchor_width / 2; 1132 else if (m_xAnchorPoint == 2) 1133 anchor_x -= anchor_width; 1134 if (m_yAnchorPoint == 1) 1135 anchor_y -= anchor_height / 2; 1136 else if (m_yAnchorPoint == 2) 1137 anchor_y -= anchor_height; 1138 1139 m_bounds = QRect(anchor_x, anchor_y, anchor_width, anchor_height); 1140 1141 // Fill in missing coordinates 1142 int y = anchor_y; 1256 1143 for (int i = 0; i < m_lines.size(); i++) 1257 1144 { 1258 int x = m_lines[i].x_indent, y = m_lines[i].y_indent; 1259 QSize sz; 1260 if ((x < 0) || (y < 0) || useBackground) 1261 sz = m_lines[i].CalcSize(m_pixelSize); 1262 if (x < 0) // centering 1263 x = (m_safeArea.width() - sz.width()) / 2; 1264 if (y < 0) // stack lines at bottom 1145 if (m_lines[i].x_indent < 0) 1146 m_lines[i].x_indent = anchor_x; 1147 if (m_lines[i].y_indent < 0) 1148 m_lines[i].y_indent = y; 1149 y += m_lines[i].CalcSize().height() * LINE_SPACING; 1150 // Prune leading all-whitespace chunks. 1151 while (!m_lines[i].chunks.isEmpty() && 1152 m_lines[i].chunks.first().text.trimmed().isEmpty()) 1265 1153 { 1266 y = m_safeArea.height(); 1267 y -= (m_lines.size() - i) * sz.height() * 1.1765f; 1154 m_lines[i].x_indent += 1155 m_lines[i].chunks.first().CalcSize().width(); 1156 m_lines[i].chunks.removeFirst(); 1268 1157 } 1269 1270 if (useBackground) 1158 // Prune trailing all-whitespace chunks. 1159 while (!m_lines[i].chunks.isEmpty() && 1160 m_lines[i].chunks.last().text.trimmed().isEmpty()) 1271 1161 { 1272 QRect bgrect(x - pad_width, y, 1273 sz.width() + pad_width, sz.height()); 1274 // Special case. If the first chunk is entirely 1275 // whitespace, don't put a black background behind that 1276 // chunk. 1277 // 1278 // This often happens when a line of cc608 caption text 1279 // begins with a mid-row format control like italics or a 1280 // color change. The spec says the mid-row control 1281 // implies a space character, which needs to be preserved 1282 // so that the rest of the text is accurately laid out. A 1283 // leading space looks clumsy against the black 1284 // background, so we adjust the background accordingly. 1285 if (!m_lines[i].chunks.isEmpty() && 1286 m_lines[i].chunks[0].text.trimmed().isEmpty()) 1287 { 1288 bgrect.setLeft( 1289 bgrect.left() + 1290 m_lines[i].chunks[0].CalcSize(m_pixelSize).width()); 1291 } 1292 MythUIShape *shape = 1293 new MythUIShape(parent, QString("subbg%1_%2").arg(x).arg(y)); 1294 shape->SetFillBrush(bgfill); 1295 shape->SetArea(MythRect(bgrect)); 1296 if (duration > 0) 1297 parent->RegisterExpiration(shape, start + duration); 1162 m_lines[i].chunks.removeLast(); 1298 1163 } 1164 // Trim trailing whitespace from last chunk. (Trimming 1165 // leading whitespace from all chunks is handled in the Draw() 1166 // routine.) 1167 if (!m_lines[i].chunks.isEmpty()) 1168 { 1169 QString *str = &m_lines[i].chunks.last().text; 1170 int idx = str->length() - 1; 1171 while (idx >= 0 && str->at(idx) == ' ') 1172 --idx; 1173 str->truncate(idx + 1); 1174 } 1175 } 1176 } 1177 1178 // Returns true if anything new was drawn, false if not. The caller 1179 // should call SubtitleScreen::OptimiseDisplayedArea() if true is 1180 // returned. 1181 bool FormattedTextSubtitle::Draw(QList<MythUIType*> *imageCache, 1182 uint64_t start, uint64_t duration) const 1183 { 1184 bool result = false; 1299 1185 1186 for (int i = 0; i < m_lines.size(); i++) 1187 { 1188 int x = m_lines[i].x_indent, y = m_lines[i].y_indent; 1189 int height = m_lines[i].CalcSize().height(); 1300 1190 QList<FormattedTextChunk>::const_iterator chunk; 1191 bool first = true; 1301 1192 for (chunk = m_lines[i].chunks.constBegin(); 1302 1193 chunk != m_lines[i].chunks.constEnd(); 1303 1194 ++chunk) 1304 1195 { 1196 MythFontProperties *mythfont = parent->Get708Font((*chunk).format); 1197 if (!mythfont) 1198 continue; 1199 QFontMetrics font(*(mythfont->GetFace())); 1305 1200 // If the chunk starts with whitespace, the leading 1306 1201 // whitespace ultimately gets lost due to the 1307 1202 // text.trimmed() operation in the MythUISimpleText … … void FormattedTextSubtitle::Draw(SubtitleScreen *parent, 1314 1209 ++count; 1315 1210 } 1316 1211 int x_adjust = count * font.width(" "); 1317 gTextSubFont->GetFace()->setItalic((*chunk).isItalic); 1318 gTextSubFont->GetFace()->setBold((*chunk).isBold); 1319 gTextSubFont->GetFace()->setUnderline((*chunk).isUnderline); 1320 gTextSubFont->SetColor((*chunk).color); 1321 QSize chunk_sz = (*chunk).CalcSize(m_pixelSize); 1212 QSize chunk_sz = (*chunk).CalcSize(); 1213 if ((*chunk).format.GetBGAlpha()) 1214 { 1215 QBrush bgfill = QBrush((*chunk).format.GetBGColor()); 1216 QRect bgrect(x, y, chunk_sz.width(), height); 1217 if (first) 1218 bgrect.setLeft(bgrect.left() + x_adjust - 1219 font.maxWidth() * PAD_WIDTH); 1220 MythUIShape *bgshape = new MythUIShape(parent, 1221 QString("subbg%1x%2@%3,%4") 1222 .arg(chunk_sz.width()) 1223 .arg(height) 1224 .arg(x).arg(y)); 1225 bgshape->SetFillBrush(bgfill); 1226 bgshape->SetArea(MythRect(bgrect)); 1227 if (imageCache) 1228 imageCache->append(bgshape); 1229 if (duration > 0) 1230 parent->RegisterExpiration(bgshape, start + duration); 1231 result = true; 1232 } 1322 1233 QRect rect(x + x_adjust, y, 1323 chunk_sz.width() - x_adjust, chunk_sz.height());1234 chunk_sz.width() - x_adjust, height); 1324 1235 1325 1236 MythUISimpleText *text = 1326 new MythUISimpleText((*chunk).text, * gTextSubFont, rect,1237 new MythUISimpleText((*chunk).text, *mythfont, rect, 1327 1238 Qt::AlignLeft, (MythUIType*)parent, 1328 1239 QString("subtxt%1x%2@%3,%4") 1329 1240 .arg(chunk_sz.width()) 1330 .arg( chunk_sz.height())1241 .arg(height) 1331 1242 .arg(x).arg(y)); 1243 if (imageCache) 1244 imageCache->append(text); 1332 1245 if (duration > 0) 1333 1246 parent->RegisterExpiration(text, start + duration); 1247 result = true; 1334 1248 1335 1249 LOG(VB_VBI, LOG_INFO, 1336 QString("Drawing chunk at (%1,%2) with " 1337 "ital=%3 bold=%4 uline=%5 color=#%6%7%8 " 1338 "text='%9'") 1339 .arg(x).arg(y) 1340 .arg((*chunk).isItalic) 1341 .arg((*chunk).isBold) 1342 .arg((*chunk).isUnderline) 1343 .arg((*chunk).color.red(), 2, 16, QLatin1Char('0')) 1344 .arg((*chunk).color.green(), 2, 16, QLatin1Char('0')) 1345 .arg((*chunk).color.blue(), 2, 16, QLatin1Char('0')) 1346 .arg((*chunk).text)); 1250 QString("Drawing chunk at (%1,%2): %3") 1251 .arg(x).arg(y).arg((*chunk).ToLogString())); 1347 1252 1348 1253 x += chunk_sz.width(); 1254 first = false; 1255 } 1256 } 1257 return result; 1258 } 1259 1260 QStringList FormattedTextSubtitle::ToSRT(void) const 1261 { 1262 QStringList result; 1263 for (int i = 0; i < m_lines.size(); i++) 1264 { 1265 QString line; 1266 if (m_lines[i].orig_x > 0) 1267 line.fill(' ', m_lines[i].orig_x); 1268 QList<FormattedTextChunk>::const_iterator chunk; 1269 for (chunk = m_lines[i].chunks.constBegin(); 1270 chunk != m_lines[i].chunks.constEnd(); 1271 ++chunk) 1272 { 1273 const QString &text = (*chunk).text; 1274 const CC708CharacterAttribute &attr = (*chunk).format; 1275 bool isBlank = !attr.underline && text.trimmed().isEmpty(); 1276 if (!isBlank) 1277 { 1278 if (attr.boldface) 1279 line += "<b>"; 1280 if (attr.italics) 1281 line += "<i>"; 1282 if (attr.underline) 1283 line += "<u>"; 1284 if (attr.GetFGColor() != Qt::white) 1285 line += QString("<font color=\"%1\">") 1286 .arg(srtColorString(attr.GetFGColor())); 1287 } 1288 line += text; 1289 if (!isBlank) 1290 { 1291 if (attr.GetFGColor() != Qt::white) 1292 line += QString("</font>"); 1293 if (attr.underline) 1294 line += "</u>"; 1295 if (attr.italics) 1296 line += "</i>"; 1297 if (attr.boldface) 1298 line += "</b>"; 1299 } 1349 1300 } 1301 if (!line.trimmed().isEmpty()) 1302 result += line; 1350 1303 } 1304 return result; 1305 } 1306 1307 void SubtitleScreen::SetFontSizes(int small, int medium, int large) 1308 { 1309 m_708fontSizes[k708AttrSizeSmall] = small; 1310 m_708fontSizes[k708AttrSizeStandard] = medium; 1311 m_708fontSizes[k708AttrSizeLarge] = large; 1312 } 1313 1314 QSize SubtitleScreen::CalcTextSize(const QString &text, 1315 const CC708CharacterAttribute &format) const 1316 { 1317 QFont *font = Get708Font(format)->GetFace(); 1318 QFontMetrics fm(*font); 1319 int width = fm.width(text) + fm.maxWidth() * PAD_WIDTH; 1320 int height = fm.height() * (1 + PAD_HEIGHT); 1321 return QSize(width, height); 1351 1322 } 1352 1323 1353 1324 #ifdef USING_LIBASS -
mythtv/libs/libmythtv/subtitlescreen.h
diff --git a/mythtv/libs/libmythtv/subtitlescreen.h b/mythtv/libs/libmythtv/subtitlescreen.h index c8f805a..ab40bd0 100644
a b extern "C" { 23 23 24 24 class SubtitleScreen : public MythScreenType 25 25 { 26 static bool InitialiseFont(int fontStretch = QFont::Unstretched); 26 friend class FormattedTextSubtitle; 27 27 28 static bool Initialise708Fonts(int fontStretch = QFont::Unstretched); 28 29 29 30 public: … … class SubtitleScreen : public MythScreenType 40 41 void ExpireSubtitles(void); 41 42 void DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos); 42 43 44 QSize CalcTextSize(const QString &text, 45 const CC708CharacterAttribute &format) const; 46 43 47 void RegisterExpiration(MythUIType *shape, long long endTime) 44 48 { 45 49 m_expireTimes.insert(shape, endTime); … … class SubtitleScreen : public MythScreenType 62 66 void DisplayCC708Subtitles(void); 63 67 void AddScaledImage(QImage &img, QRect &pos); 64 68 void Clear708Cache(int num); 65 void Display708Strings(const CC708Window &win, int num, 66 float aspect, vector<CC708String*> &list); 67 MythFontProperties* Get708Font(CC708CharacterAttribute attr); 69 MythFontProperties* Get708Font(CC708CharacterAttribute attr) const; 70 void SetFontSizes(int small, int medium, int large); 68 71 69 72 MythPlayer *m_player; 70 73 SubtitleReader *m_subreader; … … class SubtitleScreen : public MythScreenType 75 78 QRegExp m_removeHTML; 76 79 int m_subtitleType; 77 80 QHash<MythUIType*, long long> m_expireTimes; 78 int m_708fontSizes[ 3];79 int m_textFontZoom; 81 int m_708fontSizes[4]; 82 int m_textFontZoom; // valid for 708 & text subs 80 83 bool m_refreshArea; 81 84 QHash<int,QList<MythUIType*> > m_708imageCache; 82 85 int m_fontStretch; … … class SubtitleScreen : public MythScreenType 102 105 class FormattedTextChunk 103 106 { 104 107 public: 105 FormattedTextChunk( 106 const QString &t, bool ital, bool bold, bool uline, QColor clr) :107 text(t), isItalic(ital), isBold(bold), isUnderline(uline), color(clr)108 FormattedTextChunk(const QString &t, CC708CharacterAttribute formatting, 109 SubtitleScreen *p) 110 : text(t), format(formatting), parent(p) 108 111 { 109 112 } 110 113 FormattedTextChunk(void) {} 111 114 112 QSize CalcSize(int pixelSize) const; 115 QSize CalcSize(void) const 116 { 117 return parent->CalcTextSize(text, format); 118 } 113 119 bool Split(FormattedTextChunk &newChunk); 120 QString ToLogString(void) const; 114 121 115 122 QString text; 116 bool isItalic; 117 bool isBold; 118 bool isUnderline; 119 QColor color; 123 CC708CharacterAttribute format; 124 SubtitleScreen *parent; // where fonts and sizes are kept 120 125 }; 121 126 122 127 class FormattedTextLine 123 128 { 124 129 public: 125 FormattedTextLine(int x = -1, int y = -1) : x_indent(x), y_indent(y) {} 130 FormattedTextLine(int x = -1, int y = -1, int o_x = -1, int o_y = -1) 131 : x_indent(x), y_indent(y), orig_x(o_x), orig_y(o_y) {} 126 132 127 QSize CalcSize( int pixelSize) const133 QSize CalcSize(void) const 128 134 { 129 135 int height = 0, width = 0; 130 136 QList<FormattedTextChunk>::const_iterator it; 131 137 for (it = chunks.constBegin(); it != chunks.constEnd(); ++it) 132 138 { 133 QSize tmp = (*it).CalcSize( pixelSize);139 QSize tmp = (*it).CalcSize(); 134 140 height = max(height, tmp.height()); 135 141 width += tmp.width(); 136 142 } … … class FormattedTextLine 140 146 QList<FormattedTextChunk> chunks; 141 147 int x_indent; // -1 means TBD i.e. centered 142 148 int y_indent; // -1 means TBD i.e. relative to bottom 149 int orig_x, orig_y; // original, unscaled coordinates 143 150 }; 144 151 145 152 class FormattedTextSubtitle 146 153 { 147 154 public: 148 FormattedTextSubtitle(const QRect &safearea) : 149 m_safeArea(safearea), m_useBackground(true) {} 155 FormattedTextSubtitle(const QRect &safearea, bool useBackground, 156 SubtitleScreen *p) 157 : m_safeArea(safearea), m_useBackground(useBackground), 158 parent(p) {} 159 FormattedTextSubtitle(void) 160 : m_safeArea(QRect()), m_useBackground(false), parent(0) {} 150 161 void InitFromCC608(vector<CC608Text*> &buffers); 162 void InitFromCC708(const CC708Window &win, int num, 163 const vector<CC708String*> &list, 164 float aspect = 1.77777f, 165 int textFontZoom = 100); 151 166 void InitFromSRT(QStringList &subs, int textFontZoom); 152 167 void WrapLongLines(void); 153 void Draw(SubtitleScreen *parent, 168 void Layout(void); 169 bool Draw(QList<MythUIType*> *imageCache = 0, 154 170 uint64_t start = 0, uint64_t duration = 0) const; 171 QStringList ToSRT(void) const; 172 QRect m_bounds; 155 173 156 174 private: 157 175 QVector<FormattedTextLine> m_lines; 158 176 const QRect m_safeArea; 159 bool m_useBackground; 160 int m_pixelSize; 177 const bool m_useBackground; 178 SubtitleScreen *parent; // where fonts and sizes are kept 179 int m_xAnchorPoint; // 0=left, 1=center, 2=right 180 int m_yAnchorPoint; // 0=top, 1=center, 2=bottom 181 int m_xAnchor; // pixels from left 182 int m_yAnchor; // pixels from top 161 183 }; 162 184 163 185 #endif // SUBTITLESCREEN_H