1 /***************************************************************************/
5 /* OpenType Glyph Loader (body). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
11 /* This file is part of the FreeType project, and may only be used, */
12 /* modified, and distributed under the terms of the FreeType project */
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14 /* this file you indicate that you have read the license and */
15 /* understand and accept it fully. */
17 /***************************************************************************/
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_INTERNAL_SFNT_H
25 #include FT_INTERNAL_POSTSCRIPT_HINTS_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 typedef enum CFF_Operator_
78 cff_op_dotsection
, /* deprecated, acts as no-op */
112 /* Type 1 opcodes: invalid but seen in real life */
115 cff_op_callothersubr
,
119 cff_op_setcurrentpoint
,
127 #define CFF_COUNT_CHECK_WIDTH 0x80
128 #define CFF_COUNT_EXACT 0x40
129 #define CFF_COUNT_CLEAR_STACK 0x20
131 /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */
132 /* used for checking the width and requested numbers of arguments */
133 /* only; they are set to zero afterwards */
135 /* the other two flags are informative only and unused currently */
137 static const FT_Byte cff_argument_counts
[] =
141 2 | CFF_COUNT_CHECK_WIDTH
| CFF_COUNT_EXACT
, /* rmoveto */
142 1 | CFF_COUNT_CHECK_WIDTH
| CFF_COUNT_EXACT
,
143 1 | CFF_COUNT_CHECK_WIDTH
| CFF_COUNT_EXACT
,
145 0 | CFF_COUNT_CLEAR_STACK
, /* rlineto */
146 0 | CFF_COUNT_CLEAR_STACK
,
147 0 | CFF_COUNT_CLEAR_STACK
,
149 0 | CFF_COUNT_CLEAR_STACK
, /* rrcurveto */
150 0 | CFF_COUNT_CLEAR_STACK
,
151 0 | CFF_COUNT_CLEAR_STACK
,
152 0 | CFF_COUNT_CLEAR_STACK
,
153 0 | CFF_COUNT_CLEAR_STACK
,
154 0 | CFF_COUNT_CLEAR_STACK
,
155 0 | CFF_COUNT_CLEAR_STACK
,
162 0 | CFF_COUNT_CHECK_WIDTH
, /* endchar */
164 2 | CFF_COUNT_CHECK_WIDTH
, /* hstem */
165 2 | CFF_COUNT_CHECK_WIDTH
,
166 2 | CFF_COUNT_CHECK_WIDTH
,
167 2 | CFF_COUNT_CHECK_WIDTH
,
169 0 | CFF_COUNT_CHECK_WIDTH
, /* hintmask */
170 0 | CFF_COUNT_CHECK_WIDTH
, /* cntrmask */
211 2 /* setcurrentpoint */
215 /*************************************************************************/
216 /*************************************************************************/
217 /*************************************************************************/
218 /********** *********/
219 /********** *********/
220 /********** GENERIC CHARSTRING PARSING *********/
221 /********** *********/
222 /********** *********/
223 /*************************************************************************/
224 /*************************************************************************/
225 /*************************************************************************/
228 /*************************************************************************/
231 /* cff_builder_init */
234 /* Initializes a given glyph builder. */
237 /* builder :: A pointer to the glyph builder to initialize. */
240 /* face :: The current face object. */
242 /* size :: The current size object. */
244 /* glyph :: The current glyph object. */
246 /* hinting :: Whether hinting is active. */
249 cff_builder_init( CFF_Builder
* builder
,
255 builder
->path_begun
= 0;
256 builder
->load_points
= 1;
258 builder
->face
= face
;
259 builder
->glyph
= glyph
;
260 builder
->memory
= face
->root
.memory
;
264 FT_GlyphLoader loader
= glyph
->root
.internal
->loader
;
267 builder
->loader
= loader
;
268 builder
->base
= &loader
->base
.outline
;
269 builder
->current
= &loader
->current
.outline
;
270 FT_GlyphLoader_Rewind( loader
);
272 builder
->hints_globals
= 0;
273 builder
->hints_funcs
= 0;
275 if ( hinting
&& size
)
277 CFF_Internal internal
= (CFF_Internal
)size
->root
.internal
;
280 builder
->hints_globals
= (void *)internal
->topfont
;
281 builder
->hints_funcs
= glyph
->root
.internal
->glyph_hints
;
288 builder
->left_bearing
.x
= 0;
289 builder
->left_bearing
.y
= 0;
290 builder
->advance
.x
= 0;
291 builder
->advance
.y
= 0;
295 /*************************************************************************/
298 /* cff_builder_done */
301 /* Finalizes a given glyph builder. Its contents can still be used */
302 /* after the call, but the function saves important information */
303 /* within the corresponding glyph slot. */
306 /* builder :: A pointer to the glyph builder to finalize. */
309 cff_builder_done( CFF_Builder
* builder
)
311 CFF_GlyphSlot glyph
= builder
->glyph
;
315 glyph
->root
.outline
= *builder
->base
;
319 /*************************************************************************/
322 /* cff_compute_bias */
325 /* Computes the bias value in dependence of the number of glyph */
329 /* in_charstring_type :: The `CharstringType' value of the top DICT */
332 /* num_subrs :: The number of glyph subroutines. */
335 /* The bias value. */
337 cff_compute_bias( FT_Int in_charstring_type
,
343 if ( in_charstring_type
== 1 )
345 else if ( num_subrs
< 1240 )
347 else if ( num_subrs
< 33900U )
356 /*************************************************************************/
359 /* cff_decoder_init */
362 /* Initializes a given glyph decoder. */
365 /* decoder :: A pointer to the glyph builder to initialize. */
368 /* face :: The current face object. */
370 /* size :: The current size object. */
372 /* slot :: The current glyph object. */
374 /* hinting :: Whether hinting is active. */
376 /* hint_mode :: The hinting mode. */
379 cff_decoder_init( CFF_Decoder
* decoder
,
384 FT_Render_Mode hint_mode
)
386 CFF_Font cff
= (CFF_Font
)face
->extra
.data
;
389 /* clear everything */
390 FT_MEM_ZERO( decoder
, sizeof ( *decoder
) );
392 /* initialize builder */
393 cff_builder_init( &decoder
->builder
, face
, size
, slot
, hinting
);
395 /* initialize Type2 decoder */
397 decoder
->num_globals
= cff
->num_global_subrs
;
398 decoder
->globals
= cff
->global_subrs
;
399 decoder
->globals_bias
= cff_compute_bias(
400 cff
->top_font
.font_dict
.charstring_type
,
401 decoder
->num_globals
);
403 decoder
->hint_mode
= hint_mode
;
407 /* this function is used to select the subfont */
408 /* and the locals subrs array */
409 FT_LOCAL_DEF( FT_Error
)
410 cff_decoder_prepare( CFF_Decoder
* decoder
,
412 FT_UInt glyph_index
)
414 CFF_Builder
*builder
= &decoder
->builder
;
415 CFF_Font cff
= (CFF_Font
)builder
->face
->extra
.data
;
416 CFF_SubFont sub
= &cff
->top_font
;
417 FT_Error error
= CFF_Err_Ok
;
420 /* manage CID fonts */
421 if ( cff
->num_subfonts
)
423 FT_Byte fd_index
= cff_fd_select_get( &cff
->fd_select
, glyph_index
);
426 if ( fd_index
>= cff
->num_subfonts
)
428 FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
429 error
= CFF_Err_Invalid_File_Format
;
433 FT_TRACE4(( "glyph index %d (subfont %d):\n", glyph_index
, fd_index
));
435 sub
= cff
->subfonts
[fd_index
];
437 if ( builder
->hints_funcs
&& size
)
439 CFF_Internal internal
= (CFF_Internal
)size
->root
.internal
;
442 /* for CFFs without subfonts, this value has already been set */
443 builder
->hints_globals
= (void *)internal
->subfonts
[fd_index
];
446 #ifdef FT_DEBUG_LEVEL_TRACE
448 FT_TRACE4(( "glyph index %d:\n", glyph_index
));
451 decoder
->num_locals
= sub
->num_local_subrs
;
452 decoder
->locals
= sub
->local_subrs
;
453 decoder
->locals_bias
= cff_compute_bias(
454 decoder
->cff
->top_font
.font_dict
.charstring_type
,
455 decoder
->num_locals
);
457 decoder
->glyph_width
= sub
->private_dict
.default_width
;
458 decoder
->nominal_width
= sub
->private_dict
.nominal_width
;
465 /* check that there is enough space for `count' more points */
467 check_points( CFF_Builder
* builder
,
470 return FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, count
, 0 );
474 /* add a new point, do not check space */
476 cff_builder_add_point( CFF_Builder
* builder
,
481 FT_Outline
* outline
= builder
->current
;
484 if ( builder
->load_points
)
486 FT_Vector
* point
= outline
->points
+ outline
->n_points
;
487 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
;
492 *control
= (FT_Byte
)( flag
? FT_CURVE_TAG_ON
: FT_CURVE_TAG_CUBIC
);
499 /* check space for a new on-curve point, then add it */
501 cff_builder_add_point1( CFF_Builder
* builder
,
508 error
= check_points( builder
, 1 );
510 cff_builder_add_point( builder
, x
, y
, 1 );
516 /* check space for a new contour, then add it */
518 cff_builder_add_contour( CFF_Builder
* builder
)
520 FT_Outline
* outline
= builder
->current
;
524 if ( !builder
->load_points
)
526 outline
->n_contours
++;
530 error
= FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, 0, 1 );
533 if ( outline
->n_contours
> 0 )
534 outline
->contours
[outline
->n_contours
- 1] =
535 (short)( outline
->n_points
- 1 );
537 outline
->n_contours
++;
544 /* if a path was begun, add its first on-curve point */
546 cff_builder_start_point( CFF_Builder
* builder
,
550 FT_Error error
= CFF_Err_Ok
;
553 /* test whether we are building a new contour */
554 if ( !builder
->path_begun
)
556 builder
->path_begun
= 1;
557 error
= cff_builder_add_contour( builder
);
559 error
= cff_builder_add_point1( builder
, x
, y
);
566 /* close the current contour */
568 cff_builder_close_contour( CFF_Builder
* builder
)
570 FT_Outline
* outline
= builder
->current
;
577 first
= outline
->n_contours
<= 1
578 ? 0 : outline
->contours
[outline
->n_contours
- 2] + 1;
580 /* We must not include the last point in the path if it */
581 /* is located on the first point. */
582 if ( outline
->n_points
> 1 )
584 FT_Vector
* p1
= outline
->points
+ first
;
585 FT_Vector
* p2
= outline
->points
+ outline
->n_points
- 1;
586 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
- 1;
589 /* `delete' last point only if it coincides with the first */
590 /* point and if it is not a control point (which can happen). */
591 if ( p1
->x
== p2
->x
&& p1
->y
== p2
->y
)
592 if ( *control
== FT_CURVE_TAG_ON
)
596 if ( outline
->n_contours
> 0 )
598 /* Don't add contours only consisting of one point, i.e., */
599 /* check whether begin point and last point are the same. */
600 if ( first
== outline
->n_points
- 1 )
602 outline
->n_contours
--;
606 outline
->contours
[outline
->n_contours
- 1] =
607 (short)( outline
->n_points
- 1 );
613 cff_lookup_glyph_by_stdcharcode( CFF_Font cff
,
620 /* CID-keyed fonts don't have glyph names */
621 if ( !cff
->charset
.sids
)
624 /* check range of standard char code */
625 if ( charcode
< 0 || charcode
> 255 )
628 /* Get code to SID mapping from `cff_standard_encoding'. */
629 glyph_sid
= cff_get_standard_encoding( (FT_UInt
)charcode
);
631 for ( n
= 0; n
< cff
->num_glyphs
; n
++ )
633 if ( cff
->charset
.sids
[n
] == glyph_sid
)
642 cff_get_glyph_data( TT_Face face
,
647 #ifdef FT_CONFIG_OPTION_INCREMENTAL
648 /* For incremental fonts get the character data using the */
649 /* callback function. */
650 if ( face
->root
.internal
->incremental_interface
)
654 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_data(
655 face
->root
.internal
->incremental_interface
->object
,
656 glyph_index
, &data
);
659 *pointer
= (FT_Byte
*)data
.pointer
;
660 *length
= data
.length
;
665 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
668 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
671 return cff_index_access_element( &cff
->charstrings_index
, glyph_index
,
678 cff_free_glyph_data( TT_Face face
,
682 #ifndef FT_CONFIG_OPTION_INCREMENTAL
686 #ifdef FT_CONFIG_OPTION_INCREMENTAL
687 /* For incremental fonts get the character data using the */
688 /* callback function. */
689 if ( face
->root
.internal
->incremental_interface
)
694 data
.pointer
= *pointer
;
695 data
.length
= length
;
697 face
->root
.internal
->incremental_interface
->funcs
->free_glyph_data(
698 face
->root
.internal
->incremental_interface
->object
, &data
);
701 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
704 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
707 cff_index_forget_element( &cff
->charstrings_index
, pointer
);
713 cff_operator_seac( CFF_Decoder
* decoder
,
721 CFF_Builder
* builder
= &decoder
->builder
;
722 FT_Int bchar_index
, achar_index
;
723 TT_Face face
= decoder
->builder
.face
;
724 FT_Vector left_bearing
, advance
;
726 FT_ULong charstring_len
;
732 FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
733 return CFF_Err_Syntax_Error
;
736 adx
+= decoder
->builder
.left_bearing
.x
;
737 ady
+= decoder
->builder
.left_bearing
.y
;
739 #ifdef FT_CONFIG_OPTION_INCREMENTAL
740 /* Incremental fonts don't necessarily have valid charsets. */
741 /* They use the character code, not the glyph index, in this case. */
742 if ( face
->root
.internal
->incremental_interface
)
748 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
750 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
753 bchar_index
= cff_lookup_glyph_by_stdcharcode( cff
, bchar
);
754 achar_index
= cff_lookup_glyph_by_stdcharcode( cff
, achar
);
757 if ( bchar_index
< 0 || achar_index
< 0 )
759 FT_ERROR(( "cff_operator_seac:"
760 " invalid seac character code arguments\n" ));
761 return CFF_Err_Syntax_Error
;
764 /* If we are trying to load a composite glyph, do not load the */
765 /* accent character and return the array of subglyphs. */
766 if ( builder
->no_recurse
)
768 FT_GlyphSlot glyph
= (FT_GlyphSlot
)builder
->glyph
;
769 FT_GlyphLoader loader
= glyph
->internal
->loader
;
773 /* reallocate subglyph array if necessary */
774 error
= FT_GlyphLoader_CheckSubGlyphs( loader
, 2 );
778 subg
= loader
->current
.subglyphs
;
780 /* subglyph 0 = base character */
781 subg
->index
= bchar_index
;
782 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
|
783 FT_SUBGLYPH_FLAG_USE_MY_METRICS
;
788 /* subglyph 1 = accent character */
789 subg
->index
= achar_index
;
790 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
;
791 subg
->arg1
= (FT_Int
)( adx
>> 16 );
792 subg
->arg2
= (FT_Int
)( ady
>> 16 );
794 /* set up remaining glyph fields */
795 glyph
->num_subglyphs
= 2;
796 glyph
->subglyphs
= loader
->base
.subglyphs
;
797 glyph
->format
= FT_GLYPH_FORMAT_COMPOSITE
;
799 loader
->current
.num_subglyphs
= 2;
802 FT_GlyphLoader_Prepare( builder
->loader
);
804 /* First load `bchar' in builder */
805 error
= cff_get_glyph_data( face
, bchar_index
,
806 &charstring
, &charstring_len
);
809 /* the seac operator must not be nested */
810 decoder
->seac
= TRUE
;
811 error
= cff_decoder_parse_charstrings( decoder
, charstring
,
813 decoder
->seac
= FALSE
;
818 cff_free_glyph_data( face
, &charstring
, charstring_len
);
821 /* Save the left bearing, advance and glyph width of the base */
822 /* character as they will be erased by the next load. */
824 left_bearing
= builder
->left_bearing
;
825 advance
= builder
->advance
;
826 glyph_width
= decoder
->glyph_width
;
828 builder
->left_bearing
.x
= 0;
829 builder
->left_bearing
.y
= 0;
831 builder
->pos_x
= adx
- asb
;
832 builder
->pos_y
= ady
;
834 /* Now load `achar' on top of the base outline. */
835 error
= cff_get_glyph_data( face
, achar_index
,
836 &charstring
, &charstring_len
);
839 /* the seac operator must not be nested */
840 decoder
->seac
= TRUE
;
841 error
= cff_decoder_parse_charstrings( decoder
, charstring
,
843 decoder
->seac
= FALSE
;
848 cff_free_glyph_data( face
, &charstring
, charstring_len
);
851 /* Restore the left side bearing, advance and glyph width */
852 /* of the base character. */
853 builder
->left_bearing
= left_bearing
;
854 builder
->advance
= advance
;
855 decoder
->glyph_width
= glyph_width
;
865 /*************************************************************************/
868 /* cff_decoder_parse_charstrings */
871 /* Parses a given Type 2 charstrings program. */
874 /* decoder :: The current Type 1 decoder. */
877 /* charstring_base :: The base of the charstring stream. */
879 /* charstring_len :: The length in bytes of the charstring stream. */
882 /* FreeType error code. 0 means success. */
884 FT_LOCAL_DEF( FT_Error
)
885 cff_decoder_parse_charstrings( CFF_Decoder
* decoder
,
886 FT_Byte
* charstring_base
,
887 FT_ULong charstring_len
)
890 CFF_Decoder_Zone
* zone
;
893 CFF_Builder
* builder
= &decoder
->builder
;
897 FT_Int charstring_type
=
898 decoder
->cff
->top_font
.font_dict
.charstring_type
;
900 T2_Hints_Funcs hinter
;
903 /* set default width */
904 decoder
->num_hints
= 0;
905 decoder
->read_width
= 1;
907 /* compute random seed from stack address of parameter */
908 seed
= (FT_Fixed
)( ( (FT_PtrDist
)(char*)&seed
^
909 (FT_PtrDist
)(char*)&decoder
^
910 (FT_PtrDist
)(char*)&charstring_base
) &
912 seed
= ( seed
^ ( seed
>> 10 ) ^ ( seed
>> 20 ) ) & 0xFFFFL
;
916 /* initialize the decoder */
917 decoder
->top
= decoder
->stack
;
918 decoder
->zone
= decoder
->zones
;
919 zone
= decoder
->zones
;
920 stack
= decoder
->top
;
922 hinter
= (T2_Hints_Funcs
)builder
->hints_funcs
;
924 builder
->path_begun
= 0;
926 zone
->base
= charstring_base
;
927 limit
= zone
->limit
= charstring_base
+ charstring_len
;
928 ip
= zone
->cursor
= zone
->base
;
935 /* begin hints recording session, if any */
937 hinter
->open( hinter
->hints
);
939 /* now execute loop */
946 /********************************************************************/
948 /* Decode operator or operand */
951 if ( v
>= 32 || v
== 28 )
957 /* this is an operand, push it on the stack */
960 if ( ip
+ 1 >= limit
)
962 val
= (FT_Short
)( ( (FT_Short
)ip
[0] << 8 ) | ip
[1] );
966 val
= (FT_Int32
)v
- 139;
971 val
= ( (FT_Int32
)v
- 247 ) * 256 + *ip
++ + 108;
977 val
= -( (FT_Int32
)v
- 251 ) * 256 - *ip
++ - 108;
981 if ( ip
+ 3 >= limit
)
983 val
= ( (FT_Int32
)ip
[0] << 24 ) |
984 ( (FT_Int32
)ip
[1] << 16 ) |
985 ( (FT_Int32
)ip
[2] << 8 ) |
988 if ( charstring_type
== 2 )
991 if ( decoder
->top
- stack
>= CFF_MAX_OPERANDS
)
995 *decoder
->top
++ = val
;
997 #ifdef FT_DEBUG_LEVEL_TRACE
998 if ( !( val
& 0xFFFFL
) )
999 FT_TRACE4(( " %ld", (FT_Int32
)( val
>> 16 ) ));
1001 FT_TRACE4(( " %.2f", val
/ 65536.0 ));
1007 /* The specification says that normally arguments are to be taken */
1008 /* from the bottom of the stack. However, this seems not to be */
1009 /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
1010 /* arguments similar to a PS interpreter. */
1012 FT_Fixed
* args
= decoder
->top
;
1013 FT_Int num_args
= (FT_Int
)( args
- decoder
->stack
);
1018 op
= cff_op_unknown
;
1029 op
= cff_op_vmoveto
;
1032 op
= cff_op_rlineto
;
1035 op
= cff_op_hlineto
;
1038 op
= cff_op_vlineto
;
1041 op
= cff_op_rrcurveto
;
1044 op
= cff_op_closepath
;
1047 op
= cff_op_callsubr
;
1061 op
= cff_op_dotsection
;
1063 case 1: /* this is actually the Type1 vstem3 operator */
1066 case 2: /* this is actually the Type1 hstem3 operator */
1109 op
= cff_op_callothersubr
;
1148 op
= cff_op_setcurrentpoint
;
1163 /* decrement ip for syntax error message */
1172 op
= cff_op_endchar
;
1178 op
= cff_op_hstemhm
;
1181 op
= cff_op_hintmask
;
1184 op
= cff_op_cntrmask
;
1187 op
= cff_op_rmoveto
;
1190 op
= cff_op_hmoveto
;
1193 op
= cff_op_vstemhm
;
1196 op
= cff_op_rcurveline
;
1199 op
= cff_op_rlinecurve
;
1202 op
= cff_op_vvcurveto
;
1205 op
= cff_op_hhcurveto
;
1208 op
= cff_op_callgsubr
;
1211 op
= cff_op_vhcurveto
;
1214 op
= cff_op_hvcurveto
;
1220 if ( op
== cff_op_unknown
)
1223 /* check arguments */
1224 req_args
= cff_argument_counts
[op
];
1225 if ( req_args
& CFF_COUNT_CHECK_WIDTH
)
1227 if ( num_args
> 0 && decoder
->read_width
)
1229 /* If `nominal_width' is non-zero, the number is really a */
1230 /* difference against `nominal_width'. Else, the number here */
1231 /* is truly a width, not a difference against `nominal_width'. */
1232 /* If the font does not set `nominal_width', then */
1233 /* `nominal_width' defaults to zero, and so we can set */
1234 /* `glyph_width' to `nominal_width' plus number on the stack */
1235 /* -- for either case. */
1237 FT_Int set_width_ok
;
1242 case cff_op_hmoveto
:
1243 case cff_op_vmoveto
:
1244 set_width_ok
= num_args
& 2;
1249 case cff_op_hstemhm
:
1250 case cff_op_vstemhm
:
1251 case cff_op_rmoveto
:
1252 case cff_op_hintmask
:
1253 case cff_op_cntrmask
:
1254 set_width_ok
= num_args
& 1;
1257 case cff_op_endchar
:
1258 /* If there is a width specified for endchar, we either have */
1259 /* 1 argument or 5 arguments. We like to argue. */
1260 set_width_ok
= ( num_args
== 5 ) || ( num_args
== 1 );
1270 decoder
->glyph_width
= decoder
->nominal_width
+
1273 if ( decoder
->width_only
)
1275 /* we only want the advance width; stop here */
1279 /* Consumed an argument. */
1284 decoder
->read_width
= 0;
1289 if ( num_args
< req_args
)
1290 goto Stack_Underflow
;
1292 num_args
-= req_args
;
1294 /* At this point, `args' points to the first argument of the */
1295 /* operand in case `req_args' isn't zero. Otherwise, we have */
1296 /* to adjust `args' manually. */
1298 /* Note that we only pop arguments from the stack which we */
1299 /* really need and can digest so that we can continue in case */
1300 /* of superfluous stack elements. */
1306 case cff_op_hstemhm
:
1307 case cff_op_vstemhm
:
1308 /* the number of arguments is always even here */
1310 op
== cff_op_hstem
? " hstem\n" :
1311 ( op
== cff_op_vstem
? " vstem\n" :
1312 ( op
== cff_op_hstemhm
? " hstemhm\n" : " vstemhm\n" ) ) ));
1315 hinter
->stems( hinter
->hints
,
1316 ( op
== cff_op_hstem
|| op
== cff_op_hstemhm
),
1318 args
- ( num_args
& ~1 ) );
1320 decoder
->num_hints
+= num_args
/ 2;
1324 case cff_op_hintmask
:
1325 case cff_op_cntrmask
:
1326 FT_TRACE4(( op
== cff_op_hintmask
? " hintmask" : " cntrmask" ));
1328 /* implement vstem when needed -- */
1329 /* the specification doesn't say it, but this also works */
1330 /* with the 'cntrmask' operator */
1335 hinter
->stems( hinter
->hints
,
1338 args
- ( num_args
& ~1 ) );
1340 decoder
->num_hints
+= num_args
/ 2;
1345 if ( op
== cff_op_hintmask
)
1346 hinter
->hintmask( hinter
->hints
,
1347 builder
->current
->n_points
,
1351 hinter
->counter( hinter
->hints
,
1356 #ifdef FT_DEBUG_LEVEL_TRACE
1361 FT_TRACE4(( " (maskbytes: " ));
1364 maskbyte
< (FT_UInt
)(( decoder
->num_hints
+ 7 ) >> 3);
1366 FT_TRACE4(( "0x%02X", *ip
));
1368 FT_TRACE4(( ")\n" ));
1371 ip
+= ( decoder
->num_hints
+ 7 ) >> 3;
1378 case cff_op_rmoveto
:
1379 FT_TRACE4(( " rmoveto\n" ));
1381 cff_builder_close_contour( builder
);
1382 builder
->path_begun
= 0;
1388 case cff_op_vmoveto
:
1389 FT_TRACE4(( " vmoveto\n" ));
1391 cff_builder_close_contour( builder
);
1392 builder
->path_begun
= 0;
1397 case cff_op_hmoveto
:
1398 FT_TRACE4(( " hmoveto\n" ));
1400 cff_builder_close_contour( builder
);
1401 builder
->path_begun
= 0;
1406 case cff_op_rlineto
:
1407 FT_TRACE4(( " rlineto\n" ));
1409 if ( cff_builder_start_point ( builder
, x
, y
) ||
1410 check_points( builder
, num_args
/ 2 ) )
1414 goto Stack_Underflow
;
1416 args
-= num_args
& ~1;
1417 while ( args
< decoder
->top
)
1421 cff_builder_add_point( builder
, x
, y
, 1 );
1427 case cff_op_hlineto
:
1428 case cff_op_vlineto
:
1430 FT_Int phase
= ( op
== cff_op_hlineto
);
1433 FT_TRACE4(( op
== cff_op_hlineto
? " hlineto\n"
1437 goto Stack_Underflow
;
1439 if ( cff_builder_start_point ( builder
, x
, y
) ||
1440 check_points( builder
, num_args
) )
1444 while ( args
< decoder
->top
)
1451 if ( cff_builder_add_point1( builder
, x
, y
) )
1461 case cff_op_rrcurveto
:
1466 FT_TRACE4(( " rrcurveto\n" ));
1469 goto Stack_Underflow
;
1471 nargs
= num_args
- num_args
% 6;
1473 if ( cff_builder_start_point ( builder
, x
, y
) ||
1474 check_points( builder
, nargs
/ 2 ) )
1478 while ( args
< decoder
->top
)
1482 cff_builder_add_point( builder
, x
, y
, 0 );
1485 cff_builder_add_point( builder
, x
, y
, 0 );
1488 cff_builder_add_point( builder
, x
, y
, 1 );
1495 case cff_op_vvcurveto
:
1500 FT_TRACE4(( " vvcurveto\n" ));
1503 goto Stack_Underflow
;
1505 /* if num_args isn't of the form 4n or 4n+1, */
1506 /* we reduce it to 4n+1 */
1508 nargs
= num_args
- num_args
% 4;
1509 if ( num_args
- nargs
> 0 )
1512 if ( cff_builder_start_point( builder
, x
, y
) )
1524 if ( check_points( builder
, 3 * ( nargs
/ 4 ) ) )
1527 while ( args
< decoder
->top
)
1530 cff_builder_add_point( builder
, x
, y
, 0 );
1533 cff_builder_add_point( builder
, x
, y
, 0 );
1535 cff_builder_add_point( builder
, x
, y
, 1 );
1542 case cff_op_hhcurveto
:
1547 FT_TRACE4(( " hhcurveto\n" ));
1550 goto Stack_Underflow
;
1552 /* if num_args isn't of the form 4n or 4n+1, */
1553 /* we reduce it to 4n+1 */
1555 nargs
= num_args
- num_args
% 4;
1556 if ( num_args
- nargs
> 0 )
1559 if ( cff_builder_start_point( builder
, x
, y
) )
1570 if ( check_points( builder
, 3 * ( nargs
/ 4 ) ) )
1573 while ( args
< decoder
->top
)
1576 cff_builder_add_point( builder
, x
, y
, 0 );
1579 cff_builder_add_point( builder
, x
, y
, 0 );
1581 cff_builder_add_point( builder
, x
, y
, 1 );
1588 case cff_op_vhcurveto
:
1589 case cff_op_hvcurveto
:
1595 FT_TRACE4(( op
== cff_op_vhcurveto
? " vhcurveto\n"
1596 : " hvcurveto\n" ));
1598 if ( cff_builder_start_point( builder
, x
, y
) )
1602 goto Stack_Underflow
;
1604 /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
1605 /* we reduce it to the largest one which fits */
1607 nargs
= num_args
- num_args
% 4;
1608 if ( num_args
- nargs
> 0 )
1612 if ( check_points( builder
, ( nargs
/ 4 ) * 3 ) )
1613 goto Stack_Underflow
;
1615 phase
= ( op
== cff_op_hvcurveto
);
1617 while ( nargs
>= 4 )
1623 cff_builder_add_point( builder
, x
, y
, 0 );
1626 cff_builder_add_point( builder
, x
, y
, 0 );
1630 cff_builder_add_point( builder
, x
, y
, 1 );
1635 cff_builder_add_point( builder
, x
, y
, 0 );
1638 cff_builder_add_point( builder
, x
, y
, 0 );
1642 cff_builder_add_point( builder
, x
, y
, 1 );
1651 case cff_op_rlinecurve
:
1657 FT_TRACE4(( " rlinecurve\n" ));
1660 goto Stack_Underflow
;
1662 nargs
= num_args
& ~1;
1663 num_lines
= ( nargs
- 6 ) / 2;
1665 if ( cff_builder_start_point( builder
, x
, y
) ||
1666 check_points( builder
, num_lines
+ 3 ) )
1671 /* first, add the line segments */
1672 while ( num_lines
> 0 )
1676 cff_builder_add_point( builder
, x
, y
, 1 );
1681 /* then the curve */
1684 cff_builder_add_point( builder
, x
, y
, 0 );
1687 cff_builder_add_point( builder
, x
, y
, 0 );
1690 cff_builder_add_point( builder
, x
, y
, 1 );
1695 case cff_op_rcurveline
:
1701 FT_TRACE4(( " rcurveline\n" ));
1704 goto Stack_Underflow
;
1706 nargs
= num_args
- 2;
1707 nargs
= nargs
- nargs
% 6 + 2;
1708 num_curves
= ( nargs
- 2 ) / 6;
1710 if ( cff_builder_start_point ( builder
, x
, y
) ||
1711 check_points( builder
, num_curves
* 3 + 2 ) )
1716 /* first, add the curves */
1717 while ( num_curves
> 0 )
1721 cff_builder_add_point( builder
, x
, y
, 0 );
1724 cff_builder_add_point( builder
, x
, y
, 0 );
1727 cff_builder_add_point( builder
, x
, y
, 1 );
1732 /* then the final line */
1735 cff_builder_add_point( builder
, x
, y
, 1 );
1745 FT_TRACE4(( " hflex1\n" ));
1747 /* adding five more points: 4 control points, 1 on-curve point */
1748 /* -- make sure we have enough space for the start point if it */
1749 /* needs to be added */
1750 if ( cff_builder_start_point( builder
, x
, y
) ||
1751 check_points( builder
, 6 ) )
1754 /* record the starting point's y position for later use */
1757 /* first control point */
1760 cff_builder_add_point( builder
, x
, y
, 0 );
1762 /* second control point */
1765 cff_builder_add_point( builder
, x
, y
, 0 );
1767 /* join point; on curve, with y-value the same as the last */
1768 /* control point's y-value */
1770 cff_builder_add_point( builder
, x
, y
, 1 );
1772 /* third control point, with y-value the same as the join */
1773 /* point's y-value */
1775 cff_builder_add_point( builder
, x
, y
, 0 );
1777 /* fourth control point */
1780 cff_builder_add_point( builder
, x
, y
, 0 );
1782 /* ending point, with y-value the same as the start */
1785 cff_builder_add_point( builder
, x
, y
, 1 );
1796 FT_TRACE4(( " hflex\n" ));
1798 /* adding six more points; 4 control points, 2 on-curve points */
1799 if ( cff_builder_start_point( builder
, x
, y
) ||
1800 check_points( builder
, 6 ) )
1803 /* record the starting point's y-position for later use */
1806 /* first control point */
1808 cff_builder_add_point( builder
, x
, y
, 0 );
1810 /* second control point */
1813 cff_builder_add_point( builder
, x
, y
, 0 );
1815 /* join point; on curve, with y-value the same as the last */
1816 /* control point's y-value */
1818 cff_builder_add_point( builder
, x
, y
, 1 );
1820 /* third control point, with y-value the same as the join */
1821 /* point's y-value */
1823 cff_builder_add_point( builder
, x
, y
, 0 );
1825 /* fourth control point */
1828 cff_builder_add_point( builder
, x
, y
, 0 );
1830 /* ending point, with y-value the same as the start point's */
1831 /* y-value -- we don't add this point, though */
1833 cff_builder_add_point( builder
, x
, y
, 1 );
1841 FT_Pos start_x
, start_y
; /* record start x, y values for */
1843 FT_Fixed dx
= 0, dy
= 0; /* used in horizontal/vertical */
1844 /* algorithm below */
1845 FT_Int horizontal
, count
;
1849 FT_TRACE4(( " flex1\n" ));
1851 /* adding six more points; 4 control points, 2 on-curve points */
1852 if ( cff_builder_start_point( builder
, x
, y
) ||
1853 check_points( builder
, 6 ) )
1856 /* record the starting point's x, y position for later use */
1860 /* XXX: figure out whether this is supposed to be a horizontal */
1861 /* or vertical flex; the Type 2 specification is vague... */
1865 /* grab up to the last argument */
1866 for ( count
= 5; count
> 0; count
-- )
1878 /* strange test, but here it is... */
1879 horizontal
= ( dx
> dy
);
1881 for ( count
= 5; count
> 0; count
-- )
1885 cff_builder_add_point( builder
, x
, y
,
1886 (FT_Bool
)( count
== 3 ) );
1890 /* is last operand an x- or y-delta? */
1902 cff_builder_add_point( builder
, x
, y
, 1 );
1913 FT_TRACE4(( " flex\n" ));
1915 if ( cff_builder_start_point( builder
, x
, y
) ||
1916 check_points( builder
, 6 ) )
1919 for ( count
= 6; count
> 0; count
-- )
1923 cff_builder_add_point( builder
, x
, y
,
1924 (FT_Bool
)( count
== 4 || count
== 1 ) );
1933 FT_TRACE4(( " seac\n" ));
1935 error
= cff_operator_seac( decoder
,
1936 args
[0], args
[1], args
[2],
1937 (FT_Int
)( args
[3] >> 16 ),
1938 (FT_Int
)( args
[4] >> 16 ) );
1940 /* add current outline to the glyph slot */
1941 FT_GlyphLoader_Add( builder
->loader
);
1944 FT_TRACE4(( "\n" ));
1947 case cff_op_endchar
:
1948 FT_TRACE4(( " endchar\n" ));
1950 /* We are going to emulate the seac operator. */
1951 if ( num_args
>= 4 )
1953 /* Save glyph width so that the subglyphs don't overwrite it. */
1954 FT_Pos glyph_width
= decoder
->glyph_width
;
1956 error
= cff_operator_seac( decoder
,
1957 0L, args
[-4], args
[-3],
1958 (FT_Int
)( args
[-2] >> 16 ),
1959 (FT_Int
)( args
[-1] >> 16 ) );
1961 decoder
->glyph_width
= glyph_width
;
1968 cff_builder_close_contour( builder
);
1970 /* close hints recording session */
1973 if ( hinter
->close( hinter
->hints
,
1974 builder
->current
->n_points
) )
1977 /* apply hints to the loaded glyph outline now */
1978 hinter
->apply( hinter
->hints
,
1980 (PSH_Globals
)builder
->hints_globals
,
1981 decoder
->hint_mode
);
1984 /* add current outline to the glyph slot */
1985 FT_GlyphLoader_Add( builder
->loader
);
1989 FT_TRACE4(( "\n" ));
1993 FT_TRACE4(( " abs\n" ));
2001 FT_TRACE4(( " add\n" ));
2008 FT_TRACE4(( " sub\n" ));
2015 FT_TRACE4(( " div\n" ));
2017 args
[0] = FT_DivFix( args
[0], args
[1] );
2022 FT_TRACE4(( " neg\n" ));
2033 FT_TRACE4(( " rand\n" ));
2036 if ( Rand
>= 0x8000L
)
2040 seed
= FT_MulFix( seed
, 0x10000L
- seed
);
2048 FT_TRACE4(( " mul\n" ));
2050 args
[0] = FT_MulFix( args
[0], args
[1] );
2055 FT_TRACE4(( " sqrt\n" ));
2060 FT_Fixed root
= args
[0];
2066 new_root
= ( root
+ FT_DivFix( args
[0], root
) + 1 ) >> 1;
2067 if ( new_root
== root
|| count
<= 0 )
2080 FT_TRACE4(( " drop\n" ));
2089 FT_TRACE4(( " exch\n" ));
2100 FT_Int idx
= (FT_Int
)( args
[0] >> 16 );
2103 FT_TRACE4(( " index\n" ));
2107 else if ( idx
> num_args
- 2 )
2109 args
[0] = args
[-( idx
+ 1 )];
2116 FT_Int count
= (FT_Int
)( args
[0] >> 16 );
2117 FT_Int idx
= (FT_Int
)( args
[1] >> 16 );
2120 FT_TRACE4(( " roll\n" ));
2127 goto Stack_Underflow
;
2133 FT_Fixed tmp
= args
[count
- 1];
2137 for ( i
= count
- 2; i
>= 0; i
-- )
2138 args
[i
+ 1] = args
[i
];
2147 FT_Fixed tmp
= args
[0];
2151 for ( i
= 0; i
< count
- 1; i
++ )
2152 args
[i
] = args
[i
+ 1];
2153 args
[count
- 1] = tmp
;
2162 FT_TRACE4(( " dup\n" ));
2170 FT_Fixed val
= args
[0];
2171 FT_Int idx
= (FT_Int
)( args
[1] >> 16 );
2174 FT_TRACE4(( " put\n" ));
2176 if ( idx
>= 0 && idx
< CFF_MAX_TRANS_ELEMENTS
)
2177 decoder
->buildchar
[idx
] = val
;
2183 FT_Int idx
= (FT_Int
)( args
[0] >> 16 );
2187 FT_TRACE4(( " get\n" ));
2189 if ( idx
>= 0 && idx
< CFF_MAX_TRANS_ELEMENTS
)
2190 val
= decoder
->buildchar
[idx
];
2198 FT_TRACE4(( " store\n"));
2203 FT_TRACE4(( " load\n" ));
2207 case cff_op_dotsection
:
2208 /* this operator is deprecated and ignored by the parser */
2209 FT_TRACE4(( " dotsection\n" ));
2212 case cff_op_closepath
:
2213 /* this is an invalid Type 2 operator; however, there */
2214 /* exist fonts which are incorrectly converted from probably */
2215 /* Type 1 to CFF, and some parsers seem to accept it */
2217 FT_TRACE4(( " closepath (invalid op)\n" ));
2223 /* this is an invalid Type 2 operator; however, there */
2224 /* exist fonts which are incorrectly converted from probably */
2225 /* Type 1 to CFF, and some parsers seem to accept it */
2227 FT_TRACE4(( " hsbw (invalid op)\n" ));
2229 decoder
->glyph_width
= decoder
->nominal_width
+ ( args
[1] >> 16 );
2231 decoder
->builder
.left_bearing
.x
= args
[0];
2232 decoder
->builder
.left_bearing
.y
= 0;
2234 x
= decoder
->builder
.pos_x
+ args
[0];
2235 y
= decoder
->builder
.pos_y
;
2240 /* this is an invalid Type 2 operator; however, there */
2241 /* exist fonts which are incorrectly converted from probably */
2242 /* Type 1 to CFF, and some parsers seem to accept it */
2244 FT_TRACE4(( " sbw (invalid op)\n" ));
2246 decoder
->glyph_width
= decoder
->nominal_width
+ ( args
[2] >> 16 );
2248 decoder
->builder
.left_bearing
.x
= args
[0];
2249 decoder
->builder
.left_bearing
.y
= args
[1];
2251 x
= decoder
->builder
.pos_x
+ args
[0];
2252 y
= decoder
->builder
.pos_y
+ args
[1];
2256 case cff_op_setcurrentpoint
:
2257 /* this is an invalid Type 2 operator; however, there */
2258 /* exist fonts which are incorrectly converted from probably */
2259 /* Type 1 to CFF, and some parsers seem to accept it */
2261 FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
2263 x
= decoder
->builder
.pos_x
+ args
[0];
2264 y
= decoder
->builder
.pos_y
+ args
[1];
2268 case cff_op_callothersubr
:
2269 /* this is an invalid Type 2 operator; however, there */
2270 /* exist fonts which are incorrectly converted from probably */
2271 /* Type 1 to CFF, and some parsers seem to accept it */
2273 FT_TRACE4(( " callothersubr (invalid op)\n" ));
2275 /* subsequent `pop' operands should add the arguments, */
2276 /* this is the implementation described for `unknown' other */
2277 /* subroutines in the Type1 spec. */
2278 args
-= 2 + ( args
[-2] >> 16 );
2282 /* this is an invalid Type 2 operator; however, there */
2283 /* exist fonts which are incorrectly converted from probably */
2284 /* Type 1 to CFF, and some parsers seem to accept it */
2286 FT_TRACE4(( " pop (invalid op)\n" ));
2293 FT_Fixed cond
= args
[0] && args
[1];
2296 FT_TRACE4(( " and\n" ));
2298 args
[0] = cond
? 0x10000L
: 0;
2305 FT_Fixed cond
= args
[0] || args
[1];
2308 FT_TRACE4(( " or\n" ));
2310 args
[0] = cond
? 0x10000L
: 0;
2317 FT_Fixed cond
= !args
[0];
2320 FT_TRACE4(( " eq\n" ));
2322 args
[0] = cond
? 0x10000L
: 0;
2329 FT_Fixed cond
= ( args
[2] <= args
[3] );
2332 FT_TRACE4(( " ifelse\n" ));
2340 case cff_op_callsubr
:
2342 FT_UInt idx
= (FT_UInt
)( ( args
[0] >> 16 ) +
2343 decoder
->locals_bias
);
2346 FT_TRACE4(( " callsubr(%d)\n", idx
));
2348 if ( idx
>= decoder
->num_locals
)
2350 FT_ERROR(( "cff_decoder_parse_charstrings:"
2351 " invalid local subr index\n" ));
2355 if ( zone
- decoder
->zones
>= CFF_MAX_SUBRS_CALLS
)
2357 FT_ERROR(( "cff_decoder_parse_charstrings:"
2358 " too many nested subrs\n" ));
2362 zone
->cursor
= ip
; /* save current instruction pointer */
2365 zone
->base
= decoder
->locals
[idx
];
2366 zone
->limit
= decoder
->locals
[idx
+ 1];
2367 zone
->cursor
= zone
->base
;
2369 if ( !zone
->base
|| zone
->limit
== zone
->base
)
2371 FT_ERROR(( "cff_decoder_parse_charstrings:"
2372 " invoking empty subrs\n" ));
2376 decoder
->zone
= zone
;
2378 limit
= zone
->limit
;
2382 case cff_op_callgsubr
:
2384 FT_UInt idx
= (FT_UInt
)( ( args
[0] >> 16 ) +
2385 decoder
->globals_bias
);
2388 FT_TRACE4(( " callgsubr(%d)\n", idx
));
2390 if ( idx
>= decoder
->num_globals
)
2392 FT_ERROR(( "cff_decoder_parse_charstrings:"
2393 " invalid global subr index\n" ));
2397 if ( zone
- decoder
->zones
>= CFF_MAX_SUBRS_CALLS
)
2399 FT_ERROR(( "cff_decoder_parse_charstrings:"
2400 " too many nested subrs\n" ));
2404 zone
->cursor
= ip
; /* save current instruction pointer */
2407 zone
->base
= decoder
->globals
[idx
];
2408 zone
->limit
= decoder
->globals
[idx
+ 1];
2409 zone
->cursor
= zone
->base
;
2411 if ( !zone
->base
|| zone
->limit
== zone
->base
)
2413 FT_ERROR(( "cff_decoder_parse_charstrings:"
2414 " invoking empty subrs\n" ));
2418 decoder
->zone
= zone
;
2420 limit
= zone
->limit
;
2425 FT_TRACE4(( " return\n" ));
2427 if ( decoder
->zone
<= decoder
->zones
)
2429 FT_ERROR(( "cff_decoder_parse_charstrings:"
2430 " unexpected return\n" ));
2435 zone
= decoder
->zone
;
2437 limit
= zone
->limit
;
2442 FT_ERROR(( "Unimplemented opcode: %d", ip
[-1] ));
2445 FT_ERROR(( " %d", ip
[0] ));
2448 return CFF_Err_Unimplemented_Feature
;
2451 decoder
->top
= args
;
2453 } /* general operator processing */
2455 } /* while ip < limit */
2457 FT_TRACE4(( "..end..\n\n" ));
2463 FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
2464 return CFF_Err_Invalid_File_Format
;
2467 FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
2468 return CFF_Err_Too_Few_Arguments
;
2471 FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
2472 return CFF_Err_Stack_Overflow
;
2476 /*************************************************************************/
2477 /*************************************************************************/
2478 /*************************************************************************/
2479 /********** *********/
2480 /********** *********/
2481 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
2482 /********** *********/
2483 /********** The following code is in charge of computing *********/
2484 /********** the maximum advance width of the font. It *********/
2485 /********** quickly processes each glyph charstring to *********/
2486 /********** extract the value from either a `sbw' or `seac' *********/
2487 /********** operator. *********/
2488 /********** *********/
2489 /*************************************************************************/
2490 /*************************************************************************/
2491 /*************************************************************************/
2494 #if 0 /* unused until we support pure CFF fonts */
2497 FT_LOCAL_DEF( FT_Error
)
2498 cff_compute_max_advance( TT_Face face
,
2499 FT_Int
* max_advance
)
2501 FT_Error error
= CFF_Err_Ok
;
2502 CFF_Decoder decoder
;
2504 CFF_Font cff
= (CFF_Font
)face
->other
;
2509 /* Initialize load decoder */
2510 cff_decoder_init( &decoder
, face
, 0, 0, 0, 0 );
2512 decoder
.builder
.metrics_only
= 1;
2513 decoder
.builder
.load_points
= 0;
2515 /* For each glyph, parse the glyph charstring and extract */
2516 /* the advance width. */
2517 for ( glyph_index
= 0; glyph_index
< face
->root
.num_glyphs
;
2520 FT_Byte
* charstring
;
2521 FT_ULong charstring_len
;
2524 /* now get load the unscaled outline */
2525 error
= cff_get_glyph_data( face
, glyph_index
,
2526 &charstring
, &charstring_len
);
2529 error
= cff_decoder_prepare( &decoder
, size
, glyph_index
);
2531 error
= cff_decoder_parse_charstrings( &decoder
,
2535 cff_free_glyph_data( face
, &charstring
, &charstring_len
);
2538 /* ignore the error if one has occurred -- skip to next glyph */
2542 *max_advance
= decoder
.builder
.advance
.x
;
2551 FT_LOCAL_DEF( FT_Error
)
2552 cff_slot_load( CFF_GlyphSlot glyph
,
2554 FT_UInt glyph_index
,
2555 FT_Int32 load_flags
)
2558 CFF_Decoder decoder
;
2559 TT_Face face
= (TT_Face
)glyph
->root
.face
;
2560 FT_Bool hinting
, force_scaling
;
2561 CFF_Font cff
= (CFF_Font
)face
->extra
.data
;
2563 FT_Matrix font_matrix
;
2564 FT_Vector font_offset
;
2567 force_scaling
= FALSE
;
2569 /* in a CID-keyed font, consider `glyph_index' as a CID and map */
2570 /* it immediately to the real glyph_index -- if it isn't a */
2571 /* subsetted font, glyph_indices and CIDs are identical, though */
2572 if ( cff
->top_font
.font_dict
.cid_registry
!= 0xFFFFU
&&
2575 /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */
2576 if ( glyph_index
!= 0 )
2578 glyph_index
= cff_charset_cid_to_gindex( &cff
->charset
,
2580 if ( glyph_index
== 0 )
2581 return CFF_Err_Invalid_Argument
;
2584 else if ( glyph_index
>= cff
->num_glyphs
)
2585 return CFF_Err_Invalid_Argument
;
2587 if ( load_flags
& FT_LOAD_NO_RECURSE
)
2588 load_flags
|= FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
2590 glyph
->x_scale
= 0x10000L
;
2591 glyph
->y_scale
= 0x10000L
;
2594 glyph
->x_scale
= size
->root
.metrics
.x_scale
;
2595 glyph
->y_scale
= size
->root
.metrics
.y_scale
;
2598 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2600 /* try to load embedded bitmap if any */
2602 /* XXX: The convention should be emphasized in */
2603 /* the documents because it can be confusing. */
2606 CFF_Face cff_face
= (CFF_Face
)size
->root
.face
;
2607 SFNT_Service sfnt
= (SFNT_Service
)cff_face
->sfnt
;
2608 FT_Stream stream
= cff_face
->root
.stream
;
2611 if ( size
->strike_index
!= 0xFFFFFFFFUL
&&
2613 ( load_flags
& FT_LOAD_NO_BITMAP
) == 0 )
2615 TT_SBit_MetricsRec metrics
;
2618 error
= sfnt
->load_sbit_image( face
,
2623 &glyph
->root
.bitmap
,
2628 glyph
->root
.outline
.n_points
= 0;
2629 glyph
->root
.outline
.n_contours
= 0;
2631 glyph
->root
.metrics
.width
= (FT_Pos
)metrics
.width
<< 6;
2632 glyph
->root
.metrics
.height
= (FT_Pos
)metrics
.height
<< 6;
2634 glyph
->root
.metrics
.horiBearingX
= (FT_Pos
)metrics
.horiBearingX
<< 6;
2635 glyph
->root
.metrics
.horiBearingY
= (FT_Pos
)metrics
.horiBearingY
<< 6;
2636 glyph
->root
.metrics
.horiAdvance
= (FT_Pos
)metrics
.horiAdvance
<< 6;
2638 glyph
->root
.metrics
.vertBearingX
= (FT_Pos
)metrics
.vertBearingX
<< 6;
2639 glyph
->root
.metrics
.vertBearingY
= (FT_Pos
)metrics
.vertBearingY
<< 6;
2640 glyph
->root
.metrics
.vertAdvance
= (FT_Pos
)metrics
.vertAdvance
<< 6;
2642 glyph
->root
.format
= FT_GLYPH_FORMAT_BITMAP
;
2644 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
2646 glyph
->root
.bitmap_left
= metrics
.vertBearingX
;
2647 glyph
->root
.bitmap_top
= metrics
.vertBearingY
;
2651 glyph
->root
.bitmap_left
= metrics
.horiBearingX
;
2652 glyph
->root
.bitmap_top
= metrics
.horiBearingY
;
2659 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2661 /* return immediately if we only want the embedded bitmaps */
2662 if ( load_flags
& FT_LOAD_SBITS_ONLY
)
2663 return CFF_Err_Invalid_Argument
;
2665 /* if we have a CID subfont, use its matrix (which has already */
2666 /* been multiplied with the root matrix) */
2668 /* this scaling is only relevant if the PS hinter isn't active */
2669 if ( cff
->num_subfonts
)
2671 FT_Byte fd_index
= cff_fd_select_get( &cff
->fd_select
,
2674 FT_ULong top_upm
= cff
->top_font
.font_dict
.units_per_em
;
2675 FT_ULong sub_upm
= cff
->subfonts
[fd_index
]->font_dict
.units_per_em
;
2678 font_matrix
= cff
->subfonts
[fd_index
]->font_dict
.font_matrix
;
2679 font_offset
= cff
->subfonts
[fd_index
]->font_dict
.font_offset
;
2681 if ( top_upm
!= sub_upm
)
2683 glyph
->x_scale
= FT_MulDiv( glyph
->x_scale
, top_upm
, sub_upm
);
2684 glyph
->y_scale
= FT_MulDiv( glyph
->y_scale
, top_upm
, sub_upm
);
2686 force_scaling
= TRUE
;
2691 font_matrix
= cff
->top_font
.font_dict
.font_matrix
;
2692 font_offset
= cff
->top_font
.font_dict
.font_offset
;
2695 glyph
->root
.outline
.n_points
= 0;
2696 glyph
->root
.outline
.n_contours
= 0;
2698 hinting
= FT_BOOL( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 &&
2699 ( load_flags
& FT_LOAD_NO_HINTING
) == 0 );
2701 glyph
->root
.format
= FT_GLYPH_FORMAT_OUTLINE
; /* by default */
2704 FT_Byte
* charstring
;
2705 FT_ULong charstring_len
;
2708 cff_decoder_init( &decoder
, face
, size
, glyph
, hinting
,
2709 FT_LOAD_TARGET_MODE( load_flags
) );
2711 if ( load_flags
& FT_LOAD_ADVANCE_ONLY
)
2712 decoder
.width_only
= TRUE
;
2714 decoder
.builder
.no_recurse
=
2715 (FT_Bool
)( load_flags
& FT_LOAD_NO_RECURSE
);
2717 /* now load the unscaled outline */
2718 error
= cff_get_glyph_data( face
, glyph_index
,
2719 &charstring
, &charstring_len
);
2722 error
= cff_decoder_prepare( &decoder
, size
, glyph_index
);
2725 error
= cff_decoder_parse_charstrings( &decoder
,
2729 cff_free_glyph_data( face
, &charstring
, charstring_len
);
2732 #ifdef FT_CONFIG_OPTION_INCREMENTAL
2733 /* Control data and length may not be available for incremental */
2735 if ( face
->root
.internal
->incremental_interface
)
2737 glyph
->root
.control_data
= 0;
2738 glyph
->root
.control_len
= 0;
2741 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
2743 /* We set control_data and control_len if charstrings is loaded. */
2744 /* See how charstring loads at cff_index_access_element() in */
2747 CFF_Index csindex
= &cff
->charstrings_index
;
2750 if ( csindex
->offsets
)
2752 glyph
->root
.control_data
= csindex
->bytes
+
2753 csindex
->offsets
[glyph_index
] - 1;
2754 glyph
->root
.control_len
= charstring_len
;
2760 /* save new glyph tables */
2761 cff_builder_done( &decoder
.builder
);
2764 #ifdef FT_CONFIG_OPTION_INCREMENTAL
2766 /* Incremental fonts can optionally override the metrics. */
2768 face
->root
.internal
->incremental_interface
&&
2769 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics
)
2771 FT_Incremental_MetricsRec metrics
;
2774 metrics
.bearing_x
= decoder
.builder
.left_bearing
.x
;
2775 metrics
.bearing_y
= 0;
2776 metrics
.advance
= decoder
.builder
.advance
.x
;
2777 metrics
.advance_v
= decoder
.builder
.advance
.y
;
2779 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics(
2780 face
->root
.internal
->incremental_interface
->object
,
2781 glyph_index
, FALSE
, &metrics
);
2783 decoder
.builder
.left_bearing
.x
= metrics
.bearing_x
;
2784 decoder
.builder
.advance
.x
= metrics
.advance
;
2785 decoder
.builder
.advance
.y
= metrics
.advance_v
;
2788 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
2792 /* Now, set the metrics -- this is rather simple, as */
2793 /* the left side bearing is the xMin, and the top side */
2794 /* bearing the yMax. */
2796 /* For composite glyphs, return only left side bearing and */
2797 /* advance width. */
2798 if ( load_flags
& FT_LOAD_NO_RECURSE
)
2800 FT_Slot_Internal internal
= glyph
->root
.internal
;
2803 glyph
->root
.metrics
.horiBearingX
= decoder
.builder
.left_bearing
.x
;
2804 glyph
->root
.metrics
.horiAdvance
= decoder
.glyph_width
;
2805 internal
->glyph_matrix
= font_matrix
;
2806 internal
->glyph_delta
= font_offset
;
2807 internal
->glyph_transformed
= 1;
2812 FT_Glyph_Metrics
* metrics
= &glyph
->root
.metrics
;
2814 FT_Bool has_vertical_info
;
2817 /* copy the _unscaled_ advance width */
2818 metrics
->horiAdvance
= decoder
.glyph_width
;
2819 glyph
->root
.linearHoriAdvance
= decoder
.glyph_width
;
2820 glyph
->root
.internal
->glyph_transformed
= 0;
2822 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
2823 has_vertical_info
= FT_BOOL( face
->vertical_info
&&
2824 face
->vertical
.number_Of_VMetrics
> 0 &&
2825 face
->vertical
.long_metrics
);
2827 has_vertical_info
= FT_BOOL( face
->vertical_info
&&
2828 face
->vertical
.number_Of_VMetrics
> 0 );
2831 /* get the vertical metrics from the vtmx table if we have one */
2832 if ( has_vertical_info
)
2834 FT_Short vertBearingY
= 0;
2835 FT_UShort vertAdvance
= 0;
2838 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 1,
2842 metrics
->vertBearingY
= vertBearingY
;
2843 metrics
->vertAdvance
= vertAdvance
;
2847 /* make up vertical ones */
2848 if ( face
->os2
.version
!= 0xFFFFU
)
2849 metrics
->vertAdvance
= (FT_Pos
)( face
->os2
.sTypoAscender
-
2850 face
->os2
.sTypoDescender
);
2852 metrics
->vertAdvance
= (FT_Pos
)( face
->horizontal
.Ascender
-
2853 face
->horizontal
.Descender
);
2856 glyph
->root
.linearVertAdvance
= metrics
->vertAdvance
;
2858 glyph
->root
.format
= FT_GLYPH_FORMAT_OUTLINE
;
2860 glyph
->root
.outline
.flags
= 0;
2861 if ( size
&& size
->root
.metrics
.y_ppem
< 24 )
2862 glyph
->root
.outline
.flags
|= FT_OUTLINE_HIGH_PRECISION
;
2864 glyph
->root
.outline
.flags
|= FT_OUTLINE_REVERSE_FILL
;
2866 if ( !( font_matrix
.xx
== 0x10000L
&&
2867 font_matrix
.yy
== 0x10000L
&&
2868 font_matrix
.xy
== 0 &&
2869 font_matrix
.yx
== 0 ) )
2870 FT_Outline_Transform( &glyph
->root
.outline
, &font_matrix
);
2872 if ( !( font_offset
.x
== 0 &&
2873 font_offset
.y
== 0 ) )
2874 FT_Outline_Translate( &glyph
->root
.outline
,
2875 font_offset
.x
, font_offset
.y
);
2877 advance
.x
= metrics
->horiAdvance
;
2879 FT_Vector_Transform( &advance
, &font_matrix
);
2880 metrics
->horiAdvance
= advance
.x
+ font_offset
.x
;
2883 advance
.y
= metrics
->vertAdvance
;
2884 FT_Vector_Transform( &advance
, &font_matrix
);
2885 metrics
->vertAdvance
= advance
.y
+ font_offset
.y
;
2887 if ( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 || force_scaling
)
2889 /* scale the outline and the metrics */
2891 FT_Outline
* cur
= &glyph
->root
.outline
;
2892 FT_Vector
* vec
= cur
->points
;
2893 FT_Fixed x_scale
= glyph
->x_scale
;
2894 FT_Fixed y_scale
= glyph
->y_scale
;
2897 /* First of all, scale the points */
2898 if ( !hinting
|| !decoder
.builder
.hints_funcs
)
2899 for ( n
= cur
->n_points
; n
> 0; n
--, vec
++ )
2901 vec
->x
= FT_MulFix( vec
->x
, x_scale
);
2902 vec
->y
= FT_MulFix( vec
->y
, y_scale
);
2905 /* Then scale the metrics */
2906 metrics
->horiAdvance
= FT_MulFix( metrics
->horiAdvance
, x_scale
);
2907 metrics
->vertAdvance
= FT_MulFix( metrics
->vertAdvance
, y_scale
);
2910 /* compute the other metrics */
2911 FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox
);
2913 metrics
->width
= cbox
.xMax
- cbox
.xMin
;
2914 metrics
->height
= cbox
.yMax
- cbox
.yMin
;
2916 metrics
->horiBearingX
= cbox
.xMin
;
2917 metrics
->horiBearingY
= cbox
.yMax
;
2919 if ( has_vertical_info
)
2920 metrics
->vertBearingX
= metrics
->horiBearingX
-
2921 metrics
->horiAdvance
/ 2;
2924 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
2925 ft_synthesize_vertical_metrics( metrics
,
2926 metrics
->vertAdvance
);