Index: core/src/fxge/fx_freetype/fxft2.5.01/src/psaux/t1decode.c |
diff --git a/core/src/fxge/fx_freetype/fxft2.5.01/src/psaux/t1decode.c b/core/src/fxge/fx_freetype/fxft2.5.01/src/psaux/t1decode.c |
deleted file mode 100644 |
index abf1d741519b1abaf4c62ecfb06b8bc661297e6b..0000000000000000000000000000000000000000 |
--- a/core/src/fxge/fx_freetype/fxft2.5.01/src/psaux/t1decode.c |
+++ /dev/null |
@@ -1,1620 +0,0 @@ |
-/***************************************************************************/ |
-/* */ |
-/* t1decode.c */ |
-/* */ |
-/* PostScript Type 1 decoding routines (body). */ |
-/* */ |
-/* Copyright 2000-2013 by */ |
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
-/* */ |
-/* This file is part of the FreeType project, and may only be used, */ |
-/* modified, and distributed under the terms of the FreeType project */ |
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
-/* this file you indicate that you have read the license and */ |
-/* understand and accept it fully. */ |
-/* */ |
-/***************************************************************************/ |
- |
- |
-#include "../../include/ft2build.h" |
-#include "../../include/freetype/internal/ftcalc.h" |
-#include "../../include/freetype/internal/ftdebug.h" |
-#include "../../include/freetype/internal/pshints.h" |
-#include "../../include/freetype/ftoutln.h" |
- |
-#include "t1decode.h" |
-#include "psobjs.h" |
- |
-#include "psauxerr.h" |
- |
-/* ensure proper sign extension */ |
-#define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) ) |
- |
- /*************************************************************************/ |
- /* */ |
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
- /* messages during execution. */ |
- /* */ |
-#undef FT_COMPONENT |
-#define FT_COMPONENT trace_t1decode |
- |
- |
- typedef enum T1_Operator_ |
- { |
- op_none = 0, |
- op_endchar, |
- op_hsbw, |
- op_seac, |
- op_sbw, |
- op_closepath, |
- op_hlineto, |
- op_hmoveto, |
- op_hvcurveto, |
- op_rlineto, |
- op_rmoveto, |
- op_rrcurveto, |
- op_vhcurveto, |
- op_vlineto, |
- op_vmoveto, |
- op_dotsection, |
- op_hstem, |
- op_hstem3, |
- op_vstem, |
- op_vstem3, |
- op_div, |
- op_callothersubr, |
- op_callsubr, |
- op_pop, |
- op_return, |
- op_setcurrentpoint, |
- op_unknown15, |
- |
- op_max /* never remove this one */ |
- |
- } T1_Operator; |
- |
- |
- static |
- const FT_Int t1_args_count[op_max] = |
- { |
- 0, /* none */ |
- 0, /* endchar */ |
- 2, /* hsbw */ |
- 5, /* seac */ |
- 4, /* sbw */ |
- 0, /* closepath */ |
- 1, /* hlineto */ |
- 1, /* hmoveto */ |
- 4, /* hvcurveto */ |
- 2, /* rlineto */ |
- 2, /* rmoveto */ |
- 6, /* rrcurveto */ |
- 4, /* vhcurveto */ |
- 1, /* vlineto */ |
- 1, /* vmoveto */ |
- 0, /* dotsection */ |
- 2, /* hstem */ |
- 6, /* hstem3 */ |
- 2, /* vstem */ |
- 6, /* vstem3 */ |
- 2, /* div */ |
- -1, /* callothersubr */ |
- 1, /* callsubr */ |
- 0, /* pop */ |
- 0, /* return */ |
- 2, /* setcurrentpoint */ |
- 2 /* opcode 15 (undocumented and obsolete) */ |
- }; |
- |
- |
- /*************************************************************************/ |
- /* */ |
- /* <Function> */ |
- /* t1_lookup_glyph_by_stdcharcode */ |
- /* */ |
- /* <Description> */ |
- /* Looks up a given glyph by its StandardEncoding charcode. Used to */ |
- /* implement the SEAC Type 1 operator. */ |
- /* */ |
- /* <Input> */ |
- /* face :: The current face object. */ |
- /* */ |
- /* charcode :: The character code to look for. */ |
- /* */ |
- /* <Return> */ |
- /* A glyph index in the font face. Returns -1 if the corresponding */ |
- /* glyph wasn't found. */ |
- /* */ |
- static FT_Int |
- t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder, |
- FT_Int charcode ) |
- { |
- FT_UInt n; |
- const FT_String* glyph_name; |
- FT_Service_PsCMaps psnames = decoder->psnames; |
- |
- |
- /* check range of standard char code */ |
- if ( charcode < 0 || charcode > 255 ) |
- return -1; |
- |
- glyph_name = psnames->adobe_std_strings( |
- psnames->adobe_std_encoding[charcode]); |
- |
- for ( n = 0; n < decoder->num_glyphs; n++ ) |
- { |
- FT_String* name = (FT_String*)decoder->glyph_names[n]; |
- |
- |
- if ( name && |
- name[0] == glyph_name[0] && |
- ft_strcmp( name, glyph_name ) == 0 ) |
- return n; |
- } |
- |
- return -1; |
- } |
- |
- |
- /*************************************************************************/ |
- /* */ |
- /* <Function> */ |
- /* t1operator_seac */ |
- /* */ |
- /* <Description> */ |
- /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ |
- /* */ |
- /* <Input> */ |
- /* decoder :: The current CID decoder. */ |
- /* */ |
- /* asb :: The accent's side bearing. */ |
- /* */ |
- /* adx :: The horizontal offset of the accent. */ |
- /* */ |
- /* ady :: The vertical offset of the accent. */ |
- /* */ |
- /* bchar :: The base character's StandardEncoding charcode. */ |
- /* */ |
- /* achar :: The accent character's StandardEncoding charcode. */ |
- /* */ |
- /* <Return> */ |
- /* FreeType error code. 0 means success. */ |
- /* */ |
- static FT_Error |
- t1operator_seac( T1_Decoder decoder, |
- FT_Pos asb, |
- FT_Pos adx, |
- FT_Pos ady, |
- FT_Int bchar, |
- FT_Int achar ) |
- { |
- FT_Error error; |
- FT_Int bchar_index, achar_index; |
-#if 0 |
- FT_Int n_base_points; |
- FT_Outline* base = decoder->builder.base; |
-#endif |
- FT_Vector left_bearing, advance; |
- |
-#ifdef FT_CONFIG_OPTION_INCREMENTAL |
- T1_Face face = (T1_Face)decoder->builder.face; |
-#endif |
- |
- |
- if ( decoder->seac ) |
- { |
- FT_ERROR(( "t1operator_seac: invalid nested seac\n" )); |
- return FT_THROW( Syntax_Error ); |
- } |
- |
- if ( decoder->builder.metrics_only ) |
- { |
- FT_ERROR(( "t1operator_seac: unexpected seac\n" )); |
- return FT_THROW( Syntax_Error ); |
- } |
- |
- /* seac weirdness */ |
- adx += decoder->builder.left_bearing.x; |
- |
- /* `glyph_names' is set to 0 for CID fonts which do not */ |
- /* include an encoding. How can we deal with these? */ |
-#ifdef FT_CONFIG_OPTION_INCREMENTAL |
- if ( decoder->glyph_names == 0 && |
- !face->root.internal->incremental_interface ) |
-#else |
- if ( decoder->glyph_names == 0 ) |
-#endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
- { |
- FT_ERROR(( "t1operator_seac:" |
- " glyph names table not available in this font\n" )); |
- return FT_THROW( Syntax_Error ); |
- } |
- |
-#ifdef FT_CONFIG_OPTION_INCREMENTAL |
- if ( face->root.internal->incremental_interface ) |
- { |
- /* the caller must handle the font encoding also */ |
- bchar_index = bchar; |
- achar_index = achar; |
- } |
- else |
-#endif |
- { |
- bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar ); |
- achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar ); |
- } |
- |
- if ( bchar_index < 0 || achar_index < 0 ) |
- { |
- FT_ERROR(( "t1operator_seac:" |
- " invalid seac character code arguments\n" )); |
- return FT_THROW( Syntax_Error ); |
- } |
- |
- /* if we are trying to load a composite glyph, do not load the */ |
- /* accent character and return the array of subglyphs. */ |
- if ( decoder->builder.no_recurse ) |
- { |
- FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; |
- FT_GlyphLoader loader = glyph->internal->loader; |
- FT_SubGlyph subg; |
- |
- |
- /* reallocate subglyph array if necessary */ |
- error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); |
- if ( error ) |
- goto Exit; |
- |
- subg = loader->current.subglyphs; |
- |
- /* subglyph 0 = base character */ |
- subg->index = bchar_index; |
- subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | |
- FT_SUBGLYPH_FLAG_USE_MY_METRICS; |
- subg->arg1 = 0; |
- subg->arg2 = 0; |
- subg++; |
- |
- /* subglyph 1 = accent character */ |
- subg->index = achar_index; |
- subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; |
- subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb ); |
- subg->arg2 = (FT_Int)FIXED_TO_INT( ady ); |
- |
- /* set up remaining glyph fields */ |
- glyph->num_subglyphs = 2; |
- glyph->subglyphs = loader->base.subglyphs; |
- glyph->format = FT_GLYPH_FORMAT_COMPOSITE; |
- |
- loader->current.num_subglyphs = 2; |
- goto Exit; |
- } |
- |
- /* First load `bchar' in builder */ |
- /* now load the unscaled outline */ |
- |
- FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ |
- |
- /* the seac operator must not be nested */ |
- decoder->seac = TRUE; |
- error = t1_decoder_parse_glyph( decoder, bchar_index ); |
- decoder->seac = FALSE; |
- if ( error ) |
- goto Exit; |
- |
- /* save the left bearing and width of the base character */ |
- /* as they will be erased by the next load. */ |
- |
- left_bearing = decoder->builder.left_bearing; |
- advance = decoder->builder.advance; |
- |
- decoder->builder.left_bearing.x = 0; |
- decoder->builder.left_bearing.y = 0; |
- |
- decoder->builder.pos_x = adx - asb; |
- decoder->builder.pos_y = ady; |
- |
- /* Now load `achar' on top of */ |
- /* the base outline */ |
- |
- /* the seac operator must not be nested */ |
- decoder->seac = TRUE; |
- error = t1_decoder_parse_glyph( decoder, achar_index ); |
- decoder->seac = FALSE; |
- if ( error ) |
- goto Exit; |
- |
- /* restore the left side bearing and */ |
- /* advance width of the base character */ |
- |
- decoder->builder.left_bearing = left_bearing; |
- decoder->builder.advance = advance; |
- |
- decoder->builder.pos_x = 0; |
- decoder->builder.pos_y = 0; |
- |
- Exit: |
- return error; |
- } |
- |
- |
- /*************************************************************************/ |
- /* */ |
- /* <Function> */ |
- /* t1_decoder_parse_charstrings */ |
- /* */ |
- /* <Description> */ |
- /* Parses a given Type 1 charstrings program. */ |
- /* */ |
- /* <Input> */ |
- /* decoder :: The current Type 1 decoder. */ |
- /* */ |
- /* charstring_base :: The base address of the charstring stream. */ |
- /* */ |
- /* charstring_len :: The length in bytes of the charstring stream. */ |
- /* */ |
- /* <Return> */ |
- /* FreeType error code. 0 means success. */ |
- /* */ |
- FT_LOCAL_DEF( FT_Error ) |
- t1_decoder_parse_charstrings( T1_Decoder decoder, |
- FT_Byte* charstring_base, |
- FT_UInt charstring_len ) |
- { |
- FT_Error error; |
- T1_Decoder_Zone zone; |
- FT_Byte* ip; |
- FT_Byte* limit; |
- T1_Builder builder = &decoder->builder; |
- FT_Pos x, y, orig_x, orig_y; |
- FT_Int known_othersubr_result_cnt = 0; |
- FT_Int unknown_othersubr_result_cnt = 0; |
- FT_Bool large_int; |
- FT_Fixed seed; |
- |
- T1_Hints_Funcs hinter; |
- |
-#ifdef FT_DEBUG_LEVEL_TRACE |
- FT_Bool bol = TRUE; |
-#endif |
- |
- |
- /* compute random seed from stack address of parameter */ |
- seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^ |
- (FT_PtrDist)(char*)&decoder ^ |
- (FT_PtrDist)(char*)&charstring_base ) & |
- FT_ULONG_MAX ) ; |
- seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; |
- if ( seed == 0 ) |
- seed = 0x7384; |
- |
- /* First of all, initialize the decoder */ |
- decoder->top = decoder->stack; |
- decoder->zone = decoder->zones; |
- zone = decoder->zones; |
- |
- builder->parse_state = T1_Parse_Start; |
- |
- hinter = (T1_Hints_Funcs)builder->hints_funcs; |
- |
- /* a font that reads BuildCharArray without setting */ |
- /* its values first is buggy, but ... */ |
- FT_ASSERT( ( decoder->len_buildchar == 0 ) == |
- ( decoder->buildchar == NULL ) ); |
- |
- if ( decoder->buildchar && decoder->len_buildchar > 0 ) |
- ft_memset( &decoder->buildchar[0], |
- 0, |
- sizeof ( decoder->buildchar[0] ) * decoder->len_buildchar ); |
- |
- FT_TRACE4(( "\n" |
- "Start charstring\n" )); |
- |
- zone->base = charstring_base; |
- limit = zone->limit = charstring_base + charstring_len; |
- ip = zone->cursor = zone->base; |
- |
- error = FT_Err_Ok; |
- |
- x = orig_x = builder->pos_x; |
- y = orig_y = builder->pos_y; |
- |
- /* begin hints recording session, if any */ |
- if ( hinter ) |
- hinter->open( hinter->hints ); |
- |
- large_int = FALSE; |
- |
- /* now, execute loop */ |
- while ( ip < limit ) |
- { |
- FT_Long* top = decoder->top; |
- T1_Operator op = op_none; |
- FT_Int32 value = 0; |
- |
- |
- FT_ASSERT( known_othersubr_result_cnt == 0 || |
- unknown_othersubr_result_cnt == 0 ); |
- |
-#ifdef FT_DEBUG_LEVEL_TRACE |
- if ( bol ) |
- { |
- FT_TRACE5(( " (%d)", decoder->top - decoder->stack )); |
- bol = FALSE; |
- } |
-#endif |
- |
- /*********************************************************************/ |
- /* */ |
- /* Decode operator or operand */ |
- /* */ |
- /* */ |
- |
- /* first of all, decompress operator or value */ |
- switch ( *ip++ ) |
- { |
- case 1: |
- op = op_hstem; |
- break; |
- |
- case 3: |
- op = op_vstem; |
- break; |
- case 4: |
- op = op_vmoveto; |
- break; |
- case 5: |
- op = op_rlineto; |
- break; |
- case 6: |
- op = op_hlineto; |
- break; |
- case 7: |
- op = op_vlineto; |
- break; |
- case 8: |
- op = op_rrcurveto; |
- break; |
- case 9: |
- op = op_closepath; |
- break; |
- case 10: |
- op = op_callsubr; |
- break; |
- case 11: |
- op = op_return; |
- break; |
- |
- case 13: |
- op = op_hsbw; |
- break; |
- case 14: |
- op = op_endchar; |
- break; |
- |
- case 15: /* undocumented, obsolete operator */ |
- op = op_unknown15; |
- break; |
- |
- case 21: |
- op = op_rmoveto; |
- break; |
- case 22: |
- op = op_hmoveto; |
- break; |
- |
- case 30: |
- op = op_vhcurveto; |
- break; |
- case 31: |
- op = op_hvcurveto; |
- break; |
- |
- case 12: |
- if ( ip > limit ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " invalid escape (12+EOF)\n" )); |
- goto Syntax_Error; |
- } |
- |
- switch ( *ip++ ) |
- { |
- case 0: |
- op = op_dotsection; |
- break; |
- case 1: |
- op = op_vstem3; |
- break; |
- case 2: |
- op = op_hstem3; |
- break; |
- case 6: |
- op = op_seac; |
- break; |
- case 7: |
- op = op_sbw; |
- break; |
- case 12: |
- op = op_div; |
- break; |
- case 16: |
- op = op_callothersubr; |
- break; |
- case 17: |
- op = op_pop; |
- break; |
- case 33: |
- op = op_setcurrentpoint; |
- break; |
- |
- default: |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " invalid escape (12+%d)\n", |
- ip[-1] )); |
- goto Syntax_Error; |
- } |
- break; |
- |
- case 255: /* four bytes integer */ |
- if ( ip + 4 > limit ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " unexpected EOF in integer\n" )); |
- goto Syntax_Error; |
- } |
- |
- value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | |
- ( (FT_UInt32)ip[1] << 16 ) | |
- ( (FT_UInt32)ip[2] << 8 ) | |
- (FT_UInt32)ip[3] ); |
- ip += 4; |
- |
- /* According to the specification, values > 32000 or < -32000 must */ |
- /* be followed by a `div' operator to make the result be in the */ |
- /* range [-32000;32000]. We expect that the second argument of */ |
- /* `div' is not a large number. Additionally, we don't handle */ |
- /* stuff like `<large1> <large2> <num> div <num> div' or */ |
- /* <large1> <large2> <num> div div'. This is probably not allowed */ |
- /* anyway. */ |
- if ( value > 32000 || value < -32000 ) |
- { |
- if ( large_int ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " no `div' after large integer\n" )); |
- } |
- else |
- large_int = TRUE; |
- } |
- else |
- { |
- if ( !large_int ) |
- value = (FT_Int32)( (FT_UInt32)value << 16 ); |
- } |
- |
- break; |
- |
- default: |
- if ( ip[-1] >= 32 ) |
- { |
- if ( ip[-1] < 247 ) |
- value = (FT_Int32)ip[-1] - 139; |
- else |
- { |
- if ( ++ip > limit ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " unexpected EOF in integer\n" )); |
- goto Syntax_Error; |
- } |
- |
- if ( ip[-2] < 251 ) |
- value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108; |
- else |
- value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 ); |
- } |
- |
- if ( !large_int ) |
- value = (FT_Int32)( (FT_UInt32)value << 16 ); |
- } |
- else |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " invalid byte (%d)\n", ip[-1] )); |
- goto Syntax_Error; |
- } |
- } |
- |
- if ( unknown_othersubr_result_cnt > 0 ) |
- { |
- switch ( op ) |
- { |
- case op_callsubr: |
- case op_return: |
- case op_none: |
- case op_pop: |
- break; |
- |
- default: |
- /* all operands have been transferred by previous pops */ |
- unknown_othersubr_result_cnt = 0; |
- break; |
- } |
- } |
- |
- if ( large_int && !( op == op_none || op == op_div ) ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " no `div' after large integer\n" )); |
- |
- large_int = FALSE; |
- } |
- |
- /*********************************************************************/ |
- /* */ |
- /* Push value on stack, or process operator */ |
- /* */ |
- /* */ |
- if ( op == op_none ) |
- { |
- if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" )); |
- goto Syntax_Error; |
- } |
- |
-#ifdef FT_DEBUG_LEVEL_TRACE |
- if ( large_int ) |
- FT_TRACE4(( " %ld", value )); |
- else |
- FT_TRACE4(( " %ld", Fix2Int( value ) )); |
-#endif |
- |
- *top++ = value; |
- decoder->top = top; |
- } |
- else if ( op == op_callothersubr ) /* callothersubr */ |
- { |
- FT_Int subr_no; |
- FT_Int arg_cnt; |
- |
- |
-#ifdef FT_DEBUG_LEVEL_TRACE |
- FT_TRACE4(( " callothersubr\n" )); |
- bol = TRUE; |
-#endif |
- |
- if ( top - decoder->stack < 2 ) |
- goto Stack_Underflow; |
- |
- top -= 2; |
- |
- subr_no = Fix2Int( top[1] ); |
- arg_cnt = Fix2Int( top[0] ); |
- |
- /***********************************************************/ |
- /* */ |
- /* remove all operands to callothersubr from the stack */ |
- /* */ |
- /* for handled othersubrs, where we know the number of */ |
- /* arguments, we increase the stack by the value of */ |
- /* known_othersubr_result_cnt */ |
- /* */ |
- /* for unhandled othersubrs the following pops adjust the */ |
- /* stack pointer as necessary */ |
- |
- if ( arg_cnt > top - decoder->stack ) |
- goto Stack_Underflow; |
- |
- top -= arg_cnt; |
- |
- known_othersubr_result_cnt = 0; |
- unknown_othersubr_result_cnt = 0; |
- |
- /* XXX TODO: The checks to `arg_count == <whatever>' */ |
- /* might not be correct; an othersubr expects a certain */ |
- /* number of operands on the PostScript stack (as opposed */ |
- /* to the T1 stack) but it doesn't have to put them there */ |
- /* by itself; previous othersubrs might have left the */ |
- /* operands there if they were not followed by an */ |
- /* appropriate number of pops */ |
- /* */ |
- /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */ |
- /* accept a font that contains charstrings like */ |
- /* */ |
- /* 100 200 2 20 callothersubr */ |
- /* 300 1 20 callothersubr pop */ |
- /* */ |
- /* Perhaps this is the reason why BuildCharArray exists. */ |
- |
- switch ( subr_no ) |
- { |
- case 0: /* end flex feature */ |
- if ( arg_cnt != 3 ) |
- goto Unexpected_OtherSubr; |
- |
- if ( decoder->flex_state == 0 || |
- decoder->num_flex_vectors != 7 ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " unexpected flex end\n" )); |
- goto Syntax_Error; |
- } |
- |
- /* the two `results' are popped by the following setcurrentpoint */ |
- top[0] = x; |
- top[1] = y; |
- known_othersubr_result_cnt = 2; |
- break; |
- |
- case 1: /* start flex feature */ |
- if ( arg_cnt != 0 ) |
- goto Unexpected_OtherSubr; |
- |
- decoder->flex_state = 1; |
- decoder->num_flex_vectors = 0; |
- if ( ( error = t1_builder_start_point( builder, x, y ) ) |
- != FT_Err_Ok || |
- ( error = t1_builder_check_points( builder, 6 ) ) |
- != FT_Err_Ok ) |
- goto Fail; |
- break; |
- |
- case 2: /* add flex vectors */ |
- { |
- FT_Int idx; |
- |
- |
- if ( arg_cnt != 0 ) |
- goto Unexpected_OtherSubr; |
- |
- if ( decoder->flex_state == 0 ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " missing flex start\n" )); |
- goto Syntax_Error; |
- } |
- |
- /* note that we should not add a point for index 0; */ |
- /* this will move our current position to the flex */ |
- /* point without adding any point to the outline */ |
- idx = decoder->num_flex_vectors++; |
- if ( idx > 0 && idx < 7 ) |
- t1_builder_add_point( builder, |
- x, |
- y, |
- (FT_Byte)( idx == 3 || idx == 6 ) ); |
- } |
- break; |
- |
- case 3: /* change hints */ |
- if ( arg_cnt != 1 ) |
- goto Unexpected_OtherSubr; |
- |
- known_othersubr_result_cnt = 1; |
- |
- if ( hinter ) |
- hinter->reset( hinter->hints, builder->current->n_points ); |
- break; |
- |
- case 12: |
- case 13: |
- /* counter control hints, clear stack */ |
- top = decoder->stack; |
- break; |
- |
- case 14: |
- case 15: |
- case 16: |
- case 17: |
- case 18: /* multiple masters */ |
- { |
- PS_Blend blend = decoder->blend; |
- FT_UInt num_points, nn, mm; |
- FT_Long* delta; |
- FT_Long* values; |
- |
- |
- if ( !blend ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " unexpected multiple masters operator\n" )); |
- goto Syntax_Error; |
- } |
- |
- num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 ); |
- if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " incorrect number of multiple masters arguments\n" )); |
- goto Syntax_Error; |
- } |
- |
- /* We want to compute */ |
- /* */ |
- /* a0*w0 + a1*w1 + ... + ak*wk */ |
- /* */ |
- /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ |
- /* */ |
- /* However, given that w0 + w1 + ... + wk == 1, we can */ |
- /* rewrite it easily as */ |
- /* */ |
- /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ |
- /* */ |
- /* where k == num_designs-1. */ |
- /* */ |
- /* I guess that's why it's written in this `compact' */ |
- /* form. */ |
- /* */ |
- delta = top + num_points; |
- values = top; |
- for ( nn = 0; nn < num_points; nn++ ) |
- { |
- FT_Long tmp = values[0]; |
- |
- |
- for ( mm = 1; mm < blend->num_designs; mm++ ) |
- tmp += FT_MulFix( *delta++, blend->weight_vector[mm] ); |
- |
- *values++ = tmp; |
- } |
- |
- known_othersubr_result_cnt = num_points; |
- break; |
- } |
- |
- case 19: |
- /* <idx> 1 19 callothersubr */ |
- /* => replace elements starting from index cvi( <idx> ) */ |
- /* of BuildCharArray with WeightVector */ |
- { |
- FT_Int idx; |
- PS_Blend blend = decoder->blend; |
- |
- |
- if ( arg_cnt != 1 || blend == NULL ) |
- goto Unexpected_OtherSubr; |
- |
- idx = Fix2Int( top[0] ); |
- |
- if ( idx < 0 || |
- idx + blend->num_designs > decoder->len_buildchar ) |
- goto Unexpected_OtherSubr; |
- |
- ft_memcpy( &decoder->buildchar[idx], |
- blend->weight_vector, |
- blend->num_designs * |
- sizeof ( blend->weight_vector[0] ) ); |
- } |
- break; |
- |
- case 20: |
- /* <arg1> <arg2> 2 20 callothersubr pop */ |
- /* ==> push <arg1> + <arg2> onto T1 stack */ |
- if ( arg_cnt != 2 ) |
- goto Unexpected_OtherSubr; |
- |
- top[0] += top[1]; /* XXX (over|under)flow */ |
- |
- known_othersubr_result_cnt = 1; |
- break; |
- |
- case 21: |
- /* <arg1> <arg2> 2 21 callothersubr pop */ |
- /* ==> push <arg1> - <arg2> onto T1 stack */ |
- if ( arg_cnt != 2 ) |
- goto Unexpected_OtherSubr; |
- |
- top[0] -= top[1]; /* XXX (over|under)flow */ |
- |
- known_othersubr_result_cnt = 1; |
- break; |
- |
- case 22: |
- /* <arg1> <arg2> 2 22 callothersubr pop */ |
- /* ==> push <arg1> * <arg2> onto T1 stack */ |
- if ( arg_cnt != 2 ) |
- goto Unexpected_OtherSubr; |
- |
- top[0] = FT_MulFix( top[0], top[1] ); |
- |
- known_othersubr_result_cnt = 1; |
- break; |
- |
- case 23: |
- /* <arg1> <arg2> 2 23 callothersubr pop */ |
- /* ==> push <arg1> / <arg2> onto T1 stack */ |
- if ( arg_cnt != 2 || top[1] == 0 ) |
- goto Unexpected_OtherSubr; |
- |
- top[0] = FT_DivFix( top[0], top[1] ); |
- |
- known_othersubr_result_cnt = 1; |
- break; |
- |
- case 24: |
- /* <val> <idx> 2 24 callothersubr */ |
- /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ |
- { |
- FT_Int idx; |
- PS_Blend blend = decoder->blend; |
- |
- |
- if ( arg_cnt != 2 || blend == NULL ) |
- goto Unexpected_OtherSubr; |
- |
- idx = Fix2Int( top[1] ); |
- |
- if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) |
- goto Unexpected_OtherSubr; |
- |
- decoder->buildchar[idx] = top[0]; |
- } |
- break; |
- |
- case 25: |
- /* <idx> 1 25 callothersubr pop */ |
- /* ==> push BuildCharArray[cvi( idx )] */ |
- /* onto T1 stack */ |
- { |
- FT_Int idx; |
- PS_Blend blend = decoder->blend; |
- |
- |
- if ( arg_cnt != 1 || blend == NULL ) |
- goto Unexpected_OtherSubr; |
- |
- idx = Fix2Int( top[0] ); |
- |
- if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) |
- goto Unexpected_OtherSubr; |
- |
- top[0] = decoder->buildchar[idx]; |
- } |
- |
- known_othersubr_result_cnt = 1; |
- break; |
- |
-#if 0 |
- case 26: |
- /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */ |
- /* leave mark on T1 stack */ |
- /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */ |
- XXX which routine has left its mark on the (PostScript) stack?; |
- break; |
-#endif |
- |
- case 27: |
- /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ |
- /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ |
- /* otherwise push <res2> */ |
- if ( arg_cnt != 4 ) |
- goto Unexpected_OtherSubr; |
- |
- if ( top[2] > top[3] ) |
- top[0] = top[1]; |
- |
- known_othersubr_result_cnt = 1; |
- break; |
- |
- case 28: |
- /* 0 28 callothersubr pop */ |
- /* => push random value from interval [0, 1) onto stack */ |
- if ( arg_cnt != 0 ) |
- goto Unexpected_OtherSubr; |
- |
- { |
- FT_Fixed Rand; |
- |
- |
- Rand = seed; |
- if ( Rand >= 0x8000L ) |
- Rand++; |
- |
- top[0] = Rand; |
- |
- seed = FT_MulFix( seed, 0x10000L - seed ); |
- if ( seed == 0 ) |
- seed += 0x2873; |
- } |
- |
- known_othersubr_result_cnt = 1; |
- break; |
- |
- default: |
- if ( arg_cnt >= 0 && subr_no >= 0 ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " unknown othersubr [%d %d], wish me luck\n", |
- arg_cnt, subr_no )); |
- unknown_othersubr_result_cnt = arg_cnt; |
- break; |
- } |
- /* fall through */ |
- |
- Unexpected_OtherSubr: |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " invalid othersubr [%d %d]\n", arg_cnt, subr_no )); |
- goto Syntax_Error; |
- } |
- |
- top += known_othersubr_result_cnt; |
- |
- decoder->top = top; |
- } |
- else /* general operator */ |
- { |
- FT_Int num_args = t1_args_count[op]; |
- |
- |
- FT_ASSERT( num_args >= 0 ); |
- |
- if ( top - decoder->stack < num_args ) |
- goto Stack_Underflow; |
- |
- /* XXX Operators usually take their operands from the */ |
- /* bottom of the stack, i.e., the operands are */ |
- /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */ |
- /* only div, callsubr, and callothersubr are different. */ |
- /* In practice it doesn't matter (?). */ |
- |
-#ifdef FT_DEBUG_LEVEL_TRACE |
- |
- switch ( op ) |
- { |
- case op_callsubr: |
- case op_div: |
- case op_callothersubr: |
- case op_pop: |
- case op_return: |
- break; |
- |
- default: |
- if ( top - decoder->stack != num_args ) |
- FT_TRACE0(( "t1_decoder_parse_charstrings:" |
- " too much operands on the stack" |
- " (seen %d, expected %d)\n", |
- top - decoder->stack, num_args )); |
- break; |
- } |
- |
-#endif /* FT_DEBUG_LEVEL_TRACE */ |
- |
- top -= num_args; |
- |
- switch ( op ) |
- { |
- case op_endchar: |
- FT_TRACE4(( " endchar\n" )); |
- |
- t1_builder_close_contour( builder ); |
- |
- /* close hints recording session */ |
- if ( hinter ) |
- { |
- if ( hinter->close( hinter->hints, builder->current->n_points ) ) |
- goto Syntax_Error; |
- |
- /* apply hints to the loaded glyph outline now */ |
- hinter->apply( hinter->hints, |
- builder->current, |
- (PSH_Globals)builder->hints_globals, |
- decoder->hint_mode ); |
- } |
- |
- /* add current outline to the glyph slot */ |
- FT_GlyphLoader_Add( builder->loader ); |
- |
- /* the compiler should optimize away this empty loop but ... */ |
- |
-#ifdef FT_DEBUG_LEVEL_TRACE |
- |
- if ( decoder->len_buildchar > 0 ) |
- { |
- FT_UInt i; |
- |
- |
- FT_TRACE4(( "BuildCharArray = [ " )); |
- |
- for ( i = 0; i < decoder->len_buildchar; ++i ) |
- FT_TRACE4(( "%d ", decoder->buildchar[i] )); |
- |
- FT_TRACE4(( "]\n" )); |
- } |
- |
-#endif /* FT_DEBUG_LEVEL_TRACE */ |
- |
- FT_TRACE4(( "\n" )); |
- |
- /* return now! */ |
- return FT_Err_Ok; |
- |
- case op_hsbw: |
- FT_TRACE4(( " hsbw" )); |
- |
- builder->parse_state = T1_Parse_Have_Width; |
- |
- builder->left_bearing.x += top[0]; |
- builder->advance.x = top[1]; |
- builder->advance.y = 0; |
- |
- orig_x = x = builder->pos_x + top[0]; |
- orig_y = y = builder->pos_y; |
- |
- FT_UNUSED( orig_y ); |
- |
- /* the `metrics_only' indicates that we only want to compute */ |
- /* the glyph's metrics (lsb + advance width), not load the */ |
- /* rest of it; so exit immediately */ |
- if ( builder->metrics_only ) |
- return FT_Err_Ok; |
- |
- break; |
- |
- case op_seac: |
- return t1operator_seac( decoder, |
- top[0], |
- top[1], |
- top[2], |
- Fix2Int( top[3] ), |
- Fix2Int( top[4] ) ); |
- |
- case op_sbw: |
- FT_TRACE4(( " sbw" )); |
- |
- builder->parse_state = T1_Parse_Have_Width; |
- |
- builder->left_bearing.x += top[0]; |
- builder->left_bearing.y += top[1]; |
- builder->advance.x = top[2]; |
- builder->advance.y = top[3]; |
- |
- x = builder->pos_x + top[0]; |
- y = builder->pos_y + top[1]; |
- |
- /* the `metrics_only' indicates that we only want to compute */ |
- /* the glyph's metrics (lsb + advance width), not load the */ |
- /* rest of it; so exit immediately */ |
- if ( builder->metrics_only ) |
- return FT_Err_Ok; |
- |
- break; |
- |
- case op_closepath: |
- FT_TRACE4(( " closepath" )); |
- |
- /* if there is no path, `closepath' is a no-op */ |
- if ( builder->parse_state == T1_Parse_Have_Path || |
- builder->parse_state == T1_Parse_Have_Moveto ) |
- t1_builder_close_contour( builder ); |
- |
- builder->parse_state = T1_Parse_Have_Width; |
- break; |
- |
- case op_hlineto: |
- FT_TRACE4(( " hlineto" )); |
- |
- if ( ( error = t1_builder_start_point( builder, x, y ) ) |
- != FT_Err_Ok ) |
- goto Fail; |
- |
- x += top[0]; |
- goto Add_Line; |
- |
- case op_hmoveto: |
- FT_TRACE4(( " hmoveto" )); |
- |
- x += top[0]; |
- if ( !decoder->flex_state ) |
- { |
- if ( builder->parse_state == T1_Parse_Start ) |
- goto Syntax_Error; |
- builder->parse_state = T1_Parse_Have_Moveto; |
- } |
- break; |
- |
- case op_hvcurveto: |
- FT_TRACE4(( " hvcurveto" )); |
- |
- if ( ( error = t1_builder_start_point( builder, x, y ) ) |
- != FT_Err_Ok || |
- ( error = t1_builder_check_points( builder, 3 ) ) |
- != FT_Err_Ok ) |
- goto Fail; |
- |
- x += top[0]; |
- t1_builder_add_point( builder, x, y, 0 ); |
- x += top[1]; |
- y += top[2]; |
- t1_builder_add_point( builder, x, y, 0 ); |
- y += top[3]; |
- t1_builder_add_point( builder, x, y, 1 ); |
- break; |
- |
- case op_rlineto: |
- FT_TRACE4(( " rlineto" )); |
- |
- if ( ( error = t1_builder_start_point( builder, x, y ) ) |
- != FT_Err_Ok ) |
- goto Fail; |
- |
- x += top[0]; |
- y += top[1]; |
- |
- Add_Line: |
- if ( ( error = t1_builder_add_point1( builder, x, y ) ) |
- != FT_Err_Ok ) |
- goto Fail; |
- break; |
- |
- case op_rmoveto: |
- FT_TRACE4(( " rmoveto" )); |
- |
- x += top[0]; |
- y += top[1]; |
- if ( !decoder->flex_state ) |
- { |
- if ( builder->parse_state == T1_Parse_Start ) |
- goto Syntax_Error; |
- builder->parse_state = T1_Parse_Have_Moveto; |
- } |
- break; |
- |
- case op_rrcurveto: |
- FT_TRACE4(( " rrcurveto" )); |
- |
- if ( ( error = t1_builder_start_point( builder, x, y ) ) |
- != FT_Err_Ok || |
- ( error = t1_builder_check_points( builder, 3 ) ) |
- != FT_Err_Ok ) |
- goto Fail; |
- |
- x += top[0]; |
- y += top[1]; |
- t1_builder_add_point( builder, x, y, 0 ); |
- |
- x += top[2]; |
- y += top[3]; |
- t1_builder_add_point( builder, x, y, 0 ); |
- |
- x += top[4]; |
- y += top[5]; |
- t1_builder_add_point( builder, x, y, 1 ); |
- break; |
- |
- case op_vhcurveto: |
- FT_TRACE4(( " vhcurveto" )); |
- |
- if ( ( error = t1_builder_start_point( builder, x, y ) ) |
- != FT_Err_Ok || |
- ( error = t1_builder_check_points( builder, 3 ) ) |
- != FT_Err_Ok ) |
- goto Fail; |
- |
- y += top[0]; |
- t1_builder_add_point( builder, x, y, 0 ); |
- x += top[1]; |
- y += top[2]; |
- t1_builder_add_point( builder, x, y, 0 ); |
- x += top[3]; |
- t1_builder_add_point( builder, x, y, 1 ); |
- break; |
- |
- case op_vlineto: |
- FT_TRACE4(( " vlineto" )); |
- |
- if ( ( error = t1_builder_start_point( builder, x, y ) ) |
- != FT_Err_Ok ) |
- goto Fail; |
- |
- y += top[0]; |
- goto Add_Line; |
- |
- case op_vmoveto: |
- FT_TRACE4(( " vmoveto" )); |
- |
- y += top[0]; |
- if ( !decoder->flex_state ) |
- { |
- if ( builder->parse_state == T1_Parse_Start ) |
- goto Syntax_Error; |
- builder->parse_state = T1_Parse_Have_Moveto; |
- } |
- break; |
- |
- case op_div: |
- FT_TRACE4(( " div" )); |
- |
- /* if `large_int' is set, we divide unscaled numbers; */ |
- /* otherwise, we divide numbers in 16.16 format -- */ |
- /* in both cases, it is the same operation */ |
- *top = FT_DivFix( top[0], top[1] ); |
- ++top; |
- |
- large_int = FALSE; |
- break; |
- |
- case op_callsubr: |
- { |
- FT_Int idx; |
- |
- |
- FT_TRACE4(( " callsubr" )); |
- |
- idx = Fix2Int( top[0] ); |
- if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " invalid subrs index\n" )); |
- goto Syntax_Error; |
- } |
- |
- if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " too many nested subrs\n" )); |
- goto Syntax_Error; |
- } |
- |
- zone->cursor = ip; /* save current instruction pointer */ |
- |
- zone++; |
- |
- /* The Type 1 driver stores subroutines without the seed bytes. */ |
- /* The CID driver stores subroutines with seed bytes. This */ |
- /* case is taken care of when decoder->subrs_len == 0. */ |
- zone->base = decoder->subrs[idx]; |
- |
- if ( decoder->subrs_len ) |
- zone->limit = zone->base + decoder->subrs_len[idx]; |
- else |
- { |
- /* We are using subroutines from a CID font. We must adjust */ |
- /* for the seed bytes. */ |
- zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); |
- zone->limit = decoder->subrs[idx + 1]; |
- } |
- |
- zone->cursor = zone->base; |
- |
- if ( !zone->base ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " invoking empty subrs\n" )); |
- goto Syntax_Error; |
- } |
- |
- decoder->zone = zone; |
- ip = zone->base; |
- limit = zone->limit; |
- break; |
- } |
- |
- case op_pop: |
- FT_TRACE4(( " pop" )); |
- |
- if ( known_othersubr_result_cnt > 0 ) |
- { |
- known_othersubr_result_cnt--; |
- /* ignore, we pushed the operands ourselves */ |
- break; |
- } |
- |
- if ( unknown_othersubr_result_cnt == 0 ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " no more operands for othersubr\n" )); |
- goto Syntax_Error; |
- } |
- |
- unknown_othersubr_result_cnt--; |
- top++; /* `push' the operand to callothersubr onto the stack */ |
- break; |
- |
- case op_return: |
- FT_TRACE4(( " return" )); |
- |
- if ( zone <= decoder->zones ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " unexpected return\n" )); |
- goto Syntax_Error; |
- } |
- |
- zone--; |
- ip = zone->cursor; |
- limit = zone->limit; |
- decoder->zone = zone; |
- break; |
- |
- case op_dotsection: |
- FT_TRACE4(( " dotsection" )); |
- |
- break; |
- |
- case op_hstem: |
- FT_TRACE4(( " hstem" )); |
- |
- /* record horizontal hint */ |
- if ( hinter ) |
- { |
- /* top[0] += builder->left_bearing.y; */ |
- hinter->stem( hinter->hints, 1, top ); |
- } |
- break; |
- |
- case op_hstem3: |
- FT_TRACE4(( " hstem3" )); |
- |
- /* record horizontal counter-controlled hints */ |
- if ( hinter ) |
- hinter->stem3( hinter->hints, 1, top ); |
- break; |
- |
- case op_vstem: |
- FT_TRACE4(( " vstem" )); |
- |
- /* record vertical hint */ |
- if ( hinter ) |
- { |
- top[0] += orig_x; |
- hinter->stem( hinter->hints, 0, top ); |
- } |
- break; |
- |
- case op_vstem3: |
- FT_TRACE4(( " vstem3" )); |
- |
- /* record vertical counter-controlled hints */ |
- if ( hinter ) |
- { |
- FT_Pos dx = orig_x; |
- |
- |
- top[0] += dx; |
- top[2] += dx; |
- top[4] += dx; |
- hinter->stem3( hinter->hints, 0, top ); |
- } |
- break; |
- |
- case op_setcurrentpoint: |
- FT_TRACE4(( " setcurrentpoint" )); |
- |
- /* From the T1 specification, section 6.4: */ |
- /* */ |
- /* The setcurrentpoint command is used only in */ |
- /* conjunction with results from OtherSubrs procedures. */ |
- |
- /* known_othersubr_result_cnt != 0 is already handled */ |
- /* above. */ |
- |
- /* Note, however, that both Ghostscript and Adobe */ |
- /* Distiller handle this situation by silently ignoring */ |
- /* the inappropriate `setcurrentpoint' instruction. So */ |
- /* we do the same. */ |
-#if 0 |
- |
- if ( decoder->flex_state != 1 ) |
- { |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " unexpected `setcurrentpoint'\n" )); |
- goto Syntax_Error; |
- } |
- else |
- ... |
-#endif |
- |
- x = top[0]; |
- y = top[1]; |
- decoder->flex_state = 0; |
- break; |
- |
- case op_unknown15: |
- FT_TRACE4(( " opcode_15" )); |
- /* nothing to do except to pop the two arguments */ |
- break; |
- |
- default: |
- FT_ERROR(( "t1_decoder_parse_charstrings:" |
- " unhandled opcode %d\n", op )); |
- goto Syntax_Error; |
- } |
- |
- /* XXX Operators usually clear the operand stack; */ |
- /* only div, callsubr, callothersubr, pop, and */ |
- /* return are different. */ |
- /* In practice it doesn't matter (?). */ |
- |
- decoder->top = top; |
- |
-#ifdef FT_DEBUG_LEVEL_TRACE |
- FT_TRACE4(( "\n" )); |
- bol = TRUE; |
-#endif |
- |
- } /* general operator processing */ |
- |
- } /* while ip < limit */ |
- |
- FT_TRACE4(( "..end..\n\n" )); |
- |
- Fail: |
- return error; |
- |
- Syntax_Error: |
- return FT_THROW( Syntax_Error ); |
- |
- Stack_Underflow: |
- return FT_THROW( Stack_Underflow ); |
- } |
- |
- |
- /* parse a single Type 1 glyph */ |
- FT_LOCAL_DEF( FT_Error ) |
- t1_decoder_parse_glyph( T1_Decoder decoder, |
- FT_UInt glyph ) |
- { |
- return decoder->parse_callback( decoder, glyph ); |
- } |
- |
- |
- /* initialize T1 decoder */ |
- FT_LOCAL_DEF( FT_Error ) |
- t1_decoder_init( T1_Decoder decoder, |
- FT_Face face, |
- FT_Size size, |
- FT_GlyphSlot slot, |
- FT_Byte** glyph_names, |
- PS_Blend blend, |
- FT_Bool hinting, |
- FT_Render_Mode hint_mode, |
- T1_Decoder_Callback parse_callback ) |
- { |
- FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); |
- |
- /* retrieve PSNames interface from list of current modules */ |
- { |
- FT_Service_PsCMaps psnames = 0; |
- |
- |
- FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); |
- if ( !psnames ) |
- { |
- FT_ERROR(( "t1_decoder_init:" |
- " the `psnames' module is not available\n" )); |
- return FT_THROW( Unimplemented_Feature ); |
- } |
- |
- decoder->psnames = psnames; |
- } |
- |
- t1_builder_init( &decoder->builder, face, size, slot, hinting ); |
- |
- /* decoder->buildchar and decoder->len_buildchar have to be */ |
- /* initialized by the caller since we cannot know the length */ |
- /* of the BuildCharArray */ |
- |
- decoder->num_glyphs = (FT_UInt)face->num_glyphs; |
- decoder->glyph_names = glyph_names; |
- decoder->hint_mode = hint_mode; |
- decoder->blend = blend; |
- decoder->parse_callback = parse_callback; |
- |
- decoder->funcs = t1_decoder_funcs; |
- |
- return FT_Err_Ok; |
- } |
- |
- |
- /* finalize T1 decoder */ |
- FT_LOCAL_DEF( void ) |
- t1_decoder_done( T1_Decoder decoder ) |
- { |
- t1_builder_done( &decoder->builder ); |
- } |
- |
- |
-/* END */ |