Add method to count max monospace paragraph width.

This commit is contained in:
John Preston 2020-05-12 11:05:55 +04:00
parent d05d9b214d
commit b1d00d0b28
2 changed files with 61 additions and 3 deletions

View file

@ -2755,7 +2755,7 @@ void String::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
_maxWidth = _minHeight = 0;
int32 lineHeight = 0;
int32 result = 0, lastNewlineStart = 0;
int32 lastNewlineStart = 0;
QFixed _width = 0, last_rBearing = 0, last_rPadding = 0;
for (auto i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) {
auto b = i->get();
@ -2823,6 +2823,63 @@ void String::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
}
}
int String::countMaxMonospaceWidth() const {
NewlineBlock *lastNewline = 0;
auto result = QFixed();
auto paragraphWidth = QFixed();
auto lastNewlineStart = 0;
auto fullMonospace = true;
QFixed _width = 0, last_rBearing = 0, last_rPadding = 0;
for (auto i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) {
auto b = i->get();
auto _btype = b->type();
if (_btype == TextBlockTNewline) {
lastNewlineStart = b->from();
lastNewline = static_cast<NewlineBlock*>(b);
last_rBearing = b->f_rbearing();
last_rPadding = b->f_rpadding();
if (fullMonospace) {
accumulate_max(paragraphWidth, _width);
accumulate_max(result, paragraphWidth);
paragraphWidth = 0;
} else {
fullMonospace = true;
}
_width = (b->f_width() - last_rBearing);
continue;
}
if (!(b->flags() & (TextBlockFPre | TextBlockFCode))
&& (b->type() != TextBlockTSkip)) {
fullMonospace = false;
}
auto b__f_rbearing = b->f_rbearing(); // cache
// We need to accumulate max width after each block, because
// some blocks have width less than -1 * previous right bearing.
// In that cases the _width gets _smaller_ after moving to the next block.
//
// But when we layout block and we're sure that _maxWidth is enough
// for all the blocks to fit on their line we check each block, even the
// intermediate one with a large negative right bearing.
if (fullMonospace) {
accumulate_max(paragraphWidth, _width);
}
_width += last_rBearing + (last_rPadding + b->f_width() - b__f_rbearing);
last_rBearing = b__f_rbearing;
last_rPadding = b->f_rpadding();
continue;
}
if (_width > 0 && fullMonospace) {
accumulate_max(paragraphWidth, _width);
accumulate_max(result, paragraphWidth);
}
return result.ceil().toInt();
}
void String::setMarkedText(const style::TextStyle &st, const TextWithEntities &textWithEntities, const TextParseOptions &options) {
_st = &st;
clear();

View file

@ -128,12 +128,13 @@ public:
bool updateSkipBlock(int width, int height);
bool removeSkipBlock();
int32 maxWidth() const {
int maxWidth() const {
return _maxWidth.ceil().toInt();
}
int32 minHeight() const {
int minHeight() const {
return _minHeight;
}
int countMaxMonospaceWidth() const;
void draw(Painter &p, int32 left, int32 top, int32 width, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, TextSelection selection = { 0, 0 }, bool fullWidthSelection = true) const;
void drawElided(Painter &p, int32 left, int32 top, int32 width, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false, TextSelection selection = { 0, 0 }) const;