1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . Runtime . InteropServices ;
3
4
using System . Text ;
4
5
using HarfBuzzSharp ;
5
6
using SkiaSharp ;
@@ -20,13 +21,15 @@ partial class Inline
20
21
// makes here but it affects subpixel rendering accuracy. Performance does not seem to be affected by changing this value.
21
22
private const int FontScale = 512 ;
22
23
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 > (
25
26
( nm , wt , wh , sl ) => GetFont ( nm , wt , wh , sl ) ) ;
26
27
27
- private ( SKTypeface Typeface , Font Font ) ? _fontInfo ;
28
+ private FontDetails ? _fontInfo ;
28
29
private SKPaint ? _paint ;
29
30
31
+ internal record FontDetails ( SKTypeface Typeface , Font Font , Face Face ) ;
32
+
30
33
internal SKPaint Paint
31
34
{
32
35
get
@@ -47,7 +50,7 @@ internal SKPaint Paint
47
50
}
48
51
}
49
52
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 ) ;
51
54
52
55
internal float LineHeight
53
56
{
@@ -62,7 +65,7 @@ internal float LineHeight
62
65
63
66
internal float BelowBaselineHeight => Paint . FontMetrics . Descent ;
64
67
65
- private static ( SKTypeface Typeface , Font Font ) GetFont (
68
+ private static FontDetails GetFont (
66
69
string ? name ,
67
70
FontWeight weight ,
68
71
FontStretch stretch ,
@@ -105,18 +108,52 @@ private static (SKTypeface Typeface, Font Font) GetFont(
105
108
}
106
109
}
107
110
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 )
110
112
{
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 ) ) ;
113
123
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 ;
117
126
118
- return ( skTypeFace , hbFont ) ;
127
+ return value ;
119
128
}
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 ) ;
120
157
}
121
158
}
122
159
}
0 commit comments