diff --git a/src/bdf/bdfdrivr.c b/src/bdf/bdfdrivr.c index a2242be..c0a5a5c 100644 --- a/src/bdf/bdfdrivr.c +++ b/src/bdf/bdfdrivr.c @@ -545,7 +545,11 @@ THE SOFTWARE. if ( !ft_strcmp( s, "10646" ) || ( !ft_strcmp( s, "8859" ) && !ft_strcmp( face->charset_encoding, "1" ) ) ) - unicode_charmap = 1; + unicode_charmap = 1; + /* another name for ASCII */ + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( face->charset_encoding, "IRV" ) ) + unicode_charmap = 1; } { diff --git a/src/bdf/bdfdrivr.c.pcf-encoding b/src/bdf/bdfdrivr.c.pcf-encoding new file mode 100644 index 0000000..a2242be --- /dev/null +++ b/src/bdf/bdfdrivr.c.pcf-encoding @@ -0,0 +1,898 @@ +/* bdfdrivr.c + + FreeType font driver for bdf files + + Copyright (C) 2001-2008, 2011, 2013, 2014 by + Francesco Zappa Nardelli + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include + +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H +#include FT_BDF_H +#include FT_TRUETYPE_IDS_H + +#include FT_SERVICE_BDF_H +#include FT_SERVICE_FONT_FORMAT_H + +#include "bdf.h" +#include "bdfdrivr.h" + +#include "bdferror.h" + + + /*************************************************************************/ + /* */ + /* 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_bdfdriver + + + typedef struct BDF_CMapRec_ + { + FT_CMapRec cmap; + FT_ULong num_encodings; /* ftobjs.h: FT_CMap->clazz->size */ + BDF_encoding_el* encodings; + + } BDF_CMapRec, *BDF_CMap; + + + FT_CALLBACK_DEF( FT_Error ) + bdf_cmap_init( FT_CMap bdfcmap, + FT_Pointer init_data ) + { + BDF_CMap cmap = (BDF_CMap)bdfcmap; + BDF_Face face = (BDF_Face)FT_CMAP_FACE( cmap ); + FT_UNUSED( init_data ); + + + cmap->num_encodings = face->bdffont->glyphs_used; + cmap->encodings = face->en_table; + + return FT_Err_Ok; + } + + + FT_CALLBACK_DEF( void ) + bdf_cmap_done( FT_CMap bdfcmap ) + { + BDF_CMap cmap = (BDF_CMap)bdfcmap; + + + cmap->encodings = NULL; + cmap->num_encodings = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + bdf_cmap_char_index( FT_CMap bdfcmap, + FT_UInt32 charcode ) + { + BDF_CMap cmap = (BDF_CMap)bdfcmap; + BDF_encoding_el* encodings = cmap->encodings; + FT_ULong min, max, mid; /* num_encodings */ + FT_UShort result = 0; /* encodings->glyph */ + + + min = 0; + max = cmap->num_encodings; + + while ( min < max ) + { + FT_ULong code; + + + mid = ( min + max ) >> 1; + code = (FT_ULong)encodings[mid].enc; + + if ( charcode == code ) + { + /* increase glyph index by 1 -- */ + /* we reserve slot 0 for the undefined glyph */ + result = encodings[mid].glyph + 1; + break; + } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } + + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + bdf_cmap_char_next( FT_CMap bdfcmap, + FT_UInt32 *acharcode ) + { + BDF_CMap cmap = (BDF_CMap)bdfcmap; + BDF_encoding_el* encodings = cmap->encodings; + FT_ULong min, max, mid; /* num_encodings */ + FT_UShort result = 0; /* encodings->glyph */ + FT_ULong charcode = *acharcode + 1; + + + min = 0; + max = cmap->num_encodings; + + while ( min < max ) + { + FT_ULong code; /* same as BDF_encoding_el.enc */ + + + mid = ( min + max ) >> 1; + code = (FT_ULong)encodings[mid].enc; + + if ( charcode == code ) + { + /* increase glyph index by 1 -- */ + /* we reserve slot 0 for the undefined glyph */ + result = encodings[mid].glyph + 1; + goto Exit; + } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } + + charcode = 0; + if ( min < cmap->num_encodings ) + { + charcode = (FT_ULong)encodings[min].enc; + result = encodings[min].glyph + 1; + } + + Exit: + if ( charcode > 0xFFFFFFFFUL ) + { + FT_TRACE1(( "bdf_cmap_char_next: charcode 0x%x > 32bit API" )); + *acharcode = 0; + /* XXX: result should be changed to indicate an overflow error */ + } + else + *acharcode = (FT_UInt32)charcode; + return result; + } + + + static + const FT_CMap_ClassRec bdf_cmap_class = + { + sizeof ( BDF_CMapRec ), + bdf_cmap_init, + bdf_cmap_done, + bdf_cmap_char_index, + bdf_cmap_char_next, + + NULL, NULL, NULL, NULL, NULL + }; + + + static FT_Error + bdf_interpret_style( BDF_Face bdf ) + { + FT_Error error = FT_Err_Ok; + FT_Face face = FT_FACE( bdf ); + FT_Memory memory = face->memory; + bdf_font_t* font = bdf->bdffont; + bdf_property_t* prop; + + char* strings[4] = { NULL, NULL, NULL, NULL }; + size_t nn, len, lengths[4]; + + + face->style_flags = 0; + + prop = bdf_get_font_property( font, (char *)"SLANT" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && + ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' || + *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) ) + { + face->style_flags |= FT_STYLE_FLAG_ITALIC; + strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ) + ? (char *)"Oblique" + : (char *)"Italic"; + } + + prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && + ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) ) + { + face->style_flags |= FT_STYLE_FLAG_BOLD; + strings[1] = (char *)"Bold"; + } + + prop = bdf_get_font_property( font, (char *)"SETWIDTH_NAME" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && *(prop->value.atom) && + !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) + strings[3] = (char *)(prop->value.atom); + + prop = bdf_get_font_property( font, (char *)"ADD_STYLE_NAME" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && *(prop->value.atom) && + !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) + strings[0] = (char *)(prop->value.atom); + + for ( len = 0, nn = 0; nn < 4; nn++ ) + { + lengths[nn] = 0; + if ( strings[nn] ) + { + lengths[nn] = ft_strlen( strings[nn] ); + len += lengths[nn] + 1; + } + } + + if ( len == 0 ) + { + strings[0] = (char *)"Regular"; + lengths[0] = ft_strlen( strings[0] ); + len = lengths[0] + 1; + } + + { + char* s; + + + if ( FT_ALLOC( face->style_name, len ) ) + return error; + + s = face->style_name; + + for ( nn = 0; nn < 4; nn++ ) + { + char* src = strings[nn]; + + + len = lengths[nn]; + + if ( !src ) + continue; + + /* separate elements with a space */ + if ( s != face->style_name ) + *s++ = ' '; + + ft_memcpy( s, src, len ); + + /* need to convert spaces to dashes for */ + /* add_style_name and setwidth_name */ + if ( nn == 0 || nn == 3 ) + { + size_t mm; + + + for ( mm = 0; mm < len; mm++ ) + if ( s[mm] == ' ' ) + s[mm] = '-'; + } + + s += len; + } + *s = 0; + } + + return error; + } + + + FT_CALLBACK_DEF( void ) + BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */ + { + BDF_Face face = (BDF_Face)bdfface; + FT_Memory memory; + + + if ( !face ) + return; + + memory = FT_FACE_MEMORY( face ); + + bdf_free_font( face->bdffont ); + + FT_FREE( face->en_table ); + + FT_FREE( face->charset_encoding ); + FT_FREE( face->charset_registry ); + FT_FREE( bdfface->family_name ); + FT_FREE( bdfface->style_name ); + + FT_FREE( bdfface->available_sizes ); + + FT_FREE( face->bdffont ); + } + + + FT_CALLBACK_DEF( FT_Error ) + BDF_Face_Init( FT_Stream stream, + FT_Face bdfface, /* BDF_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error = FT_Err_Ok; + BDF_Face face = (BDF_Face)bdfface; + FT_Memory memory = FT_FACE_MEMORY( face ); + + bdf_font_t* font = NULL; + bdf_options_t options; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + FT_TRACE2(( "BDF driver\n" )); + + if ( FT_STREAM_SEEK( 0 ) ) + goto Exit; + + options.correct_metrics = 1; /* FZ XXX: options semantics */ + options.keep_unencoded = 1; + options.keep_comments = 0; + options.font_spacing = BDF_PROPORTIONAL; + + error = bdf_load_font( stream, memory, &options, &font ); + if ( FT_ERR_EQ( error, Missing_Startfont_Field ) ) + { + FT_TRACE2(( " not a BDF file\n" )); + goto Fail; + } + else if ( error ) + goto Exit; + + /* we have a bdf font: let's construct the face object */ + face->bdffont = font; + + /* BDF could not have multiple face in single font file. + * XXX: non-zero face_index is already invalid argument, but + * Type1, Type42 driver has a convention to return + * an invalid argument error when the font could be + * opened by the specified driver. + */ + if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) + { + FT_ERROR(( "BDF_Face_Init: invalid face index\n" )); + BDF_Face_Done( bdfface ); + return FT_THROW( Invalid_Argument ); + } + + { + bdf_property_t* prop = NULL; + + + FT_TRACE4(( " number of glyphs: allocated %d (used %d)\n", + font->glyphs_size, + font->glyphs_used )); + FT_TRACE4(( " number of unencoded glyphs: allocated %d (used %d)\n", + font->unencoded_size, + font->unencoded_used )); + + bdfface->num_faces = 1; + bdfface->face_index = 0; + + bdfface->face_flags |= FT_FACE_FLAG_FIXED_SIZES | + FT_FACE_FLAG_HORIZONTAL | + FT_FACE_FLAG_FAST_GLYPHS; + + prop = bdf_get_font_property( font, "SPACING" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && + ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' || + *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) ) + bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */ + /* FZ XXX: I need a font to implement this */ + + prop = bdf_get_font_property( font, "FAMILY_NAME" ); + if ( prop && prop->value.atom ) + { + if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) ) + goto Exit; + } + else + bdfface->family_name = NULL; + + if ( FT_SET_ERROR( bdf_interpret_style( face ) ) ) + goto Exit; + + /* the number of glyphs (with one slot for the undefined glyph */ + /* at position 0 and all unencoded glyphs) */ + bdfface->num_glyphs = (FT_Long)( font->glyphs_size + 1 ); + + bdfface->num_fixed_sizes = 1; + if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) ) + goto Exit; + + { + FT_Bitmap_Size* bsize = bdfface->available_sizes; + FT_Short resolution_x = 0, resolution_y = 0; + + + FT_ZERO( bsize ); + + bsize->height = (FT_Short)( font->font_ascent + font->font_descent ); + + prop = bdf_get_font_property( font, "AVERAGE_WIDTH" ); + if ( prop ) + bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 ); + else + bsize->width = (FT_Short)( bsize->height * 2/3 ); + + prop = bdf_get_font_property( font, "POINT_SIZE" ); + if ( prop ) + /* convert from 722.7 decipoints to 72 points per inch */ + bsize->size = + (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L ); + else + bsize->size = bsize->width << 6; + + prop = bdf_get_font_property( font, "PIXEL_SIZE" ); + if ( prop ) + bsize->y_ppem = (FT_Short)prop->value.l << 6; + + prop = bdf_get_font_property( font, "RESOLUTION_X" ); + if ( prop ) + resolution_x = (FT_Short)prop->value.l; + + prop = bdf_get_font_property( font, "RESOLUTION_Y" ); + if ( prop ) + resolution_y = (FT_Short)prop->value.l; + + if ( bsize->y_ppem == 0 ) + { + bsize->y_ppem = bsize->size; + if ( resolution_y ) + bsize->y_ppem = bsize->y_ppem * resolution_y / 72; + } + if ( resolution_x && resolution_y ) + bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y; + else + bsize->x_ppem = bsize->y_ppem; + } + + /* encoding table */ + { + bdf_glyph_t* cur = font->glyphs; + unsigned long n; + + + if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) ) + goto Exit; + + face->default_glyph = 0; + for ( n = 0; n < font->glyphs_size; n++ ) + { + (face->en_table[n]).enc = cur[n].encoding; + FT_TRACE4(( " idx %d, val 0x%lX\n", n, cur[n].encoding )); + (face->en_table[n]).glyph = (FT_UShort)n; + + if ( cur[n].encoding == font->default_char ) + { + if ( n < FT_UINT_MAX ) + face->default_glyph = (FT_UInt)n; + else + FT_TRACE1(( "BDF_Face_Init:" + " idx %d is too large for this system\n", n )); + } + } + } + + /* charmaps */ + { + bdf_property_t *charset_registry, *charset_encoding; + FT_Bool unicode_charmap = 0; + + + charset_registry = + bdf_get_font_property( font, "CHARSET_REGISTRY" ); + charset_encoding = + bdf_get_font_property( font, "CHARSET_ENCODING" ); + if ( charset_registry && charset_encoding ) + { + if ( charset_registry->format == BDF_ATOM && + charset_encoding->format == BDF_ATOM && + charset_registry->value.atom && + charset_encoding->value.atom ) + { + const char* s; + + + if ( FT_STRDUP( face->charset_encoding, + charset_encoding->value.atom ) || + FT_STRDUP( face->charset_registry, + charset_registry->value.atom ) ) + goto Exit; + + /* Uh, oh, compare first letters manually to avoid dependency */ + /* on locales. */ + s = face->charset_registry; + if ( ( s[0] == 'i' || s[0] == 'I' ) && + ( s[1] == 's' || s[1] == 'S' ) && + ( s[2] == 'o' || s[2] == 'O' ) ) + { + s += 3; + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( face->charset_encoding, "1" ) ) ) + unicode_charmap = 1; + } + + { + FT_CharMapRec charmap; + + + charmap.face = FT_FACE( face ); + charmap.encoding = FT_ENCODING_NONE; + /* initial platform/encoding should indicate unset status? */ + charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; + charmap.encoding_id = TT_APPLE_ID_DEFAULT; + + if ( unicode_charmap ) + { + charmap.encoding = FT_ENCODING_UNICODE; + charmap.platform_id = TT_PLATFORM_MICROSOFT; + charmap.encoding_id = TT_MS_ID_UNICODE_CS; + } + + error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); + +#if 0 + /* Select default charmap */ + if ( bdfface->num_charmaps ) + bdfface->charmap = bdfface->charmaps[0]; +#endif + } + + goto Exit; + } + } + + /* otherwise assume Adobe standard encoding */ + + { + FT_CharMapRec charmap; + + + charmap.face = FT_FACE( face ); + charmap.encoding = FT_ENCODING_ADOBE_STANDARD; + charmap.platform_id = TT_PLATFORM_ADOBE; + charmap.encoding_id = TT_ADOBE_ID_STANDARD; + + error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); + + /* Select default charmap */ + if ( bdfface->num_charmaps ) + bdfface->charmap = bdfface->charmaps[0]; + } + } + } + + Exit: + return error; + + Fail: + BDF_Face_Done( bdfface ); + return FT_THROW( Unknown_File_Format ); + } + + + FT_CALLBACK_DEF( FT_Error ) + BDF_Size_Select( FT_Size size, + FT_ULong strike_index ) + { + bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont; + + + FT_Select_Metrics( size->face, strike_index ); + + size->metrics.ascender = bdffont->font_ascent * 64; + size->metrics.descender = -bdffont->font_descent * 64; + size->metrics.max_advance = bdffont->bbx.width * 64; + + return FT_Err_Ok; + } + + + FT_CALLBACK_DEF( FT_Error ) + BDF_Size_Request( FT_Size size, + FT_Size_Request req ) + { + FT_Face face = size->face; + FT_Bitmap_Size* bsize = face->available_sizes; + bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont; + FT_Error error = FT_ERR( Invalid_Pixel_Size ); + FT_Long height; + + + height = FT_REQUEST_HEIGHT( req ); + height = ( height + 32 ) >> 6; + + switch ( req->type ) + { + case FT_SIZE_REQUEST_TYPE_NOMINAL: + if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) ) + error = FT_Err_Ok; + break; + + case FT_SIZE_REQUEST_TYPE_REAL_DIM: + if ( height == ( bdffont->font_ascent + + bdffont->font_descent ) ) + error = FT_Err_Ok; + break; + + default: + error = FT_THROW( Unimplemented_Feature ); + break; + } + + if ( error ) + return error; + else + return BDF_Size_Select( size, 0 ); + } + + + + FT_CALLBACK_DEF( FT_Error ) + BDF_Glyph_Load( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size ); + FT_Face face = FT_FACE( bdf ); + FT_Error error = FT_Err_Ok; + FT_Bitmap* bitmap = &slot->bitmap; + bdf_glyph_t glyph; + int bpp = bdf->bdffont->bpp; + + FT_UNUSED( load_flags ); + + + if ( !face ) + { + error = FT_THROW( Invalid_Face_Handle ); + goto Exit; + } + + if ( glyph_index >= (FT_UInt)face->num_glyphs ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index )); + + /* index 0 is the undefined glyph */ + if ( glyph_index == 0 ) + glyph_index = bdf->default_glyph; + else + glyph_index--; + + /* slot, bitmap => freetype, glyph => bdflib */ + glyph = bdf->bdffont->glyphs[glyph_index]; + + bitmap->rows = glyph.bbx.height; + bitmap->width = glyph.bbx.width; + if ( glyph.bpr > INT_MAX ) + FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n", + glyph.bpr )); + bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */ + + /* note: we don't allocate a new array to hold the bitmap; */ + /* we can simply point to it */ + ft_glyphslot_set_bitmap( slot, glyph.bitmap ); + + switch ( bpp ) + { + case 1: + bitmap->pixel_mode = FT_PIXEL_MODE_MONO; + break; + case 2: + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2; + break; + case 4: + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4; + break; + case 8: + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; + bitmap->num_grays = 256; + break; + } + + slot->format = FT_GLYPH_FORMAT_BITMAP; + slot->bitmap_left = glyph.bbx.x_offset; + slot->bitmap_top = glyph.bbx.ascent; + + slot->metrics.horiAdvance = (FT_Pos)( glyph.dwidth * 64 ); + slot->metrics.horiBearingX = (FT_Pos)( glyph.bbx.x_offset * 64 ); + slot->metrics.horiBearingY = (FT_Pos)( glyph.bbx.ascent * 64 ); + slot->metrics.width = (FT_Pos)( bitmap->width * 64 ); + slot->metrics.height = (FT_Pos)( bitmap->rows * 64 ); + + /* + * XXX DWIDTH1 and VVECTOR should be parsed and + * used here, provided such fonts do exist. + */ + ft_synthesize_vertical_metrics( &slot->metrics, + bdf->bdffont->bbx.height * 64 ); + + Exit: + return error; + } + + + /* + * + * BDF SERVICE + * + */ + + static FT_Error + bdf_get_bdf_property( BDF_Face face, + const char* prop_name, + BDF_PropertyRec *aproperty ) + { + bdf_property_t* prop; + + + FT_ASSERT( face && face->bdffont ); + + prop = bdf_get_font_property( face->bdffont, prop_name ); + if ( prop ) + { + switch ( prop->format ) + { + case BDF_ATOM: + aproperty->type = BDF_PROPERTY_TYPE_ATOM; + aproperty->u.atom = prop->value.atom; + break; + + case BDF_INTEGER: + if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) ) + { + FT_TRACE1(( "bdf_get_bdf_property:" + " too large integer 0x%x is truncated\n" )); + } + aproperty->type = BDF_PROPERTY_TYPE_INTEGER; + aproperty->u.integer = (FT_Int32)prop->value.l; + break; + + case BDF_CARDINAL: + if ( prop->value.ul > 0xFFFFFFFFUL ) + { + FT_TRACE1(( "bdf_get_bdf_property:" + " too large cardinal 0x%x is truncated\n" )); + } + aproperty->type = BDF_PROPERTY_TYPE_CARDINAL; + aproperty->u.cardinal = (FT_UInt32)prop->value.ul; + break; + + default: + goto Fail; + } + return 0; + } + + Fail: + return FT_THROW( Invalid_Argument ); + } + + + static FT_Error + bdf_get_charset_id( BDF_Face face, + const char* *acharset_encoding, + const char* *acharset_registry ) + { + *acharset_encoding = face->charset_encoding; + *acharset_registry = face->charset_registry; + + return 0; + } + + + static const FT_Service_BDFRec bdf_service_bdf = + { + (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id, /* get_charset_id */ + (FT_BDF_GetPropertyFunc) bdf_get_bdf_property /* get_property */ + }; + + + /* + * + * SERVICES LIST + * + */ + + static const FT_ServiceDescRec bdf_services[] = + { + { FT_SERVICE_ID_BDF, &bdf_service_bdf }, + { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_BDF }, + { NULL, NULL } + }; + + + FT_CALLBACK_DEF( FT_Module_Interface ) + bdf_driver_requester( FT_Module module, + const char* name ) + { + FT_UNUSED( module ); + + return ft_service_list_lookup( bdf_services, name ); + } + + + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec bdf_driver_class = + { + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_NO_OUTLINES, + sizeof ( FT_DriverRec ), + + "bdf", + 0x10000L, + 0x20000L, + + NULL, /* module-specific interface */ + + NULL, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + bdf_driver_requester /* FT_Module_Requester get_interface */ + }, + + sizeof ( BDF_FaceRec ), + sizeof ( FT_SizeRec ), + sizeof ( FT_GlyphSlotRec ), + + BDF_Face_Init, /* FT_Face_InitFunc init_face */ + BDF_Face_Done, /* FT_Face_DoneFunc done_face */ + NULL, /* FT_Size_InitFunc init_size */ + NULL, /* FT_Size_DoneFunc done_size */ + NULL, /* FT_Slot_InitFunc init_slot */ + NULL, /* FT_Slot_DoneFunc done_slot */ + + BDF_Glyph_Load, /* FT_Slot_LoadFunc load_glyph */ + + NULL, /* FT_Face_GetKerningFunc get_kerning */ + NULL, /* FT_Face_AttachFunc attach_file */ + NULL, /* FT_Face_GetAdvancesFunc get_advances */ + + BDF_Size_Request, /* FT_Size_RequestFunc request_size */ + BDF_Size_Select /* FT_Size_SelectFunc select_size */ + }; + + +/* END */ diff --git a/src/pcf/pcfdrivr.c b/src/pcf/pcfdrivr.c index 9f4d36d..5053094 100644 --- a/src/pcf/pcfdrivr.c +++ b/src/pcf/pcfdrivr.c @@ -387,7 +387,11 @@ THE SOFTWARE. if ( !ft_strcmp( s, "10646" ) || ( !ft_strcmp( s, "8859" ) && !ft_strcmp( face->charset_encoding, "1" ) ) ) - unicode_charmap = 1; + unicode_charmap = 1; + /* another name for ASCII */ + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( face->charset_encoding, "IRV" ) ) + unicode_charmap = 1; } } diff --git a/src/pcf/pcfdrivr.c.pcf-encoding b/src/pcf/pcfdrivr.c.pcf-encoding new file mode 100644 index 0000000..9f4d36d --- /dev/null +++ b/src/pcf/pcfdrivr.c.pcf-encoding @@ -0,0 +1,871 @@ +/* pcfdrivr.c + + FreeType font driver for pcf files + + Copyright (C) 2000-2004, 2006-2011, 2013, 2014 by + Francesco Zappa Nardelli + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + + +#include + +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H +#include FT_GZIP_H +#include FT_LZW_H +#include FT_BZIP2_H +#include FT_ERRORS_H +#include FT_BDF_H +#include FT_TRUETYPE_IDS_H + +#include "pcf.h" +#include "pcfdrivr.h" +#include "pcfread.h" + +#include "pcferror.h" +#include "pcfutil.h" + +#undef FT_COMPONENT +#define FT_COMPONENT trace_pcfread + +#include FT_SERVICE_BDF_H +#include FT_SERVICE_FONT_FORMAT_H +#include FT_SERVICE_PROPERTIES_H +#include FT_PCF_DRIVER_H + + + /*************************************************************************/ + /* */ + /* 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_pcfdriver + + + typedef struct PCF_CMapRec_ + { + FT_CMapRec root; + FT_ULong num_encodings; + PCF_Encoding encodings; + + } PCF_CMapRec, *PCF_CMap; + + + FT_CALLBACK_DEF( FT_Error ) + pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */ + FT_Pointer init_data ) + { + PCF_CMap cmap = (PCF_CMap)pcfcmap; + PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap ); + + FT_UNUSED( init_data ); + + + cmap->num_encodings = face->nencodings; + cmap->encodings = face->encodings; + + return FT_Err_Ok; + } + + + FT_CALLBACK_DEF( void ) + pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */ + { + PCF_CMap cmap = (PCF_CMap)pcfcmap; + + + cmap->encodings = NULL; + cmap->num_encodings = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */ + FT_UInt32 charcode ) + { + PCF_CMap cmap = (PCF_CMap)pcfcmap; + PCF_Encoding encodings = cmap->encodings; + FT_ULong min, max, mid; + FT_UInt result = 0; + + + min = 0; + max = cmap->num_encodings; + + while ( min < max ) + { + FT_ULong code; + + + mid = ( min + max ) >> 1; + code = (FT_ULong)encodings[mid].enc; + + if ( charcode == code ) + { + result = encodings[mid].glyph + 1; + break; + } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } + + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */ + FT_UInt32 *acharcode ) + { + PCF_CMap cmap = (PCF_CMap)pcfcmap; + PCF_Encoding encodings = cmap->encodings; + FT_ULong min, max, mid; + FT_ULong charcode = *acharcode + 1; + FT_UInt result = 0; + + + min = 0; + max = cmap->num_encodings; + + while ( min < max ) + { + FT_ULong code; + + + mid = ( min + max ) >> 1; + code = (FT_ULong)encodings[mid].enc; + + if ( charcode == code ) + { + result = encodings[mid].glyph + 1; + goto Exit; + } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } + + charcode = 0; + if ( min < cmap->num_encodings ) + { + charcode = (FT_ULong)encodings[min].enc; + result = encodings[min].glyph + 1; + } + + Exit: + if ( charcode > 0xFFFFFFFFUL ) + { + FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" )); + *acharcode = 0; + /* XXX: result should be changed to indicate an overflow error */ + } + else + *acharcode = (FT_UInt32)charcode; + return result; + } + + + static + const FT_CMap_ClassRec pcf_cmap_class = + { + sizeof ( PCF_CMapRec ), + pcf_cmap_init, + pcf_cmap_done, + pcf_cmap_char_index, + pcf_cmap_char_next, + + NULL, NULL, NULL, NULL, NULL + }; + + + FT_CALLBACK_DEF( void ) + PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */ + { + PCF_Face face = (PCF_Face)pcfface; + FT_Memory memory; + + + if ( !face ) + return; + + memory = FT_FACE_MEMORY( face ); + + FT_FREE( face->encodings ); + FT_FREE( face->metrics ); + + /* free properties */ + if ( face->properties ) + { + FT_Int i; + + + for ( i = 0; i < face->nprops; i++ ) + { + PCF_Property prop = &face->properties[i]; + + + if ( prop ) + { + FT_FREE( prop->name ); + if ( prop->isString ) + FT_FREE( prop->value.atom ); + } + } + + FT_FREE( face->properties ); + } + + FT_FREE( face->toc.tables ); + FT_FREE( pcfface->family_name ); + FT_FREE( pcfface->style_name ); + FT_FREE( pcfface->available_sizes ); + FT_FREE( face->charset_encoding ); + FT_FREE( face->charset_registry ); + + /* close compressed stream if any */ + if ( pcfface->stream == &face->comp_stream ) + { + FT_Stream_Close( &face->comp_stream ); + pcfface->stream = face->comp_source; + } + } + + + FT_CALLBACK_DEF( FT_Error ) + PCF_Face_Init( FT_Stream stream, + FT_Face pcfface, /* PCF_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + PCF_Face face = (PCF_Face)pcfface; + FT_Error error; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + FT_TRACE2(( "PCF driver\n" )); + + error = pcf_load_font( stream, face, face_index ); + if ( error ) + { + PCF_Face_Done( pcfface ); + +#if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \ + defined( FT_CONFIG_OPTION_USE_LZW ) || \ + defined( FT_CONFIG_OPTION_USE_BZIP2 ) + +#ifdef FT_CONFIG_OPTION_USE_ZLIB + { + FT_Error error2; + + + /* this didn't work, try gzip support! */ + FT_TRACE2(( " ... try gzip stream\n" )); + error2 = FT_Stream_OpenGzip( &face->comp_stream, stream ); + if ( FT_ERR_EQ( error2, Unimplemented_Feature ) ) + goto Fail; + + error = error2; + } +#endif /* FT_CONFIG_OPTION_USE_ZLIB */ + +#ifdef FT_CONFIG_OPTION_USE_LZW + if ( error ) + { + FT_Error error3; + + + /* this didn't work, try LZW support! */ + FT_TRACE2(( " ... try LZW stream\n" )); + error3 = FT_Stream_OpenLZW( &face->comp_stream, stream ); + if ( FT_ERR_EQ( error3, Unimplemented_Feature ) ) + goto Fail; + + error = error3; + } +#endif /* FT_CONFIG_OPTION_USE_LZW */ + +#ifdef FT_CONFIG_OPTION_USE_BZIP2 + if ( error ) + { + FT_Error error4; + + + /* this didn't work, try Bzip2 support! */ + FT_TRACE2(( " ... try Bzip2 stream\n" )); + error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream ); + if ( FT_ERR_EQ( error4, Unimplemented_Feature ) ) + goto Fail; + + error = error4; + } +#endif /* FT_CONFIG_OPTION_USE_BZIP2 */ + + if ( error ) + goto Fail; + + face->comp_source = stream; + pcfface->stream = &face->comp_stream; + + stream = pcfface->stream; + + error = pcf_load_font( stream, face, face_index ); + if ( error ) + goto Fail; + +#else /* !(FT_CONFIG_OPTION_USE_ZLIB || + FT_CONFIG_OPTION_USE_LZW || + FT_CONFIG_OPTION_USE_BZIP2) */ + + goto Fail; + +#endif + } + + /* PCF cannot have multiple faces in a single font file. + * XXX: A non-zero face_index is already an invalid argument, but + * Type1, Type42 drivers have a convention to return + * an invalid argument error when the font could be + * opened by the specified driver. + */ + if ( face_index < 0 ) + goto Exit; + else if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) + { + FT_ERROR(( "PCF_Face_Init: invalid face index\n" )); + PCF_Face_Done( pcfface ); + return FT_THROW( Invalid_Argument ); + } + + /* set up charmap */ + { + FT_String *charset_registry = face->charset_registry; + FT_String *charset_encoding = face->charset_encoding; + FT_Bool unicode_charmap = 0; + + + if ( charset_registry && charset_encoding ) + { + char* s = charset_registry; + + + /* Uh, oh, compare first letters manually to avoid dependency + on locales. */ + if ( ( s[0] == 'i' || s[0] == 'I' ) && + ( s[1] == 's' || s[1] == 'S' ) && + ( s[2] == 'o' || s[2] == 'O' ) ) + { + s += 3; + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( face->charset_encoding, "1" ) ) ) + unicode_charmap = 1; + } + } + + { + FT_CharMapRec charmap; + + + charmap.face = FT_FACE( face ); + charmap.encoding = FT_ENCODING_NONE; + /* initial platform/encoding should indicate unset status? */ + charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; + charmap.encoding_id = TT_APPLE_ID_DEFAULT; + + if ( unicode_charmap ) + { + charmap.encoding = FT_ENCODING_UNICODE; + charmap.platform_id = TT_PLATFORM_MICROSOFT; + charmap.encoding_id = TT_MS_ID_UNICODE_CS; + } + + error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL ); + +#if 0 + /* Select default charmap */ + if ( pcfface->num_charmaps ) + pcfface->charmap = pcfface->charmaps[0]; +#endif + } + } + + Exit: + return error; + + Fail: + FT_TRACE2(( " not a PCF file\n" )); + PCF_Face_Done( pcfface ); + error = FT_THROW( Unknown_File_Format ); /* error */ + goto Exit; + } + + + FT_CALLBACK_DEF( FT_Error ) + PCF_Size_Select( FT_Size size, + FT_ULong strike_index ) + { + PCF_Accel accel = &( (PCF_Face)size->face )->accel; + + + FT_Select_Metrics( size->face, strike_index ); + + size->metrics.ascender = accel->fontAscent * 64; + size->metrics.descender = -accel->fontDescent * 64; + size->metrics.max_advance = accel->maxbounds.characterWidth * 64; + + return FT_Err_Ok; + } + + + FT_CALLBACK_DEF( FT_Error ) + PCF_Size_Request( FT_Size size, + FT_Size_Request req ) + { + PCF_Face face = (PCF_Face)size->face; + FT_Bitmap_Size* bsize = size->face->available_sizes; + FT_Error error = FT_ERR( Invalid_Pixel_Size ); + FT_Long height; + + + height = FT_REQUEST_HEIGHT( req ); + height = ( height + 32 ) >> 6; + + switch ( req->type ) + { + case FT_SIZE_REQUEST_TYPE_NOMINAL: + if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) ) + error = FT_Err_Ok; + break; + + case FT_SIZE_REQUEST_TYPE_REAL_DIM: + if ( height == ( face->accel.fontAscent + + face->accel.fontDescent ) ) + error = FT_Err_Ok; + break; + + default: + error = FT_THROW( Unimplemented_Feature ); + break; + } + + if ( error ) + return error; + else + return PCF_Size_Select( size, 0 ); + } + + + FT_CALLBACK_DEF( FT_Error ) + PCF_Glyph_Load( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + PCF_Face face = (PCF_Face)FT_SIZE_FACE( size ); + FT_Stream stream; + FT_Error error = FT_Err_Ok; + FT_Bitmap* bitmap = &slot->bitmap; + PCF_Metric metric; + FT_ULong bytes; + + + FT_TRACE1(( "PCF_Glyph_Load: glyph index %d\n", glyph_index )); + + if ( !face ) + { + error = FT_THROW( Invalid_Face_Handle ); + goto Exit; + } + + if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + stream = face->root.stream; + + if ( glyph_index > 0 ) + glyph_index--; + + metric = face->metrics + glyph_index; + + bitmap->rows = (unsigned int)( metric->ascent + + metric->descent ); + bitmap->width = (unsigned int)( metric->rightSideBearing - + metric->leftSideBearing ); + bitmap->num_grays = 1; + bitmap->pixel_mode = FT_PIXEL_MODE_MONO; + + switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) ) + { + case 1: + bitmap->pitch = (int)( ( bitmap->width + 7 ) >> 3 ); + break; + + case 2: + bitmap->pitch = (int)( ( ( bitmap->width + 15 ) >> 4 ) << 1 ); + break; + + case 4: + bitmap->pitch = (int)( ( ( bitmap->width + 31 ) >> 5 ) << 2 ); + break; + + case 8: + bitmap->pitch = (int)( ( ( bitmap->width + 63 ) >> 6 ) << 3 ); + break; + + default: + return FT_THROW( Invalid_File_Format ); + } + + slot->format = FT_GLYPH_FORMAT_BITMAP; + slot->bitmap_left = metric->leftSideBearing; + slot->bitmap_top = metric->ascent; + + slot->metrics.horiAdvance = (FT_Pos)( metric->characterWidth * 64 ); + slot->metrics.horiBearingX = (FT_Pos)( metric->leftSideBearing * 64 ); + slot->metrics.horiBearingY = (FT_Pos)( metric->ascent * 64 ); + slot->metrics.width = (FT_Pos)( ( metric->rightSideBearing - + metric->leftSideBearing ) * 64 ); + slot->metrics.height = (FT_Pos)( bitmap->rows * 64 ); + + ft_synthesize_vertical_metrics( &slot->metrics, + ( face->accel.fontAscent + + face->accel.fontDescent ) * 64 ); + + if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) + goto Exit; + + /* XXX: to do: are there cases that need repadding the bitmap? */ + bytes = (FT_ULong)bitmap->pitch * bitmap->rows; + + error = ft_glyphslot_alloc_bitmap( slot, (FT_ULong)bytes ); + if ( error ) + goto Exit; + + if ( FT_STREAM_SEEK( metric->bits ) || + FT_STREAM_READ( bitmap->buffer, bytes ) ) + goto Exit; + + if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst ) + BitOrderInvert( bitmap->buffer, bytes ); + + if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) != + PCF_BIT_ORDER( face->bitmapsFormat ) ) ) + { + switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) ) + { + case 1: + break; + + case 2: + TwoByteSwap( bitmap->buffer, bytes ); + break; + + case 4: + FourByteSwap( bitmap->buffer, bytes ); + break; + } + } + + Exit: + return error; + } + + + /* + * + * BDF SERVICE + * + */ + + static FT_Error + pcf_get_bdf_property( PCF_Face face, + const char* prop_name, + BDF_PropertyRec *aproperty ) + { + PCF_Property prop; + + + prop = pcf_find_property( face, prop_name ); + if ( prop ) + { + if ( prop->isString ) + { + aproperty->type = BDF_PROPERTY_TYPE_ATOM; + aproperty->u.atom = prop->value.atom; + } + else + { + if ( prop->value.l > 0x7FFFFFFFL || + prop->value.l < ( -1 - 0x7FFFFFFFL ) ) + { + FT_TRACE1(( "pcf_get_bdf_property:" )); + FT_TRACE1(( " too large integer 0x%x is truncated\n" )); + } + + /* + * The PCF driver loads all properties as signed integers. + * This really doesn't seem to be a problem, because this is + * sufficient for any meaningful values. + */ + aproperty->type = BDF_PROPERTY_TYPE_INTEGER; + aproperty->u.integer = (FT_Int32)prop->value.l; + } + + return FT_Err_Ok; + } + + return FT_THROW( Invalid_Argument ); + } + + + static FT_Error + pcf_get_charset_id( PCF_Face face, + const char* *acharset_encoding, + const char* *acharset_registry ) + { + *acharset_encoding = face->charset_encoding; + *acharset_registry = face->charset_registry; + + return FT_Err_Ok; + } + + + static const FT_Service_BDFRec pcf_service_bdf = + { + (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id, /* get_charset_id */ + (FT_BDF_GetPropertyFunc) pcf_get_bdf_property /* get_property */ + }; + + + /* + * PROPERTY SERVICE + * + */ + static FT_Error + pcf_property_set( FT_Module module, /* PCF_Driver */ + const char* property_name, + const void* value, + FT_Bool value_is_string ) + { +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + + FT_Error error = FT_Err_Ok; + PCF_Driver driver = (PCF_Driver)module; + +#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + FT_UNUSED( value_is_string ); +#endif + + + if ( !ft_strcmp( property_name, "no-long-family-names" ) ) + { +#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + if ( value_is_string ) + { + const char* s = (const char*)value; + long lfn = ft_strtol( s, NULL, 10 ); + + + if ( lfn == 0 ) + driver->no_long_family_names = 0; + else if ( lfn == 1 ) + driver->no_long_family_names = 1; + else + return FT_THROW( Invalid_Argument ); + } + else +#endif + { + FT_Bool* no_long_family_names = (FT_Bool*)value; + + + driver->no_long_family_names = *no_long_family_names; + } + + return error; + } + +#else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_UNUSED( module ); + FT_UNUSED( value ); + FT_UNUSED( value_is_string ); +#ifndef FT_DEBUG_LEVEL_TRACE + FT_UNUSED( property_name ); +#endif + +#endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_TRACE0(( "pcf_property_set: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); + } + + + static FT_Error + pcf_property_get( FT_Module module, /* PCF_Driver */ + const char* property_name, + const void* value ) + { +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + + FT_Error error = FT_Err_Ok; + PCF_Driver driver = (PCF_Driver)module; + + + if ( !ft_strcmp( property_name, "no-long-family-names" ) ) + { + FT_Bool no_long_family_names = driver->no_long_family_names; + FT_Bool* val = (FT_Bool*)value; + + + *val = no_long_family_names; + + return error; + } + +#else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_UNUSED( module ); + FT_UNUSED( value ); +#ifndef FT_DEBUG_LEVEL_TRACE + FT_UNUSED( property_name ); +#endif + +#endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_TRACE0(( "pcf_property_get: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); + } + + + FT_DEFINE_SERVICE_PROPERTIESREC( + pcf_service_properties, + + (FT_Properties_SetFunc)pcf_property_set, /* set_property */ + (FT_Properties_GetFunc)pcf_property_get ) /* get_property */ + + + /* + * + * SERVICE LIST + * + */ + + static const FT_ServiceDescRec pcf_services[] = + { + { FT_SERVICE_ID_BDF, &pcf_service_bdf }, + { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_PCF }, + { FT_SERVICE_ID_PROPERTIES, &pcf_service_properties }, + { NULL, NULL } + }; + + + FT_CALLBACK_DEF( FT_Module_Interface ) + pcf_driver_requester( FT_Module module, + const char* name ) + { + FT_UNUSED( module ); + + return ft_service_list_lookup( pcf_services, name ); + } + + + FT_CALLBACK_DEF( FT_Error ) + pcf_driver_init( FT_Module module ) /* PCF_Driver */ + { +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + PCF_Driver driver = (PCF_Driver)module; + + + driver->no_long_family_names = 0; +#else + FT_UNUSED( module ); +#endif + + return FT_Err_Ok; + } + + + FT_CALLBACK_DEF( void ) + pcf_driver_done( FT_Module module ) /* PCF_Driver */ + { + FT_UNUSED( module ); + } + + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec pcf_driver_class = + { + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_NO_OUTLINES, + + sizeof ( PCF_DriverRec ), + "pcf", + 0x10000L, + 0x20000L, + + NULL, /* module-specific interface */ + + pcf_driver_init, /* FT_Module_Constructor module_init */ + pcf_driver_done, /* FT_Module_Destructor module_done */ + pcf_driver_requester /* FT_Module_Requester get_interface */ + }, + + sizeof ( PCF_FaceRec ), + sizeof ( FT_SizeRec ), + sizeof ( FT_GlyphSlotRec ), + + PCF_Face_Init, /* FT_Face_InitFunc init_face */ + PCF_Face_Done, /* FT_Face_DoneFunc done_face */ + NULL, /* FT_Size_InitFunc init_size */ + NULL, /* FT_Size_DoneFunc done_size */ + NULL, /* FT_Slot_InitFunc init_slot */ + NULL, /* FT_Slot_DoneFunc done_slot */ + + PCF_Glyph_Load, /* FT_Slot_LoadFunc load_glyph */ + + NULL, /* FT_Face_GetKerningFunc get_kerning */ + NULL, /* FT_Face_AttachFunc attach_file */ + NULL, /* FT_Face_GetAdvancesFunc get_advances */ + + PCF_Size_Request, /* FT_Size_RequestFunc request_size */ + PCF_Size_Select /* FT_Size_SelectFunc select_size */ + }; + + +/* END */