Add LineMetrics and per-line measurement API#499
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #499 +/- ##
======================================
Coverage 83% 83%
======================================
Files 272 274 +2
Lines 18929 19184 +255
Branches 2676 2719 +43
======================================
+ Hits 15836 16081 +245
- Misses 2422 2426 +4
- Partials 671 677 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces the LineMetrics struct and a new TextMeasurer.GetLineMetrics() API for per-line measurement. It also refactors line spacing and alignment calculations in TextLayout.cs to correctly apply LineSpacing by baking it into the stored line height at glyph-addition time (rather than multiplying later during layout), and adds CalculateLineOffsetX/Y helper methods for alignment computation.
Changes:
- Adds
LineMetricsstruct andTextMeasurer.GetLineMetrics(string/ReadOnlySpan<char>, TextOptions)public API - Refactors line height and alignment calculations in horizontal, vertical, and mixed vertical layout methods to eliminate double-application of
LineSpacing - Adds
ScaledMaxDeltatracking toTextLineandGlyphLayoutDatato support accurate guide-line positioning inGetLineMetrics
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
src/SixLabors.Fonts/LineMetrics.cs |
New struct encapsulating per-line typographic metrics |
src/SixLabors.Fonts/TextMeasurer.cs |
New GetLineMetrics overloads; CountLines refactored to use ProcessText |
src/SixLabors.Fonts/TextLayout.cs |
ProcessText made internal; LineSpacing baked into stored height; CalculateLineOffsetX/Y helpers added; ScaledMaxDelta tracking added |
tests/SixLabors.Fonts.Tests/TextLayoutTestUtilities.cs |
Added beforeAction/afterAction hooks to TestLayout |
tests/SixLabors.Fonts.Tests/Issues/Issues_353.cs |
New visual regression test for GetLineMetrics with guide-line drawing |
tests/Images/ReferenceOutput/Test_Issue_353_400.png |
Reference image for the new test |
.github/workflows/build-and-test.yml |
Upgraded Codecov action to v5; added required token |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Prerequisites
Description
This pull request introduces improvements and refactoring to the text layout logic in the SixLabors.Fonts library, focusing on more accurate handling of line spacing and alignment for both horizontal and vertical text layouts. It also adds a new
LineMetricsstruct to encapsulate line measurement details and exposes additional internal APIs for better testability and extensibility.Text layout and alignment improvements:
Refactored line spacing and centering calculations in
TextLayout.csfor horizontal, vertical, and mixed vertical layout methods, ensuring glyphs are properly centered within extra space created byLineSpacing. This addresses previous inaccuracies in how line spacing affected glyph placement. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]Added new internal methods
CalculateLineOffsetXandCalculateLineOffsetYto centralize and clarify line alignment logic for both axes, improving maintainability and correctness of text alignment calculations.API and structure enhancements:
Added a new
LineMetricsstruct inLineMetrics.csto encapsulate measured metrics for a single laid-out text line, supporting both horizontal and vertical layouts.Exposed
ProcessTextas aninternalmethod inTextLayout.csto facilitate testing and internal usage.Glyph layout and metric tracking:
TextLineclass to track an additional metric,ScaledMaxDelta, for more precise line box calculations, and ensuredLineSpacingis applied when storing line heights. [1] [2] [3] [4]Minor fixes and code clarity:
Let me know if you want a deeper dive into any of these changes or need help understanding how the new alignment logic works!