Skip to content

Commit 9a57bc5

Browse files
Merge pull request #413 from SixLabors/js/font-palette
Fix rich text cloning and palette cache key
2 parents b86b71f + 1a9c6e1 commit 9a57bc5

4 files changed

Lines changed: 35 additions & 5 deletions

File tree

src/ImageSharp.Drawing/ImageSharp.Drawing.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
<InternalsVisibleTo Include="SixLabors.ImageSharp.Drawing.WebGPU" Key="$(SixLaborsPublicKey)" />
4545
</ItemGroup>
4646
<ItemGroup>
47-
<PackageReference Include="SixLabors.Fonts" Version="3.0.1-alpha.0.17" />
48-
<PackageReference Include="SixLabors.ImageSharp" Version="4.0.1-alpha.0.23" />
47+
<PackageReference Include="SixLabors.Fonts" Version="3.0.1-alpha.0.18" />
48+
<PackageReference Include="SixLabors.ImageSharp" Version="4.0.1-alpha.0.24" />
4949
<PackageReference Include="SixLabors.PolygonClipper" Version="1.0.1-alpha.0.6" />
5050
</ItemGroup>
5151

src/ImageSharp.Drawing/Processing/RichTextGlyphRenderer.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,14 @@ internal struct GlyphRenderData
12181218
/// </summary>
12191219
public Pen? PenReference { get; init; }
12201220

1221+
/// <summary>
1222+
/// Gets the color palette selection the glyph's colors were resolved with, or
1223+
/// <see langword="null"/> when the glyph resolves no palette colors. The selection
1224+
/// changes the cached layer paints, so palette variants of one glyph must occupy
1225+
/// separate cache entries.
1226+
/// </summary>
1227+
public FontPalette? FontPalette { get; init; }
1228+
12211229
/// <summary>
12221230
/// Determines whether two <see cref="CacheKey"/> instances are equal.
12231231
/// </summary>
@@ -1269,7 +1277,8 @@ public static CacheKey FromParameters(
12691277
TextAttributes = parameters.TextRun.TextAttributes,
12701278
TextDecorations = parameters.TextRun.TextDecorations,
12711279
Size = size,
1272-
PenReference = penReference
1280+
PenReference = penReference,
1281+
FontPalette = parameters.FontPalette
12731282
};
12741283

12751284
/// <inheritdoc/>
@@ -1291,7 +1300,8 @@ public bool Equals(CacheKey other)
12911300
this.TextAttributes == other.TextAttributes &&
12921301
this.TextDecorations == other.TextDecorations &&
12931302
this.Size.Equals(other.Size) &&
1294-
ReferenceEquals(this.PenReference, other.PenReference);
1303+
ReferenceEquals(this.PenReference, other.PenReference) &&
1304+
Equals(this.FontPalette, other.FontPalette);
12951305

12961306
/// <inheritdoc/>
12971307
public override int GetHashCode()
@@ -1312,6 +1322,7 @@ public override int GetHashCode()
13121322
hash.Add(this.TextDecorations);
13131323
hash.Add(this.Size);
13141324
hash.Add(this.PenReference is null ? 0 : RuntimeHelpers.GetHashCode(this.PenReference));
1325+
hash.Add(this.FontPalette);
13151326
return hash.ToHashCode();
13161327
}
13171328
}

src/ImageSharp.Drawing/Processing/RichTextOptions.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Six Labors Split License.
33

44
using SixLabors.Fonts;
5+
using SixLabors.Fonts.Tables.AdvancedTypographic;
56

67
namespace SixLabors.ImageSharp.Drawing.Processing;
78

@@ -27,12 +28,17 @@ public RichTextOptions(RichTextOptions options)
2728
: base(options)
2829
{
2930
// Copy each run into a fresh instance so later mutation of the source runs
30-
// cannot leak into this options instance (and vice versa).
31+
// cannot leak into this options instance (and vice versa). Every property of
32+
// RichTextRun and its TextRun base must appear here: a missing property
33+
// silently resets to its default on the clone DrawText renders from.
3134
List<RichTextRun> runs = new(options.TextRuns.Count);
3235
foreach (RichTextRun run in options.TextRuns)
3336
{
3437
runs.Add(new RichTextRun()
3538
{
39+
// Brushes, pens, fonts, and palettes copy by reference: each is immutable
40+
// once constructed (FontPalette snapshots its overrides in its own
41+
// constructor), so a shared reference cannot leak later mutation.
3642
Brush = run.Brush,
3743
Pen = run.Pen,
3844
StrikeoutPen = run.StrikeoutPen,
@@ -41,8 +47,17 @@ public RichTextOptions(RichTextOptions options)
4147
Start = run.Start,
4248
End = run.End,
4349
Font = run.Font,
50+
FontWeight = run.FontWeight,
51+
Script = run.Script,
52+
Culture = run.Culture,
53+
54+
// The feature tag list is the one caller-owned mutable collection on a
55+
// run; the read-only interface is only a view, so isolation needs a copy.
56+
FeatureTags = run.FeatureTags is null ? null : new List<Tag>(run.FeatureTags),
4457
TextAttributes = run.TextAttributes,
4558
TextDecorations = run.TextDecorations,
59+
ColorFontSupport = run.ColorFontSupport,
60+
FontPalette = run.FontPalette,
4661
Placeholder = run.Placeholder
4762
});
4863
}

tests/ImageSharp.Drawing.Tests/Processing/DrawingCanvasTests.Text.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ public void DrawGlyphById_Inter_OverlappingContours_NoHoles<TPixel>(TestImagePro
107107
TextDecorations.None,
108108
LayoutMode.HorizontalTopBottom,
109109
ColorFontSupport.None,
110+
null,
110111
out FontGlyphMetrics metrics))
111112
{
112113
continue;
@@ -160,6 +161,7 @@ public void DrawGlyphById_Inter_EvenOddCanvasState_NoHoles<TPixel>(TestImageProv
160161
TextDecorations.None,
161162
LayoutMode.HorizontalTopBottom,
162163
ColorFontSupport.None,
164+
null,
163165
out FontGlyphMetrics metrics))
164166
{
165167
continue;
@@ -306,6 +308,7 @@ public void DrawPositionedGlyphs_Inter_MatchesGlyphByIdLoop<TPixel>(TestImagePro
306308
TextDecorations.None,
307309
LayoutMode.HorizontalTopBottom,
308310
ColorFontSupport.None,
311+
null,
309312
out FontGlyphMetrics metrics))
310313
{
311314
continue;
@@ -820,6 +823,7 @@ private static void DrawGlyphs<TPixel>(DrawingCanvas<TPixel> canvas, string text
820823
TextDecorations.None,
821824
LayoutMode.HorizontalTopBottom,
822825
ColorFontSupport.None,
826+
null,
823827
out FontGlyphMetrics metrics))
824828
{
825829
continue;

0 commit comments

Comments
 (0)