Add public glyph-run output API#4
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b1618e4129
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3f3bc3a2e4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 943480331c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ad86176eab
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| catch (InvalidOperationException) | ||
| { | ||
| shapedRun = null; | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Restrict TryShapeText fallback to unavailable-backend failures
TryShapeText currently swallows every InvalidOperationException, but this exception type is also used by backend/runtime code for real shaping failures (for example failed font initialization or shaper-specific runtime faults). In those cases the method returns false as if shaping were simply unavailable, which hides actionable errors and can silently downgrade rendering behavior. Narrow this catch to the specific "no shaper configured" path (or a dedicated exception) so genuine backend failures still surface.
Useful? React with 👍 / 👎.
PR Summary: Add Pretext Glyph Output API
Title
Add public glyph-run output API for Pretext shaping-capable backends
Overview
This PR extends PretextSharp beyond measurement-only layout by adding a public glyph-output API that renderers can use to build positioned glyph runs or text blobs directly. The existing
Prepare,PrepareWithSegments, layout, rich-inline, and measurement APIs remain unchanged.The new API exposes glyph ids, clusters, advances, offsets, absolute glyph positions, aggregate advance, and font-run metadata. Backends report whether output is fully platform-shaped or only mapped glyph output, so consumers can make correctness-sensitive decisions for complex scripts.
Why
Previously, Pretext backends could measure text and, in some cases, internally use shaping engines, but that shaped data was not available to callers. Consumers such as custom Skia renderers still had to draw materialized text fragments with string or grapheme APIs.
This PR makes the backend glyph data available through Pretext itself:
PretextLayout.ShapeText(...);ShapePreparedText(...)and cache shaped line output by layout cursor range;PretextGlyphRunKind.Shaped;PretextGlyphRunKind.Mappedwhen raw glyph mapping is sufficient.Main Changes
Public Contracts
Adds
src/Pretext.Contracts/TextShapingContracts.cswith:PretextGlyphRunKindPretextTextDirectionPretextShapeOptionsPretextShapedGlyphPretextShapedFontRunPretextShapedRunIPretextTextShaperIPretextTextShaperFactoryPretextTextShaperFactoryAttributePretextGlyphRunKind.Shapedmeans backend-shaped glyph positions are returned.PretextGlyphRunKind.Mappedmeans glyph ids/positions are exposed, but the output should not be treated as full complex-script shaping.Core API
Adds:
The new shaper cache is cleared with the existing
ClearCache()path. Backend discovery mirrors measurer discovery throughPretextTextShaperFactoryAttribute.The prepared shaping path adds a prepared-object cache keyed by shaping direction, plus a line-run cache keyed by
LayoutCursorstart/end ranges. Whole-segment ranges are sliced from the full prepared shaped run. Unsafe intra-segment ranges, soft-hyphen materializations, and ranges that start or end at invisible break boundaries are shaped from the exact line text once, then reused from the range cache.Backend Implementations
CoreText:
IPretextTextShaperFactory.CTLineCreateWithAttributedString,CTLineGetGlyphRuns,CTRunGetGlyphs,CTRunGetPositions,CTRunGetAdvances, andCTRunGetStringIndices.PretextGlyphRunKind.Shaped.PretextShapeOptions.Directionvalues through cached CoreText paragraph styles with base writing direction set to left-to-right or right-to-left.Autokeeps the native CoreText default.FreeType:
IPretextTextShaperFactory.PretextShapeOptions.Direction.PretextGlyphRunKind.Shapedwhen HarfBuzz returns a complete primary-face shaped run.PretextGlyphRunKind.Mappedwith FreeType/fontconfig fallback font runs when HarfBuzz is unavailable or the shaped run contains missing glyphs.SkiaSharp:
IPretextTextShaperFactory.PretextGlyphRunKind.Mappedbecause this path is useful for simple glyph rendering but is not a full complex-script shaper.DirectWrite:
Tests
Adds
PretextShapingTestscovering:ShapeTextusing a configured shaping-capable measurer factory.ShapeTextcache reuse across repeated calls and cache invalidation viaClearCache.ShapeTextforwarding explicit direction options to the configured shaper.ShapePreparedTextprepared-object reuse and shaped line-run cache reuse.TryShapeTextfailure behavior when no usable shaper exists.PretextShapeOptions.Defaultreturning fresh non-shared mutable options.Updates existing test cleanup to reset both measurer and shaper global factory state.
Documentation and Packaging
Updates README and package metadata to describe:
ShapeTextandTryShapeText;Validation
Run locally:
Results:
git diff --checkpassed.Commit Breakdown
Add public text shaping APIPretextLayout.ShapeText,TryShapeText, and shaper factory discovery/cache integration.Implement glyph output backendsCover glyph output API behaviorDocument glyph output supportCache prepared shaped line outputFix shaped line break-boundary correctnessPreserve sliced shaped-run advancesAdvanceXandAdvanceYvalues when slicing shaped runs.Honor CoreText shaping directionPretextShapeOptionsinto the CoreText shaping runtime.Use UTF-16 clusters for Skia glyph outputCompatibility Notes
This is additive API surface. Existing measurement and layout callers should not need code changes.
Consumers that need full complex-script correctness should check:
Consumers that can render simple glyph ids directly may also accept
PretextGlyphRunKind.Mapped.Follow-Up Work
PretextShapeOptions.ShapeTexton warm and cold paths.