1 /***************************************************************************/
5 /* OpenType Glyph Loader (body). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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_CALC_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_INTERNAL_SFNT_H
25 #include FT_TRUETYPE_TAGS_H
26 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
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 typedef enum CFF_Operator_
79 cff_op_dotsection
, /* deprecated, acts as no-op */
119 #define CFF_COUNT_CHECK_WIDTH 0x80
120 #define CFF_COUNT_EXACT 0x40
121 #define CFF_COUNT_CLEAR_STACK 0x20
124 static const FT_Byte cff_argument_counts
[] =
128 2 | CFF_COUNT_CHECK_WIDTH
| CFF_COUNT_EXACT
, /* rmoveto */
129 1 | CFF_COUNT_CHECK_WIDTH
| CFF_COUNT_EXACT
,
130 1 | CFF_COUNT_CHECK_WIDTH
| CFF_COUNT_EXACT
,
132 0 | CFF_COUNT_CLEAR_STACK
, /* rlineto */
133 0 | CFF_COUNT_CLEAR_STACK
,
134 0 | CFF_COUNT_CLEAR_STACK
,
136 0 | CFF_COUNT_CLEAR_STACK
, /* rrcurveto */
137 0 | CFF_COUNT_CLEAR_STACK
,
138 0 | CFF_COUNT_CLEAR_STACK
,
139 0 | CFF_COUNT_CLEAR_STACK
,
140 0 | CFF_COUNT_CLEAR_STACK
,
141 0 | CFF_COUNT_CLEAR_STACK
,
142 0 | CFF_COUNT_CLEAR_STACK
,
149 0 | CFF_COUNT_CHECK_WIDTH
, /* endchar */
151 2 | CFF_COUNT_CHECK_WIDTH
, /* hstem */
152 2 | CFF_COUNT_CHECK_WIDTH
,
153 2 | CFF_COUNT_CHECK_WIDTH
,
154 2 | CFF_COUNT_CHECK_WIDTH
,
156 0 | CFF_COUNT_CHECK_WIDTH
, /* hintmask */
157 0 | CFF_COUNT_CHECK_WIDTH
, /* cntrmask */
194 /*************************************************************************/
195 /*************************************************************************/
196 /*************************************************************************/
197 /********** *********/
198 /********** *********/
199 /********** GENERIC CHARSTRING PARSING *********/
200 /********** *********/
201 /********** *********/
202 /*************************************************************************/
203 /*************************************************************************/
204 /*************************************************************************/
207 /*************************************************************************/
210 /* cff_builder_init */
213 /* Initializes a given glyph builder. */
216 /* builder :: A pointer to the glyph builder to initialize. */
219 /* face :: The current face object. */
221 /* size :: The current size object. */
223 /* glyph :: The current glyph object. */
226 cff_builder_init( CFF_Builder
* builder
,
232 builder
->path_begun
= 0;
233 builder
->load_points
= 1;
235 builder
->face
= face
;
236 builder
->glyph
= glyph
;
237 builder
->memory
= face
->root
.memory
;
241 FT_GlyphLoader loader
= glyph
->root
.internal
->loader
;
244 builder
->loader
= loader
;
245 builder
->base
= &loader
->base
.outline
;
246 builder
->current
= &loader
->current
.outline
;
247 FT_GlyphLoader_Rewind( loader
);
249 builder
->hints_globals
= 0;
250 builder
->hints_funcs
= 0;
252 if ( hinting
&& size
)
254 builder
->hints_globals
= size
->root
.internal
;
255 builder
->hints_funcs
= glyph
->root
.internal
->glyph_hints
;
261 builder
->scale_x
= size
->root
.metrics
.x_scale
;
262 builder
->scale_y
= size
->root
.metrics
.y_scale
;
268 builder
->left_bearing
.x
= 0;
269 builder
->left_bearing
.y
= 0;
270 builder
->advance
.x
= 0;
271 builder
->advance
.y
= 0;
275 /*************************************************************************/
278 /* cff_builder_done */
281 /* Finalizes a given glyph builder. Its contents can still be used */
282 /* after the call, but the function saves important information */
283 /* within the corresponding glyph slot. */
286 /* builder :: A pointer to the glyph builder to finalize. */
289 cff_builder_done( CFF_Builder
* builder
)
291 CFF_GlyphSlot glyph
= builder
->glyph
;
295 glyph
->root
.outline
= *builder
->base
;
299 /*************************************************************************/
302 /* cff_compute_bias */
305 /* Computes the bias value in dependence of the number of glyph */
309 /* num_subrs :: The number of glyph subroutines. */
312 /* The bias value. */
314 cff_compute_bias( FT_UInt num_subrs
)
319 if ( num_subrs
< 1240 )
321 else if ( num_subrs
< 33900U )
330 /*************************************************************************/
333 /* cff_decoder_init */
336 /* Initializes a given glyph decoder. */
339 /* decoder :: A pointer to the glyph builder to initialize. */
342 /* face :: The current face object. */
344 /* size :: The current size object. */
346 /* slot :: The current glyph object. */
349 cff_decoder_init( CFF_Decoder
* decoder
,
354 FT_Render_Mode hint_mode
)
356 CFF_Font cff
= (CFF_Font
)face
->extra
.data
;
359 /* clear everything */
360 FT_MEM_ZERO( decoder
, sizeof ( *decoder
) );
362 /* initialize builder */
363 cff_builder_init( &decoder
->builder
, face
, size
, slot
, hinting
);
365 /* initialize Type2 decoder */
366 decoder
->num_globals
= cff
->num_global_subrs
;
367 decoder
->globals
= cff
->global_subrs
;
368 decoder
->globals_bias
= cff_compute_bias( decoder
->num_globals
);
370 decoder
->hint_mode
= hint_mode
;
374 /* this function is used to select the locals subrs array */
375 FT_LOCAL_DEF( FT_Error
)
376 cff_decoder_prepare( CFF_Decoder
* decoder
,
377 FT_UInt glyph_index
)
379 CFF_Font cff
= (CFF_Font
)decoder
->builder
.face
->extra
.data
;
380 CFF_SubFont sub
= &cff
->top_font
;
381 FT_Error error
= CFF_Err_Ok
;
384 /* manage CID fonts */
385 if ( cff
->num_subfonts
>= 1 )
387 FT_Byte fd_index
= cff_fd_select_get( &cff
->fd_select
, glyph_index
);
390 if ( fd_index
>= cff
->num_subfonts
)
392 FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
393 error
= CFF_Err_Invalid_File_Format
;
397 sub
= cff
->subfonts
[fd_index
];
400 decoder
->num_locals
= sub
->num_local_subrs
;
401 decoder
->locals
= sub
->local_subrs
;
402 decoder
->locals_bias
= cff_compute_bias( decoder
->num_locals
);
404 decoder
->glyph_width
= sub
->private_dict
.default_width
;
405 decoder
->nominal_width
= sub
->private_dict
.nominal_width
;
412 /* check that there is enough space for `count' more points */
414 check_points( CFF_Builder
* builder
,
417 return FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, count
, 0 );
421 /* add a new point, do not check space */
423 cff_builder_add_point( CFF_Builder
* builder
,
428 FT_Outline
* outline
= builder
->current
;
431 if ( builder
->load_points
)
433 FT_Vector
* point
= outline
->points
+ outline
->n_points
;
434 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
;
439 *control
= (FT_Byte
)( flag
? FT_CURVE_TAG_ON
: FT_CURVE_TAG_CUBIC
);
441 builder
->last
= *point
;
448 /* check space for a new on-curve point, then add it */
450 cff_builder_add_point1( CFF_Builder
* builder
,
457 error
= check_points( builder
, 1 );
459 cff_builder_add_point( builder
, x
, y
, 1 );
465 /* check space for a new contour, then add it */
467 cff_builder_add_contour( CFF_Builder
* builder
)
469 FT_Outline
* outline
= builder
->current
;
473 if ( !builder
->load_points
)
475 outline
->n_contours
++;
479 error
= FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, 0, 1 );
482 if ( outline
->n_contours
> 0 )
483 outline
->contours
[outline
->n_contours
- 1] =
484 (short)( outline
->n_points
- 1 );
486 outline
->n_contours
++;
493 /* if a path was begun, add its first on-curve point */
495 cff_builder_start_point( CFF_Builder
* builder
,
499 FT_Error error
= CFF_Err_Ok
;
502 /* test whether we are building a new contour */
503 if ( !builder
->path_begun
)
505 builder
->path_begun
= 1;
506 error
= cff_builder_add_contour( builder
);
508 error
= cff_builder_add_point1( builder
, x
, y
);
515 /* close the current contour */
517 cff_builder_close_contour( CFF_Builder
* builder
)
519 FT_Outline
* outline
= builder
->current
;
525 /* XXXX: We must not include the last point in the path if it */
526 /* is located on the first point. */
527 if ( outline
->n_points
> 1 )
530 FT_Vector
* p1
= outline
->points
+ first
;
531 FT_Vector
* p2
= outline
->points
+ outline
->n_points
- 1;
532 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
- 1;
535 if ( outline
->n_contours
> 1 )
537 first
= outline
->contours
[outline
->n_contours
- 2] + 1;
538 p1
= outline
->points
+ first
;
541 /* `delete' last point only if it coincides with the first */
542 /* point and if it is not a control point (which can happen). */
543 if ( p1
->x
== p2
->x
&& p1
->y
== p2
->y
)
544 if ( *control
== FT_CURVE_TAG_ON
)
548 if ( outline
->n_contours
> 0 )
549 outline
->contours
[outline
->n_contours
- 1] =
550 (short)( outline
->n_points
- 1 );
555 cff_lookup_glyph_by_stdcharcode( CFF_Font cff
,
562 /* CID-keyed fonts don't have glyph names */
563 if ( !cff
->charset
.sids
)
566 /* check range of standard char code */
567 if ( charcode
< 0 || charcode
> 255 )
570 /* Get code to SID mapping from `cff_standard_encoding'. */
571 glyph_sid
= cff_get_standard_encoding( (FT_UInt
)charcode
);
573 for ( n
= 0; n
< cff
->num_glyphs
; n
++ )
575 if ( cff
->charset
.sids
[n
] == glyph_sid
)
584 cff_get_glyph_data( TT_Face face
,
589 #ifdef FT_CONFIG_OPTION_INCREMENTAL
590 /* For incremental fonts get the character data using the */
591 /* callback function. */
592 if ( face
->root
.internal
->incremental_interface
)
596 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_data(
597 face
->root
.internal
->incremental_interface
->object
,
598 glyph_index
, &data
);
601 *pointer
= (FT_Byte
*)data
.pointer
;
602 *length
= data
.length
;
607 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
610 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
613 return cff_index_access_element( &cff
->charstrings_index
, glyph_index
,
620 cff_free_glyph_data( TT_Face face
,
624 #ifndef FT_CONFIG_OPTION_INCREMENTAL
628 #ifdef FT_CONFIG_OPTION_INCREMENTAL
629 /* For incremental fonts get the character data using the */
630 /* callback function. */
631 if ( face
->root
.internal
->incremental_interface
)
636 data
.pointer
= *pointer
;
637 data
.length
= length
;
639 face
->root
.internal
->incremental_interface
->funcs
->free_glyph_data(
640 face
->root
.internal
->incremental_interface
->object
,&data
);
643 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
646 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
649 cff_index_forget_element( &cff
->charstrings_index
, pointer
);
655 cff_operator_seac( CFF_Decoder
* decoder
,
662 CFF_Builder
* builder
= &decoder
->builder
;
663 FT_Int bchar_index
, achar_index
;
664 TT_Face face
= decoder
->builder
.face
;
665 FT_Vector left_bearing
, advance
;
667 FT_ULong charstring_len
;
670 #ifdef FT_CONFIG_OPTION_INCREMENTAL
671 /* Incremental fonts don't necessarily have valid charsets. */
672 /* They use the character code, not the glyph index, in this case. */
673 if ( face
->root
.internal
->incremental_interface
)
679 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
681 CFF_Font cff
= (CFF_Font
)(face
->extra
.data
);
684 bchar_index
= cff_lookup_glyph_by_stdcharcode( cff
, bchar
);
685 achar_index
= cff_lookup_glyph_by_stdcharcode( cff
, achar
);
688 if ( bchar_index
< 0 || achar_index
< 0 )
690 FT_ERROR(( "cff_operator_seac:" ));
691 FT_ERROR(( " invalid seac character code arguments\n" ));
692 return CFF_Err_Syntax_Error
;
695 /* If we are trying to load a composite glyph, do not load the */
696 /* accent character and return the array of subglyphs. */
697 if ( builder
->no_recurse
)
699 FT_GlyphSlot glyph
= (FT_GlyphSlot
)builder
->glyph
;
700 FT_GlyphLoader loader
= glyph
->internal
->loader
;
704 /* reallocate subglyph array if necessary */
705 error
= FT_GlyphLoader_CheckSubGlyphs( loader
, 2 );
709 subg
= loader
->current
.subglyphs
;
711 /* subglyph 0 = base character */
712 subg
->index
= bchar_index
;
713 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
|
714 FT_SUBGLYPH_FLAG_USE_MY_METRICS
;
719 /* subglyph 1 = accent character */
720 subg
->index
= achar_index
;
721 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
;
722 subg
->arg1
= (FT_Int
)( adx
>> 16 );
723 subg
->arg2
= (FT_Int
)( ady
>> 16 );
725 /* set up remaining glyph fields */
726 glyph
->num_subglyphs
= 2;
727 glyph
->subglyphs
= loader
->base
.subglyphs
;
728 glyph
->format
= FT_GLYPH_FORMAT_COMPOSITE
;
730 loader
->current
.num_subglyphs
= 2;
733 FT_GlyphLoader_Prepare( builder
->loader
);
735 /* First load `bchar' in builder */
736 error
= cff_get_glyph_data( face
, bchar_index
,
737 &charstring
, &charstring_len
);
740 error
= cff_decoder_parse_charstrings( decoder
, charstring
,
746 cff_free_glyph_data( face
, &charstring
, charstring_len
);
749 /* Save the left bearing and width of the base character */
750 /* as they will be erased by the next load. */
752 left_bearing
= builder
->left_bearing
;
753 advance
= builder
->advance
;
755 builder
->left_bearing
.x
= 0;
756 builder
->left_bearing
.y
= 0;
758 builder
->pos_x
= adx
;
759 builder
->pos_y
= ady
;
761 /* Now load `achar' on top of the base outline. */
762 error
= cff_get_glyph_data( face
, achar_index
,
763 &charstring
, &charstring_len
);
766 error
= cff_decoder_parse_charstrings( decoder
, charstring
,
772 cff_free_glyph_data( face
, &charstring
, charstring_len
);
775 /* Restore the left side bearing and advance width */
776 /* of the base character. */
777 builder
->left_bearing
= left_bearing
;
778 builder
->advance
= advance
;
788 /*************************************************************************/
791 /* cff_decoder_parse_charstrings */
794 /* Parses a given Type 2 charstrings program. */
797 /* decoder :: The current Type 1 decoder. */
800 /* charstring_base :: The base of the charstring stream. */
802 /* charstring_len :: The length in bytes of the charstring stream. */
805 /* FreeType error code. 0 means success. */
807 FT_LOCAL_DEF( FT_Error
)
808 cff_decoder_parse_charstrings( CFF_Decoder
* decoder
,
809 FT_Byte
* charstring_base
,
810 FT_ULong charstring_len
)
813 CFF_Decoder_Zone
* zone
;
816 CFF_Builder
* builder
= &decoder
->builder
;
821 T2_Hints_Funcs hinter
;
824 /* set default width */
825 decoder
->num_hints
= 0;
826 decoder
->read_width
= 1;
828 /* compute random seed from stack address of parameter */
829 seed
= (FT_Fixed
)(char*)&seed
^
830 (FT_Fixed
)(char*)&decoder
^
831 (FT_Fixed
)(char*)&charstring_base
;
832 seed
= ( seed
^ ( seed
>> 10 ) ^ ( seed
>> 20 ) ) & 0xFFFFL
;
836 /* initialize the decoder */
837 decoder
->top
= decoder
->stack
;
838 decoder
->zone
= decoder
->zones
;
839 zone
= decoder
->zones
;
840 stack
= decoder
->top
;
842 hinter
= (T2_Hints_Funcs
)builder
->hints_funcs
;
844 builder
->path_begun
= 0;
846 zone
->base
= charstring_base
;
847 limit
= zone
->limit
= charstring_base
+ charstring_len
;
848 ip
= zone
->cursor
= zone
->base
;
855 /* begin hints recording session, if any */
857 hinter
->open( hinter
->hints
);
859 /* now execute loop */
866 /********************************************************************/
868 /* Decode operator or operand */
871 if ( v
>= 32 || v
== 28 )
877 /* this is an operand, push it on the stack */
880 if ( ip
+ 1 >= limit
)
882 val
= (FT_Short
)( ( (FT_Short
)ip
[0] << 8 ) | ip
[1] );
886 val
= (FT_Long
)v
- 139;
891 val
= ( (FT_Long
)v
- 247 ) * 256 + *ip
++ + 108;
897 val
= -( (FT_Long
)v
- 251 ) * 256 - *ip
++ - 108;
901 if ( ip
+ 3 >= limit
)
903 val
= ( (FT_Int32
)ip
[0] << 24 ) |
904 ( (FT_Int32
)ip
[1] << 16 ) |
905 ( (FT_Int32
)ip
[2] << 8 ) |
910 if ( decoder
->top
- stack
>= CFF_MAX_OPERANDS
)
914 *decoder
->top
++ = val
;
916 #ifdef FT_DEBUG_LEVEL_TRACE
917 if ( !( val
& 0xFFFFL
) )
918 FT_TRACE4(( " %ld", (FT_Int32
)( val
>> 16 ) ));
920 FT_TRACE4(( " %.2f", val
/ 65536.0 ));
926 FT_Fixed
* args
= decoder
->top
;
927 FT_Int num_args
= (FT_Int
)( args
- decoder
->stack
);
955 op
= cff_op_rrcurveto
;
958 op
= cff_op_callsubr
;
972 op
= cff_op_dotsection
;
1053 /* decrement ip for syntax error message */
1059 op
= cff_op_endchar
;
1065 op
= cff_op_hstemhm
;
1068 op
= cff_op_hintmask
;
1071 op
= cff_op_cntrmask
;
1074 op
= cff_op_rmoveto
;
1077 op
= cff_op_hmoveto
;
1080 op
= cff_op_vstemhm
;
1083 op
= cff_op_rcurveline
;
1086 op
= cff_op_rlinecurve
;
1089 op
= cff_op_vvcurveto
;
1092 op
= cff_op_hhcurveto
;
1095 op
= cff_op_callgsubr
;
1098 op
= cff_op_vhcurveto
;
1101 op
= cff_op_hvcurveto
;
1106 if ( op
== cff_op_unknown
)
1109 /* check arguments */
1110 req_args
= cff_argument_counts
[op
];
1111 if ( req_args
& CFF_COUNT_CHECK_WIDTH
)
1115 if ( num_args
> 0 && decoder
->read_width
)
1117 /* If `nominal_width' is non-zero, the number is really a */
1118 /* difference against `nominal_width'. Else, the number here */
1119 /* is truly a width, not a difference against `nominal_width'. */
1120 /* If the font does not set `nominal_width', then */
1121 /* `nominal_width' defaults to zero, and so we can set */
1122 /* `glyph_width' to `nominal_width' plus number on the stack */
1123 /* -- for either case. */
1125 FT_Int set_width_ok
;
1130 case cff_op_hmoveto
:
1131 case cff_op_vmoveto
:
1132 set_width_ok
= num_args
& 2;
1137 case cff_op_hstemhm
:
1138 case cff_op_vstemhm
:
1139 case cff_op_rmoveto
:
1140 case cff_op_hintmask
:
1141 case cff_op_cntrmask
:
1142 set_width_ok
= num_args
& 1;
1145 case cff_op_endchar
:
1146 /* If there is a width specified for endchar, we either have */
1147 /* 1 argument or 5 arguments. We like to argue. */
1148 set_width_ok
= ( ( num_args
== 5 ) || ( num_args
== 1 ) );
1158 decoder
->glyph_width
= decoder
->nominal_width
+
1161 /* Consumed an argument. */
1167 decoder
->read_width
= 0;
1172 if ( num_args
< req_args
)
1173 goto Stack_Underflow
;
1175 num_args
-= req_args
;
1181 case cff_op_hstemhm
:
1182 case cff_op_vstemhm
:
1183 /* the number of arguments is always even here */
1184 FT_TRACE4(( op
== cff_op_hstem
? " hstem" :
1185 ( op
== cff_op_vstem
? " vstem" :
1186 ( op
== cff_op_hstemhm
? " hstemhm" : " vstemhm" ) ) ));
1189 hinter
->stems( hinter
->hints
,
1190 ( op
== cff_op_hstem
|| op
== cff_op_hstemhm
),
1194 decoder
->num_hints
+= num_args
/ 2;
1198 case cff_op_hintmask
:
1199 case cff_op_cntrmask
:
1200 FT_TRACE4(( op
== cff_op_hintmask
? " hintmask" : " cntrmask" ));
1202 /* implement vstem when needed -- */
1203 /* the specification doesn't say it, but this also works */
1204 /* with the 'cntrmask' operator */
1209 hinter
->stems( hinter
->hints
,
1214 decoder
->num_hints
+= num_args
/ 2;
1219 if ( op
== cff_op_hintmask
)
1220 hinter
->hintmask( hinter
->hints
,
1221 builder
->current
->n_points
,
1225 hinter
->counter( hinter
->hints
,
1230 #ifdef FT_DEBUG_LEVEL_TRACE
1238 maskbyte
< (FT_UInt
)(( decoder
->num_hints
+ 7 ) >> 3);
1240 FT_TRACE4(( "0x%02X", *ip
));
1243 ip
+= ( decoder
->num_hints
+ 7 ) >> 3;
1250 case cff_op_rmoveto
:
1251 FT_TRACE4(( " rmoveto" ));
1253 cff_builder_close_contour( builder
);
1254 builder
->path_begun
= 0;
1260 case cff_op_vmoveto
:
1261 FT_TRACE4(( " vmoveto" ));
1263 cff_builder_close_contour( builder
);
1264 builder
->path_begun
= 0;
1269 case cff_op_hmoveto
:
1270 FT_TRACE4(( " hmoveto" ));
1272 cff_builder_close_contour( builder
);
1273 builder
->path_begun
= 0;
1278 case cff_op_rlineto
:
1279 FT_TRACE4(( " rlineto" ));
1281 if ( cff_builder_start_point ( builder
, x
, y
) ||
1282 check_points( builder
, num_args
/ 2 ) )
1285 if ( num_args
< 2 || num_args
& 1 )
1286 goto Stack_Underflow
;
1289 while ( args
< decoder
->top
)
1293 cff_builder_add_point( builder
, x
, y
, 1 );
1299 case cff_op_hlineto
:
1300 case cff_op_vlineto
:
1302 FT_Int phase
= ( op
== cff_op_hlineto
);
1305 FT_TRACE4(( op
== cff_op_hlineto
? " hlineto"
1308 if ( cff_builder_start_point ( builder
, x
, y
) ||
1309 check_points( builder
, num_args
) )
1313 while ( args
< decoder
->top
)
1320 if ( cff_builder_add_point1( builder
, x
, y
) )
1330 case cff_op_rrcurveto
:
1331 FT_TRACE4(( " rrcurveto" ));
1333 /* check number of arguments; must be a multiple of 6 */
1334 if ( num_args
% 6 != 0 )
1335 goto Stack_Underflow
;
1337 if ( cff_builder_start_point ( builder
, x
, y
) ||
1338 check_points( builder
, num_args
/ 2 ) )
1342 while ( args
< decoder
->top
)
1346 cff_builder_add_point( builder
, x
, y
, 0 );
1349 cff_builder_add_point( builder
, x
, y
, 0 );
1352 cff_builder_add_point( builder
, x
, y
, 1 );
1358 case cff_op_vvcurveto
:
1359 FT_TRACE4(( " vvcurveto" ));
1361 if ( cff_builder_start_point( builder
, x
, y
) )
1372 if ( num_args
% 4 != 0 )
1373 goto Stack_Underflow
;
1375 if ( check_points( builder
, 3 * ( num_args
/ 4 ) ) )
1378 while ( args
< decoder
->top
)
1381 cff_builder_add_point( builder
, x
, y
, 0 );
1384 cff_builder_add_point( builder
, x
, y
, 0 );
1386 cff_builder_add_point( builder
, x
, y
, 1 );
1392 case cff_op_hhcurveto
:
1393 FT_TRACE4(( " hhcurveto" ));
1395 if ( cff_builder_start_point( builder
, x
, y
) )
1406 if ( num_args
% 4 != 0 )
1407 goto Stack_Underflow
;
1409 if ( check_points( builder
, 3 * ( num_args
/ 4 ) ) )
1412 while ( args
< decoder
->top
)
1415 cff_builder_add_point( builder
, x
, y
, 0 );
1418 cff_builder_add_point( builder
, x
, y
, 0 );
1420 cff_builder_add_point( builder
, x
, y
, 1 );
1426 case cff_op_vhcurveto
:
1427 case cff_op_hvcurveto
:
1432 FT_TRACE4(( op
== cff_op_vhcurveto
? " vhcurveto"
1435 if ( cff_builder_start_point( builder
, x
, y
) )
1439 if ( num_args
< 4 || ( num_args
% 4 ) > 1 )
1440 goto Stack_Underflow
;
1442 if ( check_points( builder
, ( num_args
/ 4 ) * 3 ) )
1443 goto Stack_Underflow
;
1445 phase
= ( op
== cff_op_hvcurveto
);
1447 while ( num_args
>= 4 )
1453 cff_builder_add_point( builder
, x
, y
, 0 );
1456 cff_builder_add_point( builder
, x
, y
, 0 );
1458 if ( num_args
== 1 )
1460 cff_builder_add_point( builder
, x
, y
, 1 );
1465 cff_builder_add_point( builder
, x
, y
, 0 );
1468 cff_builder_add_point( builder
, x
, y
, 0 );
1470 if ( num_args
== 1 )
1472 cff_builder_add_point( builder
, x
, y
, 1 );
1481 case cff_op_rlinecurve
:
1483 FT_Int num_lines
= ( num_args
- 6 ) / 2;
1486 FT_TRACE4(( " rlinecurve" ));
1488 if ( num_args
< 8 || ( num_args
- 6 ) & 1 )
1489 goto Stack_Underflow
;
1491 if ( cff_builder_start_point( builder
, x
, y
) ||
1492 check_points( builder
, num_lines
+ 3 ) )
1497 /* first, add the line segments */
1498 while ( num_lines
> 0 )
1502 cff_builder_add_point( builder
, x
, y
, 1 );
1507 /* then the curve */
1510 cff_builder_add_point( builder
, x
, y
, 0 );
1513 cff_builder_add_point( builder
, x
, y
, 0 );
1516 cff_builder_add_point( builder
, x
, y
, 1 );
1521 case cff_op_rcurveline
:
1523 FT_Int num_curves
= ( num_args
- 2 ) / 6;
1526 FT_TRACE4(( " rcurveline" ));
1528 if ( num_args
< 8 || ( num_args
- 2 ) % 6 )
1529 goto Stack_Underflow
;
1531 if ( cff_builder_start_point ( builder
, x
, y
) ||
1532 check_points( builder
, num_curves
*3 + 2 ) )
1537 /* first, add the curves */
1538 while ( num_curves
> 0 )
1542 cff_builder_add_point( builder
, x
, y
, 0 );
1545 cff_builder_add_point( builder
, x
, y
, 0 );
1548 cff_builder_add_point( builder
, x
, y
, 1 );
1553 /* then the final line */
1556 cff_builder_add_point( builder
, x
, y
, 1 );
1566 FT_TRACE4(( " hflex1" ));
1570 /* adding five more points; 4 control points, 1 on-curve point */
1571 /* make sure we have enough space for the start point if it */
1572 /* needs to be added */
1573 if ( cff_builder_start_point( builder
, x
, y
) ||
1574 check_points( builder
, 6 ) )
1577 /* Record the starting point's y position for later use */
1580 /* first control point */
1583 cff_builder_add_point( builder
, x
, y
, 0 );
1585 /* second control point */
1588 cff_builder_add_point( builder
, x
, y
, 0 );
1590 /* join point; on curve, with y-value the same as the last */
1591 /* control point's y-value */
1593 cff_builder_add_point( builder
, x
, y
, 1 );
1595 /* third control point, with y-value the same as the join */
1596 /* point's y-value */
1598 cff_builder_add_point( builder
, x
, y
, 0 );
1600 /* fourth control point */
1603 cff_builder_add_point( builder
, x
, y
, 0 );
1605 /* ending point, with y-value the same as the start */
1608 cff_builder_add_point( builder
, x
, y
, 1 );
1619 FT_TRACE4(( " hflex" ));
1623 /* adding six more points; 4 control points, 2 on-curve points */
1624 if ( cff_builder_start_point( builder
, x
, y
) ||
1625 check_points( builder
, 6 ) )
1628 /* record the starting point's y-position for later use */
1631 /* first control point */
1633 cff_builder_add_point( builder
, x
, y
, 0 );
1635 /* second control point */
1638 cff_builder_add_point( builder
, x
, y
, 0 );
1640 /* join point; on curve, with y-value the same as the last */
1641 /* control point's y-value */
1643 cff_builder_add_point( builder
, x
, y
, 1 );
1645 /* third control point, with y-value the same as the join */
1646 /* point's y-value */
1648 cff_builder_add_point( builder
, x
, y
, 0 );
1650 /* fourth control point */
1653 cff_builder_add_point( builder
, x
, y
, 0 );
1655 /* ending point, with y-value the same as the start point's */
1656 /* y-value -- we don't add this point, though */
1658 cff_builder_add_point( builder
, x
, y
, 1 );
1666 FT_Pos start_x
, start_y
; /* record start x, y values for */
1668 FT_Fixed dx
= 0, dy
= 0; /* used in horizontal/vertical */
1669 /* algorithm below */
1670 FT_Int horizontal
, count
;
1673 FT_TRACE4(( " flex1" ));
1675 /* adding six more points; 4 control points, 2 on-curve points */
1676 if ( cff_builder_start_point( builder
, x
, y
) ||
1677 check_points( builder
, 6 ) )
1680 /* record the starting point's x, y position for later use */
1684 /* XXX: figure out whether this is supposed to be a horizontal */
1685 /* or vertical flex; the Type 2 specification is vague... */
1689 /* grab up to the last argument */
1690 for ( count
= 5; count
> 0; count
-- )
1700 if ( dx
< 0 ) dx
= -dx
;
1701 if ( dy
< 0 ) dy
= -dy
;
1703 /* strange test, but here it is... */
1704 horizontal
= ( dx
> dy
);
1706 for ( count
= 5; count
> 0; count
-- )
1710 cff_builder_add_point( builder
, x
, y
, (FT_Bool
)( count
== 3 ) );
1714 /* is last operand an x- or y-delta? */
1726 cff_builder_add_point( builder
, x
, y
, 1 );
1737 FT_TRACE4(( " flex" ));
1739 if ( cff_builder_start_point( builder
, x
, y
) ||
1740 check_points( builder
, 6 ) )
1744 for ( count
= 6; count
> 0; count
-- )
1748 cff_builder_add_point( builder
, x
, y
,
1749 (FT_Bool
)( count
== 4 || count
== 1 ) );
1757 case cff_op_endchar
:
1758 FT_TRACE4(( " endchar" ));
1760 /* We are going to emulate the seac operator. */
1761 if ( num_args
== 4 )
1763 /* Save glyph width so that the subglyphs don't overwrite it. */
1764 FT_Pos glyph_width
= decoder
->glyph_width
;
1767 error
= cff_operator_seac( decoder
,
1770 (FT_Int
)( args
[2] >> 16 ),
1771 (FT_Int
)( args
[3] >> 16 ) );
1774 decoder
->glyph_width
= glyph_width
;
1781 cff_builder_close_contour( builder
);
1783 /* close hints recording session */
1786 if ( hinter
->close( hinter
->hints
,
1787 builder
->current
->n_points
) )
1790 /* apply hints to the loaded glyph outline now */
1791 hinter
->apply( hinter
->hints
,
1793 (PSH_Globals
)builder
->hints_globals
,
1794 decoder
->hint_mode
);
1797 /* add current outline to the glyph slot */
1798 FT_GlyphLoader_Add( builder
->loader
);
1802 FT_TRACE4(( "\n\n" ));
1806 FT_TRACE4(( " abs" ));
1814 FT_TRACE4(( " add" ));
1821 FT_TRACE4(( " sub" ));
1828 FT_TRACE4(( " div" ));
1830 args
[0] = FT_DivFix( args
[0], args
[1] );
1835 FT_TRACE4(( " neg" ));
1846 FT_TRACE4(( " rand" ));
1849 if ( Rand
>= 0x8000L
)
1853 seed
= FT_MulFix( seed
, 0x10000L
- seed
);
1861 FT_TRACE4(( " mul" ));
1863 args
[0] = FT_MulFix( args
[0], args
[1] );
1868 FT_TRACE4(( " sqrt" ));
1873 FT_Fixed root
= args
[0];
1879 new_root
= ( root
+ FT_DivFix( args
[0], root
) + 1 ) >> 1;
1880 if ( new_root
== root
|| count
<= 0 )
1893 FT_TRACE4(( " drop" ));
1902 FT_TRACE4(( " exch" ));
1913 FT_Int idx
= (FT_Int
)( args
[0] >> 16 );
1916 FT_TRACE4(( " index" ));
1920 else if ( idx
> num_args
- 2 )
1922 args
[0] = args
[-( idx
+ 1 )];
1929 FT_Int count
= (FT_Int
)( args
[0] >> 16 );
1930 FT_Int idx
= (FT_Int
)( args
[1] >> 16 );
1933 FT_TRACE4(( " roll" ));
1940 goto Stack_Underflow
;
1946 FT_Fixed tmp
= args
[count
- 1];
1950 for ( i
= count
- 2; i
>= 0; i
-- )
1951 args
[i
+ 1] = args
[i
];
1960 FT_Fixed tmp
= args
[0];
1964 for ( i
= 0; i
< count
- 1; i
++ )
1965 args
[i
] = args
[i
+ 1];
1966 args
[count
- 1] = tmp
;
1975 FT_TRACE4(( " dup" ));
1983 FT_Fixed val
= args
[0];
1984 FT_Int idx
= (FT_Int
)( args
[1] >> 16 );
1987 FT_TRACE4(( " put" ));
1989 if ( idx
>= 0 && idx
< decoder
->len_buildchar
)
1990 decoder
->buildchar
[idx
] = val
;
1996 FT_Int idx
= (FT_Int
)( args
[0] >> 16 );
2000 FT_TRACE4(( " get" ));
2002 if ( idx
>= 0 && idx
< decoder
->len_buildchar
)
2003 val
= decoder
->buildchar
[idx
];
2011 FT_TRACE4(( " store "));
2016 FT_TRACE4(( " load" ));
2020 case cff_op_dotsection
:
2021 /* this operator is deprecated and ignored by the parser */
2022 FT_TRACE4(( " dotsection" ));
2027 FT_Fixed cond
= args
[0] && args
[1];
2030 FT_TRACE4(( " and" ));
2032 args
[0] = cond
? 0x10000L
: 0;
2039 FT_Fixed cond
= args
[0] || args
[1];
2042 FT_TRACE4(( " or" ));
2044 args
[0] = cond
? 0x10000L
: 0;
2051 FT_Fixed cond
= !args
[0];
2054 FT_TRACE4(( " eq" ));
2056 args
[0] = cond
? 0x10000L
: 0;
2063 FT_Fixed cond
= ( args
[2] <= args
[3] );
2066 FT_TRACE4(( " ifelse" ));
2074 case cff_op_callsubr
:
2076 FT_UInt idx
= (FT_UInt
)( ( args
[0] >> 16 ) +
2077 decoder
->locals_bias
);
2080 FT_TRACE4(( " callsubr(%d)", idx
));
2082 if ( idx
>= decoder
->num_locals
)
2084 FT_ERROR(( "cff_decoder_parse_charstrings:" ));
2085 FT_ERROR(( " invalid local subr index\n" ));
2089 if ( zone
- decoder
->zones
>= CFF_MAX_SUBRS_CALLS
)
2091 FT_ERROR(( "cff_decoder_parse_charstrings:"
2092 " too many nested subrs\n" ));
2096 zone
->cursor
= ip
; /* save current instruction pointer */
2099 zone
->base
= decoder
->locals
[idx
];
2100 zone
->limit
= decoder
->locals
[idx
+ 1];
2101 zone
->cursor
= zone
->base
;
2103 if ( !zone
->base
|| zone
->limit
== zone
->base
)
2105 FT_ERROR(( "cff_decoder_parse_charstrings:"
2106 " invoking empty subrs!\n" ));
2110 decoder
->zone
= zone
;
2112 limit
= zone
->limit
;
2116 case cff_op_callgsubr
:
2118 FT_UInt idx
= (FT_UInt
)( ( args
[0] >> 16 ) +
2119 decoder
->globals_bias
);
2122 FT_TRACE4(( " callgsubr(%d)", idx
));
2124 if ( idx
>= decoder
->num_globals
)
2126 FT_ERROR(( "cff_decoder_parse_charstrings:" ));
2127 FT_ERROR(( " invalid global subr index\n" ));
2131 if ( zone
- decoder
->zones
>= CFF_MAX_SUBRS_CALLS
)
2133 FT_ERROR(( "cff_decoder_parse_charstrings:"
2134 " too many nested subrs\n" ));
2138 zone
->cursor
= ip
; /* save current instruction pointer */
2141 zone
->base
= decoder
->globals
[idx
];
2142 zone
->limit
= decoder
->globals
[idx
+ 1];
2143 zone
->cursor
= zone
->base
;
2145 if ( !zone
->base
|| zone
->limit
== zone
->base
)
2147 FT_ERROR(( "cff_decoder_parse_charstrings:"
2148 " invoking empty subrs!\n" ));
2152 decoder
->zone
= zone
;
2154 limit
= zone
->limit
;
2159 FT_TRACE4(( " return" ));
2161 if ( decoder
->zone
<= decoder
->zones
)
2163 FT_ERROR(( "cff_decoder_parse_charstrings:"
2164 " unexpected return\n" ));
2169 zone
= decoder
->zone
;
2171 limit
= zone
->limit
;
2176 FT_ERROR(( "Unimplemented opcode: %d", ip
[-1] ));
2179 FT_ERROR(( " %d", ip
[0] ));
2182 return CFF_Err_Unimplemented_Feature
;
2185 decoder
->top
= args
;
2187 } /* general operator processing */
2189 } /* while ip < limit */
2191 FT_TRACE4(( "..end..\n\n" ));
2197 FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error!" ));
2198 return CFF_Err_Invalid_File_Format
;
2201 FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow!" ));
2202 return CFF_Err_Too_Few_Arguments
;
2205 FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow!" ));
2206 return CFF_Err_Stack_Overflow
;
2210 /*************************************************************************/
2211 /*************************************************************************/
2212 /*************************************************************************/
2213 /********** *********/
2214 /********** *********/
2215 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
2216 /********** *********/
2217 /********** The following code is in charge of computing *********/
2218 /********** the maximum advance width of the font. It *********/
2219 /********** quickly processes each glyph charstring to *********/
2220 /********** extract the value from either a `sbw' or `seac' *********/
2221 /********** operator. *********/
2222 /********** *********/
2223 /*************************************************************************/
2224 /*************************************************************************/
2225 /*************************************************************************/
2228 #if 0 /* unused until we support pure CFF fonts */
2231 FT_LOCAL_DEF( FT_Error
)
2232 cff_compute_max_advance( TT_Face face
,
2233 FT_Int
* max_advance
)
2235 FT_Error error
= CFF_Err_Ok
;
2236 CFF_Decoder decoder
;
2238 CFF_Font cff
= (CFF_Font
)face
->other
;
2243 /* Initialize load decoder */
2244 cff_decoder_init( &decoder
, face
, 0, 0, 0, 0 );
2246 decoder
.builder
.metrics_only
= 1;
2247 decoder
.builder
.load_points
= 0;
2249 /* For each glyph, parse the glyph charstring and extract */
2250 /* the advance width. */
2251 for ( glyph_index
= 0; glyph_index
< face
->root
.num_glyphs
;
2254 FT_Byte
* charstring
;
2255 FT_ULong charstring_len
;
2258 /* now get load the unscaled outline */
2259 error
= cff_get_glyph_data( face
, glyph_index
,
2260 &charstring
, &charstring_len
);
2263 error
= cff_decoder_prepare( &decoder
, glyph_index
);
2265 error
= cff_decoder_parse_charstrings( &decoder
,
2269 cff_free_glyph_data( face
, &charstring
, &charstring_len
);
2272 /* ignore the error if one has occurred -- skip to next glyph */
2276 *max_advance
= decoder
.builder
.advance
.x
;
2285 FT_LOCAL_DEF( FT_Error
)
2286 cff_slot_load( CFF_GlyphSlot glyph
,
2288 FT_UInt glyph_index
,
2289 FT_Int32 load_flags
)
2292 CFF_Decoder decoder
;
2293 TT_Face face
= (TT_Face
)glyph
->root
.face
;
2295 CFF_Font cff
= (CFF_Font
)face
->extra
.data
;
2297 FT_Matrix font_matrix
;
2298 FT_Vector font_offset
;
2301 /* in a CID-keyed font, consider `glyph_index' as a CID and map */
2302 /* it immediately to the real glyph_index -- if it isn't a */
2303 /* subsetted font, glyph_indices and CIDs are identical, though */
2304 if ( cff
->top_font
.font_dict
.cid_registry
!= 0xFFFFU
&&
2307 glyph_index
= cff_charset_cid_to_gindex( &cff
->charset
, glyph_index
);
2308 if ( glyph_index
== 0 )
2309 return CFF_Err_Invalid_Argument
;
2311 else if ( glyph_index
>= cff
->num_glyphs
)
2312 return CFF_Err_Invalid_Argument
;
2314 if ( load_flags
& FT_LOAD_NO_RECURSE
)
2315 load_flags
|= FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
2317 glyph
->x_scale
= 0x10000L
;
2318 glyph
->y_scale
= 0x10000L
;
2321 glyph
->x_scale
= size
->root
.metrics
.x_scale
;
2322 glyph
->y_scale
= size
->root
.metrics
.y_scale
;
2325 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2327 /* try to load embedded bitmap if any */
2329 /* XXX: The convention should be emphasized in */
2330 /* the documents because it can be confusing. */
2333 CFF_Face cff_face
= (CFF_Face
)size
->root
.face
;
2334 SFNT_Service sfnt
= (SFNT_Service
)cff_face
->sfnt
;
2335 FT_Stream stream
= cff_face
->root
.stream
;
2338 if ( size
->strike_index
!= 0xFFFFFFFFUL
&&
2340 ( load_flags
& FT_LOAD_NO_BITMAP
) == 0 )
2342 TT_SBit_MetricsRec metrics
;
2345 error
= sfnt
->load_sbit_image( face
,
2350 &glyph
->root
.bitmap
,
2355 glyph
->root
.outline
.n_points
= 0;
2356 glyph
->root
.outline
.n_contours
= 0;
2358 glyph
->root
.metrics
.width
= (FT_Pos
)metrics
.width
<< 6;
2359 glyph
->root
.metrics
.height
= (FT_Pos
)metrics
.height
<< 6;
2361 glyph
->root
.metrics
.horiBearingX
= (FT_Pos
)metrics
.horiBearingX
<< 6;
2362 glyph
->root
.metrics
.horiBearingY
= (FT_Pos
)metrics
.horiBearingY
<< 6;
2363 glyph
->root
.metrics
.horiAdvance
= (FT_Pos
)metrics
.horiAdvance
<< 6;
2365 glyph
->root
.metrics
.vertBearingX
= (FT_Pos
)metrics
.vertBearingX
<< 6;
2366 glyph
->root
.metrics
.vertBearingY
= (FT_Pos
)metrics
.vertBearingY
<< 6;
2367 glyph
->root
.metrics
.vertAdvance
= (FT_Pos
)metrics
.vertAdvance
<< 6;
2369 glyph
->root
.format
= FT_GLYPH_FORMAT_BITMAP
;
2371 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
2373 glyph
->root
.bitmap_left
= metrics
.vertBearingX
;
2374 glyph
->root
.bitmap_top
= metrics
.vertBearingY
;
2378 glyph
->root
.bitmap_left
= metrics
.horiBearingX
;
2379 glyph
->root
.bitmap_top
= metrics
.horiBearingY
;
2386 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2388 /* return immediately if we only want the embedded bitmaps */
2389 if ( load_flags
& FT_LOAD_SBITS_ONLY
)
2390 return CFF_Err_Invalid_Argument
;
2392 glyph
->root
.outline
.n_points
= 0;
2393 glyph
->root
.outline
.n_contours
= 0;
2395 hinting
= FT_BOOL( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 &&
2396 ( load_flags
& FT_LOAD_NO_HINTING
) == 0 );
2398 glyph
->root
.format
= FT_GLYPH_FORMAT_OUTLINE
; /* by default */
2401 FT_Byte
* charstring
;
2402 FT_ULong charstring_len
;
2405 cff_decoder_init( &decoder
, face
, size
, glyph
, hinting
,
2406 FT_LOAD_TARGET_MODE( load_flags
) );
2408 decoder
.builder
.no_recurse
=
2409 (FT_Bool
)( ( load_flags
& FT_LOAD_NO_RECURSE
) != 0 );
2411 /* now load the unscaled outline */
2412 error
= cff_get_glyph_data( face
, glyph_index
,
2413 &charstring
, &charstring_len
);
2416 error
= cff_decoder_prepare( &decoder
, glyph_index
);
2419 error
= cff_decoder_parse_charstrings( &decoder
,
2423 cff_free_glyph_data( face
, &charstring
, charstring_len
);
2426 #ifdef FT_CONFIG_OPTION_INCREMENTAL
2427 /* Control data and length may not be available for incremental */
2429 if ( face
->root
.internal
->incremental_interface
)
2431 glyph
->root
.control_data
= 0;
2432 glyph
->root
.control_len
= 0;
2435 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
2437 /* We set control_data and control_len if charstrings is loaded. */
2438 /* See how charstring loads at cff_index_access_element() in */
2441 CFF_Index csindex
= &cff
->charstrings_index
;
2444 if ( csindex
->offsets
)
2446 glyph
->root
.control_data
= csindex
->bytes
+
2447 csindex
->offsets
[glyph_index
] - 1;
2448 glyph
->root
.control_len
= charstring_len
;
2454 /* save new glyph tables */
2455 cff_builder_done( &decoder
.builder
);
2458 #ifdef FT_CONFIG_OPTION_INCREMENTAL
2460 /* Incremental fonts can optionally override the metrics. */
2462 face
->root
.internal
->incremental_interface
&&
2463 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics
)
2465 FT_Incremental_MetricsRec metrics
;
2468 metrics
.bearing_x
= decoder
.builder
.left_bearing
.x
;
2469 metrics
.bearing_y
= decoder
.builder
.left_bearing
.y
;
2470 metrics
.advance
= decoder
.builder
.advance
.x
;
2471 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics(
2472 face
->root
.internal
->incremental_interface
->object
,
2473 glyph_index
, FALSE
, &metrics
);
2474 decoder
.builder
.left_bearing
.x
= metrics
.bearing_x
;
2475 decoder
.builder
.left_bearing
.y
= metrics
.bearing_y
;
2476 decoder
.builder
.advance
.x
= metrics
.advance
;
2477 decoder
.builder
.advance
.y
= 0;
2480 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
2484 if ( cff
->num_subfonts
>= 1 )
2486 FT_Byte fd_index
= cff_fd_select_get( &cff
->fd_select
,
2490 font_matrix
= cff
->subfonts
[fd_index
]->font_dict
.font_matrix
;
2491 font_offset
= cff
->subfonts
[fd_index
]->font_dict
.font_offset
;
2495 font_matrix
= cff
->top_font
.font_dict
.font_matrix
;
2496 font_offset
= cff
->top_font
.font_dict
.font_offset
;
2499 /* Now, set the metrics -- this is rather simple, as */
2500 /* the left side bearing is the xMin, and the top side */
2501 /* bearing the yMax. */
2503 /* For composite glyphs, return only left side bearing and */
2504 /* advance width. */
2505 if ( load_flags
& FT_LOAD_NO_RECURSE
)
2507 FT_Slot_Internal internal
= glyph
->root
.internal
;
2510 glyph
->root
.metrics
.horiBearingX
= decoder
.builder
.left_bearing
.x
;
2511 glyph
->root
.metrics
.horiAdvance
= decoder
.glyph_width
;
2512 internal
->glyph_matrix
= font_matrix
;
2513 internal
->glyph_delta
= font_offset
;
2514 internal
->glyph_transformed
= 1;
2519 FT_Glyph_Metrics
* metrics
= &glyph
->root
.metrics
;
2521 FT_Bool has_vertical_info
;
2524 /* copy the _unscaled_ advance width */
2525 metrics
->horiAdvance
= decoder
.glyph_width
;
2526 glyph
->root
.linearHoriAdvance
= decoder
.glyph_width
;
2527 glyph
->root
.internal
->glyph_transformed
= 0;
2529 has_vertical_info
= FT_BOOL( face
->vertical_info
&&
2530 face
->vertical
.number_Of_VMetrics
> 0 &&
2531 face
->vertical
.long_metrics
!= 0 );
2533 /* get the vertical metrics from the vtmx table if we have one */
2534 if ( has_vertical_info
)
2536 FT_Short vertBearingY
= 0;
2537 FT_UShort vertAdvance
= 0;
2540 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 1,
2544 metrics
->vertBearingY
= vertBearingY
;
2545 metrics
->vertAdvance
= vertAdvance
;
2549 /* make up vertical ones */
2550 if ( face
->os2
.version
!= 0xFFFFU
)
2551 metrics
->vertAdvance
= (FT_Pos
)( face
->os2
.sTypoAscender
-
2552 face
->os2
.sTypoDescender
);
2554 metrics
->vertAdvance
= (FT_Pos
)( face
->horizontal
.Ascender
-
2555 face
->horizontal
.Descender
);
2558 glyph
->root
.linearVertAdvance
= metrics
->vertAdvance
;
2560 glyph
->root
.format
= FT_GLYPH_FORMAT_OUTLINE
;
2562 glyph
->root
.outline
.flags
= 0;
2563 if ( size
&& size
->root
.metrics
.y_ppem
< 24 )
2564 glyph
->root
.outline
.flags
|= FT_OUTLINE_HIGH_PRECISION
;
2566 glyph
->root
.outline
.flags
|= FT_OUTLINE_REVERSE_FILL
;
2568 /* apply the font matrix */
2569 if ( !( font_matrix
.xx
== 0x10000L
&&
2570 font_matrix
.yy
== 0x10000L
&&
2571 font_matrix
.xy
== 0 &&
2572 font_matrix
.yx
== 0 ) )
2573 FT_Outline_Transform( &glyph
->root
.outline
, &font_matrix
);
2575 if ( !( font_offset
.x
== 0 &&
2576 font_offset
.y
== 0 ) )
2577 FT_Outline_Translate( &glyph
->root
.outline
,
2578 font_offset
.x
, font_offset
.y
);
2580 advance
.x
= metrics
->horiAdvance
;
2582 FT_Vector_Transform( &advance
, &font_matrix
);
2583 metrics
->horiAdvance
= advance
.x
+ font_offset
.x
;
2586 advance
.y
= metrics
->vertAdvance
;
2587 FT_Vector_Transform( &advance
, &font_matrix
);
2588 metrics
->vertAdvance
= advance
.y
+ font_offset
.y
;
2590 if ( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 )
2592 /* scale the outline and the metrics */
2594 FT_Outline
* cur
= &glyph
->root
.outline
;
2595 FT_Vector
* vec
= cur
->points
;
2596 FT_Fixed x_scale
= glyph
->x_scale
;
2597 FT_Fixed y_scale
= glyph
->y_scale
;
2600 /* First of all, scale the points */
2601 if ( !hinting
|| !decoder
.builder
.hints_funcs
)
2602 for ( n
= cur
->n_points
; n
> 0; n
--, vec
++ )
2604 vec
->x
= FT_MulFix( vec
->x
, x_scale
);
2605 vec
->y
= FT_MulFix( vec
->y
, y_scale
);
2608 /* Then scale the metrics */
2609 metrics
->horiAdvance
= FT_MulFix( metrics
->horiAdvance
, x_scale
);
2610 metrics
->vertAdvance
= FT_MulFix( metrics
->vertAdvance
, y_scale
);
2613 /* compute the other metrics */
2614 FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox
);
2616 metrics
->width
= cbox
.xMax
- cbox
.xMin
;
2617 metrics
->height
= cbox
.yMax
- cbox
.yMin
;
2619 metrics
->horiBearingX
= cbox
.xMin
;
2620 metrics
->horiBearingY
= cbox
.yMax
;
2622 if ( has_vertical_info
)
2623 metrics
->vertBearingX
= -metrics
->width
/ 2;
2625 ft_synthesize_vertical_metrics( metrics
,
2626 metrics
->vertAdvance
);