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 <freetype/src/cff/t2load.h>
35 #include <freetype/src/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;