Skip to content

Commit 64c0f46

Browse files
Bump to latest stable and update docs.
1 parent 01d70d7 commit 64c0f46

17 files changed

Lines changed: 281 additions & 85 deletions

‎articles/fonts/colorfonts.md‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,34 @@ TextOptions options = new(font)
4444
};
4545
```
4646

47+
## Font palettes
48+
49+
COLR glyphs take their colors from the font's CPAL palette table. Many color fonts ship more than one palette, such as a default and a dark-background variant. [`TextOptions.FontPalette`](xref:SixLabors.Fonts.TextOptions.FontPalette) selects the palette that resolves the colors. Leave the value `null` to keep the font's default palette.
50+
51+
```csharp
52+
using SixLabors.Fonts;
53+
54+
Font font = SystemFonts.CreateFont("Segoe UI Emoji", 32);
55+
TextOptions options = new(font)
56+
{
57+
// Resolve COLR glyph colors with the font's second palette.
58+
// Palette indexes are zero-based; null keeps the font's default.
59+
FontPalette = new FontPalette(1)
60+
};
61+
```
62+
63+
A palette selection can also override individual entries. Each [`FontPaletteOverride`](xref:SixLabors.Fonts.FontPaletteOverride) replaces the palette color at one index:
64+
65+
```csharp
66+
// Start from the default palette, then replace entry 2 with opaque red.
67+
FontPalette palette = new(0,
68+
[
69+
new FontPaletteOverride(2, new GlyphColor(255, 0, 0, 255))
70+
]);
71+
```
72+
73+
[`TextRun.FontPalette`](xref:SixLabors.Fonts.TextRun.FontPalette) replaces the selection over a range of text. [`GlyphOptions.FontPalette`](xref:SixLabors.Fonts.GlyphOptions.FontPalette) applies the same selection when rendering or measuring by glyph ID.
74+
4775
## What happens in custom renderers
4876

4977
When a resolved glyph is a painted color glyph, Fonts streams it through [`IGlyphRenderer`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer) as one or more layers.
@@ -52,9 +80,10 @@ That means custom renderers should pay attention to:
5280

5381
- [`GlyphRendererParameters.GlyphType`](xref:SixLabors.Fonts.Rendering.GlyphRendererParameters.GlyphType)
5482
- [`BeginLayer(...)`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.BeginLayer*)
83+
- [`BeginGroup(...)`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.BeginGroup*) and [`EndGroup()`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.EndGroup*)
5584
- [`Paint`](xref:SixLabors.Fonts.Rendering.Paint)
5685
- [`FillRule`](xref:SixLabors.Fonts.Rendering.FillRule)
57-
- [`ClipQuad`](xref:SixLabors.Fonts.ClipQuad)
86+
- [`ClipBounds`](xref:SixLabors.Fonts.ClipBounds)
5887

5988
Depending on the font technology in use, the `Paint` passed to `BeginLayer(...)` may be:
6089

@@ -63,6 +92,8 @@ Depending on the font technology in use, the `Paint` passed to `BeginLayer(...)`
6392
- [`RadialGradientPaint`](xref:SixLabors.Fonts.Rendering.RadialGradientPaint)
6493
- [`SweepGradientPaint`](xref:SixLabors.Fonts.Rendering.SweepGradientPaint)
6594

95+
COLR v1 paint graphs can also form composite groups. Fonts wraps such content in [`BeginGroup(...)`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.BeginGroup*) and [`EndGroup()`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.EndGroup*) calls. Layers inside a group compose as one isolated unit. The finished group then blends onto the content below it with the [`CompositeMode`](xref:SixLabors.Fonts.Rendering.CompositeMode) given to `BeginGroup(...)`. A clip for the glyph arrives through [`GlyphRendererParameters.ClipBounds`](xref:SixLabors.Fonts.Rendering.GlyphRendererParameters.ClipBounds).
96+
6697
If your renderer ignores paint information, the glyph can still be drawn, but it will no longer preserve the font's intended color presentation.
6798

6899
## Inspect color glyphs directly

‎articles/fonts/customrendering.md‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ For monochrome outline glyphs, the path callbacks are delivered inside [`BeginGl
2727
5. `SetDecoration(...)` for any decorations requested by `EnabledDecorations()`
2828
6. `EndText()`
2929

