@@ -98,14 +98,14 @@ typedef struct {
98
98
float line_height ; // spacing between lines (%)
99
99
float letter_spacing ; // spacing between characters (%)
100
100
float word_spacing ; // spacing between words (%)
101
- af_align_t align ; // horizontal and vertical alignment
101
+ unsigned int align ; // horizontal and vertical alignment
102
102
pp_mat3_t * transform ; // arbitrary transformation
103
103
} af_text_metrics_t ;
104
104
105
105
bool af_load_font_file (AF_FILE file , af_face_t * face );
106
106
void af_render_character (af_face_t * face , const char codepoint , af_text_metrics_t * tm );
107
- void af_render (af_face_t * face , const char * text , af_text_metrics_t * tm );
108
- pp_rect_t af_measure (af_face_t * face , const char * text , af_text_metrics_t * tm );
107
+ void af_render (af_face_t * face , const char * text , size_t tlen , af_text_metrics_t * tm );
108
+ pp_rect_t af_measure (af_face_t * face , const char * text , size_t tlen , af_text_metrics_t * tm );
109
109
110
110
#ifdef AF_USE_PRETTY_POLY
111
111
#endif
@@ -240,10 +240,9 @@ void af_render_character(af_face_t *face, const char c, af_text_metrics_t *tm) {
240
240
af_render_glyph (glyph , tm );
241
241
}
242
242
243
- int get_line_width (af_face_t * face , const char * text , af_text_metrics_t * tm ) {
243
+ int get_line_width (af_face_t * face , const char * text , size_t tlen , af_text_metrics_t * tm ) {
244
244
int line_width = 0 ;
245
- char * end = strchr (text , '\n' );
246
- if (!end ) end = (char * )text + strlen (text );
245
+ char * end = (char * )text + tlen ;
247
246
for (char c = * text ; text < end ; text ++ , c = * text ) {
248
247
af_glyph_t * glyph = find_glyph (face , c );
249
248
if (!glyph ) {
@@ -259,44 +258,62 @@ int get_line_width(af_face_t *face, const char *text, af_text_metrics_t *tm) {
259
258
return line_width ;
260
259
}
261
260
262
- int get_max_line_width (af_face_t * face , const char * text , af_text_metrics_t * tm ) {
261
+ size_t line_length (const char * text , const char * end ) {
262
+ if (text >= end ) return 0 ;
263
+
264
+ char * line_ending = (char * )memchr (text , '\n' , end - text );
265
+
266
+ if (line_ending == NULL || line_ending > end ) {
267
+ line_ending = (char * )end ;
268
+ }
269
+
270
+ return line_ending - text ;
271
+ }
272
+
273
+ int get_max_line_width (af_face_t * face , const char * text , size_t tlen , af_text_metrics_t * tm ) {
263
274
int max_width = 0 ;
275
+ char * line = (char * )text ;
276
+ char * tend = line + tlen ;
264
277
265
- char * end = strchr ( text , '\n' );
266
- while (end ) {
267
- int width = get_line_width (face , text , tm );
278
+ size_t line_len = line_length ( line , tend );
279
+ while (line_len ) {
280
+ int width = get_line_width (face , line , line_len , tm );
268
281
max_width = max_width < width ? width : max_width ;
269
- text = end + 1 ;
270
- end = strchr ( text , '\n' );
282
+ line += line_len + 1 ;
283
+ line_len = line_length ( line , tend );
271
284
}
272
285
273
286
return max_width ;
274
287
}
275
288
276
289
void af_render (af_face_t * face , const char * text , size_t tlen , af_text_metrics_t * tm ) {
290
+ char * line = (char * )text ;
291
+ char * tend = line + tlen ;
292
+ size_t line_len = 0 ;
293
+
277
294
pp_mat3_t * old = pp_transform (NULL );
278
295
279
296
float line_height = (tm -> line_height * 128.0f ) / 100.0f ;
280
297
float scale = tm -> size / 128.0f ;
281
298
282
- // find maximum line length
283
- int max_line_width = get_max_line_width (face , text , tm );
284
-
285
299
struct {
286
300
float x , y ;
287
301
} caret ;
288
302
289
303
caret .x = 0 ;
290
304
caret .y = 0 ;
291
305
292
- char * done = (char * )text + tlen ;
293
- char * end = strchr (text , '\n' );
294
- if (!end ) end = done ;
306
+ // find maximum line length
307
+ int max_line_width = get_max_line_width (face , text , tlen , tm );
308
+
309
+ line_len = line_length (line , tend );
310
+
311
+ while (line_len ) {
312
+ char * end = line + line_len ;
295
313
296
- while (true) {
297
- int line_width = get_line_width (face , text , tm );
314
+ int line_width = get_line_width (face , line , line_len , tm );
298
315
299
- for (char c = * text ; text < end ; text ++ , c = * text ) {
316
+ for (char c = * line ; line < end ; line ++ , c = * line ) {
300
317
af_glyph_t * glyph = find_glyph (face , c );
301
318
if (!glyph ) {
302
319
continue ;
@@ -306,11 +323,11 @@ void af_render(af_face_t *face, const char *text, size_t tlen, af_text_metrics_t
306
323
pp_mat3_scale (& caret_transform , scale , scale );
307
324
pp_mat3_translate (& caret_transform , caret .x , caret .y );
308
325
309
- if (tm -> align == AF_H_ALIGN_CENTER ) {
326
+ if (tm -> align & AF_H_ALIGN_CENTER ) {
310
327
pp_mat3_translate (& caret_transform , (max_line_width - line_width ) / 2 , 0 );
311
328
}
312
329
313
- if (tm -> align == AF_H_ALIGN_RIGHT ) {
330
+ if (tm -> align & AF_H_ALIGN_RIGHT ) {
314
331
pp_mat3_translate (& caret_transform , (max_line_width - line_width ), 0 );
315
332
}
316
333
@@ -326,10 +343,8 @@ void af_render(af_face_t *face, const char *text, size_t tlen, af_text_metrics_t
326
343
327
344
}
328
345
329
- text = end + 1 ;
330
- if (* text == '\0' || text > done ) break ;
331
- end = strchr (text , '\n' );
332
- if (!end ) end = (char * )text + tlen ;
346
+ line += 1 ; // Skip over \n
347
+ line_len = line_length (line , tend );
333
348
334
349
caret .x = 0 ;
335
350
caret .y += line_height ;
@@ -344,26 +359,75 @@ void _af_render(af_face_t *face, const char *text, af_text_metrics_t *tm) {
344
359
af_render (face , text , strlen (text ), tm );
345
360
}
346
361
347
- pp_rect_t af_measure (af_face_t * face , const char * text , af_text_metrics_t * tm ) {
362
+ pp_rect_t af_measure (af_face_t * face , const char * text , size_t tlen , af_text_metrics_t * tm ) {
348
363
pp_rect_t result ;
349
364
bool first = true;
350
- pp_mat3_t t = * tm -> transform ;
365
+ char * line = (char * )text ;
366
+ char * tend = line + tlen ;
367
+ size_t line_len = 0 ;
368
+
369
+ float line_height = (tm -> line_height * 128.0f ) / 100.0f ;
370
+ float scale = tm -> size / 128.0f ;
371
+
372
+ struct {
373
+ float x , y ;
374
+ } caret ;
375
+
376
+ caret .x = 0 ;
377
+ caret .y = 0 ;
378
+
379
+ // find maximum line length
380
+ int max_line_width = get_max_line_width (face , text , tlen , tm );
381
+
382
+ line_len = line_length (line , tend );
383
+
384
+ while (line_len ) {
385
+ char * end = line + line_len ;
386
+
387
+ int line_width = get_line_width (face , line , line_len , tm );
388
+
389
+ for (char c = * line ; line < end ; line ++ , c = * line ) {
390
+ af_glyph_t * glyph = find_glyph (face , c );
391
+ if (!glyph ) {
392
+ continue ;
393
+ }
394
+
395
+ pp_mat3_t caret_transform = * tm -> transform ;
396
+ pp_mat3_scale (& caret_transform , scale , scale );
397
+ pp_mat3_translate (& caret_transform , caret .x , caret .y );
398
+
399
+ if (tm -> align & AF_H_ALIGN_CENTER ) {
400
+ pp_mat3_translate (& caret_transform , (max_line_width - line_width ) / 2 , 0 );
401
+ }
402
+
403
+ if (tm -> align & AF_H_ALIGN_RIGHT ) {
404
+ pp_mat3_translate (& caret_transform , (max_line_width - line_width ), 0 );
405
+ }
406
+
407
+ pp_rect_t r = {glyph -> x , glyph -> y , glyph -> x + glyph -> w , glyph -> y + glyph -> h };
408
+ //pp_rect_t r = af_glyph_bounds(glyph, tm);
409
+ r = pp_rect_transform (& r , & caret_transform );
410
+
411
+ if (first ) {
412
+ result = r ;
413
+ first = false;
414
+ } else {
415
+ result = pp_rect_merge (& result , & r );
416
+ }
417
+
418
+ if (c == L' ' ) {
419
+ caret .x += (glyph -> advance * tm -> word_spacing ) / 100.0f ;
420
+ } else {
421
+ caret .x += (glyph -> advance * tm -> letter_spacing ) / 100.0f ;
422
+ }
351
423
352
- for (size_t i = 0 ; i < strlen (text ); i ++ ) {
353
- af_glyph_t * glyph = find_glyph (face , text [i ]);
354
- if (!glyph ) {
355
- continue ;
356
- }
357
- pp_rect_t r = {glyph -> x , glyph -> y , glyph -> x + glyph -> w , glyph -> y + glyph -> h };
358
- r = pp_rect_transform (& r , & t );
359
- pp_mat3_translate (& t , glyph -> advance , 0 );
360
-
361
- if (first ) {
362
- result = r ;
363
- first = false;
364
- }else {
365
- result = pp_rect_merge (& result , & r );
366
424
}
425
+
426
+ line += 1 ; // Skip over \n
427
+ line_len = line_length (line , tend );
428
+
429
+ caret .x = 0 ;
430
+ caret .y += line_height ;
367
431
}
368
432
369
433
return result ;
0 commit comments