1 /***************************************************************************/
5 /* OpenType Glyph Loader (body). */
7 /* Copyright 1996-2018 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_STREAM_H
22 #include FT_INTERNAL_SFNT_H
23 #include FT_INTERNAL_CALC_H
24 #include FT_INTERNAL_POSTSCRIPT_AUX_H
34 /*************************************************************************/
36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
38 /* messages during execution. */
41 #define FT_COMPONENT trace_cffgload
44 FT_LOCAL_DEF( FT_Error
)
45 cff_get_glyph_data( TT_Face face
,
50 #ifdef FT_CONFIG_OPTION_INCREMENTAL
51 /* For incremental fonts get the character data using the */
52 /* callback function. */
53 if ( face
->root
.internal
->incremental_interface
)
57 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_data(
58 face
->root
.internal
->incremental_interface
->object
,
62 *pointer
= (FT_Byte
*)data
.pointer
;
63 *length
= (FT_ULong
)data
.length
;
68 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
71 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
74 return cff_index_access_element( &cff
->charstrings_index
, glyph_index
,
81 cff_free_glyph_data( TT_Face face
,
85 #ifndef FT_CONFIG_OPTION_INCREMENTAL
89 #ifdef FT_CONFIG_OPTION_INCREMENTAL
90 /* For incremental fonts get the character data using the */
91 /* callback function. */
92 if ( face
->root
.internal
->incremental_interface
)
97 data
.pointer
= *pointer
;
98 data
.length
= (FT_Int
)length
;
100 face
->root
.internal
->incremental_interface
->funcs
->free_glyph_data(
101 face
->root
.internal
->incremental_interface
->object
, &data
);
104 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
107 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
110 cff_index_forget_element( &cff
->charstrings_index
, pointer
);
115 /*************************************************************************/
116 /*************************************************************************/
117 /*************************************************************************/
118 /********** *********/
119 /********** *********/
120 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
121 /********** *********/
122 /********** The following code is in charge of computing *********/
123 /********** the maximum advance width of the font. It *********/
124 /********** quickly processes each glyph charstring to *********/
125 /********** extract the value from either a `sbw' or `seac' *********/
126 /********** operator. *********/
127 /********** *********/
128 /*************************************************************************/
129 /*************************************************************************/
130 /*************************************************************************/
133 #if 0 /* unused until we support pure CFF fonts */
136 FT_LOCAL_DEF( FT_Error
)
137 cff_compute_max_advance( TT_Face face
,
138 FT_Int
* max_advance
)
140 FT_Error error
= FT_Err_Ok
;
143 CFF_Font cff
= (CFF_Font
)face
->other
;
145 PSAux_Service psaux
= (PSAux_Service
)face
->psaux
;
146 const CFF_Decoder_Funcs decoder_funcs
= psaux
->cff_decoder_funcs
;
151 /* Initialize load decoder */
152 decoder_funcs
->init( &decoder
, face
, 0, 0, 0, 0, 0, 0 );
154 decoder
.builder
.metrics_only
= 1;
155 decoder
.builder
.load_points
= 0;
157 /* For each glyph, parse the glyph charstring and extract */
158 /* the advance width. */
159 for ( glyph_index
= 0; glyph_index
< face
->root
.num_glyphs
;
163 FT_ULong charstring_len
;
166 /* now get load the unscaled outline */
167 error
= cff_get_glyph_data( face
, glyph_index
,
168 &charstring
, &charstring_len
);
171 error
= decoder_funcs
->prepare( &decoder
, size
, glyph_index
);
173 error
= decoder_funcs
->parse_charstrings_old( &decoder
,
178 cff_free_glyph_data( face
, &charstring
, &charstring_len
);
181 /* ignore the error if one has occurred -- skip to next glyph */
185 *max_advance
= decoder
.builder
.advance
.x
;
194 FT_LOCAL_DEF( FT_Error
)
195 cff_slot_load( CFF_GlyphSlot glyph
,
198 FT_Int32 load_flags
)
202 PS_Decoder psdecoder
;
203 TT_Face face
= (TT_Face
)glyph
->root
.face
;
204 FT_Bool hinting
, scaled
, force_scaling
;
205 CFF_Font cff
= (CFF_Font
)face
->extra
.data
;
207 PSAux_Service psaux
= (PSAux_Service
)face
->psaux
;
208 const CFF_Decoder_Funcs decoder_funcs
= psaux
->cff_decoder_funcs
;
210 FT_Matrix font_matrix
;
211 FT_Vector font_offset
;
214 force_scaling
= FALSE
;
216 /* in a CID-keyed font, consider `glyph_index' as a CID and map */
217 /* it immediately to the real glyph_index -- if it isn't a */
218 /* subsetted font, glyph_indices and CIDs are identical, though */
219 if ( cff
->top_font
.font_dict
.cid_registry
!= 0xFFFFU
&&
222 /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */
223 if ( glyph_index
!= 0 )
225 glyph_index
= cff_charset_cid_to_gindex( &cff
->charset
,
227 if ( glyph_index
== 0 )
228 return FT_THROW( Invalid_Argument
);
231 else if ( glyph_index
>= cff
->num_glyphs
)
232 return FT_THROW( Invalid_Argument
);
234 if ( load_flags
& FT_LOAD_NO_RECURSE
)
235 load_flags
|= FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
237 glyph
->x_scale
= 0x10000L
;
238 glyph
->y_scale
= 0x10000L
;
241 glyph
->x_scale
= size
->root
.metrics
.x_scale
;
242 glyph
->y_scale
= size
->root
.metrics
.y_scale
;
245 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
247 /* try to load embedded bitmap if any */
249 /* XXX: The convention should be emphasized in */
250 /* the documents because it can be confusing. */
253 CFF_Face cff_face
= (CFF_Face
)size
->root
.face
;
254 SFNT_Service sfnt
= (SFNT_Service
)cff_face
->sfnt
;
255 FT_Stream stream
= cff_face
->root
.stream
;
258 if ( size
->strike_index
!= 0xFFFFFFFFUL
&&
260 ( load_flags
& FT_LOAD_NO_BITMAP
) == 0 )
262 TT_SBit_MetricsRec metrics
;
265 error
= sfnt
->load_sbit_image( face
,
275 FT_Bool has_vertical_info
;
280 glyph
->root
.outline
.n_points
= 0;
281 glyph
->root
.outline
.n_contours
= 0;
283 glyph
->root
.metrics
.width
= (FT_Pos
)metrics
.width
<< 6;
284 glyph
->root
.metrics
.height
= (FT_Pos
)metrics
.height
<< 6;
286 glyph
->root
.metrics
.horiBearingX
= (FT_Pos
)metrics
.horiBearingX
<< 6;
287 glyph
->root
.metrics
.horiBearingY
= (FT_Pos
)metrics
.horiBearingY
<< 6;
288 glyph
->root
.metrics
.horiAdvance
= (FT_Pos
)metrics
.horiAdvance
<< 6;
290 glyph
->root
.metrics
.vertBearingX
= (FT_Pos
)metrics
.vertBearingX
<< 6;
291 glyph
->root
.metrics
.vertBearingY
= (FT_Pos
)metrics
.vertBearingY
<< 6;
292 glyph
->root
.metrics
.vertAdvance
= (FT_Pos
)metrics
.vertAdvance
<< 6;
294 glyph
->root
.format
= FT_GLYPH_FORMAT_BITMAP
;
296 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
298 glyph
->root
.bitmap_left
= metrics
.vertBearingX
;
299 glyph
->root
.bitmap_top
= metrics
.vertBearingY
;
303 glyph
->root
.bitmap_left
= metrics
.horiBearingX
;
304 glyph
->root
.bitmap_top
= metrics
.horiBearingY
;
307 /* compute linear advance widths */
309 (void)( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 0,
313 glyph
->root
.linearHoriAdvance
= advance
;
315 has_vertical_info
= FT_BOOL(
316 face
->vertical_info
&&
317 face
->vertical
.number_Of_VMetrics
> 0 );
319 /* get the vertical metrics from the vmtx table if we have one */
320 if ( has_vertical_info
)
322 (void)( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 1,
326 glyph
->root
.linearVertAdvance
= advance
;
330 /* make up vertical ones */
331 if ( face
->os2
.version
!= 0xFFFFU
)
332 glyph
->root
.linearVertAdvance
= (FT_Pos
)
333 ( face
->os2
.sTypoAscender
- face
->os2
.sTypoDescender
);
335 glyph
->root
.linearVertAdvance
= (FT_Pos
)
336 ( face
->horizontal
.Ascender
- face
->horizontal
.Descender
);
344 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
346 /* return immediately if we only want the embedded bitmaps */
347 if ( load_flags
& FT_LOAD_SBITS_ONLY
)
348 return FT_THROW( Invalid_Argument
);
350 /* if we have a CID subfont, use its matrix (which has already */
351 /* been multiplied with the root matrix) */
353 /* this scaling is only relevant if the PS hinter isn't active */
354 if ( cff
->num_subfonts
)
356 FT_Long top_upm
, sub_upm
;
357 FT_Byte fd_index
= cff_fd_select_get( &cff
->fd_select
,
361 if ( fd_index
>= cff
->num_subfonts
)
362 fd_index
= (FT_Byte
)( cff
->num_subfonts
- 1 );
364 top_upm
= (FT_Long
)cff
->top_font
.font_dict
.units_per_em
;
365 sub_upm
= (FT_Long
)cff
->subfonts
[fd_index
]->font_dict
.units_per_em
;
368 font_matrix
= cff
->subfonts
[fd_index
]->font_dict
.font_matrix
;
369 font_offset
= cff
->subfonts
[fd_index
]->font_dict
.font_offset
;
371 if ( top_upm
!= sub_upm
)
373 glyph
->x_scale
= FT_MulDiv( glyph
->x_scale
, top_upm
, sub_upm
);
374 glyph
->y_scale
= FT_MulDiv( glyph
->y_scale
, top_upm
, sub_upm
);
376 force_scaling
= TRUE
;
381 font_matrix
= cff
->top_font
.font_dict
.font_matrix
;
382 font_offset
= cff
->top_font
.font_dict
.font_offset
;
385 glyph
->root
.outline
.n_points
= 0;
386 glyph
->root
.outline
.n_contours
= 0;
388 /* top-level code ensures that FT_LOAD_NO_HINTING is set */
389 /* if FT_LOAD_NO_SCALE is active */
390 hinting
= FT_BOOL( ( load_flags
& FT_LOAD_NO_HINTING
) == 0 );
391 scaled
= FT_BOOL( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 );
393 glyph
->hint
= hinting
;
394 glyph
->scaled
= scaled
;
395 glyph
->root
.format
= FT_GLYPH_FORMAT_OUTLINE
; /* by default */
398 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
399 PS_Driver driver
= (PS_Driver
)FT_FACE_DRIVER( face
);
404 FT_ULong charstring_len
;
407 decoder_funcs
->init( &decoder
, face
, size
, glyph
, hinting
,
408 FT_LOAD_TARGET_MODE( load_flags
),
410 cff_free_glyph_data
);
412 /* this is for pure CFFs */
413 if ( load_flags
& FT_LOAD_ADVANCE_ONLY
)
414 decoder
.width_only
= TRUE
;
416 decoder
.builder
.no_recurse
=
417 (FT_Bool
)( load_flags
& FT_LOAD_NO_RECURSE
);
419 /* now load the unscaled outline */
420 error
= cff_get_glyph_data( face
, glyph_index
,
421 &charstring
, &charstring_len
);
423 goto Glyph_Build_Finished
;
425 error
= decoder_funcs
->prepare( &decoder
, size
, glyph_index
);
427 goto Glyph_Build_Finished
;
429 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
430 /* choose which CFF renderer to use */
431 if ( driver
->hinting_engine
== FT_HINTING_FREETYPE
)
432 error
= decoder_funcs
->parse_charstrings_old( &decoder
,
439 psaux
->ps_decoder_init( &psdecoder
, &decoder
, FALSE
);
441 error
= decoder_funcs
->parse_charstrings( &psdecoder
,
445 /* Adobe's engine uses 16.16 numbers everywhere; */
446 /* as a consequence, glyphs larger than 2000ppem get rejected */
447 if ( FT_ERR_EQ( error
, Glyph_Too_Big
) )
449 /* this time, we retry unhinted and scale up the glyph later on */
450 /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
451 /* 0x400 for both `x_scale' and `y_scale' in this case) */
453 force_scaling
= TRUE
;
454 glyph
->hint
= hinting
;
456 error
= decoder_funcs
->parse_charstrings( &psdecoder
,
462 cff_free_glyph_data( face
, &charstring
, charstring_len
);
465 goto Glyph_Build_Finished
;
467 #ifdef FT_CONFIG_OPTION_INCREMENTAL
468 /* Control data and length may not be available for incremental */
470 if ( face
->root
.internal
->incremental_interface
)
472 glyph
->root
.control_data
= NULL
;
473 glyph
->root
.control_len
= 0;
476 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
478 /* We set control_data and control_len if charstrings is loaded. */
479 /* See how charstring loads at cff_index_access_element() in */
482 CFF_Index csindex
= &cff
->charstrings_index
;
485 if ( csindex
->offsets
)
487 glyph
->root
.control_data
= csindex
->bytes
+
488 csindex
->offsets
[glyph_index
] - 1;
489 glyph
->root
.control_len
= (FT_Long
)charstring_len
;
493 Glyph_Build_Finished
:
494 /* save new glyph tables, if no error */
496 decoder
.builder
.funcs
.done( &decoder
.builder
);
497 /* XXX: anything to do for broken glyph entry? */
500 #ifdef FT_CONFIG_OPTION_INCREMENTAL
502 /* Incremental fonts can optionally override the metrics. */
504 face
->root
.internal
->incremental_interface
&&
505 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics
)
507 FT_Incremental_MetricsRec metrics
;
510 metrics
.bearing_x
= decoder
.builder
.left_bearing
.x
;
511 metrics
.bearing_y
= 0;
512 metrics
.advance
= decoder
.builder
.advance
.x
;
513 metrics
.advance_v
= decoder
.builder
.advance
.y
;
515 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics(
516 face
->root
.internal
->incremental_interface
->object
,
517 glyph_index
, FALSE
, &metrics
);
519 decoder
.builder
.left_bearing
.x
= metrics
.bearing_x
;
520 decoder
.builder
.advance
.x
= metrics
.advance
;
521 decoder
.builder
.advance
.y
= metrics
.advance_v
;
524 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
528 /* Now, set the metrics -- this is rather simple, as */
529 /* the left side bearing is the xMin, and the top side */
530 /* bearing the yMax. */
532 /* For composite glyphs, return only left side bearing and */
534 if ( load_flags
& FT_LOAD_NO_RECURSE
)
536 FT_Slot_Internal internal
= glyph
->root
.internal
;
539 glyph
->root
.metrics
.horiBearingX
= decoder
.builder
.left_bearing
.x
;
540 glyph
->root
.metrics
.horiAdvance
= decoder
.glyph_width
;
541 internal
->glyph_matrix
= font_matrix
;
542 internal
->glyph_delta
= font_offset
;
543 internal
->glyph_transformed
= 1;
548 FT_Glyph_Metrics
* metrics
= &glyph
->root
.metrics
;
549 FT_Bool has_vertical_info
;
552 if ( face
->horizontal
.number_Of_HMetrics
)
554 FT_Short horiBearingX
= 0;
555 FT_UShort horiAdvance
= 0;
558 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 0,
562 metrics
->horiAdvance
= horiAdvance
;
563 metrics
->horiBearingX
= horiBearingX
;
564 glyph
->root
.linearHoriAdvance
= horiAdvance
;
568 /* copy the _unscaled_ advance width */
569 metrics
->horiAdvance
= decoder
.glyph_width
;
570 glyph
->root
.linearHoriAdvance
= decoder
.glyph_width
;
573 glyph
->root
.internal
->glyph_transformed
= 0;
575 has_vertical_info
= FT_BOOL( face
->vertical_info
&&
576 face
->vertical
.number_Of_VMetrics
> 0 );
578 /* get the vertical metrics from the vmtx table if we have one */
579 if ( has_vertical_info
)
581 FT_Short vertBearingY
= 0;
582 FT_UShort vertAdvance
= 0;
585 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 1,
589 metrics
->vertBearingY
= vertBearingY
;
590 metrics
->vertAdvance
= vertAdvance
;
594 /* make up vertical ones */
595 if ( face
->os2
.version
!= 0xFFFFU
)
596 metrics
->vertAdvance
= (FT_Pos
)( face
->os2
.sTypoAscender
-
597 face
->os2
.sTypoDescender
);
599 metrics
->vertAdvance
= (FT_Pos
)( face
->horizontal
.Ascender
-
600 face
->horizontal
.Descender
);
603 glyph
->root
.linearVertAdvance
= metrics
->vertAdvance
;
605 glyph
->root
.format
= FT_GLYPH_FORMAT_OUTLINE
;
607 glyph
->root
.outline
.flags
= 0;
608 if ( size
&& size
->root
.metrics
.y_ppem
< 24 )
609 glyph
->root
.outline
.flags
|= FT_OUTLINE_HIGH_PRECISION
;
611 glyph
->root
.outline
.flags
|= FT_OUTLINE_REVERSE_FILL
;
613 /* apply the font matrix, if any */
614 if ( font_matrix
.xx
!= 0x10000L
|| font_matrix
.yy
!= 0x10000L
||
615 font_matrix
.xy
!= 0 || font_matrix
.yx
!= 0 )
617 FT_Outline_Transform( &glyph
->root
.outline
, &font_matrix
);
619 metrics
->horiAdvance
= FT_MulFix( metrics
->horiAdvance
,
621 metrics
->vertAdvance
= FT_MulFix( metrics
->vertAdvance
,
625 if ( font_offset
.x
|| font_offset
.y
)
627 FT_Outline_Translate( &glyph
->root
.outline
,
631 metrics
->horiAdvance
+= font_offset
.x
;
632 metrics
->vertAdvance
+= font_offset
.y
;
635 if ( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 || force_scaling
)
637 /* scale the outline and the metrics */
639 FT_Outline
* cur
= &glyph
->root
.outline
;
640 FT_Vector
* vec
= cur
->points
;
641 FT_Fixed x_scale
= glyph
->x_scale
;
642 FT_Fixed y_scale
= glyph
->y_scale
;
645 /* First of all, scale the points */
646 if ( !hinting
|| !decoder
.builder
.hints_funcs
)
647 for ( n
= cur
->n_points
; n
> 0; n
--, vec
++ )
649 vec
->x
= FT_MulFix( vec
->x
, x_scale
);
650 vec
->y
= FT_MulFix( vec
->y
, y_scale
);
653 /* Then scale the metrics */
654 metrics
->horiAdvance
= FT_MulFix( metrics
->horiAdvance
, x_scale
);
655 metrics
->vertAdvance
= FT_MulFix( metrics
->vertAdvance
, y_scale
);
658 /* compute the other metrics */
659 FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox
);
661 metrics
->width
= cbox
.xMax
- cbox
.xMin
;
662 metrics
->height
= cbox
.yMax
- cbox
.yMin
;
664 metrics
->horiBearingX
= cbox
.xMin
;
665 metrics
->horiBearingY
= cbox
.yMax
;
667 if ( has_vertical_info
)
668 metrics
->vertBearingX
= metrics
->horiBearingX
-
669 metrics
->horiAdvance
/ 2;
672 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
673 ft_synthesize_vertical_metrics( metrics
,
674 metrics
->vertAdvance
);