@@ -76,7 +76,7 @@ typedef struct {
76
76
} af_path_t ;
77
77
78
78
typedef struct {
79
- char codepoint ;
79
+ uint16_t codepoint ;
80
80
int8_t x , y , w , h ;
81
81
int8_t advance ;
82
82
uint8_t path_count ;
@@ -106,7 +106,7 @@ typedef struct {
106
106
} af_text_metrics_t ;
107
107
108
108
bool af_load_font_file (AF_FILE file , af_face_t * face );
109
- void af_render_character (af_face_t * face , const char codepoint , af_text_metrics_t * tm );
109
+ void af_render_character (af_face_t * face , uint16_t codepoint , af_text_metrics_t * tm );
110
110
void af_render (af_face_t * face , const char * text , size_t tlen , float max_line_width , float max_height , af_text_metrics_t * tm );
111
111
pp_rect_t af_measure (af_face_t * face , const char * text , size_t tlen , float max_line_width , af_text_metrics_t * tm );
112
112
@@ -210,6 +210,33 @@ bool af_load_font_file(AF_FILE file, af_face_t *face) {
210
210
return true;
211
211
}
212
212
213
+ uint16_t get_utf8_char (const char * text , const char * end ) {
214
+ uint16_t codepoint ;
215
+ if ((* text & 0x80 ) == 0x00 ) {
216
+ codepoint = * text ; // ASCII, codepoints U+0000...U007F
217
+ }
218
+ else if ( ((* text & 0xE0 ) == 0xC0 ) && (text + 1 <= end ) && ((* (text + 1 ) & 0xC0 ) == 0x80 ) ) {
219
+ codepoint = ((uint16_t )(* text & 0x1F ) << 6 ) + (* (text + 1 ) & 0x3F ); //codepoints U+0080...U+07FF
220
+ }
221
+ else if ( ((* text & 0xF0 ) == 0xE0 ) && (text + 2 <= end ) && ((* (text + 1 ) & 0xC0 ) == 0x80 ) && ((* (text + 2 ) & 0xC0 ) == 0x80 ) ) {
222
+ codepoint = ((uint16_t )(* text & 0x0F ) << 12 ) + ((uint16_t )(* (text + 1 ) & 0x3F ) << 6 ) + (* (text + 2 ) & 0x3F ); // codepoints U+0800...U+FFFF
223
+ }
224
+ else {
225
+ codepoint = 0xFFFF ; // malformed UTF-8 sequences or unsupported codepoints starting at U+10000
226
+ }
227
+ return codepoint ;
228
+ }
229
+
230
+ uint8_t num_of_utf8_continuation_bytes (const char * text , const char * end ) {
231
+ uint8_t cont = 0 ;
232
+ for (char c = * text ; text < end ; text ++ , c = * text ) {
233
+ if ((c & 0xC0 ) == 0x80 ) {
234
+ cont ++ ;
235
+ }
236
+ }
237
+ return cont ;
238
+ }
239
+
213
240
af_glyph_t * find_glyph (af_face_t * face , char c ) {
214
241
for (int i = 0 ; i < face -> glyph_count ; i ++ ) {
215
242
if (face -> glyphs [i ].codepoint == c ) {
@@ -238,7 +265,7 @@ void af_render_glyph(af_glyph_t* glyph, af_text_metrics_t *tm) {
238
265
pp_poly_free (poly );
239
266
}
240
267
241
- void af_render_character (af_face_t * face , const char c , af_text_metrics_t * tm ) {
268
+ void af_render_character (af_face_t * face , uint16_t c , af_text_metrics_t * tm ) {
242
269
af_glyph_t * glyph = find_glyph (face , c );
243
270
if (!glyph ) {
244
271
return ;
@@ -251,14 +278,23 @@ float get_line_width(af_face_t *face, const char *text, size_t *tlen, float max_
251
278
const char * start = text ;
252
279
const char * end = text + * tlen ;
253
280
const char * last_space = nullptr ;
254
- for (char c = * text ; text < end ; text ++ , c = * text ) {
255
- af_glyph_t * glyph = find_glyph (face , c );
281
+ uint16_t utf8_char ;
282
+ while (text < end ) {
283
+ utf8_char = get_utf8_char (text , end );
284
+ text ++ ;
285
+ if (utf8_char > 0x7F ) {
286
+ text ++ ;
287
+ }
288
+ if (utf8_char > 0x7FF ) {
289
+ text ++ ;
290
+ }
291
+ af_glyph_t * glyph = find_glyph (face , utf8_char );
256
292
if (!glyph ) {
257
293
continue ;
258
294
}
259
295
260
296
float char_width ;
261
- if (c == L' ' ) {
297
+ if (utf8_char == L' ' ) {
262
298
char_width = (glyph -> advance * tm -> word_spacing ) / 100.0f ;
263
299
last_space = text ;
264
300
} else {
@@ -311,6 +347,7 @@ void af_render(af_face_t *face, const char *text, size_t tlen, float max_line_wi
311
347
312
348
float line_height = (tm -> line_height * 128.0f ) / 100.0f ;
313
349
float scale = tm -> size / 128.0f ;
350
+ uint16_t utf8_char ;
314
351
315
352
struct {
316
353
float x , y ;
@@ -337,8 +374,16 @@ void af_render(af_face_t *face, const char *text, size_t tlen, float max_line_wi
337
374
int line_width = get_line_width (face , line , & line_len , max_line_width , tm );
338
375
char * end = line + line_len ;
339
376
340
- for (char c = * line ; line < end ; line ++ , c = * line ) {
341
- af_glyph_t * glyph = find_glyph (face , c );
377
+ while (line < end ) {
378
+ utf8_char = get_utf8_char (line , end );
379
+ line ++ ;
380
+ if (utf8_char > 0x7F ) {
381
+ line ++ ;
382
+ }
383
+ if (utf8_char > 0x7FF ) {
384
+ line ++ ;
385
+ }
386
+ af_glyph_t * glyph = find_glyph (face , utf8_char );
342
387
if (!glyph ) {
343
388
continue ;
344
389
}
@@ -361,7 +406,7 @@ void af_render(af_face_t *face, const char *text, size_t tlen, float max_line_wi
361
406
362
407
af_render_glyph (glyph , tm );
363
408
364
- if (c == L' ' ) {
409
+ if (utf8_char == L' ' ) {
365
410
caret .x += (glyph -> advance * tm -> word_spacing ) / 100.0f ;
366
411
} else {
367
412
caret .x += (glyph -> advance * tm -> letter_spacing ) / 100.0f ;
0 commit comments