From bfb712fb365164271b7355f72f9f58f1d408138e Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Wed, 3 Mar 2004 08:21:12 +0000 Subject: [PATCH] Add embedded bitmap support to CFF driver. * src/cff/cffobjs.h (CFF_SizeRec): New structure. * src/cff/cffgload.c (cff_builder_init): Updated. (cff_slot_load): Updated. [TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Load sbit. * src/cff/cffobjs.c (sbit_size_reset) [TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: New function. (cff_size_get_globals_funcs, cff_size_done, cff_size_init): Updated. (cff_size_reset): Updated. [TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Call sbit_size_reset. * src/cff/cffdrivr.c (Load_Glyph): Updated. (cff_driver_class): Use CFF_SizeRec. * docs/CHANGES: Updated. --- ChangeLog | 23 +++++++++- docs/CHANGES | 2 + src/cff/cffcmap.c | 2 +- src/cff/cffdrivr.c | 4 +- src/cff/cffgload.c | 97 ++++++++++++++++++++++++++++++++------- src/cff/cffload.c | 6 +-- src/cff/cffobjs.c | 112 +++++++++++++++++++++++++++++++++++++++------ src/cff/cffobjs.h | 15 +++++- 8 files changed, 221 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7f1539de2..d373ccaf4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,31 @@ +2004-03-02 Werner Lemberg + + Add embedded bitmap support to CFF driver. + + * src/cff/cffobjs.h (CFF_SizeRec): New structure. + + * src/cff/cffgload.c (cff_builder_init): Updated. + (cff_slot_load): Updated. + [TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Load sbit. + + * src/cff/cffobjs.c (sbit_size_reset) + [TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: New function. + (cff_size_get_globals_funcs, cff_size_done, cff_size_init): Updated. + (cff_size_reset): Updated. + [TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Call sbit_size_reset. + + * src/cff/cffdrivr.c (Load_Glyph): Updated. + (cff_driver_class): Use CFF_SizeRec. + + * docs/CHANGES: Updated. + 2004-03-01 Werner Lemberg * src/pshinter/pshglob.c (psh_globals_scale_widths): Don't use FT_RoundFix but FT_PIX_ROUND. (psh_blues_snap_stem): Don't use blue_shift but blue_threshold. - *src/pshinter/pshalgo.c (PSH_STRONG_THRESHOLD_MAXIMUM): New macro. + * src/pshinter/pshalgo.c (PSH_STRONG_THRESHOLD_MAXIMUM): New macro. (psh_glyph_find_string_points): Use PSH_STRONG_THRESHOLD_MAXIMUM. (psh_glyph_find_blue_points): New function. Needed for fonts like p052003l.pfb (URW Palladio L Roman) which have flex curves at the diff --git a/docs/CHANGES b/docs/CHANGES index 7c532645d..4420df0a5 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -16,6 +16,8 @@ LATEST CHANGES BETWEEN 2.1.8 and 2.1.7 correctly treated as a CID, similar to FreeType's CID driver module. Note that CID CMap support is still missing. + - Embedded bitmaps in SFNT-based CFF fonts are now supported. + - The FT_FACE_FLAGS_GLYPH_NAMES is now set correctly for all font formats. diff --git a/src/cff/cffcmap.c b/src/cff/cffcmap.c index 0c2e44e52..82e04d236 100644 --- a/src/cff/cffcmap.c +++ b/src/cff/cffcmap.c @@ -200,7 +200,7 @@ if ( new_count != count && new_count < count / 2 ) { (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count ); - error = 0; + error = CFF_Err_Ok; } /* sort the pairs table to allow efficient binary searches */ diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c index 75c072bcc..60ee90ae3 100644 --- a/src/cff/cffdrivr.c +++ b/src/cff/cffdrivr.c @@ -201,7 +201,7 @@ if ( size ) { /* these two object must have the same parent */ - if ( size->face != slot->root.face ) + if ( size->root.face != slot->root.face ) return CFF_Err_Invalid_Face_Handle; } @@ -453,7 +453,7 @@ /* now the specific driver fields */ sizeof( TT_FaceRec ), - sizeof( FT_SizeRec ), + sizeof( CFF_SizeRec ), sizeof( CFF_GlyphSlotRec ), (FT_Face_InitFunc) cff_face_init, diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index f8d611030..c5bf79ea2 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -251,15 +251,15 @@ if ( hinting && size ) { - builder->hints_globals = size->internal; + builder->hints_globals = size->root.internal; builder->hints_funcs = glyph->root.internal->glyph_hints; } } if ( size ) { - builder->scale_x = size->metrics.x_scale; - builder->scale_y = size->metrics.y_scale; + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.metrics.y_scale; } builder->pos_x = 0; @@ -485,7 +485,7 @@ FT_Pos x, FT_Pos y ) { - FT_Error error = 0; + FT_Error error = CFF_Err_Ok; /* test whether we are building a new contour */ @@ -2219,7 +2219,7 @@ cff_compute_max_advance( TT_Face face, FT_Int* max_advance ) { - FT_Error error = 0; + FT_Error error = CFF_Err_Ok; CFF_Decoder decoder; FT_Int glyph_index; CFF_Font cff = (CFF_Font)face->other; @@ -2255,7 +2255,7 @@ } /* ignore the error if one has occurred -- skip to next glyph */ - error = 0; + error = CFF_Err_Ok; } *max_advance = decoder.builder.advance.x; @@ -2289,14 +2289,19 @@ FT_Int glyph_index, FT_Int32 load_flags ) { - FT_Error error; - CFF_Decoder decoder; - TT_Face face = (TT_Face)glyph->root.face; - FT_Bool hinting; - CFF_Font cff = (CFF_Font)face->extra.data; + FT_Error error; + CFF_Decoder decoder; + TT_Face face = (TT_Face)glyph->root.face; +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + CFF_Face cff_face = (CFF_Face)size->root.face; + SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; + FT_Stream stream = cff_face->root.stream; +#endif + FT_Bool hinting; + CFF_Font cff = (CFF_Font)face->extra.data; - FT_Matrix font_matrix; - FT_Vector font_offset; + FT_Matrix font_matrix; + FT_Vector font_offset; if ( load_flags & FT_LOAD_NO_RECURSE ) @@ -2306,10 +2311,70 @@ glyph->y_scale = 0x10000L; if ( size ) { - glyph->x_scale = size->metrics.x_scale; - glyph->y_scale = size->metrics.y_scale; + glyph->x_scale = size->root.metrics.x_scale; + glyph->y_scale = size->root.metrics.y_scale; } +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* try to load embedded bitmap if any */ + /* */ + /* XXX: The convention should be emphasized in */ + /* the documents because it can be confusing. */ + if ( size && + size->strike_index != 0xFFFFU && + sfnt->load_sbits && + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) + { + TT_SBit_MetricsRec metrics; + + + error = sfnt->load_sbit_image( face, + (FT_ULong)size->strike_index, + (FT_UInt)glyph_index, + (FT_Int)load_flags, + stream, + &glyph->root.bitmap, + &metrics ); + + if ( !error ) + { + glyph->root.outline.n_points = 0; + glyph->root.outline.n_contours = 0; + + glyph->root.metrics.width = (FT_Pos)metrics.width << 6; + glyph->root.metrics.height = (FT_Pos)metrics.height << 6; + + glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; + glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; + glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; + + glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; + glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; + glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; + + glyph->root.format = FT_GLYPH_FORMAT_BITMAP; + + if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + { + glyph->root.bitmap_left = metrics.vertBearingX; + glyph->root.bitmap_top = metrics.vertBearingY; + } + else + { + glyph->root.bitmap_left = metrics.horiBearingX; + glyph->root.bitmap_top = metrics.horiBearingY; + } + return error; + } + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* return immediately if we only want the embedded bitmaps */ + if ( load_flags & FT_LOAD_SBITS_ONLY ) + return CFF_Err_Invalid_Argument; + glyph->root.outline.n_points = 0; glyph->root.outline.n_contours = 0; @@ -2444,7 +2509,7 @@ glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; glyph->root.outline.flags = 0; - if ( size && size->metrics.y_ppem < 24 ) + if ( size && size->root.metrics.y_ppem < 24 ) glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; diff --git a/src/cff/cffload.c b/src/cff/cffload.c index bbec294ed..44f3254bd 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1177,7 +1177,7 @@ cff_index_get_pointers( CFF_Index idx, FT_Byte*** table ) { - FT_Error error = 0; + FT_Error error = CFF_Err_Ok; FT_Memory memory = idx->stream->memory; FT_ULong n, offset, old_offset; FT_Byte** t; @@ -1516,7 +1516,7 @@ FT_Bool invert ) { FT_Memory memory = stream->memory; - FT_Error error = 0; + FT_Error error = CFF_Err_Ok; FT_UShort glyph_sid; @@ -1722,7 +1722,7 @@ FT_ULong base_offset, FT_ULong offset ) { - FT_Error error = 0; + FT_Error error = CFF_Err_Ok; FT_UInt count; FT_UInt j; FT_UShort glyph_sid; diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c index 6abb84b60..5e9e70a77 100644 --- a/src/cff/cffobjs.c +++ b/src/cff/cffobjs.c @@ -4,7 +4,7 @@ /* */ /* OpenType objects manager (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003 by */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -52,16 +52,81 @@ /*************************************************************************/ +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + static FT_Error + sbit_size_reset( CFF_Size size ) + { + CFF_Face face; + FT_Error error = CFF_Err_Ok; + + FT_ULong strike_index; + FT_Size_Metrics* metrics; + FT_Size_Metrics* sbit_metrics; + SFNT_Service sfnt; + + + metrics = &size->root.metrics; + + face = (CFF_Face)size->root.face; + sfnt = (SFNT_Service)face->sfnt; + + sbit_metrics = &size->strike_metrics; + + error = sfnt->set_sbit_strike( face, + metrics->x_ppem, metrics->y_ppem, + &strike_index ); + + if ( !error ) + { + TT_SBit_Strike strike = face->sbit_strikes + strike_index; + + + sbit_metrics->x_ppem = metrics->x_ppem; + sbit_metrics->y_ppem = metrics->y_ppem; + + sbit_metrics->ascender = strike->hori.ascender << 6; + sbit_metrics->descender = strike->hori.descender << 6; + + /* XXX: Is this correct? */ + sbit_metrics->height = sbit_metrics->ascender - + sbit_metrics->descender; + + /* XXX: Is this correct? */ + sbit_metrics->max_advance = ( strike->hori.min_origin_SB + + strike->hori.max_width + + strike->hori.min_advance_SB ) << 6; + + size->strike_index = (FT_UInt)strike_index; + } + else + { + size->strike_index = 0xFFFFU; + + sbit_metrics->x_ppem = 0; + sbit_metrics->y_ppem = 0; + sbit_metrics->ascender = 0; + sbit_metrics->descender = 0; + sbit_metrics->height = 0; + sbit_metrics->max_advance = 0; + } + + return error; + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + static PSH_Globals_Funcs cff_size_get_globals_funcs( CFF_Size size ) { - CFF_Face face = (CFF_Face)size->face; + CFF_Face face = (CFF_Face)size->root.face; CFF_Font font = (CFF_FontRec *)face->extra.data; PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; FT_Module module; - module = FT_Get_Module( size->face->driver->root.library, + module = FT_Get_Module( size->root.face->driver->root.library, "pshinter" ); return ( module && pshinter && pshinter->get_globals_funcs ) ? pshinter->get_globals_funcs( module ) @@ -72,16 +137,16 @@ FT_LOCAL_DEF( void ) cff_size_done( CFF_Size size ) { - if ( size->internal ) + if ( size->root.internal ) { PSH_Globals_Funcs funcs; funcs = cff_size_get_globals_funcs( size ); if ( funcs ) - funcs->destroy( (PSH_Globals)size->internal ); + funcs->destroy( (PSH_Globals)size->root.internal ); - size->internal = 0; + size->root.internal = 0; } } @@ -89,14 +154,14 @@ FT_LOCAL_DEF( FT_Error ) cff_size_init( CFF_Size size ) { - FT_Error error = 0; + FT_Error error = CFF_Err_Ok; PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size ); if ( funcs ) { PSH_Globals globals; - CFF_Face face = (CFF_Face)size->face; + CFF_Face face = (CFF_Face)size->root.face; CFF_Font font = (CFF_FontRec *)face->extra.data; CFF_SubFont subfont = &font->top_font; @@ -150,9 +215,9 @@ priv.lenIV = cpriv->lenIV; } - error = funcs->create( size->face->memory, &priv, &globals ); + error = funcs->create( size->root.face->memory, &priv, &globals ); if ( !error ) - size->internal = (FT_Size_Internal)(void*)globals; + size->root.internal = (FT_Size_Internal)(void*)globals; } return error; @@ -163,15 +228,32 @@ cff_size_reset( CFF_Size size ) { PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size ); - FT_Error error = 0; + FT_Error error = CFF_Err_Ok; + FT_Face face = size->root.face; if ( funcs ) - error = funcs->set_scale( (PSH_Globals)size->internal, - size->metrics.x_scale, - size->metrics.y_scale, + error = funcs->set_scale( (PSH_Globals)size->root.internal, + size->root.metrics.x_scale, + size->root.metrics.y_scale, 0, 0 ); - return error; + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + if ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) + { + error = sbit_size_reset( size ); + + if ( !error && !( face->face_flags & FT_FACE_FLAG_SCALABLE ) ) + size->root.metrics = size->strike_metrics; + } + +#endif + + if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + return CFF_Err_Ok; + else + return error; } diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h index 49d566550..f02a5d748 100644 --- a/src/cff/cffobjs.h +++ b/src/cff/cffobjs.h @@ -4,7 +4,7 @@ /* */ /* OpenType objects manager (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003 by */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -51,7 +51,18 @@ FT_BEGIN_HEADER /* */ /* A handle to an OpenType size object. */ /* */ - typedef FT_Size CFF_Size; + typedef struct CFF_SizeRec_ + { + FT_SizeRec root; + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + FT_UInt strike_index; /* 0xFFFF to indicate invalid */ + FT_Size_Metrics strike_metrics; /* current strike's metrics */ + +#endif + + } CFF_SizeRec, *CFF_Size; /*************************************************************************/