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 <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
;