@@ -102,6 +102,12 @@ public float GetHeight(float scale)
102
102
// }
103
103
}
104
104
105
+ public record struct GlyphCacheHash
106
+ {
107
+ public char Character ;
108
+ public float ResolutionMultiplier ;
109
+ }
110
+
105
111
public class FontAtlas
106
112
{
107
113
public required ScaledFont Font ;
@@ -110,11 +116,18 @@ public class FontAtlas
110
116
111
117
public GpuTexture GpuTexture ;
112
118
113
- public required LRUCache < int , AtlasGlyphInfo > Table ;
119
+ public required LRUCache < GlyphCacheHash , AtlasGlyphInfo > Table ;
120
+
121
+ private nint GlyphTempMemory ;
122
+
123
+ public FontAtlas ( )
124
+ {
125
+ GlyphTempMemory = Marshal . AllocHGlobal ( 100 * 100 ) ;
126
+ }
114
127
115
128
public unsafe AtlasGlyphInfo FindGlyphEntry ( char c , float resolutionMultiplier )
116
129
{
117
- var hash = HashCode . Combine ( c , resolutionMultiplier ) ;
130
+ var hash = new GlyphCacheHash { Character = c , ResolutionMultiplier = resolutionMultiplier } ;
118
131
119
132
if ( Table . TryGet ( hash , out var entry ) )
120
133
{
@@ -123,14 +136,23 @@ public unsafe AtlasGlyphInfo FindGlyphEntry(char c, float resolutionMultiplier)
123
136
124
137
entry = Table . GetLeastUsed ( ) ;
125
138
126
- int width = 0 ;
127
- int height = 0 ;
128
- int xOff = 0 ;
129
- int yOff = 0 ;
139
+ int ix0 = 0 ;
140
+ int iy0 = 0 ;
141
+ int ix1 = 0 ;
142
+ int iy1 = 0 ;
130
143
131
- var bitmap = StbTrueType . stbtt_GetCodepointBitmap ( Font . Font . FontInfo , 0 , Font . Scale * resolutionMultiplier , c ,
132
- & width , & height , & xOff , & yOff ) ;
133
- var bitmapSpan = new Span < byte > ( bitmap , width * height ) ;
144
+ var scale = Font . Scale * resolutionMultiplier ;
145
+ StbTrueType . stbtt_GetCodepointBitmapBox ( Font . Font . FontInfo , c , scale , scale , & ix0 , & iy0 , & ix1 , & iy1 ) ;
146
+ StbTrueType . stbtt_MakeCodepointBitmap ( Font . Font . FontInfo , ( byte * ) GlyphTempMemory , 100 , 100 , 100 , scale , scale , c ) ;
147
+
148
+ int width = ix1 - ix0 ;
149
+ int height = iy1 - iy0 ;
150
+ int xOff = ix0 ;
151
+ int yOff = iy0 ;
152
+
153
+ var bitmapSpan = new Span < byte > ( ( void * ) GlyphTempMemory , 100 * 100 ) ;
154
+
155
+ Console . WriteLine ( $ "glyph cache miss: { c } :{ resolutionMultiplier } , inserting into slot { entry . SlotNumber } ") ;
134
156
135
157
for ( var i = 0 ; i < bitmapSpan . Length ; i ++ ) //correct upwards for clearer text, not sure why we need to do it...
136
158
{
@@ -143,18 +165,17 @@ public unsafe AtlasGlyphInfo FindGlyphEntry(char c, float resolutionMultiplier)
143
165
144
166
GpuTexture . Gl . BindTexture ( TextureTarget . Texture2D , GpuTexture . TextureId ) ;
145
167
GpuTexture . Gl . PixelStore ( PixelStoreParameter . UnpackAlignment , 1 ) ;
146
- GpuTexture . Gl . TexSubImage2D ( TextureTarget . Texture2D , 0 , entry . AtlasX , entry . AtlasY , ( uint ) width , ( uint ) height , PixelFormat . Red , PixelType . UnsignedByte , ( void * ) bitmap ) ;
147
-
148
- Console . WriteLine ( $ "Uploading { c } at { entry . AtlasX } ,{ entry . AtlasY } ") ;
168
+ GpuTexture . Gl . TexSubImage2D ( TextureTarget . Texture2D , 0 , entry . AtlasX , entry . AtlasY , ( uint ) 100 , ( uint ) 100 , PixelFormat . Red , PixelType . UnsignedByte , ( void * ) GlyphTempMemory ) ;
149
169
150
170
var info = new AtlasGlyphInfo
151
171
{
152
- Height = height / resolutionMultiplier ,
153
- Width = width / resolutionMultiplier ,
154
- XOff = xOff / resolutionMultiplier ,
155
- YOff = yOff / resolutionMultiplier ,
172
+ Height = ( float ) height / resolutionMultiplier ,
173
+ Width = ( float ) width / resolutionMultiplier ,
174
+ XOff = ( float ) xOff / resolutionMultiplier ,
175
+ YOff = ( float ) yOff / resolutionMultiplier ,
156
176
AtlasX = entry . AtlasX ,
157
177
AtlasY = entry . AtlasY ,
178
+ SlotNumber = entry . SlotNumber ,
158
179
AtlasWidth = width ,
159
180
AtlasHeight = height ,
160
181
// GlyphBoundingBox = bb,
@@ -187,6 +208,7 @@ public struct AtlasGlyphInfo
187
208
public required float Height ; //height of the glyph
188
209
public required float XOff ;
189
210
public required float YOff ;
211
+ public required int SlotNumber ;
190
212
191
213
public int AdvanceWidth => ( int ) ( FontGlyphInfo . UnscaledAdvanceWidth * Scale ) ;
192
214
public int LeftSideBearing => ( int ) ( FontGlyphInfo . UnscaledLeftSideBearing * Scale ) ;
@@ -232,17 +254,22 @@ public static unsafe Font LoadFont(string name)
232
254
233
255
public static FontAtlas CreateFontAtlas ( ScaledFont scaledFont )
234
256
{
235
- var table = new LRUCache < int , AtlasGlyphInfo > ( 10 * 10 ) ;
257
+ var table = new LRUCache < GlyphCacheHash , AtlasGlyphInfo > ( 10 * 10 ) ;
258
+
259
+ int slotNumber = 0 ;
236
260
237
- for ( int i = 1 ; i < 11 ; i ++ )
261
+ for ( int i = 0 ; i < 10 ; i ++ )
238
262
{
239
- for ( int j = 1 ; j < 11 ; j ++ )
263
+ for ( int j = 0 ; j < 10 ; j ++ )
240
264
{
241
- table . Add ( ( int . MaxValue - i - 100 * j ) . GetHashCode ( ) , default ( AtlasGlyphInfo ) with
265
+ table . Add ( new GlyphCacheHash { Character = ( char ) ( i * 10 + j ) , ResolutionMultiplier = i * j } , default ( AtlasGlyphInfo ) with
242
266
{
243
267
AtlasX = i * 100 ,
244
268
AtlasY = j * 100 ,
269
+ SlotNumber = slotNumber
245
270
} ) ;
271
+
272
+ slotNumber ++ ;
246
273
}
247
274
}
248
275
0 commit comments