void SubtitleScreen::DrawTextSubtitles(QStringList &wrappedsubs, uint64_t start, uint64_t duration) { QFontMetrics font(*(gTextSubFont->GetFace())); int height = font.height() * (1 + PAD_HEIGHT); int pad_width = font.maxWidth() * PAD_WIDTH; int y = m_safeArea.height() - (height * wrappedsubs.size()); int centre = m_safeArea.width() / 2; QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern); foreach (QString subtitle, wrappedsubs) { if (subtitle.isEmpty()) continue; int width = font.width(subtitle) + pad_width * 2; int x = centre - (width / 2) - pad_width; QRect rect(x, y, width, height); if (m_useBackground) { MythUIShape *shape = new MythUIShape(this, QString("tsubbg%1%2").arg(x).arg(y)); shape->SetFillBrush(bgfill); shape->SetArea(MythRect(rect)); if (duration > 0) m_expireTimes.insert(shape, start + duration); } MythUISimpleText* text = new MythUISimpleText (subtitle, *gTextSubFont, rect, Qt::AlignCenter, this, QString("tsub%1%2").arg(x).arg(y)); y += height; LOG(VB_PLAYBACK, LOG_INFO, LOC + subtitle); m_refreshArea = true; if (duration > 0) { m_expireTimes.insert(text, start + duration); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Display text subtitle for %1 ms").arg(duration)); } } }
void SubtitleScreen::Display708Strings(const CC708Window &win, int num, float aspect, vector<CC708String*> &list) { LOG(VB_VBI, LOG_INFO,LOC + QString("Display Win %1, Anchor_id %2, x_anch %3, y_anch %4, " "relative %5") .arg(num).arg(win.anchor_point).arg(win.anchor_horizontal) .arg(win.anchor_vertical).arg(win.relative_pos)); bool display = false; MythFontProperties *mythfont; uint max_row_width = 0; uint total_height = 0; uint i = 0; for (uint row = 0; (row < win.true_row_count) && (i < list.size()); row++) { uint row_width = 0, max_row_height = 0; for (; (i < list.size()) && list[i] && (list[i]->y <= row); i++) { if (list[i]->y < row) continue; mythfont = Get708Font(list[i]->attr); if (!mythfont) continue; QString text = list[i]->str.trimmed(); if (!text.isEmpty()) display = true; QFontMetrics font(*(mythfont->GetFace())); uint height = (uint)font.height() * (1 + PAD_HEIGHT); row_width += font.width(list[i]->str) + (font.maxWidth() * PAD_WIDTH * 2); max_row_height = max(max_row_height, height); } max_row_width = max(max_row_width, row_width); total_height += max_row_height; } if (!display) return; float xrange = win.relative_pos ? 100.0f : (aspect > 1.4f) ? 210.0f : 160.0f; float yrange = win.relative_pos ? 100.0f : 75.0f; float xmult = (float)m_safeArea.width() / xrange; float ymult = (float)m_safeArea.height() / yrange; uint anchor_x = (uint)(xmult * (float)win.anchor_horizontal); uint anchor_y = (uint)(ymult * (float)win.anchor_vertical); if (win.anchor_point % 3 == 1) anchor_x -= (((int)max_row_width) / 2); if (win.anchor_point % 3 == 2) anchor_x -= (int)max_row_width; if (win.anchor_point / 3 == 1) anchor_y -= (((int)total_height) / 2); if (win.anchor_point / 3 == 2) anchor_y -= (int)total_height; if (win.GetFillAlpha()) // TODO border? { QRect bg(anchor_x, anchor_y, max_row_width, total_height); QBrush fill(win.GetFillColor(), Qt::SolidPattern); MythUIShape *shape = new MythUIShape(this, QString("cc708bg%1").arg(num)); shape->SetFillBrush(fill); shape->SetArea(MythRect(bg)); m_708imageCache[num].append(shape); m_refreshArea = true; } i = 0; int y = anchor_y; for (uint row = 0; (row < win.true_row_count) && (i < list.size()); row++) { uint maxheight = 0; int x = anchor_x; bool first = true; for (; (i < list.size()) && list[i] && (list[i]->y <= row); i++) { bool last = ((i + 1) == list.size()); if (!last) last = (list[i + 1]->y > row); QString rawstring = list[i]->str; mythfont = Get708Font(list[i]->attr); if ((list[i]->y < row) || !mythfont || rawstring.isEmpty()) continue; QString trimmed = rawstring.trimmed(); if (!trimmed.size() && last) continue; QFontMetrics font(*(mythfont->GetFace())); uint height = (uint)font.height() * (1 + PAD_HEIGHT); maxheight = max(maxheight, height); uint spacewidth = font.width(QString(" ")); uint textwidth = font.width(trimmed); int leading = 0; int trailing = 0; if (trimmed.size() != rawstring.size()) { if (trimmed.size()) { leading = rawstring.indexOf(trimmed.at(0)); trailing = rawstring.size() - trimmed.size() - leading; } else { leading = rawstring.size(); } leading *= spacewidth; trailing *= spacewidth; } if (!leading) textwidth += spacewidth * PAD_WIDTH; if (!trailing) textwidth += spacewidth * PAD_WIDTH; bool background = list[i]->attr.GetBGAlpha(); QBrush bgfill = QBrush((list[i]->attr.GetBGColor(), Qt::SolidPattern)); if (leading && background && !first) { // draw background for leading space QRect space(x, y, leading, height); MythUIShape *shape = new MythUIShape(this, QString("cc708shape%1x%2lead").arg(row).arg(i)); shape->SetFillBrush(bgfill); shape->SetArea(MythRect(space)); m_708imageCache[num].append(shape); m_refreshArea = true; } x += leading; QRect rect(x, y, textwidth, height); if (trimmed.size() && textwidth && background) { MythUIShape *shape = new MythUIShape(this, QString("cc708shape%1x%2main").arg(row).arg(i)); shape->SetFillBrush(bgfill); shape->SetArea(MythRect(rect)); m_708imageCache[num].append(shape); m_refreshArea = true; } if (trimmed.size() && textwidth) { MythUIText *text = new MythUIText(list[i]->str, *mythfont, rect, rect, (MythUIType*)this, QString("cc708text%1x%2").arg(row).arg(i)); m_708imageCache[num].append(text); if (text) text->SetJustification(Qt::AlignCenter); m_refreshArea = true; } x += textwidth; if (trailing && background && !last) { // draw background for trailing space QRect space(x, y, trailing, height); MythUIShape *shape = new MythUIShape(this, QString("cc708shape%1x%2trail").arg(row).arg(i)); shape->SetFillBrush(bgfill); shape->SetArea(MythRect(space)); m_708imageCache[num].append(shape); m_refreshArea = true; } x += trailing; first = false; LOG(VB_VBI, LOG_INFO, QString("Win %1 row %2 String '%3'") .arg(num).arg(row).arg(list[i]->str)); } y += maxheight; } }
void SubtitleScreen::DisplayCC608Subtitles(void) { static const QColor clr[8] = { Qt::white, Qt::red, Qt::green, Qt::yellow, Qt::blue, Qt::magenta, Qt::cyan, Qt::white, }; if (!InitialiseFont(m_fontStretch) || !m_608reader) return; bool changed = false; if (m_player && m_player->GetVideoOutput()) { QRect oldsafe = m_safeArea; m_safeArea = m_player->GetVideoOutput()->GetSafeRect(); if (oldsafe != m_safeArea) changed = true; } else { return; } CC608Buffer* textlist = m_608reader->GetOutputText(changed); if (!changed) return; if (textlist) textlist->lock.lock(); DeleteAllChildren(); if (!textlist) return; if (textlist && textlist->buffers.empty()) { SetRedraw(); textlist->lock.unlock(); return; } vector<CC608Text*>::iterator i = textlist->buffers.begin(); bool teletextmode = (*i)->teletextmode; int xscale = teletextmode ? 40 : 36; int yscale = teletextmode ? 25 : 17; gTextSubFont->GetFace()->setPixelSize(m_safeArea.height() / (yscale * 1.2)); QFontMetrics font(*(gTextSubFont->GetFace())); QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern); int height = font.height() * (1 + PAD_HEIGHT); int pad_width = font.maxWidth() * PAD_WIDTH; for (; i != textlist->buffers.end(); i++) { CC608Text *cc = (*i); if (cc && (cc->text != QString::null)) { int width = font.width(cc->text) + pad_width; int x = teletextmode ? cc->y : (cc->x + 3); int y = teletextmode ? cc->x : cc->y; x = (int)(((float)x / (float)xscale) * (float)m_safeArea.width()); y = (int)(((float)y / (float)yscale) * (float)m_safeArea.height()); QRect rect(x, y, width, height); if (!teletextmode && m_useBackground) { MythUIShape *shape = new MythUIShape(this, QString("cc608bg%1%2%3").arg(cc->x).arg(cc->y).arg(width)); shape->SetFillBrush(bgfill); QRect bgrect(x - pad_width, y, width + pad_width, height); shape->SetArea(MythRect(bgrect)); } gTextSubFont->SetColor(clr[min(max(0, cc->color), 7)]); MythUIText *text = new MythUIText( cc->text, *gTextSubFont, rect, rect, (MythUIType*)this, QString("cc608txt%1%2%3").arg(cc->x).arg(cc->y).arg(width)); if (text) text->SetJustification(Qt::AlignLeft); m_refreshArea = true; LOG(VB_VBI, LOG_INFO, QString("x %1 y %2 String: '%3'") .arg(cc->x).arg(cc->y).arg(cc->text)); } } textlist->lock.unlock(); }