diff --git a/src/pcf/module.mk b/src/pcf/module.mk new file mode 100644 index 000000000..614c31920 --- /dev/null +++ b/src/pcf/module.mk @@ -0,0 +1,32 @@ +# +# FreeType 2 PCF module definition +# + +# Copyright 2000 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. + +make_module_list: add_pcf_driver + +add_pcf_driver: + $(OPEN_DRIVER)pcf_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)pcf $(ECHO_DRIVER_DESC)pcf bitmap fonts$(ECHO_DRIVER_DONE) + +# EOF diff --git a/src/pcf/pcf.c b/src/pcf/pcf.c new file mode 100644 index 000000000..e606b7cca --- /dev/null +++ b/src/pcf/pcf.c @@ -0,0 +1,36 @@ +/* pcf.c + + FreeType font driver for pcf fonts + + Copyright 2000 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. +*/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + + +#include +#include FT_SOURCE_FILE(pcf,pcfutil.c) +#include FT_SOURCE_FILE(pcf,pcfread.c) +#include FT_SOURCE_FILE(pcf,pcfdriver.c) + +/* END */ diff --git a/src/pcf/pcf.h b/src/pcf/pcf.h new file mode 100644 index 000000000..de45fec70 --- /dev/null +++ b/src/pcf/pcf.h @@ -0,0 +1,239 @@ +/* pcf.h + + FreeType font driver for pcf fonts + + Copyright (C) 2000 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. +*/ + + +#ifndef __PCF_H__ +#define __PCF_H__ + + +#include +#include FT_INTERNAL_DRIVER_H + + +FT_BEGIN_HEADER + + typedef struct PCF_TableRec_ + { + FT_ULong type; + FT_ULong format; + FT_ULong size; + FT_ULong offset; + + } PCF_TableRec, *PCF_Table; + + + typedef struct PCF_TocRec_ + { + FT_ULong version; + FT_ULong count; + PCF_Table tables; + + } PCF_TocRec, *PCF_Toc; + + + typedef struct PCF_ParseProperty_ + { + FT_Long name; + FT_Byte isString; + FT_Long value; + + } PCF_ParsePropertyRec, *PCF_ParseProperty; + + + typedef struct PCF_Property_ + { + FT_String* name; + FT_Byte isString; + + union + { + FT_String* atom; + FT_Long integer; + FT_ULong cardinal; + + } value; + + } PCF_PropertyRec, *PCF_Property; + + + typedef struct PCF_Compressed_Metric_ + { + FT_Byte leftSideBearing; + FT_Byte rightSideBearing; + FT_Byte characterWidth; + FT_Byte ascent; + FT_Byte descent; + + } PCF_Compressed_MetricRec, *PCF_Compressed_Metric; + + + typedef struct PCF_Metric_ + { + FT_Short leftSideBearing; + FT_Short rightSideBearing; + FT_Short characterWidth; + FT_Short ascent; + FT_Short descent; + FT_Short attributes; + FT_ULong bits; + + } PCF_MetricRec, *PCF_Metric; + + + typedef struct PCF_AccelRec_ + { + FT_Byte noOverlap; + FT_Byte constantMetrics; + FT_Byte terminalFont; + FT_Byte constantWidth; + FT_Byte inkInside; + FT_Byte inkMetrics; + FT_Byte drawDirection; + FT_Long fontAscent; + FT_Long fontDescent; + FT_Long maxOverlap; + PCF_MetricRec minbounds; + PCF_MetricRec maxbounds; + PCF_MetricRec ink_minbounds; + PCF_MetricRec ink_maxbounds; + + } PCF_AccelRec, *PCF_Accel; + + + typedef struct PCD_Encoding_ + { + FT_Long enc; + FT_Short glyph; + + } PCF_EncodingRec, *PCF_Encoding; + + + typedef struct PCF_FaceRec_ + { + FT_FaceRec root; + + char* charset_encoding; + char* charset_registry; + + PCF_TocRec toc; + PCF_AccelRec accel; + + int nprops; + PCF_Property properties; + + FT_Long nmetrics; + PCF_Metric metrics; + FT_Long nencodings; + PCF_Encoding encodings; + + FT_Short defaultChar; + + FT_ULong bitmapsFormat; + + FT_CharMap charmap_handle; + FT_CharMapRec charmap; /* a single charmap per face */ + + } PCF_FaceRec, *PCF_Face; + + + /* XXX hack */ + static + FT_Error PCF_Done_Face( PCF_Face face ); + + + /* macros for pcf font format */ + +#define LSBFirst 0 +#define MSBFirst 1 + +#define PCF_FILE_VERSION ( ( 'p' << 24 ) | \ + ( 'c' << 16 ) | \ + ( 'f' << 8 ) | 1 ) +#define PCF_FORMAT_MASK 0xFFFFFF00L + +#define PCF_DEFAULT_FORMAT 0x00000000L +#define PCF_INKBOUNDS 0x00000200L +#define PCF_ACCEL_W_INKBOUNDS 0x00000100L +#define PCF_COMPRESSED_METRICS 0x00000100L + +#define PCF_FORMAT_MATCH( a, b ) \ + ( ( (a) & PCF_FORMAT_MASK ) == ( (b) & PCF_FORMAT_MASK ) ) + +#define PCF_GLYPH_PAD_MASK ( 3 << 0 ) +#define PCF_BYTE_MASK ( 1 << 2 ) +#define PCF_BIT_MASK ( 1 << 3 ) +#define PCF_SCAN_UNIT_MASK ( 3 << 4 ) + +#define PCF_BYTE_ORDER( f ) \ + ( ( (f) & PCF_BYTE_MASK ) ? MSBFirst : LSBFirst ) +#define PCF_BIT_ORDER( f ) \ + ( ( (f) & PCF_BIT_MASK ) ? MSBFirst : LSBFirst ) +#define PCF_GLYPH_PAD_INDEX( f ) \ + ( (f) & PCF_GLYPH_PAD_MASK ) +#define PCF_GLYPH_PAD( f ) \ + ( 1 << PCF_GLYPH_PAD_INDEX( f ) ) +#define PCF_SCAN_UNIT_INDEX( f ) \ + ( ( (f) & PCF_SCAN_UNIT_MASK ) >> 4 ) +#define PCF_SCAN_UNIT( f ) \ + ( 1 << PCF_SCAN_UNIT_INDEX( f ) ) +#define PCF_FORMAT_BITS( f ) \ + ( (f) & ( PCF_GLYPH_PAD_MASK | \ + PCF_BYTE_MASK | \ + PCF_BIT_MASK | \ + PCF_SCAN_UNIT_MASK ) ) + +#define PCF_SIZE_TO_INDEX( s ) ( (s) == 4 ? 2 : (s) == 2 ? 1 : 0 ) +#define PCF_INDEX_TO_SIZE( b ) ( 1 << b ) + +#define PCF_FORMAT( bit, byte, glyph, scan ) \ + ( ( PCF_SIZE_TO_INDEX( scan ) << 4 ) | \ + ( ( (bit) == MSBFirst ? 1 : 0 ) << 3 ) | \ + ( ( (byte) == MSBFirst ? 1 : 0 ) << 2 ) | \ + ( PCF_SIZE_TO_INDEX( glyph ) << 0 ) ) + +#define PCF_PROPERTIES ( 1 << 0 ) +#define PCF_ACCELERATORS ( 1 << 1 ) +#define PCF_METRICS ( 1 << 2 ) +#define PCF_BITMAPS ( 1 << 3 ) +#define PCF_INK_METRICS ( 1 << 4 ) +#define PCF_BDF_ENCODINGS ( 1 << 5 ) +#define PCF_SWIDTHS ( 1 << 6 ) +#define PCF_GLYPH_NAMES ( 1 << 7 ) +#define PCF_BDF_ACCELERATORS ( 1 << 8 ) + +#define GLYPHPADOPTIONS 4 /* I'm not sure about this */ + + static + FT_Error pcf_load_font( FT_Stream, + PCF_Face ); + + +FT_END_HEADER + +#endif /* __PCF_H__ */ + + +/* END */ diff --git a/src/pcf/pcfdriver.c b/src/pcf/pcfdriver.c new file mode 100644 index 000000000..248b89db2 --- /dev/null +++ b/src/pcf/pcfdriver.c @@ -0,0 +1,343 @@ +/* pcfdriver.c + + FreeType font driver for pcf files + + Copyright (C) 2000 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_ERRORS_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H + +#include FT_SOURCE_FILE(pcf,pcf.h) +#include FT_SOURCE_FILE(pcf,pcfdriver.h) +#include FT_SOURCE_FILE(pcf,pcfutil.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 + + + static + FT_Error PCF_Done_Face( PCF_Face face ) + { + FT_Memory memory = FT_FACE_MEMORY( face ); + PCF_Property tmp = face->properties; + int i; + + + FREE( face->encodings ); + FREE( face->metrics ); + + for ( i = 0; i < face->nprops; i++ ) + { + FREE( tmp->name ); + if ( tmp->isString ) + FREE( tmp->value ); + } + FREE( face->properties ); + + FT_TRACE4(( "DONE_FACE!!!\n" )); + + return FT_Err_Ok; + } + + + static + FT_Error PCF_Init_Face( FT_Stream stream, + PCF_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error = FT_Err_Ok; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + + + error = pcf_load_font( stream, face ); + if ( error ) + goto Fail; + + return FT_Err_Ok; + + Fail: + FT_TRACE2(( "[not a valid PCF file]\n" )); + PCF_Done_Face( face ); + + return FT_Err_Unknown_File_Format; /* error */ + } + + + static + FT_Error PCF_Set_Pixel_Size( FT_Size size ) + { + PCF_Face face = (PCF_Face)FT_SIZE_FACE( size ); + + + FT_TRACE4(( "rec %d - pres %d\n", size->metrics.y_ppem, + face->root.available_sizes->height )); + + if ( size->metrics.y_ppem == face->root.available_sizes->height ) + { + size->metrics.ascender = face->accel.fontAscent << 6; + size->metrics.descender = face->accel.fontDescent * (-64); +#if 0 + size->metrics.height = face->accel.maxbounds.ascent << 6; +#endif + size->metrics.height = size->metrics.ascender - + size->metrics.descender; + + return FT_Err_Ok; + } + else + { + FT_TRACE4(( "size WRONG\n" )); + return FT_Err_Invalid_Pixel_Size; + } + } + + + static + FT_Error PCF_Load_Glyph( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int load_flags ) + { + PCF_Face face = (PCF_Face)FT_SIZE_FACE( size ); + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_FACE(face)->memory; + FT_Bitmap* bitmap = &slot->bitmap; + PCF_Metric metric; + int bytes; + + FT_Stream stream = face->root.stream; + + FT_UNUSED( load_flags ); + + + FT_TRACE4(( "load_glyph %d ---", glyph_index )); + + if ( !face ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + metric = face->metrics + glyph_index; + + bitmap->rows = metric->ascent + metric->descent; + bitmap->width = metric->characterWidth; + bitmap->num_grays = 1; + bitmap->pixel_mode = ft_pixel_mode_mono; + + FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n", + PCF_BIT_ORDER( face->bitmapsFormat ), + PCF_BYTE_ORDER( face->bitmapsFormat ), + PCF_GLYPH_PAD( face->bitmapsFormat ) )); + + switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) ) + { + case 1: + bitmap->pitch = ( bitmap->width + 7 ) >> 3; + break; + + case 2: + bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1; + break; + + case 4: + bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2; + break; + + case 8: + bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3; + break; + + default: + return FT_Err_Invalid_File_Format; + } + + /* XXX: to do: are there cases that need repadding the bitmap? */ + bytes = bitmap->pitch * bitmap->rows; + + if ( ALLOC( bitmap->buffer, bytes ) ) + goto Exit; + + if ( FILE_Seek( metric->bits ) || + FILE_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; + } + } + + slot->bitmap_left = 0; + slot->bitmap_top = metric->ascent; + + slot->metrics.horiAdvance = metric->characterWidth << 6 ; + slot->metrics.horiBearingX = metric->rightSideBearing << 6 ; + slot->metrics.horiBearingY = metric->ascent << 6 ; + slot->metrics.width = metric->characterWidth << 6 ; + slot->metrics.height = bitmap->rows << 6; + + slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16; + slot->format = ft_glyph_format_bitmap; + slot->flags = ft_glyph_own_bitmap; + + FT_TRACE4(( " --- ok\n" )); + + Exit: + return error; + } + + + static + FT_UInt PCF_Get_Char_Index( FT_CharMap charmap, + FT_Long char_code ) + { + PCF_Face face = (PCF_Face)charmap->face; + PCF_Encoding en_table = face->encodings; + int low, high, mid; + + + FT_TRACE4(( "get_char_index %ld\n", char_code )); + + low = 0; + high = face->nencodings - 1; + while ( low <= high ) + { + mid = ( low + high ) / 2; + if ( char_code < en_table[mid].enc ) + high = mid - 1; + else if ( char_code > en_table[mid].enc ) + low = mid + 1; + else + return en_table[mid].glyph; + } + + return face->defaultChar; + } + + + FT_CALLBACK_TABLE_DEF + const FT_Driver_Class pcf_driver_class = + { + { + ft_module_font_driver, + sizeof ( FT_DriverRec ), + + "pcf", + 0x10000L, + 0x20000L, + + 0, + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + sizeof( PCF_FaceRec ), + sizeof( FT_SizeRec ), + sizeof( FT_GlyphSlotRec ), + + (FTDriver_initFace) PCF_Init_Face, + (FTDriver_doneFace) PCF_Done_Face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) PCF_Set_Pixel_Size, + (FTDriver_setPixelSizes)PCF_Set_Pixel_Size, + + (FTDriver_loadGlyph) PCF_Load_Glyph, + (FTDriver_getCharIndex) PCF_Get_Char_Index, + + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverClass */ + /* */ + /* */ + /* This function is used when compiling the TrueType driver as a */ + /* shared library (`.DLL' or `.so'). It will be used by the */ + /* high-level library of FreeType to retrieve the address of the */ + /* driver's generic interface. */ + /* */ + /* It shouldn't be implemented in a static build, as each driver must */ + /* have the same function as an exported entry point. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + FT_EXPORT_DEF( const FT_Driver_Class* ) getDriverClass( void ) + { + return &pcf_driver_class; + } + + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/src/pcf/pcfdriver.h b/src/pcf/pcfdriver.h new file mode 100644 index 000000000..676a9c467 --- /dev/null +++ b/src/pcf/pcfdriver.h @@ -0,0 +1,44 @@ +/* pcfdriver.h + + FreeType font driver for pcf fonts + + Copyright 2000 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. +*/ + + +#ifndef __PCFDRIVER_H__ +#define __PCFDRIVER_H__ + +#include +#include FT_INTERNAL_DRIVER_H + +FT_BEGIN_HEADER + + FT_EXPORT_VAR( const FT_Driver_Class ) pcf_driver_class; + +FT_END_HEADER + + +#endif /* __PCFDRIVER_H__ */ + + +/* END */ diff --git a/src/pcf/pcfread.c b/src/pcf/pcfread.c new file mode 100644 index 000000000..c6b497007 --- /dev/null +++ b/src/pcf/pcfread.c @@ -0,0 +1,1051 @@ +/* pcfread.c + + FreeType font driver for pcf fonts + + Copyright 2000 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_ERRORS_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H + +#include FT_SOURCE_FILE(pcf,pcf.h) +#include FT_SOURCE_FILE(pcf,pcfdriver.h) + +#include /* strlen(), strcpy() */ + + /*************************************************************************/ + /* */ + /* 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_pcfread + + +#if defined( FT_DEBUG_LEVEL_TRACE ) + static char* tableNames[] = + { + "prop", "accl", "mtrcs", "bmps", "imtrcs", + "enc", "swidth", "names", "accel" + }; +#endif + + + static + const FT_Frame_Field pcf_toc_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_TocRec + + FT_FRAME_START( 8 ), + FT_FRAME_ULONG_LE( version ), + FT_FRAME_ULONG_LE( count ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_table_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_TableRec + + FT_FRAME_START( 16 ), + FT_FRAME_ULONG_LE( type ), + FT_FRAME_ULONG_LE( format ), + FT_FRAME_ULONG_LE( size ), + FT_FRAME_ULONG_LE( offset ), + FT_FRAME_END + }; + + + static + FT_Error pcf_read_TOC( FT_Stream stream, + PCF_Face face ) + { + FT_Error error; + PCF_Toc toc = &face->toc; + PCF_Table tables; + + FT_Memory memory = FT_FACE(face)->memory; + unsigned int i; + + + if ( FILE_Seek ( 0 ) || + READ_Fields ( pcf_toc_header, toc ) ) + return FT_Err_Cannot_Open_Resource; + + if ( toc->version != PCF_FILE_VERSION ) + return FT_Err_Invalid_File_Format; + + if ( ALLOC( face->toc.tables, toc->count * sizeof ( PCF_TableRec ) ) ) + return FT_Err_Out_Of_Memory; + + tables = face->toc.tables; + for ( i = 0; i < toc->count; i++ ) + { + if ( READ_Fields( pcf_table_header, tables ) ) + goto Exit; + tables++; + } + +#if defined( FT_DEBUG_LEVEL_TRACE ) + + { + int i,j; + char* name; + + + FT_TRACE4(( "Tables count: %ld\n", face->toc.count )); + tables = face->toc.tables; + for ( i = 0; i < toc->count; i++ ) + { + for( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ ) + if ( tables[i].type == ( 1 << j ) ) + name=tableNames[j]; + FT_TRACE4(( "Table %d: type=%-6s format=0x%04lX " + "size=0x%06lX (%8ld) offset=0x%04lX\n", + i, name, + tables[i].format, + tables[i].size, tables[i].size, + tables[i].offset )); + } + } + +#endif + + return FT_Err_Ok; + + Exit: + FREE( face->toc.tables ); + return error; + } + + + static + const FT_Frame_Field pcf_metric_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_MetricRec + + FT_FRAME_START( 12 ), + FT_FRAME_SHORT_LE( leftSideBearing ), + FT_FRAME_SHORT_LE( rightSideBearing ), + FT_FRAME_SHORT_LE( characterWidth ), + FT_FRAME_SHORT_LE( ascent ), + FT_FRAME_SHORT_LE( descent ), + FT_FRAME_SHORT_LE( attributes ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_metric_msb_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_MetricRec + + FT_FRAME_START( 12 ), + FT_FRAME_SHORT( leftSideBearing ), + FT_FRAME_SHORT( rightSideBearing ), + FT_FRAME_SHORT( characterWidth ), + FT_FRAME_SHORT( ascent ), + FT_FRAME_SHORT( descent ), + FT_FRAME_SHORT( attributes ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_compressed_metric_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_Compressed_MetricRec + + FT_FRAME_START( 5 ), + FT_FRAME_BYTE( leftSideBearing ), + FT_FRAME_BYTE( rightSideBearing ), + FT_FRAME_BYTE( characterWidth ), + FT_FRAME_BYTE( ascent ), + FT_FRAME_BYTE( descent ), + FT_FRAME_END + }; + + + static + FT_Error pcf_parse_metric( FT_Stream stream, + const FT_Frame_Field* header, + PCF_Metric metric ) + { + FT_Error error = FT_Err_Ok; + + + (void)READ_Fields( header, metric ); + + return error; + } + + + static + FT_Error pcf_parse_compressed_metric( FT_Stream stream, + PCF_Metric metric ) + { + PCF_Compressed_MetricRec compr_metric; + FT_Error error = FT_Err_Ok; + + + (void)READ_Fields( pcf_compressed_metric_header, &compr_metric ); + + metric->leftSideBearing = (FT_Short)compr_metric.leftSideBearing - 0x80; + metric->rightSideBearing = (FT_Short)compr_metric.rightSideBearing - 0x80; + metric->characterWidth = (FT_Short)compr_metric.characterWidth - 0x80; + metric->ascent = (FT_Short)compr_metric.ascent - 0x80; + metric->descent = (FT_Short)compr_metric.descent - 0x80; + metric->attributes = 0; + + return error; + } + + + static + FT_Error pcf_get_metric( FT_Stream stream, + FT_ULong format, + PCF_Metric metric ) + { + FT_Error error = FT_Err_Ok; + + + if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + error = pcf_parse_metric( stream, pcf_metric_msb_header, metric ); + else + error = pcf_parse_metric( stream, pcf_metric_header, metric ); + } + else + error = pcf_parse_compressed_metric( stream, metric ); + + return error; + } + + + static + FT_Error pcfSeekToType( FT_Stream stream, + PCF_Table tables, + int ntables, + FT_ULong type, + FT_ULong* formatp, + FT_ULong* sizep ) + { + FT_Error error; + int i; + + + for ( i = 0; i < ntables; i++ ) + if ( tables[i].type == type ) + { + if ( stream->pos > tables[i].offset ) + return FT_Err_Invalid_Stream_Skip; + if ( FILE_Skip( tables[i].offset - stream->pos ) ) + return FT_Err_Invalid_Stream_Skip; + *sizep = tables[i].size; /* unused - to be removed */ + *formatp = tables[i].format; + return FT_Err_Ok; + } + + return FT_Err_Invalid_File_Format; + } + + + static + FT_Bool pcfHasType( PCF_Table tables, + int ntables, + FT_ULong type ) + { + int i; + + + for ( i = 0; i < ntables; i++ ) + if ( tables[i].type == type ) + return TRUE; + + return FALSE; + } + + + static + const FT_Frame_Field pcf_property_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_ParsePropertyRec + + FT_FRAME_START( 9 ), + FT_FRAME_LONG_LE( name ), + FT_FRAME_BYTE ( isString ), + FT_FRAME_LONG_LE( value ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_property_msb_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_ParsePropertyRec + + FT_FRAME_START( 9 ), + FT_FRAME_LONG( name ), + FT_FRAME_BYTE( isString ), + FT_FRAME_LONG( value ), + FT_FRAME_END + }; + + + static + PCF_Property find_property( PCF_Face face, + const FT_String* prop ) + { + PCF_Property properties = face->properties; + FT_Bool found = 0; + int i; + + + for ( i = 0 ; i < face->nprops && !found; i++ ) + { + if ( !strcmp( properties[i].name, prop ) ) + found = 1; + } + + if ( found ) + return properties + i - 1; + else + return NULL; + } + + + static + FT_Error pcf_get_properties( FT_Stream stream, + PCF_Face face ) + { + PCF_ParseProperty props = 0; + PCF_Property properties = 0; + int nprops, i; + FT_ULong format, size; + FT_Error error; + FT_Memory memory = FT_FACE(face)->memory; + FT_ULong string_size; + FT_String* strings = 0; + + + error = pcfSeekToType( stream, + face->toc.tables, + face->toc.count, + PCF_PROPERTIES, + &format, + &size ); + if ( error ) + goto Bail; + + if ( READ_ULongLE( format ) ) + goto Bail; + + FT_TRACE4(( "get_prop: format = %ld\n", format )); + + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + goto Bail; + + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)READ_ULong( nprops ); + else + (void)READ_ULongLE( nprops ); + if ( error ) + goto Bail; + + FT_TRACE4(( "get_prop: nprop = %d\n", nprops )); + + if ( ALLOC( props, nprops * sizeof ( PCF_ParsePropertyRec ) ) ) + goto Bail; + + for ( i = 0; i < nprops; i++ ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)READ_Fields( pcf_property_msb_header, props + i ); + else + (void)READ_Fields( pcf_property_header, props + i ); + if ( error ) + goto Bail; + } + + /* pad the property array */ + /* */ + /* clever here - nprops is the same as the number of odd-units read, */ + /* as only isStringProp are odd length (Keith Packard) */ + /* */ + if ( nprops & 3 ) + { + i = 4 - ( nprops & 3 ); + FT_Skip_Stream( stream, i ); + } + + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)READ_ULong( string_size ); + else + (void)READ_ULongLE( string_size ); + if ( error ) + goto Bail; + + FT_TRACE4(( "get_prop: string_size = %ld\n", string_size )); + + if ( ALLOC( strings, string_size * sizeof ( char ) ) ) + goto Bail; + + error = FT_Read_Stream( stream, (FT_Byte*)strings, string_size ); + if ( error ) + goto Bail; + + if ( ALLOC( properties, nprops * sizeof ( PCF_PropertyRec ) ) ) + goto Bail; + + for ( i = 0; i < nprops; i++ ) + { + /* XXX: make atom */ + error = ALLOC( properties[i].name, + ( strlen( strings + props[i].name ) + 1 ) * + sizeof ( char ) ); + if ( error ) + goto Bail; + strcpy( properties[i].name,strings + props[i].name ); + + properties[i].isString = props[i].isString; + + if ( props[i].isString ) + { + error = ALLOC( properties[i].value.atom, + ( strlen( strings + props[i].value ) + 1 ) * + sizeof ( char ) ); + if ( error ) + goto Bail; + strcpy( properties[i].value.atom, strings + props[i].value ); + } + else + properties[i].value.integer = props[i].value; + } + + face->properties = properties; + face->nprops = nprops; + + FREE( props ); + FREE( strings ); + + return FT_Err_Ok; + + Bail: + FREE( props ); + FREE( strings ); + + return error; + } + + + static + FT_Error pcf_get_metrics( FT_Stream stream, + PCF_Face face ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_FACE(face)->memory; + FT_ULong format = 0; + FT_ULong size = 0; + PCF_Metric metrics = 0; + int i; + int nmetrics = -1; + + + error = pcfSeekToType( stream, + face->toc.tables, + face->toc.count, + PCF_METRICS, + &format, + &size ); + if ( error ) + return error; + + error = READ_ULongLE( format ); + + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && + !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ) + return FT_Err_Invalid_File_Format; + + if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)READ_ULong( nmetrics ); + else + (void)READ_ULongLE( nmetrics ); + } + else + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)READ_UShort( nmetrics ); + else + (void)READ_UShortLE( nmetrics ); + } + if ( error || nmetrics == -1 ) + return FT_Err_Invalid_File_Format; + + face->nmetrics = nmetrics; + + error = ALLOC( face->metrics, nmetrics * sizeof ( PCF_MetricRec ) ); + if ( error ) + return FT_Err_Out_Of_Memory; + + metrics = face->metrics; + for ( i = 0; i < nmetrics; i++ ) + { + pcf_get_metric( stream, format, metrics + i ); + + metrics[i].bits = 0; + + FT_TRACE4(( "%d : width=%d, " + "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n", + i, + ( metrics + i )->characterWidth, + ( metrics + i )->leftSideBearing, + ( metrics + i )->rightSideBearing, + ( metrics + i )->ascent, + ( metrics + i )->descent, + ( metrics + i )->attributes )); + + if ( error ) + break; + } + + if ( error ) + FREE( face->metrics ); + return error; + } + + + static + FT_Error pcf_get_bitmaps( FT_Stream stream, + PCF_Face face ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_FACE(face)->memory; + FT_Long* offsets; + FT_Long bitmapSizes[GLYPHPADOPTIONS]; + FT_ULong format, size; + int nbitmaps, i, sizebitmaps; + char* bitmaps; + + + error = pcfSeekToType( stream, + face->toc.tables, + face->toc.count, + PCF_BITMAPS, + &format, + &size ); + if ( error ) + return error; + + error = FT_Access_Frame( stream, 8 ); + if ( error ) + return error; + format = GET_ULongLE(); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + return FT_Err_Invalid_File_Format; + + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + nbitmaps = GET_ULong(); + else + nbitmaps = GET_ULongLE(); + FT_Forget_Frame( stream ); + if ( nbitmaps != face->nmetrics ) + return FT_Err_Invalid_File_Format; + + error = ALLOC( offsets, nbitmaps * sizeof ( FT_ULong ) ); + if ( error ) + return error; + + if ( error ) + goto Bail; + for ( i = 0; i < nbitmaps; i++ ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)READ_Long( offsets[i] ); + else + (void)READ_LongLE( offsets[i] ); + + FT_TRACE4(( "bitmap %d is at offset %ld\n", i, offsets[i] )); + } + if ( error ) + goto Bail; + + if ( error ) + goto Bail; + for ( i = 0; i < GLYPHPADOPTIONS; i++ ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)READ_Long( bitmapSizes[i] ); + else + (void)READ_LongLE( bitmapSizes[i] ); + if ( error ) + goto Bail; + + sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )]; + + FT_TRACE4(( "padding %d implies a size of %ld\n", i, bitmapSizes[i] )); + } + + FT_TRACE4(( " %d bitmaps, padding index %ld\n", + nbitmaps, + PCF_GLYPH_PAD_INDEX( format ) )); + FT_TRACE4(( "bitmap size = %d\n", sizebitmaps )); + + for ( i = 0; i < nbitmaps; i++ ) + face->metrics[i].bits = stream->pos + offsets[i]; + + face->bitmapsFormat = format; + + FREE ( offsets ); + return error; + + Bail: + FREE ( offsets ); + FREE ( bitmaps ); + return error; + } + + + static + FT_Error pcf_get_encodings( FT_Stream stream, + PCF_Face face ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_FACE(face)->memory; + FT_ULong format, size; + int firstCol, lastCol; + int firstRow, lastRow; + int nencoding, encodingOffset; + int i, j; + PCF_Encoding tmpEncoding, encoding = 0; + + + error = pcfSeekToType( stream, + face->toc.tables, + face->toc.count, + PCF_BDF_ENCODINGS, + &format, + &size ); + if ( error ) + return error; + + error = FT_Access_Frame( stream, 14 ); + if ( error ) + return error; + format = GET_ULongLE(); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + return FT_Err_Invalid_File_Format; + + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + { + firstCol = GET_Short(); + lastCol = GET_Short(); + firstRow = GET_Short(); + lastRow = GET_Short(); + face->defaultChar = GET_Short(); + } + else + { + firstCol = GET_ShortLE(); + lastCol = GET_ShortLE(); + firstRow = GET_ShortLE(); + lastRow = GET_ShortLE(); + face->defaultChar = GET_ShortLE(); + } + + FT_Forget_Frame( stream ); + + FT_TRACE4(( "enc: firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", + firstCol, lastCol, firstRow, lastRow )); + + nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 ); + + if ( ALLOC( tmpEncoding, nencoding * sizeof ( PCF_EncodingRec ) ) ) + return FT_Err_Out_Of_Memory; + + error = FT_Access_Frame( stream, 2 * nencoding ); + if ( error ) + goto Bail; + + for ( i = 0, j = 0 ; i < nencoding; i++ ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + encodingOffset = GET_Short(); + else + encodingOffset = GET_ShortLE(); + + if ( encodingOffset != 0xFFFF ) + { + tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) + + firstRow ) * 256 ) + + ( ( i % ( lastCol - firstCol + 1 ) ) + + firstCol ); + + tmpEncoding[j].glyph = encodingOffset; + j++; + } + + FT_TRACE4(( "enc n. %d ; Uni %ld ; Glyph %d\n", + i, tmpEncoding[j - 1].enc, encodingOffset )); + } + FT_Forget_Frame( stream ); + + if ( ALLOC( encoding, (--j) * sizeof ( PCF_EncodingRec ) ) ) + goto Bail; + + for ( i = 0; i < j; i++ ) + { + encoding[i].enc = tmpEncoding[i].enc; + encoding[i].glyph = tmpEncoding[i].glyph; + } + + face->nencodings = j; + face->encodings = encoding; + FREE( tmpEncoding ); + + return error; + + Bail: + FREE( encoding ); + FREE( tmpEncoding ); + return error; + } + + + static + const FT_Frame_Field pcf_accel_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_AccelRec + + FT_FRAME_START( 20 ), + FT_FRAME_BYTE ( noOverlap ), + FT_FRAME_BYTE ( constantMetrics ), + FT_FRAME_BYTE ( terminalFont ), + FT_FRAME_BYTE ( constantWidth ), + FT_FRAME_BYTE ( inkInside ), + FT_FRAME_BYTE ( inkMetrics ), + FT_FRAME_BYTE ( drawDirection ), + FT_FRAME_SKIP_BYTES( 1 ), + FT_FRAME_LONG_LE ( fontAscent ), + FT_FRAME_LONG_LE ( fontDescent ), + FT_FRAME_LONG_LE ( maxOverlap ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_accel_msb_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_AccelRec + + FT_FRAME_START( 20 ), + FT_FRAME_BYTE ( noOverlap ), + FT_FRAME_BYTE ( constantMetrics ), + FT_FRAME_BYTE ( terminalFont ), + FT_FRAME_BYTE ( constantWidth ), + FT_FRAME_BYTE ( inkInside ), + FT_FRAME_BYTE ( inkMetrics ), + FT_FRAME_BYTE ( drawDirection ), + FT_FRAME_SKIP_BYTES( 1 ), + FT_FRAME_LONG ( fontAscent ), + FT_FRAME_LONG ( fontDescent ), + FT_FRAME_LONG ( maxOverlap ), + FT_FRAME_END + }; + + + static + FT_Error pcf_get_accel( FT_Stream stream, + PCF_Face face, + FT_ULong type ) + { + FT_ULong format, size; + FT_Error error = FT_Err_Ok; + PCF_Accel accel = &face->accel; + + + error = pcfSeekToType( stream, + face->toc.tables, + face->toc.count, + type, + &format, + &size ); + if ( error ) + goto Bail; + + error = READ_ULongLE( format ); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && + !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) + goto Bail; + + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)READ_Fields( pcf_accel_msb_header , accel ); + else + (void)READ_Fields( pcf_accel_header, accel ); + if ( error ) + goto Bail; + + error = pcf_get_metric( stream, format, &(accel->minbounds) ); + if ( error ) + goto Bail; + error = pcf_get_metric( stream, format, &(accel->maxbounds) ); + if ( error ) + goto Bail; + + if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) + { + error = pcf_get_metric( stream, format, &(accel->ink_minbounds) ); + if ( error ) + goto Bail; + error = pcf_get_metric( stream, format, &(accel->ink_maxbounds) ); + if ( error ) + goto Bail; + } + else + { + accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */ + accel->ink_maxbounds = accel->maxbounds; + } + return error; + + Bail: + return error; + } + + + FT_Error pcf_load_font( FT_Stream stream, + PCF_Face face ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_FACE(face)->memory; + FT_Bool hasBDFAccelerators; + + + error = pcf_read_TOC( stream, face ); + if ( error ) + return error; + + error = pcf_get_properties( stream, face ); + if ( error ) + return error;; + + /* Use the old accelerators if no BDF accelerators are in the file. */ + hasBDFAccelerators = pcfHasType( face->toc.tables, + face->toc.count, + PCF_BDF_ACCELERATORS ); + if ( !hasBDFAccelerators ) + { + error = pcf_get_accel( stream, face, PCF_ACCELERATORS ); + if ( error ) + goto Bail; + } + + /* metrics */ + error = pcf_get_metrics( stream, face ); + if ( error ) + goto Bail; + + /* bitmaps */ + error = pcf_get_bitmaps( stream, face ); + if ( error ) + goto Bail; + + /* encodings */ + error = pcf_get_encodings( stream, face ); + if ( error ) + goto Bail; + + /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ + if ( hasBDFAccelerators ) + { + error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS ); + if ( error ) + goto Bail; + } + + /* XXX: TO DO: inkmetrics and glyph_names are missing */ + + /* now construct the face object */ + { + FT_Face root = FT_FACE( face ); + PCF_Property prop; + + + root->num_faces = 1; + root->face_index = 0; + root->face_flags = FT_FACE_FLAG_FIXED_SIZES | + FT_FACE_FLAG_HORIZONTAL | + FT_FACE_FLAG_FAST_GLYPHS; + + if ( face->accel.constantWidth ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + root->style_flags = 0; + prop = find_property( face, "SLANT" ); + if ( prop != NULL ) + if ( prop->isString ) + if ( ( *(prop->value.atom) == 'O' ) || + ( *(prop->value.atom) == 'I' ) ) + root->style_flags |= FT_STYLE_FLAG_ITALIC; + + prop = find_property( face, "WEIGHT_NAME" ); + if ( prop != NULL ) + if ( prop->isString ) + if ( *(prop->value.atom) == 'B' ) + root->style_flags |= FT_STYLE_FLAG_BOLD; + + root->style_name = (char *)"Regular"; + + if ( root->style_flags & FT_STYLE_FLAG_BOLD ) { + if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = (char *)"Bold Italic"; + else + root->style_name = (char *)"Bold"; + } + else if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = (char *)"Italic"; + + prop = find_property( face, "FAMILY_NAME" ); + if ( prop != NULL ) + { + if ( prop->isString ) + { + int l = strlen( prop->value.atom ) + 1; + + + if ( ALLOC( root->family_name, l * sizeof ( char ) ) ) + goto Bail; + strcpy( root->family_name, prop->value.atom ); + } + } + else + root->family_name = 0; + + root->num_glyphs = face->nmetrics; + + root->num_fixed_sizes = 1; + if ( ALLOC_ARRAY( root->available_sizes, 1, FT_Bitmap_Size ) ) + goto Bail; + + prop = find_property( face, "PIXEL_SIZE" ); + if ( prop != NULL ) + { + PCF_Property xres = 0, yres = 0; + + + xres = find_property( face, "RESOLUTION_X" ); + yres = find_property( face, "RESOLUTION_Y" ); + if ( ( xres != NULL ) && ( yres != NULL ) ) + { + root->available_sizes->width = + prop->value.integer * 75 / xres->value.integer; + root->available_sizes->height = + prop->value.integer * 75 / yres->value.integer; + } + } + else + { /* XXX */ +#if 0 + printf( "PCF Warning: Pixel Size undefined, assuming 12\n"); +#endif + root->available_sizes->width = 12; + root->available_sizes->height = 12; + } + + /* XXX: charmaps */ + root->charmaps = &face->charmap_handle; + root->num_charmaps = 1; + + { + PCF_Property charset_registry = 0, charset_encoding = 0; + + + charset_registry = find_property( face, "CHARSET_REGISTRY" ); + charset_encoding = find_property( face, "CHARSET_ENCODING" ); + + if ( ( charset_registry != NULL ) && + ( charset_encoding != NULL ) ) + { + if ( ( charset_registry->isString ) && + ( charset_encoding->isString ) ) + { + if ( ALLOC( face->charset_encoding, + ( strlen( charset_encoding->value.atom ) + 1 ) * + sizeof ( char ) ) ) + goto Bail; + if ( ALLOC( face->charset_registry, + ( strlen( charset_registry->value.atom ) + 1 ) * + sizeof ( char ) ) ) + goto Bail; + strcpy( face->charset_registry, charset_registry->value.atom ); + strcpy( face->charset_encoding, charset_encoding->value.atom ); + +#if 0 + if ( !strcmp( charset_registry, "ISO10646" ) ) + { + face->charmap.encoding = ft_encoding_unicode; + face->charmap.platform_id = 3; + face->charmap.encoding_id = 1; + face->charmap.face = root; + face->charmap_handle + + return FT_Err_Ok; + } +#endif + } + } + } + + face->charmap.encoding = ft_encoding_none; + face->charmap.platform_id = 0; + face->charmap.encoding_id = 0; + face->charmap.face = root; + face->charmap_handle = &face->charmap; + root->charmap = face->charmap_handle; + } + return FT_Err_Ok; + + Bail: + PCF_Done_Face( face ); + return FT_Err_Invalid_File_Format; + } + + +/* END */ diff --git a/src/pcf/pcfutil.c b/src/pcf/pcfutil.c new file mode 100644 index 000000000..4bcc5aad1 --- /dev/null +++ b/src/pcf/pcfutil.c @@ -0,0 +1,211 @@ +/* + +Copyright 1990, 1994, 1998 The Open Group + +All Rights Reserved. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* $XFree86: xc/lib/font/util/utilbitmap.c,v 1.3 1999/08/22 08:58:58 dawes Exp $ */ + +/* + * Author: Keith Packard, MIT X Consortium + */ + + +#include +#include FT_SOURCE_FILE(pcf,pcfutil.h) + + + /* Utility functions for reformatting font bitmaps */ + + static unsigned char _reverse_byte[0x100] = + { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff + }; + + /* + * Invert bit order within each BYTE of an array. + */ + + void BitOrderInvert( unsigned char* buf, + int nbytes ) + { + unsigned char* rev = _reverse_byte; + + + for ( ; --nbytes >= 0; buf++ ) + *buf = rev[*buf]; + } + + + /* + * Invert byte order within each 16-bits of an array. + */ + + void TwoByteSwap( unsigned char* buf, + int nbytes ) + { + unsigned char c; + + + for ( ; nbytes > 0; nbytes -= 2, buf += 2 ) + { + c = buf[0]; + buf[0] = buf[1]; + buf[1] = c; + } + } + + /* + * Invert byte order within each 32-bits of an array. + */ + + void FourByteSwap( unsigned char* buf, + int nbytes ) + { + unsigned char c; + + + for ( ; nbytes > 0; nbytes -= 4, buf += 4 ) + { + c = buf[0]; + buf[0] = buf[3]; + buf[3] = c; + + c = buf[1]; + buf[1] = buf[2]; + buf[2] = c; + } + } + + + /* + * Repad a bitmap. + */ + + int RepadBitmap( char* pSrc, + char* pDst, + unsigned int srcPad, + unsigned int dstPad, + int width, + int height ) + { + int srcWidthBytes, dstWidthBytes; + int row, col; + char *pTmpSrc, *pTmpDst; + + + switch ( srcPad ) + { + case 1: + srcWidthBytes = ( width + 7 ) >> 3; + break; + + case 2: + srcWidthBytes = ( ( width + 15 ) >> 4 ) << 1; + break; + + case 4: + srcWidthBytes = ( ( width + 31 ) >> 5 ) << 2; + break; + + case 8: + srcWidthBytes = ( ( width + 63 ) >> 6 ) << 3; + break; + + default: + return 0; + } + + switch ( dstPad ) + { + case 1: + dstWidthBytes = ( width + 7 ) >> 3; + break; + + case 2: + dstWidthBytes = ( ( width + 15 ) >> 4 ) << 1; + break; + + case 4: + dstWidthBytes = ( ( width + 31 ) >> 5 ) << 2; + break; + + case 8: + dstWidthBytes = ( ( width + 63 ) >> 6 ) << 3; + break; + + default: + return 0; + } + + width = srcWidthBytes; + if ( width > dstWidthBytes ) + width = dstWidthBytes; + + pTmpSrc= pSrc; + pTmpDst= pDst; + + for ( row = 0; row < height; row++ ) + { + for ( col = 0; col < width; col++ ) + *pTmpDst++ = *pTmpSrc++; + + while ( col < dstWidthBytes ) + { + *pTmpDst++ = '\0'; + col++; + } + pTmpSrc += srcWidthBytes - width; + } + + return dstWidthBytes * height; + } + + +/* END */ diff --git a/src/pcf/pcfutil.h b/src/pcf/pcfutil.h new file mode 100644 index 000000000..3ec33968a --- /dev/null +++ b/src/pcf/pcfutil.h @@ -0,0 +1,54 @@ +/* pcfutil.h + + FreeType font driver for pcf fonts + + Copyright 2000 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. +*/ + + +#ifndef __PCFUTIL_H__ +#define __PCFUTIL_H__ + + +#include + + + void BitOrderInvert( unsigned char* buf, + int nbytes); + + void TwoByteSwap ( unsigned char* buf, + int nbytes); + + void FourByteSwap ( unsigned char* buf, + int nbytes); + + int RepadBitmap ( char* pSrc, + char* pDst, + unsigned int srcPad, + unsigned int dstPad, + int width, + int height); + +#endif /* __PCFUTIL_H__ */ + + +/* END */ diff --git a/src/pcf/readme b/src/pcf/readme new file mode 100644 index 000000000..75f49e142 --- /dev/null +++ b/src/pcf/readme @@ -0,0 +1,114 @@ + FreeType font driver for PCF fonts + + Francesco Zappa Nardelli + + + +Introduction +************ + +PCF (Portable Compiled Format) is a binary bitmap font format, largely used +in X world. This code implements a PCF driver for the FreeType library. +Glyph images are loaded into memory only on demand, thus leading to a small +memory footprint. + +Informations on the PCF font format can only be worked out from +``pcfread.c'', and ``pcfwrite.c'', to be found, for instance, in the XFree86 +(www.xfree86.org) source tree (xc/lib/font/bitmap/). + +Many good bitmap fonts in bdf format come with XFree86: they can be +compiled into the pcf format using the ``bdftopcf'' utility. + + +Supported hardware +****************** + +The driver has been tested on linux/x86 and sunos5.5/sparc. In both +cases the compiler was gcc. When back in Paris, I will test it also +on linux/alpha. + + +Encodings +********* + +The variety of encodings that accompanies pcf fonts appears to encompass the +small set defined in freetype.h. On the other hand, each pcf font defines +two properties that specify encoding and registry. + +I decided to make these two properties directly accessible, leaving to the +client application the work of interpreting them. For instance: + + #include "pcftypes.h" /* include/freetype/internal/pcftypes.h */ + + FT_Face face; + PCF_Public_Face pcfface; + + FT_New_Face( library,..., &face ); + + pcfface = (PCF_Public_Face)face; + + if ((pcfface->charset_registry == "ISO10646") && + (pcfface->charset_encoding) == "1")) [..] + +Thus the driver always export ``ft_encoding_none'' as +face->charmap.encoding. FT_Get_Char_Index() behavior is unmodified, that +is, it converts the ULong value given as argument into the corresponding +glyph number. + + +Known problems +************** + +- dealing explicitly with encodings breaks the uniformity of freetype2 + api. + +- except for encodings properties, client applications have no + visibility of the PCF_Face object. This means that applications + cannot directly access font tables and are obliged to trust + FreeType. + +- currently, glyph names and ink_metrics are ignored. + +I plan to give full visibility of the PCF_Face object in the next +release of the driver, thus implementing also glyph names and +ink_metrics. + +- height is defined as (ascent - descent). Is this correct? + +- if unable to read size informations from the font, PCF_Init_Face + sets available_size->width and available_size->height to 12. + +- too many english grammar errors in the readme file :-( + + +License +******* + +Copyright (C) 2000 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. + + +Credits +******* + +Keith Packard wrote the pcf driver found in XFree86. His work is at +the same time the specification and the sample implementation of the +PCF format. Undoubtedly, this driver is inspired from his work. diff --git a/src/pcf/rules.mk b/src/pcf/rules.mk new file mode 100644 index 000000000..d2fd9cc98 --- /dev/null +++ b/src/pcf/rules.mk @@ -0,0 +1,79 @@ +# +# FreeType 2 pcf driver configuration rules +# + + +# Copyright (C) 2000 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. + + +# pcf driver directory +# +PCF_DIR := $(SRC_)pcf +PCF_DIR_ := $(PCF_DIR)$(SEP) + + +PCF_COMPILE := $(FT_COMPILE) + + +# pcf driver sources (i.e., C files) +# +PCF_DRV_SRC := $(PCF_DIR_)pcfread.c \ + $(PCF_DIR_)pcfdriver.c \ + $(PCF_DIR_)pcfutil.c + +# pcf driver headers +# +PCF_DRV_H := $(PCF_DIR_)pcf.h \ + $(PCF_DIR_)pcfdriver.h \ + $(PCF_DIR_)pcfutil.h + +# pcf driver object(s) +# +# PCF_DRV_OBJ_M is used during `multi' builds +# PCF_DRV_OBJ_S is used during `single' builds +# +PCF_DRV_OBJ_M := $(PCF_DRV_SRC:$(PCF_DIR_)%.c=$(OBJ_)%.$O) +PCF_DRV_OBJ_S := $(OBJ_)pcf.$O + +# Windows driver source file for single build +# +PCF_DRV_SRC_S := $(PCF_DIR_)pcf.c + + +# pcf driver - single object +# +$(PCF_DRV_OBJ_S): $(PCF_DRV_SRC_S) $(PCF_DRV_SRC) $(FREETYPE_H) $(PCF_DRV_H) + $(PCF_COMPILE) $T$@ $(PCF_DRV_SRC_S) + + +# pcf driver - multiple objects +# +$(OBJ_)%.$O: $(PCF_DIR_)%.c $(FREETYPE_H) $(PCF_DRV_H) + $(PCF_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(PCF_DRV_OBJ_S) +DRV_OBJS_M += $(PCF_DRV_OBJ_M) + +# EOF