1 /***************************************************************************/
5 /* OpenType Glyph Loader (body). */
7 /* Copyright 1996-2017 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
25 #include FT_CFF_DRIVER_H
30 #include "cf2ft.h" /* for cf2_decoder_parse_charstrings */
35 /*************************************************************************/
37 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
38 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
39 /* messages during execution. */
42 #define FT_COMPONENT trace_cffgload
45 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
47 typedef enum CFF_Operator_
81 cff_op_dotsection
, /* deprecated, acts as no-op */
115 /* Type 1 opcodes: invalid but seen in real life */
118 cff_op_callothersubr
,
122 cff_op_setcurrentpoint
,
130 #define CFF_COUNT_CHECK_WIDTH 0x80
131 #define CFF_COUNT_EXACT 0x40
132 #define CFF_COUNT_CLEAR_STACK 0x20
134 /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */
135 /* used for checking the width and requested numbers of arguments */
136 /* only; they are set to zero afterwards */
138 /* the other two flags are informative only and unused currently */
140 static const FT_Byte cff_argument_counts
[] =
144 2 | CFF_COUNT_CHECK_WIDTH
| CFF_COUNT_EXACT
, /* rmoveto */
145 1 | CFF_COUNT_CHECK_WIDTH
| CFF_COUNT_EXACT
,
146 1 | CFF_COUNT_CHECK_WIDTH
| CFF_COUNT_EXACT
,
148 0 | CFF_COUNT_CLEAR_STACK
, /* rlineto */
149 0 | CFF_COUNT_CLEAR_STACK
,
150 0 | CFF_COUNT_CLEAR_STACK
,
152 0 | CFF_COUNT_CLEAR_STACK
, /* rrcurveto */
153 0 | CFF_COUNT_CLEAR_STACK
,
154 0 | CFF_COUNT_CLEAR_STACK
,
155 0 | CFF_COUNT_CLEAR_STACK
,
156 0 | CFF_COUNT_CLEAR_STACK
,
157 0 | CFF_COUNT_CLEAR_STACK
,
158 0 | CFF_COUNT_CLEAR_STACK
,
165 0 | CFF_COUNT_CHECK_WIDTH
, /* endchar */
167 2 | CFF_COUNT_CHECK_WIDTH
, /* hstem */
168 2 | CFF_COUNT_CHECK_WIDTH
,
169 2 | CFF_COUNT_CHECK_WIDTH
,
170 2 | CFF_COUNT_CHECK_WIDTH
,
172 0 | CFF_COUNT_CHECK_WIDTH
, /* hintmask */
173 0 | CFF_COUNT_CHECK_WIDTH
, /* cntrmask */
214 2 /* setcurrentpoint */
217 #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
220 /*************************************************************************/
221 /*************************************************************************/
222 /*************************************************************************/
223 /********** *********/
224 /********** *********/
225 /********** GENERIC CHARSTRING PARSING *********/
226 /********** *********/
227 /********** *********/
228 /*************************************************************************/
229 /*************************************************************************/
230 /*************************************************************************/
233 /*************************************************************************/
236 /* cff_builder_init */
239 /* Initializes a given glyph builder. */
242 /* builder :: A pointer to the glyph builder to initialize. */
245 /* face :: The current face object. */
247 /* size :: The current size object. */
249 /* glyph :: The current glyph object. */
251 /* hinting :: Whether hinting is active. */
254 cff_builder_init( CFF_Builder
* builder
,
260 builder
->path_begun
= 0;
261 builder
->load_points
= 1;
263 builder
->face
= face
;
264 builder
->glyph
= glyph
;
265 builder
->memory
= face
->root
.memory
;
269 FT_GlyphLoader loader
= glyph
->root
.internal
->loader
;
272 builder
->loader
= loader
;
273 builder
->base
= &loader
->base
.outline
;
274 builder
->current
= &loader
->current
.outline
;
275 FT_GlyphLoader_Rewind( loader
);
277 builder
->hints_globals
= NULL
;
278 builder
->hints_funcs
= NULL
;
280 if ( hinting
&& size
)
282 FT_Size ftsize
= FT_SIZE( size
);
283 CFF_Internal internal
= (CFF_Internal
)ftsize
->internal
->module_data
;
288 builder
->hints_globals
= (void *)internal
->topfont
;
289 builder
->hints_funcs
= glyph
->root
.internal
->glyph_hints
;
297 builder
->left_bearing
.x
= 0;
298 builder
->left_bearing
.y
= 0;
299 builder
->advance
.x
= 0;
300 builder
->advance
.y
= 0;
304 /*************************************************************************/
307 /* cff_builder_done */
310 /* Finalizes a given glyph builder. Its contents can still be used */
311 /* after the call, but the function saves important information */
312 /* within the corresponding glyph slot. */
315 /* builder :: A pointer to the glyph builder to finalize. */
318 cff_builder_done( CFF_Builder
* builder
)
320 CFF_GlyphSlot glyph
= builder
->glyph
;
324 glyph
->root
.outline
= *builder
->base
;
328 /*************************************************************************/
331 /* cff_compute_bias */
334 /* Computes the bias value in dependence of the number of glyph */
338 /* in_charstring_type :: The `CharstringType' value of the top DICT */
341 /* num_subrs :: The number of glyph subroutines. */
344 /* The bias value. */
346 cff_compute_bias( FT_Int in_charstring_type
,
352 if ( in_charstring_type
== 1 )
354 else if ( num_subrs
< 1240 )
356 else if ( num_subrs
< 33900U )
365 /*************************************************************************/
368 /* cff_decoder_init */
371 /* Initializes a given glyph decoder. */
374 /* decoder :: A pointer to the glyph builder to initialize. */
377 /* face :: The current face object. */
379 /* size :: The current size object. */
381 /* slot :: The current glyph object. */
383 /* hinting :: Whether hinting is active. */
385 /* hint_mode :: The hinting mode. */
388 cff_decoder_init( CFF_Decoder
* decoder
,
393 FT_Render_Mode hint_mode
)
395 CFF_Font cff
= (CFF_Font
)face
->extra
.data
;
398 /* clear everything */
401 /* initialize builder */
402 cff_builder_init( &decoder
->builder
, face
, size
, slot
, hinting
);
404 /* initialize Type2 decoder */
406 decoder
->num_globals
= cff
->global_subrs_index
.count
;
407 decoder
->globals
= cff
->global_subrs
;
408 decoder
->globals_bias
= cff_compute_bias(
409 cff
->top_font
.font_dict
.charstring_type
,
410 decoder
->num_globals
);
412 decoder
->hint_mode
= hint_mode
;
416 /* this function is used to select the subfont */
417 /* and the locals subrs array */
418 FT_LOCAL_DEF( FT_Error
)
419 cff_decoder_prepare( CFF_Decoder
* decoder
,
421 FT_UInt glyph_index
)
423 CFF_Builder
*builder
= &decoder
->builder
;
424 CFF_Font cff
= (CFF_Font
)builder
->face
->extra
.data
;
425 CFF_SubFont sub
= &cff
->top_font
;
426 FT_Error error
= FT_Err_Ok
;
429 /* manage CID fonts */
430 if ( cff
->num_subfonts
)
432 FT_Byte fd_index
= cff_fd_select_get( &cff
->fd_select
, glyph_index
);
435 if ( fd_index
>= cff
->num_subfonts
)
437 FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
438 error
= FT_THROW( Invalid_File_Format
);
442 FT_TRACE3(( " in subfont %d:\n", fd_index
));
444 sub
= cff
->subfonts
[fd_index
];
446 if ( builder
->hints_funcs
&& size
)
448 FT_Size ftsize
= FT_SIZE( size
);
449 CFF_Internal internal
= (CFF_Internal
)ftsize
->internal
->module_data
;
452 /* for CFFs without subfonts, this value has already been set */
453 builder
->hints_globals
= (void *)internal
->subfonts
[fd_index
];
457 decoder
->num_locals
= sub
->local_subrs_index
.count
;
458 decoder
->locals
= sub
->local_subrs
;
459 decoder
->locals_bias
= cff_compute_bias(
460 decoder
->cff
->top_font
.font_dict
.charstring_type
,
461 decoder
->num_locals
);
463 decoder
->glyph_width
= sub
->private_dict
.default_width
;
464 decoder
->nominal_width
= sub
->private_dict
.nominal_width
;
466 decoder
->current_subfont
= sub
;
473 /* check that there is enough space for `count' more points */
474 FT_LOCAL_DEF( FT_Error
)
475 cff_check_points( CFF_Builder
* builder
,
478 return FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, count
, 0 );
482 /* add a new point, do not check space */
484 cff_builder_add_point( CFF_Builder
* builder
,
489 FT_Outline
* outline
= builder
->current
;
492 if ( builder
->load_points
)
494 FT_Vector
* point
= outline
->points
+ outline
->n_points
;
495 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
;
497 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
498 CFF_Driver driver
= (CFF_Driver
)FT_FACE_DRIVER( builder
->face
);
501 if ( driver
->hinting_engine
== FT_CFF_HINTING_FREETYPE
)
509 /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
513 *control
= (FT_Byte
)( flag
? FT_CURVE_TAG_ON
: FT_CURVE_TAG_CUBIC
);
520 /* check space for a new on-curve point, then add it */
521 FT_LOCAL_DEF( FT_Error
)
522 cff_builder_add_point1( CFF_Builder
* builder
,
529 error
= cff_check_points( builder
, 1 );
531 cff_builder_add_point( builder
, x
, y
, 1 );
537 /* check space for a new contour, then add it */
539 cff_builder_add_contour( CFF_Builder
* builder
)
541 FT_Outline
* outline
= builder
->current
;
545 if ( !builder
->load_points
)
547 outline
->n_contours
++;
551 error
= FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, 0, 1 );
554 if ( outline
->n_contours
> 0 )
555 outline
->contours
[outline
->n_contours
- 1] =
556 (short)( outline
->n_points
- 1 );
558 outline
->n_contours
++;
565 /* if a path was begun, add its first on-curve point */
566 FT_LOCAL_DEF( FT_Error
)
567 cff_builder_start_point( CFF_Builder
* builder
,
571 FT_Error error
= FT_Err_Ok
;
574 /* test whether we are building a new contour */
575 if ( !builder
->path_begun
)
577 builder
->path_begun
= 1;
578 error
= cff_builder_add_contour( builder
);
580 error
= cff_builder_add_point1( builder
, x
, y
);
587 /* close the current contour */
589 cff_builder_close_contour( CFF_Builder
* builder
)
591 FT_Outline
* outline
= builder
->current
;
598 first
= outline
->n_contours
<= 1
599 ? 0 : outline
->contours
[outline
->n_contours
- 2] + 1;
601 /* We must not include the last point in the path if it */
602 /* is located on the first point. */
603 if ( outline
->n_points
> 1 )
605 FT_Vector
* p1
= outline
->points
+ first
;
606 FT_Vector
* p2
= outline
->points
+ outline
->n_points
- 1;
607 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
- 1;
610 /* `delete' last point only if it coincides with the first */
611 /* point and if it is not a control point (which can happen). */
612 if ( p1
->x
== p2
->x
&& p1
->y
== p2
->y
)
613 if ( *control
== FT_CURVE_TAG_ON
)
617 if ( outline
->n_contours
> 0 )
619 /* Don't add contours only consisting of one point, i.e., */
620 /* check whether begin point and last point are the same. */
621 if ( first
== outline
->n_points
- 1 )
623 outline
->n_contours
--;
627 outline
->contours
[outline
->n_contours
- 1] =
628 (short)( outline
->n_points
- 1 );
633 FT_LOCAL_DEF( FT_Int
)
634 cff_lookup_glyph_by_stdcharcode( CFF_Font cff
,
641 /* CID-keyed fonts don't have glyph names */
642 if ( !cff
->charset
.sids
)
645 /* check range of standard char code */
646 if ( charcode
< 0 || charcode
> 255 )
649 /* Get code to SID mapping from `cff_standard_encoding'. */
650 glyph_sid
= cff_get_standard_encoding( (FT_UInt
)charcode
);
652 for ( n
= 0; n
< cff
->num_glyphs
; n
++ )
654 if ( cff
->charset
.sids
[n
] == glyph_sid
)
662 FT_LOCAL_DEF( FT_Error
)
663 cff_get_glyph_data( TT_Face face
,
668 #ifdef FT_CONFIG_OPTION_INCREMENTAL
669 /* For incremental fonts get the character data using the */
670 /* callback function. */
671 if ( face
->root
.internal
->incremental_interface
)
675 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_data(
676 face
->root
.internal
->incremental_interface
->object
,
677 glyph_index
, &data
);
680 *pointer
= (FT_Byte
*)data
.pointer
;
681 *length
= (FT_ULong
)data
.length
;
686 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
689 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
692 return cff_index_access_element( &cff
->charstrings_index
, glyph_index
,
699 cff_free_glyph_data( TT_Face face
,
703 #ifndef FT_CONFIG_OPTION_INCREMENTAL
707 #ifdef FT_CONFIG_OPTION_INCREMENTAL
708 /* For incremental fonts get the character data using the */
709 /* callback function. */
710 if ( face
->root
.internal
->incremental_interface
)
715 data
.pointer
= *pointer
;
716 data
.length
= (FT_Int
)length
;
718 face
->root
.internal
->incremental_interface
->funcs
->free_glyph_data(
719 face
->root
.internal
->incremental_interface
->object
, &data
);
722 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
725 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
728 cff_index_forget_element( &cff
->charstrings_index
, pointer
);
733 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
736 cff_operator_seac( CFF_Decoder
* decoder
,
744 CFF_Builder
* builder
= &decoder
->builder
;
745 FT_Int bchar_index
, achar_index
;
746 TT_Face face
= decoder
->builder
.face
;
747 FT_Vector left_bearing
, advance
;
749 FT_ULong charstring_len
;
755 FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
756 return FT_THROW( Syntax_Error
);
759 adx
+= decoder
->builder
.left_bearing
.x
;
760 ady
+= decoder
->builder
.left_bearing
.y
;
762 #ifdef FT_CONFIG_OPTION_INCREMENTAL
763 /* Incremental fonts don't necessarily have valid charsets. */
764 /* They use the character code, not the glyph index, in this case. */
765 if ( face
->root
.internal
->incremental_interface
)
771 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
773 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
776 bchar_index
= cff_lookup_glyph_by_stdcharcode( cff
, bchar
);
777 achar_index
= cff_lookup_glyph_by_stdcharcode( cff
, achar
);
780 if ( bchar_index
< 0 || achar_index
< 0 )
782 FT_ERROR(( "cff_operator_seac:"
783 " invalid seac character code arguments\n" ));
784 return FT_THROW( Syntax_Error
);
787 /* If we are trying to load a composite glyph, do not load the */
788 /* accent character and return the array of subglyphs. */
789 if ( builder
->no_recurse
)
791 FT_GlyphSlot glyph
= (FT_GlyphSlot
)builder
->glyph
;
792 FT_GlyphLoader loader
= glyph
->internal
->loader
;
796 /* reallocate subglyph array if necessary */
797 error
= FT_GlyphLoader_CheckSubGlyphs( loader
, 2 );
801 subg
= loader
->current
.subglyphs
;
803 /* subglyph 0 = base character */
804 subg
->index
= bchar_index
;
805 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
|
806 FT_SUBGLYPH_FLAG_USE_MY_METRICS
;
811 /* subglyph 1 = accent character */
812 subg
->index
= achar_index
;
813 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
;
814 subg
->arg1
= (FT_Int
)( adx
>> 16 );
815 subg
->arg2
= (FT_Int
)( ady
>> 16 );
817 /* set up remaining glyph fields */
818 glyph
->num_subglyphs
= 2;
819 glyph
->subglyphs
= loader
->base
.subglyphs
;
820 glyph
->format
= FT_GLYPH_FORMAT_COMPOSITE
;
822 loader
->current
.num_subglyphs
= 2;
825 FT_GlyphLoader_Prepare( builder
->loader
);
827 /* First load `bchar' in builder */
828 error
= cff_get_glyph_data( face
, (FT_UInt
)bchar_index
,
829 &charstring
, &charstring_len
);
832 /* the seac operator must not be nested */
833 decoder
->seac
= TRUE
;
834 error
= cff_decoder_parse_charstrings( decoder
, charstring
,
836 decoder
->seac
= FALSE
;
838 cff_free_glyph_data( face
, &charstring
, charstring_len
);
844 /* Save the left bearing, advance and glyph width of the base */
845 /* character as they will be erased by the next load. */
847 left_bearing
= builder
->left_bearing
;
848 advance
= builder
->advance
;
849 glyph_width
= decoder
->glyph_width
;
851 builder
->left_bearing
.x
= 0;
852 builder
->left_bearing
.y
= 0;
854 builder
->pos_x
= adx
- asb
;
855 builder
->pos_y
= ady
;
857 /* Now load `achar' on top of the base outline. */
858 error
= cff_get_glyph_data( face
, (FT_UInt
)achar_index
,
859 &charstring
, &charstring_len
);
862 /* the seac operator must not be nested */
863 decoder
->seac
= TRUE
;
864 error
= cff_decoder_parse_charstrings( decoder
, charstring
,
866 decoder
->seac
= FALSE
;
868 cff_free_glyph_data( face
, &charstring
, charstring_len
);
874 /* Restore the left side bearing, advance and glyph width */
875 /* of the base character. */
876 builder
->left_bearing
= left_bearing
;
877 builder
->advance
= advance
;
878 decoder
->glyph_width
= glyph_width
;
888 /*************************************************************************/
891 /* cff_decoder_parse_charstrings */
894 /* Parses a given Type 2 charstrings program. */
897 /* decoder :: The current Type 1 decoder. */
900 /* charstring_base :: The base of the charstring stream. */
902 /* charstring_len :: The length in bytes of the charstring stream. */
904 /* in_dict :: Set to 1 if function is called from top or */
905 /* private DICT (needed for Multiple Master CFFs). */
908 /* FreeType error code. 0 means success. */
910 FT_LOCAL_DEF( FT_Error
)
911 cff_decoder_parse_charstrings( CFF_Decoder
* decoder
,
912 FT_Byte
* charstring_base
,
913 FT_ULong charstring_len
,
917 CFF_Decoder_Zone
* zone
;
920 CFF_Builder
* builder
= &decoder
->builder
;
923 FT_Int charstring_type
=
924 decoder
->cff
->top_font
.font_dict
.charstring_type
;
925 FT_UShort num_designs
=
926 decoder
->cff
->top_font
.font_dict
.num_designs
;
928 decoder
->cff
->top_font
.font_dict
.num_axes
;
930 T2_Hints_Funcs hinter
;
933 /* set default width */
934 decoder
->num_hints
= 0;
935 decoder
->read_width
= 1;
937 /* initialize the decoder */
938 decoder
->top
= decoder
->stack
;
939 decoder
->zone
= decoder
->zones
;
940 zone
= decoder
->zones
;
941 stack
= decoder
->top
;
943 hinter
= (T2_Hints_Funcs
)builder
->hints_funcs
;
945 builder
->path_begun
= 0;
947 zone
->base
= charstring_base
;
948 limit
= zone
->limit
= charstring_base
+ charstring_len
;
949 ip
= zone
->cursor
= zone
->base
;
956 /* begin hints recording session, if any */
958 hinter
->open( hinter
->hints
);
960 /* now execute loop */
967 /********************************************************************/
969 /* Decode operator or operand */
972 if ( v
>= 32 || v
== 28 )
978 /* this is an operand, push it on the stack */
980 /* if we use shifts, all computations are done with unsigned */
981 /* values; the conversion to a signed value is the last step */
984 if ( ip
+ 1 >= limit
)
986 val
= (FT_Short
)( ( (FT_UShort
)ip
[0] << 8 ) | ip
[1] );
990 val
= (FT_Int32
)v
- 139;
995 val
= ( (FT_Int32
)v
- 247 ) * 256 + *ip
++ + 108;
1001 val
= -( (FT_Int32
)v
- 251 ) * 256 - *ip
++ - 108;
1005 if ( ip
+ 3 >= limit
)
1007 val
= (FT_Int32
)( ( (FT_UInt32
)ip
[0] << 24 ) |
1008 ( (FT_UInt32
)ip
[1] << 16 ) |
1009 ( (FT_UInt32
)ip
[2] << 8 ) |
1012 if ( charstring_type
== 2 )
1015 if ( decoder
->top
- stack
>= CFF_MAX_OPERANDS
)
1016 goto Stack_Overflow
;
1018 val
= (FT_Int32
)( (FT_UInt32
)val
<< shift
);
1019 *decoder
->top
++ = val
;
1021 #ifdef FT_DEBUG_LEVEL_TRACE
1022 if ( !( val
& 0xFFFFL
) )
1023 FT_TRACE4(( " %hd", (FT_Short
)( (FT_UInt32
)val
>> 16 ) ));
1025 FT_TRACE4(( " %.5f", val
/ 65536.0 ));
1031 /* The specification says that normally arguments are to be taken */
1032 /* from the bottom of the stack. However, this seems not to be */
1033 /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
1034 /* arguments similar to a PS interpreter. */
1036 FT_Fixed
* args
= decoder
->top
;
1037 FT_Int num_args
= (FT_Int
)( args
- decoder
->stack
);
1042 op
= cff_op_unknown
;
1053 op
= cff_op_vmoveto
;
1056 op
= cff_op_rlineto
;
1059 op
= cff_op_hlineto
;
1062 op
= cff_op_vlineto
;
1065 op
= cff_op_rrcurveto
;
1068 op
= cff_op_closepath
;
1071 op
= cff_op_callsubr
;
1085 op
= cff_op_dotsection
;
1087 case 1: /* this is actually the Type1 vstem3 operator */
1090 case 2: /* this is actually the Type1 hstem3 operator */
1133 op
= cff_op_callothersubr
;
1172 op
= cff_op_setcurrentpoint
;
1187 FT_TRACE4(( " unknown op (12, %d)\n", v
));
1196 op
= cff_op_endchar
;
1202 op
= cff_op_hstemhm
;
1205 op
= cff_op_hintmask
;
1208 op
= cff_op_cntrmask
;
1211 op
= cff_op_rmoveto
;
1214 op
= cff_op_hmoveto
;
1217 op
= cff_op_vstemhm
;
1220 op
= cff_op_rcurveline
;
1223 op
= cff_op_rlinecurve
;
1226 op
= cff_op_vvcurveto
;
1229 op
= cff_op_hhcurveto
;
1232 op
= cff_op_callgsubr
;
1235 op
= cff_op_vhcurveto
;
1238 op
= cff_op_hvcurveto
;
1241 FT_TRACE4(( " unknown op (%d)\n", v
));
1245 if ( op
== cff_op_unknown
)
1248 /* in Multiple Master CFFs, T2 charstrings can appear in */
1249 /* dictionaries, but some operators are prohibited */
1256 case cff_op_vmoveto
:
1257 case cff_op_rlineto
:
1258 case cff_op_hlineto
:
1259 case cff_op_vlineto
:
1260 case cff_op_rrcurveto
:
1261 case cff_op_hstemhm
:
1262 case cff_op_hintmask
:
1263 case cff_op_cntrmask
:
1264 case cff_op_rmoveto
:
1265 case cff_op_hmoveto
:
1266 case cff_op_vstemhm
:
1267 case cff_op_rcurveline
:
1268 case cff_op_rlinecurve
:
1269 case cff_op_vvcurveto
:
1270 case cff_op_hhcurveto
:
1271 case cff_op_vhcurveto
:
1272 case cff_op_hvcurveto
:
1277 case cff_op_callsubr
:
1278 case cff_op_callgsubr
:
1286 /* check arguments */
1287 req_args
= cff_argument_counts
[op
];
1288 if ( req_args
& CFF_COUNT_CHECK_WIDTH
)
1290 if ( num_args
> 0 && decoder
->read_width
)
1292 /* If `nominal_width' is non-zero, the number is really a */
1293 /* difference against `nominal_width'. Else, the number here */
1294 /* is truly a width, not a difference against `nominal_width'. */
1295 /* If the font does not set `nominal_width', then */
1296 /* `nominal_width' defaults to zero, and so we can set */
1297 /* `glyph_width' to `nominal_width' plus number on the stack */
1298 /* -- for either case. */
1300 FT_Int set_width_ok
;
1305 case cff_op_hmoveto
:
1306 case cff_op_vmoveto
:
1307 set_width_ok
= num_args
& 2;
1312 case cff_op_hstemhm
:
1313 case cff_op_vstemhm
:
1314 case cff_op_rmoveto
:
1315 case cff_op_hintmask
:
1316 case cff_op_cntrmask
:
1317 set_width_ok
= num_args
& 1;
1320 case cff_op_endchar
:
1321 /* If there is a width specified for endchar, we either have */
1322 /* 1 argument or 5 arguments. We like to argue. */
1323 set_width_ok
= in_dict
1325 : ( ( num_args
== 5 ) || ( num_args
== 1 ) );
1335 decoder
->glyph_width
= decoder
->nominal_width
+
1338 if ( decoder
->width_only
)
1340 /* we only want the advance width; stop here */
1344 /* Consumed an argument. */
1349 decoder
->read_width
= 0;
1354 if ( num_args
< req_args
)
1355 goto Stack_Underflow
;
1357 num_args
-= req_args
;
1359 /* At this point, `args' points to the first argument of the */
1360 /* operand in case `req_args' isn't zero. Otherwise, we have */
1361 /* to adjust `args' manually. */
1363 /* Note that we only pop arguments from the stack which we */
1364 /* really need and can digest so that we can continue in case */
1365 /* of superfluous stack elements. */
1371 case cff_op_hstemhm
:
1372 case cff_op_vstemhm
:
1373 /* the number of arguments is always even here */
1375 op
== cff_op_hstem
? " hstem\n" :
1376 ( op
== cff_op_vstem
? " vstem\n" :
1377 ( op
== cff_op_hstemhm
? " hstemhm\n" : " vstemhm\n" ) ) ));
1380 hinter
->stems( hinter
->hints
,
1381 ( op
== cff_op_hstem
|| op
== cff_op_hstemhm
),
1383 args
- ( num_args
& ~1 ) );
1385 decoder
->num_hints
+= num_args
/ 2;
1389 case cff_op_hintmask
:
1390 case cff_op_cntrmask
:
1391 FT_TRACE4(( op
== cff_op_hintmask
? " hintmask" : " cntrmask" ));
1393 /* implement vstem when needed -- */
1394 /* the specification doesn't say it, but this also works */
1395 /* with the 'cntrmask' operator */
1400 hinter
->stems( hinter
->hints
,
1403 args
- ( num_args
& ~1 ) );
1405 decoder
->num_hints
+= num_args
/ 2;
1408 /* In a valid charstring there must be at least one byte */
1409 /* after `hintmask' or `cntrmask' (e.g., for a `return' */
1410 /* instruction). Additionally, there must be space for */
1411 /* `num_hints' bits. */
1413 if ( ( ip
+ ( ( decoder
->num_hints
+ 7 ) >> 3 ) ) >= limit
)
1418 if ( op
== cff_op_hintmask
)
1419 hinter
->hintmask( hinter
->hints
,
1420 (FT_UInt
)builder
->current
->n_points
,
1421 (FT_UInt
)decoder
->num_hints
,
1424 hinter
->counter( hinter
->hints
,
1425 (FT_UInt
)decoder
->num_hints
,
1429 #ifdef FT_DEBUG_LEVEL_TRACE
1434 FT_TRACE4(( " (maskbytes:" ));
1437 maskbyte
< (FT_UInt
)( ( decoder
->num_hints
+ 7 ) >> 3 );
1439 FT_TRACE4(( " 0x%02X", *ip
));
1441 FT_TRACE4(( ")\n" ));
1444 ip
+= ( decoder
->num_hints
+ 7 ) >> 3;
1449 case cff_op_rmoveto
:
1450 FT_TRACE4(( " rmoveto\n" ));
1452 cff_builder_close_contour( builder
);
1453 builder
->path_begun
= 0;
1454 x
= ADD_LONG( x
, args
[-2] );
1455 y
= ADD_LONG( y
, args
[-1] );
1459 case cff_op_vmoveto
:
1460 FT_TRACE4(( " vmoveto\n" ));
1462 cff_builder_close_contour( builder
);
1463 builder
->path_begun
= 0;
1464 y
= ADD_LONG( y
, args
[-1] );
1468 case cff_op_hmoveto
:
1469 FT_TRACE4(( " hmoveto\n" ));
1471 cff_builder_close_contour( builder
);
1472 builder
->path_begun
= 0;
1473 x
= ADD_LONG( x
, args
[-1] );
1477 case cff_op_rlineto
:
1478 FT_TRACE4(( " rlineto\n" ));
1480 if ( cff_builder_start_point( builder
, x
, y
) ||
1481 cff_check_points( builder
, num_args
/ 2 ) )
1485 goto Stack_Underflow
;
1487 args
-= num_args
& ~1;
1488 while ( args
< decoder
->top
)
1490 x
= ADD_LONG( x
, args
[0] );
1491 y
= ADD_LONG( y
, args
[1] );
1492 cff_builder_add_point( builder
, x
, y
, 1 );
1498 case cff_op_hlineto
:
1499 case cff_op_vlineto
:
1501 FT_Int phase
= ( op
== cff_op_hlineto
);
1504 FT_TRACE4(( op
== cff_op_hlineto
? " hlineto\n"
1508 goto Stack_Underflow
;
1510 /* there exist subsetted fonts (found in PDFs) */
1511 /* which call `hlineto' without arguments */
1512 if ( num_args
== 0 )
1515 if ( cff_builder_start_point( builder
, x
, y
) ||
1516 cff_check_points( builder
, num_args
) )
1520 while ( args
< decoder
->top
)
1523 x
= ADD_LONG( x
, args
[0] );
1525 y
= ADD_LONG( y
, args
[0] );
1527 if ( cff_builder_add_point1( builder
, x
, y
) )
1537 case cff_op_rrcurveto
:
1542 FT_TRACE4(( " rrcurveto\n" ));
1545 goto Stack_Underflow
;
1547 nargs
= num_args
- num_args
% 6;
1549 if ( cff_builder_start_point( builder
, x
, y
) ||
1550 cff_check_points( builder
, nargs
/ 2 ) )
1554 while ( args
< decoder
->top
)
1556 x
= ADD_LONG( x
, args
[0] );
1557 y
= ADD_LONG( y
, args
[1] );
1558 cff_builder_add_point( builder
, x
, y
, 0 );
1560 x
= ADD_LONG( x
, args
[2] );
1561 y
= ADD_LONG( y
, args
[3] );
1562 cff_builder_add_point( builder
, x
, y
, 0 );
1564 x
= ADD_LONG( x
, args
[4] );
1565 y
= ADD_LONG( y
, args
[5] );
1566 cff_builder_add_point( builder
, x
, y
, 1 );
1574 case cff_op_vvcurveto
:
1579 FT_TRACE4(( " vvcurveto\n" ));
1582 goto Stack_Underflow
;
1584 /* if num_args isn't of the form 4n or 4n+1, */
1585 /* we enforce it by clearing the second bit */
1587 nargs
= num_args
& ~2;
1589 if ( cff_builder_start_point( builder
, x
, y
) )
1596 x
= ADD_LONG( x
, args
[0] );
1601 if ( cff_check_points( builder
, 3 * ( nargs
/ 4 ) ) )
1604 while ( args
< decoder
->top
)
1606 y
= ADD_LONG( y
, args
[0] );
1607 cff_builder_add_point( builder
, x
, y
, 0 );
1609 x
= ADD_LONG( x
, args
[1] );
1610 y
= ADD_LONG( y
, args
[2] );
1611 cff_builder_add_point( builder
, x
, y
, 0 );
1613 y
= ADD_LONG( y
, args
[3] );
1614 cff_builder_add_point( builder
, x
, y
, 1 );
1622 case cff_op_hhcurveto
:
1627 FT_TRACE4(( " hhcurveto\n" ));
1630 goto Stack_Underflow
;
1632 /* if num_args isn't of the form 4n or 4n+1, */
1633 /* we enforce it by clearing the second bit */
1635 nargs
= num_args
& ~2;
1637 if ( cff_builder_start_point( builder
, x
, y
) )
1643 y
= ADD_LONG( y
, args
[0] );
1648 if ( cff_check_points( builder
, 3 * ( nargs
/ 4 ) ) )
1651 while ( args
< decoder
->top
)
1653 x
= ADD_LONG( x
, args
[0] );
1654 cff_builder_add_point( builder
, x
, y
, 0 );
1656 x
= ADD_LONG( x
, args
[1] );
1657 y
= ADD_LONG( y
, args
[2] );
1658 cff_builder_add_point( builder
, x
, y
, 0 );
1660 x
= ADD_LONG( x
, args
[3] );
1661 cff_builder_add_point( builder
, x
, y
, 1 );
1669 case cff_op_vhcurveto
:
1670 case cff_op_hvcurveto
:
1676 FT_TRACE4(( op
== cff_op_vhcurveto
? " vhcurveto\n"
1677 : " hvcurveto\n" ));
1679 if ( cff_builder_start_point( builder
, x
, y
) )
1683 goto Stack_Underflow
;
1685 /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
1686 /* we enforce it by clearing the second bit */
1688 nargs
= num_args
& ~2;
1691 if ( cff_check_points( builder
, ( nargs
/ 4 ) * 3 ) )
1692 goto Stack_Underflow
;
1694 phase
= ( op
== cff_op_hvcurveto
);
1696 while ( nargs
>= 4 )
1701 x
= ADD_LONG( x
, args
[0] );
1702 cff_builder_add_point( builder
, x
, y
, 0 );
1704 x
= ADD_LONG( x
, args
[1] );
1705 y
= ADD_LONG( y
, args
[2] );
1706 cff_builder_add_point( builder
, x
, y
, 0 );
1708 y
= ADD_LONG( y
, args
[3] );
1710 x
= ADD_LONG( x
, args
[4] );
1711 cff_builder_add_point( builder
, x
, y
, 1 );
1715 y
= ADD_LONG( y
, args
[0] );
1716 cff_builder_add_point( builder
, x
, y
, 0 );
1718 x
= ADD_LONG( x
, args
[1] );
1719 y
= ADD_LONG( y
, args
[2] );
1720 cff_builder_add_point( builder
, x
, y
, 0 );
1722 x
= ADD_LONG( x
, args
[3] );
1724 y
= ADD_LONG( y
, args
[4] );
1725 cff_builder_add_point( builder
, x
, y
, 1 );
1734 case cff_op_rlinecurve
:
1740 FT_TRACE4(( " rlinecurve\n" ));
1743 goto Stack_Underflow
;
1745 nargs
= num_args
& ~1;
1746 num_lines
= ( nargs
- 6 ) / 2;
1748 if ( cff_builder_start_point( builder
, x
, y
) ||
1749 cff_check_points( builder
, num_lines
+ 3 ) )
1754 /* first, add the line segments */
1755 while ( num_lines
> 0 )
1757 x
= ADD_LONG( x
, args
[0] );
1758 y
= ADD_LONG( y
, args
[1] );
1759 cff_builder_add_point( builder
, x
, y
, 1 );
1765 /* then the curve */
1766 x
= ADD_LONG( x
, args
[0] );
1767 y
= ADD_LONG( y
, args
[1] );
1768 cff_builder_add_point( builder
, x
, y
, 0 );
1770 x
= ADD_LONG( x
, args
[2] );
1771 y
= ADD_LONG( y
, args
[3] );
1772 cff_builder_add_point( builder
, x
, y
, 0 );
1774 x
= ADD_LONG( x
, args
[4] );
1775 y
= ADD_LONG( y
, args
[5] );
1776 cff_builder_add_point( builder
, x
, y
, 1 );
1782 case cff_op_rcurveline
:
1788 FT_TRACE4(( " rcurveline\n" ));
1791 goto Stack_Underflow
;
1793 nargs
= num_args
- 2;
1794 nargs
= nargs
- nargs
% 6 + 2;
1795 num_curves
= ( nargs
- 2 ) / 6;
1797 if ( cff_builder_start_point( builder
, x
, y
) ||
1798 cff_check_points( builder
, num_curves
* 3 + 2 ) )
1803 /* first, add the curves */
1804 while ( num_curves
> 0 )
1806 x
= ADD_LONG( x
, args
[0] );
1807 y
= ADD_LONG( y
, args
[1] );
1808 cff_builder_add_point( builder
, x
, y
, 0 );
1810 x
= ADD_LONG( x
, args
[2] );
1811 y
= ADD_LONG( y
, args
[3] );
1812 cff_builder_add_point( builder
, x
, y
, 0 );
1814 x
= ADD_LONG( x
, args
[4] );
1815 y
= ADD_LONG( y
, args
[5] );
1816 cff_builder_add_point( builder
, x
, y
, 1 );
1822 /* then the final line */
1823 x
= ADD_LONG( x
, args
[0] );
1824 y
= ADD_LONG( y
, args
[1] );
1825 cff_builder_add_point( builder
, x
, y
, 1 );
1836 FT_TRACE4(( " hflex1\n" ));
1838 /* adding five more points: 4 control points, 1 on-curve point */
1839 /* -- make sure we have enough space for the start point if it */
1840 /* needs to be added */
1841 if ( cff_builder_start_point( builder
, x
, y
) ||
1842 cff_check_points( builder
, 6 ) )
1845 /* record the starting point's y position for later use */
1848 /* first control point */
1849 x
= ADD_LONG( x
, args
[0] );
1850 y
= ADD_LONG( y
, args
[1] );
1851 cff_builder_add_point( builder
, x
, y
, 0 );
1853 /* second control point */
1854 x
= ADD_LONG( x
, args
[2] );
1855 y
= ADD_LONG( y
, args
[3] );
1856 cff_builder_add_point( builder
, x
, y
, 0 );
1858 /* join point; on curve, with y-value the same as the last */
1859 /* control point's y-value */
1860 x
= ADD_LONG( x
, args
[4] );
1861 cff_builder_add_point( builder
, x
, y
, 1 );
1863 /* third control point, with y-value the same as the join */
1864 /* point's y-value */
1865 x
= ADD_LONG( x
, args
[5] );
1866 cff_builder_add_point( builder
, x
, y
, 0 );
1868 /* fourth control point */
1869 x
= ADD_LONG( x
, args
[6] );
1870 y
= ADD_LONG( y
, args
[7] );
1871 cff_builder_add_point( builder
, x
, y
, 0 );
1873 /* ending point, with y-value the same as the start */
1874 x
= ADD_LONG( x
, args
[8] );
1876 cff_builder_add_point( builder
, x
, y
, 1 );
1887 FT_TRACE4(( " hflex\n" ));
1889 /* adding six more points; 4 control points, 2 on-curve points */
1890 if ( cff_builder_start_point( builder
, x
, y
) ||
1891 cff_check_points( builder
, 6 ) )
1894 /* record the starting point's y-position for later use */
1897 /* first control point */
1898 x
= ADD_LONG( x
, args
[0] );
1899 cff_builder_add_point( builder
, x
, y
, 0 );
1901 /* second control point */
1902 x
= ADD_LONG( x
, args
[1] );
1903 y
= ADD_LONG( y
, args
[2] );
1904 cff_builder_add_point( builder
, x
, y
, 0 );
1906 /* join point; on curve, with y-value the same as the last */
1907 /* control point's y-value */
1908 x
= ADD_LONG( x
, args
[3] );
1909 cff_builder_add_point( builder
, x
, y
, 1 );
1911 /* third control point, with y-value the same as the join */
1912 /* point's y-value */
1913 x
= ADD_LONG( x
, args
[4] );
1914 cff_builder_add_point( builder
, x
, y
, 0 );
1916 /* fourth control point */
1917 x
= ADD_LONG( x
, args
[5] );
1919 cff_builder_add_point( builder
, x
, y
, 0 );
1921 /* ending point, with y-value the same as the start point's */
1922 /* y-value -- we don't add this point, though */
1923 x
= ADD_LONG( x
, args
[6] );
1924 cff_builder_add_point( builder
, x
, y
, 1 );
1932 FT_Pos start_x
, start_y
; /* record start x, y values for */
1934 FT_Fixed dx
= 0, dy
= 0; /* used in horizontal/vertical */
1935 /* algorithm below */
1936 FT_Int horizontal
, count
;
1940 FT_TRACE4(( " flex1\n" ));
1942 /* adding six more points; 4 control points, 2 on-curve points */
1943 if ( cff_builder_start_point( builder
, x
, y
) ||
1944 cff_check_points( builder
, 6 ) )
1947 /* record the starting point's x, y position for later use */
1951 /* XXX: figure out whether this is supposed to be a horizontal */
1952 /* or vertical flex; the Type 2 specification is vague... */
1956 /* grab up to the last argument */
1957 for ( count
= 5; count
> 0; count
-- )
1959 dx
= ADD_LONG( dx
, temp
[0] );
1960 dy
= ADD_LONG( dy
, temp
[1] );
1969 /* strange test, but here it is... */
1970 horizontal
= ( dx
> dy
);
1972 for ( count
= 5; count
> 0; count
-- )
1974 x
= ADD_LONG( x
, args
[0] );
1975 y
= ADD_LONG( y
, args
[1] );
1976 cff_builder_add_point( builder
, x
, y
,
1977 (FT_Bool
)( count
== 3 ) );
1981 /* is last operand an x- or y-delta? */
1984 x
= ADD_LONG( x
, args
[0] );
1990 y
= ADD_LONG( y
, args
[0] );
1993 cff_builder_add_point( builder
, x
, y
, 1 );
2004 FT_TRACE4(( " flex\n" ));
2006 if ( cff_builder_start_point( builder
, x
, y
) ||
2007 cff_check_points( builder
, 6 ) )
2010 for ( count
= 6; count
> 0; count
-- )
2012 x
= ADD_LONG( x
, args
[0] );
2013 y
= ADD_LONG( y
, args
[1] );
2014 cff_builder_add_point( builder
, x
, y
,
2015 (FT_Bool
)( count
== 4 || count
== 1 ) );
2024 FT_TRACE4(( " seac\n" ));
2026 error
= cff_operator_seac( decoder
,
2027 args
[0], args
[1], args
[2],
2028 (FT_Int
)( args
[3] >> 16 ),
2029 (FT_Int
)( args
[4] >> 16 ) );
2031 /* add current outline to the glyph slot */
2032 FT_GlyphLoader_Add( builder
->loader
);
2035 FT_TRACE4(( "\n" ));
2038 case cff_op_endchar
:
2039 /* in dictionaries, `endchar' simply indicates end of data */
2043 FT_TRACE4(( " endchar\n" ));
2045 /* We are going to emulate the seac operator. */
2046 if ( num_args
>= 4 )
2048 /* Save glyph width so that the subglyphs don't overwrite it. */
2049 FT_Pos glyph_width
= decoder
->glyph_width
;
2052 error
= cff_operator_seac( decoder
,
2053 0L, args
[-4], args
[-3],
2054 (FT_Int
)( args
[-2] >> 16 ),
2055 (FT_Int
)( args
[-1] >> 16 ) );
2057 decoder
->glyph_width
= glyph_width
;
2061 cff_builder_close_contour( builder
);
2063 /* close hints recording session */
2066 if ( hinter
->close( hinter
->hints
,
2067 (FT_UInt
)builder
->current
->n_points
) )
2070 /* apply hints to the loaded glyph outline now */
2071 error
= hinter
->apply( hinter
->hints
,
2073 (PSH_Globals
)builder
->hints_globals
,
2074 decoder
->hint_mode
);
2079 /* add current outline to the glyph slot */
2080 FT_GlyphLoader_Add( builder
->loader
);
2084 FT_TRACE4(( "\n" ));
2088 FT_TRACE4(( " abs\n" ));
2092 if ( args
[0] == FT_LONG_MIN
)
2093 args
[0] = FT_LONG_MAX
;
2101 FT_TRACE4(( " add\n" ));
2103 args
[0] = ADD_LONG( args
[0], args
[1] );
2108 FT_TRACE4(( " sub\n" ));
2110 args
[0] = SUB_LONG( args
[0], args
[1] );
2115 FT_TRACE4(( " div\n" ));
2117 args
[0] = FT_DivFix( args
[0], args
[1] );
2122 FT_TRACE4(( " neg\n" ));
2124 if ( args
[0] == FT_LONG_MIN
)
2125 args
[0] = FT_LONG_MAX
;
2131 FT_TRACE4(( " random\n" ));
2133 /* only use the lower 16 bits of `random' */
2134 /* to generate a number in the range (0;1] */
2135 args
[0] = (FT_Fixed
)
2136 ( ( decoder
->current_subfont
->random
& 0xFFFF ) + 1 );
2139 decoder
->current_subfont
->random
=
2140 cff_random( decoder
->current_subfont
->random
);
2144 FT_TRACE4(( " mul\n" ));
2146 args
[0] = FT_MulFix( args
[0], args
[1] );
2151 FT_TRACE4(( " sqrt\n" ));
2155 FT_Fixed root
= args
[0];
2161 new_root
= ( root
+ FT_DivFix( args
[0], root
) + 1 ) >> 1;
2162 if ( new_root
== root
)
2175 FT_TRACE4(( " drop\n" ));
2184 FT_TRACE4(( " exch\n" ));
2195 FT_Int idx
= (FT_Int
)( args
[0] >> 16 );
2198 FT_TRACE4(( " index\n" ));
2202 else if ( idx
> num_args
- 2 )
2204 args
[0] = args
[-( idx
+ 1 )];
2211 FT_Int count
= (FT_Int
)( args
[0] >> 16 );
2212 FT_Int idx
= (FT_Int
)( args
[1] >> 16 );
2215 FT_TRACE4(( " roll\n" ));
2222 goto Stack_Underflow
;
2228 FT_Fixed tmp
= args
[count
- 1];
2232 for ( i
= count
- 2; i
>= 0; i
-- )
2233 args
[i
+ 1] = args
[i
];
2242 FT_Fixed tmp
= args
[0];
2246 for ( i
= 0; i
< count
- 1; i
++ )
2247 args
[i
] = args
[i
+ 1];
2248 args
[count
- 1] = tmp
;
2257 FT_TRACE4(( " dup\n" ));
2265 FT_Fixed val
= args
[0];
2266 FT_Int idx
= (FT_Int
)( args
[1] >> 16 );
2269 FT_TRACE4(( " put\n" ));
2271 /* the Type2 specification before version 16-March-2000 */
2272 /* didn't give a hard-coded size limit of the temporary */
2273 /* storage array; instead, an argument of the */
2274 /* `MultipleMaster' operator set the size */
2275 if ( idx
>= 0 && idx
< CFF_MAX_TRANS_ELEMENTS
)
2276 decoder
->buildchar
[idx
] = val
;
2282 FT_Int idx
= (FT_Int
)( args
[0] >> 16 );
2286 FT_TRACE4(( " get\n" ));
2288 if ( idx
>= 0 && idx
< CFF_MAX_TRANS_ELEMENTS
)
2289 val
= decoder
->buildchar
[idx
];
2297 /* this operator was removed from the Type2 specification */
2298 /* in version 16-March-2000 */
2300 /* since we currently don't handle interpolation of multiple */
2301 /* master fonts, this is a no-op */
2302 FT_TRACE4(( " store\n"));
2306 /* this operator was removed from the Type2 specification */
2307 /* in version 16-March-2000 */
2309 FT_Int reg_idx
= (FT_Int
)args
[0];
2310 FT_Int idx
= (FT_Int
)args
[1];
2311 FT_Int count
= (FT_Int
)args
[2];
2314 FT_TRACE4(( " load\n" ));
2316 /* since we currently don't handle interpolation of multiple */
2317 /* master fonts, we store a vector [1 0 0 ...] in the */
2318 /* temporary storage array regardless of the Registry index */
2319 if ( reg_idx
>= 0 && reg_idx
<= 2 &&
2320 idx
>= 0 && idx
< CFF_MAX_TRANS_ELEMENTS
&&
2321 count
>= 0 && count
<= num_axes
)
2326 end
= FT_MIN( idx
+ count
, CFF_MAX_TRANS_ELEMENTS
);
2329 decoder
->buildchar
[idx
] = 1 << 16;
2331 for ( i
= idx
+ 1; i
< end
; i
++ )
2332 decoder
->buildchar
[i
] = 0;
2338 /* this operator was removed from the Type2 specification */
2339 /* in version 16-March-2000 */
2341 FT_Int num_results
= (FT_Int
)( args
[0] >> 16 );
2344 FT_TRACE4(( " blend\n" ));
2346 if ( num_results
< 0 )
2349 if ( num_results
* (FT_Int
)num_designs
> num_args
)
2350 goto Stack_Underflow
;
2352 /* since we currently don't handle interpolation of multiple */
2353 /* master fonts, return the `num_results' values of the */
2355 args
-= num_results
* ( num_designs
- 1 );
2356 num_args
-= num_results
* ( num_designs
- 1 );
2360 case cff_op_dotsection
:
2361 /* this operator is deprecated and ignored by the parser */
2362 FT_TRACE4(( " dotsection\n" ));
2365 case cff_op_closepath
:
2366 /* this is an invalid Type 2 operator; however, there */
2367 /* exist fonts which are incorrectly converted from probably */
2368 /* Type 1 to CFF, and some parsers seem to accept it */
2370 FT_TRACE4(( " closepath (invalid op)\n" ));
2376 /* this is an invalid Type 2 operator; however, there */
2377 /* exist fonts which are incorrectly converted from probably */
2378 /* Type 1 to CFF, and some parsers seem to accept it */
2380 FT_TRACE4(( " hsbw (invalid op)\n" ));
2382 decoder
->glyph_width
=
2383 ADD_LONG( decoder
->nominal_width
, ( args
[1] >> 16 ) );
2385 decoder
->builder
.left_bearing
.x
= args
[0];
2386 decoder
->builder
.left_bearing
.y
= 0;
2388 x
= ADD_LONG( decoder
->builder
.pos_x
, args
[0] );
2389 y
= decoder
->builder
.pos_y
;
2394 /* this is an invalid Type 2 operator; however, there */
2395 /* exist fonts which are incorrectly converted from probably */
2396 /* Type 1 to CFF, and some parsers seem to accept it */
2398 FT_TRACE4(( " sbw (invalid op)\n" ));
2400 decoder
->glyph_width
=
2401 ADD_LONG( decoder
->nominal_width
, ( args
[2] >> 16 ) );
2403 decoder
->builder
.left_bearing
.x
= args
[0];
2404 decoder
->builder
.left_bearing
.y
= args
[1];
2406 x
= ADD_LONG( decoder
->builder
.pos_x
, args
[0] );
2407 y
= ADD_LONG( decoder
->builder
.pos_y
, args
[1] );
2411 case cff_op_setcurrentpoint
:
2412 /* this is an invalid Type 2 operator; however, there */
2413 /* exist fonts which are incorrectly converted from probably */
2414 /* Type 1 to CFF, and some parsers seem to accept it */
2416 FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
2418 x
= ADD_LONG( decoder
->builder
.pos_x
, args
[0] );
2419 y
= ADD_LONG( decoder
->builder
.pos_y
, args
[1] );
2423 case cff_op_callothersubr
:
2424 /* this is an invalid Type 2 operator; however, there */
2425 /* exist fonts which are incorrectly converted from probably */
2426 /* Type 1 to CFF, and some parsers seem to accept it */
2428 FT_TRACE4(( " callothersubr (invalid op)\n" ));
2430 /* subsequent `pop' operands should add the arguments, */
2431 /* this is the implementation described for `unknown' other */
2432 /* subroutines in the Type1 spec. */
2434 /* XXX Fix return arguments (see discussion below). */
2435 args
-= 2 + ( args
[-2] >> 16 );
2437 goto Stack_Underflow
;
2441 /* this is an invalid Type 2 operator; however, there */
2442 /* exist fonts which are incorrectly converted from probably */
2443 /* Type 1 to CFF, and some parsers seem to accept it */
2445 FT_TRACE4(( " pop (invalid op)\n" ));
2447 /* XXX Increasing `args' is wrong: After a certain number of */
2448 /* `pop's we get a stack overflow. Reason for doing it is */
2449 /* code like this (actually found in a CFF font): */
2451 /* 17 1 3 callothersubr */
2455 /* Since we handle `callothersubr' as a no-op, and */
2456 /* `callsubr' needs at least one argument, `pop' can't be a */
2457 /* no-op too as it basically should be. */
2459 /* The right solution would be to provide real support for */
2460 /* `callothersubr' as done in `t1decode.c', however, given */
2461 /* the fact that CFF fonts with `pop' are invalid, it is */
2462 /* questionable whether it is worth the time. */
2468 FT_Fixed cond
= ( args
[0] && args
[1] );
2471 FT_TRACE4(( " and\n" ));
2473 args
[0] = cond
? 0x10000L
: 0;
2480 FT_Fixed cond
= ( args
[0] || args
[1] );
2483 FT_TRACE4(( " or\n" ));
2485 args
[0] = cond
? 0x10000L
: 0;
2492 FT_Fixed cond
= !args
[0];
2495 FT_TRACE4(( " not\n" ));
2497 args
[0] = cond
? 0x10000L
: 0;
2504 FT_Fixed cond
= ( args
[0] == args
[1] );
2507 FT_TRACE4(( " eq\n" ));
2509 args
[0] = cond
? 0x10000L
: 0;
2516 FT_Fixed cond
= ( args
[2] <= args
[3] );
2519 FT_TRACE4(( " ifelse\n" ));
2527 case cff_op_callsubr
:
2529 FT_UInt idx
= (FT_UInt
)( ( args
[0] >> 16 ) +
2530 decoder
->locals_bias
);
2533 FT_TRACE4(( " callsubr (idx %d, entering level %d)\n",
2535 zone
- decoder
->zones
+ 1 ));
2537 if ( idx
>= decoder
->num_locals
)
2539 FT_ERROR(( "cff_decoder_parse_charstrings:"
2540 " invalid local subr index\n" ));
2544 if ( zone
- decoder
->zones
>= CFF_MAX_SUBRS_CALLS
)
2546 FT_ERROR(( "cff_decoder_parse_charstrings:"
2547 " too many nested subrs\n" ));
2551 zone
->cursor
= ip
; /* save current instruction pointer */
2554 zone
->base
= decoder
->locals
[idx
];
2555 zone
->limit
= decoder
->locals
[idx
+ 1];
2556 zone
->cursor
= zone
->base
;
2558 if ( !zone
->base
|| zone
->limit
== zone
->base
)
2560 FT_ERROR(( "cff_decoder_parse_charstrings:"
2561 " invoking empty subrs\n" ));
2565 decoder
->zone
= zone
;
2567 limit
= zone
->limit
;
2571 case cff_op_callgsubr
:
2573 FT_UInt idx
= (FT_UInt
)( ( args
[0] >> 16 ) +
2574 decoder
->globals_bias
);
2577 FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n",
2579 zone
- decoder
->zones
+ 1 ));
2581 if ( idx
>= decoder
->num_globals
)
2583 FT_ERROR(( "cff_decoder_parse_charstrings:"
2584 " invalid global subr index\n" ));
2588 if ( zone
- decoder
->zones
>= CFF_MAX_SUBRS_CALLS
)
2590 FT_ERROR(( "cff_decoder_parse_charstrings:"
2591 " too many nested subrs\n" ));
2595 zone
->cursor
= ip
; /* save current instruction pointer */
2598 zone
->base
= decoder
->globals
[idx
];
2599 zone
->limit
= decoder
->globals
[idx
+ 1];
2600 zone
->cursor
= zone
->base
;
2602 if ( !zone
->base
|| zone
->limit
== zone
->base
)
2604 FT_ERROR(( "cff_decoder_parse_charstrings:"
2605 " invoking empty subrs\n" ));
2609 decoder
->zone
= zone
;
2611 limit
= zone
->limit
;
2616 FT_TRACE4(( " return (leaving level %d)\n",
2617 decoder
->zone
- decoder
->zones
));
2619 if ( decoder
->zone
<= decoder
->zones
)
2621 FT_ERROR(( "cff_decoder_parse_charstrings:"
2622 " unexpected return\n" ));
2627 zone
= decoder
->zone
;
2629 limit
= zone
->limit
;
2633 FT_ERROR(( "Unimplemented opcode: %d", ip
[-1] ));
2636 FT_ERROR(( " %d", ip
[0] ));
2639 return FT_THROW( Unimplemented_Feature
);
2642 decoder
->top
= args
;
2644 if ( decoder
->top
- stack
>= CFF_MAX_OPERANDS
)
2645 goto Stack_Overflow
;
2647 } /* general operator processing */
2649 } /* while ip < limit */
2651 FT_TRACE4(( "..end..\n\n" ));
2657 FT_TRACE4(( "cff_decoder_parse_charstrings:"
2658 " invalid opcode found in top DICT charstring\n"));
2659 return FT_THROW( Invalid_File_Format
);
2662 FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
2663 return FT_THROW( Invalid_File_Format
);
2666 FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
2667 return FT_THROW( Too_Few_Arguments
);
2670 FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
2671 return FT_THROW( Stack_Overflow
);
2674 #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
2677 /*************************************************************************/
2678 /*************************************************************************/
2679 /*************************************************************************/
2680 /********** *********/
2681 /********** *********/
2682 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
2683 /********** *********/
2684 /********** The following code is in charge of computing *********/
2685 /********** the maximum advance width of the font. It *********/
2686 /********** quickly processes each glyph charstring to *********/
2687 /********** extract the value from either a `sbw' or `seac' *********/
2688 /********** operator. *********/
2689 /********** *********/
2690 /*************************************************************************/
2691 /*************************************************************************/
2692 /*************************************************************************/
2695 #if 0 /* unused until we support pure CFF fonts */
2698 FT_LOCAL_DEF( FT_Error
)
2699 cff_compute_max_advance( TT_Face face
,
2700 FT_Int
* max_advance
)
2702 FT_Error error
= FT_Err_Ok
;
2703 CFF_Decoder decoder
;
2705 CFF_Font cff
= (CFF_Font
)face
->other
;
2710 /* Initialize load decoder */
2711 cff_decoder_init( &decoder
, face
, 0, 0, 0, 0 );
2713 decoder
.builder
.metrics_only
= 1;
2714 decoder
.builder
.load_points
= 0;
2716 /* For each glyph, parse the glyph charstring and extract */
2717 /* the advance width. */
2718 for ( glyph_index
= 0; glyph_index
< face
->root
.num_glyphs
;
2721 FT_Byte
* charstring
;
2722 FT_ULong charstring_len
;
2725 /* now get load the unscaled outline */
2726 error
= cff_get_glyph_data( face
, glyph_index
,
2727 &charstring
, &charstring_len
);
2730 error
= cff_decoder_prepare( &decoder
, size
, glyph_index
);
2732 error
= cff_decoder_parse_charstrings( &decoder
,
2737 cff_free_glyph_data( face
, &charstring
, &charstring_len
);
2740 /* ignore the error if one has occurred -- skip to next glyph */
2744 *max_advance
= decoder
.builder
.advance
.x
;
2753 FT_LOCAL_DEF( FT_Error
)
2754 cff_slot_load( CFF_GlyphSlot glyph
,
2756 FT_UInt glyph_index
,
2757 FT_Int32 load_flags
)
2760 CFF_Decoder decoder
;
2761 TT_Face face
= (TT_Face
)glyph
->root
.face
;
2762 FT_Bool hinting
, scaled
, force_scaling
;
2763 CFF_Font cff
= (CFF_Font
)face
->extra
.data
;
2765 FT_Matrix font_matrix
;
2766 FT_Vector font_offset
;
2769 force_scaling
= FALSE
;
2771 /* in a CID-keyed font, consider `glyph_index' as a CID and map */
2772 /* it immediately to the real glyph_index -- if it isn't a */
2773 /* subsetted font, glyph_indices and CIDs are identical, though */
2774 if ( cff
->top_font
.font_dict
.cid_registry
!= 0xFFFFU
&&
2777 /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */
2778 if ( glyph_index
!= 0 )
2780 glyph_index
= cff_charset_cid_to_gindex( &cff
->charset
,
2782 if ( glyph_index
== 0 )
2783 return FT_THROW( Invalid_Argument
);
2786 else if ( glyph_index
>= cff
->num_glyphs
)
2787 return FT_THROW( Invalid_Argument
);
2789 if ( load_flags
& FT_LOAD_NO_RECURSE
)
2790 load_flags
|= FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
2792 glyph
->x_scale
= 0x10000L
;
2793 glyph
->y_scale
= 0x10000L
;
2796 glyph
->x_scale
= size
->root
.metrics
.x_scale
;
2797 glyph
->y_scale
= size
->root
.metrics
.y_scale
;
2800 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2802 /* try to load embedded bitmap if any */
2804 /* XXX: The convention should be emphasized in */
2805 /* the documents because it can be confusing. */
2808 CFF_Face cff_face
= (CFF_Face
)size
->root
.face
;
2809 SFNT_Service sfnt
= (SFNT_Service
)cff_face
->sfnt
;
2810 FT_Stream stream
= cff_face
->root
.stream
;
2813 if ( size
->strike_index
!= 0xFFFFFFFFUL
&&
2815 ( load_flags
& FT_LOAD_NO_BITMAP
) == 0 )
2817 TT_SBit_MetricsRec metrics
;
2820 error
= sfnt
->load_sbit_image( face
,
2823 (FT_UInt
)load_flags
,
2825 &glyph
->root
.bitmap
,
2830 FT_Bool has_vertical_info
;
2835 glyph
->root
.outline
.n_points
= 0;
2836 glyph
->root
.outline
.n_contours
= 0;
2838 glyph
->root
.metrics
.width
= (FT_Pos
)metrics
.width
<< 6;
2839 glyph
->root
.metrics
.height
= (FT_Pos
)metrics
.height
<< 6;
2841 glyph
->root
.metrics
.horiBearingX
= (FT_Pos
)metrics
.horiBearingX
<< 6;
2842 glyph
->root
.metrics
.horiBearingY
= (FT_Pos
)metrics
.horiBearingY
<< 6;
2843 glyph
->root
.metrics
.horiAdvance
= (FT_Pos
)metrics
.horiAdvance
<< 6;
2845 glyph
->root
.metrics
.vertBearingX
= (FT_Pos
)metrics
.vertBearingX
<< 6;
2846 glyph
->root
.metrics
.vertBearingY
= (FT_Pos
)metrics
.vertBearingY
<< 6;
2847 glyph
->root
.metrics
.vertAdvance
= (FT_Pos
)metrics
.vertAdvance
<< 6;
2849 glyph
->root
.format
= FT_GLYPH_FORMAT_BITMAP
;
2851 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
2853 glyph
->root
.bitmap_left
= metrics
.vertBearingX
;
2854 glyph
->root
.bitmap_top
= metrics
.vertBearingY
;
2858 glyph
->root
.bitmap_left
= metrics
.horiBearingX
;
2859 glyph
->root
.bitmap_top
= metrics
.horiBearingY
;
2862 /* compute linear advance widths */
2864 (void)( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 0,
2868 glyph
->root
.linearHoriAdvance
= advance
;
2870 has_vertical_info
= FT_BOOL(
2871 face
->vertical_info
&&
2872 face
->vertical
.number_Of_VMetrics
> 0 );
2874 /* get the vertical metrics from the vmtx table if we have one */
2875 if ( has_vertical_info
)
2877 (void)( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 1,
2881 glyph
->root
.linearVertAdvance
= advance
;
2885 /* make up vertical ones */
2886 if ( face
->os2
.version
!= 0xFFFFU
)
2887 glyph
->root
.linearVertAdvance
= (FT_Pos
)
2888 ( face
->os2
.sTypoAscender
- face
->os2
.sTypoDescender
);
2890 glyph
->root
.linearVertAdvance
= (FT_Pos
)
2891 ( face
->horizontal
.Ascender
- face
->horizontal
.Descender
);
2899 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2901 /* return immediately if we only want the embedded bitmaps */
2902 if ( load_flags
& FT_LOAD_SBITS_ONLY
)
2903 return FT_THROW( Invalid_Argument
);
2905 /* if we have a CID subfont, use its matrix (which has already */
2906 /* been multiplied with the root matrix) */
2908 /* this scaling is only relevant if the PS hinter isn't active */
2909 if ( cff
->num_subfonts
)
2911 FT_Long top_upm
, sub_upm
;
2912 FT_Byte fd_index
= cff_fd_select_get( &cff
->fd_select
,
2916 if ( fd_index
>= cff
->num_subfonts
)
2917 fd_index
= (FT_Byte
)( cff
->num_subfonts
- 1 );
2919 top_upm
= (FT_Long
)cff
->top_font
.font_dict
.units_per_em
;
2920 sub_upm
= (FT_Long
)cff
->subfonts
[fd_index
]->font_dict
.units_per_em
;
2923 font_matrix
= cff
->subfonts
[fd_index
]->font_dict
.font_matrix
;
2924 font_offset
= cff
->subfonts
[fd_index
]->font_dict
.font_offset
;
2926 if ( top_upm
!= sub_upm
)
2928 glyph
->x_scale
= FT_MulDiv( glyph
->x_scale
, top_upm
, sub_upm
);
2929 glyph
->y_scale
= FT_MulDiv( glyph
->y_scale
, top_upm
, sub_upm
);
2931 force_scaling
= TRUE
;
2936 font_matrix
= cff
->top_font
.font_dict
.font_matrix
;
2937 font_offset
= cff
->top_font
.font_dict
.font_offset
;
2940 glyph
->root
.outline
.n_points
= 0;
2941 glyph
->root
.outline
.n_contours
= 0;
2943 /* top-level code ensures that FT_LOAD_NO_HINTING is set */
2944 /* if FT_LOAD_NO_SCALE is active */
2945 hinting
= FT_BOOL( ( load_flags
& FT_LOAD_NO_HINTING
) == 0 );
2946 scaled
= FT_BOOL( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 );
2948 glyph
->hint
= hinting
;
2949 glyph
->scaled
= scaled
;
2950 glyph
->root
.format
= FT_GLYPH_FORMAT_OUTLINE
; /* by default */
2953 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
2954 CFF_Driver driver
= (CFF_Driver
)FT_FACE_DRIVER( face
);
2958 FT_Byte
* charstring
;
2959 FT_ULong charstring_len
;
2962 cff_decoder_init( &decoder
, face
, size
, glyph
, hinting
,
2963 FT_LOAD_TARGET_MODE( load_flags
) );
2965 /* this is for pure CFFs */
2966 if ( load_flags
& FT_LOAD_ADVANCE_ONLY
)
2967 decoder
.width_only
= TRUE
;
2969 decoder
.builder
.no_recurse
=
2970 (FT_Bool
)( load_flags
& FT_LOAD_NO_RECURSE
);
2972 /* now load the unscaled outline */
2973 error
= cff_get_glyph_data( face
, glyph_index
,
2974 &charstring
, &charstring_len
);
2976 goto Glyph_Build_Finished
;
2978 error
= cff_decoder_prepare( &decoder
, size
, glyph_index
);
2980 goto Glyph_Build_Finished
;
2982 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
2983 /* choose which CFF renderer to use */
2984 if ( driver
->hinting_engine
== FT_CFF_HINTING_FREETYPE
)
2985 error
= cff_decoder_parse_charstrings( &decoder
,
2992 error
= cf2_decoder_parse_charstrings( &decoder
,
2996 /* Adobe's engine uses 16.16 numbers everywhere; */
2997 /* as a consequence, glyphs larger than 2000ppem get rejected */
2998 if ( FT_ERR_EQ( error
, Glyph_Too_Big
) )
3000 /* this time, we retry unhinted and scale up the glyph later on */
3001 /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
3002 /* 0x400 for both `x_scale' and `y_scale' in this case) */
3004 force_scaling
= TRUE
;
3005 glyph
->hint
= hinting
;
3007 error
= cf2_decoder_parse_charstrings( &decoder
,
3013 cff_free_glyph_data( face
, &charstring
, charstring_len
);
3016 goto Glyph_Build_Finished
;
3018 #ifdef FT_CONFIG_OPTION_INCREMENTAL
3019 /* Control data and length may not be available for incremental */
3021 if ( face
->root
.internal
->incremental_interface
)
3023 glyph
->root
.control_data
= NULL
;
3024 glyph
->root
.control_len
= 0;
3027 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
3029 /* We set control_data and control_len if charstrings is loaded. */
3030 /* See how charstring loads at cff_index_access_element() in */
3033 CFF_Index csindex
= &cff
->charstrings_index
;
3036 if ( csindex
->offsets
)
3038 glyph
->root
.control_data
= csindex
->bytes
+
3039 csindex
->offsets
[glyph_index
] - 1;
3040 glyph
->root
.control_len
= (FT_Long
)charstring_len
;
3044 Glyph_Build_Finished
:
3045 /* save new glyph tables, if no error */
3047 cff_builder_done( &decoder
.builder
);
3048 /* XXX: anything to do for broken glyph entry? */
3051 #ifdef FT_CONFIG_OPTION_INCREMENTAL
3053 /* Incremental fonts can optionally override the metrics. */
3055 face
->root
.internal
->incremental_interface
&&
3056 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics
)
3058 FT_Incremental_MetricsRec metrics
;
3061 metrics
.bearing_x
= decoder
.builder
.left_bearing
.x
;
3062 metrics
.bearing_y
= 0;
3063 metrics
.advance
= decoder
.builder
.advance
.x
;
3064 metrics
.advance_v
= decoder
.builder
.advance
.y
;
3066 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics(
3067 face
->root
.internal
->incremental_interface
->object
,
3068 glyph_index
, FALSE
, &metrics
);
3070 decoder
.builder
.left_bearing
.x
= metrics
.bearing_x
;
3071 decoder
.builder
.advance
.x
= metrics
.advance
;
3072 decoder
.builder
.advance
.y
= metrics
.advance_v
;
3075 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
3079 /* Now, set the metrics -- this is rather simple, as */
3080 /* the left side bearing is the xMin, and the top side */
3081 /* bearing the yMax. */
3083 /* For composite glyphs, return only left side bearing and */
3084 /* advance width. */
3085 if ( load_flags
& FT_LOAD_NO_RECURSE
)
3087 FT_Slot_Internal internal
= glyph
->root
.internal
;
3090 glyph
->root
.metrics
.horiBearingX
= decoder
.builder
.left_bearing
.x
;
3091 glyph
->root
.metrics
.horiAdvance
= decoder
.glyph_width
;
3092 internal
->glyph_matrix
= font_matrix
;
3093 internal
->glyph_delta
= font_offset
;
3094 internal
->glyph_transformed
= 1;
3099 FT_Glyph_Metrics
* metrics
= &glyph
->root
.metrics
;
3100 FT_Bool has_vertical_info
;
3103 if ( face
->horizontal
.number_Of_HMetrics
)
3105 FT_Short horiBearingX
= 0;
3106 FT_UShort horiAdvance
= 0;
3109 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 0,
3113 metrics
->horiAdvance
= horiAdvance
;
3114 metrics
->horiBearingX
= horiBearingX
;
3115 glyph
->root
.linearHoriAdvance
= horiAdvance
;
3119 /* copy the _unscaled_ advance width */
3120 metrics
->horiAdvance
= decoder
.glyph_width
;
3121 glyph
->root
.linearHoriAdvance
= decoder
.glyph_width
;
3124 glyph
->root
.internal
->glyph_transformed
= 0;
3126 has_vertical_info
= FT_BOOL( face
->vertical_info
&&
3127 face
->vertical
.number_Of_VMetrics
> 0 );
3129 /* get the vertical metrics from the vmtx table if we have one */
3130 if ( has_vertical_info
)
3132 FT_Short vertBearingY
= 0;
3133 FT_UShort vertAdvance
= 0;
3136 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 1,
3140 metrics
->vertBearingY
= vertBearingY
;
3141 metrics
->vertAdvance
= vertAdvance
;
3145 /* make up vertical ones */
3146 if ( face
->os2
.version
!= 0xFFFFU
)
3147 metrics
->vertAdvance
= (FT_Pos
)( face
->os2
.sTypoAscender
-
3148 face
->os2
.sTypoDescender
);
3150 metrics
->vertAdvance
= (FT_Pos
)( face
->horizontal
.Ascender
-
3151 face
->horizontal
.Descender
);
3154 glyph
->root
.linearVertAdvance
= metrics
->vertAdvance
;
3156 glyph
->root
.format
= FT_GLYPH_FORMAT_OUTLINE
;
3158 glyph
->root
.outline
.flags
= 0;
3159 if ( size
&& size
->root
.metrics
.y_ppem
< 24 )
3160 glyph
->root
.outline
.flags
|= FT_OUTLINE_HIGH_PRECISION
;
3162 glyph
->root
.outline
.flags
|= FT_OUTLINE_REVERSE_FILL
;
3164 /* apply the font matrix, if any */
3165 if ( font_matrix
.xx
!= 0x10000L
|| font_matrix
.yy
!= 0x10000L
||
3166 font_matrix
.xy
!= 0 || font_matrix
.yx
!= 0 )
3168 FT_Outline_Transform( &glyph
->root
.outline
, &font_matrix
);
3170 metrics
->horiAdvance
= FT_MulFix( metrics
->horiAdvance
,
3172 metrics
->vertAdvance
= FT_MulFix( metrics
->vertAdvance
,
3176 if ( font_offset
.x
|| font_offset
.y
)
3178 FT_Outline_Translate( &glyph
->root
.outline
,
3182 metrics
->horiAdvance
+= font_offset
.x
;
3183 metrics
->vertAdvance
+= font_offset
.y
;
3186 if ( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 || force_scaling
)
3188 /* scale the outline and the metrics */
3190 FT_Outline
* cur
= &glyph
->root
.outline
;
3191 FT_Vector
* vec
= cur
->points
;
3192 FT_Fixed x_scale
= glyph
->x_scale
;
3193 FT_Fixed y_scale
= glyph
->y_scale
;
3196 /* First of all, scale the points */
3197 if ( !hinting
|| !decoder
.builder
.hints_funcs
)
3198 for ( n
= cur
->n_points
; n
> 0; n
--, vec
++ )
3200 vec
->x
= FT_MulFix( vec
->x
, x_scale
);
3201 vec
->y
= FT_MulFix( vec
->y
, y_scale
);
3204 /* Then scale the metrics */
3205 metrics
->horiAdvance
= FT_MulFix( metrics
->horiAdvance
, x_scale
);
3206 metrics
->vertAdvance
= FT_MulFix( metrics
->vertAdvance
, y_scale
);
3209 /* compute the other metrics */
3210 FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox
);
3212 metrics
->width
= cbox
.xMax
- cbox
.xMin
;
3213 metrics
->height
= cbox
.yMax
- cbox
.yMin
;
3215 metrics
->horiBearingX
= cbox
.xMin
;
3216 metrics
->horiBearingY
= cbox
.yMax
;
3218 if ( has_vertical_info
)
3219 metrics
->vertBearingX
= metrics
->horiBearingX
-
3220 metrics
->horiAdvance
/ 2;
3223 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
3224 ft_synthesize_vertical_metrics( metrics
,
3225 metrics
->vertAdvance
);