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);
205 int outlineAlpha = 255;
207 font.
GetOutline(outlineColor, outlineSize, outlineAlpha);
209 QPoint shadowOffset(0, 0);
211 int shadowAlpha = 255;
213 font.
GetShadow(shadowOffset, shadowColor, shadowAlpha);
215 QFontMetrics fm(font.
face());
216 int totalHeight = fm.height() + outlineSize +
217 std::max(outlineSize, std::abs(shadowOffset.y()));
222 int initialPaddingX = 0;
227 int initialPaddingY = (r.height() - totalHeight) / 2;
236 if (flags & Qt::TextWordWrap)
243 initialPaddingX + std::max(outlineSize, -shadowOffset.x());
249 initialPaddingY + std::max(outlineSize, -shadowOffset.y());
251 QImage pm(r.size(), QImage::Format_ARGB32);
252 QColor fillcolor = font.
color();
254 fillcolor = outlineColor;
255 fillcolor.setAlpha(0);
256 pm.fill(fillcolor.rgba());
259 QFont tmpfont = font.
face();
260 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
261 tmpfont.setStyleStrategy(QFont::OpenGLCompatible);
263 tmp.setFont(tmpfont);
267 path.addText(0, 0, tmpfont, msg);
271 QRect a = QRect(0, 0, r.width(), r.height());
272 a.translate(shadowOffset.x() + textOffsetX,
273 shadowOffset.y() + textOffsetY);
275 shadowColor.setAlpha(shadowAlpha);
276 tmp.setPen(shadowColor);
277 tmp.drawText(a, flags, msg);
288 int adjY = fm.ascent();
290 outlineColor.setAlpha(outlineAlpha);
291 tmp.setPen(outlineColor);
293 path.translate(adjX + textOffsetX, adjY + textOffsetY);
294 QPen pen =
tmp.pen();
295 pen.setWidth(outlineSize * 2 + 1);
296 pen.setCapStyle(Qt::RoundCap);
297 pen.setJoinStyle(Qt::RoundJoin);
301 path.translate(outlineSize, outlineSize);
306 tmp.drawText(textOffsetX, textOffsetY, r.width(), r.height(),
314 const QBrush &fillBrush,
const QPen &linePen)
319 QImage image(QSize(area.width(), area.height()), QImage::Format_ARGB32);
320 image.fill(0x00000000);
321 QPainter painter(&image);
322 painter.setRenderHint(QPainter::Antialiasing);
323 painter.setPen(linePen);
324 painter.setBrush(fillBrush);
326 if ((area.width() / 2) < radius)
327 radius = area.width() / 2;
329 if ((area.height() / 2) < radius)
330 radius = area.height() / 2;
332 int lineWidth = linePen.width();
333 QRect r(lineWidth, lineWidth,
334 area.width() - (lineWidth * 2), area.height() - (lineWidth * 2));
337 painter.drawEllipse(r);
338 else if (radius == 0)
341 painter.drawRoundedRect(r, (qreal)radius, qreal(radius));
348 int flags,
const QRect r,
351 QString incoming = font.
GetHash() + QString::number(r.width()) +
352 QString::number(r.height()) +
353 QString::number(flags) +
354 QString::number(font.
color().rgba()) + msg;
368 im->
SetFileName(QString(
"GetImageFromString: %1").arg(msg));
383 QRect &canvas, QRect &
dest)
385 QString incoming = QString::number(canvas.x()) +
386 QString::number(canvas.y()) +
387 QString::number(canvas.width()) +
388 QString::number(canvas.height()) +
389 QString::number(
dest.width()) +
390 QString::number(
dest.height()) +
393 for (
auto *layout : qAsConst(layouts))
394 incoming += layout->text();
410 QImage pm(canvas.size(), QImage::Format_ARGB32_Premultiplied);
413 QPainter painter(&pm);
414 if (!painter.isActive())
416 LOG(VB_GENERAL, LOG_ERR,
"MythPainter::GetImageFromTextLayout: "
422 clip.setSize(canvas.size());
424 QFont tmpfont = font.
face();
425 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
426 tmpfont.setStyleStrategy(QFont::OpenGLCompatible);
428 painter.setFont(tmpfont);
429 painter.setRenderHint(QPainter::Antialiasing);
436 int shadowAlpha = 255;
438 font.
GetShadow(shadowOffset, shadowColor, shadowAlpha);
439 shadowColor.setAlpha(shadowAlpha);
445 shadowRect.translate(shadow.x(), shadow.y());
447 painter.setPen(shadowColor);
448 for (
auto *layout : qAsConst(layouts))
449 layout->draw(&painter, shadowRect.topLeft(),
formats, clip);
452 painter.setPen(QPen(font.
GetBrush(), 0));
453 for (
auto *layout : qAsConst(layouts))
455 layout->draw(&painter, canvas.topLeft(),
456 layout->formats(), clip);
460 pm.setOffset(canvas.topLeft());
474 const QBrush &fillBrush,
477 if (area.width() <= 0 || area.height() <= 0)
480 uint64_t hash1 = ((0xfff & (uint64_t)area.width())) +
481 ((0xfff & (uint64_t)area.height()) << 12) +
482 ((0xff & (uint64_t)fillBrush.style()) << 24) +
483 ((0xff & (uint64_t)linePen.width()) << 32) +
484 ((0xff & (uint64_t)radius) << 40) +
485 ((0xff & (uint64_t)linePen.style()) << 48) +
486 ((0xff & (uint64_t)ellipse) << 56);
487 uint64_t hash2 = ((0xffffffff & (uint64_t)linePen.color().rgba())) +
488 ((0xffffffff & (uint64_t)fillBrush.color().rgba()) << 32);
490 QString incoming(
"R");
491 if (fillBrush.style() == Qt::LinearGradientPattern && fillBrush.gradient())
496 const auto *gradient =
static_cast<const QLinearGradient*
>(fillBrush.gradient());
499 incoming = QString::number(
500 ((0xfff & (uint64_t)gradient->start().x())) +
501 ((0xfff & (uint64_t)gradient->start().y()) << 12) +
502 ((0xfff & (uint64_t)gradient->finalStop().x()) << 24) +
503 ((0xfff & (uint64_t)gradient->finalStop().y()) << 36));
504 QGradientStops stops = gradient->stops();
505 for (
const auto & stop : qAsConst(stops))
507 incoming += QString::number(
508 ((0xfff * (uint64_t)(stop.first * 100))) +
509 ((uint64_t)stop.second.rgba() << 12));
514 incoming += QString::number(hash1) + QString::number(hash2);
529 DrawRectPriv(im, area, radius, ellipse, fillBrush, linePen);
568 bool recompute =
false;
577 QMap<QString, MythImage*>::iterator it =
609 static constexpr int64_t kOneMeg = 1LL * 1024 * 1024;
625 LOG((err) ? VB_GENERAL : VB_GUI, (err) ? LOG_ERR : LOG_INFO,
626 QString(
"MythPainter cache sizes: Hardware %1MB, Software %2MB")