30-
Painted color glyphs add [`BeginLayer(...)`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.BeginLayer*) / [`EndLayer()`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.EndLayer*) around each painted layer between [`BeginGlyph(...)`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.BeginGlyph*) and [`EndGlyph()`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.EndGlyph*).
30+
Painted color glyphs add [`BeginLayer(...)`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.BeginLayer*) / [`EndLayer()`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.EndLayer*) around each painted layer between [`BeginGlyph(...)`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.BeginGlyph*) and [`EndGlyph()`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.EndGlyph*). COLR v1 composite content adds [`BeginGroup(...)`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.BeginGroup*) / [`EndGroup()`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.EndGroup*) around layers that must compose as one isolated unit before they blend onto the content below.
3131

3232
[`BeginGlyph(...)`](xref:SixLabors.Fonts.Rendering.IGlyphRenderer.BeginGlyph*) receives [`GlyphRendererParameters`](xref:SixLabors.Fonts.Rendering.GlyphRendererParameters), which identify the glyph instance being rendered, including the glyph ID, the glyph's [`CodePoint`](xref:SixLabors.Fonts.Unicode.CodePoint) value, font style, point size, DPI, layout mode, hinting mode, and active [`TextRun`](xref:SixLabors.Fonts.TextRun). Return `false` from `BeginGlyph(...)` if you want to skip rendering that glyph. The parameters include everything that changes glyph geometry, so a renderer can use them as a cache key.
3333

@@ -57,14 +57,22 @@ public sealed class RecordingGlyphRenderer : IGlyphRenderer
5757
{
5858
}
5959

60-
public void BeginLayer(Paint? paint, FillRule fillRule, ClipQuad? clipBounds)
60+
public void BeginLayer(Paint? paint, FillRule fillRule)
6161
{
6262
}
6363

6464
public void EndLayer()
6565
{
6666
}
6767

68+
public void BeginGroup(CompositeMode mode)
69+
{
70+
}
71+
72+
public void EndGroup()
73+
{
74+
}
75+
6876
public void BeginFigure()
6977
{
7078
}

‎articles/fonts/fallbackfonts.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,28 @@ Fallback families are searched in the order you provide them.
3434
- Put emoji fonts after your normal text families unless you explicitly want them to win earlier.
3535
- Keep the fallback list as small and intentional as possible so the selection stays predictable.
3636

37+
## Resolver-based fallback
38+
39+
[`FallbackFontFamilies`](xref:SixLabors.Fonts.TextOptions.FallbackFontFamilies) is a fixed list. [`TextOptions.FontFallbackResolver`](xref:SixLabors.Fonts.TextOptions.FontFallbackResolver) adds a dynamic last step behind it. Shaping consults the resolver only for code points that neither the primary font nor any fallback family can shape. It asks at most once per distinct unresolved code point per shaping operation. Leave the value `null` to render such code points as the missing-glyph outline.
40+
41+
[`SystemFonts.FallbackResolver`](xref:SixLabors.Fonts.SystemFonts.FallbackResolver) is a built-in resolver that selects from the fonts installed on the current machine:
42+
43+
```csharp
44+
using SixLabors.Fonts;
45+
46+
Font font = SystemFonts.CreateFont("Segoe UI", 18);
47+
TextOptions options = new(font)
48+
{
49+
// Ask the operating system for a family when no configured font
50+
// can shape a code point.
51+
FontFallbackResolver = SystemFonts.FallbackResolver
52+
};
53+
```
54+
55+
Installed fonts differ between machines, so output rendered with the system resolver can differ too. Pin `FallbackFontFamilies` for output that must stay identical everywhere, and use the resolver as a safety net behind them.
56+
57+
Implement [`IFontFallbackResolver`](xref:SixLabors.Fonts.IFontFallbackResolver) for a custom policy. The resolver receives the code point, the requested family, the style, and the culture. It returns the family that contains a glyph for the code point.
58+
3759
## Mixed-script example
3860

3961
This pattern works well for text that mixes Latin, Arabic, and emoji:

‎articles/fonts/shaping.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ At a high level, Fonts does the following:
5353
5. Applies right-to-left mirrored forms and vertical alternates where the layout requires them.
5454
6. Applies OpenType GSUB substitutions through the appropriate script shaper.
5555
7. Applies GPOS positioning for kerning, marks, cursive attachment, and related placement behavior.
56-
8. Retries unmapped code points with the configured fallback font families.
56+
8. Retries unmapped code points with the configured fallback font families, then with families from [`FontFallbackResolver`](xref:SixLabors.Fonts.TextOptions.FontFallbackResolver) when one is set.
5757
9. Updates final glyph positions for every font involved in the shaped result.
5858

