sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
t1gload.c
1/****************************************************************************
2 *
3 * t1gload.c
4 *
5 * Type 1 Glyph Loader (body).
6 *
7 * Copyright (C) 1996-2025 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
19#include "t1gload.h"
23#include <freetype/ftoutln.h>
26#include <freetype/ftdriver.h>
27
28#include "t1errors.h"
29
30
31 /**************************************************************************
32 *
33 * The macro FT_COMPONENT is used in trace mode. It is an implicit
34 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
35 * messages during execution.
36 */
37#undef FT_COMPONENT
38#define FT_COMPONENT t1gload
39
40
41 static FT_Error
42 T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder,
43 FT_UInt glyph_index,
44 FT_Data* char_string,
45 FT_Bool* force_scaling )
46 {
47 T1_Face face = (T1_Face)decoder->builder.face;
48 T1_Font type1 = &face->type1;
49 FT_Error error = FT_Err_Ok;
50
51 PSAux_Service psaux = (PSAux_Service)face->psaux;
52 const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs;
53 PS_Decoder psdecoder;
54
55#ifdef FT_CONFIG_OPTION_INCREMENTAL
56 FT_Incremental_InterfaceRec *inc =
57 face->root.internal->incremental_interface;
58#endif
59
60#ifdef T1_CONFIG_OPTION_OLD_ENGINE
61 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face );
62#endif
63
64
65 decoder->font_matrix = type1->font_matrix;
66 decoder->font_offset = type1->font_offset;
67
68#ifdef FT_CONFIG_OPTION_INCREMENTAL
69
70 /* For incremental fonts get the character data using the */
71 /* callback function. */
72 if ( inc )
73 {
74 /* So `free_glyph_data` knows whether to free it. */
75 char_string->pointer = NULL;
76
77 error = inc->funcs->get_glyph_data( inc->object,
78 glyph_index, char_string );
79 }
80 else
81
82#endif /* FT_CONFIG_OPTION_INCREMENTAL */
83
84 /* For ordinary fonts get the character data stored in the face record. */
85 {
86 char_string->pointer = type1->charstrings[glyph_index];
87 char_string->length = type1->charstrings_len[glyph_index];
88 }
89
90 if ( !error )
91 {
92 /* choose which renderer to use */
93#ifdef T1_CONFIG_OPTION_OLD_ENGINE
94 if ( driver->hinting_engine == FT_HINTING_FREETYPE ||
95 decoder->builder.metrics_only )
96 error = decoder_funcs->parse_charstrings_old(
97 decoder,
98 (FT_Byte*)char_string->pointer,
99 (FT_UInt)char_string->length );
100#else
101 if ( decoder->builder.metrics_only )
102 error = decoder_funcs->parse_metrics(
103 decoder,
104 (FT_Byte*)char_string->pointer,
105 (FT_UInt)char_string->length );
106#endif
107 else
108 {
109 CFF_SubFontRec subfont;
110
111
112 psaux->ps_decoder_init( &psdecoder, decoder, TRUE );
113
114 psaux->t1_make_subfont( FT_FACE( face ),
115 &face->type1.private_dict, &subfont );
116 psdecoder.current_subfont = &subfont;
117
118 error = decoder_funcs->parse_charstrings(
119 &psdecoder,
120 (FT_Byte*)char_string->pointer,
121 (FT_ULong)char_string->length );
122
123 /* Adobe's engine uses 16.16 numbers everywhere; */
124 /* as a consequence, glyphs larger than 2000ppem get rejected */
125 if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
126 {
127 /* this time, we retry unhinted and scale up the glyph later on */
128 /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
129 /* 0x400 for both `x_scale' and `y_scale' in this case) */
130 ((T1_GlyphSlot)decoder->builder.glyph)->hint = FALSE;
131
132 *force_scaling = TRUE;
133
134 error = decoder_funcs->parse_charstrings(
135 &psdecoder,
136 (FT_Byte*)char_string->pointer,
137 (FT_ULong)char_string->length );
138 }
139 }
140 }
141
142#ifdef FT_CONFIG_OPTION_INCREMENTAL
143
144 /* Incremental fonts can optionally override the metrics. */
145 if ( !error && inc && inc->funcs->get_glyph_metrics )
146 {
147 FT_Incremental_MetricsRec metrics;
148
149
150 metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x );
151 metrics.bearing_y = 0;
152 metrics.advance = FIXED_TO_INT( decoder->builder.advance.x );
153 metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y );
154
155 error = inc->funcs->get_glyph_metrics( inc->object,
156 glyph_index, FALSE, &metrics );
157
158 decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x );
159 decoder->builder.advance.x = INT_TO_FIXED( metrics.advance );
160 decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v );
161 }
162
163 if ( error && inc )
164 inc->funcs->free_glyph_data( inc->object, char_string );
165
166#endif /* FT_CONFIG_OPTION_INCREMENTAL */
167
168 return error;
169 }
170
171
172 FT_CALLBACK_DEF( FT_Error )
173 T1_Parse_Glyph( T1_Decoder decoder,
174 FT_UInt glyph_index )
175 {
176 FT_Data glyph_data;
177 FT_Bool force_scaling = FALSE;
178 FT_Error error = T1_Parse_Glyph_And_Get_Char_String(
179 decoder, glyph_index, &glyph_data,
180 &force_scaling );
181
182
183#ifdef FT_CONFIG_OPTION_INCREMENTAL
184
185 if ( !error )
186 {
187 T1_Face face = (T1_Face)decoder->builder.face;
188
189
190 if ( face->root.internal->incremental_interface )
191 face->root.internal->incremental_interface->funcs->free_glyph_data(
192 face->root.internal->incremental_interface->object,
193 &glyph_data );
194 }
195
196#endif /* FT_CONFIG_OPTION_INCREMENTAL */
197
198 return error;
199 }
200
201
202 /*************************************************************************/
203 /*************************************************************************/
204 /*************************************************************************/
205 /********** *********/
206 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
207 /********** *********/
208 /********** The following code is in charge of computing *********/
209 /********** the maximum advance width of the font. It *********/
210 /********** quickly processes each glyph charstring to *********/
211 /********** extract the value from either a `sbw' or `seac' *********/
212 /********** operator. *********/
213 /********** *********/
214 /*************************************************************************/
215 /*************************************************************************/
216 /*************************************************************************/
217
218
219 FT_LOCAL_DEF( FT_Error )
220 T1_Compute_Max_Advance( T1_Face face,
221 FT_Pos* max_advance )
222 {
223 FT_Error error;
224 T1_DecoderRec decoder;
225 FT_Int glyph_index;
226 T1_Font type1 = &face->type1;
227 PSAux_Service psaux = (PSAux_Service)face->psaux;
228
229
230 FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );
231
232 *max_advance = 0;
233
234 /* initialize load decoder */
235 error = psaux->t1_decoder_funcs->init( &decoder,
236 (FT_Face)face,
237 0, /* size */
238 0, /* glyph slot */
239 (FT_Byte**)type1->glyph_names,
240 face->blend,
241 0,
242 FT_RENDER_MODE_NORMAL,
243 T1_Parse_Glyph );
244 if ( error )
245 return error;
246
247 decoder.builder.metrics_only = 1;
248 decoder.builder.load_points = 0;
249
250 decoder.num_subrs = type1->num_subrs;
251 decoder.subrs = type1->subrs;
252 decoder.subrs_len = type1->subrs_len;
253 decoder.subrs_hash = type1->subrs_hash;
254
255 decoder.buildchar = face->buildchar;
256 decoder.len_buildchar = face->len_buildchar;
257
258 *max_advance = 0;
259
260 FT_TRACE6(( "T1_Compute_Max_Advance:\n" ));
261
262 /* for each glyph, parse the glyph charstring and extract */
263 /* the advance width */
264 for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
265 {
266 /* now get load the unscaled outline */
267 (void)T1_Parse_Glyph( &decoder, (FT_UInt)glyph_index );
268 if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance )
269 *max_advance = decoder.builder.advance.x;
270
271 /* ignore the error if one occurred - skip to next glyph */
272 }
273
274 FT_TRACE6(( "T1_Compute_Max_Advance: max advance: %f\n",
275 (double)*max_advance / 65536 ));
276
277 psaux->t1_decoder_funcs->done( &decoder );
278
279 return FT_Err_Ok;
280 }
281
282
283 FT_LOCAL_DEF( FT_Error )
284 T1_Get_Advances( FT_Face t1face, /* T1_Face */
285 FT_UInt first,
286 FT_UInt count,
287 FT_Int32 load_flags,
288 FT_Fixed* advances )
289 {
290 T1_Face face = (T1_Face)t1face;
291 T1_DecoderRec decoder;
292 T1_Font type1 = &face->type1;
293 PSAux_Service psaux = (PSAux_Service)face->psaux;
294 FT_UInt nn;
295 FT_Error error;
296
297
298 FT_TRACE5(( "T1_Get_Advances:\n" ));
299
300 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
301 {
302 for ( nn = 0; nn < count; nn++ )
303 {
304 advances[nn] = 0;
305
306 FT_TRACE5(( " idx %u: advance height 0 font units\n",
307 first + nn ));
308 }
309
310 return FT_Err_Ok;
311 }
312
313 error = psaux->t1_decoder_funcs->init( &decoder,
314 (FT_Face)face,
315 0, /* size */
316 0, /* glyph slot */
317 (FT_Byte**)type1->glyph_names,
318 face->blend,
319 0,
320 FT_RENDER_MODE_NORMAL,
321 T1_Parse_Glyph );
322 if ( error )
323 return error;
324
325 decoder.builder.metrics_only = 1;
326 decoder.builder.load_points = 0;
327
328 decoder.num_subrs = type1->num_subrs;
329 decoder.subrs = type1->subrs;
330 decoder.subrs_len = type1->subrs_len;
331 decoder.subrs_hash = type1->subrs_hash;
332
333 decoder.buildchar = face->buildchar;
334 decoder.len_buildchar = face->len_buildchar;
335
336 for ( nn = 0; nn < count; nn++ )
337 {
338 error = T1_Parse_Glyph( &decoder, first + nn );
339 if ( !error )
340 advances[nn] = FIXED_TO_INT( decoder.builder.advance.x );
341 else
342 advances[nn] = 0;
343
344 FT_TRACE5(( " idx %u: advance width %ld font unit%s\n",
345 first + nn,
346 advances[nn],
347 advances[nn] == 1 ? "" : "s" ));
348 }
349
350 return FT_Err_Ok;
351 }
352
353
354 FT_LOCAL_DEF( FT_Error )
355 T1_Load_Glyph( FT_GlyphSlot t1glyph, /* T1_GlyphSlot */
356 FT_Size t1size, /* T1_Size */
357 FT_UInt glyph_index,
358 FT_Int32 load_flags )
359 {
360 T1_GlyphSlot glyph = (T1_GlyphSlot)t1glyph;
361 FT_Error error;
362 T1_DecoderRec decoder;
363 T1_Face face = (T1_Face)t1glyph->face;
364 FT_Bool hinting;
365 FT_Bool scaled;
366 FT_Bool force_scaling = FALSE;
367 T1_Font type1 = &face->type1;
368 PSAux_Service psaux = (PSAux_Service)face->psaux;
369 const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs;
370
371 FT_Matrix font_matrix;
372 FT_Vector font_offset;
373 FT_Data glyph_data;
374 FT_Bool must_finish_decoder = FALSE;
375#ifdef FT_CONFIG_OPTION_INCREMENTAL
376 FT_Bool glyph_data_loaded = 0;
377#endif
378
379
380#ifdef FT_CONFIG_OPTION_INCREMENTAL
381 if ( glyph_index >= (FT_UInt)face->root.num_glyphs &&
382 !face->root.internal->incremental_interface )
383#else
384 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
385#endif /* FT_CONFIG_OPTION_INCREMENTAL */
386 {
387 error = FT_THROW( Invalid_Argument );
388 goto Exit;
389 }
390
391 FT_TRACE1(( "T1_Load_Glyph: glyph index %u\n", glyph_index ));
392
393 FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );
394
395 if ( load_flags & FT_LOAD_NO_RECURSE )
396 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
397
398 if ( t1size )
399 {
400 glyph->x_scale = t1size->metrics.x_scale;
401 glyph->y_scale = t1size->metrics.y_scale;
402 }
403 else
404 {
405 glyph->x_scale = 0x10000L;
406 glyph->y_scale = 0x10000L;
407 }
408
409 hinting = FT_BOOL( !( load_flags & FT_LOAD_NO_SCALE ) &&
410 !( load_flags & FT_LOAD_NO_HINTING ) );
411 scaled = FT_BOOL( !( load_flags & FT_LOAD_NO_SCALE ) );
412
413 glyph->hint = hinting;
414 glyph->scaled = scaled;
415
416 error = decoder_funcs->init( &decoder,
417 t1glyph->face,
418 t1size,
419 t1glyph,
420 (FT_Byte**)type1->glyph_names,
421 face->blend,
422 hinting,
423 FT_LOAD_TARGET_MODE( load_flags ),
424 T1_Parse_Glyph );
425 if ( error )
426 goto Exit;
427
428 must_finish_decoder = TRUE;
429
430 decoder.builder.no_recurse = FT_BOOL( load_flags & FT_LOAD_NO_RECURSE );
431
432 decoder.num_subrs = type1->num_subrs;
433 decoder.subrs = type1->subrs;
434 decoder.subrs_len = type1->subrs_len;
435 decoder.subrs_hash = type1->subrs_hash;
436
437 decoder.buildchar = face->buildchar;
438 decoder.len_buildchar = face->len_buildchar;
439
440 /* now load the unscaled outline */
441 error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index,
442 &glyph_data,
443 &force_scaling );
444 if ( error )
445 goto Exit;
446#ifdef FT_CONFIG_OPTION_INCREMENTAL
447 glyph_data_loaded = 1;
448#endif
449
450 hinting = glyph->hint;
451 font_matrix = decoder.font_matrix;
452 font_offset = decoder.font_offset;
453
454 /* save new glyph tables */
455 decoder_funcs->done( &decoder );
456
457 must_finish_decoder = FALSE;
458
459 if ( !error )
460 {
461 /* now, set the metrics -- this is rather simple, as */
462 /* the left side bearing is the xMin, and the top side */
463 /* bearing the yMax; for composite glyphs, return only */
464 /* left side bearing and advance width */
465 if ( load_flags & FT_LOAD_NO_RECURSE )
466 {
467 FT_Slot_Internal internal = t1glyph->internal;
468
469
470 t1glyph->metrics.horiBearingX =
471 FIXED_TO_INT( decoder.builder.left_bearing.x );
472 t1glyph->metrics.horiAdvance =
473 FIXED_TO_INT( decoder.builder.advance.x );
474
475 internal->glyph_matrix = font_matrix;
476 internal->glyph_delta = font_offset;
477 internal->glyph_transformed = 1;
478 }
479 else
480 {
481 FT_BBox cbox;
482 FT_Glyph_Metrics* metrics = &t1glyph->metrics;
483
484
485 t1glyph->format = FT_GLYPH_FORMAT_OUTLINE;
486
487 t1glyph->outline.flags &= FT_OUTLINE_OWNER;
488 t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL;
489 if ( t1size && t1size->metrics.y_ppem < 24 )
490 t1glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
491
492 /* copy the _unscaled_ advance width */
493 metrics->horiAdvance =
494 FIXED_TO_INT( decoder.builder.advance.x );
495 t1glyph->linearHoriAdvance =
496 FIXED_TO_INT( decoder.builder.advance.x );
497 t1glyph->internal->glyph_transformed = 0;
498
499 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
500 {
501 /* make up vertical ones */
502 metrics->vertAdvance = ( face->type1.font_bbox.yMax -
503 face->type1.font_bbox.yMin ) >> 16;
504 t1glyph->linearVertAdvance = metrics->vertAdvance;
505 }
506 else
507 {
508 metrics->vertAdvance =
509 FIXED_TO_INT( decoder.builder.advance.y );
510 t1glyph->linearVertAdvance =
511 FIXED_TO_INT( decoder.builder.advance.y );
512 }
513
514#if 1
515 /* apply the font matrix, if any */
516 if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L ||
517 font_matrix.xy != 0 || font_matrix.yx != 0 )
518 {
519 FT_Outline_Transform( &t1glyph->outline, &font_matrix );
520
521 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
522 font_matrix.xx );
523 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance,
524 font_matrix.yy );
525 }
526
527 if ( font_offset.x || font_offset.y )
528 {
529 FT_Outline_Translate( &t1glyph->outline,
530 font_offset.x,
531 font_offset.y );
532
533 metrics->horiAdvance += font_offset.x;
534 metrics->vertAdvance += font_offset.y;
535 }
536#endif
537
538 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
539 {
540 /* scale the outline and the metrics */
541 FT_Int n;
542 FT_Outline* cur = decoder.builder.base;
543 FT_Vector* vec = cur->points;
544 FT_Fixed x_scale = glyph->x_scale;
545 FT_Fixed y_scale = glyph->y_scale;
546
547
548 /* First of all, scale the points, if we are not hinting */
549 if ( !hinting || !decoder.builder.hints_funcs )
550 for ( n = cur->n_points; n > 0; n--, vec++ )
551 {
552 vec->x = FT_MulFix( vec->x, x_scale );
553 vec->y = FT_MulFix( vec->y, y_scale );
554 }
555
556 /* Then scale the metrics */
557 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
558 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
559 }
560
561 /* compute the other metrics */
562 FT_Outline_Get_CBox( &t1glyph->outline, &cbox );
563
564 metrics->width = cbox.xMax - cbox.xMin;
565 metrics->height = cbox.yMax - cbox.yMin;
566
567 metrics->horiBearingX = cbox.xMin;
568 metrics->horiBearingY = cbox.yMax;
569
570 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
571 {
572 /* make up vertical ones */
573 ft_synthesize_vertical_metrics( metrics,
574 metrics->vertAdvance );
575 }
576 }
577
578 /* Set control data to the glyph charstrings. Note that this is */
579 /* _not_ zero-terminated. */
580 t1glyph->control_data = (FT_Byte*)glyph_data.pointer;
581 t1glyph->control_len = glyph_data.length;
582 }
583
584
585 Exit:
586
587#ifdef FT_CONFIG_OPTION_INCREMENTAL
588 if ( glyph_data_loaded && face->root.internal->incremental_interface )
589 {
590 face->root.internal->incremental_interface->funcs->free_glyph_data(
591 face->root.internal->incremental_interface->object,
592 &glyph_data );
593
594 /* Set the control data to null - it is no longer available if */
595 /* loaded incrementally. */
596 t1glyph->control_data = NULL;
597 t1glyph->control_len = 0;
598 }
599#endif
600
601 if ( must_finish_decoder )
602 decoder_funcs->done( &decoder );
603
604 return error;
605 }
606
607
608/* END */