Repository navigation
Fix composite glyph transform double-scaling - #2014
Open
soufianekhiat wants to merge 1 commit into
Open
soufianekhiat wants to merge 1 commit into
soufianekhiat wants to merge 1 commit into
Conversation
Component scale factors (m, n) were applied on top of the full 2x2 matrix, squaring the scale of scaled/transformed composite components. Per the TrueType spec they are only meant to rescale the offsets when SCALED_COMPONENT_OFFSET (bit 11) is set and UNSCALED_COMPONENT_OFFSET (bit 12) is not. Fixes wrongly sized sub-components in e.g. COLR emoji fonts (OpenMoji, Noto Color Emoji, Fluent Emoji).
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.
Problem
In
stbtt__GetGlyphShapeTT(), composite glyph components are transformed with:where
m = sqrt(mtx[0]^2 + mtx[1]^2)andn = sqrt(mtx[2]^2 + mtx[3]^2).The 2x2 matrix already contains the component scale, so multiplying by
m/nagain squares it. Any component usingWE_HAVE_A_SCALE,WE_HAVE_AN_X_AND_Y_SCALEorWE_HAVE_A_TWO_BY_TWOends up at the wrong size and position. Unscaled components (m = n = 1) are unaffected, which is why this mostly goes unnoticed with regular text fonts.It is very visible with emoji/COLR fonts that reuse scaled sub-glyphs (e.g. OpenMoji, Noto Color Emoji, Microsoft Fluent Emoji): parts of the glyph render too big or too small, or are shifted.
Fix
Per the TrueType
glyfspec,m/nshould only be used to rescale the offset (mtx[4],mtx[5]), and only whenSCALED_COMPONENT_OFFSET(bit 11, 0x0800) is set andUNSCALED_COMPONENT_OFFSET(bit 12, 0x1000) is not. The default (neither flag set) is unscaled offsets, which matches Microsoft's convention and modern font tools.The transform becomes
v' = M * v + t: