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 <freetype/src/cid/cidload.h>
27 #include <freetype/src/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;