Support three-color quote outlines.
This commit is contained in:
parent
383b5b8f7e
commit
611224c52f
3 changed files with 37 additions and 24 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue