Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<AvaloniaVersion>12.0.0</AvaloniaVersion>
<SkiaSharpVersion Condition="'$(SkiaSharpVersion)' == ''">4.148.0</SkiaSharpVersion>
<HarfBuzzSharpVersion Condition="'$(HarfBuzzSharpVersion)' == ''">14.2.0</HarfBuzzSharpVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersion)" />
Expand All @@ -14,24 +16,24 @@
<PackageVersion Include="Avalonia.Headless.XUnit" Version="$(AvaloniaVersion)" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="$(AvaloniaVersion)" />
<PackageVersion Include="Avalonia.Controls.ColorPicker" Version="$(AvaloniaVersion)" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="10.0.0" />
<PackageVersion Include="Microsoft.Maui.Controls.Compatibility" Version="10.0.0" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="10.0.20" />
<PackageVersion Include="Microsoft.Maui.Controls.Compatibility" Version="10.0.20" />
<PackageVersion Include="Microsoft.Build.Tasks.Core" Version="18.0.2" />
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="10.0.0" />
<PackageVersion Include="Mono.Cecil" Version="0.11.6" />
<PackageVersion Include="Svg" Version="3.4.4" />
<PackageVersion Include="ExCSS" Version="4.3.1" />
<PackageVersion Include="SkiaSharp" Version="3.119.2" />
<PackageVersion Include="SkiaSharp.Views.Maui.Controls" Version="3.119.2" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.2" />
<PackageVersion Include="SkiaSharp.NativeAssets.Win32" Version="3.119.2" />
<PackageVersion Include="SkiaSharp.NativeAssets.macOS" Version="3.119.2" />
<PackageVersion Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.2" />
<PackageVersion Include="SkiaSharp.HarfBuzz" Version="3.119.2" />
<PackageVersion Include="HarfBuzzSharp" Version="8.3.1.3" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="8.3.1.3" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.macOS" Version="8.3.1.3" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Win32" Version="8.3.1.3" />
<PackageVersion Include="SkiaSharp" Version="$(SkiaSharpVersion)" />
<PackageVersion Include="SkiaSharp.Views.Maui.Controls" Version="$(SkiaSharpVersion)" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="$(SkiaSharpVersion)" />
<PackageVersion Include="SkiaSharp.NativeAssets.Win32" Version="$(SkiaSharpVersion)" />
<PackageVersion Include="SkiaSharp.NativeAssets.macOS" Version="$(SkiaSharpVersion)" />
<PackageVersion Include="SkiaSharp.NativeAssets.WebAssembly" Version="$(SkiaSharpVersion)" />
<PackageVersion Include="SkiaSharp.HarfBuzz" Version="$(SkiaSharpVersion)" />
<PackageVersion Include="HarfBuzzSharp" Version="$(HarfBuzzSharpVersion)" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="$(HarfBuzzSharpVersion)" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.macOS" Version="$(HarfBuzzSharpVersion)" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Win32" Version="$(HarfBuzzSharpVersion)" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="System.Memory" Version="4.6.3" />
<PackageVersion Include="System.Text.Json" Version="9.0.9" />
Expand Down
16 changes: 10 additions & 6 deletions build/SkiaSharp.Avalonia.props
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SkiaSharpVersion Condition="'$(SkiaSharpVersion)' == ''">4.148.0</SkiaSharpVersion>
</PropertyGroup>
<ItemGroup>
<!-- Keep direct SkiaSharp references aligned with Avalonia.Skia's SkiaSharp dependency. -->
<PackageReference Update="SkiaSharp" VersionOverride="3.119.3-preview.1.1" />
<PackageReference Update="SkiaSharp.NativeAssets.Linux" VersionOverride="3.119.3-preview.1.1" />
<PackageReference Update="SkiaSharp.NativeAssets.Win32" VersionOverride="3.119.3-preview.1.1" />
<PackageReference Update="SkiaSharp.NativeAssets.macOS" VersionOverride="3.119.3-preview.1.1" />
<PackageReference Update="SkiaSharp.NativeAssets.WebAssembly" VersionOverride="3.119.3-preview.1.1" />
<!-- Avalonia.Skia still targets SkiaSharp 3.x, so these direct references intentionally
override onto SkiaSharp 4 to keep the whole solution on a single SkiaSharp version. -->
<PackageReference Update="SkiaSharp" VersionOverride="$(SkiaSharpVersion)" />
<PackageReference Update="SkiaSharp.NativeAssets.Linux" VersionOverride="$(SkiaSharpVersion)" />
<PackageReference Update="SkiaSharp.NativeAssets.Win32" VersionOverride="$(SkiaSharpVersion)" />
<PackageReference Update="SkiaSharp.NativeAssets.macOS" VersionOverride="$(SkiaSharpVersion)" />
<PackageReference Update="SkiaSharp.NativeAssets.WebAssembly" VersionOverride="$(SkiaSharpVersion)" />
</ItemGroup>
</Project>
11 changes: 0 additions & 11 deletions src/Svg.Skia/SkiaModel.Caching.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1716,10 +1716,6 @@ private static bool TryAddPaintRevision(ref RevisionBuilder hash, ShimSkiaSharp.
var style = ToSKPaintStyle(paint.Style);
var strokeCap = ToSKStrokeCap(paint.StrokeCap);
var strokeJoin = ToSKStrokeJoin(paint.StrokeJoin);
var textAlign = ToSKTextAlign(paint.TextAlign);
var typefaceResolution = ResolvePaintTypeface(paint);
var typeface = typefaceResolution?.Typeface;
var textEncoding = ToSKTextEncoding(paint.TextEncoding);
var color = paint.Color is null
? SkiaSharp.SKColor.Empty
: ToSKColor(paint.Color.Value);
Expand All @@ -1736,12 +1732,6 @@ private static bool TryAddPaintRevision(ref RevisionBuilder hash, ShimSkiaSharp.
StrokeCap = strokeCap,
StrokeJoin = strokeJoin,
StrokeMiter = paint.StrokeMiter,
TextSize = paint.TextSize,
TextAlign = textAlign,
Typeface = typeface,
LcdRenderText = paint.LcdRenderText,
SubpixelText = paint.SubpixelText,
TextEncoding = textEncoding,
Color = color,
Shader = shader,
ColorFilter = colorFilter,
Expand All @@ -1750,7 +1740,6 @@ private static bool TryAddPaintRevision(ref RevisionBuilder hash, ShimSkiaSharp.
BlendMode = blendMode
};

ApplyTypefaceAdjustments(paint, skPaint, typefaceResolution?.SuppressSyntheticBold ?? false);
return skPaint;
}

Expand Down
126 changes: 35 additions & 91 deletions src/Svg.Skia/SkiaModel.TextShaping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public TextAdvanceCacheKey(
bool fakeBoldText,
bool lcdRenderText,
bool subpixelText,
SkiaSharp.SKTextEncoding textEncoding,
string? fontFeatureSettings,
string? fontKerning,
string? fontVariantLigatures,
Expand All @@ -48,7 +47,6 @@ public TextAdvanceCacheKey(
FakeBoldText = fakeBoldText;
LcdRenderText = lcdRenderText;
SubpixelText = subpixelText;
TextEncoding = textEncoding;
FontFeatureSettings = fontFeatureSettings;
FontKerning = fontKerning;
FontVariantLigatures = fontVariantLigatures;
Expand All @@ -66,7 +64,6 @@ public TextAdvanceCacheKey(
private bool FakeBoldText { get; }
private bool LcdRenderText { get; }
private bool SubpixelText { get; }
private SkiaSharp.SKTextEncoding TextEncoding { get; }
private string? FontFeatureSettings { get; }
private string? FontKerning { get; }
private string? FontVariantLigatures { get; }
Expand All @@ -85,7 +82,6 @@ public bool Equals(TextAdvanceCacheKey other)
FakeBoldText == other.FakeBoldText &&
LcdRenderText == other.LcdRenderText &&
SubpixelText == other.SubpixelText &&
TextEncoding == other.TextEncoding &&
string.Equals(FontFeatureSettings, other.FontFeatureSettings, StringComparison.Ordinal) &&
string.Equals(FontKerning, other.FontKerning, StringComparison.Ordinal) &&
string.Equals(FontVariantLigatures, other.FontVariantLigatures, StringComparison.Ordinal) &&
Expand All @@ -112,7 +108,6 @@ public override int GetHashCode()
hash = (hash * 397) ^ (FakeBoldText ? 1 : 0);
hash = (hash * 397) ^ (LcdRenderText ? 1 : 0);
hash = (hash * 397) ^ (SubpixelText ? 1 : 0);
hash = (hash * 397) ^ (int)TextEncoding;
hash = (hash * 397) ^ (FontFeatureSettings is null ? 0 : StringComparer.Ordinal.GetHashCode(FontFeatureSettings));
hash = (hash * 397) ^ (FontKerning is null ? 0 : StringComparer.Ordinal.GetHashCode(FontKerning));
hash = (hash * 397) ^ (FontVariantLigatures is null ? 0 : StringComparer.Ordinal.GetHashCode(FontVariantLigatures));
Expand All @@ -126,75 +121,74 @@ public override int GetHashCode()
}
}

internal float GetTextAdvance(string text, SkiaSharp.SKPaint paint)
internal float GetTextAdvance(string text, SkiaSharp.SKFont font)
{
return GetTextAdvance(text, paint, fontFeatureSettings: null, fontKerning: null, fontVariantLigatures: null);
return GetTextAdvance(text, font, fontFeatureSettings: null, fontKerning: null, fontVariantLigatures: null);
}

internal float GetTextAdvance(
string text,
SkiaSharp.SKPaint paint,
SkiaSharp.SKFont font,
string? fontFeatureSettings,
string? fontKerning,
string? fontVariantLigatures)
{
var cacheKey = CreateTextAdvanceCacheKey(text, paint, fontFeatureSettings, fontKerning, fontVariantLigatures);
var cacheKey = CreateTextAdvanceCacheKey(text, font, fontFeatureSettings, fontKerning, fontVariantLigatures);
if (s_textAdvanceCache.TryGetValue(cacheKey, out var cachedAdvance))
{
return cachedAdvance;
}

var advance = GetTextAdvanceUncached(text, paint, fontFeatureSettings, fontKerning, fontVariantLigatures);
var advance = GetTextAdvanceUncached(text, font, fontFeatureSettings, fontKerning, fontVariantLigatures);
s_textAdvanceCache.TryAdd(cacheKey, advance);
TrimTextAdvanceCacheIfNeeded();
return advance;
}

private float GetTextAdvanceUncached(
string text,
SkiaSharp.SKPaint paint,
SkiaSharp.SKFont font,
string? fontFeatureSettings,
string? fontKerning,
string? fontVariantLigatures)
{
if (TryCreateStableMeasurePaint(paint, out var stablePaint, out var scaleDown))
if (TryCreateStableMeasureFont(font, out var stableFont, out var scaleDown))
{
using (stablePaint)
using (stableFont)
{
if (TryShapeText(text, 0f, 0f, stablePaint, null, fontFeatureSettings, fontKerning, fontVariantLigatures, out var stableResult))
if (TryShapeText(text, 0f, 0f, stableFont, null, fontFeatureSettings, fontKerning, fontVariantLigatures, out var stableResult))
{
return stableResult.Width * scaleDown;
}

return stablePaint.MeasureText(text) * scaleDown;
return stableFont.MeasureText(text) * scaleDown;
}
}

if (TryShapeText(text, 0f, 0f, paint, null, fontFeatureSettings, fontKerning, fontVariantLigatures, out var result))
if (TryShapeText(text, 0f, 0f, font, null, fontFeatureSettings, fontKerning, fontVariantLigatures, out var result))
{
return result.Width;
}

return paint.MeasureText(text);
return font.MeasureText(text);
}

private static TextAdvanceCacheKey CreateTextAdvanceCacheKey(
string text,
SkiaSharp.SKPaint paint,
SkiaSharp.SKFont font,
string? fontFeatureSettings,
string? fontKerning,
string? fontVariantLigatures)
{
var typeface = paint.Typeface;
var typeface = font.Typeface;
return new TextAdvanceCacheKey(
text,
paint.TextSize,
paint.TextScaleX,
paint.TextSkewX,
paint.FakeBoldText,
paint.LcdRenderText,
paint.SubpixelText,
paint.TextEncoding,
font.Size,
font.ScaleX,
font.SkewX,
font.Embolden,
font.Edging == SkiaSharp.SKFontEdging.SubpixelAntialias,
font.Subpixel,
fontFeatureSettings,
fontKerning,
fontVariantLigatures,
Expand All @@ -213,22 +207,26 @@ private static void TrimTextAdvanceCacheIfNeeded()
}
}

private static bool TryCreateStableMeasurePaint(
SkiaSharp.SKPaint paint,
out SkiaSharp.SKPaint stablePaint,
private static bool TryCreateStableMeasureFont(
SkiaSharp.SKFont font,
out SkiaSharp.SKFont stableFont,
out float scaleDown)
{
stablePaint = null!;
stableFont = null!;
scaleDown = 1f;
if (paint.TextSize <= 0f || paint.TextSize >= MinimumStableTextMeasureSize)
if (font.Size <= 0f || font.Size >= MinimumStableTextMeasureSize)
{
return false;
}

var scaleUp = MinimumStableTextMeasureSize / paint.TextSize;
var scaleUp = MinimumStableTextMeasureSize / font.Size;
scaleDown = 1f / scaleUp;
stablePaint = paint.Clone();
stablePaint.TextSize = MinimumStableTextMeasureSize;
stableFont = new SkiaSharp.SKFont(font.Typeface, MinimumStableTextMeasureSize, font.ScaleX, font.SkewX)
{
Edging = font.Edging,
Subpixel = font.Subpixel,
Embolden = font.Embolden
};
return true;
}

Expand All @@ -245,8 +243,8 @@ internal bool TryShapeGlyphRun(string? text, SKPaint paint, bool? rightToLeft, o
return false;
}

using var skPaint = ToSKTextPaint(paint);
if (skPaint is null || !TryShapeText(text!, 0f, 0f, skPaint, rightToLeft, paint.FontFeatureSettings, paint.FontKerning, paint.FontVariantLigatures, out var result))
using var skFont = ToSKFont(paint);
if (skFont is null || !TryShapeText(text!, 0f, 0f, skFont, rightToLeft, paint.FontFeatureSettings, paint.FontKerning, paint.FontVariantLigatures, out var result))
{
return false;
}
Expand Down Expand Up @@ -346,13 +344,7 @@ internal bool TryGetGlyphRunPath(ShapedGlyphRun shapedRun, SKPaint paint, float
return false;
}

using var skPaint = ToSKTextPaint(paint);
if (skPaint is null)
{
return false;
}

using var font = skPaint.ToFont();
using var font = ToSKFont(paint);
if (font is null || font.Typeface is null)
{
return false;
Expand Down Expand Up @@ -382,54 +374,6 @@ internal bool TryGetGlyphRunPath(ShapedGlyphRun shapedRun, SKPaint paint, float
return !path.IsEmpty;
}

private bool TryShapeText(
string text,
float x,
float y,
SkiaSharp.SKPaint paint,
bool? rightToLeft,
out ShapedTextResult result)
{
return TryShapeText(
text,
x,
y,
paint,
rightToLeft,
fontFeatureSettings: null,
fontKerning: null,
fontVariantLigatures: null,
out result);
}

private bool TryShapeText(
string text,
float x,
float y,
SkiaSharp.SKPaint paint,
bool? rightToLeft,
string? fontFeatureSettings,
string? fontKerning,
string? fontVariantLigatures,
out ShapedTextResult result)
{
if (string.IsNullOrEmpty(text) ||
paint.Typeface is null)
{
result = default;
return false;
}

using var font = paint.ToFont();
if (font is null || font.Typeface is null)
{
result = default;
return false;
}

return TryShapeText(text, x, y, font, rightToLeft, fontFeatureSettings, fontKerning, fontVariantLigatures, out result);
}

private static bool TryShapeText(
string text,
float x,
Expand Down
Loading
Loading