MythImage *MythPainter::GetImageFromString(const QString &msg, int flags, const QRect &r, const MythFontProperties &font) { QString incoming = font.GetHash() + QString::number(r.width()) + QString::number(r.height()) + QString::number(flags) + QString::number(font.color().rgba()) + msg; MythImage *im = NULL; if (m_StringToImageMap.contains(incoming)) { m_StringExpireList.remove(incoming); m_StringExpireList.push_back(incoming); im = m_StringToImageMap[incoming]; if (im) im->IncrRef(); } else { im = GetFormatImage(); im->SetFileName(QString("GetImageFromString: %1").arg(msg)); DrawTextPriv(im, msg, flags, r, font); im->IncrRef(); m_SoftwareCacheSize += im->bytesPerLine() * im->height(); m_StringToImageMap[incoming] = im; m_StringExpireList.push_back(incoming); ExpireImages(m_MaxSoftwareCacheSize); } return im; }
MythImage* MythPainter::GetImageFromRect(const QRect &area, int radius, int ellipse, const QBrush &fillBrush, const QPen &linePen) { if (area.width() <= 0 || area.height() <= 0) return NULL; uint64_t hash1 = ((0xfff & (uint64_t)area.width())) + ((0xfff & (uint64_t)area.height()) << 12) + ((0xff & (uint64_t)fillBrush.style()) << 24) + ((0xff & (uint64_t)linePen.width()) << 32) + ((0xff & (uint64_t)radius) << 40) + ((0xff & (uint64_t)linePen.style()) << 48) + ((0xff & (uint64_t)ellipse) << 56); uint64_t hash2 = ((0xffffffff & (uint64_t)linePen.color().rgba())) + ((0xffffffff & (uint64_t)fillBrush.color().rgba()) << 32); QString incoming("R"); if (fillBrush.style() == Qt::LinearGradientPattern && fillBrush.gradient()) { const QLinearGradient *gradient = static_cast<const QLinearGradient*>(fillBrush.gradient()); if (gradient) { incoming = QString::number( ((0xfff & (uint64_t)gradient->start().x())) + ((0xfff & (uint64_t)gradient->start().y()) << 12) + ((0xfff & (uint64_t)gradient->finalStop().x()) << 24) + ((0xfff & (uint64_t)gradient->finalStop().y()) << 36)); QGradientStops stops = gradient->stops(); for (int i = 0; i < stops.size(); i++) { incoming += QString::number( ((0xfff * (uint64_t)(stops[i].first * 100))) + ((uint64_t)stops[i].second.rgba() << 12)); } } } incoming += QString::number(hash1) + QString::number(hash2); if (m_StringToImageMap.contains(incoming)) { m_StringExpireList.remove(incoming); m_StringExpireList.push_back(incoming); return m_StringToImageMap[incoming]; } MythImage *im = GetFormatImage(); if (im) { DrawRectPriv(im, area, radius, ellipse, fillBrush, linePen); m_SoftwareCacheSize += (im->bytesPerLine() * im->height()); m_StringToImageMap[incoming] = im; m_StringExpireList.push_back(incoming); ExpireImages(m_MaxSoftwareCacheSize); } return im; }
/** * \brief Assign a set of MythImages to the widget for animation. * Use is strongly discouraged, use SetFilepattern() instead. * */ void MythUIImage::SetImages(QVector<MythImage *> &images) { Clear(); QWriteLocker updateLocker(&d->m_UpdateLock); QSize aSize = GetArea().size(); QVector<MythImage *>::iterator it; for (it = images.begin(); it != images.end(); ++it) { MythImage *im = (*it); if (!im) { QMutexLocker locker(&m_ImagesLock); m_Images[m_Images.size()] = im; continue; } im->UpRef(); if (!m_ForceSize.isNull()) { int w = (m_ForceSize.width() <= 0) ? im->width() : m_ForceSize.width(); int h = (m_ForceSize.height() <= 0) ? im->height() : m_ForceSize.height(); im->Resize(QSize(w, h), m_preserveAspect); } if (m_isReflected && !im->IsReflected()) im->Reflect(m_reflectAxis, m_reflectShear, m_reflectScale, m_reflectLength, m_reflectSpacing); if (m_isGreyscale && !im->isGrayscale()) im->ToGreyscale(); m_ImagesLock.lock(); m_Images[m_Images.size()] = im; m_ImagesLock.unlock(); aSize = aSize.expandedTo(im->size()); } SetImageCount(1, m_Images.size()); if (m_ForceSize.isNull()) SetSize(aSize); m_CurPos = 0; SetRedraw(); }
void MythPainter::ExpireImages(int64_t max) { bool recompute = false; while (!m_StringExpireList.empty()) { if (m_SoftwareCacheSize < max) break; QString oldmsg = m_StringExpireList.front(); m_StringExpireList.pop_front(); QMap<QString, MythImage*>::iterator it = m_StringToImageMap.find(oldmsg); if (it == m_StringToImageMap.end()) { recompute = true; continue; } MythImage *oldim = *it; it = m_StringToImageMap.erase(it); if (oldim) { m_SoftwareCacheSize -= oldim->bytesPerLine() * oldim->height(); if (m_SoftwareCacheSize < 0) { m_SoftwareCacheSize = 0; recompute = true; } oldim->DecrRef(); } } if (recompute) { m_SoftwareCacheSize = 0; QMap<QString, MythImage*>::iterator it = m_StringToImageMap.begin(); for (; it != m_StringToImageMap.end(); ++it) m_SoftwareCacheSize += (*it)->bytesPerLine() * (*it)->height(); } }
void MythPainter::ExpireImages(int max) { if (m_StringExpireList.size() < 1) return; while (m_SoftwareCacheSize > max) { QString oldmsg = m_StringExpireList.front(); m_StringExpireList.pop_front(); MythImage *oldim = NULL; if (m_StringToImageMap.contains(oldmsg)) oldim = m_StringToImageMap[oldmsg]; m_StringToImageMap.remove(oldmsg); if (oldim) { m_SoftwareCacheSize -= oldim->bytesPerLine() * oldim->height(); oldim->DownRef(); } } }
MythImage *MythPainter::GetImageFromTextLayout(const LayoutVector &layouts, const FormatVector &formats, const MythFontProperties &font, QRect &canvas, QRect &dest) { LayoutVector::const_iterator Ipara; QString incoming = QString::number(canvas.x()) + QString::number(canvas.y()) + QString::number(canvas.width()) + QString::number(canvas.height()) + QString::number(dest.width()) + QString::number(dest.height()) + font.GetHash(); for (Ipara = layouts.begin(); Ipara != layouts.end(); ++Ipara) incoming += (*Ipara)->text(); MythImage *im = NULL; if (m_StringToImageMap.contains(incoming)) { m_StringExpireList.remove(incoming); m_StringExpireList.push_back(incoming); im = m_StringToImageMap[incoming]; if (im) im->IncrRef(); } else { im = GetFormatImage(); im->SetFileName("GetImageFromTextLayout"); QImage pm(canvas.size(), QImage::Format_ARGB32_Premultiplied); pm.fill(0); QPainter painter(&pm); if (!painter.isActive()) { LOG(VB_GENERAL, LOG_ERR, "MythPainter::GetImageFromTextLayout: " "Invalid canvas."); return im; } QRect clip; clip.setSize(canvas.size()); QFont tmpfont = font.face(); tmpfont.setStyleStrategy(QFont::OpenGLCompatible); painter.setFont(tmpfont); painter.setRenderHint(QPainter::Antialiasing); if (font.hasShadow()) { QRect shadowRect; QPoint shadowOffset; QColor shadowColor; int shadowAlpha; font.GetShadow(shadowOffset, shadowColor, shadowAlpha); shadowColor.setAlpha(shadowAlpha); MythPoint shadow(shadowOffset); shadow.NormPoint(); // scale it to screen resolution shadowRect = canvas; shadowRect.translate(shadow.x(), shadow.y()); painter.setPen(shadowColor); for (Ipara = layouts.begin(); Ipara != layouts.end(); ++Ipara) (*Ipara)->draw(&painter, shadowRect.topLeft(), formats, clip); } painter.setPen(QPen(font.GetBrush(), 0)); for (Ipara = layouts.begin(); Ipara != layouts.end(); ++Ipara) (*Ipara)->draw(&painter, canvas.topLeft(), formats, clip); painter.end(); pm.setOffset(canvas.topLeft()); im->Assign(pm.copy(0, 0, dest.width(), dest.height())); im->IncrRef(); m_SoftwareCacheSize += im->bytesPerLine() * im->height(); m_StringToImageMap[incoming] = im; m_StringExpireList.push_back(incoming); ExpireImages(m_MaxSoftwareCacheSize); } return im; }
/** * \brief Assign a set of MythImages to the widget for animation. * Use is strongly discouraged, use SetFilepattern() instead. * */ void MythUIImage::SetImages(QVector<MythImage *> *images) { Clear(); QWriteLocker updateLocker(&d->m_UpdateLock); QSize aSize = GetFullArea().size(); m_imageProperties.isThemeImage = false; QVector<MythImage *>::iterator it; for (it = images->begin(); it != images->end(); ++it) { MythImage *im = (*it); if (!im) { QMutexLocker locker(&m_ImagesLock); m_Images[m_Images.size()] = im; continue; } im->IncrRef(); QSize forceSize = m_imageProperties.forceSize; if (!forceSize.isNull()) { int w = (forceSize.width() <= 0) ? im->width() : forceSize.width(); int h = (forceSize.height() <= 0) ? im->height() : forceSize.height(); im->Resize(QSize(w, h), m_imageProperties.preserveAspect); } if (m_imageProperties.isReflected && !im->IsReflected()) im->Reflect(m_imageProperties.reflectAxis, m_imageProperties.reflectShear, m_imageProperties.reflectScale, m_imageProperties.reflectLength, m_imageProperties.reflectSpacing); if (m_imageProperties.isGreyscale && !im->isGrayscale()) im->ToGreyscale(); if (m_imageProperties.isOriented && !im->IsOriented() && (m_imageProperties.orientation >= 1 && m_imageProperties.orientation <= 8)) im->Orientation(m_imageProperties.orientation); m_ImagesLock.lock(); m_Images[m_Images.size()] = im; m_ImagesLock.unlock(); aSize = aSize.expandedTo(im->size()); } SetImageCount(1, m_Images.size()); if (m_imageProperties.forceSize.isNull()) SetSize(aSize); MythRect rect(GetFullArea()); rect.setSize(aSize); SetMinArea(rect); m_CurPos = 0; m_animatedImage = true; m_Initiator = m_EnableInitiator; SetRedraw(); }