Support three-color quote outlines.

This commit is contained in:
John Preston 2023-10-26 23:40:26 +04:00
parent 383b5b8f7e
commit 611224c52f
3 changed files with 37 additions and 24 deletions

View file

@ -27,6 +27,7 @@ QuoteStyle {
icon: icon; icon: icon;
iconPosition: point; iconPosition: point;
outline: pixels; outline: pixels;
outlineShift: pixels;
radius: pixels; radius: pixels;
scrollable: bool; scrollable: bool;
} }

View file

@ -191,15 +191,13 @@ void ValidateQuotePaintCache(
const auto icon = st.icon.empty() ? nullptr : &st.icon; const auto icon = st.icon.empty() ? nullptr : &st.icon;
if (!cache.corners.isNull() if (!cache.corners.isNull()
&& cache.bgCached == cache.bg && cache.bgCached == cache.bg
&& cache.outline1Cached == cache.outline1 && cache.outlines == cache.outlines
&& cache.outline2Cached == cache.outline2
&& (!st.header || cache.headerCached == cache.header) && (!st.header || cache.headerCached == cache.header)
&& (!icon || cache.iconCached == cache.icon)) { && (!icon || cache.iconCached == cache.icon)) {
return; return;
} }
cache.bgCached = cache.bg; cache.bgCached = cache.bg;
cache.outline1Cached = cache.outline1; cache.outlinesCached = cache.outlines;
cache.outline2Cached = cache.outline2;
if (st.header) { if (st.header) {
cache.headerCached = cache.header; cache.headerCached = cache.header;
} }
@ -220,25 +218,35 @@ void ValidateQuotePaintCache(
const auto full = QSize(side, side); const auto full = QSize(side, side);
const auto ratio = style::DevicePixelRatio(); const auto ratio = style::DevicePixelRatio();
if (cache.outline1 == cache.outline2) { if (!cache.outlines[1].alpha()) {
cache.outline = QImage(); cache.outline = QImage();
} else if (const auto outline = st.outline) { } else if (const auto outline = st.outline) {
const auto size = QSize(outline, outline * 6); const auto third = (cache.outlines[2].alpha() != 0);
const auto size = QSize(outline, outline * (third ? 6 : 4));
cache.outline = QImage( cache.outline = QImage(
size * ratio, size * ratio,
QImage::Format_ARGB32_Premultiplied); QImage::Format_ARGB32_Premultiplied);
cache.outline.fill(cache.outline1); cache.outline.fill(cache.outlines[0]);
cache.outline.setDevicePixelRatio(ratio); cache.outline.setDevicePixelRatio(ratio);
auto p = QPainter(&cache.outline); auto p = QPainter(&cache.outline);
p.setCompositionMode(QPainter::CompositionMode_Source); p.setCompositionMode(QPainter::CompositionMode_Source);
auto hq = PainterHighQualityEnabler(p); auto hq = PainterHighQualityEnabler(p);
auto path = QPainterPath(); auto path = QPainterPath();
path.moveTo(outline, outline); path.moveTo(outline, outline);
path.lineTo(outline, outline * 4); path.lineTo(outline, outline * (third ? 4 : 3));
path.lineTo(0, outline * 5); path.lineTo(0, outline * (third ? 5 : 4));
path.lineTo(0, outline * 2); path.lineTo(0, outline * 2);
path.lineTo(outline, outline); path.lineTo(outline, outline);
p.fillPath(path, cache.outline2); p.fillPath(path, cache.outlines[third ? 2 : 1]);
if (third) {
auto path = QPainterPath();
path.moveTo(outline, outline * 3);
path.lineTo(outline, outline * 5);
path.lineTo(0, outline * 6);
path.lineTo(0, outline * 4);
path.lineTo(outline, outline * 3);
p.fillPath(path, cache.outlines[1]);
}
} }
auto image = QImage(full * ratio, QImage::Format_ARGB32_Premultiplied); auto image = QImage(full * ratio, QImage::Format_ARGB32_Premultiplied);
@ -256,11 +264,14 @@ void ValidateQuotePaintCache(
if (outline) { if (outline) {
const auto rect = QRect(0, 0, outline + radius * 2, side); const auto rect = QRect(0, 0, outline + radius * 2, side);
if (!cache.outline.isNull()) { if (!cache.outline.isNull()) {
const auto shift = QPoint(0, st.outlineShift);
p.translate(shift);
p.setBrush(cache.outline); p.setBrush(cache.outline);
p.setClipRect(0, 0, outline, side); p.setClipRect(QRect(-shift, QSize(outline, side)));
p.drawRoundedRect(rect, radius, radius); p.drawRoundedRect(rect.translated(-shift), radius, radius);
p.translate(-shift);
} else { } else {
p.setBrush(cache.outline1); p.setBrush(cache.outlines[0]);
p.setClipRect(0, 0, outline, side); p.setClipRect(0, 0, outline, side);
p.drawRoundedRect(rect, radius, radius); p.drawRoundedRect(rect, radius, radius);
} }
@ -380,9 +391,9 @@ void FillQuotePaint(
radius); radius);
} }
auto q = QPainter(&cache.bottomCorner); auto q = QPainter(&cache.bottomCorner);
const auto skipped = ihalf const auto skipped = (height - bottom)
+ int(parts.skippedTop) + (parts.skippedTop ? int(parts.skippedTop) : ihalf)
+ (height - bottom); - st.outlineShift;
q.translate(0, -skipped); q.translate(0, -skipped);
q.fillRect(0, skipped, skip, bottom, cache.outline); q.fillRect(0, skipped, skip, bottom, cache.outline);
q.setCompositionMode(QPainter::CompositionMode_DestinationIn); q.setCompositionMode(QPainter::CompositionMode_DestinationIn);
@ -402,13 +413,14 @@ void FillQuotePaint(
} }
if (outline) { if (outline) {
if (!cache.outline.isNull()) { if (!cache.outline.isNull()) {
const auto skipped = ihalf + int(parts.skippedTop); const auto skipped = st.outlineShift
const auto top = y - skipped; - (parts.skippedTop ? int(parts.skippedTop) : ihalf);
const auto top = y + skipped;
p.translate(x, top); p.translate(x, top);
p.fillRect(0, skipped, outline, height, cache.outline); p.fillRect(0, -skipped, outline, height, cache.outline);
p.translate(-x, -top); p.translate(-x, -top);
} else { } else {
p.fillRect(x, y, outline, height, cache.outline1); p.fillRect(x, y, outline, height, cache.outlines[0]);
} }
} }
p.fillRect(x + outline, y, width - outline, height, cache.bg); p.fillRect(x + outline, y, width - outline, height, cache.bg);

View file

@ -165,22 +165,22 @@ struct GeometryDescriptor {
bool elisionOneLine, bool elisionOneLine,
bool elisionBreakEverywhere); bool elisionBreakEverywhere);
constexpr auto kMaxQuoteOutlines = 3;
struct QuotePaintCache { struct QuotePaintCache {
QImage corners; QImage corners;
QImage outline; QImage outline;
mutable QImage bottomCorner; mutable QImage bottomCorner;
mutable QImage bottomRounding; mutable QImage bottomRounding;
std::array<QColor, kMaxQuoteOutlines> outlinesCached;
QColor headerCached; QColor headerCached;
QColor bgCached; QColor bgCached;
QColor outline1Cached;
QColor outline2Cached;
QColor iconCached; QColor iconCached;
std::array<QColor, kMaxQuoteOutlines> outlines;
QColor header; QColor header;
QColor bg; QColor bg;
QColor outline1;
QColor outline2;
QColor icon; QColor icon;
}; };