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