1 /***************************************************************************/
5 /* Experimental Type 1 Glyph Loader (body). */
7 /* Copyright 1996-2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
19 #ifdef FT_FLAT_COMPILE
25 #include <freetype/src/type1z/z1gload.h>
30 #include <freetype/internal/ftdebug.h>
31 #include <freetype/internal/ftstream.h>
32 #include <freetype/ftoutln.h>
34 #include <string.h> /* for strcmp() */
37 /*************************************************************************/
39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
40 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
41 /* messages during execution. */
44 #define FT_COMPONENT trace_z1gload
47 typedef enum Z1_Operator_
76 op_max /* never remove this one */
81 const FT_Int t1_args_count[op_max] =
104 -1, /* callothersubr */
108 2 /* setcurrentpoint */
112 /*************************************************************************/
113 /*************************************************************************/
114 /*************************************************************************/
115 /********** *********/
116 /********** *********/
117 /********** GENERIC CHARSTRING PARSING *********/
118 /********** *********/
119 /********** *********/
120 /*************************************************************************/
121 /*************************************************************************/
122 /*************************************************************************/
125 /*************************************************************************/
128 /* Z1_Init_Builder */
131 /* Initializes a given glyph builder. */
134 /* builder :: A pointer to the glyph builder to initialize. */
137 /* face :: The current face object. */
139 /* size :: The current size object. */
141 /* glyph :: The current glyph object. */
144 void Z1_Init_Builder( Z1_Builder* builder,
149 builder->path_begun = 0;
150 builder->load_points = 1;
152 builder->face = face;
153 builder->glyph = glyph;
154 builder->memory = face->root.memory;
158 FT_GlyphLoader* loader = glyph->root.loader;
161 builder->loader = loader;
162 builder->current = &loader->current.outline;
163 builder->base = &loader->base.outline;
165 FT_GlyphLoader_Rewind( loader );
170 builder->scale_x = size->root.metrics.x_scale;
171 builder->scale_y = size->root.metrics.y_scale;
177 builder->left_bearing.x = 0;
178 builder->left_bearing.y = 0;
179 builder->advance.x = 0;
180 builder->advance.y = 0;
184 /*************************************************************************/
187 /* Z1_Done_Builder */
190 /* Finalizes a given glyph builder. Its contents can still be used */
191 /* after the call, but the function saves important information */
192 /* within the corresponding glyph slot. */
195 /* builder :: A pointer to the glyph builder to finalize. */
198 void Z1_Done_Builder( Z1_Builder* builder )
200 Z1_GlyphSlot glyph = builder->glyph;
204 glyph->root.outline = *builder->base;
208 /*************************************************************************/
211 /* Z1_Init_Decoder */
214 /* Initializes a given glyph decoder. */
217 /* decoder :: A pointer to the glyph builder to initialize. */
220 void Z1_Init_Decoder( Z1_Decoder* decoder )
224 decoder->flex_state = 0;
225 decoder->num_flex_vectors = 0;
229 MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) );
233 /* check that there is enough space for `count' more points */
235 FT_Error check_points( Z1_Builder* builder,
238 return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
242 /* add a new point; do not check space */
244 void add_point( Z1_Builder* builder,
249 FT_Outline* outline = builder->current;
252 if ( builder->load_points )
254 FT_Vector* point = outline->points + outline->n_points;
255 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
260 *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
262 builder->last = *point;
269 /* check space for a new on-curve point, then add it */
271 FT_Error add_point1( Z1_Builder* builder,
278 error = check_points( builder, 1 );
280 add_point( builder, x, y, 1 );
286 /* check space for a new contour, then add it */
288 FT_Error add_contour( Z1_Builder* builder )
290 FT_Outline* outline = builder->current;
294 if ( !builder->load_points )
296 outline->n_contours++;
300 /* reallocate contours array if necessary */
301 error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
304 if ( outline->n_contours > 0 )
305 outline->contours[outline->n_contours - 1] = outline->n_points - 1;
307 outline->n_contours++;
314 /* if a path was begun, add its first on-curve point */
316 FT_Error start_point( Z1_Builder* builder,
320 /* test whether we are building a new contour */
321 if ( !builder->path_begun )
326 builder->path_begun = 1;
327 error = add_contour( builder );
331 return add_point1( builder, x, y );
335 /* close the current contour */
337 void close_contour( Z1_Builder* builder )
339 FT_Outline* outline = builder->current;
342 /* XXX: we must not include the last point in the path if it */
343 /* is located on the first point */
344 if ( outline->n_points > 1 )
347 FT_Vector* p1 = outline->points + first;
348 FT_Vector* p2 = outline->points + outline->n_points-1;
351 if ( outline->n_contours > 1 )
353 first = outline->contours[outline->n_contours - 2] + 1;
354 p1 = outline->points + first;
357 if ( p1->x == p2->x && p1->y == p2->y )
361 if ( outline->n_contours > 0 )
362 outline->contours[outline->n_contours - 1] = outline->n_points - 1;
366 /*************************************************************************/
369 /* lookup_glyph_by_stdcharcode */
372 /* Looks up a given glyph by its StandardEncoding charcode. Used */
373 /* to implement the SEAC Type 1 operator. */
376 /* face :: The current face object. */
378 /* charcode :: The character code to look for. */
381 /* A glyph index in the font face. Returns -1 if the corresponding */
382 /* glyph wasn't found. */
385 FT_Int lookup_glyph_by_stdcharcode( T1_Face face,
389 const FT_String* glyph_name;
390 PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
393 /* check range of standard char code */
394 if ( charcode < 0 || charcode > 255 )
397 glyph_name = psnames->adobe_std_strings(
398 psnames->adobe_std_encoding[charcode]);
400 for ( n = 0; n < face->type1.num_glyphs; n++ )
402 FT_String* name = (FT_String*)face->type1.glyph_names[n];
405 if ( name && strcmp( name,glyph_name ) == 0 )
413 /*************************************************************************/
416 /* t1operator_seac */
419 /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
422 /* decoder :: The current CID decoder. */
424 /* asb :: The accent's side bearing. */
426 /* adx :: The horizontal offset of the accent. */
428 /* ady :: The vertical offset of the accent. */
430 /* bchar :: The base character's StandardEncoding charcode. */
432 /* achar :: The accent character's StandardEncoding charcode. */
435 /* FreeType error code. 0 means success. */
438 FT_Error t1operator_seac( Z1_Decoder* decoder,
446 FT_Int bchar_index, achar_index, n_base_points;
447 FT_Outline* base = decoder->builder.base;
448 FT_Vector left_bearing, advance;
449 T1_Face face = decoder->builder.face;
450 T1_Font* type1 = &face->type1;
453 bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
454 achar_index = lookup_glyph_by_stdcharcode( face, achar );
456 if ( bchar_index < 0 || achar_index < 0 )
458 FT_ERROR(( "t1operator_seac:" ));
459 FT_ERROR(( " invalid seac character code arguments\n" ));
460 return T1_Err_Syntax_Error;
463 /* if we are trying to load a composite glyph, do not load the */
464 /* accent character and return the array of subglyphs. */
465 if ( decoder->builder.no_recurse )
467 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
468 FT_GlyphLoader* loader = glyph->loader;
472 /* reallocate subglyph array if necessary */
473 error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
477 subg = loader->current.subglyphs;
479 /* subglyph 0 = base character */
480 subg->index = bchar_index;
481 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
482 FT_SUBGLYPH_FLAG_USE_MY_METRICS;
487 /* subglyph 1 = accent character */
488 subg->index = achar_index;
489 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
490 subg->arg1 = adx - asb;
493 /* set up remaining glyph fields */
494 glyph->num_subglyphs = 2;
495 glyph->subglyphs = loader->base.subglyphs;
496 glyph->format = ft_glyph_format_composite;
498 loader->current.num_subglyphs = 2;
501 /* First load `bchar' in builder */
502 /* now load the unscaled outline */
504 FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
506 error = Z1_Parse_CharStrings( decoder,
507 type1->charstrings [bchar_index],
508 type1->charstrings_len[bchar_index],
515 n_base_points = base->n_points;
517 /* save the left bearing and width of the base character */
518 /* as they will be erased by the next load. */
520 left_bearing = decoder->builder.left_bearing;
521 advance = decoder->builder.advance;
523 decoder->builder.left_bearing.x = 0;
524 decoder->builder.left_bearing.y = 0;
526 /* Now load `achar' on top of */
527 /* the base outline */
528 error = Z1_Parse_CharStrings( decoder,
529 type1->charstrings [achar_index],
530 type1->charstrings_len[achar_index],
537 /* restore the left side bearing and */
538 /* advance width of the base character */
540 decoder->builder.left_bearing = left_bearing;
541 decoder->builder.advance = advance;
543 /* Finally, move the accent */
544 if ( decoder->builder.load_points )
549 dummy.n_points = base->n_points - n_base_points;
550 dummy.points = base->points + n_base_points;
551 FT_Outline_Translate( &dummy, adx - asb, ady );
559 #define USE_ARGS( n ) do \
562 if ( top < decoder->stack ) \
563 goto Stack_Underflow; \
567 /*************************************************************************/
570 /* Z1_Parse_CharStrings */
573 /* Parses a given Type 1 charstrings program. */
576 /* decoder :: The current Type 1 decoder. */
578 /* charstring_base :: The base address of the charstring stream. */
580 /* charstring_len :: The length in bytes of the charstring stream. */
582 /* num_subrs :: The number of sub-routines. */
584 /* subrs_base :: An array of sub-routines addresses. */
586 /* subrs_len :: An array of sub-routines lengths. */
589 /* Free error code. 0 means success. */
592 FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder,
593 FT_Byte* charstring_base,
594 FT_Int charstring_len,
596 FT_Byte** subrs_base,
600 Z1_Decoder_Zone* zone;
603 Z1_Builder* builder = &decoder->builder;
608 /* First of all, initialize the decoder */
609 decoder->top = decoder->stack;
610 decoder->zone = decoder->zones;
611 zone = decoder->zones;
613 builder->path_begun = 0;
615 zone->base = charstring_base;
616 limit = zone->limit = charstring_base + charstring_len;
617 ip = zone->cursor = zone->base;
620 outline = builder->current;
625 /* now, execute loop */
628 FT_Int* top = decoder->top;
629 Z1_Operator op = op_none;
633 /*********************************************************************/
635 /* Decode operator or operand */
639 /* first of all, decompress operator or value */
698 FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+EOF)\n" ));
723 op = op_callothersubr;
729 op = op_setcurrentpoint;
733 FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n",
739 case 255: /* four bytes integer */
740 if ( ip + 4 > limit )
742 FT_ERROR(( "Z1_Parse_CharStrings: unexpected EOF in integer\n" ));
746 value = ( (FT_Long)ip[0] << 24 ) |
747 ( (FT_Long)ip[1] << 16 ) |
748 ( (FT_Long)ip[2] << 8 ) |
757 value = (FT_Long)ip[-1] - 139;
762 FT_ERROR(( "Z1_Parse_CharStrings:" ));
763 FT_ERROR(( " unexpected EOF in integer\n" ));
768 value = ( (FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
770 value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
775 FT_ERROR(( "Z1_Parse_CharStrings: invalid byte (%d)\n",
781 /*********************************************************************/
783 /* Push value on stack, or process operator */
788 if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
790 FT_ERROR(( "Z1_Parse_CharStrings: stack overflow!\n" ));
794 FT_TRACE4(( " %ld", value ));
799 else if ( op == op_callothersubr ) /* callothersubr */
801 FT_TRACE4(( " callothersubr" ));
803 if ( top - decoder->stack < 2 )
804 goto Stack_Underflow;
809 case 1: /* start flex feature */
811 goto Unexpected_OtherSubr;
813 decoder->flex_state = 1;
814 decoder->num_flex_vectors = 0;
815 if ( start_point( builder, x, y ) ||
816 check_points( builder, 6 ) )
820 case 2: /* add flex vectors */
825 goto Unexpected_OtherSubr;
827 /* note that we should not add a point for index 0; */
828 /* this will move our current position to the flex */
829 /* point without adding any point to the outline */
830 index = decoder->num_flex_vectors++;
831 if ( index > 0 && index < 7 )
835 (FT_Byte)( index == 3 || index == 6 ) );
839 case 0: /* end flex feature */
841 goto Unexpected_OtherSubr;
843 if ( decoder->flex_state == 0 ||
844 decoder->num_flex_vectors != 7 )
846 FT_ERROR(( "Z1_Parse_CharStrings: unexpected flex end\n" ));
850 /* now consume the remaining `pop pop setcurpoint' */
851 if ( ip + 6 > limit ||
852 ip[0] != 12 || ip[1] != 17 || /* pop */
853 ip[2] != 12 || ip[3] != 17 || /* pop */
854 ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */
856 FT_ERROR(( "Z1_Parse_CharStrings: invalid flex charstring\n" ));
861 decoder->flex_state = 0;
864 case 3: /* change hints */
866 goto Unexpected_OtherSubr;
868 /* eat the following `pop' */
869 if ( ip + 2 > limit )
871 FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n",
876 if ( ip[0] != 12 || ip[1] != 17 )
878 FT_ERROR(( "Z1_Parse_CharStrings:" ));
879 FT_ERROR(( " `pop' expected, found (%d %d)\n",
888 /* counter control hints, clear stack */
889 top = decoder->stack;
896 case 18: /* multiple masters */
898 T1_Blend* blend = decoder->blend;
899 FT_UInt num_points, nn, mm;
906 FT_ERROR(( "Z1_Parse_CharStrings:" ));
907 FT_ERROR(( " unexpected multiple masters operator!\n" ));
911 num_points = top[1] - 13 + ( top[1] == 18 );
912 if ( top[0] != (FT_Int)( num_points * blend->num_designs ) )
914 FT_ERROR(( "Z1_Parse_CharStrings:" ));
915 FT_ERROR(( " incorrect number of mm arguments\n" ));
919 top -= blend->num_designs*num_points;
920 if ( top < decoder->stack )
921 goto Stack_Underflow;
923 /* we want to compute: */
925 /* a0*w0 + a1*w1 + ... + ak*wk */
927 /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */
928 /* however, given that w0 + w1 + ... + wk == 1, we can */
929 /* rewrite it easily as: */
931 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
933 /* where k == num_designs-1 */
935 /* I guess that's why it's written in this `compact' */
938 delta = top + num_points;
940 for ( nn = 0; nn < num_points; nn++ )
942 FT_Int x = values[0];
945 for ( mm = 1; mm < blend->num_designs; mm++ )
946 x += FT_MulFix( *delta++, blend->weight_vector[mm] );
950 /* note that `top' will be incremented later by calls to `pop' */
955 Unexpected_OtherSubr:
956 FT_ERROR(( "Z1_Parse_CharStrings: invalid othersubr [%d %d]!\n",
962 else /* general operator */
964 FT_Int num_args = t1_args_count[op];
967 if ( top - decoder->stack < num_args )
968 goto Stack_Underflow;
975 FT_TRACE4(( " endchar" ));
977 close_contour( builder );
979 /* add current outline to the glyph slot */
980 FT_GlyphLoader_Add( builder->loader );
983 FT_TRACE4(( "\n\n" ));
987 FT_TRACE4(( " hsbw" ));
989 builder->left_bearing.x += top[0];
990 builder->advance.x = top[1];
991 builder->advance.y = 0;
993 builder->last.x = x = top[0];
994 builder->last.y = y = 0;
996 /* the `metrics_only' indicates that we only want to compute */
997 /* the glyph's metrics (lsb + advance width), not load the */
998 /* rest of it; so exit immediately */
999 if ( builder->metrics_only )
1005 /* return immediately after the processing */
1006 return t1operator_seac( decoder, top[0], top[1],
1007 top[2], top[3], top[4] );
1010 FT_TRACE4(( " sbw" ));
1012 builder->left_bearing.x += top[0];
1013 builder->left_bearing.y += top[1];
1014 builder->advance.x = top[2];
1015 builder->advance.y = top[3];
1017 builder->last.x = x = top[0];
1018 builder->last.y = y = top[1];
1020 /* the `metrics_only' indicates that we only want to compute */
1021 /* the glyph's metrics (lsb + advance width), not load the */
1022 /* rest of it; so exit immediately */
1023 if ( builder->metrics_only )
1029 FT_TRACE4(( " closepath" ));
1031 close_contour( builder );
1032 builder->path_begun = 0;
1036 FT_TRACE4(( " hlineto" ));
1038 if ( start_point( builder, x, y ) )
1045 FT_TRACE4(( " hmoveto" ));
1051 FT_TRACE4(( " hvcurveto" ));
1053 if ( start_point( builder, x, y ) ||
1054 check_points( builder, 3 ) )
1058 add_point( builder, x, y, 0 );
1061 add_point( builder, x, y, 0 );
1063 add_point( builder, x, y, 1 );
1067 FT_TRACE4(( " rlineto" ));
1069 if ( start_point( builder, x, y ) )
1076 if ( add_point1( builder, x, y ) )
1081 FT_TRACE4(( " rmoveto" ));
1088 FT_TRACE4(( " rcurveto" ));
1090 if ( start_point( builder, x, y ) ||
1091 check_points( builder, 3 ) )
1096 add_point( builder, x, y, 0 );
1100 add_point( builder, x, y, 0 );
1104 add_point( builder, x, y, 1 );
1108 FT_TRACE4(( " vhcurveto" ));
1110 if ( start_point( builder, x, y ) ||
1111 check_points( builder, 3 ) )
1115 add_point( builder, x, y, 0 );
1118 add_point( builder, x, y, 0 );
1120 add_point( builder, x, y, 1 );
1124 FT_TRACE4(( " vlineto" ));
1126 if ( start_point( builder, x, y ) )
1133 FT_TRACE4(( " vmoveto" ));
1139 FT_TRACE4(( " div" ));
1143 *top = top[0] / top[1];
1148 FT_ERROR(( "Z1_Parse_CharStrings: division by 0\n" ));
1158 FT_TRACE4(( " callsubr" ));
1161 if ( index < 0 || index >= num_subrs )
1163 FT_ERROR(( "Z1_Parse_CharStrings: invalid subrs index\n" ));
1167 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
1169 FT_ERROR(( "Z1_Parse_CharStrings: too many nested subrs\n" ));
1173 zone->cursor = ip; /* save current instruction pointer */
1176 zone->base = subrs_base[index];
1177 zone->limit = zone->base + subrs_len[index];
1178 zone->cursor = zone->base;
1182 FT_ERROR(( "Z1_Parse_CharStrings: invoking empty subrs!\n" ));
1186 decoder->zone = zone;
1188 limit = zone->limit;
1193 FT_TRACE4(( " pop" ));
1195 /* theorically, the arguments are already on the stack */
1200 FT_TRACE4(( " return" ));
1202 if ( zone <= decoder->zones )
1204 FT_ERROR(( "Z1_Parse_CharStrings: unexpected return\n" ));
1210 limit = zone->limit;
1211 decoder->zone = zone;
1215 FT_TRACE4(( " dotsection" ));
1220 FT_TRACE4(( " hstem" ));
1225 FT_TRACE4(( " hstem3" ));
1230 FT_TRACE4(( " vstem" ));
1235 FT_TRACE4(( " vstem3" ));
1239 case op_setcurrentpoint:
1240 FT_TRACE4(( " setcurrentpoint" ));
1242 FT_ERROR(( "Z1_Parse_CharStrings:" ));
1243 FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
1247 FT_ERROR(( "Z1_Parse_CharStrings: unhandled opcode %d\n", op ));
1253 } /* general operator processing */
1255 } /* while ip < limit */
1257 FT_TRACE4(( "..end..\n\n" ));
1261 return T1_Err_Syntax_Error;
1264 return T1_Err_Stack_Underflow;
1267 return builder->error;
1271 /*************************************************************************/
1272 /*************************************************************************/
1273 /*************************************************************************/
1274 /********** *********/
1275 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
1276 /********** *********/
1277 /********** The following code is in charge of computing *********/
1278 /********** the maximum advance width of the font. It *********/
1279 /********** quickly processes each glyph charstring to *********/
1280 /********** extract the value from either a `sbw' or `seac' *********/
1281 /********** operator. *********/
1282 /********** *********/
1283 /*************************************************************************/
1284 /*************************************************************************/
1285 /*************************************************************************/
1289 FT_Error Z1_Compute_Max_Advance( T1_Face face,
1290 FT_Int* max_advance )
1295 T1_Font* type1 = &face->type1;
1300 /* Initialize load decoder */
1301 Z1_Init_Decoder( &decoder );
1302 Z1_Init_Builder( &decoder.builder, face, 0, 0 );
1304 decoder.blend = face->blend;
1305 decoder.builder.metrics_only = 1;
1306 decoder.builder.load_points = 0;
1308 /* for each glyph, parse the glyph charstring and extract */
1309 /* the advance width */
1310 for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
1312 /* now get load the unscaled outline */
1313 error = Z1_Parse_CharStrings( &decoder,
1314 type1->charstrings [glyph_index],
1315 type1->charstrings_len[glyph_index],
1319 /* ignore the error if one occured - skip to next glyph */
1322 *max_advance = decoder.builder.advance.x;
1327 /*************************************************************************/
1328 /*************************************************************************/
1329 /*************************************************************************/
1330 /********** *********/
1331 /********** UNHINTED GLYPH LOADER *********/
1332 /********** *********/
1333 /********** The following code is in charge of loading a *********/
1334 /********** single outline. It completely ignores hinting *********/
1335 /********** and is used when FT_LOAD_NO_HINTING is set. *********/
1336 /********** *********/
1337 /********** The Type 1 hinter is located in `t1hint.c' *********/
1338 /********** *********/
1339 /*************************************************************************/
1340 /*************************************************************************/
1341 /*************************************************************************/
1345 FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph,
1352 T1_Face face = (T1_Face)glyph->root.face;
1354 T1_Font* type1 = &face->type1;
1357 if ( load_flags & FT_LOAD_NO_RECURSE )
1358 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
1360 glyph->x_scale = size->root.metrics.x_scale;
1361 glyph->y_scale = size->root.metrics.y_scale;
1363 glyph->root.outline.n_points = 0;
1364 glyph->root.outline.n_contours = 0;
1366 hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
1367 ( load_flags & FT_LOAD_NO_HINTING ) == 0;
1369 glyph->root.format = ft_glyph_format_outline;
1371 Z1_Init_Decoder( &decoder );
1372 Z1_Init_Builder( &decoder.builder, face, size, glyph );
1374 decoder.blend = ((T1_Face)glyph->root.face)->blend;
1375 decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0;
1377 /* now load the unscaled outline */
1378 error = Z1_Parse_CharStrings( &decoder,
1379 type1->charstrings [glyph_index],
1380 type1->charstrings_len[glyph_index],
1385 /* save new glyph tables */
1386 Z1_Done_Builder( &decoder.builder );
1388 /* now, set the metrics -- this is rather simple, as */
1389 /* the left side bearing is the xMin, and the top side */
1390 /* bearing the yMax */
1393 glyph->root.outline.flags &= ft_outline_owner;
1394 glyph->root.outline.flags |= ft_outline_reverse_fill;
1396 /* for composite glyphs, return only left side bearing and */
1398 if ( load_flags & FT_LOAD_NO_RECURSE )
1400 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
1401 glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
1406 FT_Glyph_Metrics* metrics = &glyph->root.metrics;
1409 /* copy the _unscaled_ advance width */
1410 metrics->horiAdvance = decoder.builder.advance.x;
1412 /* make up vertical metrics */
1413 metrics->vertBearingX = 0;
1414 metrics->vertBearingY = 0;
1415 metrics->vertAdvance = 0;
1417 glyph->root.format = ft_glyph_format_outline;
1419 if ( size && size->root.metrics.y_ppem < 24 )
1420 glyph->root.outline.flags |= ft_outline_high_precision;
1423 glyph->root.outline.second_pass = TRUE;
1424 glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
1425 glyph->root.outline.dropout_mode = 2;
1428 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
1430 /* scale the outline and the metrics */
1432 FT_Outline* cur = decoder.builder.base;
1433 FT_Vector* vec = cur->points;
1434 FT_Fixed x_scale = glyph->x_scale;
1435 FT_Fixed y_scale = glyph->y_scale;
1438 /* First of all, scale the points */
1439 for ( n = cur->n_points; n > 0; n--, vec++ )
1441 vec->x = FT_MulFix( vec->x, x_scale );
1442 vec->y = FT_MulFix( vec->y, y_scale );
1445 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
1447 /* Then scale the metrics */
1448 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
1449 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
1451 metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
1452 metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
1455 /* apply the font matrix */
1456 FT_Outline_Transform( &glyph->root.outline,
1457 &face->type1.font_matrix );
1459 /* compute the other metrics */
1460 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
1462 /* grid fit the bounding box if necessary */
1467 cbox.xMax = ( cbox.xMax+63 ) & -64;
1468 cbox.yMax = ( cbox.yMax+63 ) & -64;
1471 metrics->width = cbox.xMax - cbox.xMin;
1472 metrics->height = cbox.yMax - cbox.yMin;
1474 metrics->horiBearingX = cbox.xMin;
1475 metrics->horiBearingY = cbox.yMax;