ref: 993a8d044538e59ebaffe27d4d04f8efb979fd7c
parent: b89a42c6c554ff13f65b3161c5754de4f6a04628
author: David Turner <[email protected]>
date: Sat May 18 08:03:43 EDT 2002
adding BDF driver
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -92,6 +92,9 @@
FT_TRACE_DEF( pcfdriver )
FT_TRACE_DEF( pcfread )
+/* BDF fonts component */
+FT_TRACE_DEF( bdf )
+
/* PFR fonts component */
FT_TRACE_DEF( pfr )
--- a/src/Jamfile
+++ b/src/Jamfile
@@ -17,6 +17,7 @@
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 ;
--- /dev/null
+++ b/src/bdf/bdf.c
@@ -1,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 <ft2build.h>
+#include "bdflib.c"
+#include "bdfdriver.c"
+
+/* END */
--- /dev/null
+++ b/src/bdf/bdf.h
@@ -1,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 <string.h>
+
+#include <ft2build.h>
+#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 */
--- /dev/null
+++ b/src/bdf/bdfdriver.c
@@ -1,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 <ft2build.h>
+
+#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; n<font->glyphs_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 ; i<glyph.bytes ; i++) {
+ bitmap->buffer[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
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* getDriverClass */
+ /* */
+ /* <Description> */
+ /* 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. */
+ /* */
+ /* <Return> */
+ /* 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 */
--- /dev/null
+++ b/src/bdf/bdfdriver.h
@@ -1,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 <ft2build.h>
+#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 */
+
--- /dev/null
+++ b/src/bdf/bdferror.h
@@ -1,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 */
--- /dev/null
+++ b/src/bdf/bdflib.c
@@ -1,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 <ft2build.h>
+
+#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;
+}
--- /dev/null
+++ b/src/bdf/module.mk
@@ -1,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)
+
--- /dev/null
+++ b/src/bdf/rules.mk
@@ -1,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