SubtitleScreen* OSD::InitSubtitles(void) { SubtitleScreen *sub = NULL; if (m_Children.contains(OSD_WIN_SUBTITLE)) { sub = (SubtitleScreen*)m_Children.value(OSD_WIN_SUBTITLE); } else { OverrideUIScale(); sub = new SubtitleScreen(m_parent, OSD_WIN_SUBTITLE, m_fontStretch); sub->SetPainter(m_CurrentPainter); if (sub->Create()) { m_Children.insert(OSD_WIN_SUBTITLE, sub); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created window %1") .arg(OSD_WIN_SUBTITLE)); } else { delete sub; sub = NULL; } RevertUIScale(); } if (!sub) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create subtitle window"); return NULL; } return sub; }
bool OSD::Init(const QRect &rect, float font_aspect) { m_Rect = rect; m_fontStretch = (int)((font_aspect * 100) + 0.5f); OverrideUIScale(); LoadWindows(); RevertUIScale(); if (!m_Children.size()) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to load any windows."); return false; } LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Loaded OSD: size %1x%2 offset %3+%4") .arg(m_Rect.width()).arg(m_Rect.height()) .arg(m_Rect.left()).arg(m_Rect.top())); HideAll(false); return true; }
TeletextScreen* OSD::InitTeletext(void) { TeletextScreen *tt = NULL; if (m_Children.contains(OSD_WIN_TELETEXT)) { tt = (TeletextScreen*)m_Children.value(OSD_WIN_TELETEXT); } else { OverrideUIScale(); tt = new TeletextScreen(m_parent, OSD_WIN_TELETEXT, m_fontStretch); tt->SetPainter(m_CurrentPainter); if (tt->Create()) { m_Children.insert(OSD_WIN_TELETEXT, tt); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created window %1") .arg(OSD_WIN_TELETEXT)); } else { delete tt; tt = NULL; } RevertUIScale(); } if (!tt) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Teletext window"); return NULL; } HideWindow(OSD_WIN_TELETEXT); tt->SetDisplaying(false); return tt; }
QRegion OSD::Draw(MythPainter* painter, QPaintDevice *device, QSize size, QRegion &changed, int alignx, int aligny) { bool redraw = m_Refresh; QRegion visible = QRegion(); QRegion dirty = m_Refresh ? QRegion(QRect(QPoint(0,0), m_Rect.size())) : QRegion(); m_Refresh = false; if (!painter || !device) return visible; QTime now = MythDate::current().time(); CheckExpiry(); // first update for alpha pulse and fade QMap<QString,MythScreenType*>::const_iterator it; for (it = m_Children.begin(); it != m_Children.end(); ++it) { if ((*it)->IsVisible()) { QRect vis = (*it)->GetArea().toQRect(); if (visible.isEmpty()) visible = QRegion(vis); else visible = visible.united(vis); (*it)->Pulse(); if (m_Effects && m_ExpireTimes.contains((*it))) { QTime expires = m_ExpireTimes.value((*it)).time(); int left = now.msecsTo(expires); if (left < m_FadeTime) (*it)->SetAlpha((255 * left) / m_FadeTime); } } if ((*it)->NeedsRedraw()) { QRegion area = (*it)->GetDirtyArea(); dirty = dirty.united(area); redraw = true; } } MythNotificationCenter *nc = GetNotificationCenter(); QList<MythScreenType*> notifications; nc->GetNotificationScreens(notifications); QList<MythScreenType*>::iterator it2 = notifications.begin(); while (it2 != notifications.end()) { if (!GetNotificationCenter()->ScreenCreated(*it2)) { if (!m_UIScaleOverride) { OverrideUIScale(false); } (*it2)->SetPainter(m_CurrentPainter); if (!(*it2)->Create()) { it2 = notifications.erase(it2); continue; } } if ((*it2)->IsVisible()) { if (!m_UIScaleOverride) { OverrideUIScale(false); } nc->UpdateScreen(*it2); QRect vis = (*it2)->GetArea().toQRect(); if (visible.isEmpty()) visible = QRegion(vis); else visible = visible.united(vis); (*it2)->Pulse(); if (m_Effects) { QTime expires = nc->ScreenExpiryTime(*it2).time(); int left = now.msecsTo(expires); if (expires.isValid() && left < m_FadeTime) (*it2)->SetAlpha((255 * left) / m_FadeTime); } } if ((*it2)->NeedsRedraw()) { QRegion area = (*it2)->GetDirtyArea(); dirty = dirty.united(area); redraw = true; } ++it2; } RevertUIScale(); if (redraw) { // clear the dirty area painter->Clear(device, dirty); // set redraw for any widgets that may now need a partial repaint for (it = m_Children.begin(); it != m_Children.end(); ++it) { if ((*it)->IsVisible() && !(*it)->NeedsRedraw() && dirty.intersects((*it)->GetArea().toQRect())) { (*it)->SetRedraw(); } } for (it2 = notifications.begin(); it2 != notifications.end(); ++it2) { if ((*it2)->IsVisible() && !(*it2)->NeedsRedraw() && dirty.intersects((*it2)->GetArea().toQRect())) { (*it2)->SetRedraw(); } } // and finally draw QRect cliprect = dirty.boundingRect(); painter->Begin(device); painter->SetClipRegion(dirty); // TODO painting in reverse may be more efficient... for (it = m_Children.begin(); it != m_Children.end(); ++it) { if ((*it)->NeedsRedraw()) { if ((*it)->IsVisible()) (*it)->Draw(painter, 0, 0, 255, cliprect); (*it)->SetAlpha(255); (*it)->ResetNeedsRedraw(); } } for (it2 = notifications.begin(); it2 != notifications.end(); ++it2) { if ((*it2)->NeedsRedraw()) { if ((*it2)->IsVisible()) (*it2)->Draw(painter, 0, 0, 255, cliprect); (*it2)->SetAlpha(255); (*it2)->ResetNeedsRedraw(); } } painter->End(); } changed = dirty; if (visible.isEmpty() || (!alignx && !aligny)) return visible; // assist yuv blending with some friendly alignments QRegion aligned; QVector<QRect> rects = visible.rects(); for (int i = 0; i < rects.size(); i++) { QRect r = rects[i]; int left = r.left() & ~(alignx - 1); int top = r.top() & ~(aligny - 1); int right = (r.left() + r.width()); int bot = (r.top() + r.height()); if (right & (alignx - 1)) right += alignx - (right & (alignx - 1)); if (bot % aligny) bot += aligny - (bot % aligny); aligned = aligned.united(QRegion(left, top, right - left, bot - top)); } return aligned.intersected(QRect(QPoint(0,0), size)); }
bool OSD::DrawDirect(MythPainter* painter, QSize size, bool repaint) { if (!painter) return false; bool visible = false; bool redraw = m_Refresh; m_Refresh = false; QTime now = MythDate::current().time(); CheckExpiry(); QMap<QString,MythScreenType*>::const_iterator it; for (it = m_Children.begin(); it != m_Children.end(); ++it) { if ((*it)->IsVisible()) { visible = true; (*it)->Pulse(); if (m_Effects && m_ExpireTimes.contains((*it))) { QTime expires = m_ExpireTimes.value((*it)).time(); int left = now.msecsTo(expires); if (left < m_FadeTime) (*it)->SetAlpha((255 * left) / m_FadeTime); } if ((*it)->NeedsRedraw()) redraw = true; } } MythNotificationCenter *nc = GetNotificationCenter(); QList<MythScreenType*> notifications; nc->GetNotificationScreens(notifications); QList<MythScreenType*>::iterator it2 = notifications.begin(); while (it2 != notifications.end()) { if (!nc->ScreenCreated(*it2)) { LOG(VB_GUI, LOG_DEBUG, LOC + "Creating OSD Notification"); if (!m_UIScaleOverride) { OverrideUIScale(false); } (*it2)->SetPainter(m_CurrentPainter); if (!(*it2)->Create()) { it2 = notifications.erase(it2); continue; } } if ((*it2)->IsVisible()) { if (!m_UIScaleOverride) { OverrideUIScale(false); } nc->UpdateScreen(*it2); visible = true; (*it2)->Pulse(); if (m_Effects) { QTime expires = nc->ScreenExpiryTime(*it2).time(); int left = now.msecsTo(expires); if (expires.isValid() && left < m_FadeTime) (*it2)->SetAlpha((255 * left) / m_FadeTime); } if ((*it2)->NeedsRedraw()) redraw = true; } ++it2; } RevertUIScale(); redraw |= repaint; if (redraw && visible) { QRect cliprect = QRect(QPoint(0, 0), size); painter->Begin(NULL); for (it = m_Children.begin(); it != m_Children.end(); ++it) { if ((*it)->IsVisible()) { (*it)->Draw(painter, 0, 0, 255, cliprect); (*it)->SetAlpha(255); (*it)->ResetNeedsRedraw(); } } for (it2 = notifications.begin(); it2 != notifications.end(); ++it2) { if ((*it2)->IsVisible()) { (*it2)->Draw(painter, 0, 0, 255, cliprect); (*it2)->SetAlpha(255); (*it2)->ResetNeedsRedraw(); } } painter->End(); } return visible; }
void OSD::DialogShow(const QString &window, const QString &text, int updatefor) { if (m_Dialog) { QString current = m_Dialog->objectName(); if (current != window) { DialogQuit(); } else { MythDialogBox *dialog = dynamic_cast<MythDialogBox*>(m_Dialog); if (dialog) dialog->Reset(); DialogSetText(text); } } if (!m_Dialog) { OverrideUIScale(); MythScreenType *dialog; if (window == OSD_DLG_EDITOR) dialog = new ChannelEditor(m_ParentObject, window.toLatin1()); else if (window == OSD_DLG_CONFIRM) dialog = new MythConfirmationDialog(NULL, text, false); else dialog = new MythDialogBox(text, NULL, window.toLatin1(), false, true); dialog->SetPainter(m_CurrentPainter); if (dialog->Create()) { PositionWindow(dialog); m_Dialog = dialog; MythDialogBox *dbox = dynamic_cast<MythDialogBox*>(m_Dialog); if (dbox) dbox->SetReturnEvent(m_ParentObject, window); MythConfirmationDialog *cbox = dynamic_cast<MythConfirmationDialog*>(m_Dialog); if (cbox) { cbox->SetReturnEvent(m_ParentObject, window); cbox->SetData("DIALOG_CONFIRM_X_X"); } m_Children.insert(window, m_Dialog); } else { RevertUIScale(); delete dialog; return; } RevertUIScale(); } if (updatefor) { m_NextPulseUpdate = MythDate::current(); m_PulsedDialogText = text; SetExpiry(window, kOSDTimeout_None, updatefor); } DialogBack(); HideAll(true, m_Dialog); m_Dialog->SetVisible(true); }