1 /***************************************************************************/
5 /* OpenType Glyph Loader (body). */
7 /* Copyright 1996-2001 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
33 /*************************************************************************/
35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
37 /* messages during execution. */
40 #define FT_COMPONENT trace_cffgload
43 typedef enum CFF_Operator_
77 cff_op_dotsection, /* deprecated, acts as no-op */
117 #define CFF_COUNT_CHECK_WIDTH 0x80
118 #define CFF_COUNT_EXACT 0x40
119 #define CFF_COUNT_CLEAR_STACK 0x20
122 static const FT_Byte cff_argument_counts[] =
126 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
127 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
128 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
130 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
131 0 | CFF_COUNT_CLEAR_STACK,
132 0 | CFF_COUNT_CLEAR_STACK,
134 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
135 0 | CFF_COUNT_CLEAR_STACK,
136 0 | CFF_COUNT_CLEAR_STACK,
137 0 | CFF_COUNT_CLEAR_STACK,
138 0 | CFF_COUNT_CLEAR_STACK,
139 0 | CFF_COUNT_CLEAR_STACK,
140 0 | CFF_COUNT_CLEAR_STACK,
147 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
149 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
150 2 | CFF_COUNT_CHECK_WIDTH,
151 2 | CFF_COUNT_CHECK_WIDTH,
152 2 | CFF_COUNT_CHECK_WIDTH,
192 /*************************************************************************/
193 /*************************************************************************/
194 /*************************************************************************/
195 /********** *********/
196 /********** *********/
197 /********** GENERIC CHARSTRING PARSING *********/
198 /********** *********/
199 /********** *********/
200 /*************************************************************************/
201 /*************************************************************************/
202 /*************************************************************************/
205 /*************************************************************************/
208 /* CFF_Init_Builder */
211 /* Initializes a given glyph builder. */
214 /* builder :: A pointer to the glyph builder to initialize. */
217 /* face :: The current face object. */
219 /* size :: The current size object. */
221 /* glyph :: The current glyph object. */
224 CFF_Init_Builder( CFF_Builder* builder,
227 CFF_GlyphSlot glyph )
229 builder->path_begun = 0;
230 builder->load_points = 1;
232 builder->face = face;
233 builder->glyph = glyph;
234 builder->memory = face->root.memory;
238 FT_GlyphLoader* loader = glyph->root.internal->loader;
241 builder->loader = loader;
242 builder->base = &loader->base.outline;
243 builder->current = &loader->current.outline;
244 FT_GlyphLoader_Rewind( loader );
249 builder->scale_x = size->metrics.x_scale;
250 builder->scale_y = size->metrics.y_scale;
256 builder->left_bearing.x = 0;
257 builder->left_bearing.y = 0;
258 builder->advance.x = 0;
259 builder->advance.y = 0;
263 /*************************************************************************/
266 /* CFF_Done_Builder */
269 /* Finalizes a given glyph builder. Its contents can still be used */
270 /* after the call, but the function saves important information */
271 /* within the corresponding glyph slot. */
274 /* builder :: A pointer to the glyph builder to finalize. */
277 CFF_Done_Builder( CFF_Builder* builder )
279 CFF_GlyphSlot glyph = builder->glyph;
283 glyph->root.outline = *builder->base;
287 /*************************************************************************/
290 /* cff_compute_bias */
293 /* Computes the bias value in dependence of the number of glyph */
297 /* num_subrs :: The number of glyph subroutines. */
300 /* The bias value. */
302 cff_compute_bias( FT_UInt num_subrs )
307 if ( num_subrs < 1240 )
309 else if ( num_subrs < 33900U )
318 /*************************************************************************/
321 /* CFF_Init_Decoder */
324 /* Initializes a given glyph decoder. */
327 /* decoder :: A pointer to the glyph builder to initialize. */
330 /* face :: The current face object. */
332 /* size :: The current size object. */
334 /* slot :: The current glyph object. */
337 CFF_Init_Decoder( CFF_Decoder* decoder,
342 CFF_Font* cff = (CFF_Font*)face->extra.data;
345 /* clear everything */
346 MEM_Set( decoder, 0, sizeof ( *decoder ) );
348 /* initialize builder */
349 CFF_Init_Builder( &decoder->builder, face, size, slot );
351 /* initialize Type2 decoder */
352 decoder->num_globals = cff->num_global_subrs;
353 decoder->globals = cff->global_subrs;
354 decoder->globals_bias = cff_compute_bias( decoder->num_globals );
358 /* this function is used to select the locals subrs array */
360 CFF_Prepare_Decoder( CFF_Decoder* decoder,
361 FT_UInt glyph_index )
363 CFF_Font* cff = (CFF_Font*)decoder->builder.face->extra.data;
364 CFF_SubFont* sub = &cff->top_font;
367 /* manage CID fonts */
368 if ( cff->num_subfonts >= 1 )
370 FT_Byte fd_index = CFF_Get_FD( &cff->fd_select, glyph_index );
373 sub = cff->subfonts[fd_index];
376 decoder->num_locals = sub->num_local_subrs;
377 decoder->locals = sub->local_subrs;
378 decoder->locals_bias = cff_compute_bias( decoder->num_locals );
380 decoder->glyph_width = sub->private_dict.default_width;
381 decoder->nominal_width = sub->private_dict.nominal_width;
385 /* check that there is enough room for `count' more points */
387 check_points( CFF_Builder* builder,
390 return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
394 /* add a new point, do not check space */
396 add_point( CFF_Builder* builder,
401 FT_Outline* outline = builder->current;
404 if ( builder->load_points )
406 FT_Vector* point = outline->points + outline->n_points;
407 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
412 *control = (FT_Byte)( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
414 builder->last = *point;
420 /* check space for a new on-curve point, then add it */
422 add_point1( CFF_Builder* builder,
429 error = check_points( builder, 1 );
431 add_point( builder, x, y, 1 );
437 /* check room for a new contour, then add it */
439 add_contour( CFF_Builder* builder )
441 FT_Outline* outline = builder->current;
445 if ( !builder->load_points )
447 outline->n_contours++;
451 error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
454 if ( outline->n_contours > 0 )
455 outline->contours[outline->n_contours - 1] =
456 (short)( outline->n_points - 1 );
458 outline->n_contours++;
465 /* if a path was begun, add its first on-curve point */
467 start_point( CFF_Builder* builder,
474 /* test whether we are building a new contour */
475 if ( !builder->path_begun )
477 builder->path_begun = 1;
478 error = add_contour( builder );
480 error = add_point1( builder, x, y );
486 /* close the current contour */
488 close_contour( CFF_Builder* builder )
490 FT_Outline* outline = builder->current;
492 /* XXXX: We must not include the last point in the path if it */
493 /* is located on the first point. */
494 if ( outline->n_points > 1 )
497 FT_Vector* p1 = outline->points + first;
498 FT_Vector* p2 = outline->points + outline->n_points - 1;
499 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
502 if ( outline->n_contours > 1 )
504 first = outline->contours[outline->n_contours - 2] + 1;
505 p1 = outline->points + first;
508 /* `delete' last point only if it coincides with the first */
509 /* point and it is not a control point (which can happen). */
510 if ( p1->x == p2->x && p1->y == p2->y )
511 if ( *control == FT_Curve_Tag_On )
515 if ( outline->n_contours > 0 )
516 outline->contours[outline->n_contours - 1] =
517 (short)( outline->n_points - 1 );
522 cff_lookup_glyph_by_stdcharcode( CFF_Font* cff,
529 /* check range of standard char code */
530 if ( charcode < 0 || charcode > 255 )
534 /* Get code to SID mapping from `cff_standard_encoding'. */
535 glyph_sid = cff_standard_encoding[charcode];
537 for ( n = 0; n < cff->num_glyphs; n++ )
539 if ( cff->charset.sids[n] == glyph_sid )
548 cff_operator_seac( CFF_Decoder* decoder,
555 FT_Int bchar_index, achar_index, n_base_points;
556 FT_Outline* base = decoder->builder.base;
557 TT_Face face = decoder->builder.face;
558 CFF_Font* cff = (CFF_Font*)(face->extra.data);
559 FT_Vector left_bearing, advance;
561 FT_ULong charstring_len;
564 bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
565 achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
567 if ( bchar_index < 0 || achar_index < 0 )
569 FT_ERROR(( "cff_operator_seac:" ));
570 FT_ERROR(( " invalid seac character code arguments\n" ));
571 return CFF_Err_Syntax_Error;
574 /* If we are trying to load a composite glyph, do not load the */
575 /* accent character and return the array of subglyphs. */
576 if ( decoder->builder.no_recurse )
578 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
579 FT_GlyphLoader* loader = glyph->internal->loader;
583 /* reallocate subglyph array if necessary */
584 error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
588 subg = loader->current.subglyphs;
590 /* subglyph 0 = base character */
591 subg->index = bchar_index;
592 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
593 FT_SUBGLYPH_FLAG_USE_MY_METRICS;
598 /* subglyph 1 = accent character */
599 subg->index = achar_index;
600 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
604 /* set up remaining glyph fields */
605 glyph->num_subglyphs = 2;
606 glyph->subglyphs = loader->base.subglyphs;
607 glyph->format = ft_glyph_format_composite;
609 loader->current.num_subglyphs = 2;
612 /* First load `bchar' in builder */
613 error = CFF_Access_Element( &cff->charstrings_index, bchar_index,
614 &charstring, &charstring_len );
617 error = CFF_Parse_CharStrings( decoder, charstring, charstring_len );
622 CFF_Forget_Element( &cff->charstrings_index, &charstring );
625 n_base_points = base->n_points;
627 /* Save the left bearing and width of the base character */
628 /* as they will be erased by the next load. */
630 left_bearing = decoder->builder.left_bearing;
631 advance = decoder->builder.advance;
633 decoder->builder.left_bearing.x = 0;
634 decoder->builder.left_bearing.y = 0;
636 /* Now load `achar' on top of the base outline. */
637 error = CFF_Access_Element( &cff->charstrings_index, achar_index,
638 &charstring, &charstring_len );
641 error = CFF_Parse_CharStrings( decoder, charstring, charstring_len );
646 CFF_Forget_Element( &cff->charstrings_index, &charstring );
649 /* Restore the left side bearing and advance width */
650 /* of the base character. */
651 decoder->builder.left_bearing = left_bearing;
652 decoder->builder.advance = advance;
654 /* Finally, move the accent. */
655 if ( decoder->builder.load_points )
660 dummy.n_points = (short)( base->n_points - n_base_points );
661 dummy.points = base->points + n_base_points;
663 FT_Outline_Translate( &dummy, adx, ady );
671 /*************************************************************************/
674 /* CFF_Parse_CharStrings */
677 /* Parses a given Type 2 charstrings program. */
680 /* decoder :: The current Type 1 decoder. */
683 /* charstring_base :: The base of the charstring stream. */
685 /* charstring_len :: The length in bytes of the charstring stream. */
688 /* FreeType error code. 0 means success. */
690 FT_LOCAL_DEF FT_Error
691 CFF_Parse_CharStrings( CFF_Decoder* decoder,
692 FT_Byte* charstring_base,
693 FT_Int charstring_len )
696 CFF_Decoder_Zone* zone;
699 CFF_Builder* builder = &decoder->builder;
705 /* set default width */
706 decoder->num_hints = 0;
707 decoder->read_width = 1;
709 /* compute random seed from stack address of parameter */
710 seed = (FT_Fixed)(char*)&seed ^
711 (FT_Fixed)(char*)&decoder ^
712 (FT_Fixed)(char*)&charstring_base;
713 seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFF;
717 /* initialize the decoder */
718 decoder->top = decoder->stack;
719 decoder->zone = decoder->zones;
720 zone = decoder->zones;
721 stack = decoder->top;
723 builder->path_begun = 0;
725 zone->base = charstring_base;
726 limit = zone->limit = charstring_base + charstring_len;
727 ip = zone->cursor = zone->base;
734 /* now, execute loop */
741 /********************************************************************/
743 /* Decode operator or operand */
746 if ( v >= 32 || v == 28 )
752 /* this is an operand, push it on the stack */
755 if ( ip + 1 >= limit )
757 val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
761 val = (FT_Long)v - 139;
766 val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
772 val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
776 if ( ip + 3 >= limit )
778 val = ( (FT_Int32)ip[0] << 24 ) |
779 ( (FT_Int32)ip[1] << 16 ) |
780 ( (FT_Int32)ip[2] << 8 ) |
785 if ( decoder->top - stack >= CFF_MAX_OPERANDS )
789 *decoder->top++ = val;
791 #ifdef FT_DEBUG_LEVEL_TRACE
792 if ( !( val & 0xFFFF ) )
793 FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) ));
795 FT_TRACE4(( " %.2f", val / 65536.0 ));
801 FT_Fixed* args = decoder->top;
802 FT_Int num_args = args - decoder->stack;
830 op = cff_op_rrcurveto;
833 op = cff_op_callsubr;
847 op = cff_op_dotsection;
928 /* decrement ip for syntax error message */
943 op = cff_op_hintmask;
946 op = cff_op_cntrmask;
958 op = cff_op_rcurveline;
961 op = cff_op_rlinecurve;
964 op = cff_op_vvcurveto;
967 op = cff_op_hhcurveto;
970 op = cff_op_callgsubr;
973 op = cff_op_vhcurveto;
976 op = cff_op_hvcurveto;
981 if ( op == cff_op_unknown )
984 /* check arguments */
985 req_args = cff_argument_counts[op];
986 if ( req_args & CFF_COUNT_CHECK_WIDTH )
990 if ( num_args > 0 && decoder->read_width )
992 /* If `nominal_width' is non-zero, the number is really a */
993 /* difference against `nominal_width'. Else, the number here */
994 /* is truly a width, not a difference against `nominal_width'. */
995 /* If the font does not set `nominal_width', then */
996 /* `nominal_width' defaults to zero, and so we can set */
997 /* `glyph_width' to `nominal_width' plus number on the stack */
998 /* -- for either case. */
1000 FT_Int set_width_ok;
1005 case cff_op_hmoveto:
1006 case cff_op_vmoveto:
1007 set_width_ok = num_args & 2;
1012 case cff_op_hstemhm:
1013 case cff_op_vstemhm:
1014 case cff_op_rmoveto:
1015 set_width_ok = num_args & 1;
1018 case cff_op_endchar:
1019 /* If there is a width specified for endchar, we either have */
1020 /* 1 argument or 5 arguments. We like to argue. */
1021 set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) );
1031 decoder->glyph_width = decoder->nominal_width +
1034 /* Consumed an argument. */
1040 decoder->read_width = 0;
1045 if ( num_args < req_args )
1046 goto Stack_Underflow;
1048 num_args -= req_args;
1054 case cff_op_hstemhm:
1055 case cff_op_vstemhm:
1056 /* if the number of arguments is not even, the first one */
1057 /* is simply the glyph width, encoded as the difference */
1058 /* to nominalWidthX */
1059 FT_TRACE4(( op == cff_op_hstem ? " hstem" :
1060 op == cff_op_vstem ? " vstem" :
1061 op == cff_op_hstemhm ? " hstemhm" :
1063 decoder->num_hints += num_args / 2;
1067 case cff_op_hintmask:
1068 case cff_op_cntrmask:
1069 FT_TRACE4(( op == cff_op_hintmask ? " hintmask"
1072 decoder->num_hints += num_args / 2;
1074 #ifdef FT_DEBUG_LEVEL_TRACE
1081 maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3);
1084 FT_TRACE4(( "%02X", *ip ));
1089 ip += ( decoder->num_hints + 7 ) >> 3;
1096 case cff_op_rmoveto:
1097 FT_TRACE4(( " rmoveto" ));
1099 close_contour( builder );
1100 builder->path_begun = 0;
1106 case cff_op_vmoveto:
1107 FT_TRACE4(( " vmoveto" ));
1109 close_contour( builder );
1110 builder->path_begun = 0;
1115 case cff_op_hmoveto:
1116 FT_TRACE4(( " hmoveto" ));
1118 close_contour( builder );
1119 builder->path_begun = 0;
1124 case cff_op_rlineto:
1125 FT_TRACE4(( " rlineto" ));
1127 if ( start_point ( builder, x, y ) ||
1128 check_points( builder, num_args / 2 ) )
1131 if ( num_args < 2 || num_args & 1 )
1132 goto Stack_Underflow;
1135 while ( args < decoder->top )
1139 add_point( builder, x, y, 1 );
1145 case cff_op_hlineto:
1146 case cff_op_vlineto:
1148 FT_Int phase = ( op == cff_op_hlineto );
1151 FT_TRACE4(( op == cff_op_hlineto ? " hlineto"
1154 if ( start_point ( builder, x, y ) ||
1155 check_points( builder, num_args ) )
1159 while (args < decoder->top )
1166 if ( add_point1( builder, x, y ) )
1176 case cff_op_rrcurveto:
1177 FT_TRACE4(( " rrcurveto" ));
1179 /* check number of arguments; must be a multiple of 6 */
1180 if ( num_args % 6 != 0 )
1181 goto Stack_Underflow;
1183 if ( start_point ( builder, x, y ) ||
1184 check_points( builder, num_args / 2 ) )
1188 while ( args < decoder->top )
1192 add_point( builder, x, y, 0 );
1195 add_point( builder, x, y, 0 );
1198 add_point( builder, x, y, 1 );
1204 case cff_op_vvcurveto:
1205 FT_TRACE4(( " vvcurveto" ));
1207 if ( start_point ( builder, x, y ) )
1218 if ( num_args % 4 != 0 )
1219 goto Stack_Underflow;
1221 if ( check_points( builder, 3 * ( num_args / 4 ) ) )
1224 while ( args < decoder->top )
1227 add_point( builder, x, y, 0 );
1230 add_point( builder, x, y, 0 );
1232 add_point( builder, x, y, 1 );
1238 case cff_op_hhcurveto:
1239 FT_TRACE4(( " hhcurveto" ));
1241 if ( start_point ( builder, x, y ) )
1252 if ( num_args % 4 != 0 )
1253 goto Stack_Underflow;
1255 if ( check_points( builder, 3 * ( num_args / 4 ) ) )
1258 while ( args < decoder->top )
1261 add_point( builder, x, y, 0 );
1264 add_point( builder, x, y, 0 );
1266 add_point( builder, x, y, 1 );
1272 case cff_op_vhcurveto:
1273 case cff_op_hvcurveto:
1278 FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto"
1281 if ( start_point ( builder, x, y ) )
1285 if (num_args < 4 || ( num_args % 4 ) > 1 )
1286 goto Stack_Underflow;
1288 if ( check_points( builder, ( num_args / 4 ) * 3 ) )
1289 goto Stack_Underflow;
1291 phase = ( op == cff_op_hvcurveto );
1293 while ( num_args >= 4 )
1299 add_point( builder, x, y, 0 );
1302 add_point( builder, x, y, 0 );
1304 if ( num_args == 1 )
1306 add_point( builder, x, y, 1 );
1311 add_point( builder, x, y, 0 );
1314 add_point( builder, x, y, 0 );
1316 if ( num_args == 1 )
1318 add_point( builder, x, y, 1 );
1327 case cff_op_rlinecurve:
1329 FT_Int num_lines = ( num_args - 6 ) / 2;
1332 FT_TRACE4(( " rlinecurve" ));
1334 if ( num_args < 8 || ( num_args - 6 ) & 1 )
1335 goto Stack_Underflow;
1337 if ( start_point( builder, x, y ) ||
1338 check_points( builder, num_lines + 3 ) )
1343 /* first, add the line segments */
1344 while ( num_lines > 0 )
1348 add_point( builder, x, y, 1 );
1353 /* then the curve */
1356 add_point( builder, x, y, 0 );
1359 add_point( builder, x, y, 0 );
1362 add_point( builder, x, y, 1 );
1367 case cff_op_rcurveline:
1369 FT_Int num_curves = ( num_args - 2 ) / 6;
1372 FT_TRACE4(( " rcurveline" ));
1374 if ( num_args < 8 || ( num_args - 2 ) % 6 )
1375 goto Stack_Underflow;
1377 if ( start_point ( builder, x, y ) ||
1378 check_points( builder, num_curves*3 + 2 ) )
1383 /* first, add the curves */
1384 while ( num_curves > 0 )
1388 add_point( builder, x, y, 0 );
1391 add_point( builder, x, y, 0 );
1394 add_point( builder, x, y, 1 );
1399 /* then the final line */
1402 add_point( builder, x, y, 1 );
1412 FT_TRACE4(( " hflex1" ));
1416 /* adding five more points; 4 control points, 1 on-curve point */
1417 /* make sure we have enough space for the start point if it */
1418 /* needs to be added.. */
1419 if ( start_point( builder, x, y ) ||
1420 check_points( builder, 6 ) )
1423 /* Record the starting point's y postion for later use */
1426 /* first control point */
1429 add_point( builder, x, y, 0 );
1431 /* second control point */
1434 add_point( builder, x, y, 0 );
1436 /* join point; on curve, with y-value the same as the last */
1437 /* control point's y-value */
1439 add_point( builder, x, y, 1 );
1441 /* third control point, with y-value the same as the join */
1442 /* point's y-value */
1444 add_point( builder, x, y, 0 );
1446 /* fourth control point */
1449 add_point( builder, x, y, 0 );
1451 /* ending point, with y-value the same as the start */
1454 add_point( builder, x, y, 1 );
1465 FT_TRACE4(( " hflex" ));
1469 /* adding six more points; 4 control points, 2 on-curve points */
1470 if ( start_point( builder, x, y ) ||
1471 check_points ( builder, 6 ) )
1474 /* record the starting point's y-position for later use */
1477 /* first control point */
1479 add_point( builder, x, y, 0 );
1481 /* second control point */
1484 add_point( builder, x, y, 0 );
1486 /* join point; on curve, with y-value the same as the last */
1487 /* control point's y-value */
1489 add_point( builder, x, y, 1 );
1491 /* third control point, with y-value the same as the join */
1492 /* point's y-value */
1494 add_point( builder, x, y, 0 );
1496 /* fourth control point */
1499 add_point( builder, x, y, 0 );
1501 /* ending point, with y-value the same as the start point's */
1502 /* y-value -- we don't add this point, though */
1504 add_point( builder, x, y, 1 );
1512 FT_Pos start_x, start_y; /* record start x, y values for alter */
1514 FT_Int dx = 0, dy = 0; /* used in horizontal/vertical */
1515 /* algorithm below */
1516 FT_Int horizontal, count;
1519 FT_TRACE4(( " flex1" ));
1521 /* adding six more points; 4 control points, 2 on-curve points */
1522 if ( start_point( builder, x, y ) ||
1523 check_points( builder, 6 ) )
1526 /* record the starting point's x, y postion for later use */
1530 /* XXX: figure out whether this is supposed to be a horizontal */
1531 /* or vertical flex; the Type 2 specification is vague... */
1535 /* grab up to the last argument */
1536 for ( count = 5; count > 0; count-- )
1546 if ( dx < 0 ) dx = -dx;
1547 if ( dy < 0 ) dy = -dy;
1549 /* strange test, but here it is... */
1550 horizontal = ( dx > dy );
1552 for ( count = 5; count > 0; count-- )
1556 add_point( builder, x, y, (FT_Bool)( count == 3 ) );
1560 /* is last operand an x- or y-delta? */
1572 add_point( builder, x, y, 1 );
1583 FT_TRACE4(( " flex" ));
1585 if ( start_point( builder, x, y ) ||
1586 check_points( builder, 6 ) )
1590 for ( count = 6; count > 0; count-- )
1594 add_point( builder, x, y,
1595 (FT_Bool)( count == 3 || count == 0 ) );
1603 case cff_op_endchar:
1604 FT_TRACE4(( " endchar" ));
1606 /* We are going to emulate the seac operator. */
1607 if ( num_args == 4 )
1609 error = cff_operator_seac( decoder,
1610 args[0] >> 16, args[1] >> 16,
1611 args[2] >> 16, args[3] >> 16 );
1618 close_contour( builder );
1620 /* add current outline to the glyph slot */
1621 FT_GlyphLoader_Add( builder->loader );
1624 FT_TRACE4(( "\n\n" ));
1628 FT_TRACE4(( " abs" ));
1636 FT_TRACE4(( " add" ));
1643 FT_TRACE4(( " sub" ));
1650 FT_TRACE4(( " div" ));
1652 args[0] = FT_DivFix( args[0], args[1] );
1657 FT_TRACE4(( " neg" ));
1668 FT_TRACE4(( " rand" ));
1671 if ( rand >= 0x8000 )
1675 seed = FT_MulFix( seed, 0x10000L - seed );
1683 FT_TRACE4(( " mul" ));
1685 args[0] = FT_MulFix( args[0], args[1] );
1690 FT_TRACE4(( " sqrt" ));
1695 FT_Fixed root = args[0];
1701 new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
1702 if ( new_root == root || count <= 0 )
1715 FT_TRACE4(( " drop" ));
1724 FT_TRACE4(( " exch" ));
1735 FT_Int index = args[0] >> 16;
1738 FT_TRACE4(( " index" ));
1742 else if ( index > num_args - 2 )
1743 index = num_args - 2;
1744 args[0] = args[-( index + 1 )];
1751 FT_Int count = (FT_Int)( args[0] >> 16 );
1752 FT_Int index = (FT_Int)( args[1] >> 16 );
1755 FT_TRACE4(( " roll" ));
1762 goto Stack_Underflow;
1768 FT_Fixed tmp = args[count - 1];
1772 for ( i = count - 2; i >= 0; i-- )
1773 args[i + 1] = args[i];
1782 FT_Fixed tmp = args[0];
1786 for ( i = 0; i < count - 1; i++ )
1787 args[i] = args[i + 1];
1788 args[count - 1] = tmp;
1797 FT_TRACE4(( " dup" ));
1805 FT_Fixed val = args[0];
1806 FT_Int index = (FT_Int)( args[1] >> 16 );
1809 FT_TRACE4(( " put" ));
1811 if ( index >= 0 && index < decoder->len_buildchar )
1812 decoder->buildchar[index] = val;
1818 FT_Int index = (FT_Int)( args[0] >> 16 );
1822 FT_TRACE4(( " get" ));
1824 if ( index >= 0 && index < decoder->len_buildchar )
1825 val = decoder->buildchar[index];
1833 FT_TRACE4(( " store "));
1838 FT_TRACE4(( " load" ));
1842 case cff_op_dotsection:
1843 /* this operator is deprecated and ignored by the parser */
1844 FT_TRACE4(( " dotsection" ));
1849 FT_Fixed cond = args[0] && args[1];
1852 FT_TRACE4(( " and" ));
1854 args[0] = cond ? 0x10000L : 0;
1861 FT_Fixed cond = args[0] || args[1];
1864 FT_TRACE4(( " or" ));
1866 args[0] = cond ? 0x10000L : 0;
1873 FT_Fixed cond = !args[0];
1876 FT_TRACE4(( " eq" ));
1878 args[0] = cond ? 0x10000L : 0;
1885 FT_Fixed cond = (args[2] <= args[3]);
1888 FT_TRACE4(( " ifelse" ));
1896 case cff_op_callsubr:
1898 FT_UInt index = (FT_UInt)( ( args[0] >> 16 ) +
1899 decoder->locals_bias );
1902 FT_TRACE4(( " callsubr(%d)", index ));
1904 if ( index >= decoder->num_locals )
1906 FT_ERROR(( "CFF_Parse_CharStrings:" ));
1907 FT_ERROR(( " invalid local subr index\n" ));
1911 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
1913 FT_ERROR(( "CFF_Parse_CharStrings: too many nested subrs\n" ));
1917 zone->cursor = ip; /* save current instruction pointer */
1920 zone->base = decoder->locals[index];
1921 zone->limit = decoder->locals[index + 1];
1922 zone->cursor = zone->base;
1926 FT_ERROR(( "CFF_Parse_CharStrings: invoking empty subrs!\n" ));
1930 decoder->zone = zone;
1932 limit = zone->limit;
1936 case cff_op_callgsubr:
1938 FT_UInt index = (FT_UInt)( ( args[0] >> 16 ) +
1939 decoder->globals_bias );
1942 FT_TRACE4(( " callgsubr(%d)", index ));
1944 if ( index >= decoder->num_globals )
1946 FT_ERROR(( "CFF_Parse_CharStrings:" ));
1947 FT_ERROR(( " invalid global subr index\n" ));
1951 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
1953 FT_ERROR(( "CFF_Parse_CharStrings: too many nested subrs\n" ));
1957 zone->cursor = ip; /* save current instruction pointer */
1960 zone->base = decoder->globals[index];
1961 zone->limit = decoder->globals[index+1];
1962 zone->cursor = zone->base;
1966 FT_ERROR(( "CFF_Parse_CharStrings: invoking empty subrs!\n" ));
1970 decoder->zone = zone;
1972 limit = zone->limit;
1977 FT_TRACE4(( " return" ));
1979 if ( decoder->zone <= decoder->zones )
1981 FT_ERROR(( "CFF_Parse_CharStrings: unexpected return\n" ));
1986 zone = decoder->zone;
1988 limit = zone->limit;
1993 FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
1996 FT_ERROR(( " %d", ip[0] ));
1999 return CFF_Err_Unimplemented_Feature;
2002 decoder->top = args;
2004 } /* general operator processing */
2006 } /* while ip < limit */
2008 FT_TRACE4(( "..end..\n\n" ));
2013 FT_TRACE4(( "CFF_Parse_CharStrings: syntax error!" ));
2014 return CFF_Err_Invalid_File_Format;
2017 FT_TRACE4(( "CFF_Parse_CharStrings: stack underflow!" ));
2018 return CFF_Err_Too_Few_Arguments;
2021 FT_TRACE4(( "CFF_Parse_CharStrings: stack overflow!" ));
2022 return CFF_Err_Stack_Overflow;
2025 return builder->error;
2029 /*************************************************************************/
2030 /*************************************************************************/
2031 /*************************************************************************/
2032 /********** *********/
2033 /********** *********/
2034 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
2035 /********** *********/
2036 /********** The following code is in charge of computing *********/
2037 /********** the maximum advance width of the font. It *********/
2038 /********** quickly processes each glyph charstring to *********/
2039 /********** extract the value from either a `sbw' or `seac' *********/
2040 /********** operator. *********/
2041 /********** *********/
2042 /*************************************************************************/
2043 /*************************************************************************/
2044 /*************************************************************************/
2047 #if 0 /* unused until we support pure CFF fonts */
2050 FT_LOCAL_DEF FT_Error
2051 CFF_Compute_Max_Advance( TT_Face face,
2052 FT_Int* max_advance )
2055 CFF_Decoder decoder;
2057 CFF_Font* cff = (CFF_Font*)face->other;
2062 /* Initialize load decoder */
2063 CFF_Init_Decoder( &decoder, face, 0, 0 );
2065 decoder.builder.metrics_only = 1;
2066 decoder.builder.load_points = 0;
2068 /* For each glyph, parse the glyph charstring and extract */
2069 /* the advance width. */
2070 for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
2073 FT_Byte* charstring;
2074 FT_ULong charstring_len;
2077 /* now get load the unscaled outline */
2078 error = CFF_Access_Element( &cff->charstrings_index, glyph_index,
2079 &charstring, &charstring_len );
2082 CFF_Prepare_Decoder( &decoder, glyph_index );
2083 error = CFF_Parse_CharStrings( &decoder, charstring, charstring_len );
2085 CFF_Forget_Element( &cff->charstrings_index, &charstring );
2088 /* ignore the error if one has occurred -- skip to next glyph */
2092 *max_advance = decoder.builder.advance.x;
2101 /*************************************************************************/
2102 /*************************************************************************/
2103 /*************************************************************************/
2104 /********** *********/
2105 /********** *********/
2106 /********** UNHINTED GLYPH LOADER *********/
2107 /********** *********/
2108 /********** The following code is in charge of loading a *********/
2109 /********** single outline. It completely ignores hinting *********/
2110 /********** and is used when FT_LOAD_NO_HINTING is set. *********/
2111 /********** *********/
2112 /*************************************************************************/
2113 /*************************************************************************/
2114 /*************************************************************************/
2117 FT_LOCAL_DEF FT_Error
2118 CFF_Load_Glyph( CFF_GlyphSlot glyph,
2124 CFF_Decoder decoder;
2125 TT_Face face = (TT_Face)glyph->root.face;
2127 CFF_Font* cff = (CFF_Font*)face->extra.data;
2129 FT_Matrix font_matrix;
2130 FT_Vector font_offset;
2133 if ( load_flags & FT_LOAD_NO_RECURSE )
2134 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
2136 glyph->x_scale = 0x10000L;
2137 glyph->y_scale = 0x10000L;
2140 glyph->x_scale = size->metrics.x_scale;
2141 glyph->y_scale = size->metrics.y_scale;
2144 glyph->root.outline.n_points = 0;
2145 glyph->root.outline.n_contours = 0;
2147 hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
2148 ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
2150 glyph->root.format = ft_glyph_format_outline; /* by default */
2153 FT_Byte* charstring;
2154 FT_ULong charstring_len;
2157 CFF_Init_Decoder( &decoder, face, size, glyph );
2159 decoder.builder.no_recurse =
2160 (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
2162 /* now load the unscaled outline */
2163 error = CFF_Access_Element( &cff->charstrings_index, glyph_index,
2164 &charstring, &charstring_len );
2167 CFF_Index csindex = cff->charstrings_index;
2170 CFF_Prepare_Decoder( &decoder, glyph_index );
2171 error = CFF_Parse_CharStrings( &decoder, charstring, charstring_len );
2173 CFF_Forget_Element( &cff->charstrings_index, &charstring );
2175 /* We set control_data and control_len if charstrings is loaded. */
2176 /* See how charstring loads at CFF_Access_Element() in cffload.c. */
2178 glyph->root.control_data =
2179 csindex.bytes + csindex.offsets[glyph_index] - 1;
2180 glyph->root.control_len =
2184 /* save new glyph tables */
2185 CFF_Done_Builder( &decoder.builder );
2188 font_matrix = cff->top_font.font_dict.font_matrix;
2189 font_offset = cff->top_font.font_dict.font_offset;
2191 /* Now, set the metrics -- this is rather simple, as */
2192 /* the left side bearing is the xMin, and the top side */
2193 /* bearing the yMax. */
2196 /* For composite glyphs, return only left side bearing and */
2197 /* advance width. */
2198 if ( load_flags & FT_LOAD_NO_RECURSE )
2200 FT_Slot_Internal internal = glyph->root.internal;
2203 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
2204 glyph->root.metrics.horiAdvance = decoder.glyph_width;
2205 internal->glyph_matrix = font_matrix;
2206 internal->glyph_delta = font_offset;
2207 internal->glyph_transformed = 1;
2212 FT_Glyph_Metrics* metrics = &glyph->root.metrics;
2215 /* copy the _unscaled_ advance width */
2216 metrics->horiAdvance = decoder.glyph_width;
2217 glyph->root.linearHoriAdvance = decoder.glyph_width;
2218 glyph->root.internal->glyph_transformed = 0;
2220 /* make up vertical metrics */
2221 metrics->vertBearingX = 0;
2222 metrics->vertBearingY = 0;
2223 metrics->vertAdvance = 0;
2225 glyph->root.linearVertAdvance = 0;
2227 glyph->root.format = ft_glyph_format_outline;
2229 glyph->root.outline.flags = 0;
2230 if ( size && size->metrics.y_ppem < 24 )
2231 glyph->root.outline.flags |= ft_outline_high_precision;
2233 glyph->root.outline.flags |= ft_outline_reverse_fill;
2235 /* apply the font matrix */
2236 FT_Outline_Transform( &glyph->root.outline, &font_matrix );
2238 FT_Outline_Translate( &glyph->root.outline,
2242 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
2244 /* scale the outline and the metrics */
2246 FT_Outline* cur = &glyph->root.outline;
2247 FT_Vector* vec = cur->points;
2248 FT_Fixed x_scale = glyph->x_scale;
2249 FT_Fixed y_scale = glyph->y_scale;
2252 /* First of all, scale the points */
2253 for ( n = cur->n_points; n > 0; n--, vec++ )
2255 vec->x = FT_MulFix( vec->x, x_scale );
2256 vec->y = FT_MulFix( vec->y, y_scale );
2259 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
2261 /* Then scale the metrics */
2262 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
2263 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
2265 metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
2266 metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
2269 /* compute the other metrics */
2270 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
2272 /* grid fit the bounding box if necessary */
2277 cbox.xMax = ( cbox.xMax + 63 ) & -64;
2278 cbox.yMax = ( cbox.yMax + 63 ) & -64;
2281 metrics->width = cbox.xMax - cbox.xMin;
2282 metrics->height = cbox.yMax - cbox.yMin;
2284 metrics->horiBearingX = cbox.xMin;
2285 metrics->horiBearingY = cbox.yMax;