From 11cb8c36ed9c75ccf3b80bdb59e9b2a75993a1cd Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Mon, 22 Jun 2009 16:56:47 +0200 Subject: [PATCH] Use 16.16 format while parsing Type 1 charstrings. This fixes Savannah bug #26867. Previously, only integers have been used which can lead to serious rounding errors. However, fractional values are only used internally; after the charstrings (of either Type 1 or 2) have been processed, the resulting coordinates get rounded to integers currently -- before applying scaling. This should be fixed; at the same time a new load flag should be introduced, to be used in combination with FT_LOAD_NO_SCALE, which indicates that font units are returned in 16.16 format. Similarly, the incremental interface should be extended to allow fractional values for metrics. * include/freetype/internal/psaux.h (T1_BuilderRec): Remove `shift' field. * include/freetype/internal/pshints.h (T1_Hints_SetStemFunc, T1_Hints_SetStem3Func): Use FT_Fixed for coordinates. * src/psaux/psobjs.c: Include FT_INTERNAL_CALC_H. (t1_build_add_point): Always convert fixed to integer. * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Use 16.16 format everywhere (except for large integers followed by a `div'). [CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS]: Remove #ifdef and activate code uncoditionally. Add support for random numbers and update remaining code accordingly; this should work now. (t1_operator_seac): Updated. * src/psaux/pshrec.c: Include FT_INTERNAL_CALC_H. (ps_hints_t1stem3, t1_hints_stem): Updated. * src/cid/cidgload.c: Include FT_INTERNAL_CALC_H. (cid_load_glyph) [FT_CONFIG_OPTION_INCREMENTAL], (cid_face_compute_max_advance, cid_slot_load_glyph): Updated. * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String) [FT_CONFIG_OPTION_INCREMENTAL], (T1_Get_Advances, T1_Load_Glyph): Updated. * src/type1/t1load.c: Include FT_INTERNAL_CALC_H. * src/type1/t1objs.c (T1_Face_Init): Updated. --- ChangeLog | 45 ++++++++++++ include/freetype/internal/psaux.h | 1 - include/freetype/internal/pshints.h | 23 +++--- src/cid/cidgload.c | 57 ++++++++------- src/psaux/psobjs.c | 14 ++-- src/psaux/t1decode.c | 107 +++++++++++++++++----------- src/pshinter/pshrec.c | 35 +++++---- src/type1/t1gload.c | 55 ++++++++------ src/type1/t1load.c | 1 + src/type1/t1objs.c | 4 +- 10 files changed, 217 insertions(+), 125 deletions(-) diff --git a/ChangeLog b/ChangeLog index ceb529c52..9b8a3c3cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +2009-06-22 Werner Lemberg + + Use 16.16 format while parsing Type 1 charstrings. + This fixes Savannah bug #26867. + + Previously, only integers have been used which can lead to serious + rounding errors. + + However, fractional values are only used internally; after the + charstrings (of either Type 1 or 2) have been processed, the + resulting coordinates get rounded to integers currently -- before + applying scaling. This should be fixed; at the same time a new load + flag should be introduced, to be used in combination with + FT_LOAD_NO_SCALE, which indicates that font units are returned in + 16.16 format. Similarly, the incremental interface should be + extended to allow fractional values for metrics. + + * include/freetype/internal/psaux.h (T1_BuilderRec): Remove `shift' + field. + * include/freetype/internal/pshints.h (T1_Hints_SetStemFunc, + T1_Hints_SetStem3Func): Use FT_Fixed for coordinates. + + * src/psaux/psobjs.c: Include FT_INTERNAL_CALC_H. + (t1_build_add_point): Always convert fixed to integer. + * src/psaux/t1decode.c (t1_decoder_parse_charstrings): + Use 16.16 format everywhere (except for large integers followed by a + `div'). + [CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS]: Remove #ifdef and activate + code uncoditionally. + Add support for random numbers and update remaining code + accordingly; this should work now. + (t1_operator_seac): Updated. + * src/psaux/pshrec.c: Include FT_INTERNAL_CALC_H. + (ps_hints_t1stem3, t1_hints_stem): Updated. + + * src/cid/cidgload.c: Include FT_INTERNAL_CALC_H. + (cid_load_glyph) [FT_CONFIG_OPTION_INCREMENTAL], + (cid_face_compute_max_advance, cid_slot_load_glyph): Updated. + + * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String) + [FT_CONFIG_OPTION_INCREMENTAL], (T1_Get_Advances, T1_Load_Glyph): + Updated. + * src/type1/t1load.c: Include FT_INTERNAL_CALC_H. + * src/type1/t1objs.c (T1_Face_Init): Updated. + 2009-06-21 Werner Lemberg * src/pshinter/pshrec.c: Use PSH_Err_Ok. diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h index d078ac9fc..cac9f47a7 100644 --- a/include/freetype/internal/psaux.h +++ b/include/freetype/internal/psaux.h @@ -575,7 +575,6 @@ FT_BEGIN_HEADER T1_ParseState parse_state; FT_Bool load_points; FT_Bool no_recurse; - FT_Bool shift; FT_Bool metrics_only; diff --git a/include/freetype/internal/pshints.h b/include/freetype/internal/pshints.h index 4ad3ac5fa..0c357651b 100644 --- a/include/freetype/internal/pshints.h +++ b/include/freetype/internal/pshints.h @@ -6,7 +6,7 @@ /* recorders (specification only). These are used to support native */ /* T1/T2 hints in the `type1', `cid', and `cff' font drivers. */ /* */ -/* Copyright 2001, 2002, 2003, 2005, 2006, 2007 by */ +/* Copyright 2001, 2002, 2003, 2005, 2006, 2007, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -157,7 +157,8 @@ FT_BEGIN_HEADER * 0 for horizontal stems (hstem), 1 for vertical ones (vstem). * * coords :: - * Array of 2 integers, used as (position,length) stem descriptor. + * Array of 2 coordinates in 16.16 format, used as (position,length) + * stem descriptor. * * @note: * Use vertical coordinates (y) for horizontal stems (dim=0). Use @@ -175,9 +176,9 @@ FT_BEGIN_HEADER * */ typedef void - (*T1_Hints_SetStemFunc)( T1_Hints hints, - FT_UInt dimension, - FT_Long* coords ); + (*T1_Hints_SetStemFunc)( T1_Hints hints, + FT_UInt dimension, + FT_Fixed* coords ); /************************************************************************* @@ -197,8 +198,8 @@ FT_BEGIN_HEADER * 0 for horizontal stems, 1 for vertical ones. * * coords :: - * An array of 6 integers, holding 3 (position,length) pairs for the - * counter-controlled stems. + * An array of 6 values in 16.16 format, holding 3 (position,length) + * pairs for the counter-controlled stems. * * @note: * Use vertical coordinates (y) for horizontal stems (dim=0). Use @@ -209,9 +210,9 @@ FT_BEGIN_HEADER * */ typedef void - (*T1_Hints_SetStem3Func)( T1_Hints hints, - FT_UInt dimension, - FT_Long* coords ); + (*T1_Hints_SetStem3Func)( T1_Hints hints, + FT_UInt dimension, + FT_Fixed* coords ); /************************************************************************* @@ -446,7 +447,7 @@ FT_BEGIN_HEADER * The number of stems. * * coords :: - * An array of `count' (position,length) pairs. + * An array of `count' (position,length) pairs in 16.16 format. * * @note: * Use vertical coordinates (y) for horizontal stems (dim=0). Use diff --git a/src/cid/cidgload.c b/src/cid/cidgload.c index 64994b441..f59035ffa 100644 --- a/src/cid/cidgload.c +++ b/src/cid/cidgload.c @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 Glyph Loader (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,6 +22,7 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_STREAM_H #include FT_OUTLINE_H +#include FT_INTERNAL_CALC_H #include "ciderrs.h" @@ -51,20 +52,23 @@ FT_ULong glyph_length = 0; PSAux_Service psaux = (PSAux_Service)face->psaux; +#ifdef FT_CONFIG_OPTION_INCREMENTAL + FT_Incremental_InterfaceRec *inc = + face->root.internal->incremental_interface; +#endif + #ifdef FT_CONFIG_OPTION_INCREMENTAL /* For incremental fonts get the character data using */ /* the callback function. */ - if ( face->root.internal->incremental_interface ) + if ( inc ) { FT_Data glyph_data; - error = face->root.internal->incremental_interface->funcs->get_glyph_data( - face->root.internal->incremental_interface->object, - glyph_index, - &glyph_data ); + error = inc->funcs->get_glyph_data( inc->object, + glyph_index, &glyph_data ); if ( error ) goto Exit; @@ -80,9 +84,7 @@ glyph_length ); } - face->root.internal->incremental_interface->funcs->free_glyph_data( - face->root.internal->incremental_interface->object, - &glyph_data ); + inc->funcs->free_glyph_data( inc->object, &glyph_data ); if ( error ) goto Exit; @@ -163,22 +165,21 @@ #ifdef FT_CONFIG_OPTION_INCREMENTAL /* Incremental fonts can optionally override the metrics. */ - if ( !error && - face->root.internal->incremental_interface && - face->root.internal->incremental_interface->funcs->get_glyph_metrics ) + if ( !error && inc && inc->funcs->get_glyph_metrics ) { FT_Incremental_MetricsRec metrics; - metrics.bearing_x = decoder->builder.left_bearing.x; - metrics.bearing_y = decoder->builder.left_bearing.y; - metrics.advance = decoder->builder.advance.x; - error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( - face->root.internal->incremental_interface->object, - glyph_index, FALSE, &metrics ); - decoder->builder.left_bearing.x = metrics.bearing_x; - decoder->builder.left_bearing.y = metrics.bearing_y; - decoder->builder.advance.x = metrics.advance; + metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); + metrics.bearing_y = FIXED_TO_INT( decoder->builder.left_bearing.y ); + metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); + + error = inc->funcs->get_glyph_metrics( inc->object, + glyph_index, FALSE, &metrics ); + + decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); + decoder->builder.left_bearing.y = INT_TO_FIXED( metrics.bearing_y ); + decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); decoder->builder.advance.y = 0; } @@ -251,7 +252,7 @@ /* ignore the error if one occurred - skip to next glyph */ } - *max_advance = decoder.builder.advance.x; + *max_advance = FIXED_TO_INT( decoder.builder.advance.x ); psaux->t1_decoder_funcs->done( &decoder ); @@ -342,8 +343,10 @@ FT_Slot_Internal internal = cidglyph->internal; - cidglyph->metrics.horiBearingX = decoder.builder.left_bearing.x; - cidglyph->metrics.horiAdvance = decoder.builder.advance.x; + cidglyph->metrics.horiBearingX = + FIXED_TO_INT( decoder.builder.left_bearing.x ); + cidglyph->metrics.horiAdvance = + FIXED_TO_INT( decoder.builder.advance.x ); internal->glyph_matrix = font_matrix; internal->glyph_delta = font_offset; @@ -357,8 +360,10 @@ /* copy the _unscaled_ advance width */ - metrics->horiAdvance = decoder.builder.advance.x; - cidglyph->linearHoriAdvance = decoder.builder.advance.x; + metrics->horiAdvance = + FIXED_TO_INT( decoder.builder.advance.x ); + cidglyph->linearHoriAdvance = + FIXED_TO_INT( decoder.builder.advance.x ); cidglyph->internal->glyph_transformed = 0; /* make up vertical ones */ diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c index b3f3a70de..28cfcc41c 100644 --- a/src/psaux/psobjs.c +++ b/src/psaux/psobjs.c @@ -19,6 +19,7 @@ #include #include FT_INTERNAL_POSTSCRIPT_AUX_H #include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H #include "psobjs.h" #include "psconv.h" @@ -1551,13 +1552,8 @@ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; - if ( builder->shift ) - { - x >>= 16; - y >>= 16; - } - point->x = x; - point->y = y; + point->x = FIXED_TO_INT( x ); + point->y = FIXED_TO_INT( y ); *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); } outline->n_points++; @@ -1666,8 +1662,8 @@ if ( outline->n_contours > 0 ) { - /* Don't add contours only consisting of one point, i.e., */ - /* check whether begin point and last point are the same. */ + /* Don't add contours only consisting of one point, i.e., */ + /* check whether the first and the last point is the same. */ if ( first == outline->n_points - 1 ) { outline->n_contours--; diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c index 47681f8d9..85d34e4ba 100644 --- a/src/psaux/t1decode.c +++ b/src/psaux/t1decode.c @@ -253,8 +253,8 @@ /* subglyph 1 = accent character */ subg->index = achar_index; subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; - subg->arg1 = (FT_Int)( adx - asb ); - subg->arg2 = (FT_Int)ady; + 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; @@ -338,6 +338,7 @@ 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; @@ -354,6 +355,15 @@ #define add_contour t1_builder_add_contour #define close_contour t1_builder_close_contour + + /* compute random seed from stack address of parameter */ + seed = (FT_Fixed)(char*)&seed ^ + (FT_Fixed)(char*)&decoder ^ + (FT_Fixed)(char*)&charstring_base; + 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; @@ -395,7 +405,7 @@ { FT_Long* top = decoder->top; T1_Operator op = op_none; - FT_Long value = 0; + FT_Int32 value = 0; FT_ASSERT( known_othersubr_result_cnt == 0 || @@ -552,6 +562,11 @@ else large_int = TRUE; } + else + { + if ( !large_int ) + value <<= 16; + } break; @@ -574,6 +589,9 @@ else value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); } + + if ( !large_int ) + value <<= 16; } else { @@ -621,7 +639,12 @@ goto Syntax_Error; } - FT_TRACE4(( " %ld", value )); +#ifdef FT_DEBUG_LEVEL_TRACE + if ( large_int ) + FT_TRACE4(( " %ld", value )); + else + FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) )); +#endif *top++ = value; decoder->top = top; @@ -642,8 +665,8 @@ top -= 2; - subr_no = (FT_Int)top[1]; - arg_cnt = (FT_Int)top[0]; + subr_no = (FT_Int)( top[1] >> 16 ); + arg_cnt = (FT_Int)( top[0] >> 16 ); /***********************************************************/ /* */ @@ -805,12 +828,6 @@ break; } -#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS - - /* We cannot yet enable these since currently */ - /* our T1 stack stores integers which lack the */ - /* precision to express the values */ - case 19: /* 1 19 callothersubr */ /* => replace elements starting from index cvi( ) */ @@ -823,10 +840,10 @@ if ( arg_cnt != 1 || blend == NULL ) goto Unexpected_OtherSubr; - idx = top[0]; + idx = (FT_Int)( top[0] >> 16 ); - if ( idx < 0 || - idx + blend->num_designs > decoder->face->len_buildchar ) + if ( idx < 0 || + idx + blend->num_designs > decoder->len_buildchar ) goto Unexpected_OtherSubr; ft_memcpy( &decoder->buildchar[idx], @@ -864,7 +881,7 @@ if ( arg_cnt != 2 ) goto Unexpected_OtherSubr; - top[0] *= top[1]; /* XXX (over|under)flow */ + top[0] = FT_MulFix( top[0], top[1] ); known_othersubr_result_cnt = 1; break; @@ -875,13 +892,11 @@ if ( arg_cnt != 2 || top[1] == 0 ) goto Unexpected_OtherSubr; - top[0] /= top[1]; /* XXX (over|under)flow */ + top[0] = FT_DivFix( top[0], top[1] ); known_othersubr_result_cnt = 1; break; -#endif /* CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS */ - case 24: /* 2 24 callothersubr */ /* => set BuildCharArray[cvi( )] = */ @@ -889,10 +904,11 @@ FT_Int idx; PS_Blend blend = decoder->blend; + if ( arg_cnt != 2 || blend == NULL ) goto Unexpected_OtherSubr; - idx = top[1]; + idx = (FT_Int)( top[1] >> 16 ); if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; @@ -909,10 +925,11 @@ FT_Int idx; PS_Blend blend = decoder->blend; + if ( arg_cnt != 1 || blend == NULL ) goto Unexpected_OtherSubr; - idx = top[0]; + idx = (FT_Int)( top[0] >> 16 ); if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; @@ -945,17 +962,29 @@ known_othersubr_result_cnt = 1; break; -#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS case 28: /* 0 28 callothersubr pop */ /* => push random value from interval [0, 1) onto stack */ if ( arg_cnt != 0 ) goto Unexpected_OtherSubr; - top[0] = FT_rand(); + { + 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; -#endif default: FT_ERROR(( "t1_decoder_parse_charstrings: " @@ -1024,13 +1053,13 @@ /* close hints recording session */ if ( hinter ) { - if (hinter->close( hinter->hints, builder->current->n_points )) + 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, + (PSH_Globals)builder->hints_globals, decoder->hint_mode ); } @@ -1085,8 +1114,12 @@ case op_seac: /* return immediately after the processing */ - return t1operator_seac( decoder, top[0], top[1], top[2], - (FT_Int)top[3], (FT_Int)top[4] ); + return t1operator_seac( decoder, + top[0], + top[1], + top[2], + (FT_Int)( top[3] >> 16 ), + (FT_Int)( top[4] >> 16 ) ); case op_sbw: FT_TRACE4(( " sbw" )); @@ -1244,19 +1277,13 @@ case op_div: FT_TRACE4(( " div" )); - if ( top[1] ) - { - *top = top[0] / top[1]; - ++top; - } - else - { - FT_ERROR(( "t1_decoder_parse_charstrings: division by 0\n" )); - goto Syntax_Error; - } + /* 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: @@ -1266,7 +1293,7 @@ FT_TRACE4(( " callsubr" )); - idx = (FT_Int)top[0]; + idx = (FT_Int)( top[0] >> 16 ); if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs ) { FT_ERROR(( "t1_decoder_parse_charstrings: " diff --git a/src/pshinter/pshrec.c b/src/pshinter/pshrec.c index cfe23f08c..8273dabb4 100644 --- a/src/pshinter/pshrec.c +++ b/src/pshinter/pshrec.c @@ -4,7 +4,7 @@ /* */ /* FreeType PostScript hints recorder (body). */ /* */ -/* Copyright 2001, 2002, 2003, 2004, 2007 by */ +/* Copyright 2001, 2002, 2003, 2004, 2007, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,8 @@ #include FT_FREETYPE_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H + #include "pshrec.h" #include "pshalgo.h" @@ -800,7 +802,7 @@ { FT_MEM_ZERO( hints, sizeof ( *hints ) ); hints->memory = memory; - return 0; + return PSH_Err_Ok; } @@ -888,9 +890,9 @@ /* add one Type1 counter stem to the current hints table */ static void - ps_hints_t1stem3( PS_Hints hints, - FT_Int dimension, - FT_Long* stems ) + ps_hints_t1stem3( PS_Hints hints, + FT_Int dimension, + FT_Fixed* stems ) { FT_Error error = PSH_Err_Ok; @@ -919,9 +921,10 @@ /* add the three stems to our hints/masks table */ for ( count = 0; count < 3; count++, stems += 2 ) { - error = ps_dimension_add_t1stem( - dim, (FT_Int)stems[0], (FT_Int)stems[1], - memory, &idx[count] ); + error = ps_dimension_add_t1stem( dim, + (FT_Int)FIXED_TO_INT( stems[0] ), + (FT_Int)FIXED_TO_INT( stems[1] ), + memory, &idx[count] ); if ( error ) goto Fail; } @@ -1124,11 +1127,17 @@ } static void - t1_hints_stem( T1_Hints hints, - FT_Int dimension, - FT_Long* coords ) + t1_hints_stem( T1_Hints hints, + FT_Int dimension, + FT_Fixed* coords ) { - ps_hints_stem( (PS_Hints)hints, dimension, 1, coords ); + FT_Pos stems[2]; + + + stems[0] = FIXED_TO_INT( coords[0] ); + stems[1] = FIXED_TO_INT( coords[1] ); + + ps_hints_stem( (PS_Hints)hints, dimension, 1, stems ); } @@ -1183,7 +1192,7 @@ for ( n = 0; n < count * 2; n++ ) { y += coords[n]; - stems[n] = ( y + 0x8000L ) >> 16; + stems[n] = FIXED_TO_INT( y ); } /* compute lengths */ diff --git a/src/type1/t1gload.c b/src/type1/t1gload.c index 8462028eb..01bc4ce7b 100644 --- a/src/type1/t1gload.c +++ b/src/type1/t1gload.c @@ -62,6 +62,11 @@ T1_Font type1 = &face->type1; FT_Error error = T1_Err_Ok; +#ifdef FT_CONFIG_OPTION_INCREMENTAL + FT_Incremental_InterfaceRec *inc = + face->root.internal->incremental_interface; +#endif + decoder->font_matrix = type1->font_matrix; decoder->font_offset = type1->font_offset; @@ -70,10 +75,9 @@ /* For incremental fonts get the character data using the */ /* callback function. */ - if ( face->root.internal->incremental_interface ) - error = face->root.internal->incremental_interface->funcs->get_glyph_data( - face->root.internal->incremental_interface->object, - glyph_index, char_string ); + if ( inc ) + error = inc->funcs->get_glyph_data( inc->object, + glyph_index, char_string ); else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ @@ -92,21 +96,21 @@ #ifdef FT_CONFIG_OPTION_INCREMENTAL /* Incremental fonts can optionally override the metrics. */ - if ( !error && face->root.internal->incremental_interface && - face->root.internal->incremental_interface->funcs->get_glyph_metrics ) + if ( !error && inc && inc->funcs->get_glyph_metrics ) { FT_Incremental_MetricsRec metrics; - metrics.bearing_x = decoder->builder.left_bearing.x; - metrics.bearing_y = decoder->builder.left_bearing.y; - metrics.advance = decoder->builder.advance.x; - error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( - face->root.internal->incremental_interface->object, - glyph_index, FALSE, &metrics ); - decoder->builder.left_bearing.x = metrics.bearing_x; - decoder->builder.left_bearing.y = metrics.bearing_y; - decoder->builder.advance.x = metrics.advance; + metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); + metrics.bearing_y = FIXED_TO_INT( decoder->builder.left_bearing.y ); + metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); + + error = inc->funcs->get_glyph_metrics( inc->object, + glyph_index, FALSE, &metrics ); + + decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); + decoder->builder.left_bearing.y = INT_TO_FIXED( metrics.bearing_y ); + decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); decoder->builder.advance.y = 0; } @@ -250,7 +254,7 @@ { error = T1_Parse_Glyph( &decoder, first + nn ); if ( !error ) - advances[nn] = decoder.builder.advance.x; + advances[nn] = FIXED_TO_INT( decoder.builder.advance.x ); else advances[nn] = 0; } @@ -368,11 +372,14 @@ FT_Slot_Internal internal = glyph->root.internal; - glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; - glyph->root.metrics.horiAdvance = decoder.builder.advance.x; - internal->glyph_matrix = font_matrix; - internal->glyph_delta = font_offset; - internal->glyph_transformed = 1; + glyph->root.metrics.horiBearingX = + FIXED_TO_INT( decoder.builder.left_bearing.x ); + glyph->root.metrics.horiAdvance = + FIXED_TO_INT( decoder.builder.advance.x ); + + internal->glyph_matrix = font_matrix; + internal->glyph_delta = font_offset; + internal->glyph_transformed = 1; } else { @@ -382,8 +389,10 @@ /* copy the _unscaled_ advance width */ - metrics->horiAdvance = decoder.builder.advance.x; - glyph->root.linearHoriAdvance = decoder.builder.advance.x; + metrics->horiAdvance = + FIXED_TO_INT( decoder.builder.advance.x ); + glyph->root.linearHoriAdvance = + FIXED_TO_INT( decoder.builder.advance.x ); glyph->root.internal->glyph_transformed = 0; /* make up vertical ones */ diff --git a/src/type1/t1load.c b/src/type1/t1load.c index 2e4700e54..d5e7791d1 100644 --- a/src/type1/t1load.c +++ b/src/type1/t1load.c @@ -65,6 +65,7 @@ #include FT_CONFIG_CONFIG_H #include FT_MULTIPLE_MASTERS_H #include FT_INTERNAL_TYPE1_TYPES_H +#include FT_INTERNAL_CALC_H #include "t1load.h" #include "t1errors.h" diff --git a/src/type1/t1objs.c b/src/type1/t1objs.c index 2f90dd62f..df87ffcf8 100644 --- a/src/type1/t1objs.c +++ b/src/type1/t1objs.c @@ -4,7 +4,7 @@ /* */ /* Type 1 objects manager (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -467,7 +467,7 @@ /* in case of error, keep the standard width */ if ( !error ) - root->max_advance_width = (FT_Short)max_advance; + root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance ); else error = T1_Err_Ok; /* clear error */ }