Skip to content

Implement baseline anchoring and visible bounds culling for text - #549

Merged
JimBobSquarePants merged 2 commits into
mainfrom
js/render-culling
Jul 23, 2026
Merged

Implement baseline anchoring and visible bounds culling for text#549
JimBobSquarePants merged 2 commits into
mainfrom
js/render-culling

Conversation

@JimBobSquarePants

Copy link
Copy Markdown
Member

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following matches the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

This pull request introduces several enhancements to font metrics and text rendering, focusing on improved baseline and bounding box handling, as well as adding support for additional font metrics such as x-height and cap height. These changes improve the library's ability to accurately render and layout text, especially with respect to advanced typographic features and culling of invisible glyphs.

Font Metrics Enhancements:

  • Added support for retrieving x-height and cap height from fonts by introducing XHeight and CapHeight properties to FontMetrics and implementing them in all relevant subclasses (StreamFontMetrics, FileFontMetrics, MemoryFontMetrics). [1] [2] [3] [4] [5] [6]
  • Added a method to retrieve baseline coordinates (TryGetBaselineCoordinate) to FontMetrics and its subclasses, enabling more precise baseline alignment using the font's BASE table when available. [1] [2] [3] [4]

Font Table and Data Handling:

  • Updated font table reading logic to load the BASE table for both TrueType and CFF fonts and store it in the font's table structures, making advanced baseline data available for rendering. [1] [2] [3] [4] [5]

Text Rendering and Layout Improvements:

  • Enhanced GlyphOptions and TextRenderer to support visible bounds culling (VisibleBounds), baseline alignment (TextBaseline), and baseline offset (BaselineOffset) for glyph rendering, allowing for more precise and efficient text rendering. [1] [2]
  • Refactored text rendering to handle empty input gracefully, and to support line-breaking and culling of invisible lines based on visible bounds, improving performance and correctness for large or clipped text. [1] [2]

Internal Data Structure Updates:

  • Updated the internal representation of code page ranges in OS2Table to use 32-bit integers instead of 16-bit, for improved compatibility with font specifications.

Introduces configurable text/glyph baseline anchoring via new `TextBaseline` options and wires it through layout, rendering, and metrics. Adds OpenType `BASE` table loading plus OS/2 x-height/cap-height support so hanging/ideographic and related baselines can use font-provided coordinates with metric fallbacks.

Rendering now supports visible-region culling for text blocks, one-shot text rendering, and glyph runs (including early line-break stop when safe). Measurement behavior was aligned with rendering semantics (zero-based logical advance, positioned renderable bounds), and comprehensive tests/reference outputs were added, including new baseline browser comparison fixtures and a Noto Sans SC baseline subset font.
Introduces `BaselineOffset` on `TextOptions` (and `GlyphOptions`) and propagates it through layout, rendering, measuring, and line metrics so baseline shift composes with baseline anchoring consistently. The offset is treated as pixel units, applies correctly for horizontal and vertical modes, and keeps logical advance unchanged. Added/updated baseline tests and layout test utilities to cover render/measure parity, vertical behavior, and DPI independence.
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.52880% with 40 lines in your changes missing coverage. Please review.
✅ Project coverage is 80%. Comparing base (2a6df82) to head (eecad11).

Files with missing lines Patch % Lines
src/SixLabors.Fonts/TextLayout.cs 81% 15 Missing and 9 partials ⚠️
src/SixLabors.Fonts/Rendering/TextRenderer.cs 85% 4 Missing and 5 partials ⚠️
src/SixLabors.Fonts/MemoryFontMetrics.cs 33% 2 Missing ⚠️
src/SixLabors.Fonts/StreamFontMetrics.cs 81% 1 Missing and 1 partial ⚠️
src/SixLabors.Fonts/FileFontMetrics.cs 66% 1 Missing ⚠️
...bors.Fonts/Tables/AdvancedTypographic/BaseTable.cs 99% 0 Missing and 1 partial ⚠️
src/SixLabors.Fonts/TextBlock.cs 95% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@          Coverage Diff           @@
##            main    #549    +/-   ##
======================================
  Coverage     80%     80%            
======================================
  Files        348     349     +1     
  Lines      26860   27165   +305     
  Branches    4002    4059    +57     
======================================
+ Hits       21491   21784   +293     
- Misses      4394    4396     +2     
- Partials     975     985    +10     
Flag Coverage Δ
unittests 80% <89%> (+<1%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JimBobSquarePants
JimBobSquarePants merged commit aba0a93 into main Jul 23, 2026
13 checks passed
@JimBobSquarePants
JimBobSquarePants deleted the js/render-culling branch July 23, 2026 02:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant