1 /***************************************************************************/
5 /* OpenType Glyph Loader (body). */
7 /* Copyright 1996-2000 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 /***************************************************************************/
19 #include <freetype/internal/ftdebug.h>
20 #include <freetype/internal/ftcalc.h>
21 #include <freetype/internal/ftstream.h>
22 #include <freetype/internal/sfnt.h>
23 #include <freetype/ftoutln.h>
24 #include <freetype/tttags.h>
27 #ifdef FT_FLAT_COMPILE
34 #include <cff/t2load.h>
35 #include <cff/t2gload.h>
40 #include <freetype/internal/t2errors.h>
43 /*************************************************************************/
45 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
46 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
47 /* messages during execution. */
50 #define FT_COMPONENT trace_t2gload
53 typedef enum T2_Operator_
126 #define T2_COUNT_CHECK_WIDTH 0x80
127 #define T2_COUNT_EXACT 0x40
128 #define T2_COUNT_CLEAR_STACK 0x20
131 static const FT_Byte t2_argument_counts
[] =
135 2 | T2_COUNT_CHECK_WIDTH
| T2_COUNT_EXACT
, /* rmoveto */
136 1 | T2_COUNT_CHECK_WIDTH
| T2_COUNT_EXACT
,
137 1 | T2_COUNT_CHECK_WIDTH
| T2_COUNT_EXACT
,
139 0 | T2_COUNT_CLEAR_STACK
, /* rlineto */
140 0 | T2_COUNT_CLEAR_STACK
,
141 0 | T2_COUNT_CLEAR_STACK
,
143 0 | T2_COUNT_CLEAR_STACK
, /* rrcurveto */
144 0 | T2_COUNT_CLEAR_STACK
,
145 0 | T2_COUNT_CLEAR_STACK
,
146 0 | T2_COUNT_CLEAR_STACK
,
147 0 | T2_COUNT_CLEAR_STACK
,
148 0 | T2_COUNT_CLEAR_STACK
,
149 0 | T2_COUNT_CLEAR_STACK
,
158 2 | T2_COUNT_CHECK_WIDTH
, /* hstem */
159 2 | T2_COUNT_CHECK_WIDTH
,
160 2 | T2_COUNT_CHECK_WIDTH
,
161 2 | T2_COUNT_CHECK_WIDTH
,
200 /*************************************************************************/
201 /*************************************************************************/
202 /*************************************************************************/
203 /********** *********/
204 /********** *********/
205 /********** GENERIC CHARSTRING PARSING *********/
206 /********** *********/
207 /********** *********/
208 /*************************************************************************/
209 /*************************************************************************/
210 /*************************************************************************/
213 /*************************************************************************/
216 /* T2_Init_Builder */
219 /* Initializes a given glyph builder. */
222 /* builder :: A pointer to the glyph builder to initialize. */
225 /* face :: The current face object. */
227 /* size :: The current size object. */
229 /* glyph :: The current glyph object. */
232 void T2_Init_Builder( T2_Builder
* builder
,
237 builder
->path_begun
= 0;
238 builder
->load_points
= 1;
240 builder
->face
= face
;
241 builder
->glyph
= glyph
;
242 builder
->memory
= face
->root
.memory
;
246 FT_GlyphLoader
* loader
= glyph
->root
.loader
;
249 builder
->loader
= loader
;
250 builder
->base
= &loader
->base
.outline
;
251 builder
->current
= &loader
->current
.outline
;
252 FT_GlyphLoader_Rewind( loader
);
257 builder
->scale_x
= size
->metrics
.x_scale
;
258 builder
->scale_y
= size
->metrics
.y_scale
;
264 builder
->left_bearing
.x
= 0;
265 builder
->left_bearing
.y
= 0;
266 builder
->advance
.x
= 0;
267 builder
->advance
.y
= 0;
271 /*************************************************************************/
274 /* T2_Done_Builder */
277 /* Finalizes a given glyph builder. Its contents can still be used */
278 /* after the call, but the function saves important information */
279 /* within the corresponding glyph slot. */
282 /* builder :: A pointer to the glyph builder to finalize. */
285 void T2_Done_Builder( T2_Builder
* builder
)
287 T2_GlyphSlot glyph
= builder
->glyph
;
291 glyph
->root
.outline
= *builder
->base
;
295 /*************************************************************************/
298 /* t2_compute_bias */
301 /* Computes the bias value in dependence of the number of glyph */
305 /* num_subrs :: The number of glyph subroutines. */
308 /* The bias value. */
310 FT_Int
t2_compute_bias( FT_UInt num_subrs
)
315 if ( num_subrs
< 1240 )
317 else if ( num_subrs
< 33900 )
326 /*************************************************************************/
329 /* T2_Init_Decoder */
332 /* Initializes a given glyph decoder. */
335 /* decoder :: A pointer to the glyph builder to initialize. */
338 /* face :: The current face object. */
340 /* size :: The current size object. */
342 /* slot :: The current glyph object. */
345 void T2_Init_Decoder( T2_Decoder
* decoder
,
350 CFF_Font
* cff
= (CFF_Font
*)face
->extra
.data
;
353 /* clear everything */
354 MEM_Set( decoder
, 0, sizeof ( *decoder
) );
356 /* initialize builder */
357 T2_Init_Builder( &decoder
->builder
, face
, size
, slot
);
359 /* initialize Type2 decoder */
360 decoder
->num_globals
= cff
->num_global_subrs
;
361 decoder
->globals
= cff
->global_subrs
;
362 decoder
->globals_bias
= t2_compute_bias( decoder
->num_globals
);
366 /* this function is used to select the locals subrs array */
368 void T2_Prepare_Decoder( T2_Decoder
* decoder
,
369 FT_UInt glyph_index
)
371 CFF_Font
* cff
= (CFF_Font
*)decoder
->builder
.face
->extra
.data
;
372 CFF_SubFont
* sub
= &cff
->top_font
;
375 /* manage CID fonts */
376 if ( cff
->num_subfonts
>= 1 )
378 FT_Byte fd_index
= CFF_Get_FD( &cff
->fd_select
, glyph_index
);
381 sub
= cff
->subfonts
[fd_index
];
384 decoder
->num_locals
= sub
->num_local_subrs
;
385 decoder
->locals
= sub
->local_subrs
;
386 decoder
->locals_bias
= t2_compute_bias( decoder
->num_locals
);
388 decoder
->glyph_width
= sub
->private_dict
.default_width
;
389 decoder
->nominal_width
= sub
->private_dict
.nominal_width
;
393 /* check that there is enough room for `count' more points */
395 FT_Error
check_points( T2_Builder
* builder
,
398 return FT_GlyphLoader_Check_Points( builder
->loader
, count
, 0 );
402 /* add a new point, do not check space */
404 void add_point( T2_Builder
* builder
,
409 FT_Outline
* outline
= builder
->current
;
412 if ( builder
->load_points
)
414 FT_Vector
* point
= outline
->points
+ outline
->n_points
;
415 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
;
420 *control
= flag
? FT_Curve_Tag_On
: FT_Curve_Tag_Cubic
;
422 builder
->last
= *point
;
428 /* check space for a new on-curve point, then add it */
430 FT_Error
add_point1( T2_Builder
* builder
,
437 error
= check_points( builder
, 1 );
439 add_point( builder
, x
, y
, 1 );
445 /* check room for a new contour, then add it */
447 FT_Error
add_contour( T2_Builder
* builder
)
449 FT_Outline
* outline
= builder
->current
;
453 if ( !builder
->load_points
)
455 outline
->n_contours
++;
459 error
= FT_GlyphLoader_Check_Points( builder
->loader
, 0, 1 );
462 if ( outline
->n_contours
> 0 )
463 outline
->contours
[outline
->n_contours
- 1] = outline
->n_points
- 1;
465 outline
->n_contours
++;
472 /* if a path was begun, add its first on-curve point */
474 FT_Error
start_point( T2_Builder
* builder
,
481 /* test whether we are building a new contour */
482 if ( !builder
->path_begun
)
484 builder
->path_begun
= 1;
485 error
= add_contour( builder
);
487 error
= add_point1( builder
, x
, y
);
493 /* close the current contour */
495 void close_contour( T2_Builder
* builder
)
497 FT_Outline
* outline
= builder
->current
;
499 /* XXXX: We must not include the last point in the path if it */
500 /* is located on the first point. */
501 if ( outline
->n_points
> 1 )
504 FT_Vector
* p1
= outline
->points
+ first
;
505 FT_Vector
* p2
= outline
->points
+ outline
->n_points
- 1;
507 if ( outline
->n_contours
> 1 )
509 first
= outline
->contours
[outline
->n_contours
- 2] + 1;
510 p1
= outline
->points
+ first
;
513 if ( p1
->x
== p2
->x
&& p1
->y
== p2
->y
)
517 if ( outline
->n_contours
> 0 )
518 outline
->contours
[outline
->n_contours
- 1] = outline
->n_points
- 1;
522 #define USE_ARGS( n ) do \
525 if ( top < decoder->stack ) \
526 goto Stack_Underflow; \
530 /*************************************************************************/
533 /* T2_Parse_CharStrings */
536 /* Parses a given Type 2 charstrings program. */
539 /* decoder :: The current Type 1 decoder. */
542 /* charstring_base :: The base of the charstring stream. */
544 /* charstring_len :: The length in bytes of the charstring stream. */
547 /* FreeType error code. 0 means success. */
550 FT_Error
T2_Parse_CharStrings( T2_Decoder
* decoder
,
551 FT_Byte
* charstring_base
,
552 FT_Int charstring_len
)
555 T2_Decoder_Zone
* zone
;
558 T2_Builder
* builder
= &decoder
->builder
;
565 /* set default width */
566 decoder
->num_hints
= 0;
567 decoder
->read_width
= 1;
569 /* compute random seed from stack address of parameter */
570 seed
= (FT_Fixed
)(char*)&seed
^
571 (FT_Fixed
)(char*)&decoder
^
572 (FT_Fixed
)(char*)&charstring_base
;
573 seed
= ( seed
^ ( seed
>> 10 ) ^ ( seed
>> 20 ) ) & 0xFFFF;
577 /* initialize the decoder */
578 decoder
->top
= decoder
->stack
;
579 decoder
->zone
= decoder
->zones
;
580 zone
= decoder
->zones
;
581 stack
= decoder
->top
;
583 builder
->path_begun
= 0;
585 zone
->base
= charstring_base
;
586 limit
= zone
->limit
= charstring_base
+ charstring_len
;
587 ip
= zone
->cursor
= zone
->base
;
590 outline
= builder
->current
;
595 /* now, execute loop */
603 /********************************************************************/
605 /* Decode operator or operand */
608 if ( v
>= 32 || v
== 28 )
614 /* this is an operand, push it on the stack */
617 if ( ip
+ 1 >= limit
)
619 val
= (FT_Short
)( ( (FT_Short
)ip
[0] << 8 ) | ip
[1] );
623 val
= (FT_Long
)v
- 139;
628 val
= ( (FT_Long
)v
- 247 ) * 256 + *ip
++ + 108;
634 val
= -( (FT_Long
)v
- 251 ) * 256 - *ip
++ - 108;
638 if ( ip
+ 3 >= limit
)
640 val
= ( (FT_Int32
)ip
[0] << 24 ) |
641 ( (FT_Int32
)ip
[1] << 16 ) |
642 ( (FT_Int32
)ip
[2] << 8 ) |
647 if ( decoder
->top
- stack
>= T2_MAX_OPERANDS
)
651 *decoder
->top
++ = val
;
653 #ifdef FT_DEBUG_LEVEL_TRACE
654 if ( !( val
& 0xFFFF ) )
655 FT_TRACE4(( " %d", (FT_Int32
)( val
>> 16 ) ));
657 FT_TRACE4(( " %.2f", val
/65536.0 ));
663 FT_Fixed
* args
= decoder
->top
;
664 FT_Int num_args
= args
- decoder
->stack
;
692 op
= t2_op_rrcurveto
;
787 /* decrement ip for syntax error message */
817 op
= t2_op_rcurveline
;
820 op
= t2_op_rlinecurve
;
823 op
= t2_op_vvcurveto
;
826 op
= t2_op_hhcurveto
;
829 op
= t2_op_callgsubr
;
832 op
= t2_op_vhcurveto
;
835 op
= t2_op_hvcurveto
;
840 if ( op
== t2_op_unknown
)
843 /* check arguments */
844 req_args
= count
= t2_argument_counts
[op
];
845 if ( req_args
& T2_COUNT_CHECK_WIDTH
)
848 if ( num_args
& 1 && decoder
->read_width
)
850 decoder
->glyph_width
= decoder
->nominal_width
+
855 decoder
->read_width
= 0;
860 if ( num_args
< req_args
)
861 goto Stack_Underflow
;
863 num_args
-= req_args
;
871 /* if the number of arguments is not even, the first one */
872 /* is simply the glyph width, encoded as the difference */
873 /* to nominalWidthX */
874 FT_TRACE4(( op
== t2_op_hstem
? " hstem" :
875 op
== t2_op_vstem
? " vstem" :
876 op
== t2_op_hstemhm
? " hstemhm" :
878 decoder
->num_hints
+= num_args
/ 2;
884 FT_TRACE4(( op
== t2_op_hintmask
? " hintmask"
887 decoder
->num_hints
+= num_args
/ 2;
888 ip
+= ( decoder
->num_hints
+ 7 ) >> 3;
895 FT_TRACE4(( " rmoveto" ));
897 close_contour( builder
);
898 builder
->path_begun
= 0;
905 FT_TRACE4(( " vmoveto" ));
907 close_contour( builder
);
908 builder
->path_begun
= 0;
914 FT_TRACE4(( " hmoveto" ));
916 close_contour( builder
);
917 builder
->path_begun
= 0;
923 FT_TRACE4(( " rlineto" ));
925 if ( start_point ( builder
, x
, y
) ||
926 check_points( builder
, num_args
/ 2 ) )
929 if ( num_args
< 2 || num_args
& 1 )
930 goto Stack_Underflow
;
933 while ( args
< decoder
->top
)
937 add_point( builder
, x
, y
, 1 );
946 FT_Int phase
= ( op
== t2_op_hlineto
);
949 FT_TRACE4(( op
== t2_op_hlineto
? " hlineto"
952 if ( start_point ( builder
, x
, y
) ||
953 check_points( builder
, num_args
) )
957 while (args
< decoder
->top
)
964 if ( add_point1( builder
, x
, y
) )
974 case t2_op_rrcurveto
:
975 FT_TRACE4(( " rrcurveto" ));
977 /* check number of arguments; must be a multiple of 6 */
978 if ( num_args
% 6 != 0 )
979 goto Stack_Underflow
;
981 if ( start_point ( builder
, x
, y
) ||
982 check_points( builder
, num_args
/ 2 ) )
986 while ( args
< decoder
->top
)
990 add_point( builder
, x
, y
, 0 );
993 add_point( builder
, x
, y
, 0 );
996 add_point( builder
, x
, y
, 1 );
1002 case t2_op_vvcurveto
:
1003 FT_TRACE4(( " vvcurveto" ));
1005 if ( start_point ( builder
, x
, y
) )
1016 if ( num_args
% 4 != 0 )
1017 goto Stack_Underflow
;
1019 if ( check_points( builder
, 3 * ( num_args
/ 4 ) ) )
1022 while ( args
< decoder
->top
)
1025 add_point( builder
, x
, y
, 0 );
1028 add_point( builder
, x
, y
, 0 );
1030 add_point( builder
, x
, y
, 1 );
1036 case t2_op_hhcurveto
:
1037 FT_TRACE4(( " hhcurveto" ));
1039 if ( start_point ( builder
, x
, y
) )
1050 if ( num_args
% 4 != 0 )
1051 goto Stack_Underflow
;
1053 if ( check_points( builder
, 3 * ( num_args
/ 4 ) ) )
1056 while ( args
< decoder
->top
)
1059 add_point( builder
, x
, y
, 0 );
1062 add_point( builder
, x
, y
, 0 );
1064 add_point( builder
, x
, y
, 1 );
1070 case t2_op_vhcurveto
:
1071 case t2_op_hvcurveto
:
1076 FT_TRACE4(( op
== t2_op_vhcurveto
? " vhcurveto"
1079 if ( start_point ( builder
, x
, y
) )
1083 if (num_args
< 4 || ( num_args
% 4 ) > 1 )
1084 goto Stack_Underflow
;
1086 if ( check_points( builder
, ( num_args
/ 4 ) * 3 ) )
1087 goto Stack_Underflow
;
1089 phase
= ( op
== t2_op_hvcurveto
);
1091 while ( num_args
>= 4 )
1097 add_point( builder
, x
, y
, 0 );
1100 add_point( builder
, x
, y
, 0 );
1102 if ( num_args
== 1 )
1104 add_point( builder
, x
, y
, 1 );
1109 add_point( builder
, x
, y
, 0 );
1112 add_point( builder
, x
, y
, 0 );
1114 if ( num_args
== 1 )
1116 add_point( builder
, x
, y
, 1 );
1125 case t2_op_rlinecurve
:
1127 FT_Int num_lines
= ( num_args
- 6 ) / 2;
1130 FT_TRACE4(( " rlinecurve" ));
1132 if ( num_args
< 8 || ( num_args
- 6 ) & 1 )
1133 goto Stack_Underflow
;
1135 if ( start_point( builder
, x
, y
) ||
1136 check_points( builder
, num_lines
+ 3 ) )
1141 /* first, add the line segments */
1142 while ( num_lines
> 0 )
1146 add_point( builder
, x
, y
, 1 );
1151 /* then the curve */
1154 add_point( builder
, x
, y
, 0 );
1157 add_point( builder
, x
, y
, 0 );
1160 add_point( builder
, x
, y
, 1 );
1165 case t2_op_rcurveline
:
1167 FT_Int num_curves
= ( num_args
- 2 ) / 6;
1170 FT_TRACE4(( " rcurveline" ));
1172 if ( num_args
< 8 || ( num_args
- 2 ) % 6 )
1173 goto Stack_Underflow
;
1175 if ( start_point ( builder
, x
, y
) ||
1176 check_points( builder
, num_curves
*3 + 2 ) )
1181 /* first, add the curves */
1182 while ( num_curves
> 0 )
1186 add_point( builder
, x
, y
, 0 );
1189 add_point( builder
, x
, y
, 0 );
1192 add_point( builder
, x
, y
, 1 );
1197 /* then the final line */
1200 add_point( builder
, x
, y
, 1 );
1210 FT_TRACE4(( " hflex1" ));
1214 /* adding five more points; 4 control points, 1 on-curve point */
1215 /* make sure we have enough space for the start point if it */
1216 /* needs to be added.. */
1217 if ( start_point( builder
, x
, y
) ||
1218 check_points( builder
, 6 ) )
1221 /* Record the starting point's y postion for later use */
1224 /* first control point */
1227 add_point( builder
, x
, y
, 0 );
1229 /* second control point */
1232 add_point( builder
, x
, y
, 0 );
1234 /* join point; on curve, with y-value the same as the last */
1235 /* control point's y-value */
1237 add_point( builder
, x
, y
, 1 );
1239 /* third control point, with y-value the same as the join */
1240 /* point's y-value */
1242 add_point( builder
, x
, y
, 0 );
1244 /* fourth control point */
1247 add_point( builder
, x
, y
, 0 );
1249 /* ending point, with y-value the same as the start */
1252 add_point( builder
, x
, y
, 1 );
1263 FT_TRACE4(( " hflex" ));
1267 /* adding six more points; 4 control points, 2 on-curve points */
1268 if ( start_point( builder
, x
, y
) ||
1269 check_points ( builder
, 6 ) )
1272 /* record the starting point's y-position for later use */
1275 /* first control point */
1277 add_point( builder
, x
, y
, 0 );
1279 /* second control point */
1282 add_point( builder
, x
, y
, 0 );
1284 /* join point; on curve, with y-value the same as the last */
1285 /* control point's y-value */
1287 add_point( builder
, x
, y
, 1 );
1289 /* third control point, with y-value the same as the join */
1290 /* point's y-value */
1292 add_point( builder
, x
, y
, 0 );
1294 /* fourth control point */
1297 add_point( builder
, x
, y
, 0 );
1299 /* ending point, with y-value the same as the start point's */
1300 /* y-value -- we don't add this point, though */
1302 add_point( builder
, x
, y
, 1 );
1310 FT_Pos start_x
, start_y
; /* record start x, y values for alter */
1312 FT_Int dx
= 0, dy
= 0; /* used in horizontal/vertical */
1313 /* algorithm below */
1314 FT_Int horizontal
, count
;
1317 FT_TRACE4(( " flex1" ));
1319 /* adding six more points; 4 control points, 2 on-curve points */
1320 if ( start_point( builder
, x
, y
) ||
1321 check_points( builder
, 6 ) )
1324 /* record the starting point's x, y postion for later use */
1328 /* XXX: figure out whether this is supposed to be a horizontal */
1329 /* or vertical flex; the Type 2 specification is vague... */
1333 /* grab up to the last argument */
1334 for ( count
= 5; count
> 0; count
-- )
1344 if ( dx
< 0 ) dx
= -dx
;
1345 if ( dy
< 0 ) dy
= -dy
;
1347 /* strange test, but here it is... */
1348 horizontal
= ( dx
> dy
);
1350 for ( count
= 5; count
> 0; count
-- )
1354 add_point( builder
, x
, y
, (FT_Bool
)( count
== 3 ) );
1358 /* is last operand an x- or y-delta? */
1370 add_point( builder
, x
, y
, 1 );
1381 FT_TRACE4(( " flex" ));
1383 if ( start_point( builder
, x
, y
) ||
1384 check_points( builder
, 6 ) )
1388 for ( count
= 6; count
> 0; count
-- )
1392 add_point( builder
, x
, y
,
1393 (FT_Bool
)( count
== 3 || count
== 0 ) );
1402 FT_TRACE4(( " endchar" ));
1404 close_contour( builder
);
1406 /* add current outline to the glyph slot */
1407 FT_GlyphLoader_Add( builder
->loader
);
1410 FT_TRACE4(( "\n\n" ));
1414 FT_TRACE4(( " abs" ));
1422 FT_TRACE4(( " add" ));
1429 FT_TRACE4(( " sub" ));
1436 FT_TRACE4(( " div" ));
1438 args
[0] = FT_DivFix( args
[0], args
[1] );
1443 FT_TRACE4(( " neg" ));
1454 FT_TRACE4(( " rand" ));
1457 if ( rand
>= 0x8000 )
1461 seed
= FT_MulFix( seed
, 0x10000L
- seed
);
1469 FT_TRACE4(( " mul" ));
1471 args
[0] = FT_MulFix( args
[0], args
[1] );
1476 FT_TRACE4(( " sqrt" ));
1481 FT_Fixed root
= args
[0];
1487 new_root
= ( root
+ FT_DivFix(args
[0],root
) + 1 ) >> 1;
1488 if ( new_root
== root
|| count
<= 0 )
1501 FT_TRACE4(( " drop" ));
1510 FT_TRACE4(( " exch" ));
1521 FT_Int index
= args
[0] >> 16;
1524 FT_TRACE4(( " index" ));
1528 else if ( index
> num_args
- 2 )
1529 index
= num_args
- 2;
1530 args
[0] = args
[-( index
+ 1 )];
1537 FT_Int count
= (FT_Int
)( args
[0] >> 16 );
1538 FT_Int index
= (FT_Int
)( args
[1] >> 16 );
1541 FT_TRACE4(( " roll" ));
1548 goto Stack_Underflow
;
1554 FT_Fixed tmp
= args
[count
- 1];
1558 for ( i
= count
- 2; i
>= 0; i
-- )
1559 args
[i
+ 1] = args
[i
];
1568 FT_Fixed tmp
= args
[0];
1572 for ( i
= 0; i
< count
- 1; i
++ )
1573 args
[i
] = args
[i
+ 1];
1574 args
[count
- 1] = tmp
;
1583 FT_TRACE4(( " dup" ));
1591 FT_Fixed val
= args
[0];
1592 FT_Int index
= (FT_Int
)( args
[1] >> 16 );
1595 FT_TRACE4(( " put" ));
1597 if ( index
>= 0 && index
< decoder
->len_buildchar
)
1598 decoder
->buildchar
[index
] = val
;
1604 FT_Int index
= (FT_Int
)( args
[0] >> 16 );
1608 FT_TRACE4(( " get" ));
1610 if ( index
>= 0 && index
< decoder
->len_buildchar
)
1611 val
= decoder
->buildchar
[index
];
1619 FT_TRACE4(( " store "));
1624 FT_TRACE4(( " load" ));
1630 FT_Fixed cond
= args
[0] && args
[1];
1633 FT_TRACE4(( " and" ));
1635 args
[0] = cond
? 0x10000L
: 0;
1642 FT_Fixed cond
= args
[0] || args
[1];
1645 FT_TRACE4(( " or" ));
1647 args
[0] = cond
? 0x10000L
: 0;
1654 FT_Fixed cond
= !args
[0];
1657 FT_TRACE4(( " eq" ));
1659 args
[0] = cond
? 0x10000L
: 0;
1666 FT_Fixed cond
= (args
[2] <= args
[3]);
1669 FT_TRACE4(( " ifelse" ));
1677 case t2_op_callsubr
:
1679 FT_UInt index
= (FT_UInt
)( ( args
[0] >> 16 ) +
1680 decoder
->locals_bias
);
1683 FT_TRACE4(( " callsubr(%d)", index
));
1685 if ( index
>= decoder
->num_locals
)
1687 FT_ERROR(( "T2_Parse_CharStrings:" ));
1688 FT_ERROR(( " invalid local subr index\n" ));
1692 if ( zone
- decoder
->zones
>= T2_MAX_SUBRS_CALLS
)
1694 FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" ));
1698 zone
->cursor
= ip
; /* save current instruction pointer */
1701 zone
->base
= decoder
->locals
[index
];
1702 zone
->limit
= decoder
->locals
[index
+1];
1703 zone
->cursor
= zone
->base
;
1707 FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" ));
1711 decoder
->zone
= zone
;
1713 limit
= zone
->limit
;
1717 case t2_op_callgsubr
:
1719 FT_UInt index
= (FT_UInt
)( ( args
[0] >> 16 ) +
1720 decoder
->globals_bias
);
1723 FT_TRACE4(( " callgsubr(%d)", index
));
1725 if ( index
>= decoder
->num_globals
)
1727 FT_ERROR(( "T2_Parse_CharStrings:" ));
1728 FT_ERROR(( " invalid global subr index\n" ));
1732 if ( zone
- decoder
->zones
>= T2_MAX_SUBRS_CALLS
)
1734 FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" ));
1738 zone
->cursor
= ip
; /* save current instruction pointer */
1741 zone
->base
= decoder
->globals
[index
];
1742 zone
->limit
= decoder
->globals
[index
+1];
1743 zone
->cursor
= zone
->base
;
1747 FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" ));
1751 decoder
->zone
= zone
;
1753 limit
= zone
->limit
;
1758 FT_TRACE4(( " return" ));
1760 if ( decoder
->zone
<= decoder
->zones
)
1762 FT_ERROR(( "T2_Parse_CharStrings: unexpected return\n" ));
1767 zone
= decoder
->zone
;
1769 limit
= zone
->limit
;
1774 FT_ERROR(( "Unimplemented opcode: %d", ip
[-1] ));
1777 FT_ERROR(( " %d", ip
[0] ));
1780 return T2_Err_Unimplemented_Feature
;
1783 decoder
->top
= args
;
1785 } /* general operator processing */
1787 } /* while ip < limit */
1789 FT_TRACE4(( "..end..\n\n" ));
1794 FT_TRACE4(( "T2_Parse_CharStrings: syntax error!" ));
1795 return T2_Err_Invalid_File_Format
;
1798 FT_TRACE4(( "T2_Parse_CharStrings: stack underflow!" ));
1799 return T2_Err_Too_Few_Arguments
;
1802 FT_TRACE4(( "T2_Parse_CharStrings: stack overflow!" ));
1803 return T2_Err_Stack_Overflow
;
1806 return builder
->error
;
1810 /*************************************************************************/
1811 /*************************************************************************/
1812 /*************************************************************************/
1813 /********** *********/
1814 /********** *********/
1815 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
1816 /********** *********/
1817 /********** The following code is in charge of computing *********/
1818 /********** the maximum advance width of the font. It *********/
1819 /********** quickly processes each glyph charstring to *********/
1820 /********** extract the value from either a `sbw' or `seac' *********/
1821 /********** operator. *********/
1822 /********** *********/
1823 /*************************************************************************/
1824 /*************************************************************************/
1825 /*************************************************************************/
1828 #if 0 /* unused until we support pure CFF fonts */
1832 FT_Error
T2_Compute_Max_Advance( TT_Face face
,
1833 FT_Int
* max_advance
)
1838 CFF_Font
* cff
= (CFF_Font
*)face
->other
;
1843 /* Initialize load decoder */
1844 T2_Init_Decoder( &decoder
, face
, 0, 0 );
1846 decoder
.builder
.metrics_only
= 1;
1847 decoder
.builder
.load_points
= 0;
1849 /* For each glyph, parse the glyph charstring and extract */
1850 /* the advance width. */
1851 for ( glyph_index
= 0; glyph_index
< face
->root
.num_glyphs
;
1854 FT_Byte
* charstring
;
1855 FT_ULong charstring_len
;
1858 /* now get load the unscaled outline */
1859 error
= T2_Access_Element( &cff
->charstrings_index
, glyph_index
,
1860 &charstring
, &charstring_len
);
1863 T2_Prepare_Decoder( &decoder
, glyph_index
);
1864 error
= T2_Parse_CharStrings( &decoder
, charstring
, charstring_len
);
1866 T2_Forget_Element( &cff
->charstrings_index
, &charstring
);
1869 /* ignore the error if one has occurred -- skip to next glyph */
1873 *max_advance
= decoder
.builder
.advance
.x
;
1882 /*************************************************************************/
1883 /*************************************************************************/
1884 /*************************************************************************/
1885 /********** *********/
1886 /********** *********/
1887 /********** UNHINTED GLYPH LOADER *********/
1888 /********** *********/
1889 /********** The following code is in charge of loading a *********/
1890 /********** single outline. It completely ignores hinting *********/
1891 /********** and is used when FT_LOAD_NO_HINTING is set. *********/
1892 /********** *********/
1893 /*************************************************************************/
1894 /*************************************************************************/
1895 /*************************************************************************/
1899 FT_Error
T2_Load_Glyph( T2_GlyphSlot glyph
,
1906 TT_Face face
= (TT_Face
)glyph
->root
.face
;
1908 CFF_Font
* cff
= (CFF_Font
*)face
->extra
.data
;
1911 if ( load_flags
& FT_LOAD_NO_RECURSE
)
1912 load_flags
|= FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
1914 glyph
->x_scale
= 0x10000L
;
1915 glyph
->y_scale
= 0x10000L
;
1918 glyph
->x_scale
= size
->metrics
.x_scale
;
1919 glyph
->y_scale
= size
->metrics
.y_scale
;
1922 glyph
->root
.outline
.n_points
= 0;
1923 glyph
->root
.outline
.n_contours
= 0;
1925 hinting
= ( load_flags
& FT_LOAD_NO_SCALE
) == 0 &&
1926 ( load_flags
& FT_LOAD_NO_HINTING
) == 0;
1928 glyph
->root
.format
= ft_glyph_format_outline
; /* by default */
1931 FT_Byte
* charstring
;
1932 FT_ULong charstring_len
;
1935 T2_Init_Decoder( &decoder
, face
, size
, glyph
);
1937 decoder
.builder
.no_recurse
=
1938 (FT_Bool
)( ( load_flags
& FT_LOAD_NO_RECURSE
) != 0 );
1940 /* now load the unscaled outline */
1941 error
= T2_Access_Element( &cff
->charstrings_index
, glyph_index
,
1942 &charstring
, &charstring_len
);
1945 T2_Prepare_Decoder( &decoder
, glyph_index
);
1946 error
= T2_Parse_CharStrings( &decoder
, charstring
, charstring_len
);
1948 T2_Forget_Element( &cff
->charstrings_index
, &charstring
);
1951 /* save new glyph tables */
1952 T2_Done_Builder( &decoder
.builder
);
1955 /* Now, set the metrics -- this is rather simple, as */
1956 /* the left side bearing is the xMin, and the top side */
1957 /* bearing the yMax. */
1960 /* for composite glyphs, return only left side bearing and */
1962 if ( glyph
->root
.format
== ft_glyph_format_composite
)
1964 glyph
->root
.metrics
.horiBearingX
= decoder
.builder
.left_bearing
.x
;
1965 glyph
->root
.metrics
.horiAdvance
= decoder
.glyph_width
;
1970 FT_Glyph_Metrics
* metrics
= &glyph
->root
.metrics
;
1973 /* copy the _unscaled_ advance width */
1974 metrics
->horiAdvance
= decoder
.glyph_width
;
1976 /* make up vertical metrics */
1977 metrics
->vertBearingX
= 0;
1978 metrics
->vertBearingY
= 0;
1979 metrics
->vertAdvance
= 0;
1981 glyph
->root
.format
= ft_glyph_format_outline
;
1983 glyph
->root
.outline
.flags
= 0;
1984 if ( size
&& size
->metrics
.y_ppem
< 24 )
1985 glyph
->root
.outline
.flags
|= ft_outline_high_precision
;
1987 glyph
->root
.outline
.flags
|= ft_outline_reverse_fill
;
1989 if ( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1991 /* scale the outline and the metrics */
1993 FT_Outline
* cur
= &glyph
->root
.outline
;
1994 FT_Vector
* vec
= cur
->points
;
1995 FT_Fixed x_scale
= glyph
->x_scale
;
1996 FT_Fixed y_scale
= glyph
->y_scale
;
1999 /* First of all, scale the points */
2000 for ( n
= cur
->n_points
; n
> 0; n
--, vec
++ )
2002 vec
->x
= FT_MulFix( vec
->x
, x_scale
);
2003 vec
->y
= FT_MulFix( vec
->y
, y_scale
);
2006 FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox
);
2008 /* Then scale the metrics */
2009 metrics
->horiAdvance
= FT_MulFix( metrics
->horiAdvance
, x_scale
);
2010 metrics
->vertAdvance
= FT_MulFix( metrics
->vertAdvance
, y_scale
);
2012 metrics
->vertBearingX
= FT_MulFix( metrics
->vertBearingX
, x_scale
);
2013 metrics
->vertBearingY
= FT_MulFix( metrics
->vertBearingY
, y_scale
);
2017 /* apply the font matrix */
2018 FT_Outline_Transform( &glyph
->root
.outline
, cff
->font_matrix
);
2021 /* compute the other metrics */
2022 FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox
);
2024 /* grid fit the bounding box if necessary */
2029 cbox
.xMax
= ( cbox
.xMax
+ 63 ) & -64;
2030 cbox
.yMax
= ( cbox
.yMax
+ 63 ) & -64;
2033 metrics
->width
= cbox
.xMax
- cbox
.xMin
;
2034 metrics
->height
= cbox
.yMax
- cbox
.yMin
;
2036 metrics
->horiBearingX
= cbox
.xMin
;
2037 metrics
->horiBearingY
= cbox
.yMax
;