Text rendering fixes - #341
Open
ilya-fedin wants to merge 7 commits into
Open
Conversation
None of these are referenced by the files that include them: text_renderer.cpp <private/qharfbuzz_p.h> no hb_ or HB_ symbols text_block.cpp <private/qfontengine_p.h> no QFontEngine, no QGlyphLayout text_block.h <private/qfixed_p.h> no QFixed text_block_parser.cpp <private/qfixed_p.h> no QFixed Private headers carry no binary compatibility guarantee, so every one of them is a rebuild risk for distribution packagers on a Qt point release. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The line came from QTextEngine::itemize(), where Qt guards it:
if (!qt_useHarfbuzzNG())
analysis[i].script = hbscript_to_script(script_to_hbscript(...));
and qt_useHarfbuzzNG() is `qgetenv("QT_HARFBUZZ") != "old"`, so Qt 5.15 only
runs it for the legacy shaper nobody asks for. Our copy dropped the guard and
ran it always. Qt itself introduced the mapping in 2012 when it moved to
QChar::Script, to keep the behaviour of the old harfbuzz, which knew 29 scripts
and treated the rest - latin, Han, hiragana, katakana and everything Unicode
gained since - as Common; Qt 6 lost it in f0813484 ("Remove old harfbuzz
dependency from QTextEngine"), which deleted that shaper wholesale.
Collapsing scripts to Common made itemization group into one item what it
otherwise splits, so dropping it does not change what the text looks like: it
adopts what Qt 5 does by default and what Qt 6 does always.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…dle. A middle elision fills each half of the line from its outer edge inwards, so it has to keep the end of an item that faces the middle - and which end that is depends on the item's direction, since glyphs are stored in logical order and the visually left part of a right-to-left item is its last glyphs. Walking from the first glyph regardless kept the wrong end as soon as a half spanned more than one item: instead of the beginning and the end of the text, a right-to-left line showed two stretches out of its middle, out of order. An item covers at most kMaxItemLength characters, so this takes a longer text than that - a Premium message of up to 8192, or an Instant View paragraph. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A cluster can map to several glyphs, and the walks that turn an x into a character and a character range into a highlight took only the first one's advance. Their running x then fell behind the text as it is drawn - by 117 pixels on a devanagari item here - so a drag resolved to a character left of the pointer, and the highlight started left of the characters it covered. The gap left at the end of a line by a selection that spans lines came from the same place, at seven pixels of it. Sum the advances of the cluster's glyphs instead, which makes the walks add up to the item width they are laid out with. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
When a selection runs past the end of a line, the rest of the line is filled separately, and that fill started where the line width minus what was left over said the text ended. The items add up to a slightly different place - the leftover counts the last word's right bearing, the items do not - so on a script whose last glyph overhangs, the two rounded to different pixels and left a gap. The devanagari sample showed it at one pixel; before the cluster width fix it was seven. Fill it after the items instead, where the end of the text is known exactly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A point outside a line is checked against the line's width, which counts the last word's right bearing, while the items that take a point inside the line do not count it - so up to a pixel between the last glyph and the line's width belongs to neither check. A click there fell through to whatever the walk over lines had left behind: the end of the line above, or the very start of the text when there is no line above. Resolve it like a point past the line, at the end of the line it is on, and let the three places that resolve to an edge of a line share one helper. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A visible letter can take several characters and several glyphs - a consonant with its matra, a conjunct, a base with combining marks - and the only places a caret can be at are its boundaries. Three walks used to step a glyph at a time and land inside one: a drag resolved to a character no selection could start at, so half a letter could be highlighted; the middle elision left an orphan matra behind and let the line run past the width it was given; and the ordinary one replaced half a letter with the ellipsis. Step by grapheme in all three, weighing each letter by the advances of the glyphs it takes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.