From 993a8d044538e59ebaffe27d4d04f8efb979fd7c Mon Sep 17 00:00:00 2001 From: David Turner Date: Sat, 18 May 2002 12:03:43 +0000 Subject: [PATCH] adding BDF driver --- include/freetype/internal/fttrace.h | 3 + src/Jamfile | 1 + src/bdf/bdf.c | 33 + src/bdf/bdf.h | 367 ++++ src/bdf/bdfdriver.c | 463 +++++ src/bdf/bdfdriver.h | 68 + src/bdf/bdferror.h | 44 + src/bdf/bdflib.c | 2465 +++++++++++++++++++++++++++ src/bdf/module.mk | 31 + src/bdf/rules.mk | 80 + 10 files changed, 3555 insertions(+) create mode 100644 src/bdf/bdf.c create mode 100644 src/bdf/bdf.h create mode 100644 src/bdf/bdfdriver.c create mode 100644 src/bdf/bdfdriver.h create mode 100644 src/bdf/bdferror.h create mode 100644 src/bdf/bdflib.c create mode 100644 src/bdf/module.mk create mode 100644 src/bdf/rules.mk diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h index 0753e43b8..a0c93447b 100644 --- a/include/freetype/internal/fttrace.h +++ b/include/freetype/internal/fttrace.h @@ -92,6 +92,9 @@ FT_TRACE_DEF( winfnt ) FT_TRACE_DEF( pcfdriver ) FT_TRACE_DEF( pcfread ) +/* BDF fonts component */ +FT_TRACE_DEF( bdf ) + /* PFR fonts component */ FT_TRACE_DEF( pfr ) diff --git a/src/Jamfile b/src/Jamfile index f1b3b9bff..9192c7e95 100644 --- a/src/Jamfile +++ b/src/Jamfile @@ -17,6 +17,7 @@ HDRMACRO [ FT2_SubDir include internal internal.h ] ; SubInclude FT2_TOP src pshinter ; SubInclude FT2_TOP src autohint ; SubInclude FT2_TOP src base ; +SubInclude FT2_TOP src bdf ; SubInclude FT2_TOP src cache ; SubInclude FT2_TOP src cff ; SubInclude FT2_TOP src cid ; diff --git a/src/bdf/bdf.c b/src/bdf/bdf.c new file mode 100644 index 000000000..6c308be3b --- /dev/null +++ b/src/bdf/bdf.c @@ -0,0 +1,33 @@ +/* bdf.c + + FreeType font driver for bdf files + + Copyright (C) 2001 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 "bdflib.c" +#include "bdfdriver.c" + +/* END */ diff --git a/src/bdf/bdf.h b/src/bdf/bdf.h new file mode 100644 index 000000000..0ba587eda --- /dev/null +++ b/src/bdf/bdf.h @@ -0,0 +1,367 @@ +/* + * Copyright 2000 Computing Research Labs, New Mexico State University + * Copyright 2001 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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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 __BDF_H__ +#define __BDF_H__ + +/* + * $Id$ + */ + +#include + +#include +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_STREAM_H + + +FT_BEGIN_HEADER +/* Imported from bdfP.h */ + +#ifndef MYABS +#define MYABS(xx) ((xx) < 0 ? -(xx) : (xx)) +#endif + +#define _bdf_glyph_modified(map, e) ((map)[(e) >> 5] & (1 << ((e) & 31))) +#define _bdf_set_glyph_modified(map, e) (map)[(e) >> 5] |= (1 << ((e) & 31)) +#define _bdf_clear_glyph_modified(map, e) (map)[(e) >> 5] &= ~(1 << ((e) & 31)) + +/* end of bdfP.h */ + +/************************************************************************** + * + * BDF font options macros and types. + * + **************************************************************************/ + +#define BDF_UNIX_EOL 1 /* Save fonts with Unix LF. */ +#define BDF_DOS_EOL 2 /* Save fonts with DOS CRLF. */ +#define BDF_MAC_EOL 3 /* Save fonts with Mac CR. */ + +#define BDF_CORRECT_METRICS 0x01 /* Correct invalid metrics when loading. */ +#define BDF_KEEP_COMMENTS 0x02 /* Preserve the font comments. */ +#define BDF_KEEP_UNENCODED 0x04 /* Keep the unencoded glyphs. */ +#define BDF_PROPORTIONAL 0x08 /* Font has proportional spacing. */ +#define BDF_MONOWIDTH 0x10 /* Font has mono width. */ +#define BDF_CHARCELL 0x20 /* Font has charcell spacing. */ + +#define BDF_ALL_SPACING (BDF_PROPORTIONAL|BDF_MONOWIDTH|BDF_CHARCELL) + +#define BDF_DEFAULT_LOAD_OPTIONS \ + (BDF_CORRECT_METRICS|BDF_KEEP_COMMENTS|BDF_KEEP_UNENCODED|BDF_PROPORTIONAL) + +typedef struct { + int ttf_hint; + int correct_metrics; + int keep_unencoded; + int keep_comments; + int pad_cells; + int font_spacing; + long point_size; + unsigned long resolution_x; + unsigned long resolution_y; + int bits_per_pixel; + int eol; +} bdf_options_t; + +/* + * Callback function type for unknown configuration options. + */ +typedef int (*bdf_options_callback_t) (bdf_options_t *opts, + char **params, + unsigned long nparams, + void *client_data); + +/************************************************************************** + * + * BDF font property macros and types. + * + **************************************************************************/ + +#define BDF_ATOM 1 +#define BDF_INTEGER 2 +#define BDF_CARDINAL 3 + +/* + * This structure represents a particular property of a font. + * There are a set of defaults and each font has their own. + */ +typedef struct { + char *name; /* Name of the property. */ + int format; /* Format of the property. */ + int builtin; /* A builtin property. */ + union { + char *atom; + long int32; + unsigned long card32; + } value; /* Value of the property. */ +} bdf_property_t; + +/************************************************************************** + * + * BDF font metric and glyph types. + * + **************************************************************************/ + +/* + * A general bitmap type, mostly used when the glyph bitmap is being edited. + */ +typedef struct { + short x; + short y; + unsigned short width; + unsigned short height; + unsigned short bpp; + unsigned short pad; + unsigned char *bitmap; + unsigned long bytes; +} bdf_bitmap_t; + +typedef struct { + int font_spacing; + unsigned short swidth; + unsigned short dwidth; + unsigned short width; + unsigned short height; + short x_offset; + short y_offset; + short ascent; + short descent; +} bdf_metrics_t; + +typedef struct { + unsigned short width; + unsigned short height; + short x_offset; + short y_offset; + short ascent; + short descent; +} bdf_bbx_t; + +typedef struct { + char *name; /* Glyph name. */ + long encoding; /* Glyph encoding. */ + unsigned short swidth; /* Scalable width. */ + unsigned short dwidth; /* Device width. */ + bdf_bbx_t bbx; /* Glyph bounding box. */ + unsigned char *bitmap; /* Glyph bitmap. */ + unsigned short bytes; /* Number of bytes used for the bitmap. */ +} bdf_glyph_t; + +typedef struct { + char *key; + void *data; +} _hashnode, *hashnode; + +typedef struct { + int limit; + int size; + int used; + hashnode *table; +} hashtable; + +typedef struct { + unsigned short pad; /* Pad to 4-byte boundary. */ + unsigned short bpp; /* Bits per pixel. */ + long start; /* Beginning encoding value of glyphs. */ + long end; /* Ending encoding value of glyphs. */ + bdf_glyph_t *glyphs; /* Glyphs themselves. */ + unsigned long glyphs_size; /* Glyph structures allocated. */ + unsigned long glyphs_used; /* Glyph structures used. */ + bdf_bbx_t bbx; /* Overall bounding box of glyphs. */ +} bdf_glyphlist_t; + +typedef struct { + char *name; /* Name of the font. */ + bdf_bbx_t bbx; /* Font bounding box. */ + + long point_size; /* Point size of the font. */ + unsigned long resolution_x; /* Font horizontal resolution. */ + unsigned long resolution_y; /* Font vertical resolution. */ + + int hbf; /* Font came from an HBF font. */ + + int spacing; /* Font spacing value. */ + + unsigned short monowidth; /* Logical width for monowidth font. */ + + long default_glyph; /* Encoding of the default glyph. */ + + long font_ascent; /* Font ascent. */ + long font_descent; /* Font descent. */ + + long glyphs_size; /* Glyph structures allocated. */ + long glyphs_used; /* Glyph structures used. */ + bdf_glyph_t *glyphs; /* Glyphs themselves. */ + + long unencoded_size; /* Unencoded glyph structures allocated. */ + long unencoded_used; /* Unencoded glyph structures used. */ + bdf_glyph_t *unencoded; /* Unencoded glyphs themselves. */ + + unsigned long props_size; /* Font properties allocated. */ + unsigned long props_used; /* Font properties used. */ + bdf_property_t *props; /* Font properties themselves. */ + + char *comments; /* Font comments. */ + unsigned long comments_len; /* Length of comment string. */ + + char *acmsgs; /* Auto-correction messages. */ + unsigned long acmsgs_len; /* Length of auto-correction messages. */ + + bdf_glyphlist_t overflow; /* Storage used for glyph insertion. */ + + void *internal; /* Internal data for the font. */ + + unsigned long nmod[2048]; /* Bitmap indicating modified glyphs. */ + unsigned long umod[2048]; /* Bitmap indicating modified unencoded. */ + + unsigned short modified; /* Boolean indicating font modified. */ + unsigned short bpp; /* Bits per pixel. */ + + FT_Memory memory; + bdf_property_t *user_props; + unsigned long nuser_props; + hashtable proptbl; + +} bdf_font_t; + + +/************************************************************************** + * + * Types for load/save callbacks. + * + **************************************************************************/ + +/* + * Callback reasons. + */ +#define BDF_LOAD_START 1 +#define BDF_LOADING 2 +#define BDF_SAVE_START 3 +#define BDF_SAVING 4 +#define BDF_TRANSLATE_START 5 +#define BDF_TRANSLATING 6 +#define BDF_ROTATE_START 7 +#define BDF_ROTATING 8 +#define BDF_SHEAR_START 9 +#define BDF_SHEARING 10 +#define BDF_GLYPH_NAME_START 11 +#define BDF_GLYPH_NAME 12 +#define BDF_EXPORT_START 13 +#define BDF_EXPORTING 14 +#define BDF_EMBOLDEN_START 15 +#define BDF_EMBOLDENING 16 +#define BDF_WARNING 20 +#define BDF_ERROR 21 + +/* + * Error codes. + */ +#define BDF_OK 0 +#define BDF_MISSING_START -1 +#define BDF_MISSING_FONTNAME -2 +#define BDF_MISSING_SIZE -3 +#define BDF_MISSING_FONTBBX -4 +#define BDF_MISSING_CHARS -5 +#define BDF_MISSING_STARTCHAR -6 +#define BDF_MISSING_ENCODING -7 +#define BDF_MISSING_BBX -8 + +#define BDF_NOT_CONSOLE_FONT -10 +#define BDF_NOT_MF_FONT -11 +#define BDF_NOT_PSF_FONT -12 + +#define BDF_OUT_OF_MEMORY -20 + +#define BDF_EMPTY_FONT -99 +#define BDF_INVALID_LINE -100 + +typedef struct { + unsigned long reason; + unsigned long current; + unsigned long total; + unsigned long errlineno; +} bdf_callback_struct_t; + +typedef void (*bdf_callback_t) (bdf_callback_struct_t *call_data, + void *client_data); + +/************************************************************************** + * + * BDF font API. + * + **************************************************************************/ + +/* + * Startup and shutdown functions are no more needed + */ + +/* + * Font options functions. + */ +/*extern void bdf_default_options (bdf_options_t *opts);*/ + +/* + * Font load, create, save and free functions. + */ + +FT_LOCAL( bdf_font_t* ) bdf_load_font (FT_Stream stream, FT_Memory memory, + bdf_options_t *opts, + bdf_callback_t callback, void *data); + + +FT_LOCAL( void ) bdf_free_font (bdf_font_t *font); + +/* + * Font property functions. + */ +/* extern void bdf_create_property (char *name, int type, bdf_font_t *font); */ +FT_LOCAL( bdf_property_t* ) bdf_get_property (char *name, bdf_font_t *font); +FT_LOCAL( unsigned long ) bdf_property_list (bdf_property_t **props); + +FT_LOCAL( void ) bdf_add_font_property (bdf_font_t *font, + bdf_property_t *property); + +FT_LOCAL( void ) bdf_delete_font_property (bdf_font_t *font, char *name); + +FT_LOCAL( bdf_property_t* ) bdf_get_font_property (bdf_font_t *font, + char *name); + +FT_LOCAL( unsigned long ) bdf_font_property_list (bdf_font_t *font, + bdf_property_t **props); + +/* + * Font comment functions. + */ +FT_LOCAL( int ) bdf_replace_comments (bdf_font_t *font, char *comments, + unsigned long comments_len); + +/* + * Other miscellaneous functions. + */ +FT_LOCAL( void ) bdf_set_default_metrics (bdf_font_t *font); + +/* */ + +FT_END_HEADER + +#endif /* _h_bdf */ diff --git a/src/bdf/bdfdriver.c b/src/bdf/bdfdriver.c new file mode 100644 index 000000000..3b0122bd9 --- /dev/null +++ b/src/bdf/bdfdriver.c @@ -0,0 +1,463 @@ +/* bdfdriver.c + + FreeType font driver for bdf files + + Copyright (C) 2001-2002 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 "bdf.h" +#include "bdfdriver.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_bdf + + +FT_CALLBACK_DEF( FT_Error ) +BDF_Face_Done( BDF_Face face ) +{ + FT_Memory 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( face->root.family_name ); + + FT_FREE( face->root.available_sizes ); + FT_FREE( face->bdffont ); + + FT_TRACE4(("bdf: done face\n")); + + return FT_Err_Ok; +} + + +FT_CALLBACK_DEF( FT_Error ) +BDF_Face_Init( FT_Stream stream, + BDF_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) +{ + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_FACE_MEMORY( face ); + bdf_font_t* font; + bdf_options_t options; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + + (void) FT_STREAM_SEEK( 0 ); + + options.correct_metrics = 1; /* FZ XXX : options semantics */ + options.keep_unencoded = 1; + options.pad_cells = 1; + + font = bdf_load_font( stream, memory, &options, 0, 0 ); + if ( font == NULL ) + { + FT_TRACE2(("[not a valid BDF file]\n")); + goto Fail; + } + + /* we have a bdf font: let's construct the face object */ + face->bdffont = font; + { + FT_Face root = FT_FACE( face ); + bdf_property_t* prop = NULL; + + FT_TRACE4(("glyph %d - %d, unencoded %d %d\n",font->glyphs_size, + font->glyphs_used, font->unencoded_size, font->unencoded_used)); + + + 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 ; + + prop = bdf_get_font_property (font,"SPACING"); + + if ( prop && prop->format == BDF_ATOM ) + { + if ( (*(prop->value.atom) == 'M') || + (*(prop->value.atom) == 'C') ) + { + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + } + } + } + + /* FZ XXX : TO DO : FT_FACE_FLAGS_VERTICAL */ + /* FZ XXX : I need a font to implement this */ + + root->style_flags = 0; + + prop = bdf_get_font_property (font,"SLANT"); + + if ( prop && prop->format == BDF_ATOM ) + { + if ( (*(prop->value.atom) == 'O' ) || + (*(prop->value.atom) == 'I' ) ) + { + root->style_flags |= FT_STYLE_FLAG_ITALIC; + } + } + + prop = bdf_get_font_property (font,"WEIGHT_NAME"); + + if ( prop && prop->format == BDF_ATOM ) + { + if ( *(prop->value.atom) == 'B' ) + root->style_flags |= FT_STYLE_FLAG_BOLD; + } + + + prop = bdf_get_font_property (font,"FAMILY_NAME"); + if (prop != NULL) { + int l = strlen(prop->value.atom) + 1; + if ( FT_ALLOC( root->family_name, l * sizeof(char)) ) + goto Fail; + strcpy(root->family_name, prop->value.atom); + } else root->family_name = 0; + + 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"; + + root->num_glyphs = font->glyphs_size ; /* unencoded included */ + + root->num_fixed_sizes = 1; + if ( FT_ALLOC_ARRAY( root->available_sizes, 1, + FT_Bitmap_Size ) ) + goto Fail; + + prop = bdf_get_font_property(font,"PIXEL_SIZE"); + if (prop != NULL) { + bdf_property_t *xres = 0, *yres = 0; + + xres = bdf_get_font_property(font,"RESOLUTION_X"); + yres = bdf_get_font_property(font,"RESOLUTION_Y"); + if ((xres != NULL) && (yres != NULL)) { + FT_TRACE4(("prop %d %d %d\n",prop->value.int32, xres->value.int32, + yres->value.int32)); + root->available_sizes->width = + prop->value.int32 * 75 / xres->value.int32; + root->available_sizes->height = + prop->value.int32 * 75 / yres->value.int32; + } + } else { + /* some fonts have broken SIZE declaration (jiskan24.bdf) */ + FT_ERROR(("BDF Warning: reading size\n")); + root->available_sizes->width = font->point_size ; + root->available_sizes->height = font->point_size ; + } + + /* encoding table */ + { + bdf_glyph_t *cur = font->glyphs; + int n; + + if ( FT_ALLOC ( face->en_table , + font->glyphs_size * sizeof(BDF_encoding_el ) ) ) + goto Fail; + + for (n = 0; nglyphs_size ; n++) { + (face->en_table[n]).enc = cur[n].encoding ; + FT_TRACE4(("enc n: %d, val %ld\n",n,cur[n].encoding)); + (face->en_table[n]).glyph = n; + } + } + + /* charmaps */ + { + bdf_property_t *charset_registry = 0, *charset_encoding = 0; + + charset_registry = bdf_get_font_property(font,"CHARSET_REGISTRY"); + charset_encoding = bdf_get_font_property(font,"CHARSET_ENCODING"); + if ((charset_registry != NULL) && (charset_encoding != NULL)) { + if ((charset_registry->format == BDF_ATOM) && + (charset_encoding->format == BDF_ATOM)) { + if (FT_ALLOC(face->charset_encoding, + (strlen(charset_encoding->value.atom)+1) * sizeof(char))) + goto Exit; + if (FT_ALLOC(face->charset_registry, + (strlen(charset_registry->value.atom)+1) * sizeof(char))) + goto Exit; + strcpy(face->charset_registry,charset_registry->value.atom); + strcpy(face->charset_encoding,charset_encoding->value.atom); + + 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; + goto Exit; + } + } + + /* otherwise assume adobe standard encoding */ + face->charmap.encoding = ft_encoding_adobe_standard; + face->charmap.platform_id = 7; /* taken from t1objs.c */ + face->charmap.encoding_id = 0; + face->charmap.face = root; + face->charmap_handle = &face->charmap; + root->charmap = face->charmap_handle; + } + } + + Exit: + return FT_Err_Ok; + + Fail: + BDF_Face_Done( face ); + return FT_Err_Unknown_File_Format; +} + +static +FT_Error BDF_Set_Pixel_Size( FT_Size size ) +{ + BDF_Face face = (BDF_Face)FT_SIZE_FACE( size ); + FT_Face root = FT_FACE( face ); + + FT_TRACE4(("rec %d - pres %d\n",size->metrics.y_ppem, + root->available_sizes->height)); + if (size->metrics.y_ppem == root->available_sizes->height) { + + size->metrics.ascender = face->bdffont->bbx.ascent << 6; + size->metrics.descender = face->bdffont->bbx.descent * (-64); + size->metrics.height = face->bdffont->bbx.height <<6; + + return FT_Err_Ok; + } + else { + return FT_Err_Invalid_Pixel_Size; + } +} + +static +FT_Error BDF_Glyph_Load( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int load_flags ) +{ + BDF_Face face = (BDF_Face)FT_SIZE_FACE( size ); + FT_Error error = FT_Err_Ok; + FT_Bitmap *bitmap = &slot->bitmap; + bdf_glyph_t glyph; + int i; + FT_Memory memory = face->bdffont->memory; + + if (!face) { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + /* slot, bitmap => freetype, glyph => bdflib */ + glyph = face->bdffont->glyphs[glyph_index]; + + bitmap->pitch = (glyph.bbx.width + 7) >> 3; + bitmap->rows = glyph.bbx.height; + bitmap->width = glyph.bbx.width; + bitmap->num_grays = 1; /* unused */ + bitmap->pixel_mode = ft_pixel_mode_mono; + + if ( FT_ALLOC ( bitmap->buffer , glyph.bytes) ) + return FT_Err_Out_Of_Memory; + FT_MEM_SET( bitmap->buffer , 0 , glyph.bytes ); + for (i=0 ; ibuffer[i] = glyph.bitmap[i]; + } + + slot->bitmap_left = 0; + slot->bitmap_top = glyph.bbx.ascent ; + + /* FZ TO DO : vertical metrics */ + slot->metrics.horiAdvance = glyph.dwidth << 6; + slot->metrics.horiBearingX = glyph.bbx.x_offset << 6 ; + slot->metrics.horiBearingY = glyph.bbx.y_offset << 6 ; + slot->metrics.width = bitmap->width << 6 ; + slot->metrics.height = bitmap->rows << 6; + + slot->linearHoriAdvance = (FT_Fixed)glyph.dwidth << 16; + slot->format = ft_glyph_format_bitmap; + slot->flags = FT_GLYPH_OWN_BITMAP; + + Exit: + return error; +} + +static +FT_UInt BDF_Get_Char_Index( FT_CharMap charmap, + FT_ULong char_code ) +{ + BDF_Face face = ((BDF_Face)charmap->face); + BDF_encoding_el *en_table = face->en_table; + int low, high, mid; + + FT_TRACE4(("get_char_index %ld\n", char_code)); + + low = 0; + high = face->bdffont->glyphs_used - 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->bdffont->default_glyph; +} + +FT_CALLBACK_TABLE_DEF +const FT_Driver_ClassRec bdf_driver_class = +{ + { + ft_module_font_driver, + sizeof ( FT_DriverRec ), + + "bdf", + 0x10000L, + 0x20000L, + + 0, + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + sizeof( BDF_FaceRec ), + sizeof( FT_SizeRec ), + sizeof( FT_GlyphSlotRec ), + + (FT_Face_InitFunc) BDF_Face_Init, + (FT_Face_DoneFunc) BDF_Face_Done, + (FT_Size_InitFunc) 0, + (FT_Size_DoneFunc) 0, + (FT_Slot_InitFunc) 0, + (FT_Slot_DoneFunc) 0, + + (FT_Size_ResetPointsFunc) BDF_Set_Pixel_Size, + (FT_Size_ResetPixelsFunc) BDF_Set_Pixel_Size, + + (FT_Slot_LoadFunc) BDF_Glyph_Load, + +#ifndef FT_CONFIG_OPTION_USE_CMAPS + (FT_CharMap_CharIndexFunc)0, +#else + (FT_CharMap_CharIndexFunc)0, +#endif + + (FT_Face_GetKerningFunc) 0, + (FT_Face_AttachFunc) 0, + (FT_Face_GetAdvancesFunc) 0, + +#ifndef FT_CONFIG_OPTION_USE_CMAPS + (FT_CharMap_CharNextFunc) 0, /*PCF_Char_Get_Next,*/ +#else + (FT_CharMap_CharNextFunc) 0 +#endif + }; + + /* + (FTDriver_initFace) BDF_Init_Face, + (FTDriver_doneFace) BDF_Done_Face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) BDF_Set_Pixel_Size, + (FTDriver_setPixelSizes)BDF_Set_Pixel_Size, + + (FTDriver_loadGlyph) BDF_Load_Glyph, + (FTDriver_getCharIndex) BDF_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 &bdf_driver_class; + } + + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/src/bdf/bdfdriver.h b/src/bdf/bdfdriver.h new file mode 100644 index 000000000..daa870cb2 --- /dev/null +++ b/src/bdf/bdfdriver.h @@ -0,0 +1,68 @@ +/* bdfdriver.h + + FreeType font driver for bdf fonts + + Copyright (C) 2001 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 __BDF_DRIVER_H__ +#define __BDF_DRIVER_H__ + +#include +#include FT_INTERNAL_DRIVER_H + +#include "bdf.h" + +FT_BEGIN_HEADER + + typedef struct { + FT_Long enc; + FT_Short glyph; + } BDF_encoding_el; + + typedef struct BDF_FaceRec_ + { + FT_FaceRec root; + + char *charset_encoding; + char *charset_registry; + + bdf_font_t *bdffont; + + BDF_encoding_el *en_table; + + FT_CharMap charmap_handle; + FT_CharMapRec charmap; /* a single charmap per face */ + } BDF_FaceRec, *BDF_Face; + + + FT_EXPORT_VAR( const FT_Driver_ClassRec ) bdf_driver_class; + +FT_END_HEADER + + +#endif /* __BDF_DRIVER_H__ */ + + +/* END */ + diff --git a/src/bdf/bdferror.h b/src/bdf/bdferror.h new file mode 100644 index 000000000..271ba827b --- /dev/null +++ b/src/bdf/bdferror.h @@ -0,0 +1,44 @@ +/* + * Copyright 2001 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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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. + */ + + /*************************************************************************/ + /* */ + /* This file is used to define the PCF error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __BDFERROR_H__ +#define __BDFERROR_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX BDF_Err_ +#define FT_ERR_BASE FT_Mod_Err_BDF + +#include FT_ERRORS_H + +#endif /* __PCFERROR_H__ */ + + +/* END */ diff --git a/src/bdf/bdflib.c b/src/bdf/bdflib.c new file mode 100644 index 000000000..d7bc87c8c --- /dev/null +++ b/src/bdf/bdflib.c @@ -0,0 +1,2465 @@ +/* + * Copyright 2000 Computing Research Labs, New Mexico State University + * Copyright 2001 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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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. + */ + +/* +static char rcsid[] = "$Id$"; +*/ + +#include + +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H + +#include "bdf.h" + +#include "bdferror.h" + +#undef MAX +#define MAX(h, i) ((h) > (i) ? (h) : (i)) + +#undef MIN +#define MIN(l, o) ((l) < (o) ? (l) : (o)) + +/************************************************************************** + * + * Masks used for checking different bits per pixel cases. + * + **************************************************************************/ + +static const unsigned char onebpp[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; +static const unsigned char twobpp[] = { 0xc0, 0x30, 0x0c, 0x03 }; +static const unsigned char fourbpp[] = { 0xf0, 0x0f }; +static const unsigned char eightbpp[] = { 0xff }; + +/************************************************************************** + * + * Default BDF font options. + * + **************************************************************************/ + +static const bdf_options_t _bdf_opts = +{ + 1, /* Hint TTF glyphs. */ + 1, /* Correct metrics. */ + 1, /* Preserve unencoded glyphs. */ + 1, /* Preserve comments. */ + 1, /* Pad character-cells. */ + BDF_PROPORTIONAL, /* Default spacing. */ + 12, /* Default point size. */ + 0, /* Default horizontal resolution. */ + 0, /* Default vertical resolution. */ + 1, /* Bits per pixel. */ + BDF_UNIX_EOL, /* Line separator. */ +}; + +/************************************************************************** + * + * Builtin BDF font properties. + * + **************************************************************************/ + +/* + * List of most properties that might appear in a font. Doesn't include the + * RAW_* and AXIS_* properties in X11R6 polymorphic fonts. + */ +static const bdf_property_t _bdf_properties[] = +{ + {"ADD_STYLE_NAME", BDF_ATOM, 1}, + {"AVERAGE_WIDTH", BDF_INTEGER, 1}, + {"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1}, + {"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1}, + {"CAP_HEIGHT", BDF_INTEGER, 1}, + {"CHARSET_COLLECTIONS", BDF_ATOM, 1}, + {"CHARSET_ENCODING", BDF_ATOM, 1}, + {"CHARSET_REGISTRY", BDF_ATOM, 1}, + {"COMMENT", BDF_ATOM, 1}, + {"COPYRIGHT", BDF_ATOM, 1}, + {"DEFAULT_CHAR", BDF_CARDINAL, 1}, + {"DESTINATION", BDF_CARDINAL, 1}, + {"DEVICE_FONT_NAME", BDF_ATOM, 1}, + {"END_SPACE", BDF_INTEGER, 1}, + {"FACE_NAME", BDF_ATOM, 1}, + {"FAMILY_NAME", BDF_ATOM, 1}, + {"FIGURE_WIDTH", BDF_INTEGER, 1}, + {"FONT", BDF_ATOM, 1}, + {"FONTNAME_REGISTRY", BDF_ATOM, 1}, + {"FONT_ASCENT", BDF_INTEGER, 1}, + {"FONT_DESCENT", BDF_INTEGER, 1}, + {"FOUNDRY", BDF_ATOM, 1}, + {"FULL_NAME", BDF_ATOM, 1}, + {"ITALIC_ANGLE", BDF_INTEGER, 1}, + {"MAX_SPACE", BDF_INTEGER, 1}, + {"MIN_SPACE", BDF_INTEGER, 1}, + {"NORM_SPACE", BDF_INTEGER, 1}, + {"NOTICE", BDF_ATOM, 1}, + {"PIXEL_SIZE", BDF_INTEGER, 1}, + {"POINT_SIZE", BDF_INTEGER, 1}, + {"QUAD_WIDTH", BDF_INTEGER, 1}, + {"RAW_ASCENT", BDF_INTEGER, 1}, + {"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1}, + {"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1}, + {"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1}, + {"RAW_CAP_HEIGHT", BDF_INTEGER, 1}, + {"RAW_DESCENT", BDF_INTEGER, 1}, + {"RAW_END_SPACE", BDF_INTEGER, 1}, + {"RAW_FIGURE_WIDTH", BDF_INTEGER, 1}, + {"RAW_MAX_SPACE", BDF_INTEGER, 1}, + {"RAW_MIN_SPACE", BDF_INTEGER, 1}, + {"RAW_NORM_SPACE", BDF_INTEGER, 1}, + {"RAW_PIXEL_SIZE", BDF_INTEGER, 1}, + {"RAW_POINT_SIZE", BDF_INTEGER, 1}, + {"RAW_PIXELSIZE", BDF_INTEGER, 1}, + {"RAW_POINTSIZE", BDF_INTEGER, 1}, + {"RAW_QUAD_WIDTH", BDF_INTEGER, 1}, + {"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1}, + {"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1}, + {"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1}, + {"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1}, + {"RAW_SUBSCRIPT_X", BDF_INTEGER, 1}, + {"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1}, + {"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1}, + {"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1}, + {"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1}, + {"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1}, + {"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1}, + {"RAW_X_HEIGHT", BDF_INTEGER, 1}, + {"RELATIVE_SETWIDTH", BDF_CARDINAL, 1}, + {"RELATIVE_WEIGHT", BDF_CARDINAL, 1}, + {"RESOLUTION", BDF_INTEGER, 1}, + {"RESOLUTION_X", BDF_CARDINAL, 1}, + {"RESOLUTION_Y", BDF_CARDINAL, 1}, + {"SETWIDTH_NAME", BDF_ATOM, 1}, + {"SLANT", BDF_ATOM, 1}, + {"SMALL_CAP_SIZE", BDF_INTEGER, 1}, + {"SPACING", BDF_ATOM, 1}, + {"STRIKEOUT_ASCENT", BDF_INTEGER, 1}, + {"STRIKEOUT_DESCENT", BDF_INTEGER, 1}, + {"SUBSCRIPT_SIZE", BDF_INTEGER, 1}, + {"SUBSCRIPT_X", BDF_INTEGER, 1}, + {"SUBSCRIPT_Y", BDF_INTEGER, 1}, + {"SUPERSCRIPT_SIZE", BDF_INTEGER, 1}, + {"SUPERSCRIPT_X", BDF_INTEGER, 1}, + {"SUPERSCRIPT_Y", BDF_INTEGER, 1}, + {"UNDERLINE_POSITION", BDF_INTEGER, 1}, + {"UNDERLINE_THICKNESS", BDF_INTEGER, 1}, + {"WEIGHT", BDF_CARDINAL, 1}, + {"WEIGHT_NAME", BDF_ATOM, 1}, + {"X_HEIGHT", BDF_INTEGER, 1}, + {"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1}, + {"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1}, +}; + +static const FT_ULong _num_bdf_properties = FT_NUM_ELEMENT(_bdf_properties); + +/* + * User defined properties. + */ +/*static bdf_property_t *user_props; + static unsigned long nuser_props = 0;*/ + +/************************************************************************** + * + * Hash table utilities for the properties. + * + **************************************************************************/ + +#define INITIAL_HT_SIZE 241 + +typedef void (*hash_free_func)(hashnode node); + +static hashnode* +hash_bucket(char *key, hashtable *ht) +{ + char* kp = key; + unsigned long res = 0; + hashnode* bp = ht->table, *ndp; + + /* + * Mocklisp hash function. + */ + while (*kp) + res = (res << 5) - res + *kp++; + + ndp = bp + (res % ht->size); + while (*ndp) + { + kp = (*ndp)->key; + + if (kp[0] == key[0] && ft_strcmp(kp, key) == 0) + break; + + ndp--; + if (ndp < bp) + ndp = bp + (ht->size - 1); + } + return ndp; +} + + +static FT_Error +hash_rehash ( hashtable* ht, + FT_Memory memory ) +{ + hashnode *obp = ht->table, *bp, *nbp; + int i, sz = ht->size; + FT_Error error; + + ht->size <<= 1; + ht->limit = ht->size / 3; + + if ( FT_NEW_ARRAY( ht->table , ht->size ) ) + return error; + + for (i = 0, bp = obp; i < sz; i++, bp++) + { + if (*bp) + { + nbp = hash_bucket((*bp)->key, ht); + *nbp = *bp; + } + } + FT_FREE(obp); + + return FT_Err_Ok; +} + + +static FT_Error +hash_init ( hashtable* ht, + FT_Memory memory ) +{ + int sz = INITIAL_HT_SIZE; + FT_Error error; + + ht->size = sz; + ht->limit = sz / 3; + ht->used = 0; + + if ( FT_NEW_ARRAY( ht->table, size ) ) + return error; + + return FT_Err_Ok; +} + + +static void +hash_free( hashtable* ht, + FT_Memory memory ) +{ + /* FT_Error error; */ + + if ( ht != 0 ) + { + int i, sz = ht->size; + hashnode* bp = ht->table; + + for (i = 0; i < sz; i++, bp++) + { + if (*bp) + FT_FREE(*bp); + } + if (sz > 0) + FT_FREE(ht->table); + } +} + + +static FT_Error +hash_insert ( char* key, + void* data, + hashtable* ht, + FT_Memory memory ) +{ + FT_Error error = FT_Err_Ok; + hashnode nn, *bp = hash_bucket(key, ht); + + nn = *bp; + if (!nn) + { + if ( FT_NEW( nn ) ) + return error; + + *bp = nn; + nn->key = key; + nn->data = data; + + if (ht->used >= ht->limit) + error = hash_rehash(ht, memory); + + ht->used++; + } + else + nn->data = data; + + return error; +} + + +static hashnode +hash_lookup(char *key, hashtable *ht) +{ + hashnode *np = hash_bucket(key, ht); + return *np; +} + +#ifdef 0 +static void +hash_delete(char *name, hashtable *ht , FT_Memory memory) +{ + hashnode *hp; + /* FT_Error error; */ + + hp = hash_bucket(name, ht); + FT_FREE( *hp ); +} +#endif + +/* + * The builtin property table. + */ +/*static hashtable proptbl; */ /* XXX eliminate this */ + + + +/************************************************************************** + * + * Utility types and functions. + * + **************************************************************************/ + +/* + * Function type for parsing lines of a BDF font. + */ +typedef int (*_bdf_line_func_t)( char* line, + unsigned long linelen, + unsigned long lineno, + void* call_data, + void* client_data ); + +/* + * List structure for splitting lines into fields. + */ +typedef struct +{ + char** field; + unsigned long size; + unsigned long used; + char* bfield; + unsigned long bsize; + unsigned long bused; + +} _bdf_list_t; + + +/* + * Structure used while loading BDF fonts. + */ +typedef struct +{ + unsigned long flags; + unsigned long cnt; + unsigned long row; + unsigned long bpr; + short minlb; + short maxlb; + short maxrb; + short maxas; + short maxds; + short rbearing; + char* glyph_name; + long glyph_enc; + bdf_font_t* font; + bdf_options_t* opts; + void* client_data; + bdf_callback_t callback; + bdf_callback_struct_t cb; + unsigned long have[2048]; + _bdf_list_t list; + + FT_Memory memory; + +} _bdf_parse_t; + +#define setsbit(m, cc) (m[(cc) >> 3] |= (1 << ((cc) & 7))) +#define sbitset(m, cc) (m[(cc) >> 3] & (1 << ((cc) & 7))) + +/* + * An empty string for empty fields. + */ +static const char empty[1] = { 0 }; /* XXX eliminate this */ + +/* + * Assume the line is NULL terminated and that the `list' parameter was + * initialized the first time it was used. + */ +static FT_Error +_bdf_split ( char* separators, + char* line, + unsigned long linelen, + _bdf_list_t* list, + FT_Memory memory ) +{ + int mult, final_empty; + char *sp, *ep, *end; + unsigned char seps[32]; + FT_Error error; + + /* + * Initialize the list. + */ + list->used = list->bused = 0; + + /* + * If the line is empty, then simply return. + */ + if ( linelen == 0 || line[0] == 0 ) + return FT_Err_Ok; + + /* + * If the `separators' parameter is NULL or empty, split the list into + * individual bytes. + */ + if ( separators == 0 || *separators == 0 ) + { + if ( linelen > list->bsize ) + { + if ( list->bsize ) + { + if ( FT_ALLOC ( list->bfield , linelen) ) + return error; + } + else + { + if ( FT_REALLOC ( list->bfield , list->bsize, linelen) ) + return error; + } + list->bsize = linelen; + } + list->bused = linelen; + + FT_MEM_COPY (list->bfield, line, linelen); + return FT_Err_Ok; + } + + /* + * Prepare the separator bitmap. + */ + FT_MEM_ZERO( seps, 32 ); + + /* + * If the very last character of the separator string is a plus, then set + * the `mult' flag to indicate that multiple separators should be + * collapsed into one. + */ + for ( mult = 0, sp = separators; sp && *sp; sp++ ) + { + if ( sp[0] == '+' && sp[1] == 0) + mult = 1; + else + setsbit( seps, sp[0] ); + } + + /* + * Break the line up into fields. + */ + final_empty = 0; + sp = ep = line; + end = sp + linelen; + for ( ; sp < end && *sp;) + { + /* + * Collect everything that is not a separator. + */ + for ( ; *ep && !sbitset( seps, *ep ); ep++ ) ; + + /* + * Resize the list if necessary. + */ + if ( list->used == list->size ) + { + if ( list->size == 0 ) + { + if ( FT_NEW_ARRAY( list->field , 5) ) + return error; + } + else + { + if ( FT_RENEW_ARRAY( list->field , list->size, list->size+5 ) + return error; + } + list->size += 5; + } + + /* + * Assign the field appropriately. + */ + list->field[ list->used++ ] = (ep > sp) ? sp : empty; + + sp = ep; + if (mult) + { + /* + * If multiple separators should be collapsed, do it now by + * setting all the separator characters to 0. + */ + for ( ; *ep && sbitset(seps, *ep); ep++ ) + *ep = 0; + + } + else if (*ep != 0) + { + /* + * Don't collapse multiple separators by making them 0, so just + * make the one encountered 0. + */ + *ep++ = 0; + } + + final_empty = ( ep > sp && *ep == 0 ); + sp = ep; + } + + /* + * Finally, NULL terminate the list. + */ + if ( list->used + final_empty + 1 >= list->size ) + { + if ( list->used == list->size ) + { + if ( list->size == 0 ) + { + if ( FT_NEW_ARRAY( list->field, 5 ) ) + return error; + } + else + { + if ( FT_RENEW_ARRAY( list->field , list->size, list->size+5 ) ) + return error; + } + list->size += 5; + } + } + + if (final_empty) + list->field[ list->used++ ] = empty; + + if ( list->used == list->size ) + { + if ( list->size == 0 ) + { + if ( FT_NEW_ARRAY( list->field , 5 ) ) + return error; + } + else + { + if ( FT_NEW_ARRAY( list->field, list->size, list->size + 5 ) ) + return error; + } + list->size += 5; + } + list->field[ list->used ] = 0; + + return FT_Err_Ok; +} + + +static void +_bdf_shift( unsigned long n, + _bdf_list_t* list) +{ + unsigned long i, u; + + if ( list == 0 || list->used == 0 || n == 0 ) + return; + + if ( n >= list->used ) + { + list->used = 0; + return; + } + for ( u = n, i = 0; u < list->used; i++, u++ ) + list->field[i] = list->field[u]; + + list->used -= n; +} + + +static char* +_bdf_join( int c, + unsigned long* len, + _bdf_list_t* list) +{ + unsigned long i, j; + char *fp, *dp; + + if ( list == 0 || list->used == 0 ) + return 0; + + *len = 0; + + dp = list->field[0]; + + for ( i = j = 0; i < list->used; i++ ) + { + fp = list->field[i]; + while (*fp) + dp[j++] = *fp++; + + if (i + 1 < list->used) + dp[j++] = c; + } + dp[j] = 0; + + *len = j; + return dp; +} + +/* + * High speed file reader that passes each line to a callback. + */ +int ftreadstream( FT_Stream stream, + char* buffer, + int count ) +{ + int read_bytes; + int pos = stream->pos; + + if ( pos >= stream->size ) + { + FT_ERROR(( "FT_Read_Stream_At:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + return 0; + } + + if ( stream->read ) + read_bytes = stream->read( stream, pos, buffer, count ); + else + { + read_bytes = stream->size - pos; + if ( read_bytes > count ) + read_bytes = count; + + ft_memcpy( buffer, stream->base + pos, read_bytes ); + } + + stream->pos = pos + read_bytes; + + return read_bytes; +} + +static int +_bdf_readstream( FT_Stream stream, + _bdf_line_func_t callback, + void* client_data, + unsigned long* lno) +{ + _bdf_line_func_t cb; + unsigned long lineno; + int n, res, done, refill, bytes, hold; + char *ls, *le, *pp, *pe, *hp; + char buf[65536]; + + if (callback == 0) + return -1; + + cb = callback; + lineno = 1; + buf[0] = 0; + res = done = 0; + pp = ls = le = buf; + bytes = 65536; + + while ( !done && (n = ftreadstream(stream, pp, bytes)) > 0 ) + { + /* + * Determine the new end of the buffer pages. + */ + pe = pp + n; + + for (refill = 0; done == 0 && refill == 0; ) + { + while (le < pe && *le != '\n' && *le != '\r') + le++; + + if (le == pe) + { + /* + * Hit the end of the last page in the buffer. Need to find + * out how many pages to shift and how many pages need to be + * read in. Adjust the line start and end pointers down to + * point to the right places in the pages. + */ + pp = buf + (((ls - buf) >> 13) << 13); + n = pp - buf; + ls -= n; + le -= n; + n = pe - pp; + (void) ft_memcpy(buf, pp, n); + pp = buf + n; + bytes = 65536 - n; + refill = 1; + } + else + { + /* + * Temporarily NULL terminate the line. + */ + hp = le; + hold = *le; + *le = 0; + + if (callback && *ls != '#' && *ls != 0x1a && le > ls && + (res = (*cb)(ls, le - ls, lineno, (void *) &cb, + client_data)) != 0) + done = 1; + else { + ls = ++le; + /* + * Handle the case of DOS crlf sequences. + */ + if (le < pe && hold == '\n' && *le =='\r') + ls = ++le; + } + + /* + * Increment the line number. + */ + lineno++; + + /* + * Restore the character at the end of the line. + */ + *hp = hold; + } + } + } + *lno = lineno; + return res; +} + + +FT_LOCAL_DEF( void ) +_bdf_memmove(char *dest, char *src, unsigned long bytes) +{ + long i, j; + + i = (long) bytes; + j = i & 7; + i = (i + 7) >> 3; + + /* + * Do a memmove using Ye Olde Duff's Device for efficiency. + */ + if (src < dest) { + src += bytes; + dest += bytes; + + switch (j) { + case 0: do { + *--dest = *--src; + case 7: *--dest = *--src; + case 6: *--dest = *--src; + case 5: *--dest = *--src; + case 4: *--dest = *--src; + case 3: *--dest = *--src; + case 2: *--dest = *--src; + case 1: *--dest = *--src; + } while (--i > 0); + } + } else if (src > dest) { + switch (j) { + case 0: do { + *dest++ = *src++; + case 7: *dest++ = *src++; + case 6: *dest++ = *src++; + case 5: *dest++ = *src++; + case 4: *dest++ = *src++; + case 3: *dest++ = *src++; + case 2: *dest++ = *src++; + case 1: *dest++ = *src++; + } while (--i > 0); + } + } +} + +static const unsigned char a2i[128] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char odigits[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static const unsigned char ddigits[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static const unsigned char hdigits[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +#define isdigok(m, d) (m[(d) >> 3] & (1 << ((d) & 7))) + +/* + * Routine to convert an ASCII string into an unsigned long integer. + */ +static unsigned long +_bdf_atoul(char *s, char **end, int base) +{ + unsigned long v; + unsigned char *dmap; + + if (s == 0 || *s == 0) + return 0; + + /* + * Make sure the radix is something recognizable. Default to 10. + */ + switch (base) + { + case 8: dmap = odigits; break; + case 16: dmap = hdigits; break; + default: base = 10; dmap = ddigits; break; + } + + /* + * Check for the special hex prefix. + */ + if ( s[0] == '0' && ( s[1] == 'x' || s[1] == 'X')) + { + base = 16; + dmap = hdigits; + s += 2; + } + + for ( v = 0; isdigok(dmap, *s); s++ ) + v = (v * base) + a2i[(int) *s]; + + if (end != 0) + *end = s; + + return v; +} + + +/* + * Routine to convert an ASCII string into an signed long integer. + */ +static long +_bdf_atol(char *s, char **end, int base) +{ + long v, neg; + unsigned char *dmap; + + if (s == 0 || *s == 0) + return 0; + + /* + * Make sure the radix is something recognizable. Default to 10. + */ + switch (base) { + case 8: dmap = odigits; break; + case 16: dmap = hdigits; break; + default: base = 10; dmap = ddigits; break; + } + + /* + * Check for a minus sign. + */ + neg = 0; + if (*s == '-') { + s++; + neg = 1; + } + + /* + * Check for the special hex prefix. + */ + if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) { + base = 16; + dmap = hdigits; + s += 2; + } + + for (v = 0; isdigok(dmap, *s); s++) + v = (v * base) + a2i[(int) *s]; + + if (end != 0) + *end = s; + + return (!neg) ? v : -v; +} + + +/* + * Routine to convert an ASCII string into an signed short integer. + */ +static short +_bdf_atos(char *s, char **end, int base) +{ + short v, neg; + unsigned char *dmap; + + if (s == 0 || *s == 0) + return 0; + + /* + * Make sure the radix is something recognizable. Default to 10. + */ + switch (base) { + case 8: dmap = odigits; break; + case 16: dmap = hdigits; break; + default: base = 10; dmap = ddigits; break; + } + + /* + * Check for a minus. + */ + neg = 0; + if (*s == '-') { + s++; + neg = 1; + } + + /* + * Check for the special hex prefix. + */ + if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) { + base = 16; + dmap = hdigits; + s += 2; + } + + for (v = 0; isdigok(dmap, *s); s++) + v = (v * base) + a2i[(int) *s]; + + if (end != 0) + *end = s; + + return (!neg) ? v : -v; +} + +/* + * Routine to compare two glyphs by encoding so they can be sorted. + */ +static int +by_encoding(const void *a, const void *b) +{ + bdf_glyph_t *c1, *c2; + + c1 = (bdf_glyph_t *) a; + c2 = (bdf_glyph_t *) b; + if (c1->encoding < c2->encoding) + return -1; + else if (c1->encoding > c2->encoding) + return 1; + return 0; +} + + + +static FT_Error +bdf_create_property( char* name, + int format, + bdf_font_t* font ) +{ + unsigned long n; + bdf_property_t* p; + FT_Memory memory = font->memory; + FT_Error error; + + /* + * First check to see if the property has + * already been added or not. If it has, then + * simply ignore it. + */ + if ( hash_lookup( name, &(font->proptbl)) ) + return FT_Err_Ok; + + if (font->nuser_props == 0) + { + if ( FT_NEW( font->user_props ) ) + return error; + } + else + { + if ( FT_RENEW_ARRAY( font->user_props, font->nuser_props, + (font->nuser_props + 1) ) ) + return error; + } + + p = font->user_props + font->nuser_props; + + FT_ZERO( p ); + + n = (unsigned long) (ft_strlen(name) + 1); + + if ( FT_ALLOC ( p->name , n) ) + return error; + + FT_MEM_COPY(p->name, name, n); + p->format = format; + p->builtin = 0; + + n = _num_bdf_properties + font->nuser_props; + + error = hash_insert(p->name, (void *) n, &(font->proptbl) , memory); + if (error) return error; + + font->nuser_props++; + return FT_Err_Ok; +} + + +FT_LOCAL_DEF( bdf_property_t* ) +bdf_get_property(char *name, bdf_font_t *font) +{ + hashnode hn; + unsigned long propid; + + if (name == 0 || *name == 0) + return 0; + + if ((hn = hash_lookup(name, &(font->proptbl))) == 0) + return 0; + + propid = (unsigned long) hn->data; + if (propid >= _num_bdf_properties) + return font->user_props + (propid - _num_bdf_properties); + + return _bdf_properties + propid; +} + + +/************************************************************************** + * + * BDF font file parsing flags and functions. + * + **************************************************************************/ + +/* + * Parse flags. + */ +#define _BDF_START 0x0001 +#define _BDF_FONT_NAME 0x0002 +#define _BDF_SIZE 0x0004 +#define _BDF_FONT_BBX 0x0008 +#define _BDF_PROPS 0x0010 +#define _BDF_GLYPHS 0x0020 +#define _BDF_GLYPH 0x0040 +#define _BDF_ENCODING 0x0080 +#define _BDF_SWIDTH 0x0100 +#define _BDF_DWIDTH 0x0200 +#define _BDF_BBX 0x0400 +#define _BDF_BITMAP 0x0800 + +#define _BDF_SWIDTH_ADJ 0x1000 + +#define _BDF_GLYPH_BITS (_BDF_GLYPH|_BDF_ENCODING|_BDF_SWIDTH|\ + _BDF_DWIDTH|_BDF_BBX|_BDF_BITMAP) + +#define _BDF_GLYPH_WIDTH_CHECK 0x40000000 +#define _BDF_GLYPH_HEIGHT_CHECK 0x80000000 + +/* + * Auto correction messages. + */ +#define ACMSG1 "FONT_ASCENT property missing. Added \"FONT_ASCENT %hd\"." +#define ACMSG2 "FONT_DESCENT property missing. Added \"FONT_DESCENT %hd\"." +#define ACMSG3 "Font width != actual width. Old: %hd New: %hd." +#define ACMSG4 "Font left bearing != actual left bearing. Old: %hd New: %hd." +#define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd." +#define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd." +#define ACMSG7 "Font height != actual height. Old: %hd New: %hd." +#define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made." +#define ACMSG9 "SWIDTH field missing at line %ld. Set automatically." +#define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width." +#define ACMSG11 "SIZE bits per pixel field adjusted to %hd." +#define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded." +#define ACMSG13 "Glyph %ld extra rows removed." +#define ACMSG14 "Glyph %ld extra columns removed." +#define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found." + +/* + * Error messages. + */ +#define ERRMSG1 "[line %ld] Missing \"%s\" line." +#define ERRMSG2 "[line %ld] Font header corrupted or missing fields." +#define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields." + +static FT_Error +_bdf_add_acmsg ( bdf_font_t* font, + char* msg, + unsigned long len ) +{ + char* cp; + FT_Memory memory = font->memory; + FT_Error error; + + if ( font->acmsgs_len == 0 ) + { + if ( FT_ALLOC ( font->acmsgs , len + 1 ) ) + return error; + } + else + { + if ( FT_REALLOC ( font->acmsgs , font->acmsgs_len , + font->acmsgs_len + len + 1 ) ) + return error; + } + + cp = font->acmsgs + font->acmsgs_len; + FT_MEM_COPY(cp, msg, len); + cp += len; + *cp++ = '\n'; + font->acmsgs_len += len + 1; + + return FT_Err_Ok; +} + + +static FT_Error +_bdf_add_comment ( bdf_font_t* font, + char* comment, + unsigned long len ) +{ + char *cp; + FT_Memory memory = font->memory; + FT_Error error; + + if (font->comments_len == 0) { + if ( FT_ALLOC ( font->comments , len + 1 ) ) + return error; + } + else + { + if ( FT_REALLOC ( font->comments , font->comments_len, + font->comments_len + len + 1) ) + return error; + } + + cp = font->comments + font->comments_len; + FT_MEM_COPY(cp, comment, len); + cp += len; + *cp++ = '\n'; + font->comments_len += len + 1; + + return FT_Err_Ok; +} + +/* + * Set the spacing from the font name if it exists, or set it to the default + * specified in the options. + */ +static void +_bdf_set_default_spacing( bdf_font_t* font, + bdf_options_t* opts) +{ + unsigned long len; + char name[128]; + _bdf_list_t list; + FT_Memory memory; + /* FT_Error error; */ + + if ( font == 0 || font->name == 0 || font->name[0] == 0 ) + return; + + memory = font->memory; + + font->spacing = opts->font_spacing; + + len = (unsigned long) ( ft_strlen(font->name) + 1 ); + (void) ft_memcpy(name, font->name, len); + + list.size = list.used = 0; + _bdf_split("-", name, len, &list, memory); + + if (list.used == 15) { + switch (list.field[11][0]) { + case 'C': case 'c': font->spacing = BDF_CHARCELL; break; + case 'M': case 'm': font->spacing = BDF_MONOWIDTH; break; + case 'P': case 'p': font->spacing = BDF_PROPORTIONAL; break; + } + } + if (list.size > 0) + FT_FREE(list.field); +} + + +/* + * Determine if the property is an atom or not. If it is, then clean it up so + * the double quotes are removed if they exist. + */ +static int +_bdf_is_atom( char* line, + unsigned long linelen, + char* *name, + char* *value, + bdf_font_t* font) +{ + int hold; + char *sp, *ep; + bdf_property_t *p; + + *name = sp = ep = line; + while (*ep && *ep != ' ' && *ep != '\t') + ep++; + + hold = -1; + if (*ep) + { + hold = *ep; + *ep = 0; + } + + p = bdf_get_property(sp, font); + + /* + * Restore the character that was saved before any return can happen. + */ + if (hold != -1) + *ep = hold; + + /* + * If the propert exists and is not an atom, just return here. + */ + if (p && p->format != BDF_ATOM) + return 0; + + /* + * The property is an atom. Trim all leading and trailing whitespace and + * double quotes for the atom value. + */ + sp = ep; + ep = line + linelen; + + /* + * Trim the leading whitespace if it exists. + */ + *sp++ = 0; + while (*sp && (*sp == ' ' || *sp == '\t')) + sp++; + + /* + * Trim the leading double quote if it exists. + */ + if (*sp == '"') + sp++; + *value = sp; + + /* + * Trim the trailing whitespace if it exists. + */ + while (ep > sp && (*(ep - 1) == ' ' || *(ep - 1) == '\t')) + *--ep = 0; + + /* + * Trim the trailing double quote if it exists. + */ + if (ep > sp && *(ep - 1) == '"') + *--ep = 0; + + return 1; +} + + +static FT_Error +_bdf_add_property ( bdf_font_t* font, + char* name, + char* value) +{ + unsigned long propid; + hashnode hn; + int len; + bdf_property_t *prop, *fp; + FT_Memory memory = font->memory; + FT_Error error; + /* hashtable proptbl = font->proptbl; + bdf_property_t *user_props = font->user_props; + unsigned long nuser_props = font->nuser_props; + */ + + /* + * First, check to see if the property already exists in the font. + */ + if ((hn = hash_lookup(name, (hashtable *) font->internal)) != 0) { + /* + * The property already exists in the font, so simply replace + * the value of the property with the current value. + */ + fp = font->props + (unsigned long) hn->data; + + switch (prop->format) + { + case BDF_ATOM: + { + /* + * Delete the current atom if it exists. + */ + FT_FREE ( fp->value.atom ); + + if (value == 0) + len = 1; + else + len = ft_strlen(value) + 1; + if (len > 1) + { + if ( FT_ALLOC ( fp->value.atom , len ) ) + return error; + + FT_MEM_COPY(fp->value.atom, value, len); + } + else + fp->value.atom = 0; + } + break; + + case BDF_INTEGER: + fp->value.int32 = _bdf_atol(value, 0, 10); + break; + + case BDF_CARDINAL: + fp->value.card32 = _bdf_atoul(value, 0, 10); + break; + + default: + ; + } + return FT_Err_Ok; + } + + /* + * See if this property type exists yet or not. If not, create it. + */ + hn = hash_lookup(name, &(font->proptbl)); + if (hn == 0) { + bdf_create_property(name, BDF_ATOM, font); + hn = hash_lookup(name, &(font->proptbl)); + } + + /* + * Allocate another property if this is overflow. + */ + if (font->props_used == font->props_size) + { + if (font->props_size == 0) + { + if ( FT_NEW( font->props ) ) + return error; + } + else + { + if ( FT_RENEW_ARRAY( font->props, font->props_size, + (font->props_size + 1) ) ) + return error; + } + fp = font->props + font->props_size; + FT_ZERO( fp ); + font->props_size++; + } + + propid = (unsigned long) hn->data; + if (propid >= _num_bdf_properties) + prop = font->user_props + (propid - _num_bdf_properties); + else + prop = _bdf_properties + propid; + + fp = font->props + font->props_used; + + fp->name = prop->name; + fp->format = prop->format; + fp->builtin = prop->builtin; + + switch (prop->format) + { + case BDF_ATOM: + { + fp->value.atom = NULL; + + if ( value && value[0] != 0 ) + { + len = ft_strlen(value) + 1; + + if ( FT_ALLOC ( fp->value.atom , len ) ) + return error; + + FT_MEM_COPY (fp->value.atom, value, len); + } + } + break; + + case BDF_INTEGER: + fp->value.int32 = _bdf_atol(value, 0, 10); + break; + + case BDF_CARDINAL: + fp->value.card32 = _bdf_atoul(value, 0, 10); + break; + + default: + ; + } + + /* + * If the property happens to be a comment, then it doesn't need + * to be added to the internal hash table. + */ + if ( ft_memcmp(name, "COMMENT", 7) != 0 ) + /* + * Add the property to the font property table. + */ + hash_insert( fp->name, (void *) font->props_used, + (hashtable *) font->internal, memory); + + font->props_used++; + + /* + * Some special cases need to be handled here. The DEFAULT_CHAR property + * needs to be located if it exists in the property list, the FONT_ASCENT + * and FONT_DESCENT need to be assigned if they are present, and the + * SPACING property should override the default spacing. + */ + if ( ft_memcmp(name, "DEFAULT_CHAR", 12) == 0 ) + font->default_glyph = fp->value.int32; + + else if ( ft_memcmp(name, "FONT_ASCENT", 11) == 0 ) + font->font_ascent = fp->value.int32; + + else if ( ft_memcmp(name, "FONT_DESCENT", 12) == 0 ) + font->font_descent = fp->value.int32; + + else if ( ft_memcmp(name, "SPACING", 7) == 0 ) + { + if (fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P') + font->spacing = BDF_PROPORTIONAL; + + else if (fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M') + font->spacing = BDF_MONOWIDTH; + + else if (fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C') + font->spacing = BDF_CHARCELL; + } + + return FT_Err_Ok; +} + +/* + * Actually parse the glyph info and bitmaps. + */ +static int +_bdf_parse_glyphs( char* line, + unsigned long linelen, + unsigned long lineno, + void* call_data, + void* client_data) +{ + int c; + char *s; + unsigned char *bp; + unsigned long i, slen, nibbles; + double ps, rx, dw, sw; + _bdf_line_func_t *next; + _bdf_parse_t *p; + bdf_glyph_t *glyph; + bdf_font_t *font; + char nbuf[128]; + FT_Memory memory; + FT_Error error; + + next = (_bdf_line_func_t *) call_data; + p = (_bdf_parse_t *) client_data; + + font = p->font; + memory = font->memory; + + /* + * Check for a comment. + */ + if (ft_memcmp(line, "COMMENT", 7) == 0) { + linelen -= 7; + s = line + 7; + if (*s != 0) { + s++; + linelen--; + } + _bdf_add_comment(p->font, s, linelen); + return 0; + } + + /* + * The very first thing expected is the number of glyphs. + */ + if (!(p->flags & _BDF_GLYPHS)) { + if (ft_memcmp(line, "CHARS", 5) != 0) { + sprintf(nbuf, ERRMSG1, lineno, "CHARS"); + _bdf_add_acmsg(p->font, nbuf, ft_strlen(nbuf)); + return BDF_MISSING_CHARS; + } + _bdf_split(" +", line, linelen, &p->list, memory); + p->cnt = font->glyphs_size = _bdf_atoul(p->list.field[1], 0, 10); + + /* + * Make sure the number of glyphs is non-zero. + */ + if (p->cnt == 0) + font->glyphs_size = 64; + +if ( FT_ALLOC ( font->glyphs , sizeof(bdf_glyph_t) * + font->glyphs_size ) ) + return FT_Err_Out_Of_Memory; + + /* + * Set up the callback to indicate the glyph loading is about to + * begin. + */ + if (p->callback != 0) { + p->cb.reason = BDF_LOAD_START; + p->cb.total = p->cnt; + p->cb.current = 0; + (*p->callback)(&p->cb, p->client_data); + } + p->flags |= _BDF_GLYPHS; + return 0; + } + + /* + * Check for the ENDFONT field. + */ + if (ft_memcmp(line, "ENDFONT", 7) == 0) { + /* + * Sort the glyphs by encoding. + */ + qsort((char *) font->glyphs, font->glyphs_used, sizeof(bdf_glyph_t), + by_encoding); + + p->flags &= ~_BDF_START; + return 0; + } + + /* + * Check for the ENDCHAR field. + */ + if (ft_memcmp(line, "ENDCHAR", 7) == 0) { + /* + * Set up and call the callback if it was passed. + */ + if (p->callback != 0) { + p->cb.reason = BDF_LOADING; + p->cb.total = font->glyphs_size; + p->cb.current = font->glyphs_used; + (*p->callback)(&p->cb, p->client_data); + } + p->glyph_enc = 0; + p->flags &= ~_BDF_GLYPH_BITS; + return 0; + } + + /* + * Check to see if a glyph is being scanned but should be ignored + * because it is an unencoded glyph. + */ + if ((p->flags & _BDF_GLYPH) && + p->glyph_enc == -1 && p->opts->keep_unencoded == 0) + return 0; + + /* + * Check for the STARTCHAR field. + */ + if (ft_memcmp(line, "STARTCHAR", 9) == 0) { + /* + * Set the character name in the parse info first until the + * encoding can be checked for an unencoded character. + */ + if (p->glyph_name != 0) + FT_FREE(p->glyph_name); + _bdf_split(" +", line, linelen, &p->list,memory); + _bdf_shift(1, &p->list); + s = _bdf_join(' ', &slen, &p->list); + if ( FT_ALLOC ( p->glyph_name , (slen + 1) ) ) + return BDF_OUT_OF_MEMORY; + FT_MEM_COPY(p->glyph_name, s, slen + 1); + p->flags |= _BDF_GLYPH; + return 0; + } + + /* + * Check for the ENCODING field. + */ + if (ft_memcmp(line, "ENCODING", 8) == 0) { + if (!(p->flags & _BDF_GLYPH)) { + /* + * Missing STARTCHAR field. + */ + sprintf(nbuf, ERRMSG1, lineno, "STARTCHAR"); + _bdf_add_acmsg(font, nbuf, ft_strlen(nbuf)); + return BDF_MISSING_STARTCHAR; + } + _bdf_split(" +", line, linelen, &p->list, memory); + p->glyph_enc = _bdf_atol(p->list.field[1], 0, 10); + + /* + * Check to see if this encoding has already been encountered. If it + * has then change it to unencoded so it gets added if indicated. + */ + if (p->glyph_enc >= 0) { + if (_bdf_glyph_modified(p->have, p->glyph_enc)) { + /* + * Add a message saying a glyph has been moved to the + * unencoded area. + */ + sprintf(nbuf, ACMSG12, p->glyph_enc, p->glyph_name); + _bdf_add_acmsg(font, nbuf, ft_strlen(nbuf)); + p->glyph_enc = -1; + font->modified = 1; + } else + _bdf_set_glyph_modified(p->have, p->glyph_enc); + } + + if (p->glyph_enc >= 0) { + /* + * Make sure there are enough glyphs allocated in case the + * number of characters happen to be wrong. + */ + if (font->glyphs_used == font->glyphs_size) { + if ( FT_REALLOC ( font->glyphs, + sizeof(bdf_glyph_t) * font->glyphs_size, + sizeof(bdf_glyph_t) * (font->glyphs_size + 64) ) ) + return BDF_OUT_OF_MEMORY; + FT_MEM_SET ((char *) (font->glyphs + font->glyphs_size), + 0, sizeof(bdf_glyph_t) << 6); /* FZ inutile */ + font->glyphs_size += 64; + } + + glyph = font->glyphs + font->glyphs_used++; + glyph->name = p->glyph_name; + glyph->encoding = p->glyph_enc; + + /* + * Reset the initial glyph info. + */ + p->glyph_name = 0; + } else { + /* + * Unencoded glyph. Check to see if it should be added or not. + */ + if (p->opts->keep_unencoded != 0) { + /* + * Allocate the next unencoded glyph. + */ + if (font->unencoded_used == font->unencoded_size) { + if (font->unencoded_size == 0) { + if ( FT_ALLOC ( font->unencoded , sizeof(bdf_glyph_t) << 2 ) ) + return BDF_OUT_OF_MEMORY; + } + else { + if ( FT_REALLOC ( font->unencoded , + sizeof(bdf_glyph_t) * font->unencoded_size, + sizeof(bdf_glyph_t) * + (font->unencoded_size + 4) ) ) + return BDF_OUT_OF_MEMORY; + } + font->unencoded_size += 4; + } + + glyph = font->unencoded + font->unencoded_used; + glyph->name = p->glyph_name; + glyph->encoding = font->unencoded_used++; + } else + /* + * Free up the glyph name if the unencoded shouldn't be + * kept. + */ + FT_FREE( p->glyph_name ); + + p->glyph_name = 0; + } + + /* + * Clear the flags that might be added when width and height are + * checked for consistency. + */ + p->flags &= ~(_BDF_GLYPH_WIDTH_CHECK|_BDF_GLYPH_HEIGHT_CHECK); + + p->flags |= _BDF_ENCODING; + return 0; + } + + /* + * Point at the glyph being constructed. + */ + if (p->glyph_enc == -1) + glyph = font->unencoded + (font->unencoded_used - 1); + else + glyph = font->glyphs + (font->glyphs_used - 1); + + /* + * Check to see if a bitmap is being constructed. + */ + if (p->flags & _BDF_BITMAP) { + /* + * If there are more rows than are specified in the glyph metrics, + * ignore the remaining lines. + */ + if (p->row >= glyph->bbx.height) { + if (!(p->flags & _BDF_GLYPH_HEIGHT_CHECK)) { + sprintf(nbuf, ACMSG13, glyph->encoding); + _bdf_add_acmsg(font, nbuf, ft_strlen(nbuf)); + p->flags |= _BDF_GLYPH_HEIGHT_CHECK; + font->modified = 1; + } + return 0; + } + + /* + * Only collect the number of nibbles indicated by the glyph metrics. + * If there are more columns, they are simply ignored. + */ + nibbles = p->bpr << 1; + bp = glyph->bitmap + (p->row * p->bpr); + for (i = 0, *bp = 0; i < nibbles; i++) { + c = line[i]; + *bp = (*bp << 4) + a2i[c]; + if (i + 1 < nibbles && (i & 1)) + *++bp = 0; + } + + /* + * If any line has extra columns, indicate they have been removed. + */ + if ((line[nibbles] == '0' || a2i[(int) line[nibbles]] != 0) && + !(p->flags & _BDF_GLYPH_WIDTH_CHECK)) { + sprintf(nbuf, ACMSG14, glyph->encoding); + _bdf_add_acmsg(font, nbuf, ft_strlen(nbuf)); + p->flags |= _BDF_GLYPH_WIDTH_CHECK; + font->modified = 1; + } + + p->row++; + return 0; + } + + /* + * Expect the SWIDTH (scalable width) field next. + */ + if (ft_memcmp(line, "SWIDTH", 6) == 0) { + if (!(p->flags & _BDF_ENCODING)) { + /* + * Missing ENCODING field. + */ + sprintf(nbuf, ERRMSG1, lineno, "ENCODING"); + _bdf_add_acmsg(font, nbuf, ft_strlen(nbuf)); + return BDF_MISSING_ENCODING; + } + _bdf_split(" +", line, linelen, &p->list, memory); + glyph->swidth = _bdf_atoul(p->list.field[1], 0, 10); + p->flags |= _BDF_SWIDTH; + return 0; + } + + /* + * Expect the DWIDTH (scalable width) field next. + */ + if (ft_memcmp(line, "DWIDTH", 6) == 0) { + _bdf_split(" +", line, linelen, &p->list,memory); + glyph->dwidth = _bdf_atoul(p->list.field[1], 0, 10); + + if (!(p->flags & _BDF_SWIDTH)) { + /* + * Missing SWIDTH field. Add an auto correction message and set + * the scalable width from the device width. + */ + sprintf(nbuf, ACMSG9, lineno); + _bdf_add_acmsg(font, nbuf, ft_strlen(nbuf)); + ps = (double) font->point_size; + rx = (double) font->resolution_x; + dw = (double) glyph->dwidth; + glyph->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx)); + } + + p->flags |= _BDF_DWIDTH; + return 0; + } + + /* + * Expect the BBX field next. + */ + if (ft_memcmp(line, "BBX", 3) == 0) { + _bdf_split(" +", line, linelen, &p->list, memory); + glyph->bbx.width = _bdf_atos(p->list.field[1], 0, 10); + glyph->bbx.height = _bdf_atos(p->list.field[2], 0, 10); + glyph->bbx.x_offset = _bdf_atos(p->list.field[3], 0, 10); + glyph->bbx.y_offset = _bdf_atos(p->list.field[4], 0, 10); + + /* + * Generate the ascent and descent of the character. + */ + glyph->bbx.ascent = glyph->bbx.height + glyph->bbx.y_offset; + glyph->bbx.descent = -glyph->bbx.y_offset; + + /* + * Determine the overall font bounding box as the characters are + * loaded so corrections can be done later if indicated. + */ + p->maxas = MAX(glyph->bbx.ascent, p->maxas); + p->maxds = MAX(glyph->bbx.descent, p->maxds); + p->rbearing = glyph->bbx.width + glyph->bbx.x_offset; + p->maxrb = MAX(p->rbearing, p->maxrb); + p->minlb = MIN(glyph->bbx.x_offset, p->minlb); + p->maxlb = MAX(glyph->bbx.x_offset, p->maxlb); + + if (!(p->flags & _BDF_DWIDTH)) { + /* + * Missing DWIDTH field. Add an auto correction message and set + * the device width to the glyph width. + */ + sprintf(nbuf, ACMSG10, lineno); + _bdf_add_acmsg(font, nbuf, ft_strlen(nbuf)); + glyph->dwidth = glyph->bbx.width; + } + + /* + * If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH + * value if necessary. + */ + if (p->opts->correct_metrics != 0) { + /* + * Determine the point size of the glyph. + */ + ps = (double) font->point_size; + rx = (double) font->resolution_x; + dw = (double) glyph->dwidth; + sw = (unsigned short) ((dw * 72000.0) / (ps * rx)); + + if (sw != glyph->swidth) { + glyph->swidth = sw; + if (p->glyph_enc == -1) + _bdf_set_glyph_modified(font->umod, + font->unencoded_used - 1); + else + _bdf_set_glyph_modified(font->nmod, glyph->encoding); + p->flags |= _BDF_SWIDTH_ADJ; + font->modified = 1; + } + } + p->flags |= _BDF_BBX; + return 0; + } + + /* + * And finally, gather up the bitmap. + */ + if (ft_memcmp(line, "BITMAP", 6) == 0) { + if (!(p->flags & _BDF_BBX)) { + /* + * Missing BBX field. + */ + sprintf(nbuf, ERRMSG1, lineno, "BBX"); + _bdf_add_acmsg(font, nbuf, ft_strlen(nbuf)); + return BDF_MISSING_BBX; + } + /* + * Allocate enough space for the bitmap. + */ + p->bpr = ((glyph->bbx.width * p->font->bpp) + 7) >> 3; + glyph->bytes = p->bpr * glyph->bbx.height; + if ( FT_ALLOC ( glyph->bitmap , glyph->bytes ) ) + return BDF_OUT_OF_MEMORY; + p->row = 0; + p->flags |= _BDF_BITMAP; + return 0; + } + + return BDF_INVALID_LINE; +} + +/* +* Load the font properties. +*/ +static int +_bdf_parse_properties(char *line, unsigned long linelen, unsigned long lineno, + void *call_data, void *client_data) +{ + unsigned long vlen; + _bdf_line_func_t *next; + _bdf_parse_t *p; + char *name, *value, nbuf[128]; + FT_Memory memory; + + next = (_bdf_line_func_t *) call_data; + p = (_bdf_parse_t *) client_data; + + memory = p->font->memory; + /* + * Check for the end of the properties. + */ + if (ft_memcmp(line, "ENDPROPERTIES", 13) == 0) { + /* + * If the FONT_ASCENT or FONT_DESCENT properties have not been + * encountered yet, then make sure they are added as properties and + * make sure they are set from the font bounding box info. + * + * This is *always* done regardless of the options, because X11 + * requires these two fields to compile fonts. + */ + if (bdf_get_font_property(p->font, "FONT_ASCENT") == 0) { + p->font->font_ascent = p->font->bbx.ascent; + sprintf(nbuf, "%hd", p->font->bbx.ascent); + _bdf_add_property(p->font, "FONT_ASCENT", nbuf); + sprintf(nbuf, ACMSG1, p->font->bbx.ascent); + _bdf_add_acmsg(p->font, nbuf, ft_strlen(nbuf)); + p->font->modified = 1; + } + if (bdf_get_font_property(p->font, "FONT_DESCENT") == 0) { + p->font->font_descent = p->font->bbx.descent; + sprintf(nbuf, "%hd", p->font->bbx.descent); + _bdf_add_property(p->font, "FONT_DESCENT", nbuf); + sprintf(nbuf, ACMSG2, p->font->bbx.descent); + _bdf_add_acmsg(p->font, nbuf, ft_strlen(nbuf)); + p->font->modified = 1; + } + p->flags &= ~_BDF_PROPS; + *next = _bdf_parse_glyphs; + return 0; + } + + /* + * Ignore the _XFREE86_GLYPH_RANGES properties. + */ + if (ft_memcmp(line, "_XFREE86_GLYPH_RANGES", 21) == 0) + return 0; + + /* + * Handle COMMENT fields and properties in a special way to preserve + * the spacing. + */ + if (ft_memcmp(line, "COMMENT", 7) == 0) { + name = value = line; + value += 7; + if (*value) + *value++ = 0; + _bdf_add_property(p->font, name, value); + } else if (_bdf_is_atom(line, linelen, &name, &value, p->font)) + _bdf_add_property(p->font, name, value); + else { + _bdf_split(" +", line, linelen, &p->list, memory); + name = p->list.field[0]; + _bdf_shift(1, &p->list); + value = _bdf_join(' ', &vlen, &p->list); + _bdf_add_property(p->font, name, value); + } + + return 0; +} + +/* + * Load the font header. + */ +static int +_bdf_parse_start(char *line, unsigned long linelen, unsigned long lineno, + void *call_data, void *client_data) +{ + unsigned long slen; + _bdf_line_func_t *next; + _bdf_parse_t *p; + bdf_font_t *font; + char *s, nbuf[128]; + /* int test; */ + FT_Memory memory; + FT_Error error; + + next = (_bdf_line_func_t *) call_data; + p = (_bdf_parse_t *) client_data; + if (p->font) + memory = p->font->memory; + + /* + * Check for a comment. This is done to handle those fonts that have + * comments before the STARTFONT line for some reason. + */ + if (ft_memcmp(line, "COMMENT", 7) == 0) { + if (p->opts->keep_comments != 0 && p->font != 0) { + linelen -= 7; + s = line + 7; + if (*s != 0) { + s++; + linelen--; + } + _bdf_add_comment(p->font, s, linelen); + /* here font is not defined ! */ + } + return 0; + } + + if (!(p->flags & _BDF_START)) { + + memory = p->memory; + + if (ft_memcmp(line, "STARTFONT", 9) != 0) + /* + * No STARTFONT field is a good indication of a problem. + */ + return BDF_MISSING_START; + p->flags = _BDF_START; + font = p->font = 0; + + if ( FT_ALLOC ( font, sizeof(bdf_font_t) ) ) + return BDF_OUT_OF_MEMORY; + p->font = font; + + font->memory = p->memory; + p->memory = 0; + + /* if (font == 0) { + fprintf(stderr,"failed font\n"); + }*/ /* XXX */ + + { /* setup */ + unsigned long i; + bdf_property_t *prop; + + hash_init(&(font->proptbl), memory); + for (i = 0, prop = _bdf_properties; + i < _num_bdf_properties; i++, prop++) + hash_insert(prop->name, (void *) i, &(font->proptbl) , memory); + } + + if ( FT_ALLOC ( p->font->internal , sizeof(hashtable) ) ) + return BDF_OUT_OF_MEMORY; + hash_init((hashtable *) p->font->internal,memory); + p->font->spacing = p->opts->font_spacing; + p->font->default_glyph = -1; + return 0; + } + + /* + * Check for the start of the properties. + */ + if (ft_memcmp(line, "STARTPROPERTIES", 15) == 0) { + _bdf_split(" +", line, linelen, &p->list, memory); + p->cnt = p->font->props_size = _bdf_atoul(p->list.field[1], 0, 10); + + if ( FT_ALLOC ( p->font->props , (sizeof(bdf_property_t) * p->cnt) ) ) + return BDF_OUT_OF_MEMORY; + p->flags |= _BDF_PROPS; + *next = _bdf_parse_properties; + return 0; + } + + /* + * Check for the FONTBOUNDINGBOX field. + */ + if (ft_memcmp(line, "FONTBOUNDINGBOX", 15) == 0) { + if (!(p->flags & _BDF_SIZE)) { + /* + * Missing the SIZE field. + */ + sprintf(nbuf, ERRMSG1, lineno, "SIZE"); + _bdf_add_acmsg(p->font, nbuf, ft_strlen(nbuf)); + return BDF_MISSING_SIZE; + } + _bdf_split(" +", line, linelen, &p->list , memory); + p->font->bbx.width = _bdf_atos(p->list.field[1], 0, 10); + p->font->bbx.height = _bdf_atos(p->list.field[2], 0, 10); + p->font->bbx.x_offset = _bdf_atos(p->list.field[3], 0, 10); + p->font->bbx.y_offset = _bdf_atos(p->list.field[4], 0, 10); + p->font->bbx.ascent = p->font->bbx.height + p->font->bbx.y_offset; + p->font->bbx.descent = -p->font->bbx.y_offset; + p->flags |= _BDF_FONT_BBX; + return 0; + } + + /* + * The next thing to check for is the FONT field. + */ + if (ft_memcmp(line, "FONT", 4) == 0) { + _bdf_split(" +", line, linelen, &p->list , memory); + _bdf_shift(1, &p->list); + s = _bdf_join(' ', &slen, &p->list); + if ( FT_ALLOC ( p->font->name , slen + 1 ) ) + return BDF_OUT_OF_MEMORY; + (void) ft_memcpy(p->font->name, s, slen + 1); + /* + * If the font name is an XLFD name, set the spacing to the one in the + * font name. If there is no spacing fall back on the default. + */ + _bdf_set_default_spacing(p->font, p->opts); + p->flags |= _BDF_FONT_NAME; + return 0; + } + + /* + * Check for the SIZE field. + */ + if (ft_memcmp(line, "SIZE", 4) == 0) { + if (!(p->flags & _BDF_FONT_NAME)) { + /* + * Missing the FONT field. + */ + sprintf(nbuf, ERRMSG1, lineno, "FONT"); + _bdf_add_acmsg(p->font, nbuf, ft_strlen(nbuf)); + return BDF_MISSING_FONTNAME; + } + _bdf_split(" +", line, linelen, &p->list, memory); + p->font->point_size = _bdf_atoul(p->list.field[1], 0, 10); + p->font->resolution_x = _bdf_atoul(p->list.field[2], 0, 10); + p->font->resolution_y = _bdf_atoul(p->list.field[3], 0, 10); + + /* + * Check for the bits per pixel field. + */ + if (p->list.used == 5) { + p->font->bpp = _bdf_atos(p->list.field[4], 0, 10); + if (p->font->bpp > 1 && (p->font->bpp & 1)) { + /* + * Move up to the next bits per pixel value if an odd number + * is encountered. + */ + p->font->bpp++; + if (p->font->bpp <= 4) { + sprintf(nbuf, ACMSG11, p->font->bpp); + _bdf_add_acmsg(p->font, nbuf, ft_strlen(nbuf)); + } + } + if (p->font->bpp > 4) { + sprintf(nbuf, ACMSG11, p->font->bpp); + _bdf_add_acmsg(p->font, nbuf, ft_strlen(nbuf)); + p->font->bpp = 4; + } + } else + p->font->bpp = 1; + + p->flags |= _BDF_SIZE; + return 0; + } + + return BDF_INVALID_LINE; +} + +/************************************************************************** + * + * API. + * + **************************************************************************/ + + +FT_LOCAL_DEF( bdf_font_t* ) +bdf_load_font( FT_Stream stream, + FT_Memory extmemory, + bdf_options_t* opts, + bdf_callback_t callback, + void* data) +{ + int n; + unsigned long lineno; + char msgbuf[128]; + _bdf_parse_t p; + FT_Memory memory; + FT_Error error; + + (void) ft_memset((char *) &p, 0, sizeof(_bdf_parse_t)); + p.opts = (opts != 0) ? opts : &_bdf_opts; + p.minlb = 32767; + p.callback = callback; + p.client_data = data; + + p.memory = extmemory; /* only during font creation */ + + n = _bdf_readstream(stream, _bdf_parse_start, (void *) &p, &lineno); + + if (p.font != 0) { + /* + * If the font is not proportional, set the fonts monowidth + * field to the width of the font bounding box. + */ + memory = p.font->memory; + + if (p.font->spacing != BDF_PROPORTIONAL) + p.font->monowidth = p.font->bbx.width; + + /* + * If the number of glyphs loaded is not that of the original count, + * indicate the difference. + */ + if (p.cnt != p.font->glyphs_used + p.font->unencoded_used) { + sprintf(msgbuf, ACMSG15, p.cnt, + p.font->glyphs_used + p.font->unencoded_used); + _bdf_add_acmsg(p.font, msgbuf, ft_strlen(msgbuf)); + p.font->modified = 1; + } + + /* + * Once the font has been loaded, adjust the overall font metrics if + * necessary. + */ + if (p.opts->correct_metrics != 0 && + (p.font->glyphs_used > 0 || p.font->unencoded_used > 0)) { + if (p.maxrb - p.minlb != p.font->bbx.width) { + sprintf(msgbuf, ACMSG3, p.font->bbx.width, p.maxrb - p.minlb); + _bdf_add_acmsg(p.font, msgbuf, ft_strlen(msgbuf)); + p.font->bbx.width = p.maxrb - p.minlb; + p.font->modified = 1; + } + if (p.font->bbx.x_offset != p.minlb) { + sprintf(msgbuf, ACMSG4, p.font->bbx.x_offset, p.minlb); + _bdf_add_acmsg(p.font, msgbuf, ft_strlen(msgbuf)); + p.font->bbx.x_offset = p.minlb; + p.font->modified = 1; + } + if (p.font->bbx.ascent != p.maxas) { + sprintf(msgbuf, ACMSG5, p.font->bbx.ascent, p.maxas); + _bdf_add_acmsg(p.font, msgbuf, ft_strlen(msgbuf)); + p.font->bbx.ascent = p.maxas; + p.font->modified = 1; + } + if (p.font->bbx.descent != p.maxds) { + sprintf(msgbuf, ACMSG6, p.font->bbx.descent, p.maxds); + _bdf_add_acmsg(p.font, msgbuf, ft_strlen(msgbuf)); + p.font->bbx.descent = p.maxds; + p.font->bbx.y_offset = -p.maxds; + p.font->modified = 1; + } + if (p.maxas + p.maxds != p.font->bbx.height) { + sprintf(msgbuf, ACMSG7, p.font->bbx.height, p.maxas + p.maxds); + _bdf_add_acmsg(p.font, msgbuf, ft_strlen(msgbuf)); + } + p.font->bbx.height = p.maxas + p.maxds; + + if (p.flags & _BDF_SWIDTH_ADJ) + _bdf_add_acmsg(p.font, ACMSG8, ft_strlen(ACMSG8)); + } + } + + /* + * Last, if an error happened during loading, handle the messages. + */ + if (n < 0 && callback != 0) { + /* + * An error was returned. Alert the client. + */ + p.cb.reason = BDF_ERROR; + p.cb.errlineno = lineno; + (*callback)(&p.cb, data); + } else if (p.flags & _BDF_START) { + if (p.font != 0) { + /* + * The ENDFONT field was never reached or did not exist. + */ + if (!(p.flags & _BDF_GLYPHS)) + /* + * Error happened while parsing header. + */ + sprintf(msgbuf, ERRMSG2, lineno); + else + /* + * Error happened when parsing glyphs. + */ + sprintf(msgbuf, ERRMSG3, lineno); + + _bdf_add_acmsg(p.font, msgbuf, ft_strlen(msgbuf)); + } + + if (callback != 0) { + p.cb.reason = BDF_ERROR; + p.cb.errlineno = lineno; + (*callback)(&p.cb, data); + } + } else if (callback != 0) { + /* + * This forces the progress bar to always finish. + */ + p.cb.current = p.cb.total; + (*p.callback)(&p.cb, p.client_data); + } + + /* + * Free up the list used during the parsing. + */ + if (p.list.size > 0) + FT_FREE( p.list.field ); + + if (p.font != 0) { + /* + * Make sure the comments are NULL terminated if they exist. + */ + memory = p.font->memory; + + if (p.font->comments_len > 0) { + if ( FT_REALLOC ( p.font->comments , p.font->comments_len , + p.font->comments_len + 1 ) ) + return 0; + p.font->comments[p.font->comments_len] = 0; + } + + /* + * Make sure the auto-correct messages are NULL terminated if they + * exist. + */ + if (p.font->acmsgs_len > 0) { + memory = p.font->memory; + + if ( FT_REALLOC ( p.font->acmsgs , p.font->acmsgs_len , + p.font->acmsgs_len + 1 ) ) + return 0; + p.font->acmsgs[p.font->acmsgs_len] = 0; + } + } + + return p.font; +} + + +FT_LOCAL_DEF( void ) +bdf_free_font( bdf_font_t *font ) +{ + bdf_property_t *prop; + unsigned long i; + bdf_glyph_t *glyphs; + FT_Memory memory; + + if (font == 0) + return; + + memory = font->memory; + + if (font->name != 0) + FT_FREE(font->name); + + /* + * Free up the internal hash table of property names. + */ + if (font->internal) { + hash_free((hashtable *) font->internal, memory); + FT_FREE(font->internal); + } + /* + * Free up the comment info. + */ + if (font->comments_len > 0) + FT_FREE(font->comments); + + /* + * Free up the auto-correction messages. + */ + if (font->acmsgs_len > 0) + FT_FREE(font->acmsgs); + + /* + * Free up the properties. + */ + for (i = 0; i < font->props_size; i++) { + if (font->props[i].format == BDF_ATOM && font->props[i].value.atom) + FT_FREE(font->props[i].value.atom); + } + + if (font->props_size > 0 && font->props != 0) + FT_FREE(font->props); + + /* + * Free up the character info. + */ + for (i = 0, glyphs = font->glyphs; i < font->glyphs_used; i++, glyphs++) { + if (glyphs->name) + FT_FREE(glyphs->name); + if (glyphs->bytes > 0 && glyphs->bitmap != 0) + FT_FREE(glyphs->bitmap); + } + + for (i = 0, glyphs = font->unencoded; i < font->unencoded_used; + i++, glyphs++) { + if (glyphs->name) + FT_FREE(glyphs->name); + if (glyphs->bytes > 0) + FT_FREE(glyphs->bitmap); + } + + if (font->glyphs_size > 0) + FT_FREE( font->glyphs); + + if (font->unencoded_size > 0) + FT_FREE( font->unencoded); + + /* + * Free up the overflow storage if it was used. + */ + for (i = 0, glyphs = font->overflow.glyphs; i < font->overflow.glyphs_used; + i++, glyphs++) { + if (glyphs->name != 0) + FT_FREE(glyphs->name); + if (glyphs->bytes > 0) + FT_FREE( glyphs->bitmap);; + } + if (font->overflow.glyphs_size > 0) + FT_FREE(font->overflow.glyphs); + + /* bdf_cleanup */ + hash_free(&(font->proptbl),memory); + + /* + * Free up the user defined properties. + */ + for (prop = font->user_props, i = 0; i < font->nuser_props; i++, prop++) { + FT_FREE(prop->name); + if (prop->format == BDF_ATOM && prop->value.atom != 0) + FT_FREE(prop->value.atom); + } + if (font->nuser_props > 0) + FT_FREE(font->user_props); + + /*FREE( font);*/ /* XXX Fixme */ +} + + + +FT_LOCAL_DEF( bdf_property_t* ) +bdf_get_font_property( bdf_font_t* font, + char* name) +{ + hashnode hn; + + if (font == 0 || font->props_size == 0 || name == 0 || *name == 0) + return 0; + + hn = hash_lookup(name, (hashtable *) font->internal); + return (hn) ? (font->props + ((unsigned long) hn->data)) : 0; +} diff --git a/src/bdf/module.mk b/src/bdf/module.mk new file mode 100644 index 000000000..1e5a62c84 --- /dev/null +++ b/src/bdf/module.mk @@ -0,0 +1,31 @@ +# +# FreeType 2 BDF module definition +# + +# Copyright 2001 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_bdf_driver + +add_bdf_driver: + $(OPEN_DRIVER)bdf_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)bdf $(ECHO_DRIVER_DESC)bdf bitmap fonts$(ECHO_DRIVER_DONE) + diff --git a/src/bdf/rules.mk b/src/bdf/rules.mk new file mode 100644 index 000000000..9201e24ae --- /dev/null +++ b/src/bdf/rules.mk @@ -0,0 +1,80 @@ +# +# FreeType 2 bdf driver configuration rules +# + + +# Copyright (C) 2001 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. + + + + +# bdf driver directory +# +BDF_DIR := $(SRC_)bdf +BDF_DIR_ := $(BDF_DIR)$(SEP) + + +BDF_COMPILE := $(FT_COMPILE) $I$(BDF_DIR) + + +# bdf driver sources (i.e., C files) +# +BDF_DRV_SRC := $(BDF_DIR_)bdflib.c $(BDF_DIR_)bdfdriver.c + + +# bdf driver headers +# +#BDF_DRV_H := $(BDF_DRV_SRC:%.c=%.h) +BDF_DRV_H := $(BDF_DIR_)bdf.h \ + $(BDF_DIR_)bdfdriver.h + +# bdf driver object(s) +# +# BDF_DRV_OBJ_M is used during `multi' builds +# BDF_DRV_OBJ_S is used during `single' builds +# +BDF_DRV_OBJ_M := $(BDF_DRV_SRC:$(BDF_DIR_)%.c=$(OBJ_)%.$O) +BDF_DRV_OBJ_S := $(OBJ_)bdf.$O + +# bdf driver source file for single build +# +BDF_DRV_SRC_S := $(BDF_DIR_)bdf.c + + +# bdf driver - single object +# +$(BDF_DRV_OBJ_S): $(BDF_DRV_SRC_S) $(BDF_DRV_SRC) $(FREETYPE_H) $(BDF_DRV_H) + $(BDF_COMPILE) $T$@ $(BDF_DRV_SRC_S) + + +# bdf driver - multiple objects +# +$(OBJ_)%.$O: $(BDF_DIR_)%.c $(FREETYPE_H) $(BDF_DRV_H) + $(BDF_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(BDF_DRV_OBJ_S) +DRV_OBJS_M += $(BDF_DRV_OBJ_M) + +# EOF