5959
The first shaping result is independent of wrapping width. Line composition and alignment happen after shaping, so the same shaped text can be measured, wrapped, rendered, or inspected without changing which glyphs were chosen.
@@ -127,7 +127,7 @@ Mirrored forms, such as paired punctuation in right-to-left runs, are part of th
127127

128128
Fallback is not just a missing-glyph replacement step at the end of rendering. It participates in shaping because each font has its own glyph coverage, metrics, OpenType tables, script tags, and mark positioning behavior.
129129

130-
When the primary text-run font cannot map every code point, Fonts retries unresolved text against [`FallbackFontFamilies`](xref:SixLabors.Fonts.TextOptions.FallbackFontFamilies). The fallback font supplies the glyphs and positions for the code points it covers.
130+
When the primary text-run font cannot map every code point, Fonts retries unresolved text against [`FallbackFontFamilies`](xref:SixLabors.Fonts.TextOptions.FallbackFontFamilies). The fallback font supplies the glyphs and positions for the code points it covers. A configured [`FontFallbackResolver`](xref:SixLabors.Fonts.TextOptions.FontFallbackResolver) is consulted last, for code points that no listed family can shape. See [Fallback Fonts and Multilingual Text](fallbackfonts.md).
131131

132132
For multilingual text, emoji, and complex scripts, validate fallback with real production strings. A font can contain the individual code points but still lack the OpenType data needed for correct shaping.
133133

‎articles/fonts/systemfonts.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ The main entry points are:
1212
- [`SystemFonts.Get(...)`](xref:SixLabors.Fonts.SystemFonts.Get*) and [`SystemFonts.TryGet(...)`](xref:SixLabors.Fonts.SystemFonts.TryGet*) to resolve a family by invariant name
1313
- [`SystemFonts.CreateFont(...)`](xref:SixLabors.Fonts.SystemFonts.CreateFont*) to create a [`Font`](xref:SixLabors.Fonts.Font) directly
1414
- [`SystemFonts.Collection`](xref:SixLabors.Fonts.SystemFonts.Collection) when you also need access to the searched directories
15+
- [`SystemFonts.TryMatchCharacter(...)`](xref:SixLabors.Fonts.SystemFonts.TryMatchCharacter*) to ask the operating system which installed font covers a code point
16+
- [`SystemFonts.FallbackResolver`](xref:SixLabors.Fonts.SystemFonts.FallbackResolver) to let text shaping consult the system for unresolved code points; see [Fallback Fonts and Multilingual Text](fallbackfonts.md)
1517

