Support quote icon in blockquote.
This commit is contained in:
parent
6e7c4c1c4d
commit
46465fc5ce
4 changed files with 56 additions and 34 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 <
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue