Skip to content

Commit 3e19d6a

Browse files
Gillibaldclaude
andcommitted
Split the batch metrics loop on the glyf branch instead of per glyph
The glyf check does not vary across the run, so it belongs above the loop rather than inside it. Splitting it also lets the bounds buffer live only in the branch that reads it, which drops the zero-length allocation that CFF / CFF2 fonts used to make just to satisfy the shared loop. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 84ed811 commit 3e19d6a

1 file changed

Lines changed: 15 additions & 18 deletions

File tree

src/Avalonia.Base/Media/GlyphTypeface.cs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -828,25 +828,17 @@ public bool TryGetGlyphMetrics(ReadOnlySpan<ushort> glyphIndices, Span<GlyphMetr
828828
return false;
829829
}
830830

831-
// Read all bounding boxes in one batch (spans fetched once), then combine. When
832-
// the font has no glyf table, bearings fall back to hmtx/vmtx and the box is zero.
833-
var hasGlyf = _glyfTable != null;
834-
835-
// No glyf table (CFF / CFF2) → no ink bounds to read; keep the buffer empty so
836-
// those fonts don't allocate a per-glyph bounds array that is never used.
837-
var boundsCount = hasGlyf ? glyphIndices.Length : 0;
838-
Span<GlyphBounds> bounds = boundsCount <= 256
839-
? stackalloc GlyphBounds[boundsCount]
840-
: new GlyphBounds[boundsCount];
841-
842-
if (hasGlyf)
831+
if (_glyfTable != null)
843832
{
844-
_glyfTable!.GetGlyphBounds(glyphIndices, bounds);
845-
}
833+
// Read all bounding boxes in one batch, so the glyf and loca spans are fetched once
834+
// for the whole run rather than per glyph.
835+
Span<GlyphBounds> bounds = glyphIndices.Length <= 256
836+
? stackalloc GlyphBounds[glyphIndices.Length]
837+
: new GlyphBounds[glyphIndices.Length];
846838

847-
for (int i = 0; i < glyphIndices.Length; i++)
848-
{
849-
if (hasGlyf)
839+
_glyfTable.GetGlyphBounds(glyphIndices, bounds);
840+
841+
for (int i = 0; i < glyphIndices.Length; i++)
850842
{
851843
var b = bounds[i];
852844

@@ -860,7 +852,12 @@ public bool TryGetGlyphMetrics(ReadOnlySpan<ushort> glyphIndices, Span<GlyphMetr
860852
AdvanceHeight = hasVertical ? vMetrics[i].AdvanceHeight : (ushort)0,
861853
};
862854
}
863-
else
855+
}
856+
else
857+
{
858+
// No glyf table (CFF / CFF2): there are no ink bounds to read, so bearings fall
859+
// back to hmtx/vmtx and the box stays zero. No bounds buffer is allocated either.
860+
for (int i = 0; i < glyphIndices.Length; i++)
864861
{
865862
metrics[i] = new GlyphMetrics
866863
{

0 commit comments

Comments
 (0)