Repository navigation
Description
WebParagraph's line metrics diverge from SkParagraph (CanvasKit / Skwasm) in several independent ways. All of them are visible through Paragraph.height, Paragraph.alphabeticBaseline, computeLineMetrics(), getBoxesForRange() and getBoxesForPlaceholders(); the reference behavior is Run::calculateMetrics, InternalLineMetrics, TextWrapper::breakTextIntoLines, ParagraphImpl::computeEmptyMetrics and TextLine::getRectsForRange in modules/skparagraph.
1. kTextHeightNone is treated as a height multiplier of 0.0
ChildStyleNode._heightmapsTextStyle(height: kTextHeightNone)tonulland then falls back to the parent's height, so a child span cannot opt out of aParagraphStyle(height: 3.0).LineBlockand the empty-paragraph branch ofTextLayout.wrapTextonly checkheight != null, soParagraphStyle(height: kTextHeightNone)multiplies the line metrics by0.0.
Expected: kTextHeightNone disables the multiplier and the line is laid out at the font's own ascent + descent.
2. The default TextLeadingDistribution is even, and TextHeightBehavior.leadingDistribution is ignored
LineBlocktreatsleadingDistribution == nullaseven(half-leading). SkParagraph's default isproportional(fHalfLeading == false), i.e. ascent and descent are scaled by the same factor. The total line height is the same, but the baseline position differs for every paragraph that setsheightwithout an explicitleadingDistribution.WebParagraphStyledoesn't passtextHeightBehavior.leadingDistributionto its root text style andRootStyleNode._leadingDistributionalways returnsnull, soTextHeightBehavior(leadingDistribution: even)has no effect.
3. StrutStyle does not affect line metrics
StrutStylehas no effect on line metrics:WebStrutStyle.calculateMetricscomputesstrutAscent/strutDescent/strutLeading, but their only consumer isgetBoxesForRange(boxHeightStyle: BoxHeightStyle.strut).TextLinestarts from0/0and only accumulates block metrics, so a strut never sets a minimum line height,forceStrutHeightis a no-op (for text and placeholders alike) andleadingis lost. E.g.StrutStyle(fontFamily: 'Arial', fontSize: 20, height: 1.0, leading: 1.5, forceStrutHeight: true)+'Hello'should give a 50px line (20 + 30 of leading); WebParagraph gives the font's natural height.WebStrutStyle.calculateMetricsalso bails out whenfontSizeisnull(SkParagraph falls back to the default font size, 14), ignores the paragraph'sTextHeightBehavior.leadingDistributionas a fallback (dart:uiresolvesstrutStyle.leadingDistribution ?? textHeightBehavior.leadingDistribution), and accepts a negativeleading.- An empty paragraph ignores
height,StrutStyleandTextHeightBehaviorentirely:paragraph.heightis just the height of the empty cluster, and both baselines are set to that height.
4. TextHeightBehavior.applyHeightToFirstAscent / applyHeightToLastDescent are ignored
Both flags are no-ops: the first line keeps its scaled ascent and the last line keeps its scaled descent. SkParagraph reverts them to the unscaled font metrics (and, after a trailing \n, it is the synthetic empty last line that loses its descent, not the text line before it).
5. Placeholder positioning and BoxHeightStyle.tight
- In
TextLayout.addLinea placeholder'sadvance.top = line.fontBoundingBoxAscent - block.ascentis computed in the same pass that grows the line ascent, so a taller placeholder later on the same line leaves the earlier one positioned against a stale ascent.getBoxesForRangeandgetBoxesForPlaceholdersthen disagree for the same placeholder. getBoxesForRange(..., boxHeightStyle: tight): for a placeholder,line.fontBoundingBoxAscent - block.multipliedFontBoundingBoxAscentis added a second time on top ofblock.advance.top; for text, the box uses the scaled (multiplied*) metrics instead of the unscaled glyph bounds thatTextLine::getRectsForRangereturns.
Part of #172561.
Activity
[web_paragraph] Honor kTextHeightNone in TextStyle and ParagraphStyle (…
[web_paragraph] Honor TextHeightBehavior.leadingDistribution and defa…
[web_paragraph] Fix placeholder positioning and BoxHeightStyle.tight …
[web_paragraph] Honor TextHeightBehavior.applyHeightToFirstAscent and…
[web_paragraph] Honor kTextHeightNone in TextStyle and ParagraphStyle (…
[web_paragraph] Honor TextHeightBehavior.leadingDistribution and defa…
[web_paragraph] Fix placeholder positioning and BoxHeightStyle.tight …
[web_paragraph] Honor TextHeightBehavior.applyHeightToFirstAscent and…