1618
```csharp
1719
using SixLabors.Fonts;

‎articles/imagesharp.drawing/canvas.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ Layer bounds limit the isolated target and final composition area. They do not m
220220

221221
A layer is useful when a group of commands must be blended as one result. Without a layer, each command is blended into the parent independently. With a layer, commands first render into an isolated target, then that whole target is composited back once.
222222

223-
`SaveLayer(...)` overloads also accept a [`LayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.LayerEffect), such as blur, drop shadow, glow, or a backdrop filter, that transforms the layer when it is restored. See [Clipping, Regions, and Layers](clippingregionslayers.md) for the effect model.
223+
`SaveLayer(...)` overloads also accept a [`LayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.LayerEffect), such as blur, drop shadow, glow, or a backdrop filter, that transforms the layer when it is restored. See [Layer and Backdrop Effects](layereffects.md) for the effect model.
224224

225225
The layer lifecycle is:
226226

‎articles/imagesharp.drawing/clippingregionslayers.md‎

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -114,83 +114,14 @@ Use layers when a group of commands should blend back as one result. Without a l
114114

115115
## Layer Effects
116116

117-
`SaveLayer(...)` overloads accept a [`LayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.LayerEffect) that transforms the layer content when the layer is restored. The layer isolates the content, so the effect operates on exactly what was drawn between `SaveLayer(...)` and `Restore()`, against transparency, before the result composites onto the canvas.
118-
119-
The built-in content effects are:
120-
121-
- [`BlurLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.BlurLayerEffect) blurs the layer content with a Gaussian sigma.
122-
- [`DropShadowLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.DropShadowLayerEffect) slots a blurred, offset shadow beneath the layer content.
123-
- [`GlowLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.GlowLayerEffect) surrounds the content with a colored glow.
124-
- [`InnerShadowLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.InnerShadowLayerEffect) shades the content inside its own edges.
125-
- [`ColorMatrixLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.ColorMatrixLayerEffect) transforms the content colors through a `ColorMatrix`.
126-
127-
The layer bounds are expanded internally by the effect's reach, so blurred or offset output is not cut off.
128-
129-
```csharp
130-
using SixLabors.ImageSharp;
131-
using SixLabors.ImageSharp.Drawing.Processing;
132-
using SixLabors.ImageSharp.PixelFormats;
133-
using SixLabors.ImageSharp.Processing;
134-
135-
using Image<Rgba32> image = new(360, 220, Color.White.ToPixel<Rgba32>());
136-
137-
image.Mutate(ctx => ctx.Paint(canvas =>
138-
{
139-
_ = canvas.SaveLayer(
140-
new GraphicsOptions(),
141-
new Rectangle(60, 40, 240, 140),
142-
new DropShadowLayerEffect(new Point(6, 6), 4F, Color.Black.WithAlpha(0.5F)));
143-
144-
canvas.FillEllipse(Brushes.Solid(Color.OrangeRed), new(180, 110), new(90, 50));
145-
canvas.Restore();
146-
}));
147-
```
148-
149-
An overload accepts an `IPath` region instead of a rectangle. The effect then processes only pixels covered by the path, and its output lands on the path translated by the effect's offset.
150-
151-
## Backdrop Effects
152-
153-
A [`BackdropLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.BackdropLayerEffect) filters the pixels already on the canvas beneath the layer's region. The filter runs when the layer is opened, the filtered result is clipped to the region, and the layer's content then renders above it. This is the CSS `backdrop-filter` model.
154-
155-
The built-in backdrop effects are:
156-
157-
- [`BackdropBlurLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.BackdropBlurLayerEffect) blurs the backdrop, the classic frosted-glass base.
158-
- [`BackdropAcrylicLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.BackdropAcrylicLayerEffect) combines a blur with a tint color for acrylic panels.
159-
- [`BackdropDropShadowLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.BackdropDropShadowLayerEffect) casts a shadow from the backdrop content.
160-
- [`BackdropColorMatrixLayerEffect`](xref:SixLabors.ImageSharp.Drawing.Processing.BackdropColorMatrixLayerEffect) transforms backdrop colors through a `ColorMatrix`. Prebuilt variants cover brightness, contrast, grayscale, hue rotation, inversion, opacity, sepia, and saturation.
161-
162-
```csharp
163-
using SixLabors.ImageSharp;
164-
using SixLabors.ImageSharp.Drawing.Processing;
165-
using SixLabors.ImageSharp.PixelFormats;
166-
using SixLabors.ImageSharp.Processing;
167-
168-
using Image<Rgba32> image = Image.Load<Rgba32>("photo.jpg");
169-
170-
image.Mutate(ctx => ctx.Paint(canvas =>
171-
{
172-
Rectangle panel = new(70, 46, 220, 128);
173-
174-
_ = canvas.SaveLayer(
175-
new GraphicsOptions(),
176-
panel,
177-
new BackdropAcrylicLayerEffect(10F, Color.White.WithAlpha(0.3F)));
178-
179-
// The backdrop inside the panel is already blurred and tinted.
180-
// Content drawn here renders above the filtered backdrop.
181-
canvas.Draw(Pens.Solid(Color.White, 2), panel);
182-
canvas.Restore();
183-
}));
184-
```
185-
186-
Content effects and backdrop effects answer different questions. Use a content effect when the drawing inside the layer needs the treatment. Use a backdrop effect when the pixels behind a panel need the treatment and the panel content must stay sharp.
117+
`SaveLayer(...)` overloads accept effects that transform the layer when it is restored: blur, drop shadow, glow, inner shadow, color matrix, and CSS-style backdrop filters. The built-in set, the GPU shader implementations, and custom effect authoring have a dedicated page. See [Layer and Backdrop Effects](layereffects.md).
187118

188119
## Practical Guidance
189120

190121
- Use clips when geometry should constrain later commands in the current coordinate space.
191122
- Use regions when a child layout should have its own local origin.
192123
- Use layers when several commands should blend back as one grouped result.
193-
- Use a `LayerEffect` when the layer content needs blur, shadow, glow, or color treatment as a group.
124+
- Use a `LayerEffect` when the layer content needs blur, shadow, glow, or color treatment as a group. See [Layer and Backdrop Effects](layereffects.md).
194125
- Use a `BackdropLayerEffect` when the pixels behind a region need treatment while the content on top stays sharp.
195126
- Remember that layer bounds constrain composition but do not move the coordinate system.
196127
- Restore saved state as soon as the scoped work is complete.

0 commit comments

Comments
 (0)