Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencffgload.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* cffgload.c */ 00004 /* */ 00005 /* OpenType Glyph Loader (body). */ 00006 /* */ 00007 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ 00008 /* 2010 by */ 00009 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00010 /* */ 00011 /* This file is part of the FreeType project, and may only be used, */ 00012 /* modified, and distributed under the terms of the FreeType project */ 00013 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00014 /* this file you indicate that you have read the license and */ 00015 /* understand and accept it fully. */ 00016 /* */ 00017 /***************************************************************************/ 00018 00019 00020 #include <ft2build.h> 00021 #include FT_INTERNAL_DEBUG_H 00022 #include FT_INTERNAL_STREAM_H 00023 #include FT_INTERNAL_SFNT_H 00024 #include FT_OUTLINE_H 00025 00026 #include "cffobjs.h" 00027 #include "cffload.h" 00028 #include "cffgload.h" 00029 00030 #include "cfferrs.h" 00031 00032 00033 /*************************************************************************/ 00034 /* */ 00035 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00036 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00037 /* messages during execution. */ 00038 /* */ 00039 #undef FT_COMPONENT 00040 #define FT_COMPONENT trace_cffgload 00041 00042 00043 typedef enum CFF_Operator_ 00044 { 00045 cff_op_unknown = 0, 00046 00047 cff_op_rmoveto, 00048 cff_op_hmoveto, 00049 cff_op_vmoveto, 00050 00051 cff_op_rlineto, 00052 cff_op_hlineto, 00053 cff_op_vlineto, 00054 00055 cff_op_rrcurveto, 00056 cff_op_hhcurveto, 00057 cff_op_hvcurveto, 00058 cff_op_rcurveline, 00059 cff_op_rlinecurve, 00060 cff_op_vhcurveto, 00061 cff_op_vvcurveto, 00062 00063 cff_op_flex, 00064 cff_op_hflex, 00065 cff_op_hflex1, 00066 cff_op_flex1, 00067 00068 cff_op_endchar, 00069 00070 cff_op_hstem, 00071 cff_op_vstem, 00072 cff_op_hstemhm, 00073 cff_op_vstemhm, 00074 00075 cff_op_hintmask, 00076 cff_op_cntrmask, 00077 cff_op_dotsection, /* deprecated, acts as no-op */ 00078 00079 cff_op_abs, 00080 cff_op_add, 00081 cff_op_sub, 00082 cff_op_div, 00083 cff_op_neg, 00084 cff_op_random, 00085 cff_op_mul, 00086 cff_op_sqrt, 00087 00088 cff_op_blend, 00089 00090 cff_op_drop, 00091 cff_op_exch, 00092 cff_op_index, 00093 cff_op_roll, 00094 cff_op_dup, 00095 00096 cff_op_put, 00097 cff_op_get, 00098 cff_op_store, 00099 cff_op_load, 00100 00101 cff_op_and, 00102 cff_op_or, 00103 cff_op_not, 00104 cff_op_eq, 00105 cff_op_ifelse, 00106 00107 cff_op_callsubr, 00108 cff_op_callgsubr, 00109 cff_op_return, 00110 00111 /* Type 1 opcodes: invalid but seen in real life */ 00112 cff_op_hsbw, 00113 cff_op_closepath, 00114 cff_op_callothersubr, 00115 cff_op_pop, 00116 cff_op_seac, 00117 cff_op_sbw, 00118 cff_op_setcurrentpoint, 00119 00120 /* do not remove */ 00121 cff_op_max 00122 00123 } CFF_Operator; 00124 00125 00126 #define CFF_COUNT_CHECK_WIDTH 0x80 00127 #define CFF_COUNT_EXACT 0x40 00128 #define CFF_COUNT_CLEAR_STACK 0x20 00129 00130 /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */ 00131 /* used for checking the width and requested numbers of arguments */ 00132 /* only; they are set to zero afterwards */ 00133 00134 /* the other two flags are informative only and unused currently */ 00135 00136 static const FT_Byte cff_argument_counts[] = 00137 { 00138 0, /* unknown */ 00139 00140 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */ 00141 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, 00142 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, 00143 00144 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */ 00145 0 | CFF_COUNT_CLEAR_STACK, 00146 0 | CFF_COUNT_CLEAR_STACK, 00147 00148 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */ 00149 0 | CFF_COUNT_CLEAR_STACK, 00150 0 | CFF_COUNT_CLEAR_STACK, 00151 0 | CFF_COUNT_CLEAR_STACK, 00152 0 | CFF_COUNT_CLEAR_STACK, 00153 0 | CFF_COUNT_CLEAR_STACK, 00154 0 | CFF_COUNT_CLEAR_STACK, 00155 00156 13, /* flex */ 00157 7, 00158 9, 00159 11, 00160 00161 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */ 00162 00163 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */ 00164 2 | CFF_COUNT_CHECK_WIDTH, 00165 2 | CFF_COUNT_CHECK_WIDTH, 00166 2 | CFF_COUNT_CHECK_WIDTH, 00167 00168 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */ 00169 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */ 00170 0, /* dotsection */ 00171 00172 1, /* abs */ 00173 2, 00174 2, 00175 2, 00176 1, 00177 0, 00178 2, 00179 1, 00180 00181 1, /* blend */ 00182 00183 1, /* drop */ 00184 2, 00185 1, 00186 2, 00187 1, 00188 00189 2, /* put */ 00190 1, 00191 4, 00192 3, 00193 00194 2, /* and */ 00195 2, 00196 1, 00197 2, 00198 4, 00199 00200 1, /* callsubr */ 00201 1, 00202 0, 00203 00204 2, /* hsbw */ 00205 0, 00206 0, 00207 0, 00208 5, /* seac */ 00209 4, /* sbw */ 00210 2 /* setcurrentpoint */ 00211 }; 00212 00213 00214 /*************************************************************************/ 00215 /*************************************************************************/ 00216 /*************************************************************************/ 00217 /********** *********/ 00218 /********** *********/ 00219 /********** GENERIC CHARSTRING PARSING *********/ 00220 /********** *********/ 00221 /********** *********/ 00222 /*************************************************************************/ 00223 /*************************************************************************/ 00224 /*************************************************************************/ 00225 00226 00227 /*************************************************************************/ 00228 /* */ 00229 /* <Function> */ 00230 /* cff_builder_init */ 00231 /* */ 00232 /* <Description> */ 00233 /* Initializes a given glyph builder. */ 00234 /* */ 00235 /* <InOut> */ 00236 /* builder :: A pointer to the glyph builder to initialize. */ 00237 /* */ 00238 /* <Input> */ 00239 /* face :: The current face object. */ 00240 /* */ 00241 /* size :: The current size object. */ 00242 /* */ 00243 /* glyph :: The current glyph object. */ 00244 /* */ 00245 /* hinting :: Whether hinting is active. */ 00246 /* */ 00247 static void 00248 cff_builder_init( CFF_Builder* builder, 00249 TT_Face face, 00250 CFF_Size size, 00251 CFF_GlyphSlot glyph, 00252 FT_Bool hinting ) 00253 { 00254 builder->path_begun = 0; 00255 builder->load_points = 1; 00256 00257 builder->face = face; 00258 builder->glyph = glyph; 00259 builder->memory = face->root.memory; 00260 00261 if ( glyph ) 00262 { 00263 FT_GlyphLoader loader = glyph->root.internal->loader; 00264 00265 00266 builder->loader = loader; 00267 builder->base = &loader->base.outline; 00268 builder->current = &loader->current.outline; 00269 FT_GlyphLoader_Rewind( loader ); 00270 00271 builder->hints_globals = 0; 00272 builder->hints_funcs = 0; 00273 00274 if ( hinting && size ) 00275 { 00276 CFF_Internal internal = (CFF_Internal)size->root.internal; 00277 00278 00279 builder->hints_globals = (void *)internal->topfont; 00280 builder->hints_funcs = glyph->root.internal->glyph_hints; 00281 } 00282 } 00283 00284 builder->pos_x = 0; 00285 builder->pos_y = 0; 00286 00287 builder->left_bearing.x = 0; 00288 builder->left_bearing.y = 0; 00289 builder->advance.x = 0; 00290 builder->advance.y = 0; 00291 } 00292 00293 00294 /*************************************************************************/ 00295 /* */ 00296 /* <Function> */ 00297 /* cff_builder_done */ 00298 /* */ 00299 /* <Description> */ 00300 /* Finalizes a given glyph builder. Its contents can still be used */ 00301 /* after the call, but the function saves important information */ 00302 /* within the corresponding glyph slot. */ 00303 /* */ 00304 /* <Input> */ 00305 /* builder :: A pointer to the glyph builder to finalize. */ 00306 /* */ 00307 static void 00308 cff_builder_done( CFF_Builder* builder ) 00309 { 00310 CFF_GlyphSlot glyph = builder->glyph; 00311 00312 00313 if ( glyph ) 00314 glyph->root.outline = *builder->base; 00315 } 00316 00317 00318 /*************************************************************************/ 00319 /* */ 00320 /* <Function> */ 00321 /* cff_compute_bias */ 00322 /* */ 00323 /* <Description> */ 00324 /* Computes the bias value in dependence of the number of glyph */ 00325 /* subroutines. */ 00326 /* */ 00327 /* <Input> */ 00328 /* in_charstring_type :: The `CharstringType' value of the top DICT */ 00329 /* dictionary. */ 00330 /* */ 00331 /* num_subrs :: The number of glyph subroutines. */ 00332 /* */ 00333 /* <Return> */ 00334 /* The bias value. */ 00335 static FT_Int 00336 cff_compute_bias( FT_Int in_charstring_type, 00337 FT_UInt num_subrs ) 00338 { 00339 FT_Int result; 00340 00341 00342 if ( in_charstring_type == 1 ) 00343 result = 0; 00344 else if ( num_subrs < 1240 ) 00345 result = 107; 00346 else if ( num_subrs < 33900U ) 00347 result = 1131; 00348 else 00349 result = 32768U; 00350 00351 return result; 00352 } 00353 00354 00355 /*************************************************************************/ 00356 /* */ 00357 /* <Function> */ 00358 /* cff_decoder_init */ 00359 /* */ 00360 /* <Description> */ 00361 /* Initializes a given glyph decoder. */ 00362 /* */ 00363 /* <InOut> */ 00364 /* decoder :: A pointer to the glyph builder to initialize. */ 00365 /* */ 00366 /* <Input> */ 00367 /* face :: The current face object. */ 00368 /* */ 00369 /* size :: The current size object. */ 00370 /* */ 00371 /* slot :: The current glyph object. */ 00372 /* */ 00373 /* hinting :: Whether hinting is active. */ 00374 /* */ 00375 /* hint_mode :: The hinting mode. */ 00376 /* */ 00377 FT_LOCAL_DEF( void ) 00378 cff_decoder_init( CFF_Decoder* decoder, 00379 TT_Face face, 00380 CFF_Size size, 00381 CFF_GlyphSlot slot, 00382 FT_Bool hinting, 00383 FT_Render_Mode hint_mode ) 00384 { 00385 CFF_Font cff = (CFF_Font)face->extra.data; 00386 00387 00388 /* clear everything */ 00389 FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); 00390 00391 /* initialize builder */ 00392 cff_builder_init( &decoder->builder, face, size, slot, hinting ); 00393 00394 /* initialize Type2 decoder */ 00395 decoder->cff = cff; 00396 decoder->num_globals = cff->global_subrs_index.count; 00397 decoder->globals = cff->global_subrs; 00398 decoder->globals_bias = cff_compute_bias( 00399 cff->top_font.font_dict.charstring_type, 00400 decoder->num_globals ); 00401 00402 decoder->hint_mode = hint_mode; 00403 } 00404 00405 00406 /* this function is used to select the subfont */ 00407 /* and the locals subrs array */ 00408 FT_LOCAL_DEF( FT_Error ) 00409 cff_decoder_prepare( CFF_Decoder* decoder, 00410 CFF_Size size, 00411 FT_UInt glyph_index ) 00412 { 00413 CFF_Builder *builder = &decoder->builder; 00414 CFF_Font cff = (CFF_Font)builder->face->extra.data; 00415 CFF_SubFont sub = &cff->top_font; 00416 FT_Error error = CFF_Err_Ok; 00417 00418 00419 /* manage CID fonts */ 00420 if ( cff->num_subfonts ) 00421 { 00422 FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); 00423 00424 00425 if ( fd_index >= cff->num_subfonts ) 00426 { 00427 FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" )); 00428 error = CFF_Err_Invalid_File_Format; 00429 goto Exit; 00430 } 00431 00432 FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index )); 00433 00434 sub = cff->subfonts[fd_index]; 00435 00436 if ( builder->hints_funcs && size ) 00437 { 00438 CFF_Internal internal = (CFF_Internal)size->root.internal; 00439 00440 00441 /* for CFFs without subfonts, this value has already been set */ 00442 builder->hints_globals = (void *)internal->subfonts[fd_index]; 00443 } 00444 } 00445 #ifdef FT_DEBUG_LEVEL_TRACE 00446 else 00447 FT_TRACE3(( "glyph index %d:\n", glyph_index )); 00448 #endif 00449 00450 decoder->num_locals = sub->local_subrs_index.count; 00451 decoder->locals = sub->local_subrs; 00452 decoder->locals_bias = cff_compute_bias( 00453 decoder->cff->top_font.font_dict.charstring_type, 00454 decoder->num_locals ); 00455 00456 decoder->glyph_width = sub->private_dict.default_width; 00457 decoder->nominal_width = sub->private_dict.nominal_width; 00458 00459 Exit: 00460 return error; 00461 } 00462 00463 00464 /* check that there is enough space for `count' more points */ 00465 static FT_Error 00466 check_points( CFF_Builder* builder, 00467 FT_Int count ) 00468 { 00469 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); 00470 } 00471 00472 00473 /* add a new point, do not check space */ 00474 static void 00475 cff_builder_add_point( CFF_Builder* builder, 00476 FT_Pos x, 00477 FT_Pos y, 00478 FT_Byte flag ) 00479 { 00480 FT_Outline* outline = builder->current; 00481 00482 00483 if ( builder->load_points ) 00484 { 00485 FT_Vector* point = outline->points + outline->n_points; 00486 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; 00487 00488 00489 point->x = x >> 16; 00490 point->y = y >> 16; 00491 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); 00492 } 00493 00494 outline->n_points++; 00495 } 00496 00497 00498 /* check space for a new on-curve point, then add it */ 00499 static FT_Error 00500 cff_builder_add_point1( CFF_Builder* builder, 00501 FT_Pos x, 00502 FT_Pos y ) 00503 { 00504 FT_Error error; 00505 00506 00507 error = check_points( builder, 1 ); 00508 if ( !error ) 00509 cff_builder_add_point( builder, x, y, 1 ); 00510 00511 return error; 00512 } 00513 00514 00515 /* check space for a new contour, then add it */ 00516 static FT_Error 00517 cff_builder_add_contour( CFF_Builder* builder ) 00518 { 00519 FT_Outline* outline = builder->current; 00520 FT_Error error; 00521 00522 00523 if ( !builder->load_points ) 00524 { 00525 outline->n_contours++; 00526 return CFF_Err_Ok; 00527 } 00528 00529 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); 00530 if ( !error ) 00531 { 00532 if ( outline->n_contours > 0 ) 00533 outline->contours[outline->n_contours - 1] = 00534 (short)( outline->n_points - 1 ); 00535 00536 outline->n_contours++; 00537 } 00538 00539 return error; 00540 } 00541 00542 00543 /* if a path was begun, add its first on-curve point */ 00544 static FT_Error 00545 cff_builder_start_point( CFF_Builder* builder, 00546 FT_Pos x, 00547 FT_Pos y ) 00548 { 00549 FT_Error error = CFF_Err_Ok; 00550 00551 00552 /* test whether we are building a new contour */ 00553 if ( !builder->path_begun ) 00554 { 00555 builder->path_begun = 1; 00556 error = cff_builder_add_contour( builder ); 00557 if ( !error ) 00558 error = cff_builder_add_point1( builder, x, y ); 00559 } 00560 00561 return error; 00562 } 00563 00564 00565 /* close the current contour */ 00566 static void 00567 cff_builder_close_contour( CFF_Builder* builder ) 00568 { 00569 FT_Outline* outline = builder->current; 00570 FT_Int first; 00571 00572 00573 if ( !outline ) 00574 return; 00575 00576 first = outline->n_contours <= 1 00577 ? 0 : outline->contours[outline->n_contours - 2] + 1; 00578 00579 /* We must not include the last point in the path if it */ 00580 /* is located on the first point. */ 00581 if ( outline->n_points > 1 ) 00582 { 00583 FT_Vector* p1 = outline->points + first; 00584 FT_Vector* p2 = outline->points + outline->n_points - 1; 00585 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; 00586 00587 00588 /* `delete' last point only if it coincides with the first */ 00589 /* point and if it is not a control point (which can happen). */ 00590 if ( p1->x == p2->x && p1->y == p2->y ) 00591 if ( *control == FT_CURVE_TAG_ON ) 00592 outline->n_points--; 00593 } 00594 00595 if ( outline->n_contours > 0 ) 00596 { 00597 /* Don't add contours only consisting of one point, i.e., */ 00598 /* check whether begin point and last point are the same. */ 00599 if ( first == outline->n_points - 1 ) 00600 { 00601 outline->n_contours--; 00602 outline->n_points--; 00603 } 00604 else 00605 outline->contours[outline->n_contours - 1] = 00606 (short)( outline->n_points - 1 ); 00607 } 00608 } 00609 00610 00611 static FT_Int 00612 cff_lookup_glyph_by_stdcharcode( CFF_Font cff, 00613 FT_Int charcode ) 00614 { 00615 FT_UInt n; 00616 FT_UShort glyph_sid; 00617 00618 00619 /* CID-keyed fonts don't have glyph names */ 00620 if ( !cff->charset.sids ) 00621 return -1; 00622 00623 /* check range of standard char code */ 00624 if ( charcode < 0 || charcode > 255 ) 00625 return -1; 00626 00627 /* Get code to SID mapping from `cff_standard_encoding'. */ 00628 glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode ); 00629 00630 for ( n = 0; n < cff->num_glyphs; n++ ) 00631 { 00632 if ( cff->charset.sids[n] == glyph_sid ) 00633 return n; 00634 } 00635 00636 return -1; 00637 } 00638 00639 00640 static FT_Error 00641 cff_get_glyph_data( TT_Face face, 00642 FT_UInt glyph_index, 00643 FT_Byte** pointer, 00644 FT_ULong* length ) 00645 { 00646 #ifdef FT_CONFIG_OPTION_INCREMENTAL 00647 /* For incremental fonts get the character data using the */ 00648 /* callback function. */ 00649 if ( face->root.internal->incremental_interface ) 00650 { 00651 FT_Data data; 00652 FT_Error error = 00653 face->root.internal->incremental_interface->funcs->get_glyph_data( 00654 face->root.internal->incremental_interface->object, 00655 glyph_index, &data ); 00656 00657 00658 *pointer = (FT_Byte*)data.pointer; 00659 *length = data.length; 00660 00661 return error; 00662 } 00663 else 00664 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 00665 00666 { 00667 CFF_Font cff = (CFF_Font)(face->extra.data); 00668 00669 00670 return cff_index_access_element( &cff->charstrings_index, glyph_index, 00671 pointer, length ); 00672 } 00673 } 00674 00675 00676 static void 00677 cff_free_glyph_data( TT_Face face, 00678 FT_Byte** pointer, 00679 FT_ULong length ) 00680 { 00681 #ifndef FT_CONFIG_OPTION_INCREMENTAL 00682 FT_UNUSED( length ); 00683 #endif 00684 00685 #ifdef FT_CONFIG_OPTION_INCREMENTAL 00686 /* For incremental fonts get the character data using the */ 00687 /* callback function. */ 00688 if ( face->root.internal->incremental_interface ) 00689 { 00690 FT_Data data; 00691 00692 00693 data.pointer = *pointer; 00694 data.length = length; 00695 00696 face->root.internal->incremental_interface->funcs->free_glyph_data( 00697 face->root.internal->incremental_interface->object, &data ); 00698 } 00699 else 00700 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 00701 00702 { 00703 CFF_Font cff = (CFF_Font)(face->extra.data); 00704 00705 00706 cff_index_forget_element( &cff->charstrings_index, pointer ); 00707 } 00708 } 00709 00710 00711 static FT_Error 00712 cff_operator_seac( CFF_Decoder* decoder, 00713 FT_Pos asb, 00714 FT_Pos adx, 00715 FT_Pos ady, 00716 FT_Int bchar, 00717 FT_Int achar ) 00718 { 00719 FT_Error error; 00720 CFF_Builder* builder = &decoder->builder; 00721 FT_Int bchar_index, achar_index; 00722 TT_Face face = decoder->builder.face; 00723 FT_Vector left_bearing, advance; 00724 FT_Byte* charstring; 00725 FT_ULong charstring_len; 00726 FT_Pos glyph_width; 00727 00728 00729 if ( decoder->seac ) 00730 { 00731 FT_ERROR(( "cff_operator_seac: invalid nested seac\n" )); 00732 return CFF_Err_Syntax_Error; 00733 } 00734 00735 adx += decoder->builder.left_bearing.x; 00736 ady += decoder->builder.left_bearing.y; 00737 00738 #ifdef FT_CONFIG_OPTION_INCREMENTAL 00739 /* Incremental fonts don't necessarily have valid charsets. */ 00740 /* They use the character code, not the glyph index, in this case. */ 00741 if ( face->root.internal->incremental_interface ) 00742 { 00743 bchar_index = bchar; 00744 achar_index = achar; 00745 } 00746 else 00747 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 00748 { 00749 CFF_Font cff = (CFF_Font)(face->extra.data); 00750 00751 00752 bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); 00753 achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar ); 00754 } 00755 00756 if ( bchar_index < 0 || achar_index < 0 ) 00757 { 00758 FT_ERROR(( "cff_operator_seac:" 00759 " invalid seac character code arguments\n" )); 00760 return CFF_Err_Syntax_Error; 00761 } 00762 00763 /* If we are trying to load a composite glyph, do not load the */ 00764 /* accent character and return the array of subglyphs. */ 00765 if ( builder->no_recurse ) 00766 { 00767 FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph; 00768 FT_GlyphLoader loader = glyph->internal->loader; 00769 FT_SubGlyph subg; 00770 00771 00772 /* reallocate subglyph array if necessary */ 00773 error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); 00774 if ( error ) 00775 goto Exit; 00776 00777 subg = loader->current.subglyphs; 00778 00779 /* subglyph 0 = base character */ 00780 subg->index = bchar_index; 00781 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | 00782 FT_SUBGLYPH_FLAG_USE_MY_METRICS; 00783 subg->arg1 = 0; 00784 subg->arg2 = 0; 00785 subg++; 00786 00787 /* subglyph 1 = accent character */ 00788 subg->index = achar_index; 00789 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; 00790 subg->arg1 = (FT_Int)( adx >> 16 ); 00791 subg->arg2 = (FT_Int)( ady >> 16 ); 00792 00793 /* set up remaining glyph fields */ 00794 glyph->num_subglyphs = 2; 00795 glyph->subglyphs = loader->base.subglyphs; 00796 glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 00797 00798 loader->current.num_subglyphs = 2; 00799 } 00800 00801 FT_GlyphLoader_Prepare( builder->loader ); 00802 00803 /* First load `bchar' in builder */ 00804 error = cff_get_glyph_data( face, bchar_index, 00805 &charstring, &charstring_len ); 00806 if ( !error ) 00807 { 00808 /* the seac operator must not be nested */ 00809 decoder->seac = TRUE; 00810 error = cff_decoder_parse_charstrings( decoder, charstring, 00811 charstring_len ); 00812 decoder->seac = FALSE; 00813 00814 cff_free_glyph_data( face, &charstring, charstring_len ); 00815 00816 if ( error ) 00817 goto Exit; 00818 } 00819 00820 /* Save the left bearing, advance and glyph width of the base */ 00821 /* character as they will be erased by the next load. */ 00822 00823 left_bearing = builder->left_bearing; 00824 advance = builder->advance; 00825 glyph_width = decoder->glyph_width; 00826 00827 builder->left_bearing.x = 0; 00828 builder->left_bearing.y = 0; 00829 00830 builder->pos_x = adx - asb; 00831 builder->pos_y = ady; 00832 00833 /* Now load `achar' on top of the base outline. */ 00834 error = cff_get_glyph_data( face, achar_index, 00835 &charstring, &charstring_len ); 00836 if ( !error ) 00837 { 00838 /* the seac operator must not be nested */ 00839 decoder->seac = TRUE; 00840 error = cff_decoder_parse_charstrings( decoder, charstring, 00841 charstring_len ); 00842 decoder->seac = FALSE; 00843 00844 cff_free_glyph_data( face, &charstring, charstring_len ); 00845 00846 if ( error ) 00847 goto Exit; 00848 } 00849 00850 /* Restore the left side bearing, advance and glyph width */ 00851 /* of the base character. */ 00852 builder->left_bearing = left_bearing; 00853 builder->advance = advance; 00854 decoder->glyph_width = glyph_width; 00855 00856 builder->pos_x = 0; 00857 builder->pos_y = 0; 00858 00859 Exit: 00860 return error; 00861 } 00862 00863 00864 /*************************************************************************/ 00865 /* */ 00866 /* <Function> */ 00867 /* cff_decoder_parse_charstrings */ 00868 /* */ 00869 /* <Description> */ 00870 /* Parses a given Type 2 charstrings program. */ 00871 /* */ 00872 /* <InOut> */ 00873 /* decoder :: The current Type 1 decoder. */ 00874 /* */ 00875 /* <Input> */ 00876 /* charstring_base :: The base of the charstring stream. */ 00877 /* */ 00878 /* charstring_len :: The length in bytes of the charstring stream. */ 00879 /* */ 00880 /* <Return> */ 00881 /* FreeType error code. 0 means success. */ 00882 /* */ 00883 FT_LOCAL_DEF( FT_Error ) 00884 cff_decoder_parse_charstrings( CFF_Decoder* decoder, 00885 FT_Byte* charstring_base, 00886 FT_ULong charstring_len ) 00887 { 00888 FT_Error error; 00889 CFF_Decoder_Zone* zone; 00890 FT_Byte* ip; 00891 FT_Byte* limit; 00892 CFF_Builder* builder = &decoder->builder; 00893 FT_Pos x, y; 00894 FT_Fixed seed; 00895 FT_Fixed* stack; 00896 FT_Int charstring_type = 00897 decoder->cff->top_font.font_dict.charstring_type; 00898 00899 T2_Hints_Funcs hinter; 00900 00901 00902 /* set default width */ 00903 decoder->num_hints = 0; 00904 decoder->read_width = 1; 00905 00906 /* compute random seed from stack address of parameter */ 00907 seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^ 00908 (FT_PtrDist)(char*)&decoder ^ 00909 (FT_PtrDist)(char*)&charstring_base ) & 00910 FT_ULONG_MAX ) ; 00911 seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; 00912 if ( seed == 0 ) 00913 seed = 0x7384; 00914 00915 /* initialize the decoder */ 00916 decoder->top = decoder->stack; 00917 decoder->zone = decoder->zones; 00918 zone = decoder->zones; 00919 stack = decoder->top; 00920 00921 hinter = (T2_Hints_Funcs)builder->hints_funcs; 00922 00923 builder->path_begun = 0; 00924 00925 zone->base = charstring_base; 00926 limit = zone->limit = charstring_base + charstring_len; 00927 ip = zone->cursor = zone->base; 00928 00929 error = CFF_Err_Ok; 00930 00931 x = builder->pos_x; 00932 y = builder->pos_y; 00933 00934 /* begin hints recording session, if any */ 00935 if ( hinter ) 00936 hinter->open( hinter->hints ); 00937 00938 /* now execute loop */ 00939 while ( ip < limit ) 00940 { 00941 CFF_Operator op; 00942 FT_Byte v; 00943 00944 00945 /********************************************************************/ 00946 /* */ 00947 /* Decode operator or operand */ 00948 /* */ 00949 v = *ip++; 00950 if ( v >= 32 || v == 28 ) 00951 { 00952 FT_Int shift = 16; 00953 FT_Int32 val; 00954 00955 00956 /* this is an operand, push it on the stack */ 00957 if ( v == 28 ) 00958 { 00959 if ( ip + 1 >= limit ) 00960 goto Syntax_Error; 00961 val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] ); 00962 ip += 2; 00963 } 00964 else if ( v < 247 ) 00965 val = (FT_Int32)v - 139; 00966 else if ( v < 251 ) 00967 { 00968 if ( ip >= limit ) 00969 goto Syntax_Error; 00970 val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108; 00971 } 00972 else if ( v < 255 ) 00973 { 00974 if ( ip >= limit ) 00975 goto Syntax_Error; 00976 val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108; 00977 } 00978 else 00979 { 00980 if ( ip + 3 >= limit ) 00981 goto Syntax_Error; 00982 val = ( (FT_Int32)ip[0] << 24 ) | 00983 ( (FT_Int32)ip[1] << 16 ) | 00984 ( (FT_Int32)ip[2] << 8 ) | 00985 ip[3]; 00986 ip += 4; 00987 if ( charstring_type == 2 ) 00988 shift = 0; 00989 } 00990 if ( decoder->top - stack >= CFF_MAX_OPERANDS ) 00991 goto Stack_Overflow; 00992 00993 val <<= shift; 00994 *decoder->top++ = val; 00995 00996 #ifdef FT_DEBUG_LEVEL_TRACE 00997 if ( !( val & 0xFFFFL ) ) 00998 FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) )); 00999 else 01000 FT_TRACE4(( " %.2f", val / 65536.0 )); 01001 #endif 01002 01003 } 01004 else 01005 { 01006 /* The specification says that normally arguments are to be taken */ 01007 /* from the bottom of the stack. However, this seems not to be */ 01008 /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */ 01009 /* arguments similar to a PS interpreter. */ 01010 01011 FT_Fixed* args = decoder->top; 01012 FT_Int num_args = (FT_Int)( args - decoder->stack ); 01013 FT_Int req_args; 01014 01015 01016 /* find operator */ 01017 op = cff_op_unknown; 01018 01019 switch ( v ) 01020 { 01021 case 1: 01022 op = cff_op_hstem; 01023 break; 01024 case 3: 01025 op = cff_op_vstem; 01026 break; 01027 case 4: 01028 op = cff_op_vmoveto; 01029 break; 01030 case 5: 01031 op = cff_op_rlineto; 01032 break; 01033 case 6: 01034 op = cff_op_hlineto; 01035 break; 01036 case 7: 01037 op = cff_op_vlineto; 01038 break; 01039 case 8: 01040 op = cff_op_rrcurveto; 01041 break; 01042 case 9: 01043 op = cff_op_closepath; 01044 break; 01045 case 10: 01046 op = cff_op_callsubr; 01047 break; 01048 case 11: 01049 op = cff_op_return; 01050 break; 01051 case 12: 01052 { 01053 if ( ip >= limit ) 01054 goto Syntax_Error; 01055 v = *ip++; 01056 01057 switch ( v ) 01058 { 01059 case 0: 01060 op = cff_op_dotsection; 01061 break; 01062 case 1: /* this is actually the Type1 vstem3 operator */ 01063 op = cff_op_vstem; 01064 break; 01065 case 2: /* this is actually the Type1 hstem3 operator */ 01066 op = cff_op_hstem; 01067 break; 01068 case 3: 01069 op = cff_op_and; 01070 break; 01071 case 4: 01072 op = cff_op_or; 01073 break; 01074 case 5: 01075 op = cff_op_not; 01076 break; 01077 case 6: 01078 op = cff_op_seac; 01079 break; 01080 case 7: 01081 op = cff_op_sbw; 01082 break; 01083 case 8: 01084 op = cff_op_store; 01085 break; 01086 case 9: 01087 op = cff_op_abs; 01088 break; 01089 case 10: 01090 op = cff_op_add; 01091 break; 01092 case 11: 01093 op = cff_op_sub; 01094 break; 01095 case 12: 01096 op = cff_op_div; 01097 break; 01098 case 13: 01099 op = cff_op_load; 01100 break; 01101 case 14: 01102 op = cff_op_neg; 01103 break; 01104 case 15: 01105 op = cff_op_eq; 01106 break; 01107 case 16: 01108 op = cff_op_callothersubr; 01109 break; 01110 case 17: 01111 op = cff_op_pop; 01112 break; 01113 case 18: 01114 op = cff_op_drop; 01115 break; 01116 case 20: 01117 op = cff_op_put; 01118 break; 01119 case 21: 01120 op = cff_op_get; 01121 break; 01122 case 22: 01123 op = cff_op_ifelse; 01124 break; 01125 case 23: 01126 op = cff_op_random; 01127 break; 01128 case 24: 01129 op = cff_op_mul; 01130 break; 01131 case 26: 01132 op = cff_op_sqrt; 01133 break; 01134 case 27: 01135 op = cff_op_dup; 01136 break; 01137 case 28: 01138 op = cff_op_exch; 01139 break; 01140 case 29: 01141 op = cff_op_index; 01142 break; 01143 case 30: 01144 op = cff_op_roll; 01145 break; 01146 case 33: 01147 op = cff_op_setcurrentpoint; 01148 break; 01149 case 34: 01150 op = cff_op_hflex; 01151 break; 01152 case 35: 01153 op = cff_op_flex; 01154 break; 01155 case 36: 01156 op = cff_op_hflex1; 01157 break; 01158 case 37: 01159 op = cff_op_flex1; 01160 break; 01161 default: 01162 /* decrement ip for syntax error message */ 01163 ip--; 01164 } 01165 } 01166 break; 01167 case 13: 01168 op = cff_op_hsbw; 01169 break; 01170 case 14: 01171 op = cff_op_endchar; 01172 break; 01173 case 16: 01174 op = cff_op_blend; 01175 break; 01176 case 18: 01177 op = cff_op_hstemhm; 01178 break; 01179 case 19: 01180 op = cff_op_hintmask; 01181 break; 01182 case 20: 01183 op = cff_op_cntrmask; 01184 break; 01185 case 21: 01186 op = cff_op_rmoveto; 01187 break; 01188 case 22: 01189 op = cff_op_hmoveto; 01190 break; 01191 case 23: 01192 op = cff_op_vstemhm; 01193 break; 01194 case 24: 01195 op = cff_op_rcurveline; 01196 break; 01197 case 25: 01198 op = cff_op_rlinecurve; 01199 break; 01200 case 26: 01201 op = cff_op_vvcurveto; 01202 break; 01203 case 27: 01204 op = cff_op_hhcurveto; 01205 break; 01206 case 29: 01207 op = cff_op_callgsubr; 01208 break; 01209 case 30: 01210 op = cff_op_vhcurveto; 01211 break; 01212 case 31: 01213 op = cff_op_hvcurveto; 01214 break; 01215 default: 01216 break; 01217 } 01218 01219 if ( op == cff_op_unknown ) 01220 goto Syntax_Error; 01221 01222 /* check arguments */ 01223 req_args = cff_argument_counts[op]; 01224 if ( req_args & CFF_COUNT_CHECK_WIDTH ) 01225 { 01226 if ( num_args > 0 && decoder->read_width ) 01227 { 01228 /* If `nominal_width' is non-zero, the number is really a */ 01229 /* difference against `nominal_width'. Else, the number here */ 01230 /* is truly a width, not a difference against `nominal_width'. */ 01231 /* If the font does not set `nominal_width', then */ 01232 /* `nominal_width' defaults to zero, and so we can set */ 01233 /* `glyph_width' to `nominal_width' plus number on the stack */ 01234 /* -- for either case. */ 01235 01236 FT_Int set_width_ok; 01237 01238 01239 switch ( op ) 01240 { 01241 case cff_op_hmoveto: 01242 case cff_op_vmoveto: 01243 set_width_ok = num_args & 2; 01244 break; 01245 01246 case cff_op_hstem: 01247 case cff_op_vstem: 01248 case cff_op_hstemhm: 01249 case cff_op_vstemhm: 01250 case cff_op_rmoveto: 01251 case cff_op_hintmask: 01252 case cff_op_cntrmask: 01253 set_width_ok = num_args & 1; 01254 break; 01255 01256 case cff_op_endchar: 01257 /* If there is a width specified for endchar, we either have */ 01258 /* 1 argument or 5 arguments. We like to argue. */ 01259 set_width_ok = ( num_args == 5 ) || ( num_args == 1 ); 01260 break; 01261 01262 default: 01263 set_width_ok = 0; 01264 break; 01265 } 01266 01267 if ( set_width_ok ) 01268 { 01269 decoder->glyph_width = decoder->nominal_width + 01270 ( stack[0] >> 16 ); 01271 01272 if ( decoder->width_only ) 01273 { 01274 /* we only want the advance width; stop here */ 01275 break; 01276 } 01277 01278 /* Consumed an argument. */ 01279 num_args--; 01280 } 01281 } 01282 01283 decoder->read_width = 0; 01284 req_args = 0; 01285 } 01286 01287 req_args &= 0x000F; 01288 if ( num_args < req_args ) 01289 goto Stack_Underflow; 01290 args -= req_args; 01291 num_args -= req_args; 01292 01293 /* At this point, `args' points to the first argument of the */ 01294 /* operand in case `req_args' isn't zero. Otherwise, we have */ 01295 /* to adjust `args' manually. */ 01296 01297 /* Note that we only pop arguments from the stack which we */ 01298 /* really need and can digest so that we can continue in case */ 01299 /* of superfluous stack elements. */ 01300 01301 switch ( op ) 01302 { 01303 case cff_op_hstem: 01304 case cff_op_vstem: 01305 case cff_op_hstemhm: 01306 case cff_op_vstemhm: 01307 /* the number of arguments is always even here */ 01308 FT_TRACE4(( 01309 op == cff_op_hstem ? " hstem\n" : 01310 ( op == cff_op_vstem ? " vstem\n" : 01311 ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) )); 01312 01313 if ( hinter ) 01314 hinter->stems( hinter->hints, 01315 ( op == cff_op_hstem || op == cff_op_hstemhm ), 01316 num_args / 2, 01317 args - ( num_args & ~1 ) ); 01318 01319 decoder->num_hints += num_args / 2; 01320 args = stack; 01321 break; 01322 01323 case cff_op_hintmask: 01324 case cff_op_cntrmask: 01325 FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); 01326 01327 /* implement vstem when needed -- */ 01328 /* the specification doesn't say it, but this also works */ 01329 /* with the 'cntrmask' operator */ 01330 /* */ 01331 if ( num_args > 0 ) 01332 { 01333 if ( hinter ) 01334 hinter->stems( hinter->hints, 01335 0, 01336 num_args / 2, 01337 args - ( num_args & ~1 ) ); 01338 01339 decoder->num_hints += num_args / 2; 01340 } 01341 01342 /* In a valid charstring there must be at least one byte */ 01343 /* after `hintmask' or `cntrmask' (e.g., for a `return' */ 01344 /* instruction). Additionally, there must be space for */ 01345 /* `num_hints' bits. */ 01346 01347 if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit ) 01348 goto Syntax_Error; 01349 01350 if ( hinter ) 01351 { 01352 if ( op == cff_op_hintmask ) 01353 hinter->hintmask( hinter->hints, 01354 builder->current->n_points, 01355 decoder->num_hints, 01356 ip ); 01357 else 01358 hinter->counter( hinter->hints, 01359 decoder->num_hints, 01360 ip ); 01361 } 01362 01363 #ifdef FT_DEBUG_LEVEL_TRACE 01364 { 01365 FT_UInt maskbyte; 01366 01367 01368 FT_TRACE4(( " (maskbytes:" )); 01369 01370 for ( maskbyte = 0; 01371 maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 ); 01372 maskbyte++, ip++ ) 01373 FT_TRACE4(( " 0x%02X", *ip )); 01374 01375 FT_TRACE4(( ")\n" )); 01376 } 01377 #else 01378 ip += ( decoder->num_hints + 7 ) >> 3; 01379 #endif 01380 args = stack; 01381 break; 01382 01383 case cff_op_rmoveto: 01384 FT_TRACE4(( " rmoveto\n" )); 01385 01386 cff_builder_close_contour( builder ); 01387 builder->path_begun = 0; 01388 x += args[-2]; 01389 y += args[-1]; 01390 args = stack; 01391 break; 01392 01393 case cff_op_vmoveto: 01394 FT_TRACE4(( " vmoveto\n" )); 01395 01396 cff_builder_close_contour( builder ); 01397 builder->path_begun = 0; 01398 y += args[-1]; 01399 args = stack; 01400 break; 01401 01402 case cff_op_hmoveto: 01403 FT_TRACE4(( " hmoveto\n" )); 01404 01405 cff_builder_close_contour( builder ); 01406 builder->path_begun = 0; 01407 x += args[-1]; 01408 args = stack; 01409 break; 01410 01411 case cff_op_rlineto: 01412 FT_TRACE4(( " rlineto\n" )); 01413 01414 if ( cff_builder_start_point ( builder, x, y ) || 01415 check_points( builder, num_args / 2 ) ) 01416 goto Fail; 01417 01418 if ( num_args < 2 ) 01419 goto Stack_Underflow; 01420 01421 args -= num_args & ~1; 01422 while ( args < decoder->top ) 01423 { 01424 x += args[0]; 01425 y += args[1]; 01426 cff_builder_add_point( builder, x, y, 1 ); 01427 args += 2; 01428 } 01429 args = stack; 01430 break; 01431 01432 case cff_op_hlineto: 01433 case cff_op_vlineto: 01434 { 01435 FT_Int phase = ( op == cff_op_hlineto ); 01436 01437 01438 FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n" 01439 : " vlineto\n" )); 01440 01441 if ( num_args < 1 ) 01442 goto Stack_Underflow; 01443 01444 if ( cff_builder_start_point ( builder, x, y ) || 01445 check_points( builder, num_args ) ) 01446 goto Fail; 01447 01448 args = stack; 01449 while ( args < decoder->top ) 01450 { 01451 if ( phase ) 01452 x += args[0]; 01453 else 01454 y += args[0]; 01455 01456 if ( cff_builder_add_point1( builder, x, y ) ) 01457 goto Fail; 01458 01459 args++; 01460 phase ^= 1; 01461 } 01462 args = stack; 01463 } 01464 break; 01465 01466 case cff_op_rrcurveto: 01467 { 01468 FT_Int nargs; 01469 01470 01471 FT_TRACE4(( " rrcurveto\n" )); 01472 01473 if ( num_args < 6 ) 01474 goto Stack_Underflow; 01475 01476 nargs = num_args - num_args % 6; 01477 01478 if ( cff_builder_start_point ( builder, x, y ) || 01479 check_points( builder, nargs / 2 ) ) 01480 goto Fail; 01481 01482 args -= nargs; 01483 while ( args < decoder->top ) 01484 { 01485 x += args[0]; 01486 y += args[1]; 01487 cff_builder_add_point( builder, x, y, 0 ); 01488 x += args[2]; 01489 y += args[3]; 01490 cff_builder_add_point( builder, x, y, 0 ); 01491 x += args[4]; 01492 y += args[5]; 01493 cff_builder_add_point( builder, x, y, 1 ); 01494 args += 6; 01495 } 01496 args = stack; 01497 } 01498 break; 01499 01500 case cff_op_vvcurveto: 01501 { 01502 FT_Int nargs; 01503 01504 01505 FT_TRACE4(( " vvcurveto\n" )); 01506 01507 if ( num_args < 4 ) 01508 goto Stack_Underflow; 01509 01510 /* if num_args isn't of the form 4n or 4n+1, */ 01511 /* we reduce it to 4n+1 */ 01512 01513 nargs = num_args - num_args % 4; 01514 if ( num_args - nargs > 0 ) 01515 nargs += 1; 01516 01517 if ( cff_builder_start_point( builder, x, y ) ) 01518 goto Fail; 01519 01520 args -= nargs; 01521 01522 if ( nargs & 1 ) 01523 { 01524 x += args[0]; 01525 args++; 01526 nargs--; 01527 } 01528 01529 if ( check_points( builder, 3 * ( nargs / 4 ) ) ) 01530 goto Fail; 01531 01532 while ( args < decoder->top ) 01533 { 01534 y += args[0]; 01535 cff_builder_add_point( builder, x, y, 0 ); 01536 x += args[1]; 01537 y += args[2]; 01538 cff_builder_add_point( builder, x, y, 0 ); 01539 y += args[3]; 01540 cff_builder_add_point( builder, x, y, 1 ); 01541 args += 4; 01542 } 01543 args = stack; 01544 } 01545 break; 01546 01547 case cff_op_hhcurveto: 01548 { 01549 FT_Int nargs; 01550 01551 01552 FT_TRACE4(( " hhcurveto\n" )); 01553 01554 if ( num_args < 4 ) 01555 goto Stack_Underflow; 01556 01557 /* if num_args isn't of the form 4n or 4n+1, */ 01558 /* we reduce it to 4n+1 */ 01559 01560 nargs = num_args - num_args % 4; 01561 if ( num_args - nargs > 0 ) 01562 nargs += 1; 01563 01564 if ( cff_builder_start_point( builder, x, y ) ) 01565 goto Fail; 01566 01567 args -= nargs; 01568 if ( nargs & 1 ) 01569 { 01570 y += args[0]; 01571 args++; 01572 nargs--; 01573 } 01574 01575 if ( check_points( builder, 3 * ( nargs / 4 ) ) ) 01576 goto Fail; 01577 01578 while ( args < decoder->top ) 01579 { 01580 x += args[0]; 01581 cff_builder_add_point( builder, x, y, 0 ); 01582 x += args[1]; 01583 y += args[2]; 01584 cff_builder_add_point( builder, x, y, 0 ); 01585 x += args[3]; 01586 cff_builder_add_point( builder, x, y, 1 ); 01587 args += 4; 01588 } 01589 args = stack; 01590 } 01591 break; 01592 01593 case cff_op_vhcurveto: 01594 case cff_op_hvcurveto: 01595 { 01596 FT_Int phase; 01597 FT_Int nargs; 01598 01599 01600 FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n" 01601 : " hvcurveto\n" )); 01602 01603 if ( cff_builder_start_point( builder, x, y ) ) 01604 goto Fail; 01605 01606 if ( num_args < 4 ) 01607 goto Stack_Underflow; 01608 01609 /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */ 01610 /* we reduce it to the largest one which fits */ 01611 01612 nargs = num_args - num_args % 4; 01613 if ( num_args - nargs > 0 ) 01614 nargs += 1; 01615 01616 args -= nargs; 01617 if ( check_points( builder, ( nargs / 4 ) * 3 ) ) 01618 goto Stack_Underflow; 01619 01620 phase = ( op == cff_op_hvcurveto ); 01621 01622 while ( nargs >= 4 ) 01623 { 01624 nargs -= 4; 01625 if ( phase ) 01626 { 01627 x += args[0]; 01628 cff_builder_add_point( builder, x, y, 0 ); 01629 x += args[1]; 01630 y += args[2]; 01631 cff_builder_add_point( builder, x, y, 0 ); 01632 y += args[3]; 01633 if ( nargs == 1 ) 01634 x += args[4]; 01635 cff_builder_add_point( builder, x, y, 1 ); 01636 } 01637 else 01638 { 01639 y += args[0]; 01640 cff_builder_add_point( builder, x, y, 0 ); 01641 x += args[1]; 01642 y += args[2]; 01643 cff_builder_add_point( builder, x, y, 0 ); 01644 x += args[3]; 01645 if ( nargs == 1 ) 01646 y += args[4]; 01647 cff_builder_add_point( builder, x, y, 1 ); 01648 } 01649 args += 4; 01650 phase ^= 1; 01651 } 01652 args = stack; 01653 } 01654 break; 01655 01656 case cff_op_rlinecurve: 01657 { 01658 FT_Int num_lines; 01659 FT_Int nargs; 01660 01661 01662 FT_TRACE4(( " rlinecurve\n" )); 01663 01664 if ( num_args < 8 ) 01665 goto Stack_Underflow; 01666 01667 nargs = num_args & ~1; 01668 num_lines = ( nargs - 6 ) / 2; 01669 01670 if ( cff_builder_start_point( builder, x, y ) || 01671 check_points( builder, num_lines + 3 ) ) 01672 goto Fail; 01673 01674 args -= nargs; 01675 01676 /* first, add the line segments */ 01677 while ( num_lines > 0 ) 01678 { 01679 x += args[0]; 01680 y += args[1]; 01681 cff_builder_add_point( builder, x, y, 1 ); 01682 args += 2; 01683 num_lines--; 01684 } 01685 01686 /* then the curve */ 01687 x += args[0]; 01688 y += args[1]; 01689 cff_builder_add_point( builder, x, y, 0 ); 01690 x += args[2]; 01691 y += args[3]; 01692 cff_builder_add_point( builder, x, y, 0 ); 01693 x += args[4]; 01694 y += args[5]; 01695 cff_builder_add_point( builder, x, y, 1 ); 01696 args = stack; 01697 } 01698 break; 01699 01700 case cff_op_rcurveline: 01701 { 01702 FT_Int num_curves; 01703 FT_Int nargs; 01704 01705 01706 FT_TRACE4(( " rcurveline\n" )); 01707 01708 if ( num_args < 8 ) 01709 goto Stack_Underflow; 01710 01711 nargs = num_args - 2; 01712 nargs = nargs - nargs % 6 + 2; 01713 num_curves = ( nargs - 2 ) / 6; 01714 01715 if ( cff_builder_start_point ( builder, x, y ) || 01716 check_points( builder, num_curves * 3 + 2 ) ) 01717 goto Fail; 01718 01719 args -= nargs; 01720 01721 /* first, add the curves */ 01722 while ( num_curves > 0 ) 01723 { 01724 x += args[0]; 01725 y += args[1]; 01726 cff_builder_add_point( builder, x, y, 0 ); 01727 x += args[2]; 01728 y += args[3]; 01729 cff_builder_add_point( builder, x, y, 0 ); 01730 x += args[4]; 01731 y += args[5]; 01732 cff_builder_add_point( builder, x, y, 1 ); 01733 args += 6; 01734 num_curves--; 01735 } 01736 01737 /* then the final line */ 01738 x += args[0]; 01739 y += args[1]; 01740 cff_builder_add_point( builder, x, y, 1 ); 01741 args = stack; 01742 } 01743 break; 01744 01745 case cff_op_hflex1: 01746 { 01747 FT_Pos start_y; 01748 01749 01750 FT_TRACE4(( " hflex1\n" )); 01751 01752 /* adding five more points: 4 control points, 1 on-curve point */ 01753 /* -- make sure we have enough space for the start point if it */ 01754 /* needs to be added */ 01755 if ( cff_builder_start_point( builder, x, y ) || 01756 check_points( builder, 6 ) ) 01757 goto Fail; 01758 01759 /* record the starting point's y position for later use */ 01760 start_y = y; 01761 01762 /* first control point */ 01763 x += args[0]; 01764 y += args[1]; 01765 cff_builder_add_point( builder, x, y, 0 ); 01766 01767 /* second control point */ 01768 x += args[2]; 01769 y += args[3]; 01770 cff_builder_add_point( builder, x, y, 0 ); 01771 01772 /* join point; on curve, with y-value the same as the last */ 01773 /* control point's y-value */ 01774 x += args[4]; 01775 cff_builder_add_point( builder, x, y, 1 ); 01776 01777 /* third control point, with y-value the same as the join */ 01778 /* point's y-value */ 01779 x += args[5]; 01780 cff_builder_add_point( builder, x, y, 0 ); 01781 01782 /* fourth control point */ 01783 x += args[6]; 01784 y += args[7]; 01785 cff_builder_add_point( builder, x, y, 0 ); 01786 01787 /* ending point, with y-value the same as the start */ 01788 x += args[8]; 01789 y = start_y; 01790 cff_builder_add_point( builder, x, y, 1 ); 01791 01792 args = stack; 01793 break; 01794 } 01795 01796 case cff_op_hflex: 01797 { 01798 FT_Pos start_y; 01799 01800 01801 FT_TRACE4(( " hflex\n" )); 01802 01803 /* adding six more points; 4 control points, 2 on-curve points */ 01804 if ( cff_builder_start_point( builder, x, y ) || 01805 check_points( builder, 6 ) ) 01806 goto Fail; 01807 01808 /* record the starting point's y-position for later use */ 01809 start_y = y; 01810 01811 /* first control point */ 01812 x += args[0]; 01813 cff_builder_add_point( builder, x, y, 0 ); 01814 01815 /* second control point */ 01816 x += args[1]; 01817 y += args[2]; 01818 cff_builder_add_point( builder, x, y, 0 ); 01819 01820 /* join point; on curve, with y-value the same as the last */ 01821 /* control point's y-value */ 01822 x += args[3]; 01823 cff_builder_add_point( builder, x, y, 1 ); 01824 01825 /* third control point, with y-value the same as the join */ 01826 /* point's y-value */ 01827 x += args[4]; 01828 cff_builder_add_point( builder, x, y, 0 ); 01829 01830 /* fourth control point */ 01831 x += args[5]; 01832 y = start_y; 01833 cff_builder_add_point( builder, x, y, 0 ); 01834 01835 /* ending point, with y-value the same as the start point's */ 01836 /* y-value -- we don't add this point, though */ 01837 x += args[6]; 01838 cff_builder_add_point( builder, x, y, 1 ); 01839 01840 args = stack; 01841 break; 01842 } 01843 01844 case cff_op_flex1: 01845 { 01846 FT_Pos start_x, start_y; /* record start x, y values for */ 01847 /* alter use */ 01848 FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ 01849 /* algorithm below */ 01850 FT_Int horizontal, count; 01851 FT_Fixed* temp; 01852 01853 01854 FT_TRACE4(( " flex1\n" )); 01855 01856 /* adding six more points; 4 control points, 2 on-curve points */ 01857 if ( cff_builder_start_point( builder, x, y ) || 01858 check_points( builder, 6 ) ) 01859 goto Fail; 01860 01861 /* record the starting point's x, y position for later use */ 01862 start_x = x; 01863 start_y = y; 01864 01865 /* XXX: figure out whether this is supposed to be a horizontal */ 01866 /* or vertical flex; the Type 2 specification is vague... */ 01867 01868 temp = args; 01869 01870 /* grab up to the last argument */ 01871 for ( count = 5; count > 0; count-- ) 01872 { 01873 dx += temp[0]; 01874 dy += temp[1]; 01875 temp += 2; 01876 } 01877 01878 if ( dx < 0 ) 01879 dx = -dx; 01880 if ( dy < 0 ) 01881 dy = -dy; 01882 01883 /* strange test, but here it is... */ 01884 horizontal = ( dx > dy ); 01885 01886 for ( count = 5; count > 0; count-- ) 01887 { 01888 x += args[0]; 01889 y += args[1]; 01890 cff_builder_add_point( builder, x, y, 01891 (FT_Bool)( count == 3 ) ); 01892 args += 2; 01893 } 01894 01895 /* is last operand an x- or y-delta? */ 01896 if ( horizontal ) 01897 { 01898 x += args[0]; 01899 y = start_y; 01900 } 01901 else 01902 { 01903 x = start_x; 01904 y += args[0]; 01905 } 01906 01907 cff_builder_add_point( builder, x, y, 1 ); 01908 01909 args = stack; 01910 break; 01911 } 01912 01913 case cff_op_flex: 01914 { 01915 FT_UInt count; 01916 01917 01918 FT_TRACE4(( " flex\n" )); 01919 01920 if ( cff_builder_start_point( builder, x, y ) || 01921 check_points( builder, 6 ) ) 01922 goto Fail; 01923 01924 for ( count = 6; count > 0; count-- ) 01925 { 01926 x += args[0]; 01927 y += args[1]; 01928 cff_builder_add_point( builder, x, y, 01929 (FT_Bool)( count == 4 || count == 1 ) ); 01930 args += 2; 01931 } 01932 01933 args = stack; 01934 } 01935 break; 01936 01937 case cff_op_seac: 01938 FT_TRACE4(( " seac\n" )); 01939 01940 error = cff_operator_seac( decoder, 01941 args[0], args[1], args[2], 01942 (FT_Int)( args[3] >> 16 ), 01943 (FT_Int)( args[4] >> 16 ) ); 01944 01945 /* add current outline to the glyph slot */ 01946 FT_GlyphLoader_Add( builder->loader ); 01947 01948 /* return now! */ 01949 FT_TRACE4(( "\n" )); 01950 return error; 01951 01952 case cff_op_endchar: 01953 FT_TRACE4(( " endchar\n" )); 01954 01955 /* We are going to emulate the seac operator. */ 01956 if ( num_args >= 4 ) 01957 { 01958 /* Save glyph width so that the subglyphs don't overwrite it. */ 01959 FT_Pos glyph_width = decoder->glyph_width; 01960 01961 error = cff_operator_seac( decoder, 01962 0L, args[-4], args[-3], 01963 (FT_Int)( args[-2] >> 16 ), 01964 (FT_Int)( args[-1] >> 16 ) ); 01965 01966 decoder->glyph_width = glyph_width; 01967 } 01968 else 01969 { 01970 if ( !error ) 01971 error = CFF_Err_Ok; 01972 01973 cff_builder_close_contour( builder ); 01974 01975 /* close hints recording session */ 01976 if ( hinter ) 01977 { 01978 if ( hinter->close( hinter->hints, 01979 builder->current->n_points ) ) 01980 goto Syntax_Error; 01981 01982 /* apply hints to the loaded glyph outline now */ 01983 hinter->apply( hinter->hints, 01984 builder->current, 01985 (PSH_Globals)builder->hints_globals, 01986 decoder->hint_mode ); 01987 } 01988 01989 /* add current outline to the glyph slot */ 01990 FT_GlyphLoader_Add( builder->loader ); 01991 } 01992 01993 /* return now! */ 01994 FT_TRACE4(( "\n" )); 01995 return error; 01996 01997 case cff_op_abs: 01998 FT_TRACE4(( " abs\n" )); 01999 02000 if ( args[0] < 0 ) 02001 args[0] = -args[0]; 02002 args++; 02003 break; 02004 02005 case cff_op_add: 02006 FT_TRACE4(( " add\n" )); 02007 02008 args[0] += args[1]; 02009 args++; 02010 break; 02011 02012 case cff_op_sub: 02013 FT_TRACE4(( " sub\n" )); 02014 02015 args[0] -= args[1]; 02016 args++; 02017 break; 02018 02019 case cff_op_div: 02020 FT_TRACE4(( " div\n" )); 02021 02022 args[0] = FT_DivFix( args[0], args[1] ); 02023 args++; 02024 break; 02025 02026 case cff_op_neg: 02027 FT_TRACE4(( " neg\n" )); 02028 02029 args[0] = -args[0]; 02030 args++; 02031 break; 02032 02033 case cff_op_random: 02034 { 02035 FT_Fixed Rand; 02036 02037 02038 FT_TRACE4(( " rand\n" )); 02039 02040 Rand = seed; 02041 if ( Rand >= 0x8000L ) 02042 Rand++; 02043 02044 args[0] = Rand; 02045 seed = FT_MulFix( seed, 0x10000L - seed ); 02046 if ( seed == 0 ) 02047 seed += 0x2873; 02048 args++; 02049 } 02050 break; 02051 02052 case cff_op_mul: 02053 FT_TRACE4(( " mul\n" )); 02054 02055 args[0] = FT_MulFix( args[0], args[1] ); 02056 args++; 02057 break; 02058 02059 case cff_op_sqrt: 02060 FT_TRACE4(( " sqrt\n" )); 02061 02062 if ( args[0] > 0 ) 02063 { 02064 FT_Int count = 9; 02065 FT_Fixed root = args[0]; 02066 FT_Fixed new_root; 02067 02068 02069 for (;;) 02070 { 02071 new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; 02072 if ( new_root == root || count <= 0 ) 02073 break; 02074 root = new_root; 02075 } 02076 args[0] = new_root; 02077 } 02078 else 02079 args[0] = 0; 02080 args++; 02081 break; 02082 02083 case cff_op_drop: 02084 /* nothing */ 02085 FT_TRACE4(( " drop\n" )); 02086 02087 break; 02088 02089 case cff_op_exch: 02090 { 02091 FT_Fixed tmp; 02092 02093 02094 FT_TRACE4(( " exch\n" )); 02095 02096 tmp = args[0]; 02097 args[0] = args[1]; 02098 args[1] = tmp; 02099 args += 2; 02100 } 02101 break; 02102 02103 case cff_op_index: 02104 { 02105 FT_Int idx = (FT_Int)( args[0] >> 16 ); 02106 02107 02108 FT_TRACE4(( " index\n" )); 02109 02110 if ( idx < 0 ) 02111 idx = 0; 02112 else if ( idx > num_args - 2 ) 02113 idx = num_args - 2; 02114 args[0] = args[-( idx + 1 )]; 02115 args++; 02116 } 02117 break; 02118 02119 case cff_op_roll: 02120 { 02121 FT_Int count = (FT_Int)( args[0] >> 16 ); 02122 FT_Int idx = (FT_Int)( args[1] >> 16 ); 02123 02124 02125 FT_TRACE4(( " roll\n" )); 02126 02127 if ( count <= 0 ) 02128 count = 1; 02129 02130 args -= count; 02131 if ( args < stack ) 02132 goto Stack_Underflow; 02133 02134 if ( idx >= 0 ) 02135 { 02136 while ( idx > 0 ) 02137 { 02138 FT_Fixed tmp = args[count - 1]; 02139 FT_Int i; 02140 02141 02142 for ( i = count - 2; i >= 0; i-- ) 02143 args[i + 1] = args[i]; 02144 args[0] = tmp; 02145 idx--; 02146 } 02147 } 02148 else 02149 { 02150 while ( idx < 0 ) 02151 { 02152 FT_Fixed tmp = args[0]; 02153 FT_Int i; 02154 02155 02156 for ( i = 0; i < count - 1; i++ ) 02157 args[i] = args[i + 1]; 02158 args[count - 1] = tmp; 02159 idx++; 02160 } 02161 } 02162 args += count; 02163 } 02164 break; 02165 02166 case cff_op_dup: 02167 FT_TRACE4(( " dup\n" )); 02168 02169 args[1] = args[0]; 02170 args += 2; 02171 break; 02172 02173 case cff_op_put: 02174 { 02175 FT_Fixed val = args[0]; 02176 FT_Int idx = (FT_Int)( args[1] >> 16 ); 02177 02178 02179 FT_TRACE4(( " put\n" )); 02180 02181 if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) 02182 decoder->buildchar[idx] = val; 02183 } 02184 break; 02185 02186 case cff_op_get: 02187 { 02188 FT_Int idx = (FT_Int)( args[0] >> 16 ); 02189 FT_Fixed val = 0; 02190 02191 02192 FT_TRACE4(( " get\n" )); 02193 02194 if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) 02195 val = decoder->buildchar[idx]; 02196 02197 args[0] = val; 02198 args++; 02199 } 02200 break; 02201 02202 case cff_op_store: 02203 FT_TRACE4(( " store\n")); 02204 02205 goto Unimplemented; 02206 02207 case cff_op_load: 02208 FT_TRACE4(( " load\n" )); 02209 02210 goto Unimplemented; 02211 02212 case cff_op_dotsection: 02213 /* this operator is deprecated and ignored by the parser */ 02214 FT_TRACE4(( " dotsection\n" )); 02215 break; 02216 02217 case cff_op_closepath: 02218 /* this is an invalid Type 2 operator; however, there */ 02219 /* exist fonts which are incorrectly converted from probably */ 02220 /* Type 1 to CFF, and some parsers seem to accept it */ 02221 02222 FT_TRACE4(( " closepath (invalid op)\n" )); 02223 02224 args = stack; 02225 break; 02226 02227 case cff_op_hsbw: 02228 /* this is an invalid Type 2 operator; however, there */ 02229 /* exist fonts which are incorrectly converted from probably */ 02230 /* Type 1 to CFF, and some parsers seem to accept it */ 02231 02232 FT_TRACE4(( " hsbw (invalid op)\n" )); 02233 02234 decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 ); 02235 02236 decoder->builder.left_bearing.x = args[0]; 02237 decoder->builder.left_bearing.y = 0; 02238 02239 x = decoder->builder.pos_x + args[0]; 02240 y = decoder->builder.pos_y; 02241 args = stack; 02242 break; 02243 02244 case cff_op_sbw: 02245 /* this is an invalid Type 2 operator; however, there */ 02246 /* exist fonts which are incorrectly converted from probably */ 02247 /* Type 1 to CFF, and some parsers seem to accept it */ 02248 02249 FT_TRACE4(( " sbw (invalid op)\n" )); 02250 02251 decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 ); 02252 02253 decoder->builder.left_bearing.x = args[0]; 02254 decoder->builder.left_bearing.y = args[1]; 02255 02256 x = decoder->builder.pos_x + args[0]; 02257 y = decoder->builder.pos_y + args[1]; 02258 args = stack; 02259 break; 02260 02261 case cff_op_setcurrentpoint: 02262 /* this is an invalid Type 2 operator; however, there */ 02263 /* exist fonts which are incorrectly converted from probably */ 02264 /* Type 1 to CFF, and some parsers seem to accept it */ 02265 02266 FT_TRACE4(( " setcurrentpoint (invalid op)\n" )); 02267 02268 x = decoder->builder.pos_x + args[0]; 02269 y = decoder->builder.pos_y + args[1]; 02270 args = stack; 02271 break; 02272 02273 case cff_op_callothersubr: 02274 /* this is an invalid Type 2 operator; however, there */ 02275 /* exist fonts which are incorrectly converted from probably */ 02276 /* Type 1 to CFF, and some parsers seem to accept it */ 02277 02278 FT_TRACE4(( " callothersubr (invalid op)\n" )); 02279 02280 /* subsequent `pop' operands should add the arguments, */ 02281 /* this is the implementation described for `unknown' other */ 02282 /* subroutines in the Type1 spec. */ 02283 /* */ 02284 /* XXX Fix return arguments (see discussion below). */ 02285 args -= 2 + ( args[-2] >> 16 ); 02286 if ( args < stack ) 02287 goto Stack_Underflow; 02288 break; 02289 02290 case cff_op_pop: 02291 /* this is an invalid Type 2 operator; however, there */ 02292 /* exist fonts which are incorrectly converted from probably */ 02293 /* Type 1 to CFF, and some parsers seem to accept it */ 02294 02295 FT_TRACE4(( " pop (invalid op)\n" )); 02296 02297 /* XXX Increasing `args' is wrong: After a certain number of */ 02298 /* `pop's we get a stack overflow. Reason for doing it is */ 02299 /* code like this (actually found in a CFF font): */ 02300 /* */ 02301 /* 17 1 3 callothersubr */ 02302 /* pop */ 02303 /* callsubr */ 02304 /* */ 02305 /* Since we handle `callothersubr' as a no-op, and */ 02306 /* `callsubr' needs at least one argument, `pop' can't be a */ 02307 /* no-op too as it basically should be. */ 02308 /* */ 02309 /* The right solution would be to provide real support for */ 02310 /* `callothersubr' as done in `t1decode.c', however, given */ 02311 /* the fact that CFF fonts with `pop' are invalid, it is */ 02312 /* questionable whether it is worth the time. */ 02313 args++; 02314 break; 02315 02316 case cff_op_and: 02317 { 02318 FT_Fixed cond = args[0] && args[1]; 02319 02320 02321 FT_TRACE4(( " and\n" )); 02322 02323 args[0] = cond ? 0x10000L : 0; 02324 args++; 02325 } 02326 break; 02327 02328 case cff_op_or: 02329 { 02330 FT_Fixed cond = args[0] || args[1]; 02331 02332 02333 FT_TRACE4(( " or\n" )); 02334 02335 args[0] = cond ? 0x10000L : 0; 02336 args++; 02337 } 02338 break; 02339 02340 case cff_op_eq: 02341 { 02342 FT_Fixed cond = !args[0]; 02343 02344 02345 FT_TRACE4(( " eq\n" )); 02346 02347 args[0] = cond ? 0x10000L : 0; 02348 args++; 02349 } 02350 break; 02351 02352 case cff_op_ifelse: 02353 { 02354 FT_Fixed cond = ( args[2] <= args[3] ); 02355 02356 02357 FT_TRACE4(( " ifelse\n" )); 02358 02359 if ( !cond ) 02360 args[0] = args[1]; 02361 args++; 02362 } 02363 break; 02364 02365 case cff_op_callsubr: 02366 { 02367 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + 02368 decoder->locals_bias ); 02369 02370 02371 FT_TRACE4(( " callsubr(%d)\n", idx )); 02372 02373 if ( idx >= decoder->num_locals ) 02374 { 02375 FT_ERROR(( "cff_decoder_parse_charstrings:" 02376 " invalid local subr index\n" )); 02377 goto Syntax_Error; 02378 } 02379 02380 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) 02381 { 02382 FT_ERROR(( "cff_decoder_parse_charstrings:" 02383 " too many nested subrs\n" )); 02384 goto Syntax_Error; 02385 } 02386 02387 zone->cursor = ip; /* save current instruction pointer */ 02388 02389 zone++; 02390 zone->base = decoder->locals[idx]; 02391 zone->limit = decoder->locals[idx + 1]; 02392 zone->cursor = zone->base; 02393 02394 if ( !zone->base || zone->limit == zone->base ) 02395 { 02396 FT_ERROR(( "cff_decoder_parse_charstrings:" 02397 " invoking empty subrs\n" )); 02398 goto Syntax_Error; 02399 } 02400 02401 decoder->zone = zone; 02402 ip = zone->base; 02403 limit = zone->limit; 02404 } 02405 break; 02406 02407 case cff_op_callgsubr: 02408 { 02409 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + 02410 decoder->globals_bias ); 02411 02412 02413 FT_TRACE4(( " callgsubr(%d)\n", idx )); 02414 02415 if ( idx >= decoder->num_globals ) 02416 { 02417 FT_ERROR(( "cff_decoder_parse_charstrings:" 02418 " invalid global subr index\n" )); 02419 goto Syntax_Error; 02420 } 02421 02422 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) 02423 { 02424 FT_ERROR(( "cff_decoder_parse_charstrings:" 02425 " too many nested subrs\n" )); 02426 goto Syntax_Error; 02427 } 02428 02429 zone->cursor = ip; /* save current instruction pointer */ 02430 02431 zone++; 02432 zone->base = decoder->globals[idx]; 02433 zone->limit = decoder->globals[idx + 1]; 02434 zone->cursor = zone->base; 02435 02436 if ( !zone->base || zone->limit == zone->base ) 02437 { 02438 FT_ERROR(( "cff_decoder_parse_charstrings:" 02439 " invoking empty subrs\n" )); 02440 goto Syntax_Error; 02441 } 02442 02443 decoder->zone = zone; 02444 ip = zone->base; 02445 limit = zone->limit; 02446 } 02447 break; 02448 02449 case cff_op_return: 02450 FT_TRACE4(( " return\n" )); 02451 02452 if ( decoder->zone <= decoder->zones ) 02453 { 02454 FT_ERROR(( "cff_decoder_parse_charstrings:" 02455 " unexpected return\n" )); 02456 goto Syntax_Error; 02457 } 02458 02459 decoder->zone--; 02460 zone = decoder->zone; 02461 ip = zone->cursor; 02462 limit = zone->limit; 02463 break; 02464 02465 default: 02466 Unimplemented: 02467 FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); 02468 02469 if ( ip[-1] == 12 ) 02470 FT_ERROR(( " %d", ip[0] )); 02471 FT_ERROR(( "\n" )); 02472 02473 return CFF_Err_Unimplemented_Feature; 02474 } 02475 02476 decoder->top = args; 02477 02478 if ( decoder->top - stack >= CFF_MAX_OPERANDS ) 02479 goto Stack_Overflow; 02480 02481 } /* general operator processing */ 02482 02483 } /* while ip < limit */ 02484 02485 FT_TRACE4(( "..end..\n\n" )); 02486 02487 Fail: 02488 return error; 02489 02490 Syntax_Error: 02491 FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" )); 02492 return CFF_Err_Invalid_File_Format; 02493 02494 Stack_Underflow: 02495 FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" )); 02496 return CFF_Err_Too_Few_Arguments; 02497 02498 Stack_Overflow: 02499 FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" )); 02500 return CFF_Err_Stack_Overflow; 02501 } 02502 02503 02504 /*************************************************************************/ 02505 /*************************************************************************/ 02506 /*************************************************************************/ 02507 /********** *********/ 02508 /********** *********/ 02509 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ 02510 /********** *********/ 02511 /********** The following code is in charge of computing *********/ 02512 /********** the maximum advance width of the font. It *********/ 02513 /********** quickly processes each glyph charstring to *********/ 02514 /********** extract the value from either a `sbw' or `seac' *********/ 02515 /********** operator. *********/ 02516 /********** *********/ 02517 /*************************************************************************/ 02518 /*************************************************************************/ 02519 /*************************************************************************/ 02520 02521 02522 #if 0 /* unused until we support pure CFF fonts */ 02523 02524 02525 FT_LOCAL_DEF( FT_Error ) 02526 cff_compute_max_advance( TT_Face face, 02527 FT_Int* max_advance ) 02528 { 02529 FT_Error error = CFF_Err_Ok; 02530 CFF_Decoder decoder; 02531 FT_Int glyph_index; 02532 CFF_Font cff = (CFF_Font)face->other; 02533 02534 02535 *max_advance = 0; 02536 02537 /* Initialize load decoder */ 02538 cff_decoder_init( &decoder, face, 0, 0, 0, 0 ); 02539 02540 decoder.builder.metrics_only = 1; 02541 decoder.builder.load_points = 0; 02542 02543 /* For each glyph, parse the glyph charstring and extract */ 02544 /* the advance width. */ 02545 for ( glyph_index = 0; glyph_index < face->root.num_glyphs; 02546 glyph_index++ ) 02547 { 02548 FT_Byte* charstring; 02549 FT_ULong charstring_len; 02550 02551 02552 /* now get load the unscaled outline */ 02553 error = cff_get_glyph_data( face, glyph_index, 02554 &charstring, &charstring_len ); 02555 if ( !error ) 02556 { 02557 error = cff_decoder_prepare( &decoder, size, glyph_index ); 02558 if ( !error ) 02559 error = cff_decoder_parse_charstrings( &decoder, 02560 charstring, 02561 charstring_len ); 02562 02563 cff_free_glyph_data( face, &charstring, &charstring_len ); 02564 } 02565 02566 /* ignore the error if one has occurred -- skip to next glyph */ 02567 error = CFF_Err_Ok; 02568 } 02569 02570 *max_advance = decoder.builder.advance.x; 02571 02572 return CFF_Err_Ok; 02573 } 02574 02575 02576 #endif /* 0 */ 02577 02578 02579 FT_LOCAL_DEF( FT_Error ) 02580 cff_slot_load( CFF_GlyphSlot glyph, 02581 CFF_Size size, 02582 FT_UInt glyph_index, 02583 FT_Int32 load_flags ) 02584 { 02585 FT_Error error; 02586 CFF_Decoder decoder; 02587 TT_Face face = (TT_Face)glyph->root.face; 02588 FT_Bool hinting, force_scaling; 02589 CFF_Font cff = (CFF_Font)face->extra.data; 02590 02591 FT_Matrix font_matrix; 02592 FT_Vector font_offset; 02593 02594 02595 force_scaling = FALSE; 02596 02597 /* in a CID-keyed font, consider `glyph_index' as a CID and map */ 02598 /* it immediately to the real glyph_index -- if it isn't a */ 02599 /* subsetted font, glyph_indices and CIDs are identical, though */ 02600 if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && 02601 cff->charset.cids ) 02602 { 02603 /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */ 02604 if ( glyph_index != 0 ) 02605 { 02606 glyph_index = cff_charset_cid_to_gindex( &cff->charset, 02607 glyph_index ); 02608 if ( glyph_index == 0 ) 02609 return CFF_Err_Invalid_Argument; 02610 } 02611 } 02612 else if ( glyph_index >= cff->num_glyphs ) 02613 return CFF_Err_Invalid_Argument; 02614 02615 if ( load_flags & FT_LOAD_NO_RECURSE ) 02616 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 02617 02618 glyph->x_scale = 0x10000L; 02619 glyph->y_scale = 0x10000L; 02620 if ( size ) 02621 { 02622 glyph->x_scale = size->root.metrics.x_scale; 02623 glyph->y_scale = size->root.metrics.y_scale; 02624 } 02625 02626 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 02627 02628 /* try to load embedded bitmap if any */ 02629 /* */ 02630 /* XXX: The convention should be emphasized in */ 02631 /* the documents because it can be confusing. */ 02632 if ( size ) 02633 { 02634 CFF_Face cff_face = (CFF_Face)size->root.face; 02635 SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; 02636 FT_Stream stream = cff_face->root.stream; 02637 02638 02639 if ( size->strike_index != 0xFFFFFFFFUL && 02640 sfnt->load_eblc && 02641 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) 02642 { 02643 TT_SBit_MetricsRec metrics; 02644 02645 02646 error = sfnt->load_sbit_image( face, 02647 size->strike_index, 02648 glyph_index, 02649 (FT_Int)load_flags, 02650 stream, 02651 &glyph->root.bitmap, 02652 &metrics ); 02653 02654 if ( !error ) 02655 { 02656 glyph->root.outline.n_points = 0; 02657 glyph->root.outline.n_contours = 0; 02658 02659 glyph->root.metrics.width = (FT_Pos)metrics.width << 6; 02660 glyph->root.metrics.height = (FT_Pos)metrics.height << 6; 02661 02662 glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; 02663 glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; 02664 glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; 02665 02666 glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; 02667 glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; 02668 glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; 02669 02670 glyph->root.format = FT_GLYPH_FORMAT_BITMAP; 02671 02672 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 02673 { 02674 glyph->root.bitmap_left = metrics.vertBearingX; 02675 glyph->root.bitmap_top = metrics.vertBearingY; 02676 } 02677 else 02678 { 02679 glyph->root.bitmap_left = metrics.horiBearingX; 02680 glyph->root.bitmap_top = metrics.horiBearingY; 02681 } 02682 return error; 02683 } 02684 } 02685 } 02686 02687 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 02688 02689 /* return immediately if we only want the embedded bitmaps */ 02690 if ( load_flags & FT_LOAD_SBITS_ONLY ) 02691 return CFF_Err_Invalid_Argument; 02692 02693 /* if we have a CID subfont, use its matrix (which has already */ 02694 /* been multiplied with the root matrix) */ 02695 02696 /* this scaling is only relevant if the PS hinter isn't active */ 02697 if ( cff->num_subfonts ) 02698 { 02699 FT_ULong top_upm, sub_upm; 02700 FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, 02701 glyph_index ); 02702 02703 if ( fd_index >= cff->num_subfonts ) 02704 fd_index = cff->num_subfonts - 1; 02705 02706 top_upm = cff->top_font.font_dict.units_per_em; 02707 sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em; 02708 02709 02710 font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; 02711 font_offset = cff->subfonts[fd_index]->font_dict.font_offset; 02712 02713 if ( top_upm != sub_upm ) 02714 { 02715 glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm ); 02716 glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm ); 02717 02718 force_scaling = TRUE; 02719 } 02720 } 02721 else 02722 { 02723 font_matrix = cff->top_font.font_dict.font_matrix; 02724 font_offset = cff->top_font.font_dict.font_offset; 02725 } 02726 02727 glyph->root.outline.n_points = 0; 02728 glyph->root.outline.n_contours = 0; 02729 02730 hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && 02731 ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); 02732 02733 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ 02734 02735 { 02736 FT_Byte* charstring; 02737 FT_ULong charstring_len; 02738 02739 02740 cff_decoder_init( &decoder, face, size, glyph, hinting, 02741 FT_LOAD_TARGET_MODE( load_flags ) ); 02742 02743 if ( load_flags & FT_LOAD_ADVANCE_ONLY ) 02744 decoder.width_only = TRUE; 02745 02746 decoder.builder.no_recurse = 02747 (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE ); 02748 02749 /* now load the unscaled outline */ 02750 error = cff_get_glyph_data( face, glyph_index, 02751 &charstring, &charstring_len ); 02752 if ( error ) 02753 goto Glyph_Build_Finished; 02754 02755 error = cff_decoder_prepare( &decoder, size, glyph_index ); 02756 if ( error ) 02757 goto Glyph_Build_Finished; 02758 02759 error = cff_decoder_parse_charstrings( &decoder, 02760 charstring, 02761 charstring_len ); 02762 02763 cff_free_glyph_data( face, &charstring, charstring_len ); 02764 02765 if ( error ) 02766 goto Glyph_Build_Finished; 02767 02768 #ifdef FT_CONFIG_OPTION_INCREMENTAL 02769 /* Control data and length may not be available for incremental */ 02770 /* fonts. */ 02771 if ( face->root.internal->incremental_interface ) 02772 { 02773 glyph->root.control_data = 0; 02774 glyph->root.control_len = 0; 02775 } 02776 else 02777 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 02778 02779 /* We set control_data and control_len if charstrings is loaded. */ 02780 /* See how charstring loads at cff_index_access_element() in */ 02781 /* cffload.c. */ 02782 { 02783 CFF_Index csindex = &cff->charstrings_index; 02784 02785 02786 if ( csindex->offsets ) 02787 { 02788 glyph->root.control_data = csindex->bytes + 02789 csindex->offsets[glyph_index] - 1; 02790 glyph->root.control_len = charstring_len; 02791 } 02792 } 02793 02794 Glyph_Build_Finished: 02795 /* save new glyph tables, if no error */ 02796 if ( !error ) 02797 cff_builder_done( &decoder.builder ); 02798 /* XXX: anything to do for broken glyph entry? */ 02799 } 02800 02801 #ifdef FT_CONFIG_OPTION_INCREMENTAL 02802 02803 /* Incremental fonts can optionally override the metrics. */ 02804 if ( !error && 02805 face->root.internal->incremental_interface && 02806 face->root.internal->incremental_interface->funcs->get_glyph_metrics ) 02807 { 02808 FT_Incremental_MetricsRec metrics; 02809 02810 02811 metrics.bearing_x = decoder.builder.left_bearing.x; 02812 metrics.bearing_y = 0; 02813 metrics.advance = decoder.builder.advance.x; 02814 metrics.advance_v = decoder.builder.advance.y; 02815 02816 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 02817 face->root.internal->incremental_interface->object, 02818 glyph_index, FALSE, &metrics ); 02819 02820 decoder.builder.left_bearing.x = metrics.bearing_x; 02821 decoder.builder.advance.x = metrics.advance; 02822 decoder.builder.advance.y = metrics.advance_v; 02823 } 02824 02825 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 02826 02827 if ( !error ) 02828 { 02829 /* Now, set the metrics -- this is rather simple, as */ 02830 /* the left side bearing is the xMin, and the top side */ 02831 /* bearing the yMax. */ 02832 02833 /* For composite glyphs, return only left side bearing and */ 02834 /* advance width. */ 02835 if ( load_flags & FT_LOAD_NO_RECURSE ) 02836 { 02837 FT_Slot_Internal internal = glyph->root.internal; 02838 02839 02840 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; 02841 glyph->root.metrics.horiAdvance = decoder.glyph_width; 02842 internal->glyph_matrix = font_matrix; 02843 internal->glyph_delta = font_offset; 02844 internal->glyph_transformed = 1; 02845 } 02846 else 02847 { 02848 FT_BBox cbox; 02849 FT_Glyph_Metrics* metrics = &glyph->root.metrics; 02850 FT_Vector advance; 02851 FT_Bool has_vertical_info; 02852 02853 02854 /* copy the _unscaled_ advance width */ 02855 metrics->horiAdvance = decoder.glyph_width; 02856 glyph->root.linearHoriAdvance = decoder.glyph_width; 02857 glyph->root.internal->glyph_transformed = 0; 02858 02859 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 02860 has_vertical_info = FT_BOOL( face->vertical_info && 02861 face->vertical.number_Of_VMetrics > 0 && 02862 face->vertical.long_metrics ); 02863 #else 02864 has_vertical_info = FT_BOOL( face->vertical_info && 02865 face->vertical.number_Of_VMetrics > 0 ); 02866 #endif 02867 02868 /* get the vertical metrics from the vtmx table if we have one */ 02869 if ( has_vertical_info ) 02870 { 02871 FT_Short vertBearingY = 0; 02872 FT_UShort vertAdvance = 0; 02873 02874 02875 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, 02876 glyph_index, 02877 &vertBearingY, 02878 &vertAdvance ); 02879 metrics->vertBearingY = vertBearingY; 02880 metrics->vertAdvance = vertAdvance; 02881 } 02882 else 02883 { 02884 /* make up vertical ones */ 02885 if ( face->os2.version != 0xFFFFU ) 02886 metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender - 02887 face->os2.sTypoDescender ); 02888 else 02889 metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender - 02890 face->horizontal.Descender ); 02891 } 02892 02893 glyph->root.linearVertAdvance = metrics->vertAdvance; 02894 02895 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; 02896 02897 glyph->root.outline.flags = 0; 02898 if ( size && size->root.metrics.y_ppem < 24 ) 02899 glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; 02900 02901 glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; 02902 02903 if ( !( font_matrix.xx == 0x10000L && 02904 font_matrix.yy == 0x10000L && 02905 font_matrix.xy == 0 && 02906 font_matrix.yx == 0 ) ) 02907 FT_Outline_Transform( &glyph->root.outline, &font_matrix ); 02908 02909 if ( !( font_offset.x == 0 && 02910 font_offset.y == 0 ) ) 02911 FT_Outline_Translate( &glyph->root.outline, 02912 font_offset.x, font_offset.y ); 02913 02914 advance.x = metrics->horiAdvance; 02915 advance.y = 0; 02916 FT_Vector_Transform( &advance, &font_matrix ); 02917 metrics->horiAdvance = advance.x + font_offset.x; 02918 02919 advance.x = 0; 02920 advance.y = metrics->vertAdvance; 02921 FT_Vector_Transform( &advance, &font_matrix ); 02922 metrics->vertAdvance = advance.y + font_offset.y; 02923 02924 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) 02925 { 02926 /* scale the outline and the metrics */ 02927 FT_Int n; 02928 FT_Outline* cur = &glyph->root.outline; 02929 FT_Vector* vec = cur->points; 02930 FT_Fixed x_scale = glyph->x_scale; 02931 FT_Fixed y_scale = glyph->y_scale; 02932 02933 02934 /* First of all, scale the points */ 02935 if ( !hinting || !decoder.builder.hints_funcs ) 02936 for ( n = cur->n_points; n > 0; n--, vec++ ) 02937 { 02938 vec->x = FT_MulFix( vec->x, x_scale ); 02939 vec->y = FT_MulFix( vec->y, y_scale ); 02940 } 02941 02942 /* Then scale the metrics */ 02943 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 02944 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 02945 } 02946 02947 /* compute the other metrics */ 02948 FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); 02949 02950 metrics->width = cbox.xMax - cbox.xMin; 02951 metrics->height = cbox.yMax - cbox.yMin; 02952 02953 metrics->horiBearingX = cbox.xMin; 02954 metrics->horiBearingY = cbox.yMax; 02955 02956 if ( has_vertical_info ) 02957 metrics->vertBearingX = metrics->horiBearingX - 02958 metrics->horiAdvance / 2; 02959 else 02960 { 02961 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 02962 ft_synthesize_vertical_metrics( metrics, 02963 metrics->vertAdvance ); 02964 } 02965 } 02966 } 02967 02968 return error; 02969 } 02970 02971 02972 /* END */ Generated on Sat May 26 2012 04:32:40 for ReactOS by
1.7.6.1
|