| /* 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 <freetype/internal/ftdebug.h> |
| #include <freetype/internal/ftstream.h> |
| #include <freetype/internal/ftobjs.h> |
| #include <freetype/ftgzip.h> |
| #include <freetype/ftlzw.h> |
| #include <freetype/ftbzip2.h> |
| #include <freetype/fterrors.h> |
| #include <freetype/ftbdf.h> |
| #include <freetype/ttnameid.h> |
| |
| #include "pcf.h" |
| #include "pcfdrivr.h" |
| #include "pcfread.h" |
| |
| #include "pcferror.h" |
| #include "pcfutil.h" |
| |
| #undef FT_COMPONENT |
| #define FT_COMPONENT pcfread |
| |
| #include <freetype/internal/services/svbdf.h> |
| #include <freetype/internal/services/svfntfmt.h> |
| #include <freetype/internal/services/svprop.h> |
| #include <freetype/ftdriver.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 pcfdriver |
| |
| |
| /* |
| * This file uses X11 terminology for PCF data; an `encoding' in X11 speak |
| * is the same as a `character code' in FreeType speak. |
| */ |
| typedef struct PCF_CMapRec_ |
| { |
| FT_CMapRec root; |
| PCF_Enc enc; |
| |
| } 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->enc = &face->enc; |
| |
| return FT_Err_Ok; |
| } |
| |
| |
| FT_CALLBACK_DEF( void ) |
| pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */ |
| { |
| PCF_CMap cmap = (PCF_CMap)pcfcmap; |
| |
| |
| cmap->enc = NULL; |
| } |
| |
| |
| FT_CALLBACK_DEF( FT_UInt ) |
| pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */ |
| FT_UInt32 charcode ) |
| { |
| PCF_Enc enc = ( (PCF_CMap)pcfcmap )->enc; |
| |
| FT_UInt32 i = ( charcode >> 8 ) - enc->firstRow; |
| FT_UInt32 j = ( charcode & 0xFF ) - enc->firstCol; |
| FT_UInt32 h = enc->lastRow - enc->firstRow + 1; |
| FT_UInt32 w = enc->lastCol - enc->firstCol + 1; |
| |
| |
| /* wrapped around "negative" values are also rejected */ |
| if ( i >= h || j >= w ) |
| return 0; |
| |
| return (FT_UInt)enc->offset[i * w + j]; |
| } |
| |
| |
| FT_CALLBACK_DEF( FT_UInt ) |
| pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */ |
| FT_UInt32 *acharcode ) |
| { |
| PCF_Enc enc = ( (PCF_CMap)pcfcmap )->enc; |
| FT_UInt32 charcode = *acharcode + 1; |
| |
| FT_UInt32 i = ( charcode >> 8 ) - enc->firstRow; |
| FT_UInt32 j = ( charcode & 0xFF ) - enc->firstCol; |
| FT_UInt32 h = enc->lastRow - enc->firstRow + 1; |
| FT_UInt32 w = enc->lastCol - enc->firstCol + 1; |
| |
| FT_UInt result = 0; |
| |
| |
| /* adjust wrapped around "negative" values */ |
| if ( (FT_Int32)i < 0 ) |
| i = 0; |
| if ( (FT_Int32)j < 0 ) |
| j = 0; |
| |
| for ( ; i < h; i++, j = 0 ) |
| for ( ; j < w; j++ ) |
| { |
| result = (FT_UInt)enc->offset[i * w + j]; |
| if ( result != 0xFFFFU ) |
| goto Exit; |
| } |
| |
| Exit: |
| *acharcode = ( ( i + enc->firstRow ) << 8 ) | ( j + enc->firstCol ); |
| |
| 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->metrics ); |
| FT_FREE( face->enc.offset ); |
| |
| /* 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; |
| /* another name for ASCII */ |
| else if ( !ft_strcmp( s, "646.1991" ) && |
| !ft_strcmp( face->charset_encoding, "IRV" ) ) |
| 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 ); |
| } |
| } |
| |
| 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; |
| |
| 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_TRACE2(( "pcf_get_bdf_property:" |
| " too large integer 0x%lx is truncated\n", |
| prop->value.l )); |
| } |
| |
| /* |
| * 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_TRACE2(( "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_TRACE2(( "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 */ |