1 /***************************************************************************/
5 /* CID-keyed Type1 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
26 #include <cid/cidload.h>
27 #include <cid/cidgload.h>
32 #include <freetype/internal/ftdebug.h>
33 #include <freetype/internal/ftstream.h>
34 #include <freetype/ftoutln.h>
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_cidgload
49 FT_Error
cid_load_glyph( CID_Decoder
* decoder
,
50 FT_UInt glyph_index
);
53 typedef enum CID_Operator_
87 op_max
/* never remove this one */
92 const FT_Int t1_args_count
[op_max
] =
119 -1, /* callothersubr */
123 2 /* setcurrentpoint */
127 /*************************************************************************/
128 /*************************************************************************/
129 /*************************************************************************/
130 /********** *********/
131 /********** *********/
132 /********** GENERIC CHARSTRING PARSING *********/
133 /********** *********/
134 /********** *********/
135 /*************************************************************************/
136 /*************************************************************************/
137 /*************************************************************************/
140 /*************************************************************************/
143 /* CID_Init_Builder */
146 /* Initializes a given glyph builder. */
149 /* builder :: A pointer to the glyph builder to initialize. */
152 /* face :: The current face object. */
154 /* size :: The current size object. */
156 /* glyph :: The current glyph object. */
159 void CID_Init_Builder( CID_Builder
* builder
,
162 CID_GlyphSlot glyph
)
164 builder
->path_begun
= 0;
165 builder
->load_points
= 1;
167 builder
->face
= face
;
168 builder
->glyph
= glyph
;
169 builder
->memory
= face
->root
.memory
;
173 FT_GlyphLoader
* loader
= glyph
->root
.loader
;
176 builder
->loader
= loader
;
177 builder
->base
= &loader
->base
.outline
;
178 builder
->current
= &loader
->current
.outline
;
180 FT_GlyphLoader_Rewind( loader
);
185 builder
->scale_x
= size
->root
.metrics
.x_scale
;
186 builder
->scale_y
= size
->root
.metrics
.y_scale
;
192 builder
->left_bearing
.x
= 0;
193 builder
->left_bearing
.y
= 0;
194 builder
->advance
.x
= 0;
195 builder
->advance
.y
= 0;
200 /*************************************************************************/
203 /* CID_Done_Builder */
206 /* Finalizes a given glyph builder. Its contents can still be used */
207 /* after the call, but the function saves important information */
208 /* within the corresponding glyph slot. */
211 /* builder :: A pointer to the glyph builder to finalize. */
214 void CID_Done_Builder( CID_Builder
* builder
)
216 CID_GlyphSlot glyph
= builder
->glyph
;
220 glyph
->root
.outline
= *builder
->base
;
224 /*************************************************************************/
227 /* CID_Init_Decoder */
230 /* Initializes a given glyph decoder. */
233 /* decoder :: A pointer to the glyph builder to initialize. */
236 void CID_Init_Decoder( CID_Decoder
* decoder
)
238 MEM_Set( decoder
, 0, sizeof ( *decoder
) );
240 decoder
->font_matrix
.xx
= 0x10000L
;
241 decoder
->font_matrix
.yy
= 0x10000L
;
245 /* check that there is enough space for `count' more points */
247 FT_Error
check_points( CID_Builder
* builder
,
250 return FT_GlyphLoader_Check_Points( builder
->loader
, count
, 0 );
254 /* add a new point, but do not check space */
256 void add_point( CID_Builder
* builder
,
261 FT_Outline
* outline
= builder
->current
;
264 if ( builder
->load_points
)
266 FT_Vector
* point
= outline
->points
+ outline
->n_points
;
267 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
;
272 *control
= flag
? FT_Curve_Tag_On
: FT_Curve_Tag_Cubic
;
274 builder
->last
= *point
;
281 /* check space for a new on-curve point, then add it */
283 FT_Error
add_point1( CID_Builder
* builder
,
290 error
= check_points( builder
, 1 );
292 add_point( builder
, x
, y
, 1 );
298 /* check room for a new contour, then add it */
300 FT_Error
add_contour( CID_Builder
* builder
)
302 FT_Outline
* outline
= builder
->current
;
306 if ( !builder
->load_points
)
308 outline
->n_contours
++;
312 error
= FT_GlyphLoader_Check_Points( builder
->loader
, 0, 1 );
315 if ( outline
->n_contours
> 0 )
316 outline
->contours
[outline
->n_contours
- 1] = outline
->n_points
- 1;
318 outline
->n_contours
++;
324 /* if a path has been started, add its first on-curve point */
326 FT_Error
start_point( CID_Builder
* builder
,
330 /* test whether we are building a new contour */
331 if ( !builder
->path_begun
)
336 builder
->path_begun
= 1;
337 error
= add_contour( builder
);
342 return add_point1( builder
, x
, y
);
346 /* close the current contour */
348 void close_contour( CID_Builder
* builder
)
350 FT_Outline
* outline
= builder
->current
;
353 /* XXX: We must not include the last point in the path if it */
354 /* is located on the first point. */
355 if ( outline
->n_points
> 1 )
358 FT_Vector
* p1
= outline
->points
+ first
;
359 FT_Vector
* p2
= outline
->points
+ outline
->n_points
- 1;
362 if ( outline
->n_contours
> 1 )
364 first
= outline
->contours
[outline
->n_contours
- 2] + 1;
365 p1
= outline
->points
+ first
;
368 if ( p1
->x
== p2
->x
&& p1
->y
== p2
->y
)
372 if ( outline
->n_contours
> 0 )
373 outline
->contours
[outline
->n_contours
- 1] = outline
->n_points
- 1;
380 /*************************************************************************/
383 /* lookup_glyph_by_stdcharcode */
386 /* Looks up a given glyph by its StandardEncoding charcode. Used */
387 /* to implement the SEAC Type 1 operator. */
390 /* face :: The current face object. */
392 /* charcode :: The character code to look for. */
395 /* A glyph index in the font face. Returns -1 if the corresponding */
396 /* glyph wasn't found. */
399 FT_Int
lookup_glyph_by_stdcharcode( CID_Face face
,
403 const FT_String
* glyph_name
;
404 PSNames_Interface
* psnames
= (PSNames_Interface
*)face
->psnames
;
407 /* check range of standard char code */
408 if ( charcode
< 0 || charcode
> 255 )
411 glyph_name
= psnames
->adobe_std_strings(
412 psnames
->adobe_std_encoding
[charcode
]);
414 for ( n
= 0; n
< face
->cid
.cid_count
; n
++ )
416 FT_String
* name
= (FT_String
*)face
->type1
.glyph_names
[n
];
419 if ( name
&& strcmp( name
, glyph_name
) == 0 )
430 /*************************************************************************/
433 /* t1operator_seac */
436 /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
439 /* decoder :: The current CID decoder. */
441 /* asb :: The accent's side bearing. */
443 /* adx :: The horizontal offset of the accent. */
445 /* ady :: The vertical offset of the accent. */
447 /* bchar :: The base character's StandardEncoding charcode. */
449 /* achar :: The accent character's StandardEncoding charcode. */
452 /* FreeType error code. 0 means success. */
455 FT_Error
t1operator_seac( CID_Decoder
* decoder
,
463 FT_Int bchar_index
, achar_index
, n_base_points
;
464 FT_Outline
* base
= decoder
->builder
.base
;
465 FT_Vector left_bearing
, advance
;
471 if ( bchar_index
< 0 || achar_index
< 0 )
473 FT_ERROR(( "t1operator_seac:" ));
474 FT_ERROR(( " invalid seac character code arguments\n" ));
475 return T1_Err_Syntax_Error
;
478 /* if we are trying to load a composite glyph, do not load the */
479 /* accent character and return the array of subglyphs. */
480 if ( decoder
->builder
.no_recurse
)
482 FT_GlyphSlot glyph
= (FT_GlyphSlot
)decoder
->builder
.glyph
;
483 FT_GlyphLoader
* loader
= glyph
->loader
;
487 /* reallocate subglyph array if necessary */
488 error
= FT_GlyphLoader_Check_Subglyphs( loader
, 2 );
492 subg
= loader
->current
.subglyphs
;
494 /* subglyph 0 = base character */
495 subg
->index
= bchar_index
;
496 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
|
497 FT_SUBGLYPH_FLAG_USE_MY_METRICS
;
502 /* subglyph 1 = accent character */
503 subg
->index
= achar_index
;
504 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
;
505 subg
->arg1
= adx
- asb
;
508 /* set up remaining glyph fields */
509 glyph
->num_subglyphs
= 2;
510 glyph
->subglyphs
= loader
->current
.subglyphs
;
511 glyph
->format
= ft_glyph_format_composite
;
513 loader
->current
.num_subglyphs
= 2;
516 /* First load `bchar' in builder */
517 /* now load the unscaled outline */
518 if ( decoder
->builder
.loader
)
519 FT_GlyphLoader_Prepare( decoder
->builder
.loader
);
521 error
= cid_load_glyph( decoder
, bchar_index
); /* load one glyph */
525 n_base_points
= base
->n_points
;
528 /* save the left bearing and width of the base character */
529 /* as they will be erased by the next load. */
531 left_bearing
= decoder
->builder
.left_bearing
;
532 advance
= decoder
->builder
.advance
;
534 decoder
->builder
.left_bearing
.x
= 0;
535 decoder
->builder
.left_bearing
.y
= 0;
537 /* Now load `achar' on top of */
538 /* the base outline */
539 error
= cid_load_glyph( decoder
, achar_index
);
543 /* restore the left side bearing and */
544 /* advance width of the base character */
546 decoder
->builder
.left_bearing
= left_bearing
;
547 decoder
->builder
.advance
= advance
;
549 /* Finally, move the accent */
550 if ( decoder
->builder
.load_points
)
555 dummy
.n_points
= base
->n_points
- n_base_points
;
556 dummy
.points
= base
->points
+ n_base_points
;
557 FT_Outline_Translate( &dummy
, adx
- asb
, ady
);
566 #define USE_ARGS( n ) do \
569 if ( top < decoder->stack ) \
570 goto Stack_Underflow; \
574 /*************************************************************************/
577 /* CID_Parse_CharStrings */
580 /* Parses a given CID charstrings program. */
583 /* decoder :: The current CID decoder. */
586 /* charstring_base :: The base of the charstring stream. */
588 /* charstring_len :: The length in bytes of the charstring stream. */
591 /* FreeType error code. 0 means success. */
594 FT_Error
CID_Parse_CharStrings( CID_Decoder
* decoder
,
595 FT_Byte
* charstring_base
,
596 FT_Int charstring_len
)
599 CID_Decoder_Zone
* zone
;
602 CID_Builder
* builder
= &decoder
->builder
;
607 /* First of all, initialize the decoder */
608 decoder
->top
= decoder
->stack
;
609 decoder
->zone
= decoder
->zones
;
610 zone
= decoder
->zones
;
612 builder
->path_begun
= 0;
614 zone
->base
= charstring_base
;
615 limit
= zone
->limit
= charstring_base
+ charstring_len
;
616 ip
= zone
->cursor
= zone
->base
;
619 outline
= builder
->current
;
624 /* now, execute loop */
627 FT_Int
* top
= decoder
->top
;
628 CID_Operator op
= op_none
;
632 /********************************************************************/
634 /* Decode operator or operand */
637 /* First of all, decompress operator or value */
696 FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+EOF)\n" ));
721 op
= op_callothersubr
;
727 op
= op_setcurrentpoint
;
731 FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n",
737 case 255: /* four bytes integer */
738 if ( ip
+ 4 > limit
)
740 FT_ERROR(( "CID_Parse_CharStrings: unexpected EOF in integer\n" ));
744 value
= ( (long)ip
[0] << 24 ) |
745 ( (long)ip
[1] << 16 ) |
746 ( (long)ip
[2] << 8 ) |
755 value
= (long)ip
[-1] - 139;
760 FT_ERROR(( "CID_Parse_CharStrings:" ));
761 FT_ERROR(( " unexpected EOF in integer\n" ));
766 value
= ( (long)( ip
[-2] - 247 ) << 8 ) + ip
[-1] + 108;
768 value
= -( ( ( (long)ip
[-2] - 251 ) << 8 ) + ip
[-1] + 108 );
773 FT_ERROR(( "CID_Parse_CharStrings: invalid byte (%d)\n",
779 /********************************************************************/
781 /* Push value on stack, or process operator */
785 if ( top
- decoder
->stack
>= T1_MAX_CHARSTRINGS_OPERANDS
)
787 FT_ERROR(( "CID_Parse_CharStrings: Stack overflow!\n" ));
791 FT_TRACE4(( " %ld", value
));
795 else if ( op
== op_callothersubr
) /* callothersubr */
797 FT_TRACE4(( " callothersubr" ));
799 if ( top
- decoder
->stack
< 2 )
800 goto Stack_Underflow
;
805 case 1: /* start flex feature ---------------------- */
807 goto Unexpected_OtherSubr
;
809 decoder
->flex_state
= 1;
810 decoder
->num_flex_vectors
= 0;
811 if ( start_point( builder
, x
, y
) ||
812 check_points( builder
, 6 ) )
816 case 2: /* add flex vectors ------------------------ */
822 goto Unexpected_OtherSubr
;
824 /* note that we should not add a point for index 0. */
825 /* this will move our current position to the flex */
826 /* point without adding any point to the outline */
827 index
= decoder
->num_flex_vectors
++;
828 if ( index
> 0 && index
< 7 )
832 (FT_Byte
)( index
==3 || index
==6 ) );
836 case 0: /* end flex feature ------------------------- */
838 goto Unexpected_OtherSubr
;
840 if ( decoder
->flex_state
== 0 ||
841 decoder
->num_flex_vectors
!= 7 )
843 FT_ERROR(( "CID_Parse_CharStrings: unexpected flex end\n" ));
847 /* now consume the remaining `pop pop setcurpoint' */
848 if ( ip
+ 6 > limit
||
849 ip
[0] != 12 || ip
[1] != 17 || /* pop */
850 ip
[2] != 12 || ip
[3] != 17 || /* pop */
851 ip
[4] != 12 || ip
[5] != 33 ) /* setcurpoint */
853 FT_ERROR(( "CID_Parse_CharStrings: invalid flex charstring\n" ));
858 decoder
->flex_state
= 0;
861 case 3: /* change hints ---------------------------- */
863 goto Unexpected_OtherSubr
;
865 /* eat the following `pop' */
866 if ( ip
+ 2 > limit
)
868 FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n",
873 if ( ip
[0] != 12 || ip
[1] != 17 )
875 FT_ERROR(( "CID_Parse_CharStrings:" ));
876 FT_ERROR(( " `pop' expected, found (%d %d)\n",
885 /* counter control hints, clear stack */
886 top
= decoder
->stack
;
895 case 18: /* multiple masters */
897 T1_Blend
* blend
= decoder
->blend
;
898 FT_UInt num_points
, nn
, mm
;
905 FT_ERROR(( "CID_Parse_CharStrings:" ));
906 FT_ERROR(( " unexpected multiple masters operator!\n" ));
910 num_points
= top
[1] - 13 + ( top
[1] == 18 );
911 if ( top
[0] != num_points
* blend
->num_designs
)
913 FT_ERROR(( "CID_Parse_CharStrings:" ));
914 FT_ERROR(( " incorrect number of mm arguments\n" ));
918 top
-= blend
->num_designs
* num_points
;
919 if ( top
< decoder
->stack
)
920 goto Stack_Underflow
;
922 /* We want to compute: */
924 /* a0*w0 + a1*w1 + ... + ak*wk */
926 /* but we only have the a0, a1-a0, a2-a0, .. ak-a0. */
927 /* However, given that w0 + w1 + ... + wk == 1, we can */
928 /* rewrite it easily as: */
930 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
932 /* where k == num_designs-1 */
934 /* I guess that's why it's written in this `compact' */
937 delta
= top
+ num_points
;
939 for ( nn
= 0; nn
< num_points
; nn
++ )
941 FT_Int x
= values
[0];
944 for ( mm
= 1; mm
< blend
->num_designs
; mm
++ )
945 x
+= FT_MulFix( *delta
++, blend
->weight_vector
[mm
] );
949 /* note that `top' will be incremented later by calls to `pop' */
956 Unexpected_OtherSubr
:
957 FT_ERROR(( "CID_Parse_CharStrings: invalid othersubr [%d %d]!\n",
963 else /* general operator */
965 FT_Int num_args
= t1_args_count
[op
];
968 if ( top
- decoder
->stack
< num_args
)
969 goto Stack_Underflow
;
976 FT_TRACE4(( " endchar" ));
978 close_contour( builder
);
980 /* add current outline to the glyph slot */
981 FT_GlyphLoader_Add( builder
->loader
);
984 FT_TRACE4(( "\n\n" ));
988 FT_TRACE4(( " hsbw" ));
990 builder
->left_bearing
.x
+= top
[0];
991 builder
->advance
.x
= top
[1];
992 builder
->advance
.y
= 0;
994 builder
->last
.x
= x
= top
[0];
995 builder
->last
.y
= y
= 0;
997 /* The `metrics_only' indicates that we only want to compute */
998 /* the glyph's metrics (lsb + advance width), not load the */
999 /* rest of it. So exit immediately. */
1000 if ( builder
->metrics_only
)
1006 /* return immediately after processing */
1007 return t1operator_seac( decoder
, top
[0], top
[1],
1008 top
[2], top
[3], top
[4] );
1011 FT_TRACE4(( " sbw" ));
1013 builder
->left_bearing
.x
+= top
[0];
1014 builder
->left_bearing
.y
+= top
[1];
1015 builder
->advance
.x
= top
[2];
1016 builder
->advance
.y
= top
[3];
1018 builder
->last
.x
= x
= top
[0];
1019 builder
->last
.y
= y
= top
[1];
1021 /* The `metrics_only' indicates that we only want to compute */
1022 /* the glyph's metrics (lsb + advance width), not load the */
1023 /* rest of it. So exit immediately. */
1024 if ( builder
->metrics_only
)
1030 FT_TRACE4(( " closepath" ));
1032 close_contour( builder
);
1033 builder
->path_begun
= 0;
1037 FT_TRACE4(( " hlineto" ));
1039 if ( start_point( builder
, x
, y
) )
1046 FT_TRACE4(( " hmoveto" ));
1052 FT_TRACE4(( " hvcurveto" ));
1054 if ( start_point( builder
, x
, y
) ||
1055 check_points( builder
, 3 ) )
1059 add_point( builder
, x
, y
, 0 );
1063 add_point( builder
, x
, y
, 0 );
1066 add_point( builder
, x
, y
, 1 );
1071 FT_TRACE4(( " rlineto" ));
1073 if ( start_point( builder
, x
, y
) )
1080 if ( add_point1( builder
, x
, y
) )
1085 FT_TRACE4(( " rmoveto" ));
1092 FT_TRACE4(( " rcurveto" ));
1094 if ( start_point( builder
, x
, y
) ||
1095 check_points( builder
, 3 ) )
1100 add_point( builder
, x
, y
, 0 );
1104 add_point( builder
, x
, y
, 0 );
1108 add_point( builder
, x
, y
, 1 );
1113 FT_TRACE4(( " vhcurveto" ));
1115 if ( start_point( builder
, x
, y
) ||
1116 check_points( builder
, 3 ) )
1120 add_point( builder
, x
, y
, 0 );
1124 add_point( builder
, x
, y
, 0 );
1127 add_point( builder
, x
, y
, 1 );
1132 FT_TRACE4(( " vlineto" ));
1134 if ( start_point( builder
, x
, y
) )
1141 FT_TRACE4(( " vmoveto" ));
1147 FT_TRACE4(( " div" ));
1151 *top
= top
[0] / top
[1];
1156 FT_ERROR(( "CID_Parse_CharStrings: division by 0\n" ));
1166 FT_TRACE4(( " callsubr" ));
1169 if ( index
< 0 || index
>= (FT_Int
)decoder
->subrs
->num_subrs
)
1171 FT_ERROR(( "CID_Parse_CharStrings: invalid subrs index\n" ));
1175 if ( zone
- decoder
->zones
>= T1_MAX_SUBRS_CALLS
)
1177 FT_ERROR(( "CID_Parse_CharStrings: too many nested subrs\n" ));
1181 zone
->cursor
= ip
; /* save current instruction pointer */
1184 zone
->base
= decoder
->subrs
->code
[index
] + decoder
->lenIV
;
1185 zone
->limit
= decoder
->subrs
->code
[index
+ 1];
1186 zone
->cursor
= zone
->base
;
1190 FT_ERROR(( "CID_Parse_CharStrings: invoking empty subrs!\n" ));
1194 decoder
->zone
= zone
;
1196 limit
= zone
->limit
;
1201 FT_TRACE4(( " pop" ));
1203 /* theoretically, the arguments are already on the stack */
1208 FT_TRACE4(( " return" ));
1210 if ( zone
<= decoder
->zones
)
1212 FT_ERROR(( "CID_Parse_CharStrings: unexpected return\n" ));
1218 limit
= zone
->limit
;
1219 decoder
->zone
= zone
;
1224 FT_TRACE4(( " dotsection" ));
1229 FT_TRACE4(( " hstem" ));
1234 FT_TRACE4(( " hstem3" ));
1239 FT_TRACE4(( " vstem" ));
1244 FT_TRACE4(( " vstem3" ));
1248 case op_setcurrentpoint
:
1249 FT_TRACE4(( " setcurrentpoint" ));
1251 FT_ERROR(( "CID_Parse_CharStrings:" ));
1252 FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
1256 FT_ERROR(( "CID_Parse_CharStrings: unhandled opcode %d\n", op
));
1262 } /* general operator processing */
1264 } /* while ip < limit */
1266 FT_TRACE4(( "..end..\n\n" ));
1271 return T1_Err_Syntax_Error
;
1274 return T1_Err_Stack_Underflow
;
1277 return builder
->error
;
1284 /*************************************************************************/
1285 /*************************************************************************/
1286 /*************************************************************************/
1287 /********** *********/
1288 /********** *********/
1289 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
1290 /********** *********/
1291 /********** The following code is in charge of computing *********/
1292 /********** the maximum advance width of the font. It *********/
1293 /********** quickly processes each glyph charstring to *********/
1294 /********** extract the value from either a `sbw' or `seac' *********/
1295 /********** operator. *********/
1296 /********** *********/
1297 /*************************************************************************/
1298 /*************************************************************************/
1299 /*************************************************************************/
1303 FT_Error
CID_Compute_Max_Advance( CID_Face face
,
1304 FT_Int
* max_advance
)
1307 CID_Decoder decoder
;
1313 /* Initialize load decoder */
1314 CID_Init_Decoder( &decoder
);
1315 CID_Init_Builder( &decoder
.builder
, face
, 0, 0 );
1317 decoder
.builder
.metrics_only
= 1;
1318 decoder
.builder
.load_points
= 0;
1320 /* for each glyph, parse the glyph charstring and extract */
1321 /* the advance width */
1322 for ( glyph_index
= 0; glyph_index
< face
->root
.num_glyphs
;
1325 /* now get load the unscaled outline */
1326 error
= cid_load_glyph( &decoder
, glyph_index
);
1327 /* ignore the error if one occurred - skip to next glyph */
1330 *max_advance
= decoder
.builder
.advance
.x
;
1339 /*************************************************************************/
1340 /*************************************************************************/
1341 /*************************************************************************/
1342 /********** *********/
1343 /********** *********/
1344 /********** UNHINTED GLYPH LOADER *********/
1345 /********** *********/
1346 /********** The following code is in charge of loading a *********/
1347 /********** single outline. It completely ignores hinting *********/
1348 /********** and is used when FT_LOAD_NO_HINTING is set. *********/
1349 /********** *********/
1350 /*************************************************************************/
1351 /*************************************************************************/
1352 /*************************************************************************/
1356 FT_Error
cid_load_glyph( CID_Decoder
* decoder
,
1357 FT_UInt glyph_index
)
1359 CID_Face face
= decoder
->builder
.face
;
1360 CID_Info
* cid
= &face
->cid
;
1362 FT_UInt entry_len
= cid
->fd_bytes
+ cid
->gd_bytes
;
1364 FT_ULong off1
, glyph_len
;
1365 FT_Stream stream
= face
->root
.stream
;
1369 /* read the CID font dict index and charstring offset from the CIDMap */
1370 if ( FILE_Seek( cid
->data_offset
+ cid
->cidmap_offset
+
1371 glyph_index
* entry_len
) ||
1372 ACCESS_Frame( 2 * entry_len
) )
1375 p
= (FT_Byte
*)stream
->cursor
;
1376 fd_select
= (FT_UInt
) cid_get_offset( &p
, (FT_Byte
)cid
->fd_bytes
);
1377 off1
= (FT_ULong
)cid_get_offset( &p
, (FT_Byte
)cid
->gd_bytes
);
1379 glyph_len
= cid_get_offset( &p
, (FT_Byte
)cid
->gd_bytes
) - off1
;
1383 /* now, if the glyph is not empty, set up the subrs array, and parse */
1384 /* the charstrings */
1385 if ( glyph_len
> 0 )
1388 FT_Byte
* charstring
;
1390 FT_Memory memory
= face
->root
.memory
;
1394 decoder
->subrs
= face
->subrs
+ fd_select
;
1396 /* setup font matrix */
1397 dict
= cid
->font_dicts
+ fd_select
;
1398 decoder
->font_matrix
= dict
->font_matrix
;
1399 lenIV
= dict
->private_dict
.lenIV
;
1400 decoder
->lenIV
= lenIV
;
1402 /* the charstrings are encoded (stupid!) */
1403 /* load the charstrings, then execute it */
1405 if ( ALLOC( charstring
, glyph_len
) )
1408 if ( !FILE_Read_At( cid
->data_offset
+ off1
, charstring
, glyph_len
) )
1410 cid_decrypt( charstring
, glyph_len
, 4330 );
1411 error
= CID_Parse_CharStrings( decoder
,
1413 glyph_len
- lenIV
);
1425 FT_Error
CID_Load_Glyph( CID_GlyphSlot glyph
,
1431 CID_Decoder decoder
;
1432 CID_Face face
= (CID_Face
)glyph
->root
.face
;
1436 if ( load_flags
& FT_LOAD_NO_RECURSE
)
1437 load_flags
|= FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
1439 glyph
->x_scale
= size
->root
.metrics
.x_scale
;
1440 glyph
->y_scale
= size
->root
.metrics
.y_scale
;
1442 glyph
->root
.outline
.n_points
= 0;
1443 glyph
->root
.outline
.n_contours
= 0;
1445 hinting
= ( load_flags
& FT_LOAD_NO_SCALE
) == 0 &&
1446 ( load_flags
& FT_LOAD_NO_HINTING
) == 0;
1448 glyph
->root
.format
= ft_glyph_format_outline
;
1451 CID_Init_Decoder( &decoder
);
1452 CID_Init_Builder( &decoder
.builder
, face
, size
, glyph
);
1454 /* set up the decoder */
1455 decoder
.builder
.no_recurse
=
1456 (FT_Bool
)( load_flags
& FT_LOAD_NO_RECURSE
);
1458 error
= cid_load_glyph( &decoder
, glyph_index
);
1460 /* save new glyph tables */
1461 CID_Done_Builder( &decoder
.builder
);
1464 /* Now, set the metrics - this is rather simple, as */
1465 /* the left side bearing is the xMin, and the top side */
1466 /* bearing the yMax. */
1469 /* for composite glyphs, return only the left side bearing and the */
1471 if ( load_flags
& FT_LOAD_NO_RECURSE
)
1473 glyph
->root
.metrics
.horiBearingX
= decoder
.builder
.left_bearing
.x
;
1474 glyph
->root
.metrics
.horiAdvance
= decoder
.builder
.advance
.x
;
1479 FT_Glyph_Metrics
* metrics
= &glyph
->root
.metrics
;
1482 /* copy the _unscaled_ advance width */
1483 metrics
->horiAdvance
= decoder
.builder
.advance
.x
;
1485 /* make up vertical metrics */
1486 metrics
->vertBearingX
= 0;
1487 metrics
->vertBearingY
= 0;
1488 metrics
->vertAdvance
= 0;
1490 glyph
->root
.format
= ft_glyph_format_outline
;
1492 glyph
->root
.outline
.flags
&= ft_outline_owner
;
1493 if ( size
&& size
->root
.metrics
.y_ppem
< 24 )
1494 glyph
->root
.outline
.flags
|= ft_outline_high_precision
;
1496 glyph
->root
.outline
.flags
|= ft_outline_reverse_fill
;
1499 glyph
->root
.outline
.second_pass
= TRUE
;
1500 glyph
->root
.outline
.high_precision
= size
->root
.metrics
.y_ppem
< 24;
1501 glyph
->root
.outline
.dropout_mode
= 2;
1504 if ( ( load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1506 /* scale the outline and the metrics */
1508 FT_Outline
* cur
= &glyph
->root
.outline
;
1509 FT_Vector
* vec
= cur
->points
;
1510 FT_Fixed x_scale
= glyph
->x_scale
;
1511 FT_Fixed y_scale
= glyph
->y_scale
;
1514 /* First of all, scale the points */
1515 for ( n
= cur
->n_points
; n
> 0; n
--, vec
++ )
1517 vec
->x
= FT_MulFix( vec
->x
, x_scale
);
1518 vec
->y
= FT_MulFix( vec
->y
, y_scale
);
1521 FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox
);
1523 /* Then scale the metrics */
1524 metrics
->horiAdvance
= FT_MulFix( metrics
->horiAdvance
, x_scale
);
1525 metrics
->vertAdvance
= FT_MulFix( metrics
->vertAdvance
, y_scale
);
1527 metrics
->vertBearingX
= FT_MulFix( metrics
->vertBearingX
, x_scale
);
1528 metrics
->vertBearingY
= FT_MulFix( metrics
->vertBearingY
, y_scale
);
1531 /* apply the font matrix */
1532 FT_Outline_Transform( &glyph
->root
.outline
, &decoder
.font_matrix
);
1534 /* compute the other metrics */
1535 FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox
);
1537 /* grid fit the bounding box if necessary */
1542 cbox
.xMax
= ( cbox
.xMax
+ 63 ) & -64;
1543 cbox
.yMax
= ( cbox
.yMax
+ 63 ) & -64;
1546 metrics
->width
= cbox
.xMax
- cbox
.xMin
;
1547 metrics
->height
= cbox
.yMax
- cbox
.yMin
;
1549 metrics
->horiBearingX
= cbox
.xMin
;
1550 metrics
->horiBearingY
= cbox
.yMax
;