8 #include <QPainterPath>
36 LOG(VB_GENERAL, LOG_WARNING,
37 QString(
"MythPainter: %1 images not yet de-allocated.")
42 image->SetParent(
nullptr);
62 LOG(VB_GENERAL, LOG_ERR,
63 "Null image pointer passed to MythPainter::DrawImage()");
66 QRect
dest = QRect(x, y, im->width(), im->height());
67 QRect src = im->rect();
73 DrawImage(topLeft.x(), topLeft.y(), im, alpha);
78 int alpha,
const QRect boundRect)
84 QRect destRect(boundRect);
85 QRect srcRect(0,0,r.width(),r.height());
86 if (!boundRect.isEmpty() && boundRect != r)
90 int width = boundRect.width();
91 int height = boundRect.height();
93 if (boundRect.x() > r.x())
95 x = boundRect.x()-r.x();
97 else if (r.x() > boundRect.x())
100 width = (boundRect.x() + boundRect.width()) - r.x();
103 if (boundRect.y() > r.y())
105 y = boundRect.y()-r.y();
107 else if (r.y() > boundRect.y())
109 destRect.setY(r.y());
110 height = (boundRect.y() + boundRect.height()) - r.y();
113 if (width <= 0 || height <= 0)
116 srcRect.setRect(x,y,width,height);
127 const QRect destRect)
129 if (canvasRect.isNull())
132 QRect canvas(canvasRect);
133 QRect
dest(destRect);
139 LOG(VB_GENERAL, LOG_ERR, QString(
"MythPainter::DrawTextLayout: "
140 "Unable to create image."));
145 LOG(VB_GENERAL, LOG_DEBUG, QString(
"MythPainter::DrawTextLayout: "
146 "Rendered image is null."));
151 QRect srcRect(0, 0,
dest.width(),
dest.height());
158 const QPen &linePen,
int alpha)
163 DrawImage(area.x(), area.y(), im, alpha);
169 const QBrush &fillBrush,
const QPen &linePen,
175 DrawImage(area.x(), area.y(), im, alpha);
181 const QPen &linePen,
int alpha)
186 DrawImage(area.x(), area.y(), im, alpha);
199 int outlineAlpha = 255;
201 font.
GetOutline(outlineColor, outlineSize, outlineAlpha);
203 QPoint shadowOffset(0, 0);
205 int shadowAlpha = 255;
207 font.
GetShadow(shadowOffset, shadowColor, shadowAlpha);
209 QFontMetrics fm(font.
face());
210 int totalHeight = fm.height() + outlineSize +
211 std::max(outlineSize, std::abs(shadowOffset.y()));
216 int initialPaddingX = 0;
221 int initialPaddingY = (r.height() - totalHeight) / 2;
230 if (flags & Qt::TextWordWrap)
237 initialPaddingX + std::max(outlineSize, -shadowOffset.x());
243 initialPaddingY + std::max(outlineSize, -shadowOffset.y());
245 QImage pm(r.size(), QImage::Format_ARGB32);
246 QColor fillcolor = font.
color();
248 fillcolor = outlineColor;
249 fillcolor.setAlpha(0);
250 pm.fill(fillcolor.rgba());
253 QFont tmpfont = font.
face();
254 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
255 tmpfont.setStyleStrategy(QFont::OpenGLCompatible);
257 tmp.setFont(tmpfont);
261 path.addText(0, 0, tmpfont, msg);
265 QRect a = QRect(0, 0, r.width(), r.height());
266 a.translate(shadowOffset.x() + textOffsetX,
267 shadowOffset.y() + textOffsetY);
269 shadowColor.setAlpha(shadowAlpha);
270 tmp.setPen(shadowColor);
271 tmp.drawText(a, flags, msg);
282 int adjY = fm.ascent();
284 outlineColor.setAlpha(outlineAlpha);
285 tmp.setPen(outlineColor);
287 path.translate(adjX + textOffsetX, adjY + textOffsetY);
288 QPen pen =
tmp.pen();
289 pen.setWidth(outlineSize * 2 + 1);
290 pen.setCapStyle(Qt::RoundCap);
291 pen.setJoinStyle(Qt::RoundJoin);
295 path.translate(outlineSize, outlineSize);
300 tmp.drawText(textOffsetX, textOffsetY, r.width(), r.height(),
308 const QBrush &fillBrush,
const QPen &linePen)
313 QImage image(QSize(area.width(), area.height()), QImage::Format_ARGB32);
314 image.fill(0x00000000);
315 QPainter painter(&image);
316 painter.setRenderHint(QPainter::Antialiasing);
317 painter.setPen(linePen);
318 painter.setBrush(fillBrush);
320 if ((area.width() / 2) < radius)
321 radius = area.width() / 2;
323 if ((area.height() / 2) < radius)
324 radius = area.height() / 2;
326 int lineWidth = linePen.width();
327 QRect r(lineWidth, lineWidth,
328 area.width() - (lineWidth * 2), area.height() - (lineWidth * 2));
331 painter.drawEllipse(r);
332 else if (radius == 0)
335 painter.drawRoundedRect(r, (qreal)radius, qreal(radius));
342 int flags,
const QRect r,
345 QString incoming = font.
GetHash() + QString::number(r.width()) +
346 QString::number(r.height()) +
347 QString::number(flags) +
348 QString::number(font.
color().rgba()) + msg;
362 im->
SetFileName(QString(
"GetImageFromString: %1").arg(msg));
377 QRect &canvas, QRect &
dest)
379 QString incoming = QString::number(canvas.x()) +
380 QString::number(canvas.y()) +
381 QString::number(canvas.width()) +
382 QString::number(canvas.height()) +
383 QString::number(
dest.width()) +
384 QString::number(
dest.height()) +
387 for (
auto *layout : qAsConst(layouts))
388 incoming += layout->text();
404 QImage pm(canvas.size(), QImage::Format_ARGB32_Premultiplied);
407 QPainter painter(&pm);
408 if (!painter.isActive())
410 LOG(VB_GENERAL, LOG_ERR,
"MythPainter::GetImageFromTextLayout: "
416 clip.setSize(canvas.size());
418 QFont tmpfont = font.
face();
419 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
420 tmpfont.setStyleStrategy(QFont::OpenGLCompatible);
422 painter.setFont(tmpfont);
423 painter.setRenderHint(QPainter::Antialiasing);
430 int shadowAlpha = 255;
432 font.
GetShadow(shadowOffset, shadowColor, shadowAlpha);
433 shadowColor.setAlpha(shadowAlpha);
439 shadowRect.translate(shadow.x(), shadow.y());
441 painter.setPen(shadowColor);
442 for (
auto *layout : qAsConst(layouts))
443 layout->draw(&painter, shadowRect.topLeft(),
formats, clip);
446 painter.setPen(QPen(font.
GetBrush(), 0));
447 for (
auto *layout : qAsConst(layouts))
449 layout->draw(&painter, canvas.topLeft(),
450 layout->formats(), clip);
454 pm.setOffset(canvas.topLeft());
468 const QBrush &fillBrush,
471 if (area.width() <= 0 || area.height() <= 0)
474 uint64_t hash1 = ((0xfff & (uint64_t)area.width())) +
475 ((0xfff & (uint64_t)area.height()) << 12) +
476 ((0xff & (uint64_t)fillBrush.style()) << 24) +
477 ((0xff & (uint64_t)linePen.width()) << 32) +
478 ((0xff & (uint64_t)radius) << 40) +
479 ((0xff & (uint64_t)linePen.style()) << 48) +
480 ((0xff & (uint64_t)ellipse) << 56);
481 uint64_t hash2 = ((0xffffffff & (uint64_t)linePen.color().rgba())) +
482 ((0xffffffff & (uint64_t)fillBrush.color().rgba()) << 32);
484 QString incoming(
"R");
485 if (fillBrush.style() == Qt::LinearGradientPattern && fillBrush.gradient())
490 const auto *gradient =
static_cast<const QLinearGradient*
>(fillBrush.gradient());
493 incoming = QString::number(
494 ((0xfff & (uint64_t)gradient->start().x())) +
495 ((0xfff & (uint64_t)gradient->start().y()) << 12) +
496 ((0xfff & (uint64_t)gradient->finalStop().x()) << 24) +
497 ((0xfff & (uint64_t)gradient->finalStop().y()) << 36));
498 QGradientStops stops = gradient->stops();
499 for (
const auto & stop : qAsConst(stops))
501 incoming += QString::number(
502 ((0xfff * (uint64_t)(stop.first * 100))) +
503 ((uint64_t)stop.second.rgba() << 12));
508 incoming += QString::number(hash1) + QString::number(hash2);
523 DrawRectPriv(im, area, radius, ellipse, fillBrush, linePen);
562 bool recompute =
false;
571 QMap<QString, MythImage*>::iterator it =
603 static constexpr int64_t kOneMeg = 1LL * 1024 * 1024;
619 LOG((err) ? VB_GENERAL : VB_GUI, (err) ? LOG_ERR : LOG_INFO,
620 QString(
"MythPainter cache sizes: Hardware %1MB, Software %2MB")