void SubtitleScreen::DisplayRawTextSubtitles(void) { if (!InitialiseFont(m_fontStretch) || !m_player || !m_subreader) return; uint64_t duration; QStringList subs = m_subreader->GetRawTextSubtitles(duration); if (subs.empty()) return; VideoOutput *vo = m_player->GetVideoOutput(); if (vo) { QRect oldsafe = m_safeArea; m_safeArea = m_player->GetVideoOutput()->GetSafeRect(); if (oldsafe != m_safeArea) { int height = (m_safeArea.height() * m_textFontZoom) / 1800; gTextSubFont->GetFace()->setPixelSize(height); gTextSubFont->SetColor(Qt::white); } } else return; VideoFrame *currentFrame = vo->GetLastShownFrame(); if (!currentFrame) return; // delete old subs that may still be on screen DeleteAllChildren(); OptimiseTextSubs(subs); DrawTextSubtitles(subs, currentFrame->timecode, duration); }
GlFont::GlFont(const std::string& filename, float pixel_height, int tex_w, int tex_h) { unsigned char* ttf_buffer = new unsigned char[1<<20]; const size_t bytes_read = fread(ttf_buffer, 1, 1<<20, fopen(filename.c_str(), "rb")); if(bytes_read > 0) { InitialiseFont(ttf_buffer, pixel_height, tex_w, tex_h); }else{ throw std::runtime_error("Unable to read font from file."); } delete[] ttf_buffer; }
void SubtitleScreen::DisplayTextSubtitles(void) { if (!InitialiseFont(m_fontStretch) || !m_player || !m_subreader) return; bool changed = false; VideoOutput *vo = m_player->GetVideoOutput(); if (vo) { QRect oldsafe = m_safeArea; m_safeArea = m_player->GetVideoOutput()->GetSafeRect(); if (oldsafe != m_safeArea) { changed = true; int height = (m_safeArea.height() * m_textFontZoom) / 2000; gTextSubFont->GetFace()->setPixelSize(height); gTextSubFont->GetFace()->setItalic(false); gTextSubFont->GetFace()->setUnderline(false); gTextSubFont->SetColor(Qt::white); } } else { return; } VideoFrame *currentFrame = vo->GetLastShownFrame(); if (!currentFrame) return; TextSubtitles *subs = m_subreader->GetTextSubtitles(); subs->Lock(); uint64_t playPos = 0; if (subs->IsFrameBasedTiming()) { // frame based subtitles get out of synch after running mythcommflag // for the file, i.e., the following number is wrong and does not // match the subtitle frame numbers: playPos = currentFrame->frameNumber; } else { // Use timecodes for time based SRT subtitles. Feeding this into // NormalizeVideoTimecode() should adjust for non-zero start times // and wraps. For MPEG, wraps will occur just once every 26.5 hours // and other formats less frequently so this should be sufficient. // Note: timecodes should now always be valid even in the case // when a frame doesn't have a valid timestamp. If an exception is // found where this is not true then we need to use the frameNumber // when timecode is not defined by uncommenting the following lines. //if (currentFrame->timecode == 0) // playPos = (uint64_t) // ((currentFrame->frameNumber / video_frame_rate) * 1000); //else playPos = m_player->GetDecoder()->NormalizeVideoTimecode(currentFrame->timecode); } if (playPos != 0) changed |= subs->HasSubtitleChanged(playPos); if (!changed) { subs->Unlock(); return; } DeleteAllChildren(); SetRedraw(); if (playPos == 0) { subs->Unlock(); return; } QStringList rawsubs = subs->GetSubtitles(playPos); if (rawsubs.empty()) { subs->Unlock(); return; } OptimiseTextSubs(rawsubs); subs->Unlock(); DrawTextSubtitles(rawsubs, 0, 0); }
GlFont::GlFont(const unsigned char* ttf_buffer, float pixel_height, int tex_w, int tex_h) { InitialiseFont(ttf_buffer, pixel_height, tex_w, tex_h); }
void TeletextScreen::Pulse(void) { if (!InitialiseFont() || !m_displaying) return; if (m_player && m_player->GetVideoOutput()) { static const float kTextPadding = 0.96f; QRect oldsafe = m_safeArea; m_safeArea = m_player->GetVideoOutput()->GetSafeRect(); m_colWidth = (int)((float)m_safeArea.width() / (float)kTeletextColumns); m_rowHeight = (int)((float)m_safeArea.height() / (float)kTeletextRows); if (oldsafe != m_safeArea) { m_teletextReader->SetPageChanged(true); int max_width = (int)((float)m_colWidth * kTextPadding); m_fontHeight = (int)((float)m_rowHeight * kTextPadding); if (max_width > (m_colWidth - 2)) max_width = m_colWidth -2; if (m_fontHeight > (m_rowHeight - 2)) m_fontHeight = m_rowHeight - 2; gTTFont->GetFace()->setPixelSize(m_fontHeight); m_fontStretch = 200; bool ok = false; while (!ok && m_fontStretch > 50) { gTTFont->GetFace()->setStretch(m_fontStretch); QFontMetrics font(*(gTTFont->GetFace())); if (font.averageCharWidth() <= max_width || m_fontStretch < 50) ok = true; else m_fontStretch -= 10; } } } else { return; } if (!m_teletextReader->PageChanged()) return; ClearScreen(); const TeletextSubPage *ttpage = m_teletextReader->FindSubPage(); if (!ttpage) { // no page selected so show the header and a list of available pages DrawHeader(NULL, 0); m_teletextReader->SetPageChanged(false); OptimiseDisplayedArea(); return; } m_teletextReader->SetSubPage(ttpage->subpagenum); int a = 0; if ((ttpage->subtitle) || (ttpage->flags & (TP_SUPPRESS_HEADER | TP_NEWSFLASH | TP_SUBTITLE))) { a = 1; // when showing subtitles we don't want to see the teletext // header line, so we skip that line... m_teletextReader->SetShowHeader(false); m_teletextReader->SetIsSubtitle(true); } else { m_teletextReader->SetShowHeader(true); m_teletextReader->SetIsSubtitle(false); DrawHeader(m_teletextReader->GetHeader(), ttpage->lang); m_teletextReader->SetHeaderChanged(false); } for (int y = kTeletextRows - a; y >= 2; y--) DrawLine(ttpage->data[y-1], y, ttpage->lang); m_teletextReader->SetPageChanged(false); OptimiseDisplayedArea(); }
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(); }