diff --git a/ui/basic.style b/ui/basic.style index faab247..c0de76f 100644 --- a/ui/basic.style +++ b/ui/basic.style @@ -19,17 +19,24 @@ TextPalette { linkAlwaysActive: bool; } +ParagraphStyle { + padding: margins; + verticalSkip: pixels; + header: pixels; + headerPosition: point; + icon: icon; + iconPosition: point; + outline: pixels; + radius: pixels; + scrollable: bool; +} + TextStyle { font: font; linkUnderline: int; - blockPadding: margins; - blockVerticalSkip: pixels; - blockHeader: pixels; - blockHeaderPosition: point; - blockOutline: pixels; - blockRadius: pixels; - preScrollable: bool; lineHeight: pixels; + blockquote: ParagraphStyle; + pre: ParagraphStyle; } kLinkUnderlineNever: 0; @@ -58,10 +65,14 @@ defaultTextPalette: TextPalette { selectSpoilerFg: msgInDateFgSelected; selectOverlay: msgSelectOverlay; } +defaultParagraphStyle: ParagraphStyle { +} defaultTextStyle: TextStyle { font: normalFont; linkUnderline: kLinkUnderlineActive; lineHeight: 0px; + blockquote: defaultParagraphStyle; + pre: defaultParagraphStyle; } semiboldTextStyle: TextStyle(defaultTextStyle) { font: semiboldFont; diff --git a/ui/text/text.cpp b/ui/text/text.cpp index f53e648..fc14c68 100644 --- a/ui/text/text.cpp +++ b/ui/text/text.cpp @@ -185,29 +185,34 @@ GeometryDescriptor SimpleGeometry( } }; - void ValidateBlockPaintCache( BlockPaintCache &cache, - const style::TextStyle &st) { + const style::ParagraphStyle &st) { + const auto icon = st.icon.empty() ? nullptr : &st.icon; if (!cache.corners.isNull() && cache.bgCached == cache.bg && cache.outlineCached == cache.outline - && (!cache.withHeader || cache.headerCached == cache.header) - && (!cache.topright || cache.iconCached == cache.icon)) { + && (!st.header || cache.headerCached == cache.header) + && (!icon || cache.iconCached == cache.icon)) { return; } cache.bgCached = cache.bg; cache.outlineCached = cache.outline; - if (cache.withHeader) { + if (st.header) { cache.headerCached = cache.header; } - if (cache.topright) { + if (!st.icon.empty()) { cache.iconCached = cache.icon; } - const auto radius = st.blockRadius; - const auto header = cache.withHeader ? st.blockHeader : 0; - const auto outline = st.blockOutline; - const auto corner = std::max({ header, radius, outline }); + const auto radius = st.radius; + const auto header = st.header; + const auto outline = st.outline; + const auto iconsize = icon + ? std::max( + icon->width() + st.iconPosition.x(), + icon->height() + st.iconPosition.y()) + : 0; + const auto corner = std::max({ header, radius, outline, iconsize }); const auto middle = st::lineWidth; const auto side = 2 * corner + middle; const auto full = QSize(side, side); @@ -233,6 +238,11 @@ void ValidateBlockPaintCache( p.setBrush(cache.bg); p.setClipRect(outline, header, side - outline, side - header); p.drawRoundedRect(0, 0, side, side, radius, radius); + if (icon) { + const auto left = side - icon->width() - st.iconPosition.x(); + const auto top = st.iconPosition.y(); + icon->paint(p, left, top, side, cache.icon); + } p.end(); cache.corners = std::move(image); @@ -242,7 +252,7 @@ void FillBlockPaint( QPainter &p, QRect rect, const BlockPaintCache &cache, - const style::TextStyle &st, + const style::ParagraphStyle &st, SkipBlockPaintParts parts) { const auto &image = cache.corners; const auto ratio = int(image.devicePixelRatio()); @@ -265,7 +275,7 @@ void FillBlockPaint( image, QRect((iwidth - ihalf) * ratio, 0, ihalf * ratio, top * ratio)); if (const auto middle = width - 2 * ihalf) { - const auto header = cache.withHeader ? st.blockHeader : 0; + const auto header = st.header; const auto fillHeader = std::min(header, top); if (fillHeader) { p.fillRect(x + ihalf, y, middle, fillHeader, cache.header); @@ -316,7 +326,7 @@ void FillBlockPaint( } rect.setHeight(height); } - const auto outline = st.blockOutline; + const auto outline = st.outline; if (outline) { p.fillRect(x, y, outline, height, cache.outline); } @@ -1086,9 +1096,10 @@ QMargins String::paragraphPadding(ParagraphDetails *info) const { if (!info) { return {}; } - const auto skip = _st->blockVerticalSkip; - const auto top = info->pre ? _st->blockHeader : 0; - return _st->blockPadding + QMargins(0, top + skip, 0, skip); + const auto &st = info->pre ? _st->pre : _st->blockquote; + const auto skip = st.verticalSkip; + const auto top = st.header; + return st.padding + QMargins(0, top + skip, 0, skip); } template < diff --git a/ui/text/text.h b/ui/text/text.h index 00c63a8..9e33d56 100644 --- a/ui/text/text.h +++ b/ui/text/text.h @@ -24,6 +24,7 @@ enum class type : uchar; namespace style { struct TextStyle; struct TextPalette; +struct ParagraphStyle; } // namespace style namespace Ui { @@ -175,15 +176,11 @@ struct BlockPaintCache { QColor bg; QColor outline; QColor icon; - - const style::icon *topright = nullptr; - QPoint toprightPosition; - bool withHeader = false; }; void ValidateBlockPaintCache( BlockPaintCache &cache, - const style::TextStyle &st); + const style::ParagraphStyle &st); struct SkipBlockPaintParts { bool skipTop : 1 = false; @@ -193,7 +190,7 @@ void FillBlockPaint( QPainter &p, QRect rect, const BlockPaintCache &cache, - const style::TextStyle &st, + const style::ParagraphStyle &st, SkipBlockPaintParts parts = {}); struct PaintContext { diff --git a/ui/text/text_renderer.cpp b/ui/text/text_renderer.cpp index 896ca0c..fa6adca 100644 --- a/ui/text/text_renderer.cpp +++ b/ui/text/text_renderer.cpp @@ -415,29 +415,32 @@ void Renderer::fillParagraphBg(int paddingBottom) { ? _blockquoteBlockCache : nullptr; if (cache) { + const auto &st = _paragraph->pre + ? _t->_st->pre + : _t->_st->blockquote; auto &valid = _paragraph->pre ? _preBlockCacheValid : _blockquoteBlockCacheValid; if (!valid) { valid = true; - ValidateBlockPaintCache(*cache, *_t->_st); + ValidateBlockPaintCache(*cache, st); } - const auto skip = _t->_st->blockVerticalSkip; + const auto skip = st.verticalSkip; const auto isTop = (_y != _blockLineTop); const auto isBottom = (paddingBottom != 0); const auto top = _blockLineTop + (isTop ? skip : 0); const auto fill = _y + _lineHeight + paddingBottom - top - (isBottom ? skip : 0); const auto rect = QRect(_startLeft, top, _startLineWidth, fill); - FillBlockPaint(*_p, rect, *cache, *_t->_st, { + FillBlockPaint(*_p, rect, *cache, st, { .skipTop = !isTop, .skipBottom = !isBottom, }); - if (isTop && cache->withHeader) { + if (isTop && st.header > 0) { const auto font = _t->_st->font->monospace(); const auto topleft = rect.topLeft(); - const auto position = topleft + _t->_st->blockHeaderPosition; + const auto position = topleft + st.headerPosition; const auto baseline = position + QPoint(0, font->ascent); _p->setFont(font); _p->setPen(_palette->monoFg->p);