1 /***************************************************************************/
5 /* PostScript Type 1 decoding routines (body). */
7 /* Copyright 2000-2001, 2002 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_POSTSCRIPT_HINTS_H
30 /*************************************************************************/
32 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
33 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
34 /* messages during execution. */
37 #define FT_COMPONENT trace_t1decode
40 typedef enum T1_Operator_
69 op_max /* never remove this one */
75 const FT_Int t1_args_count[op_max] =
98 -1, /* callothersubr */
102 2 /* setcurrentpoint */
106 /*************************************************************************/
109 /* t1_lookup_glyph_by_stdcharcode */
112 /* Looks up a given glyph by its StandardEncoding charcode. Used to */
113 /* implement the SEAC Type 1 operator. */
116 /* face :: The current face object. */
118 /* charcode :: The character code to look for. */
121 /* A glyph index in the font face. Returns -1 if the corresponding */
122 /* glyph wasn't found. */
125 t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder,
129 const FT_String* glyph_name;
130 PSNames_Service psnames = decoder->psnames;
133 /* check range of standard char code */
134 if ( charcode < 0 || charcode > 255 )
137 glyph_name = psnames->adobe_std_strings(
138 psnames->adobe_std_encoding[charcode]);
140 for ( n = 0; n < decoder->num_glyphs; n++ )
142 FT_String* name = (FT_String*)decoder->glyph_names[n];
145 if ( name && name[0] == glyph_name[0] &&
146 ft_strcmp( name,glyph_name ) == 0 )
154 /*************************************************************************/
157 /* t1operator_seac */
160 /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
163 /* decoder :: The current CID decoder. */
165 /* asb :: The accent's side bearing. */
167 /* adx :: The horizontal offset of the accent. */
169 /* ady :: The vertical offset of the accent. */
171 /* bchar :: The base character's StandardEncoding charcode. */
173 /* achar :: The accent character's StandardEncoding charcode. */
176 /* FreeType error code. 0 means success. */
179 t1operator_seac( T1_Decoder decoder,
187 FT_Int bchar_index, achar_index;
189 FT_Int n_base_points;
190 FT_Outline* base = decoder->builder.base;
192 FT_Vector left_bearing, advance;
196 adx += decoder->builder.left_bearing.x;
198 /* `glyph_names' is set to 0 for CID fonts which do not */
199 /* include an encoding. How can we deal with these? */
200 if ( decoder->glyph_names == 0 )
202 FT_ERROR(( "t1operator_seac:" ));
203 FT_ERROR(( " glyph names table not available in this font!\n" ));
204 return PSaux_Err_Syntax_Error;
207 bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
208 achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
210 if ( bchar_index < 0 || achar_index < 0 )
212 FT_ERROR(( "t1operator_seac:" ));
213 FT_ERROR(( " invalid seac character code arguments\n" ));
214 return PSaux_Err_Syntax_Error;
217 /* if we are trying to load a composite glyph, do not load the */
218 /* accent character and return the array of subglyphs. */
219 if ( decoder->builder.no_recurse )
221 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
222 FT_GlyphLoader loader = glyph->internal->loader;
226 /* reallocate subglyph array if necessary */
227 error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
231 subg = loader->current.subglyphs;
233 /* subglyph 0 = base character */
234 subg->index = bchar_index;
235 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
236 FT_SUBGLYPH_FLAG_USE_MY_METRICS;
241 /* subglyph 1 = accent character */
242 subg->index = achar_index;
243 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
244 subg->arg1 = adx - asb;
247 /* set up remaining glyph fields */
248 glyph->num_subglyphs = 2;
249 glyph->subglyphs = loader->base.subglyphs;
250 glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
252 loader->current.num_subglyphs = 2;
256 /* First load `bchar' in builder */
257 /* now load the unscaled outline */
259 FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
261 error = t1_decoder_parse_glyph( decoder, bchar_index );
266 n_base_points = base->n_points;
269 /* save the left bearing and width of the base character */
270 /* as they will be erased by the next load. */
272 left_bearing = decoder->builder.left_bearing;
273 advance = decoder->builder.advance;
275 decoder->builder.left_bearing.x = 0;
276 decoder->builder.left_bearing.y = 0;
278 decoder->builder.pos_x = adx - asb;
279 decoder->builder.pos_y = ady;
281 /* Now load `achar' on top of */
282 /* the base outline */
283 error = t1_decoder_parse_glyph( decoder, achar_index );
287 /* restore the left side bearing and */
288 /* advance width of the base character */
290 decoder->builder.left_bearing = left_bearing;
291 decoder->builder.advance = advance;
293 /* XXX: old code doesn't work with PostScript hinter */
295 /* Finally, move the accent */
296 if ( decoder->builder.load_points )
301 dummy.n_points = (short)( base->n_points - n_base_points );
302 dummy.points = base->points + n_base_points;
304 FT_Outline_Translate( &dummy, adx - asb, ady );
307 decoder->builder.pos_x = 0;
308 decoder->builder.pos_y = 0;
316 /*************************************************************************/
319 /* t1_decoder_parse_charstrings */
322 /* Parses a given Type 1 charstrings program. */
325 /* decoder :: The current Type 1 decoder. */
327 /* charstring_base :: The base address of the charstring stream. */
329 /* charstring_len :: The length in bytes of the charstring stream. */
332 /* FreeType error code. 0 means success. */
334 FT_LOCAL_DEF( FT_Error )
335 t1_decoder_parse_charstrings( T1_Decoder decoder,
336 FT_Byte* charstring_base,
337 FT_UInt charstring_len )
340 T1_Decoder_Zone zone;
343 T1_Builder builder = &decoder->builder;
344 FT_Pos x, y, orig_x, orig_y;
346 T1_Hints_Funcs hinter;
349 /* we don't want to touch the source code -- use macro trick */
350 #define start_point t1_builder_start_point
351 #define check_points t1_builder_check_points
352 #define add_point t1_builder_add_point
353 #define add_point1 t1_builder_add_point1
354 #define add_contour t1_builder_add_contour
355 #define close_contour t1_builder_close_contour
357 /* First of all, initialize the decoder */
358 decoder->top = decoder->stack;
359 decoder->zone = decoder->zones;
360 zone = decoder->zones;
362 builder->path_begun = 0;
364 hinter = (T1_Hints_Funcs)builder->hints_funcs;
366 zone->base = charstring_base;
367 limit = zone->limit = charstring_base + charstring_len;
368 ip = zone->cursor = zone->base;
370 error = PSaux_Err_Ok;
372 x = orig_x = builder->pos_x;
373 y = orig_y = builder->pos_y;
375 /* begin hints recording session, if any */
377 hinter->open( hinter->hints );
379 /* now, execute loop */
382 FT_Long* top = decoder->top;
383 T1_Operator op = op_none;
387 /*********************************************************************/
389 /* Decode operator or operand */
393 /* first of all, decompress operator or value */
435 case 15: /* undocumented, obsolete operator */
456 FT_ERROR(( "t1_decoder_parse_charstrings: "
457 "invalid escape (12+EOF)\n" ));
482 op = op_callothersubr;
488 op = op_setcurrentpoint;
492 FT_ERROR(( "t1_decoder_parse_charstrings: "
493 "invalid escape (12+%d)\n",
499 case 255: /* four bytes integer */
500 if ( ip + 4 > limit )
502 FT_ERROR(( "t1_decoder_parse_charstrings: "
503 "unexpected EOF in integer\n" ));
507 value = (FT_Int32)( ((FT_Long)ip[0] << 24) |
508 ((FT_Long)ip[1] << 16) |
509 ((FT_Long)ip[2] << 8 ) |
518 value = (FT_Long)ip[-1] - 139;
523 FT_ERROR(( "t1_decoder_parse_charstrings: " ));
524 FT_ERROR(( "unexpected EOF in integer\n" ));
529 value = ( ( (FT_Long)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
531 value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
536 FT_ERROR(( "t1_decoder_parse_charstrings: "
537 "invalid byte (%d)\n", ip[-1] ));
542 /*********************************************************************/
544 /* Push value on stack, or process operator */
549 if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
551 FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow!\n" ));
555 FT_TRACE4(( " %ld", value ));
560 else if ( op == op_callothersubr ) /* callothersubr */
562 FT_TRACE4(( " callothersubr" ));
564 if ( top - decoder->stack < 2 )
565 goto Stack_Underflow;
570 case 1: /* start flex feature */
572 goto Unexpected_OtherSubr;
574 decoder->flex_state = 1;
575 decoder->num_flex_vectors = 0;
576 if ( start_point( builder, x, y ) ||
577 check_points( builder, 6 ) )
581 case 2: /* add flex vectors */
587 goto Unexpected_OtherSubr;
589 /* note that we should not add a point for index 0; */
590 /* this will move our current position to the flex */
591 /* point without adding any point to the outline */
592 idx = decoder->num_flex_vectors++;
593 if ( idx > 0 && idx < 7 )
597 (FT_Byte)( idx == 3 || idx == 6 ) );
601 case 0: /* end flex feature */
603 goto Unexpected_OtherSubr;
605 if ( decoder->flex_state == 0 ||
606 decoder->num_flex_vectors != 7 )
608 FT_ERROR(( "t1_decoder_parse_charstrings: "
609 "unexpected flex end\n" ));
613 /* now consume the remaining `pop pop setcurpoint' */
614 if ( ip + 6 > limit ||
615 ip[0] != 12 || ip[1] != 17 || /* pop */
616 ip[2] != 12 || ip[3] != 17 || /* pop */
617 ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */
619 FT_ERROR(( "t1_decoder_parse_charstrings: "
620 "invalid flex charstring\n" ));
625 decoder->flex_state = 0;
628 case 3: /* change hints */
630 goto Unexpected_OtherSubr;
632 /* eat the following `pop' */
633 if ( ip + 2 > limit )
635 FT_ERROR(( "t1_decoder_parse_charstrings: "
636 "invalid escape (12+%d)\n", ip[-1] ));
640 if ( ip[0] != 12 || ip[1] != 17 )
642 FT_ERROR(( "t1_decoder_parse_charstrings: " ));
643 FT_ERROR(( "`pop' expected, found (%d %d)\n", ip[0], ip[1] ));
649 hinter->reset( hinter->hints, builder->current->n_points );
655 /* counter control hints, clear stack */
656 top = decoder->stack;
663 case 18: /* multiple masters */
665 PS_Blend blend = decoder->blend;
666 FT_UInt num_points, nn, mm;
673 FT_ERROR(( "t1_decoder_parse_charstrings: " ));
674 FT_ERROR(( "unexpected multiple masters operator!\n" ));
678 num_points = (FT_UInt)top[1] - 13 + ( top[1] == 18 );
679 if ( top[0] != (FT_Int)( num_points * blend->num_designs ) )
681 FT_ERROR(( "t1_decoder_parse_charstrings: " ));
682 FT_ERROR(( "incorrect number of mm arguments\n" ));
686 top -= blend->num_designs * num_points;
687 if ( top < decoder->stack )
688 goto Stack_Underflow;
690 /* we want to compute: */
692 /* a0*w0 + a1*w1 + ... + ak*wk */
694 /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */
695 /* however, given that w0 + w1 + ... + wk == 1, we can */
696 /* rewrite it easily as: */
698 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
700 /* where k == num_designs-1 */
702 /* I guess that's why it's written in this `compact' */
705 delta = top + num_points;
707 for ( nn = 0; nn < num_points; nn++ )
709 FT_Int tmp = values[0];
712 for ( mm = 1; mm < blend->num_designs; mm++ )
713 tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
717 /* note that `top' will be incremented later by calls to `pop' */
722 Unexpected_OtherSubr:
723 FT_ERROR(( "t1_decoder_parse_charstrings: "
724 "invalid othersubr [%d %d]!\n", top[0], top[1] ));
729 else /* general operator */
731 FT_Int num_args = t1_args_count[op];
734 if ( top - decoder->stack < num_args )
735 goto Stack_Underflow;
742 FT_TRACE4(( " endchar" ));
744 close_contour( builder );
746 /* close hints recording session */
749 if (hinter->close( hinter->hints, builder->current->n_points ))
752 /* apply hints to the loaded glyph outline now */
753 hinter->apply( hinter->hints,
755 (PSH_Globals) builder->hints_globals,
756 decoder->hint_mode );
759 /* add current outline to the glyph slot */
760 FT_GlyphLoader_Add( builder->loader );
763 FT_TRACE4(( "\n\n" ));
767 FT_TRACE4(( " hsbw" ));
769 builder->left_bearing.x += top[0];
770 builder->advance.x = top[1];
771 builder->advance.y = 0;
773 orig_x = builder->last.x = x = builder->pos_x + top[0];
774 orig_y = builder->last.y = y = builder->pos_y;
778 /* the `metrics_only' indicates that we only want to compute */
779 /* the glyph's metrics (lsb + advance width), not load the */
780 /* rest of it; so exit immediately */
781 if ( builder->metrics_only )
787 /* return immediately after the processing */
788 return t1operator_seac( decoder, top[0], top[1],
789 top[2], top[3], top[4] );
792 FT_TRACE4(( " sbw" ));
794 builder->left_bearing.x += top[0];
795 builder->left_bearing.y += top[1];
796 builder->advance.x = top[2];
797 builder->advance.y = top[3];
799 builder->last.x = x = builder->pos_x + top[0];
800 builder->last.y = y = builder->pos_y + top[1];
802 /* the `metrics_only' indicates that we only want to compute */
803 /* the glyph's metrics (lsb + advance width), not load the */
804 /* rest of it; so exit immediately */
805 if ( builder->metrics_only )
811 FT_TRACE4(( " closepath" ));
813 close_contour( builder );
814 builder->path_begun = 0;
818 FT_TRACE4(( " hlineto" ));
820 if ( start_point( builder, x, y ) )
827 FT_TRACE4(( " hmoveto" ));
830 if ( !decoder->flex_state )
831 builder->path_begun = 0;
835 FT_TRACE4(( " hvcurveto" ));
837 if ( start_point( builder, x, y ) ||
838 check_points( builder, 3 ) )
842 add_point( builder, x, y, 0 );
845 add_point( builder, x, y, 0 );
847 add_point( builder, x, y, 1 );
851 FT_TRACE4(( " rlineto" ));
853 if ( start_point( builder, x, y ) )
860 if ( add_point1( builder, x, y ) )
865 FT_TRACE4(( " rmoveto" ));
869 if ( !decoder->flex_state )
870 builder->path_begun = 0;
874 FT_TRACE4(( " rcurveto" ));
876 if ( start_point( builder, x, y ) ||
877 check_points( builder, 3 ) )
882 add_point( builder, x, y, 0 );
886 add_point( builder, x, y, 0 );
890 add_point( builder, x, y, 1 );
894 FT_TRACE4(( " vhcurveto" ));
896 if ( start_point( builder, x, y ) ||
897 check_points( builder, 3 ) )
901 add_point( builder, x, y, 0 );
904 add_point( builder, x, y, 0 );
906 add_point( builder, x, y, 1 );
910 FT_TRACE4(( " vlineto" ));
912 if ( start_point( builder, x, y ) )
919 FT_TRACE4(( " vmoveto" ));
922 if ( !decoder->flex_state )
923 builder->path_begun = 0;
927 FT_TRACE4(( " div" ));
931 *top = top[0] / top[1];
936 FT_ERROR(( "t1_decoder_parse_charstrings: division by 0\n" ));
946 FT_TRACE4(( " callsubr" ));
949 if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
951 FT_ERROR(( "t1_decoder_parse_charstrings: "
952 "invalid subrs index\n" ));
956 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
958 FT_ERROR(( "t1_decoder_parse_charstrings: "
959 "too many nested subrs\n" ));
963 zone->cursor = ip; /* save current instruction pointer */
967 /* The Type 1 driver stores subroutines without the seed bytes. */
968 /* The CID driver stores subroutines with seed bytes. This */
969 /* case is taken care of when decoder->subrs_len == 0. */
970 zone->base = decoder->subrs[idx];
972 if ( decoder->subrs_len )
973 zone->limit = zone->base + decoder->subrs_len[idx];
976 /* We are using subroutines from a CID font. We must adjust */
977 /* for the seed bytes. */
978 zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
979 zone->limit = decoder->subrs[idx + 1];
982 zone->cursor = zone->base;
986 FT_ERROR(( "t1_decoder_parse_charstrings: "
987 "invoking empty subrs!\n" ));
991 decoder->zone = zone;
998 FT_TRACE4(( " pop" ));
1000 /* theoretically, the arguments are already on the stack */
1005 FT_TRACE4(( " return" ));
1007 if ( zone <= decoder->zones )
1009 FT_ERROR(( "t1_decoder_parse_charstrings: unexpected return\n" ));
1015 limit = zone->limit;
1016 decoder->zone = zone;
1020 FT_TRACE4(( " dotsection" ));
1025 FT_TRACE4(( " hstem" ));
1027 /* record horizontal hint */
1030 /* top[0] += builder->left_bearing.y; */
1031 hinter->stem( hinter->hints, 1, top );
1037 FT_TRACE4(( " hstem3" ));
1039 /* record horizontal counter-controlled hints */
1041 hinter->stem3( hinter->hints, 1, top );
1046 FT_TRACE4(( " vstem" ));
1048 /* record vertical hint */
1052 hinter->stem( hinter->hints, 0, top );
1058 FT_TRACE4(( " vstem3" ));
1060 /* record vertical counter-controlled hints */
1069 hinter->stem3( hinter->hints, 0, top );
1073 case op_setcurrentpoint:
1074 FT_TRACE4(( " setcurrentpoint" ));
1076 FT_ERROR(( "t1_decoder_parse_charstrings: " ));
1077 FT_ERROR(( "unexpected `setcurrentpoint'\n" ));
1081 FT_ERROR(( "t1_decoder_parse_charstrings: "
1082 "unhandled opcode %d\n", op ));
1088 } /* general operator processing */
1090 } /* while ip < limit */
1092 FT_TRACE4(( "..end..\n\n" ));
1097 return PSaux_Err_Syntax_Error;
1100 return PSaux_Err_Stack_Underflow;
1103 return builder->error;
1107 /* parse a single Type 1 glyph */
1108 FT_LOCAL_DEF( FT_Error )
1109 t1_decoder_parse_glyph( T1_Decoder decoder,
1112 return decoder->parse_callback( decoder, glyph );
1116 /* initialize T1 decoder */
1117 FT_LOCAL_DEF( FT_Error )
1118 t1_decoder_init( T1_Decoder decoder,
1122 FT_Byte** glyph_names,
1125 FT_Render_Mode hint_mode,
1126 T1_Decoder_Callback parse_callback )
1128 FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
1130 /* retrieve PSNames interface from list of current modules */
1132 PSNames_Service psnames = 0;
1135 psnames = (PSNames_Service)FT_Get_Module_Interface(
1136 FT_FACE_LIBRARY(face), "psnames" );
1139 FT_ERROR(( "t1_decoder_init: " ));
1140 FT_ERROR(( "the `psnames' module is not available\n" ));
1141 return PSaux_Err_Unimplemented_Feature;
1144 decoder->psnames = psnames;
1147 t1_builder_init( &decoder->builder, face, size, slot, hinting );
1149 decoder->num_glyphs = (FT_UInt)face->num_glyphs;
1150 decoder->glyph_names = glyph_names;
1151 decoder->hint_flags = face->internal->hint_flags;
1152 decoder->hint_mode = hint_mode;
1153 decoder->blend = blend;
1154 decoder->parse_callback = parse_callback;
1156 decoder->funcs = t1_decoder_funcs;
1162 /* finalize T1 decoder */
1163 FT_LOCAL_DEF( void )
1164 t1_decoder_done( T1_Decoder decoder )
1166 t1_builder_done( &decoder->builder );