Skip to content

Commit cc0b352

Browse files
committed
fix: Adjust harbuzz initialization to avoid Gtk3 interference
1 parent 8d19ef0 commit cc0b352

File tree

2 files changed

+52
-13
lines changed

2 files changed

+52
-13
lines changed

src/Uno.UI.Runtime.Skia.Gtk/GtkHost.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ public GtkHost(Func<WUX.Application> appBuilder)
8181

8282
public void Run()
8383
{
84+
Windows.UI.Xaml.Documents.Inline.ApplyHarfbuzzWorkaround();
85+
8486
Gtk.Application.Init();
8587
SetupTheme();
8688

src/Uno.UI/UI/Xaml/Documents/Inline.skia.cs

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Runtime.InteropServices;
34
using System.Text;
45
using HarfBuzzSharp;
56
using SkiaSharp;
@@ -20,13 +21,15 @@ partial class Inline
2021
// makes here but it affects subpixel rendering accuracy. Performance does not seem to be affected by changing this value.
2122
private const int FontScale = 512;
2223

23-
private static readonly Func<string?, FontWeight, FontStretch, FontStyle, (SKTypeface, Font)> _getFont =
24-
Funcs.CreateMemoized<string?, FontWeight, FontStretch, FontStyle, (SKTypeface, Font)>(
24+
private static readonly Func<string?, FontWeight, FontStretch, FontStyle, FontDetails> _getFont =
25+
Funcs.CreateMemoized<string?, FontWeight, FontStretch, FontStyle, FontDetails>(
2526
(nm, wt, wh, sl) => GetFont(nm, wt, wh, sl));
2627

27-
private (SKTypeface Typeface, Font Font)? _fontInfo;
28+
private FontDetails? _fontInfo;
2829
private SKPaint? _paint;
2930

31+
internal record FontDetails(SKTypeface Typeface, Font Font, Face Face);
32+
3033
internal SKPaint Paint
3134
{
3235
get
@@ -47,7 +50,7 @@ internal SKPaint Paint
4750
}
4851
}
4952

50-
internal (SKTypeface Typeface, Font Font) FontInfo => _fontInfo ??= _getFont(FontFamily?.Source, FontWeight, FontStretch, FontStyle);
53+
internal FontDetails FontInfo => _fontInfo ??= _getFont(FontFamily?.Source, FontWeight, FontStretch, FontStyle);
5154

5255
internal float LineHeight
5356
{
@@ -62,7 +65,7 @@ internal float LineHeight
6265

6366
internal float BelowBaselineHeight => Paint.FontMetrics.Descent;
6467

65-
private static (SKTypeface Typeface, Font Font) GetFont(
68+
private static FontDetails GetFont(
6669
string? name,
6770
FontWeight weight,
6871
FontStretch stretch,
@@ -105,18 +108,52 @@ private static (SKTypeface Typeface, Font Font) GetFont(
105108
}
106109
}
107110

108-
using (var hbBlob = skTypeFace.OpenStream(out int index).ToHarfBuzzBlob())
109-
using (var hbFace = new Face(hbBlob, index))
111+
Blob? GetTable(Face face, Tag tag)
110112
{
111-
hbFace.Index = index;
112-
hbFace.UnitsPerEm = skTypeFace.UnitsPerEm;
113+
var size = skTypeFace.GetTableSize(tag);
114+
115+
if(size == 0)
116+
{
117+
return null;
118+
}
119+
120+
var data = Marshal.AllocCoTaskMem(size);
121+
122+
var releaseDelegate = new ReleaseDelegate(() => Marshal.FreeCoTaskMem(data));
113123

114-
var hbFont = new Font(hbFace);
115-
hbFont.SetScale(FontScale, FontScale);
116-
hbFont.SetFunctionsOpenType();
124+
var value = skTypeFace.TryGetTableData(tag, 0, size, data) ?
125+
new Blob(data, size, MemoryMode.Writeable, releaseDelegate) : null;
117126

118-
return (skTypeFace, hbFont);
127+
return value;
119128
}
129+
130+
var hbFace = new Face(GetTable);
131+
132+
hbFace.UnitsPerEm = skTypeFace.UnitsPerEm;
133+
134+
var hbFont = new Font(hbFace);
135+
hbFont.SetScale(FontScale, FontScale);
136+
hbFont.SetFunctionsOpenType();
137+
138+
return new(skTypeFace, hbFont, hbFace);
139+
}
140+
141+
/// <summary>
142+
/// Apply a workaround for https://github.com/mono/SkiaSharp/issues/2113
143+
/// </summary>
144+
public static void ApplyHarfbuzzWorkaround()
145+
{
146+
// HarfBuzzSharp.Font.SetFunctionsOpenType() needs to be initialized before GtkSharp is initialized
147+
// to avoid libHarfBuzzSharp's own static library to hook onto
148+
// the system implementation of libHarfBuzzSharp.
149+
var font = GetFont(null, FontWeights.Normal, FontStretch.Normal, FontStyle.Normal);
150+
151+
using HarfBuzzSharp.Buffer buffer = new();
152+
buffer.ContentType = ContentType.Unicode;
153+
buffer.GuessSegmentProperties();
154+
155+
// Force a font loading by shaping a buffer.
156+
font.Font.Shape(buffer);
120157
}
121158
}
122159
}

0 commit comments

Comments
 (0)