1 /***************************************************************************/
2 /* */
3 /* cffgload.c */
4 /* */
5 /* OpenType Glyph Loader (body). */
6 /* */
7 /* Copyright 1996-2001 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
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. */
15 /* */
16 /***************************************************************************/
19 #include <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_CALC_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_INTERNAL_SFNT_H
24 #include FT_OUTLINE_H
25 #include FT_TRUETYPE_TAGS_H
27 #include "cffload.h"
28 #include "cffgload.h"
30 #include "cfferrs.h"
33 /*************************************************************************/
34 /* */
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. */
38 /* */
39 #undef FT_COMPONENT
40 #define FT_COMPONENT trace_cffgload
43 typedef enum CFF_Operator_
44 {
45 cff_op_unknown = 0,
47 cff_op_rmoveto,
48 cff_op_hmoveto,
49 cff_op_vmoveto,
51 cff_op_rlineto,
52 cff_op_hlineto,
53 cff_op_vlineto,
55 cff_op_rrcurveto,
56 cff_op_hhcurveto,
57 cff_op_hvcurveto,
58 cff_op_rcurveline,
59 cff_op_rlinecurve,
60 cff_op_vhcurveto,
61 cff_op_vvcurveto,
63 cff_op_flex,
64 cff_op_hflex,
65 cff_op_hflex1,
66 cff_op_flex1,
68 cff_op_endchar,
70 cff_op_hstem,
71 cff_op_vstem,
72 cff_op_hstemhm,
73 cff_op_vstemhm,
75 cff_op_hintmask,
76 cff_op_cntrmask,
77 cff_op_dotsection, /* deprecated, acts as no-op */
79 cff_op_abs,
80 cff_op_add,
81 cff_op_sub,
82 cff_op_div,
83 cff_op_neg,
84 cff_op_random,
85 cff_op_mul,
86 cff_op_sqrt,
88 cff_op_blend,
90 cff_op_drop,
91 cff_op_exch,
92 cff_op_index,
93 cff_op_roll,
94 cff_op_dup,
96 cff_op_put,
97 cff_op_get,
98 cff_op_store,
99 cff_op_load,
101 cff_op_and,
102 cff_op_or,
103 cff_op_not,
104 cff_op_eq,
105 cff_op_ifelse,
107 cff_op_callsubr,
108 cff_op_callgsubr,
109 cff_op_return,
111 /* do not remove */
112 cff_op_max
114 } CFF_Operator;
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[] =
123 {
124 0, /* unknown */
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,
142 13, /* flex */
143 7,
144 9,
145 11,
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,
154 0, /* hintmask */
155 0, /* cntrmask */
156 0, /* dotsection */
158 1, /* abs */
159 2,
160 2,
161 2,
162 1,
163 0,
164 2,
165 1,
167 1, /* blend */
169 1, /* drop */
170 2,
171 1,
172 2,
173 1,
175 2, /* put */
176 1,
177 4,
178 3,
180 2, /* and */
181 2,
182 1,
183 2,
184 4,
186 1, /* callsubr */
187 1,
188 0
189 };
192 /*************************************************************************/
193 /*************************************************************************/
194 /*************************************************************************/
195 /********** *********/
196 /********** *********/
197 /********** GENERIC CHARSTRING PARSING *********/
198 /********** *********/
199 /********** *********/
200 /*************************************************************************/
201 /*************************************************************************/
202 /*************************************************************************/
205 /*************************************************************************/
206 /* */
207 /* <Function> */
208 /* CFF_Init_Builder */
209 /* */
210 /* <Description> */
211 /* Initializes a given glyph builder. */
212 /* */
213 /* <InOut> */
214 /* builder :: A pointer to the glyph builder to initialize. */
215 /* */
216 /* <Input> */
217 /* face :: The current face object. */
218 /* */
219 /* size :: The current size object. */
220 /* */
221 /* glyph :: The current glyph object. */
222 /* */
223 static void
224 CFF_Init_Builder( CFF_Builder* builder,
225 TT_Face face,
226 CFF_Size size,
227 CFF_GlyphSlot glyph )
228 {
229 builder->path_begun = 0;
230 builder->load_points = 1;
232 builder->face = face;
233 builder->glyph = glyph;
234 builder->memory = face->root.memory;
236 if ( glyph )
237 {
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 );
245 }
247 if ( size )
248 {
249 builder->scale_x = size->metrics.x_scale;
250 builder->scale_y = size->metrics.y_scale;
251 }
253 builder->pos_x = 0;
254 builder->pos_y = 0;
256 builder->left_bearing.x = 0;
257 builder->left_bearing.y = 0;
258 builder->advance.x = 0;
259 builder->advance.y = 0;
260 }
263 /*************************************************************************/
264 /* */
265 /* <Function> */
266 /* CFF_Done_Builder */
267 /* */
268 /* <Description> */
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. */
272 /* */
273 /* <Input> */
274 /* builder :: A pointer to the glyph builder to finalize. */
275 /* */
276 static void
277 CFF_Done_Builder( CFF_Builder* builder )
278 {
279 CFF_GlyphSlot glyph = builder->glyph;
282 if ( glyph )
283 glyph->root.outline = *builder->base;
284 }
287 /*************************************************************************/
288 /* */
289 /* <Function> */
290 /* cff_compute_bias */
291 /* */
292 /* <Description> */
293 /* Computes the bias value in dependence of the number of glyph */
294 /* subroutines. */
295 /* */
296 /* <Input> */
297 /* num_subrs :: The number of glyph subroutines. */
298 /* */
299 /* <Return> */
300 /* The bias value. */
301 static FT_Int
302 cff_compute_bias( FT_UInt num_subrs )
303 {
304 FT_Int result;
307 if ( num_subrs < 1240 )
308 result = 107;
309 else if ( num_subrs < 33900U )
310 result = 1131;
311 else
312 result = 32768U;
314 return result;
315 }
318 /*************************************************************************/
319 /* */
320 /* <Function> */
321 /* CFF_Init_Decoder */
322 /* */
323 /* <Description> */
324 /* Initializes a given glyph decoder. */
325 /* */
326 /* <InOut> */
327 /* decoder :: A pointer to the glyph builder to initialize. */
328 /* */
329 /* <Input> */
330 /* face :: The current face object. */
331 /* */
332 /* size :: The current size object. */
333 /* */
334 /* slot :: The current glyph object. */
335 /* */
336 FT_LOCAL_DEF void
337 CFF_Init_Decoder( CFF_Decoder* decoder,
338 TT_Face face,
339 CFF_Size size,
340 CFF_GlyphSlot slot )
341 {
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 );
355 }
358 /* this function is used to select the locals subrs array */
359 FT_LOCAL_DEF void
360 CFF_Prepare_Decoder( CFF_Decoder* decoder,
361 FT_UInt glyph_index )
362 {
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 )
369 {
370 FT_Byte fd_index = CFF_Get_FD( &cff->fd_select, glyph_index );
373 sub = cff->subfonts[fd_index];
374 }
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;
382 }
385 /* check that there is enough room for `count' more points */
386 static FT_Error
387 check_points( CFF_Builder* builder,
388 FT_Int count )
389 {
390 return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
391 }
394 /* add a new point, do not check space */
395 static void
396 add_point( CFF_Builder* builder,
397 FT_Pos x,
398 FT_Pos y,
399 FT_Byte flag )
400 {
401 FT_Outline* outline = builder->current;
404 if ( builder->load_points )
405 {
406 FT_Vector* point = outline->points + outline->n_points;
407 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
410 point->x = x >> 16;
411 point->y = y >> 16;
412 *control = (FT_Byte)( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
414 builder->last = *point;
415 }
416 outline->n_points++;
417 }
420 /* check space for a new on-curve point, then add it */
421 static FT_Error
422 add_point1( CFF_Builder* builder,
423 FT_Pos x,
424 FT_Pos y )
425 {
426 FT_Error error;
429 error = check_points( builder, 1 );
430 if ( !error )
431 add_point( builder, x, y, 1 );
433 return error;
434 }
437 /* check room for a new contour, then add it */
438 static FT_Error
439 add_contour( CFF_Builder* builder )
440 {
441 FT_Outline* outline = builder->current;
442 FT_Error error;
445 if ( !builder->load_points )
446 {
447 outline->n_contours++;
448 return CFF_Err_Ok;
449 }
451 error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
452 if ( !error )
453 {
454 if ( outline->n_contours > 0 )
455 outline->contours[outline->n_contours - 1] =
456 (short)( outline->n_points - 1 );
458 outline->n_contours++;
459 }
461 return error;
462 }
465 /* if a path was begun, add its first on-curve point */
466 static FT_Error
467 start_point( CFF_Builder* builder,
468 FT_Pos x,
469 FT_Pos y )
470 {
471 FT_Error error = 0;
474 /* test whether we are building a new contour */
475 if ( !builder->path_begun )
476 {
477 builder->path_begun = 1;
478 error = add_contour( builder );
479 if ( !error )
480 error = add_point1( builder, x, y );
481 }
482 return error;
483 }
486 /* close the current contour */
487 static void
488 close_contour( CFF_Builder* builder )
489 {
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 )
495 {
496 FT_Int first = 0;
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 )
503 {
504 first = outline->contours[outline->n_contours - 2] + 1;
505 p1 = outline->points + first;
506 }
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 )
512 outline->n_points--;
513 }
515 if ( outline->n_contours > 0 )
516 outline->contours[outline->n_contours - 1] =
517 (short)( outline->n_points - 1 );
518 }
521 static FT_Int
522 cff_lookup_glyph_by_stdcharcode( CFF_Font* cff,
523 FT_Int charcode )
524 {
525 FT_UInt n;
526 FT_UShort glyph_sid;
529 /* check range of standard char code */
530 if ( charcode < 0 || charcode > 255 )
531 return -1;
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++ )
538 {
539 if ( cff->charset.sids[n] == glyph_sid )
540 return n;
541 }
543 return -1;
544 }
547 static FT_Error
548 cff_operator_seac( CFF_Decoder* decoder,
549 FT_Pos adx,
550 FT_Pos ady,
551 FT_Int bchar,
552 FT_Int achar )
553 {
554 FT_Error error;
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;
560 FT_Byte* charstring;
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 )
568 {
569 FT_ERROR(( "cff_operator_seac:" ));
570 FT_ERROR(( " invalid seac character code arguments\n" ));
571 return CFF_Err_Syntax_Error;
572 }
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 )
577 {
578 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
579 FT_GlyphLoader* loader = glyph->internal->loader;
580 FT_SubGlyph* subg;
583 /* reallocate subglyph array if necessary */
584 error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
585 if ( error )
586 goto Exit;
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;
594 subg->arg1 = 0;
595 subg->arg2 = 0;
596 subg++;
598 /* subglyph 1 = accent character */
599 subg->index = achar_index;
600 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
601 subg->arg1 = adx;
602 subg->arg2 = ady;
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;
610 }
612 /* First load `bchar' in builder */
613 error = CFF_Access_Element( &cff->charstrings_index, bchar_index,
614 &charstring, &charstring_len );
615 if ( !error )
616 {
617 error = CFF_Parse_CharStrings( decoder, charstring, charstring_len );
619 if ( error )
620 goto Exit;
622 CFF_Forget_Element( &cff->charstrings_index, &charstring );
623 }
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 );
639 if ( !error )
640 {
641 error = CFF_Parse_CharStrings( decoder, charstring, charstring_len );
643 if ( error )
644 goto Exit;
646 CFF_Forget_Element( &cff->charstrings_index, &charstring );
647 }
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 )
656 {
657 FT_Outline dummy;
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 );
664 }
666 Exit:
667 return error;
668 }
671 /*************************************************************************/
672 /* */
673 /* <Function> */
674 /* CFF_Parse_CharStrings */
675 /* */
676 /* <Description> */
677 /* Parses a given Type 2 charstrings program. */
678 /* */
679 /* <InOut> */
680 /* decoder :: The current Type 1 decoder. */
681 /* */
682 /* <Input> */
683 /* charstring_base :: The base of the charstring stream. */
684 /* */
685 /* charstring_len :: The length in bytes of the charstring stream. */
686 /* */
687 /* <Return> */
688 /* FreeType error code. 0 means success. */
689 /* */
690 FT_LOCAL_DEF FT_Error
691 CFF_Parse_CharStrings( CFF_Decoder* decoder,
692 FT_Byte* charstring_base,
693 FT_Int charstring_len )
694 {
695 FT_Error error;
696 CFF_Decoder_Zone* zone;
697 FT_Byte* ip;
698 FT_Byte* limit;
699 CFF_Builder* builder = &decoder->builder;
700 FT_Pos x, y;
701 FT_Fixed seed;
702 FT_Fixed* stack;
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;
714 if ( seed == 0 )
715 seed = 0x7384;
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;
729 error = CFF_Err_Ok;
731 x = builder->pos_x;
732 y = builder->pos_y;
734 /* now, execute loop */
735 while ( ip < limit )
736 {
737 CFF_Operator op;
738 FT_Byte v;
741 /********************************************************************/
742 /* */
743 /* Decode operator or operand */
744 /* */
745 v = *ip++;
746 if ( v >= 32 || v == 28 )
747 {
748 FT_Int shift = 16;
749 FT_Int32 val;
752 /* this is an operand, push it on the stack */
753 if ( v == 28 )
754 {
755 if ( ip + 1 >= limit )
756 goto Syntax_Error;
757 val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
758 ip += 2;
759 }
760 else if ( v < 247 )
761 val = (FT_Long)v - 139;
762 else if ( v < 251 )
763 {
764 if ( ip >= limit )
765 goto Syntax_Error;
766 val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
767 }
768 else if ( v < 255 )
769 {
770 if ( ip >= limit )
771 goto Syntax_Error;
772 val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
773 }
774 else
775 {
776 if ( ip + 3 >= limit )
777 goto Syntax_Error;
778 val = ( (FT_Int32)ip[0] << 24 ) |
779 ( (FT_Int32)ip[1] << 16 ) |
780 ( (FT_Int32)ip[2] << 8 ) |
781 ip[3];
782 ip += 4;
783 shift = 0;
784 }
785 if ( decoder->top - stack >= CFF_MAX_OPERANDS )
786 goto Stack_Overflow;
788 val <<= shift;
789 *decoder->top++ = val;
791 #ifdef FT_DEBUG_LEVEL_TRACE
792 if ( !( val & 0xFFFF ) )
793 FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) ));
794 else
795 FT_TRACE4(( " %.2f", val / 65536.0 ));
796 #endif
798 }
799 else
800 {
801 FT_Fixed* args = decoder->top;
802 FT_Int num_args = args - decoder->stack;
803 FT_Int req_args;
806 /* find operator */
807 op = cff_op_unknown;
809 switch ( v )
810 {
811 case 1:
812 op = cff_op_hstem;
813 break;
814 case 3:
815 op = cff_op_vstem;
816 break;
817 case 4:
818 op = cff_op_vmoveto;
819 break;
820 case 5:
821 op = cff_op_rlineto;
822 break;
823 case 6:
824 op = cff_op_hlineto;
825 break;
826 case 7:
827 op = cff_op_vlineto;
828 break;
829 case 8:
830 op = cff_op_rrcurveto;
831 break;
832 case 10:
833 op = cff_op_callsubr;
834 break;
835 case 11:
836 op = cff_op_return;
837 break;
838 case 12:
839 {
840 if ( ip >= limit )
841 goto Syntax_Error;
842 v = *ip++;
844 switch ( v )
845 {
846 case 0:
847 op = cff_op_dotsection;
848 break;
849 case 3:
850 op = cff_op_and;
851 break;
852 case 4:
853 op = cff_op_or;
854 break;
855 case 5:
856 op = cff_op_not;
857 break;
858 case 8:
859 op = cff_op_store;
860 break;
861 case 9:
862 op = cff_op_abs;
863 break;
864 case 10:
865 op = cff_op_add;
866 break;
867 case 11:
868 op = cff_op_sub;
869 break;
870 case 12:
871 op = cff_op_div;
872 break;
873 case 13:
874 op = cff_op_load;
875 break;
876 case 14:
877 op = cff_op_neg;
878 break;
879 case 15:
880 op = cff_op_eq;
881 break;
882 case 18:
883 op = cff_op_drop;
884 break;
885 case 20:
886 op = cff_op_put;
887 break;
888 case 21:
889 op = cff_op_get;
890 break;
891 case 22:
892 op = cff_op_ifelse;
893 break;
894 case 23:
895 op = cff_op_random;
896 break;
897 case 24:
898 op = cff_op_mul;
899 break;
900 case 26:
901 op = cff_op_sqrt;
902 break;
903 case 27:
904 op = cff_op_dup;
905 break;
906 case 28:
907 op = cff_op_exch;
908 break;
909 case 29:
910 op = cff_op_index;
911 break;
912 case 30:
913 op = cff_op_roll;
914 break;
915 case 34:
916 op = cff_op_hflex;
917 break;
918 case 35:
919 op = cff_op_flex;
920 break;
921 case 36:
922 op = cff_op_hflex1;
923 break;
924 case 37:
925 op = cff_op_flex1;
926 break;
927 default:
928 /* decrement ip for syntax error message */
929 ip--;
930 }
931 }
932 break;
933 case 14:
934 op = cff_op_endchar;
935 break;
936 case 16:
937 op = cff_op_blend;
938 break;
939 case 18:
940 op = cff_op_hstemhm;
941 break;
942 case 19:
943 op = cff_op_hintmask;
944 break;
945 case 20:
946 op = cff_op_cntrmask;
947 break;
948 case 21:
949 op = cff_op_rmoveto;
950 break;
951 case 22:
952 op = cff_op_hmoveto;
953 break;
954 case 23:
955 op = cff_op_vstemhm;
956 break;
957 case 24:
958 op = cff_op_rcurveline;
959 break;
960 case 25:
961 op = cff_op_rlinecurve;
962 break;
963 case 26:
964 op = cff_op_vvcurveto;
965 break;
966 case 27:
967 op = cff_op_hhcurveto;
968 break;
969 case 29:
970 op = cff_op_callgsubr;
971 break;
972 case 30:
973 op = cff_op_vhcurveto;
974 break;
975 case 31:
976 op = cff_op_hvcurveto;
977 break;
978 default:
979 ;
980 }
981 if ( op == cff_op_unknown )
982 goto Syntax_Error;
984 /* check arguments */
985 req_args = cff_argument_counts[op];
986 if ( req_args & CFF_COUNT_CHECK_WIDTH )
987 {
988 args = stack;
990 if ( num_args > 0 && decoder->read_width )
991 {
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;
1003 switch ( op )
1004 {
1005 case cff_op_hmoveto:
1006 case cff_op_vmoveto:
1007 set_width_ok = num_args & 2;
1008 break;
1010 case cff_op_hstem:
1011 case cff_op_vstem:
1012 case cff_op_hstemhm:
1013 case cff_op_vstemhm:
1014 case cff_op_rmoveto:
1015 set_width_ok = num_args & 1;
1016 break;
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 ) );
1022 break;
1024 default:
1025 set_width_ok = 0;
1026 break;
1027 }
1029 if ( set_width_ok )
1030 {
1031 decoder->glyph_width = decoder->nominal_width +
1032 ( stack[0] >> 16 );
1034 /* Consumed an argument. */
1035 num_args--;
1036 args++;
1037 }
1038 }
1040 decoder->read_width = 0;
1041 req_args = 0;
1042 }
1044 req_args &= 15;
1045 if ( num_args < req_args )
1046 goto Stack_Underflow;
1047 args -= req_args;
1048 num_args -= req_args;
1050 switch ( op )
1051 {
1052 case cff_op_hstem:
1053 case cff_op_vstem:
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" :
1062 " vstemhm" ));
1063 decoder->num_hints += num_args / 2;
1064 args = stack;
1065 break;
1067 case cff_op_hintmask:
1068 case cff_op_cntrmask:
1069 FT_TRACE4(( op == cff_op_hintmask ? " hintmask"
1070 : " cntrmask" ));
1072 decoder->num_hints += num_args / 2;
1074 #ifdef FT_DEBUG_LEVEL_TRACE
1075 {
1076 FT_UInt maskbyte;
1078 FT_TRACE4(( " " ));
1080 for ( maskbyte = 0;
1081 maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3);
1082 maskbyte++, ip++ )
1083 {
1084 FT_TRACE4(( "%02X", *ip ));
1085 }
1087 }
1088 #else
1089 ip += ( decoder->num_hints + 7 ) >> 3;
1090 #endif
1091 if ( ip >= limit )
1092 goto Syntax_Error;
1093 args = stack;
1094 break;
1096 case cff_op_rmoveto:
1097 FT_TRACE4(( " rmoveto" ));
1099 close_contour( builder );
1100 builder->path_begun = 0;
1101 x += args[0];
1102 y += args[1];
1103 args = stack;
1104 break;
1106 case cff_op_vmoveto:
1107 FT_TRACE4(( " vmoveto" ));
1109 close_contour( builder );
1110 builder->path_begun = 0;
1111 y += args[0];
1112 args = stack;
1113 break;
1115 case cff_op_hmoveto:
1116 FT_TRACE4(( " hmoveto" ));
1118 close_contour( builder );
1119 builder->path_begun = 0;
1120 x += args[0];
1121 args = stack;
1122 break;
1124 case cff_op_rlineto:
1125 FT_TRACE4(( " rlineto" ));
1127 if ( start_point ( builder, x, y ) ||
1128 check_points( builder, num_args / 2 ) )
1129 goto Memory_Error;
1131 if ( num_args < 2 || num_args & 1 )
1132 goto Stack_Underflow;
1134 args = stack;
1135 while ( args < decoder->top )
1136 {
1137 x += args[0];
1138 y += args[1];
1139 add_point( builder, x, y, 1 );
1140 args += 2;
1141 }
1142 args = stack;
1143 break;
1145 case cff_op_hlineto:
1146 case cff_op_vlineto:
1147 {
1148 FT_Int phase = ( op == cff_op_hlineto );
1151 FT_TRACE4(( op == cff_op_hlineto ? " hlineto"
1152 : " vlineto" ));
1154 if ( start_point ( builder, x, y ) ||
1155 check_points( builder, num_args ) )
1156 goto Memory_Error;
1158 args = stack;
1159 while (args < decoder->top )
1160 {
1161 if ( phase )
1162 x += args[0];
1163 else
1164 y += args[0];
1166 if ( add_point1( builder, x, y ) )
1167 goto Memory_Error;
1169 args++;
1170 phase ^= 1;
1171 }
1172 args = stack;
1173 }
1174 break;
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 ) )
1185 goto Memory_Error;
1187 args = stack;
1188 while ( args < decoder->top )
1189 {
1190 x += args[0];
1191 y += args[1];
1192 add_point( builder, x, y, 0 );
1193 x += args[2];
1194 y += args[3];
1195 add_point( builder, x, y, 0 );
1196 x += args[4];
1197 y += args[5];
1198 add_point( builder, x, y, 1 );
1199 args += 6;
1200 }
1201 args = stack;
1202 break;
1204 case cff_op_vvcurveto:
1205 FT_TRACE4(( " vvcurveto" ));
1207 if ( start_point ( builder, x, y ) )
1208 goto Memory_Error;
1210 args = stack;
1211 if ( num_args & 1 )
1212 {
1213 x += args[0];
1214 args++;
1215 num_args--;
1216 }
1218 if ( num_args % 4 != 0 )
1219 goto Stack_Underflow;
1221 if ( check_points( builder, 3 * ( num_args / 4 ) ) )
1222 goto Memory_Error;
1224 while ( args < decoder->top )
1225 {
1226 y += args[0];
1227 add_point( builder, x, y, 0 );
1228 x += args[1];
1229 y += args[2];
1230 add_point( builder, x, y, 0 );
1231 y += args[3];
1232 add_point( builder, x, y, 1 );
1233 args += 4;
1234 }
1235 args = stack;
1236 break;
1238 case cff_op_hhcurveto:
1239 FT_TRACE4(( " hhcurveto" ));
1241 if ( start_point ( builder, x, y ) )
1242 goto Memory_Error;
1244 args = stack;
1245 if ( num_args & 1 )
1246 {
1247 y += args[0];
1248 args++;
1249 num_args--;
1250 }
1252 if ( num_args % 4 != 0 )
1253 goto Stack_Underflow;
1255 if ( check_points( builder, 3 * ( num_args / 4 ) ) )
1256 goto Memory_Error;
1258 while ( args < decoder->top )
1259 {
1260 x += args[0];
1261 add_point( builder, x, y, 0 );
1262 x += args[1];
1263 y += args[2];
1264 add_point( builder, x, y, 0 );
1265 x += args[3];
1266 add_point( builder, x, y, 1 );
1267 args += 4;
1268 }
1269 args = stack;
1270 break;
1272 case cff_op_vhcurveto:
1273 case cff_op_hvcurveto:
1274 {
1275 FT_Int phase;
1278 FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto"
1279 : " hvcurveto" ));
1281 if ( start_point ( builder, x, y ) )
1282 goto Memory_Error;
1284 args = stack;
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 )
1294 {
1295 num_args -= 4;
1296 if ( phase )
1297 {
1298 x += args[0];
1299 add_point( builder, x, y, 0 );
1300 x += args[1];
1301 y += args[2];
1302 add_point( builder, x, y, 0 );
1303 y += args[3];
1304 if ( num_args == 1 )
1305 x += args[4];
1306 add_point( builder, x, y, 1 );
1307 }
1308 else
1309 {
1310 y += args[0];
1311 add_point( builder, x, y, 0 );
1312 x += args[1];
1313 y += args[2];
1314 add_point( builder, x, y, 0 );
1315 x += args[3];
1316 if ( num_args == 1 )
1317 y += args[4];
1318 add_point( builder, x, y, 1 );
1319 }
1320 args += 4;
1321 phase ^= 1;
1322 }
1323 args = stack;
1324 }
1325 break;
1327 case cff_op_rlinecurve:
1328 {
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 ) )
1339 goto Memory_Error;
1341 args = stack;
1343 /* first, add the line segments */
1344 while ( num_lines > 0 )
1345 {
1346 x += args[0];
1347 y += args[1];
1348 add_point( builder, x, y, 1 );
1349 args += 2;
1350 num_lines--;
1351 }
1353 /* then the curve */
1354 x += args[0];
1355 y += args[1];
1356 add_point( builder, x, y, 0 );
1357 x += args[2];
1358 y += args[3];
1359 add_point( builder, x, y, 0 );
1360 x += args[4];
1361 y += args[5];
1362 add_point( builder, x, y, 1 );
1363 args = stack;
1364 }
1365 break;
1367 case cff_op_rcurveline:
1368 {
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 ) )
1379 goto Memory_Error;
1381 args = stack;
1383 /* first, add the curves */
1384 while ( num_curves > 0 )
1385 {
1386 x += args[0];
1387 y += args[1];
1388 add_point( builder, x, y, 0 );
1389 x += args[2];
1390 y += args[3];
1391 add_point( builder, x, y, 0 );
1392 x += args[4];
1393 y += args[5];
1394 add_point( builder, x, y, 1 );
1395 args += 6;
1396 num_curves--;
1397 }
1399 /* then the final line */
1400 x += args[0];
1401 y += args[1];
1402 add_point( builder, x, y, 1 );
1403 args = stack;
1404 }
1405 break;
1407 case cff_op_hflex1:
1408 {
1409 FT_Pos start_y;
1412 FT_TRACE4(( " hflex1" ));
1414 args = stack;
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 ) )
1421 goto Memory_Error;
1423 /* Record the starting point's y postion for later use */
1424 start_y = y;
1426 /* first control point */
1427 x += args[0];
1428 y += args[1];
1429 add_point( builder, x, y, 0 );
1431 /* second control point */
1432 x += args[2];
1433 y += args[3];
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 */
1438 x += args[4];
1439 add_point( builder, x, y, 1 );
1441 /* third control point, with y-value the same as the join */
1442 /* point's y-value */
1443 x += args[5];
1444 add_point( builder, x, y, 0 );
1446 /* fourth control point */
1447 x += args[6];
1448 y += args[7];
1449 add_point( builder, x, y, 0 );
1451 /* ending point, with y-value the same as the start */
1452 x += args[8];
1453 y = start_y;
1454 add_point( builder, x, y, 1 );
1456 args = stack;
1457 break;
1458 }
1460 case cff_op_hflex:
1461 {
1462 FT_Pos start_y;
1465 FT_TRACE4(( " hflex" ));
1467 args = stack;
1469 /* adding six more points; 4 control points, 2 on-curve points */
1470 if ( start_point( builder, x, y ) ||
1471 check_points ( builder, 6 ) )
1472 goto Memory_Error;
1474 /* record the starting point's y-position for later use */
1475 start_y = y;
1477 /* first control point */
1478 x += args[0];
1479 add_point( builder, x, y, 0 );
1481 /* second control point */
1482 x += args[1];
1483 y += args[2];
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 */
1488 x += args[3];
1489 add_point( builder, x, y, 1 );
1491 /* third control point, with y-value the same as the join */
1492 /* point's y-value */
1493 x += args[4];
1494 add_point( builder, x, y, 0 );
1496 /* fourth control point */
1497 x += args[5];
1498 y = start_y;
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 */
1503 x += args[6];
1504 add_point( builder, x, y, 1 );
1506 args = stack;
1507 break;
1508 }
1510 case cff_op_flex1:
1511 {
1512 FT_Pos start_x, start_y; /* record start x, y values for alter */
1513 /* use */
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 ) )
1524 goto Memory_Error;
1526 /* record the starting point's x, y postion for later use */
1527 start_x = x;
1528 start_y = y;
1530 /* XXX: figure out whether this is supposed to be a horizontal */
1531 /* or vertical flex; the Type 2 specification is vague... */
1533 args = stack;
1535 /* grab up to the last argument */
1536 for ( count = 5; count > 0; count-- )
1537 {
1538 dx += args[0];
1539 dy += args[1];
1540 args += 2;
1541 }
1543 /* rewind */
1544 args = stack;
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-- )
1553 {
1554 x += args[0];
1555 y += args[1];
1556 add_point( builder, x, y, (FT_Bool)( count == 3 ) );
1557 args += 2;
1558 }
1560 /* is last operand an x- or y-delta? */
1561 if ( horizontal )
1562 {
1563 x += args[0];
1564 y = start_y;
1565 }
1566 else
1567 {
1568 x = start_x;
1569 y += args[0];
1570 }
1572 add_point( builder, x, y, 1 );
1574 args = stack;
1575 break;
1576 }
1578 case cff_op_flex:
1579 {
1580 FT_UInt count;
1583 FT_TRACE4(( " flex" ));
1585 if ( start_point( builder, x, y ) ||
1586 check_points( builder, 6 ) )
1587 goto Memory_Error;
1589 args = stack;
1590 for ( count = 6; count > 0; count-- )
1591 {
1592 x += args[0];
1593 y += args[1];
1594 add_point( builder, x, y,
1595 (FT_Bool)( count == 3 || count == 0 ) );
1596 args += 2;
1597 }
1599 args = stack;
1600 }
1601 break;
1603 case cff_op_endchar:
1604 FT_TRACE4(( " endchar" ));
1606 /* We are going to emulate the seac operator. */
1607 if ( num_args == 4 )
1608 {
1609 error = cff_operator_seac( decoder,
1610 args[0] >> 16, args[1] >> 16,
1611 args[2] >> 16, args[3] >> 16 );
1612 args += 4;
1613 }
1615 if ( !error )
1616 error = CFF_Err_Ok;
1618 close_contour( builder );
1620 /* add current outline to the glyph slot */
1621 FT_GlyphLoader_Add( builder->loader );
1623 /* return now! */
1624 FT_TRACE4(( "\n\n" ));
1625 return error;
1627 case cff_op_abs:
1628 FT_TRACE4(( " abs" ));
1630 if ( args[0] < 0 )
1631 args[0] = -args[0];
1632 args++;
1633 break;
1635 case cff_op_add:
1636 FT_TRACE4(( " add" ));
1638 args[0] += args[1];
1639 args++;
1640 break;
1642 case cff_op_sub:
1643 FT_TRACE4(( " sub" ));
1645 args[0] -= args[1];
1646 args++;
1647 break;
1649 case cff_op_div:
1650 FT_TRACE4(( " div" ));
1652 args[0] = FT_DivFix( args[0], args[1] );
1653 args++;
1654 break;
1656 case cff_op_neg:
1657 FT_TRACE4(( " neg" ));
1659 args[0] = -args[0];
1660 args++;
1661 break;
1663 case cff_op_random:
1664 {
1665 FT_Fixed rand;
1668 FT_TRACE4(( " rand" ));
1670 rand = seed;
1671 if ( rand >= 0x8000 )
1672 rand++;
1674 args[0] = rand;
1675 seed = FT_MulFix( seed, 0x10000L - seed );
1676 if ( seed == 0 )
1677 seed += 0x2873;
1678 args++;
1679 }
1680 break;
1682 case cff_op_mul:
1683 FT_TRACE4(( " mul" ));
1685 args[0] = FT_MulFix( args[0], args[1] );
1686 args++;
1687 break;
1689 case cff_op_sqrt:
1690 FT_TRACE4(( " sqrt" ));
1692 if ( args[0] > 0 )
1693 {
1694 FT_Int count = 9;
1695 FT_Fixed root = args[0];
1696 FT_Fixed new_root;
1699 for (;;)
1700 {
1701 new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
1702 if ( new_root == root || count <= 0 )
1703 break;
1704 root = new_root;
1705 }
1706 args[0] = new_root;
1707 }
1708 else
1709 args[0] = 0;
1710 args++;
1711 break;
1713 case cff_op_drop:
1714 /* nothing */
1715 FT_TRACE4(( " drop" ));
1717 break;
1719 case cff_op_exch:
1720 {
1721 FT_Fixed tmp;
1724 FT_TRACE4(( " exch" ));
1726 tmp = args[0];
1727 args[0] = args[1];
1728 args[1] = tmp;
1729 args += 2;
1730 }
1731 break;
1733 case cff_op_index:
1734 {
1735 FT_Int index = args[0] >> 16;
1738 FT_TRACE4(( " index" ));
1740 if ( index < 0 )
1741 index = 0;
1742 else if ( index > num_args - 2 )
1743 index = num_args - 2;
1744 args[0] = args[-( index + 1 )];
1745 args++;
1746 }
1747 break;
1749 case cff_op_roll:
1750 {
1751 FT_Int count = (FT_Int)( args[0] >> 16 );
1752 FT_Int index = (FT_Int)( args[1] >> 16 );
1755 FT_TRACE4(( " roll" ));
1757 if ( count <= 0 )
1758 count = 1;
1760 args -= count;
1761 if ( args < stack )
1762 goto Stack_Underflow;
1764 if ( index >= 0 )
1765 {
1766 while ( index > 0 )
1767 {
1768 FT_Fixed tmp = args[count - 1];
1769 FT_Int i;
1772 for ( i = count - 2; i >= 0; i-- )
1773 args[i + 1] = args[i];
1774 args[0] = tmp;
1775 index--;
1776 }
1777 }
1778 else
1779 {
1780 while ( index < 0 )
1781 {
1782 FT_Fixed tmp = args[0];
1783 FT_Int i;
1786 for ( i = 0; i < count - 1; i++ )
1787 args[i] = args[i + 1];
1788 args[count - 1] = tmp;
1789 index++;
1790 }
1791 }
1792 args += count;
1793 }
1794 break;
1796 case cff_op_dup:
1797 FT_TRACE4(( " dup" ));
1799 args[1] = args[0];
1800 args++;
1801 break;
1803 case cff_op_put:
1804 {
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;
1813 }
1814 break;
1816 case cff_op_get:
1817 {
1818 FT_Int index = (FT_Int)( args[0] >> 16 );
1819 FT_Fixed val = 0;
1822 FT_TRACE4(( " get" ));
1824 if ( index >= 0 && index < decoder->len_buildchar )
1825 val = decoder->buildchar[index];
1827 args[0] = val;
1828 args++;
1829 }
1830 break;
1832 case cff_op_store:
1833 FT_TRACE4(( " store "));
1835 goto Unimplemented;
1837 case cff_op_load:
1838 FT_TRACE4(( " load" ));
1840 goto Unimplemented;
1842 case cff_op_dotsection:
1843 /* this operator is deprecated and ignored by the parser */
1844 FT_TRACE4(( " dotsection" ));
1845 break;
1847 case cff_op_and:
1848 {
1849 FT_Fixed cond = args[0] && args[1];
1852 FT_TRACE4(( " and" ));
1854 args[0] = cond ? 0x10000L : 0;
1855 args++;
1856 }
1857 break;
1859 case cff_op_or:
1860 {
1861 FT_Fixed cond = args[0] || args[1];
1864 FT_TRACE4(( " or" ));
1866 args[0] = cond ? 0x10000L : 0;
1867 args++;
1868 }
1869 break;
1871 case cff_op_eq:
1872 {
1873 FT_Fixed cond = !args[0];
1876 FT_TRACE4(( " eq" ));
1878 args[0] = cond ? 0x10000L : 0;
1879 args++;
1880 }
1881 break;
1883 case cff_op_ifelse:
1884 {
1885 FT_Fixed cond = (args[2] <= args[3]);
1888 FT_TRACE4(( " ifelse" ));
1890 if ( !cond )
1891 args[0] = args[1];
1892 args++;
1893 }
1894 break;
1896 case cff_op_callsubr:
1897 {
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 )
1905 {
1906 FT_ERROR(( "CFF_Parse_CharStrings:" ));
1907 FT_ERROR(( " invalid local subr index\n" ));
1908 goto Syntax_Error;
1909 }
1911 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
1912 {
1913 FT_ERROR(( "CFF_Parse_CharStrings: too many nested subrs\n" ));
1914 goto Syntax_Error;
1915 }
1917 zone->cursor = ip; /* save current instruction pointer */
1919 zone++;
1920 zone->base = decoder->locals[index];
1921 zone->limit = decoder->locals[index + 1];
1922 zone->cursor = zone->base;
1924 if ( !zone->base )
1925 {
1926 FT_ERROR(( "CFF_Parse_CharStrings: invoking empty subrs!\n" ));
1927 goto Syntax_Error;
1928 }
1930 decoder->zone = zone;
1931 ip = zone->base;
1932 limit = zone->limit;
1933 }
1934 break;
1936 case cff_op_callgsubr:
1937 {
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 )
1945 {
1946 FT_ERROR(( "CFF_Parse_CharStrings:" ));
1947 FT_ERROR(( " invalid global subr index\n" ));
1948 goto Syntax_Error;
1949 }
1951 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
1952 {
1953 FT_ERROR(( "CFF_Parse_CharStrings: too many nested subrs\n" ));
1954 goto Syntax_Error;
1955 }
1957 zone->cursor = ip; /* save current instruction pointer */
1959 zone++;
1960 zone->base = decoder->globals[index];
1961 zone->limit = decoder->globals[index+1];
1962 zone->cursor = zone->base;
1964 if ( !zone->base )
1965 {
1966 FT_ERROR(( "CFF_Parse_CharStrings: invoking empty subrs!\n" ));
1967 goto Syntax_Error;
1968 }
1970 decoder->zone = zone;
1971 ip = zone->base;
1972 limit = zone->limit;
1973 }
1974 break;
1976 case cff_op_return:
1977 FT_TRACE4(( " return" ));
1979 if ( decoder->zone <= decoder->zones )
1980 {
1981 FT_ERROR(( "CFF_Parse_CharStrings: unexpected return\n" ));
1982 goto Syntax_Error;
1983 }
1985 decoder->zone--;
1986 zone = decoder->zone;
1987 ip = zone->cursor;
1988 limit = zone->limit;
1989 break;
1991 default:
1992 Unimplemented:
1993 FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
1995 if ( ip[-1] == 12 )
1996 FT_ERROR(( " %d", ip[0] ));
1997 FT_ERROR(( "\n" ));
1999 return CFF_Err_Unimplemented_Feature;
2000 }
2002 decoder->top = args;
2004 } /* general operator processing */
2006 } /* while ip < limit */
2008 FT_TRACE4(( "..end..\n\n" ));
2010 return error;
2012 Syntax_Error:
2013 FT_TRACE4(( "CFF_Parse_CharStrings: syntax error!" ));
2014 return CFF_Err_Invalid_File_Format;
2016 Stack_Underflow:
2017 FT_TRACE4(( "CFF_Parse_CharStrings: stack underflow!" ));
2018 return CFF_Err_Too_Few_Arguments;
2020 Stack_Overflow:
2021 FT_TRACE4(( "CFF_Parse_CharStrings: stack overflow!" ));
2022 return CFF_Err_Stack_Overflow;
2024 Memory_Error:
2025 return builder->error;
2026 }
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 )
2053 {
2054 FT_Error error = 0;
2055 CFF_Decoder decoder;
2056 FT_Int glyph_index;
2057 CFF_Font* cff = (CFF_Font*)face->other;
2060 *max_advance = 0;
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;
2071 glyph_index++ )
2072 {
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 );
2080 if ( !error )
2081 {
2082 CFF_Prepare_Decoder( &decoder, glyph_index );
2083 error = CFF_Parse_CharStrings( &decoder, charstring, charstring_len );
2085 CFF_Forget_Element( &cff->charstrings_index, &charstring );
2086 }
2088 /* ignore the error if one has occurred -- skip to next glyph */
2089 error = 0;
2090 }
2092 *max_advance = decoder.builder.advance.x;
2094 return CFF_Err_Ok;
2095 }
2098 #endif /* 0 */
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,
2119 CFF_Size size,
2120 FT_Int glyph_index,
2121 FT_Int load_flags )
2122 {
2123 FT_Error error;
2124 CFF_Decoder decoder;
2125 TT_Face face = (TT_Face)glyph->root.face;
2126 FT_Bool hinting;
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;
2138 if ( size )
2139 {
2140 glyph->x_scale = size->metrics.x_scale;
2141 glyph->y_scale = size->metrics.y_scale;
2142 }
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 */
2152 {
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 );
2165 if ( !error )
2166 {
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 =
2181 charstring_len;
2182 }
2184 /* save new glyph tables */
2185 CFF_Done_Builder( &decoder.builder );
2186 }
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. */
2194 if ( !error )
2195 {
2196 /* For composite glyphs, return only left side bearing and */
2197 /* advance width. */
2198 if ( load_flags & FT_LOAD_NO_RECURSE )
2199 {
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;
2208 }
2209 else
2210 {
2211 FT_BBox cbox;
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,
2239 font_offset.x,
2240 font_offset.y );
2242 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
2243 {
2244 /* scale the outline and the metrics */
2245 FT_Int n;
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++ )
2254 {
2255 vec->x = FT_MulFix( vec->x, x_scale );
2256 vec->y = FT_MulFix( vec->y, y_scale );
2257 }
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 );
2267 }
2269 /* compute the other metrics */
2270 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
2272 /* grid fit the bounding box if necessary */
2273 if ( hinting )
2274 {
2275 cbox.xMin &= -64;
2276 cbox.yMin &= -64;
2277 cbox.xMax = ( cbox.xMax + 63 ) & -64;
2278 cbox.yMax = ( cbox.yMax + 63 ) & -64;
2279 }
2281 metrics->width = cbox.xMax - cbox.xMin;
2282 metrics->height = cbox.yMax - cbox.yMin;
2284 metrics->horiBearingX = cbox.xMin;
2285 metrics->horiBearingY = cbox.yMax;
2286 }
2287 }
2289 return error;
2290 }
2293 /* END */