1*37da2899SCharles.Forsyth /* 2*37da2899SCharles.Forsyth * Copyright 2000 Computing Research Labs, New Mexico State University 3*37da2899SCharles.Forsyth * Copyright 2001, 2002 Francesco Zappa Nardelli 4*37da2899SCharles.Forsyth * 5*37da2899SCharles.Forsyth * Permission is hereby granted, free of charge, to any person obtaining a 6*37da2899SCharles.Forsyth * copy of this software and associated documentation files (the "Software"), 7*37da2899SCharles.Forsyth * to deal in the Software without restriction, including without limitation 8*37da2899SCharles.Forsyth * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9*37da2899SCharles.Forsyth * and/or sell copies of the Software, and to permit persons to whom the 10*37da2899SCharles.Forsyth * Software is furnished to do so, subject to the following conditions: 11*37da2899SCharles.Forsyth * 12*37da2899SCharles.Forsyth * The above copyright notice and this permission notice shall be included in 13*37da2899SCharles.Forsyth * all copies or substantial portions of the Software. 14*37da2899SCharles.Forsyth * 15*37da2899SCharles.Forsyth * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*37da2899SCharles.Forsyth * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*37da2899SCharles.Forsyth * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*37da2899SCharles.Forsyth * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY 19*37da2899SCharles.Forsyth * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 20*37da2899SCharles.Forsyth * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21*37da2899SCharles.Forsyth * THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22*37da2899SCharles.Forsyth */ 23*37da2899SCharles.Forsyth 24*37da2899SCharles.Forsyth /*************************************************************************/ 25*37da2899SCharles.Forsyth /* */ 26*37da2899SCharles.Forsyth /* This file is based on bdf.c,v 1.22 2000/03/16 20:08:50 */ 27*37da2899SCharles.Forsyth /* */ 28*37da2899SCharles.Forsyth /* taken from Mark Leisher's xmbdfed package */ 29*37da2899SCharles.Forsyth /* */ 30*37da2899SCharles.Forsyth /*************************************************************************/ 31*37da2899SCharles.Forsyth 32*37da2899SCharles.Forsyth 33*37da2899SCharles.Forsyth #include <ft2build.h> 34*37da2899SCharles.Forsyth 35*37da2899SCharles.Forsyth #include FT_FREETYPE_H 36*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 37*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H 38*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H 39*37da2899SCharles.Forsyth 40*37da2899SCharles.Forsyth #include "bdf.h" 41*37da2899SCharles.Forsyth #include "bdferror.h" 42*37da2899SCharles.Forsyth 43*37da2899SCharles.Forsyth 44*37da2899SCharles.Forsyth /*************************************************************************/ 45*37da2899SCharles.Forsyth /* */ 46*37da2899SCharles.Forsyth /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 47*37da2899SCharles.Forsyth /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 48*37da2899SCharles.Forsyth /* messages during execution. */ 49*37da2899SCharles.Forsyth /* */ 50*37da2899SCharles.Forsyth #undef FT_COMPONENT 51*37da2899SCharles.Forsyth #define FT_COMPONENT trace_bdflib 52*37da2899SCharles.Forsyth 53*37da2899SCharles.Forsyth 54*37da2899SCharles.Forsyth /*************************************************************************/ 55*37da2899SCharles.Forsyth /* */ 56*37da2899SCharles.Forsyth /* Default BDF font options. */ 57*37da2899SCharles.Forsyth /* */ 58*37da2899SCharles.Forsyth /*************************************************************************/ 59*37da2899SCharles.Forsyth 60*37da2899SCharles.Forsyth 61*37da2899SCharles.Forsyth static const bdf_options_t _bdf_opts = 62*37da2899SCharles.Forsyth { 63*37da2899SCharles.Forsyth 1, /* Correct metrics. */ 64*37da2899SCharles.Forsyth 1, /* Preserve unencoded glyphs. */ 65*37da2899SCharles.Forsyth 0, /* Preserve comments. */ 66*37da2899SCharles.Forsyth BDF_PROPORTIONAL /* Default spacing. */ 67*37da2899SCharles.Forsyth }; 68*37da2899SCharles.Forsyth 69*37da2899SCharles.Forsyth 70*37da2899SCharles.Forsyth /*************************************************************************/ 71*37da2899SCharles.Forsyth /* */ 72*37da2899SCharles.Forsyth /* Builtin BDF font properties. */ 73*37da2899SCharles.Forsyth /* */ 74*37da2899SCharles.Forsyth /*************************************************************************/ 75*37da2899SCharles.Forsyth 76*37da2899SCharles.Forsyth /* List of most properties that might appear in a font. Doesn't include */ 77*37da2899SCharles.Forsyth /* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts. */ 78*37da2899SCharles.Forsyth 79*37da2899SCharles.Forsyth static const bdf_property_t _bdf_properties[] = 80*37da2899SCharles.Forsyth { 81*37da2899SCharles.Forsyth { (char *)"ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } }, 82*37da2899SCharles.Forsyth { (char *)"AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } }, 83*37da2899SCharles.Forsyth { (char *)"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } }, 84*37da2899SCharles.Forsyth { (char *)"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } }, 85*37da2899SCharles.Forsyth { (char *)"CAP_HEIGHT", BDF_INTEGER, 1, { 0 } }, 86*37da2899SCharles.Forsyth { (char *)"CHARSET_COLLECTIONS", BDF_ATOM, 1, { 0 } }, 87*37da2899SCharles.Forsyth { (char *)"CHARSET_ENCODING", BDF_ATOM, 1, { 0 } }, 88*37da2899SCharles.Forsyth { (char *)"CHARSET_REGISTRY", BDF_ATOM, 1, { 0 } }, 89*37da2899SCharles.Forsyth { (char *)"COMMENT", BDF_ATOM, 1, { 0 } }, 90*37da2899SCharles.Forsyth { (char *)"COPYRIGHT", BDF_ATOM, 1, { 0 } }, 91*37da2899SCharles.Forsyth { (char *)"DEFAULT_CHAR", BDF_CARDINAL, 1, { 0 } }, 92*37da2899SCharles.Forsyth { (char *)"DESTINATION", BDF_CARDINAL, 1, { 0 } }, 93*37da2899SCharles.Forsyth { (char *)"DEVICE_FONT_NAME", BDF_ATOM, 1, { 0 } }, 94*37da2899SCharles.Forsyth { (char *)"END_SPACE", BDF_INTEGER, 1, { 0 } }, 95*37da2899SCharles.Forsyth { (char *)"FACE_NAME", BDF_ATOM, 1, { 0 } }, 96*37da2899SCharles.Forsyth { (char *)"FAMILY_NAME", BDF_ATOM, 1, { 0 } }, 97*37da2899SCharles.Forsyth { (char *)"FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } }, 98*37da2899SCharles.Forsyth { (char *)"FONT", BDF_ATOM, 1, { 0 } }, 99*37da2899SCharles.Forsyth { (char *)"FONTNAME_REGISTRY", BDF_ATOM, 1, { 0 } }, 100*37da2899SCharles.Forsyth { (char *)"FONT_ASCENT", BDF_INTEGER, 1, { 0 } }, 101*37da2899SCharles.Forsyth { (char *)"FONT_DESCENT", BDF_INTEGER, 1, { 0 } }, 102*37da2899SCharles.Forsyth { (char *)"FOUNDRY", BDF_ATOM, 1, { 0 } }, 103*37da2899SCharles.Forsyth { (char *)"FULL_NAME", BDF_ATOM, 1, { 0 } }, 104*37da2899SCharles.Forsyth { (char *)"ITALIC_ANGLE", BDF_INTEGER, 1, { 0 } }, 105*37da2899SCharles.Forsyth { (char *)"MAX_SPACE", BDF_INTEGER, 1, { 0 } }, 106*37da2899SCharles.Forsyth { (char *)"MIN_SPACE", BDF_INTEGER, 1, { 0 } }, 107*37da2899SCharles.Forsyth { (char *)"NORM_SPACE", BDF_INTEGER, 1, { 0 } }, 108*37da2899SCharles.Forsyth { (char *)"NOTICE", BDF_ATOM, 1, { 0 } }, 109*37da2899SCharles.Forsyth { (char *)"PIXEL_SIZE", BDF_INTEGER, 1, { 0 } }, 110*37da2899SCharles.Forsyth { (char *)"POINT_SIZE", BDF_INTEGER, 1, { 0 } }, 111*37da2899SCharles.Forsyth { (char *)"QUAD_WIDTH", BDF_INTEGER, 1, { 0 } }, 112*37da2899SCharles.Forsyth { (char *)"RAW_ASCENT", BDF_INTEGER, 1, { 0 } }, 113*37da2899SCharles.Forsyth { (char *)"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } }, 114*37da2899SCharles.Forsyth { (char *)"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } }, 115*37da2899SCharles.Forsyth { (char *)"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } }, 116*37da2899SCharles.Forsyth { (char *)"RAW_CAP_HEIGHT", BDF_INTEGER, 1, { 0 } }, 117*37da2899SCharles.Forsyth { (char *)"RAW_DESCENT", BDF_INTEGER, 1, { 0 } }, 118*37da2899SCharles.Forsyth { (char *)"RAW_END_SPACE", BDF_INTEGER, 1, { 0 } }, 119*37da2899SCharles.Forsyth { (char *)"RAW_FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } }, 120*37da2899SCharles.Forsyth { (char *)"RAW_MAX_SPACE", BDF_INTEGER, 1, { 0 } }, 121*37da2899SCharles.Forsyth { (char *)"RAW_MIN_SPACE", BDF_INTEGER, 1, { 0 } }, 122*37da2899SCharles.Forsyth { (char *)"RAW_NORM_SPACE", BDF_INTEGER, 1, { 0 } }, 123*37da2899SCharles.Forsyth { (char *)"RAW_PIXEL_SIZE", BDF_INTEGER, 1, { 0 } }, 124*37da2899SCharles.Forsyth { (char *)"RAW_POINT_SIZE", BDF_INTEGER, 1, { 0 } }, 125*37da2899SCharles.Forsyth { (char *)"RAW_PIXELSIZE", BDF_INTEGER, 1, { 0 } }, 126*37da2899SCharles.Forsyth { (char *)"RAW_POINTSIZE", BDF_INTEGER, 1, { 0 } }, 127*37da2899SCharles.Forsyth { (char *)"RAW_QUAD_WIDTH", BDF_INTEGER, 1, { 0 } }, 128*37da2899SCharles.Forsyth { (char *)"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } }, 129*37da2899SCharles.Forsyth { (char *)"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } }, 130*37da2899SCharles.Forsyth { (char *)"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } }, 131*37da2899SCharles.Forsyth { (char *)"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } }, 132*37da2899SCharles.Forsyth { (char *)"RAW_SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } }, 133*37da2899SCharles.Forsyth { (char *)"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } }, 134*37da2899SCharles.Forsyth { (char *)"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } }, 135*37da2899SCharles.Forsyth { (char *)"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } }, 136*37da2899SCharles.Forsyth { (char *)"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } }, 137*37da2899SCharles.Forsyth { (char *)"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } }, 138*37da2899SCharles.Forsyth { (char *)"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } }, 139*37da2899SCharles.Forsyth { (char *)"RAW_X_HEIGHT", BDF_INTEGER, 1, { 0 } }, 140*37da2899SCharles.Forsyth { (char *)"RELATIVE_SETWIDTH", BDF_CARDINAL, 1, { 0 } }, 141*37da2899SCharles.Forsyth { (char *)"RELATIVE_WEIGHT", BDF_CARDINAL, 1, { 0 } }, 142*37da2899SCharles.Forsyth { (char *)"RESOLUTION", BDF_INTEGER, 1, { 0 } }, 143*37da2899SCharles.Forsyth { (char *)"RESOLUTION_X", BDF_CARDINAL, 1, { 0 } }, 144*37da2899SCharles.Forsyth { (char *)"RESOLUTION_Y", BDF_CARDINAL, 1, { 0 } }, 145*37da2899SCharles.Forsyth { (char *)"SETWIDTH_NAME", BDF_ATOM, 1, { 0 } }, 146*37da2899SCharles.Forsyth { (char *)"SLANT", BDF_ATOM, 1, { 0 } }, 147*37da2899SCharles.Forsyth { (char *)"SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } }, 148*37da2899SCharles.Forsyth { (char *)"SPACING", BDF_ATOM, 1, { 0 } }, 149*37da2899SCharles.Forsyth { (char *)"STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } }, 150*37da2899SCharles.Forsyth { (char *)"STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } }, 151*37da2899SCharles.Forsyth { (char *)"SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } }, 152*37da2899SCharles.Forsyth { (char *)"SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } }, 153*37da2899SCharles.Forsyth { (char *)"SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } }, 154*37da2899SCharles.Forsyth { (char *)"SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } }, 155*37da2899SCharles.Forsyth { (char *)"SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } }, 156*37da2899SCharles.Forsyth { (char *)"SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } }, 157*37da2899SCharles.Forsyth { (char *)"UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } }, 158*37da2899SCharles.Forsyth { (char *)"UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } }, 159*37da2899SCharles.Forsyth { (char *)"WEIGHT", BDF_CARDINAL, 1, { 0 } }, 160*37da2899SCharles.Forsyth { (char *)"WEIGHT_NAME", BDF_ATOM, 1, { 0 } }, 161*37da2899SCharles.Forsyth { (char *)"X_HEIGHT", BDF_INTEGER, 1, { 0 } }, 162*37da2899SCharles.Forsyth { (char *)"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1, { 0 } }, 163*37da2899SCharles.Forsyth { (char *)"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } }, 164*37da2899SCharles.Forsyth }; 165*37da2899SCharles.Forsyth 166*37da2899SCharles.Forsyth static unsigned long 167*37da2899SCharles.Forsyth _num_bdf_properties = sizeof ( _bdf_properties ) / 168*37da2899SCharles.Forsyth sizeof ( _bdf_properties[0] ); 169*37da2899SCharles.Forsyth 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth /*************************************************************************/ 172*37da2899SCharles.Forsyth /* */ 173*37da2899SCharles.Forsyth /* Hash table utilities for the properties. */ 174*37da2899SCharles.Forsyth /* */ 175*37da2899SCharles.Forsyth /*************************************************************************/ 176*37da2899SCharles.Forsyth 177*37da2899SCharles.Forsyth /* XXX: Replace this with FreeType's hash functions */ 178*37da2899SCharles.Forsyth 179*37da2899SCharles.Forsyth 180*37da2899SCharles.Forsyth #define INITIAL_HT_SIZE 241 181*37da2899SCharles.Forsyth 182*37da2899SCharles.Forsyth typedef void 183*37da2899SCharles.Forsyth (*hash_free_func)( hashnode node ); 184*37da2899SCharles.Forsyth 185*37da2899SCharles.Forsyth static hashnode* hash_bucket(char * key,hashtable * ht)186*37da2899SCharles.Forsyth hash_bucket( char* key, 187*37da2899SCharles.Forsyth hashtable* ht ) 188*37da2899SCharles.Forsyth { 189*37da2899SCharles.Forsyth char* kp = key; 190*37da2899SCharles.Forsyth unsigned long res = 0; 191*37da2899SCharles.Forsyth hashnode* bp = ht->table, *ndp; 192*37da2899SCharles.Forsyth 193*37da2899SCharles.Forsyth 194*37da2899SCharles.Forsyth /* Mocklisp hash function. */ 195*37da2899SCharles.Forsyth while ( *kp ) 196*37da2899SCharles.Forsyth res = ( res << 5 ) - res + *kp++; 197*37da2899SCharles.Forsyth 198*37da2899SCharles.Forsyth ndp = bp + ( res % ht->size ); 199*37da2899SCharles.Forsyth while ( *ndp ) 200*37da2899SCharles.Forsyth { 201*37da2899SCharles.Forsyth kp = (*ndp)->key; 202*37da2899SCharles.Forsyth if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 ) 203*37da2899SCharles.Forsyth break; 204*37da2899SCharles.Forsyth ndp--; 205*37da2899SCharles.Forsyth if ( ndp < bp ) 206*37da2899SCharles.Forsyth ndp = bp + ( ht->size - 1 ); 207*37da2899SCharles.Forsyth } 208*37da2899SCharles.Forsyth 209*37da2899SCharles.Forsyth return ndp; 210*37da2899SCharles.Forsyth } 211*37da2899SCharles.Forsyth 212*37da2899SCharles.Forsyth 213*37da2899SCharles.Forsyth static FT_Error hash_rehash(hashtable * ht,FT_Memory memory)214*37da2899SCharles.Forsyth hash_rehash( hashtable* ht, 215*37da2899SCharles.Forsyth FT_Memory memory ) 216*37da2899SCharles.Forsyth { 217*37da2899SCharles.Forsyth hashnode* obp = ht->table, *bp, *nbp; 218*37da2899SCharles.Forsyth int i, sz = ht->size; 219*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 220*37da2899SCharles.Forsyth 221*37da2899SCharles.Forsyth 222*37da2899SCharles.Forsyth ht->size <<= 1; 223*37da2899SCharles.Forsyth ht->limit = ht->size / 3; 224*37da2899SCharles.Forsyth 225*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( ht->table, ht->size ) ) 226*37da2899SCharles.Forsyth goto Exit; 227*37da2899SCharles.Forsyth FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * ht->size ); 228*37da2899SCharles.Forsyth 229*37da2899SCharles.Forsyth for ( i = 0, bp = obp; i < sz; i++, bp++ ) 230*37da2899SCharles.Forsyth { 231*37da2899SCharles.Forsyth if ( *bp ) 232*37da2899SCharles.Forsyth { 233*37da2899SCharles.Forsyth nbp = hash_bucket( (*bp)->key, ht ); 234*37da2899SCharles.Forsyth *nbp = *bp; 235*37da2899SCharles.Forsyth } 236*37da2899SCharles.Forsyth } 237*37da2899SCharles.Forsyth FT_FREE( obp ); 238*37da2899SCharles.Forsyth 239*37da2899SCharles.Forsyth Exit: 240*37da2899SCharles.Forsyth return error; 241*37da2899SCharles.Forsyth } 242*37da2899SCharles.Forsyth 243*37da2899SCharles.Forsyth 244*37da2899SCharles.Forsyth static FT_Error hash_init(hashtable * ht,FT_Memory memory)245*37da2899SCharles.Forsyth hash_init( hashtable* ht, 246*37da2899SCharles.Forsyth FT_Memory memory ) 247*37da2899SCharles.Forsyth { 248*37da2899SCharles.Forsyth int sz = INITIAL_HT_SIZE; 249*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 250*37da2899SCharles.Forsyth 251*37da2899SCharles.Forsyth 252*37da2899SCharles.Forsyth ht->size = sz; 253*37da2899SCharles.Forsyth ht->limit = sz / 3; 254*37da2899SCharles.Forsyth ht->used = 0; 255*37da2899SCharles.Forsyth 256*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( ht->table, sz ) ) 257*37da2899SCharles.Forsyth goto Exit; 258*37da2899SCharles.Forsyth FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * sz ); 259*37da2899SCharles.Forsyth 260*37da2899SCharles.Forsyth Exit: 261*37da2899SCharles.Forsyth return error; 262*37da2899SCharles.Forsyth } 263*37da2899SCharles.Forsyth 264*37da2899SCharles.Forsyth 265*37da2899SCharles.Forsyth static void hash_free(hashtable * ht,FT_Memory memory)266*37da2899SCharles.Forsyth hash_free( hashtable* ht, 267*37da2899SCharles.Forsyth FT_Memory memory ) 268*37da2899SCharles.Forsyth { 269*37da2899SCharles.Forsyth if ( ht != 0 ) 270*37da2899SCharles.Forsyth { 271*37da2899SCharles.Forsyth int i, sz = ht->size; 272*37da2899SCharles.Forsyth hashnode* bp = ht->table; 273*37da2899SCharles.Forsyth 274*37da2899SCharles.Forsyth 275*37da2899SCharles.Forsyth for ( i = 0; i < sz; i++, bp++ ) 276*37da2899SCharles.Forsyth FT_FREE( *bp ); 277*37da2899SCharles.Forsyth 278*37da2899SCharles.Forsyth FT_FREE( ht->table ); 279*37da2899SCharles.Forsyth } 280*37da2899SCharles.Forsyth } 281*37da2899SCharles.Forsyth 282*37da2899SCharles.Forsyth 283*37da2899SCharles.Forsyth static FT_Error hash_insert(char * key,void * data,hashtable * ht,FT_Memory memory)284*37da2899SCharles.Forsyth hash_insert( char* key, 285*37da2899SCharles.Forsyth void* data, 286*37da2899SCharles.Forsyth hashtable* ht, 287*37da2899SCharles.Forsyth FT_Memory memory ) 288*37da2899SCharles.Forsyth { 289*37da2899SCharles.Forsyth hashnode nn, *bp = hash_bucket( key, ht ); 290*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 291*37da2899SCharles.Forsyth 292*37da2899SCharles.Forsyth 293*37da2899SCharles.Forsyth nn = *bp; 294*37da2899SCharles.Forsyth if ( !nn ) 295*37da2899SCharles.Forsyth { 296*37da2899SCharles.Forsyth if ( FT_NEW( nn ) ) 297*37da2899SCharles.Forsyth goto Exit; 298*37da2899SCharles.Forsyth *bp = nn; 299*37da2899SCharles.Forsyth 300*37da2899SCharles.Forsyth nn->key = key; 301*37da2899SCharles.Forsyth nn->data = data; 302*37da2899SCharles.Forsyth 303*37da2899SCharles.Forsyth if ( ht->used >= ht->limit ) 304*37da2899SCharles.Forsyth { 305*37da2899SCharles.Forsyth error = hash_rehash( ht, memory ); 306*37da2899SCharles.Forsyth if ( error ) 307*37da2899SCharles.Forsyth goto Exit; 308*37da2899SCharles.Forsyth } 309*37da2899SCharles.Forsyth ht->used++; 310*37da2899SCharles.Forsyth } 311*37da2899SCharles.Forsyth else 312*37da2899SCharles.Forsyth nn->data = data; 313*37da2899SCharles.Forsyth 314*37da2899SCharles.Forsyth Exit: 315*37da2899SCharles.Forsyth return error; 316*37da2899SCharles.Forsyth } 317*37da2899SCharles.Forsyth 318*37da2899SCharles.Forsyth 319*37da2899SCharles.Forsyth static hashnode hash_lookup(char * key,hashtable * ht)320*37da2899SCharles.Forsyth hash_lookup( char* key, 321*37da2899SCharles.Forsyth hashtable* ht ) 322*37da2899SCharles.Forsyth { 323*37da2899SCharles.Forsyth hashnode *np = hash_bucket( key, ht ); 324*37da2899SCharles.Forsyth 325*37da2899SCharles.Forsyth 326*37da2899SCharles.Forsyth return *np; 327*37da2899SCharles.Forsyth } 328*37da2899SCharles.Forsyth 329*37da2899SCharles.Forsyth 330*37da2899SCharles.Forsyth /*************************************************************************/ 331*37da2899SCharles.Forsyth /* */ 332*37da2899SCharles.Forsyth /* Utility types and functions. */ 333*37da2899SCharles.Forsyth /* */ 334*37da2899SCharles.Forsyth /*************************************************************************/ 335*37da2899SCharles.Forsyth 336*37da2899SCharles.Forsyth 337*37da2899SCharles.Forsyth /* Function type for parsing lines of a BDF font. */ 338*37da2899SCharles.Forsyth 339*37da2899SCharles.Forsyth typedef FT_Error 340*37da2899SCharles.Forsyth (*_bdf_line_func_t)( char* line, 341*37da2899SCharles.Forsyth unsigned long linelen, 342*37da2899SCharles.Forsyth unsigned long lineno, 343*37da2899SCharles.Forsyth void* call_data, 344*37da2899SCharles.Forsyth void* client_data ); 345*37da2899SCharles.Forsyth 346*37da2899SCharles.Forsyth 347*37da2899SCharles.Forsyth /* List structure for splitting lines into fields. */ 348*37da2899SCharles.Forsyth 349*37da2899SCharles.Forsyth typedef struct _bdf_list_t_ 350*37da2899SCharles.Forsyth { 351*37da2899SCharles.Forsyth char** field; 352*37da2899SCharles.Forsyth unsigned long size; 353*37da2899SCharles.Forsyth unsigned long used; 354*37da2899SCharles.Forsyth 355*37da2899SCharles.Forsyth } _bdf_list_t; 356*37da2899SCharles.Forsyth 357*37da2899SCharles.Forsyth 358*37da2899SCharles.Forsyth /* Structure used while loading BDF fonts. */ 359*37da2899SCharles.Forsyth 360*37da2899SCharles.Forsyth typedef struct _bdf_parse_t_ 361*37da2899SCharles.Forsyth { 362*37da2899SCharles.Forsyth unsigned long flags; 363*37da2899SCharles.Forsyth unsigned long cnt; 364*37da2899SCharles.Forsyth unsigned long row; 365*37da2899SCharles.Forsyth 366*37da2899SCharles.Forsyth short minlb; 367*37da2899SCharles.Forsyth short maxlb; 368*37da2899SCharles.Forsyth short maxrb; 369*37da2899SCharles.Forsyth short maxas; 370*37da2899SCharles.Forsyth short maxds; 371*37da2899SCharles.Forsyth 372*37da2899SCharles.Forsyth short rbearing; 373*37da2899SCharles.Forsyth 374*37da2899SCharles.Forsyth char* glyph_name; 375*37da2899SCharles.Forsyth long glyph_enc; 376*37da2899SCharles.Forsyth 377*37da2899SCharles.Forsyth bdf_font_t* font; 378*37da2899SCharles.Forsyth bdf_options_t* opts; 379*37da2899SCharles.Forsyth 380*37da2899SCharles.Forsyth unsigned long have[2048]; 381*37da2899SCharles.Forsyth _bdf_list_t list; 382*37da2899SCharles.Forsyth 383*37da2899SCharles.Forsyth FT_Memory memory; 384*37da2899SCharles.Forsyth 385*37da2899SCharles.Forsyth } _bdf_parse_t; 386*37da2899SCharles.Forsyth 387*37da2899SCharles.Forsyth 388*37da2899SCharles.Forsyth #define setsbit( m, cc ) ( m[(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) ) 389*37da2899SCharles.Forsyth #define sbitset( m, cc ) ( m[(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) ) 390*37da2899SCharles.Forsyth 391*37da2899SCharles.Forsyth 392*37da2899SCharles.Forsyth /* An empty string for empty fields. */ 393*37da2899SCharles.Forsyth 394*37da2899SCharles.Forsyth static char empty[1] = { 0 }; /* XXX eliminate this */ 395*37da2899SCharles.Forsyth 396*37da2899SCharles.Forsyth 397*37da2899SCharles.Forsyth /* Assume the line is NULL-terminated and that the `list' parameter */ 398*37da2899SCharles.Forsyth /* was initialized the first time it was used. */ 399*37da2899SCharles.Forsyth 400*37da2899SCharles.Forsyth static FT_Error _bdf_split(char * separators,char * line,unsigned long linelen,_bdf_list_t * list,FT_Memory memory)401*37da2899SCharles.Forsyth _bdf_split( char* separators, 402*37da2899SCharles.Forsyth char* line, 403*37da2899SCharles.Forsyth unsigned long linelen, 404*37da2899SCharles.Forsyth _bdf_list_t* list, 405*37da2899SCharles.Forsyth FT_Memory memory ) 406*37da2899SCharles.Forsyth { 407*37da2899SCharles.Forsyth int mult, final_empty; 408*37da2899SCharles.Forsyth char *sp, *ep, *end; 409*37da2899SCharles.Forsyth char seps[32]; 410*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 411*37da2899SCharles.Forsyth 412*37da2899SCharles.Forsyth 413*37da2899SCharles.Forsyth /* Initialize the list. */ 414*37da2899SCharles.Forsyth list->used = 0; 415*37da2899SCharles.Forsyth 416*37da2899SCharles.Forsyth /* If the line is empty, then simply return. */ 417*37da2899SCharles.Forsyth if ( linelen == 0 || line[0] == 0 ) 418*37da2899SCharles.Forsyth goto Exit; 419*37da2899SCharles.Forsyth 420*37da2899SCharles.Forsyth /* In the original code, if the `separators' parameter is NULL or */ 421*37da2899SCharles.Forsyth /* empty, the list is split into individual bytes. We don't need */ 422*37da2899SCharles.Forsyth /* this, so an error is signaled. */ 423*37da2899SCharles.Forsyth if ( separators == 0 || *separators == 0 ) 424*37da2899SCharles.Forsyth { 425*37da2899SCharles.Forsyth error = BDF_Err_Invalid_Argument; 426*37da2899SCharles.Forsyth goto Exit; 427*37da2899SCharles.Forsyth } 428*37da2899SCharles.Forsyth 429*37da2899SCharles.Forsyth /* Prepare the separator bitmap. */ 430*37da2899SCharles.Forsyth FT_MEM_ZERO( seps, 32 ); 431*37da2899SCharles.Forsyth 432*37da2899SCharles.Forsyth /* If the very last character of the separator string is a plus, then */ 433*37da2899SCharles.Forsyth /* set the `mult' flag to indicate that multiple separators should be */ 434*37da2899SCharles.Forsyth /* collapsed into one. */ 435*37da2899SCharles.Forsyth for ( mult = 0, sp = separators; sp && *sp; sp++ ) 436*37da2899SCharles.Forsyth { 437*37da2899SCharles.Forsyth if ( *sp == '+' && *( sp + 1 ) == 0 ) 438*37da2899SCharles.Forsyth mult = 1; 439*37da2899SCharles.Forsyth else 440*37da2899SCharles.Forsyth setsbit( seps, *sp ); 441*37da2899SCharles.Forsyth } 442*37da2899SCharles.Forsyth 443*37da2899SCharles.Forsyth /* Break the line up into fields. */ 444*37da2899SCharles.Forsyth for ( final_empty = 0, sp = ep = line, end = sp + linelen; 445*37da2899SCharles.Forsyth sp < end && *sp; ) 446*37da2899SCharles.Forsyth { 447*37da2899SCharles.Forsyth /* Collect everything that is not a separator. */ 448*37da2899SCharles.Forsyth for ( ; *ep && !sbitset( seps, *ep ); ep++ ) 449*37da2899SCharles.Forsyth ; 450*37da2899SCharles.Forsyth 451*37da2899SCharles.Forsyth /* Resize the list if necessary. */ 452*37da2899SCharles.Forsyth if ( list->used == list->size ) 453*37da2899SCharles.Forsyth { 454*37da2899SCharles.Forsyth if ( list->size == 0 ) 455*37da2899SCharles.Forsyth { 456*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( list->field, 5 ) ) 457*37da2899SCharles.Forsyth goto Exit; 458*37da2899SCharles.Forsyth } 459*37da2899SCharles.Forsyth else 460*37da2899SCharles.Forsyth { 461*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY ( list->field , 462*37da2899SCharles.Forsyth list->size, 463*37da2899SCharles.Forsyth list->size + 5 ) ) 464*37da2899SCharles.Forsyth goto Exit; 465*37da2899SCharles.Forsyth } 466*37da2899SCharles.Forsyth 467*37da2899SCharles.Forsyth list->size += 5; 468*37da2899SCharles.Forsyth } 469*37da2899SCharles.Forsyth 470*37da2899SCharles.Forsyth /* Assign the field appropriately. */ 471*37da2899SCharles.Forsyth list->field[list->used++] = ( ep > sp ) ? sp : empty; 472*37da2899SCharles.Forsyth 473*37da2899SCharles.Forsyth sp = ep; 474*37da2899SCharles.Forsyth 475*37da2899SCharles.Forsyth if ( mult ) 476*37da2899SCharles.Forsyth { 477*37da2899SCharles.Forsyth /* If multiple separators should be collapsed, do it now by */ 478*37da2899SCharles.Forsyth /* setting all the separator characters to 0. */ 479*37da2899SCharles.Forsyth for ( ; *ep && sbitset( seps, *ep ); ep++ ) 480*37da2899SCharles.Forsyth *ep = 0; 481*37da2899SCharles.Forsyth } 482*37da2899SCharles.Forsyth else if ( *ep != 0 ) 483*37da2899SCharles.Forsyth /* Don't collapse multiple separators by making them 0, so just */ 484*37da2899SCharles.Forsyth /* make the one encountered 0. */ 485*37da2899SCharles.Forsyth *ep++ = 0; 486*37da2899SCharles.Forsyth 487*37da2899SCharles.Forsyth final_empty = ( ep > sp && *ep == 0 ); 488*37da2899SCharles.Forsyth sp = ep; 489*37da2899SCharles.Forsyth } 490*37da2899SCharles.Forsyth 491*37da2899SCharles.Forsyth /* Finally, NULL-terminate the list. */ 492*37da2899SCharles.Forsyth if ( list->used + final_empty + 1 >= list->size ) 493*37da2899SCharles.Forsyth { 494*37da2899SCharles.Forsyth if ( list->used == list->size ) 495*37da2899SCharles.Forsyth { 496*37da2899SCharles.Forsyth if ( list->size == 0 ) 497*37da2899SCharles.Forsyth { 498*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( list->field, 5 ) ) 499*37da2899SCharles.Forsyth goto Exit; 500*37da2899SCharles.Forsyth } 501*37da2899SCharles.Forsyth else 502*37da2899SCharles.Forsyth { 503*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( list->field, 504*37da2899SCharles.Forsyth list->size, 505*37da2899SCharles.Forsyth list->size + 5 ) ) 506*37da2899SCharles.Forsyth goto Exit; 507*37da2899SCharles.Forsyth } 508*37da2899SCharles.Forsyth 509*37da2899SCharles.Forsyth list->size += 5; 510*37da2899SCharles.Forsyth } 511*37da2899SCharles.Forsyth } 512*37da2899SCharles.Forsyth 513*37da2899SCharles.Forsyth if ( final_empty ) 514*37da2899SCharles.Forsyth list->field[list->used++] = empty; 515*37da2899SCharles.Forsyth 516*37da2899SCharles.Forsyth if ( list->used == list->size ) 517*37da2899SCharles.Forsyth { 518*37da2899SCharles.Forsyth if ( list->size == 0 ) 519*37da2899SCharles.Forsyth { 520*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( list->field, 5 ) ) 521*37da2899SCharles.Forsyth goto Exit; 522*37da2899SCharles.Forsyth } 523*37da2899SCharles.Forsyth else 524*37da2899SCharles.Forsyth { 525*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( list->field, 526*37da2899SCharles.Forsyth list->size, 527*37da2899SCharles.Forsyth list->size + 5 ) ) 528*37da2899SCharles.Forsyth goto Exit; 529*37da2899SCharles.Forsyth } 530*37da2899SCharles.Forsyth 531*37da2899SCharles.Forsyth list->size += 5; 532*37da2899SCharles.Forsyth } 533*37da2899SCharles.Forsyth 534*37da2899SCharles.Forsyth list->field[list->used] = 0; 535*37da2899SCharles.Forsyth 536*37da2899SCharles.Forsyth Exit: 537*37da2899SCharles.Forsyth return error; 538*37da2899SCharles.Forsyth } 539*37da2899SCharles.Forsyth 540*37da2899SCharles.Forsyth 541*37da2899SCharles.Forsyth static void _bdf_shift(unsigned long n,_bdf_list_t * list)542*37da2899SCharles.Forsyth _bdf_shift( unsigned long n, 543*37da2899SCharles.Forsyth _bdf_list_t* list ) 544*37da2899SCharles.Forsyth { 545*37da2899SCharles.Forsyth unsigned long i, u; 546*37da2899SCharles.Forsyth 547*37da2899SCharles.Forsyth 548*37da2899SCharles.Forsyth if ( list == 0 || list->used == 0 || n == 0 ) 549*37da2899SCharles.Forsyth return; 550*37da2899SCharles.Forsyth 551*37da2899SCharles.Forsyth if ( n >= list->used ) 552*37da2899SCharles.Forsyth { 553*37da2899SCharles.Forsyth list->used = 0; 554*37da2899SCharles.Forsyth return; 555*37da2899SCharles.Forsyth } 556*37da2899SCharles.Forsyth 557*37da2899SCharles.Forsyth for ( u = n, i = 0; u < list->used; i++, u++ ) 558*37da2899SCharles.Forsyth list->field[i] = list->field[u]; 559*37da2899SCharles.Forsyth list->used -= n; 560*37da2899SCharles.Forsyth } 561*37da2899SCharles.Forsyth 562*37da2899SCharles.Forsyth 563*37da2899SCharles.Forsyth static char * _bdf_join(int c,unsigned long * len,_bdf_list_t * list)564*37da2899SCharles.Forsyth _bdf_join( int c, 565*37da2899SCharles.Forsyth unsigned long* len, 566*37da2899SCharles.Forsyth _bdf_list_t* list ) 567*37da2899SCharles.Forsyth { 568*37da2899SCharles.Forsyth unsigned long i, j; 569*37da2899SCharles.Forsyth char *fp, *dp; 570*37da2899SCharles.Forsyth 571*37da2899SCharles.Forsyth 572*37da2899SCharles.Forsyth if ( list == 0 || list->used == 0 ) 573*37da2899SCharles.Forsyth return 0; 574*37da2899SCharles.Forsyth 575*37da2899SCharles.Forsyth *len = 0; 576*37da2899SCharles.Forsyth 577*37da2899SCharles.Forsyth dp = list->field[0]; 578*37da2899SCharles.Forsyth for ( i = j = 0; i < list->used; i++ ) 579*37da2899SCharles.Forsyth { 580*37da2899SCharles.Forsyth fp = list->field[i]; 581*37da2899SCharles.Forsyth while ( *fp ) 582*37da2899SCharles.Forsyth dp[j++] = *fp++; 583*37da2899SCharles.Forsyth 584*37da2899SCharles.Forsyth if ( i + 1 < list->used ) 585*37da2899SCharles.Forsyth dp[j++] = (char)c; 586*37da2899SCharles.Forsyth } 587*37da2899SCharles.Forsyth dp[j] = 0; 588*37da2899SCharles.Forsyth 589*37da2899SCharles.Forsyth *len = j; 590*37da2899SCharles.Forsyth return dp; 591*37da2899SCharles.Forsyth } 592*37da2899SCharles.Forsyth 593*37da2899SCharles.Forsyth 594*37da2899SCharles.Forsyth /* High speed file reader that passes each line to a callback. */ 595*37da2899SCharles.Forsyth static FT_Error bdf_internal_readstream(FT_Stream stream,char * buffer,int count,int * read_bytes)596*37da2899SCharles.Forsyth bdf_internal_readstream( FT_Stream stream, 597*37da2899SCharles.Forsyth char* buffer, 598*37da2899SCharles.Forsyth int count, 599*37da2899SCharles.Forsyth int *read_bytes ) 600*37da2899SCharles.Forsyth { 601*37da2899SCharles.Forsyth int rbytes; 602*37da2899SCharles.Forsyth unsigned long pos = stream->pos; 603*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 604*37da2899SCharles.Forsyth 605*37da2899SCharles.Forsyth 606*37da2899SCharles.Forsyth if ( pos > stream->size ) 607*37da2899SCharles.Forsyth { 608*37da2899SCharles.Forsyth FT_ERROR(( "bdf_internal_readstream:" )); 609*37da2899SCharles.Forsyth FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", 610*37da2899SCharles.Forsyth pos, stream->size )); 611*37da2899SCharles.Forsyth error = BDF_Err_Invalid_Stream_Operation; 612*37da2899SCharles.Forsyth goto Exit; 613*37da2899SCharles.Forsyth } 614*37da2899SCharles.Forsyth 615*37da2899SCharles.Forsyth if ( stream->read ) 616*37da2899SCharles.Forsyth rbytes = stream->read( stream, pos, 617*37da2899SCharles.Forsyth (unsigned char *)buffer, count ); 618*37da2899SCharles.Forsyth else 619*37da2899SCharles.Forsyth { 620*37da2899SCharles.Forsyth rbytes = stream->size - pos; 621*37da2899SCharles.Forsyth if ( rbytes > count ) 622*37da2899SCharles.Forsyth rbytes = count; 623*37da2899SCharles.Forsyth 624*37da2899SCharles.Forsyth FT_MEM_COPY( buffer, stream->base + pos, rbytes ); 625*37da2899SCharles.Forsyth } 626*37da2899SCharles.Forsyth 627*37da2899SCharles.Forsyth stream->pos = pos + rbytes; 628*37da2899SCharles.Forsyth 629*37da2899SCharles.Forsyth *read_bytes = rbytes; 630*37da2899SCharles.Forsyth 631*37da2899SCharles.Forsyth Exit: 632*37da2899SCharles.Forsyth return error; 633*37da2899SCharles.Forsyth } 634*37da2899SCharles.Forsyth 635*37da2899SCharles.Forsyth 636*37da2899SCharles.Forsyth static FT_Error _bdf_readstream(FT_Stream stream,_bdf_line_func_t callback,void * client_data,unsigned long * lno)637*37da2899SCharles.Forsyth _bdf_readstream( FT_Stream stream, 638*37da2899SCharles.Forsyth _bdf_line_func_t callback, 639*37da2899SCharles.Forsyth void* client_data, 640*37da2899SCharles.Forsyth unsigned long *lno ) 641*37da2899SCharles.Forsyth { 642*37da2899SCharles.Forsyth _bdf_line_func_t cb; 643*37da2899SCharles.Forsyth unsigned long lineno; 644*37da2899SCharles.Forsyth int n, res, done, refill, bytes, hold; 645*37da2899SCharles.Forsyth char *ls, *le, *pp, *pe, *hp; 646*37da2899SCharles.Forsyth char *buf = 0; 647*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 648*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 649*37da2899SCharles.Forsyth 650*37da2899SCharles.Forsyth 651*37da2899SCharles.Forsyth if ( callback == 0 ) 652*37da2899SCharles.Forsyth { 653*37da2899SCharles.Forsyth error = BDF_Err_Invalid_Argument; 654*37da2899SCharles.Forsyth goto Exit; 655*37da2899SCharles.Forsyth } 656*37da2899SCharles.Forsyth 657*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( buf, 65536L ) ) 658*37da2899SCharles.Forsyth goto Exit; 659*37da2899SCharles.Forsyth 660*37da2899SCharles.Forsyth cb = callback; 661*37da2899SCharles.Forsyth lineno = 1; 662*37da2899SCharles.Forsyth buf[0] = 0; 663*37da2899SCharles.Forsyth 664*37da2899SCharles.Forsyth res = done = 0; 665*37da2899SCharles.Forsyth pp = ls = le = buf; 666*37da2899SCharles.Forsyth 667*37da2899SCharles.Forsyth bytes = 65536L; 668*37da2899SCharles.Forsyth 669*37da2899SCharles.Forsyth while ( !done ) 670*37da2899SCharles.Forsyth { 671*37da2899SCharles.Forsyth error = bdf_internal_readstream( stream, pp, bytes, &n ); 672*37da2899SCharles.Forsyth if ( error ) 673*37da2899SCharles.Forsyth goto Exit; 674*37da2899SCharles.Forsyth 675*37da2899SCharles.Forsyth if ( n == 0 ) 676*37da2899SCharles.Forsyth break; 677*37da2899SCharles.Forsyth 678*37da2899SCharles.Forsyth /* Determine the new end of the buffer pages. */ 679*37da2899SCharles.Forsyth pe = pp + n; 680*37da2899SCharles.Forsyth 681*37da2899SCharles.Forsyth for ( refill = 0; done == 0 && refill == 0; ) 682*37da2899SCharles.Forsyth { 683*37da2899SCharles.Forsyth while ( le < pe && *le != '\n' && *le != '\r' ) 684*37da2899SCharles.Forsyth le++; 685*37da2899SCharles.Forsyth 686*37da2899SCharles.Forsyth if ( le == pe ) 687*37da2899SCharles.Forsyth { 688*37da2899SCharles.Forsyth /* Hit the end of the last page in the buffer. Need to find */ 689*37da2899SCharles.Forsyth /* out how many pages to shift and how many pages need to be */ 690*37da2899SCharles.Forsyth /* read in. Adjust the line start and end pointers down to */ 691*37da2899SCharles.Forsyth /* point to the right places in the pages. */ 692*37da2899SCharles.Forsyth 693*37da2899SCharles.Forsyth pp = buf + ( ( ( ls - buf ) >> 13 ) << 13 ); 694*37da2899SCharles.Forsyth n = pp - buf; 695*37da2899SCharles.Forsyth ls -= n; 696*37da2899SCharles.Forsyth le -= n; 697*37da2899SCharles.Forsyth n = pe - pp; 698*37da2899SCharles.Forsyth 699*37da2899SCharles.Forsyth FT_MEM_COPY( buf, pp, n ); 700*37da2899SCharles.Forsyth 701*37da2899SCharles.Forsyth pp = buf + n; 702*37da2899SCharles.Forsyth bytes = 65536L - n; 703*37da2899SCharles.Forsyth refill = 1; 704*37da2899SCharles.Forsyth } 705*37da2899SCharles.Forsyth else 706*37da2899SCharles.Forsyth { 707*37da2899SCharles.Forsyth /* Temporarily NULL-terminate the line. */ 708*37da2899SCharles.Forsyth hp = le; 709*37da2899SCharles.Forsyth hold = *le; 710*37da2899SCharles.Forsyth *le = 0; 711*37da2899SCharles.Forsyth 712*37da2899SCharles.Forsyth /* XXX: Use encoding independent value for 0x1a */ 713*37da2899SCharles.Forsyth if ( *ls != '#' && *ls != 0x1a && 714*37da2899SCharles.Forsyth le > ls && 715*37da2899SCharles.Forsyth ( error = (*cb)( ls, le - ls, lineno, (void *)&cb, 716*37da2899SCharles.Forsyth client_data ) ) != BDF_Err_Ok ) 717*37da2899SCharles.Forsyth done = 1; 718*37da2899SCharles.Forsyth else 719*37da2899SCharles.Forsyth { 720*37da2899SCharles.Forsyth ls = ++le; 721*37da2899SCharles.Forsyth /* Handle the case of DOS crlf sequences. */ 722*37da2899SCharles.Forsyth if ( le < pe && hold == '\n' && *le =='\r' ) 723*37da2899SCharles.Forsyth ls = ++le; 724*37da2899SCharles.Forsyth } 725*37da2899SCharles.Forsyth 726*37da2899SCharles.Forsyth /* Increment the line number. */ 727*37da2899SCharles.Forsyth lineno++; 728*37da2899SCharles.Forsyth 729*37da2899SCharles.Forsyth /* Restore the character at the end of the line. */ 730*37da2899SCharles.Forsyth *hp = (char)hold; 731*37da2899SCharles.Forsyth } 732*37da2899SCharles.Forsyth } 733*37da2899SCharles.Forsyth } 734*37da2899SCharles.Forsyth 735*37da2899SCharles.Forsyth *lno = lineno; 736*37da2899SCharles.Forsyth 737*37da2899SCharles.Forsyth Exit: 738*37da2899SCharles.Forsyth FT_FREE( buf ); 739*37da2899SCharles.Forsyth return error; 740*37da2899SCharles.Forsyth } 741*37da2899SCharles.Forsyth 742*37da2899SCharles.Forsyth 743*37da2899SCharles.Forsyth /* XXX: make this work with EBCDIC also */ 744*37da2899SCharles.Forsyth 745*37da2899SCharles.Forsyth static const unsigned char a2i[128] = 746*37da2899SCharles.Forsyth { 747*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 748*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 749*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 750*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 751*37da2899SCharles.Forsyth 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 752*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 753*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 754*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 755*37da2899SCharles.Forsyth 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 756*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 757*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 758*37da2899SCharles.Forsyth }; 759*37da2899SCharles.Forsyth 760*37da2899SCharles.Forsyth static const unsigned char odigits[32] = 761*37da2899SCharles.Forsyth { 762*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 763*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 764*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 765*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 766*37da2899SCharles.Forsyth }; 767*37da2899SCharles.Forsyth 768*37da2899SCharles.Forsyth static const unsigned char ddigits[32] = 769*37da2899SCharles.Forsyth { 770*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 771*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 772*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 773*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 774*37da2899SCharles.Forsyth }; 775*37da2899SCharles.Forsyth 776*37da2899SCharles.Forsyth static const unsigned char hdigits[32] = 777*37da2899SCharles.Forsyth { 778*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 779*37da2899SCharles.Forsyth 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 780*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 781*37da2899SCharles.Forsyth 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 782*37da2899SCharles.Forsyth }; 783*37da2899SCharles.Forsyth 784*37da2899SCharles.Forsyth 785*37da2899SCharles.Forsyth #define isdigok( m, d ) (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) ) 786*37da2899SCharles.Forsyth 787*37da2899SCharles.Forsyth 788*37da2899SCharles.Forsyth /* Routine to convert an ASCII string into an unsigned long integer. */ 789*37da2899SCharles.Forsyth static unsigned long _bdf_atoul(char * s,char ** end,int base)790*37da2899SCharles.Forsyth _bdf_atoul( char* s, 791*37da2899SCharles.Forsyth char** end, 792*37da2899SCharles.Forsyth int base ) 793*37da2899SCharles.Forsyth { 794*37da2899SCharles.Forsyth unsigned long v; 795*37da2899SCharles.Forsyth const unsigned char* dmap; 796*37da2899SCharles.Forsyth 797*37da2899SCharles.Forsyth 798*37da2899SCharles.Forsyth if ( s == 0 || *s == 0 ) 799*37da2899SCharles.Forsyth return 0; 800*37da2899SCharles.Forsyth 801*37da2899SCharles.Forsyth /* Make sure the radix is something recognizable. Default to 10. */ 802*37da2899SCharles.Forsyth switch ( base ) 803*37da2899SCharles.Forsyth { 804*37da2899SCharles.Forsyth case 8: 805*37da2899SCharles.Forsyth dmap = odigits; 806*37da2899SCharles.Forsyth break; 807*37da2899SCharles.Forsyth case 16: 808*37da2899SCharles.Forsyth dmap = hdigits; 809*37da2899SCharles.Forsyth break; 810*37da2899SCharles.Forsyth default: 811*37da2899SCharles.Forsyth base = 10; 812*37da2899SCharles.Forsyth dmap = ddigits; 813*37da2899SCharles.Forsyth break; 814*37da2899SCharles.Forsyth } 815*37da2899SCharles.Forsyth 816*37da2899SCharles.Forsyth /* Check for the special hex prefix. */ 817*37da2899SCharles.Forsyth if ( *s == '0' && 818*37da2899SCharles.Forsyth ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) ) 819*37da2899SCharles.Forsyth { 820*37da2899SCharles.Forsyth base = 16; 821*37da2899SCharles.Forsyth dmap = hdigits; 822*37da2899SCharles.Forsyth s += 2; 823*37da2899SCharles.Forsyth } 824*37da2899SCharles.Forsyth 825*37da2899SCharles.Forsyth for ( v = 0; isdigok( dmap, *s ); s++ ) 826*37da2899SCharles.Forsyth v = v * base + a2i[(int)*s]; 827*37da2899SCharles.Forsyth 828*37da2899SCharles.Forsyth if ( end != 0 ) 829*37da2899SCharles.Forsyth *end = s; 830*37da2899SCharles.Forsyth 831*37da2899SCharles.Forsyth return v; 832*37da2899SCharles.Forsyth } 833*37da2899SCharles.Forsyth 834*37da2899SCharles.Forsyth 835*37da2899SCharles.Forsyth /* Routine to convert an ASCII string into an signed long integer. */ 836*37da2899SCharles.Forsyth static long _bdf_atol(char * s,char ** end,int base)837*37da2899SCharles.Forsyth _bdf_atol( char* s, 838*37da2899SCharles.Forsyth char** end, 839*37da2899SCharles.Forsyth int base ) 840*37da2899SCharles.Forsyth { 841*37da2899SCharles.Forsyth long v, neg; 842*37da2899SCharles.Forsyth const unsigned char* dmap; 843*37da2899SCharles.Forsyth 844*37da2899SCharles.Forsyth 845*37da2899SCharles.Forsyth if ( s == 0 || *s == 0 ) 846*37da2899SCharles.Forsyth return 0; 847*37da2899SCharles.Forsyth 848*37da2899SCharles.Forsyth /* Make sure the radix is something recognizable. Default to 10. */ 849*37da2899SCharles.Forsyth switch ( base ) 850*37da2899SCharles.Forsyth { 851*37da2899SCharles.Forsyth case 8: 852*37da2899SCharles.Forsyth dmap = odigits; 853*37da2899SCharles.Forsyth break; 854*37da2899SCharles.Forsyth case 16: 855*37da2899SCharles.Forsyth dmap = hdigits; 856*37da2899SCharles.Forsyth break; 857*37da2899SCharles.Forsyth default: 858*37da2899SCharles.Forsyth base = 10; 859*37da2899SCharles.Forsyth dmap = ddigits; 860*37da2899SCharles.Forsyth break; 861*37da2899SCharles.Forsyth } 862*37da2899SCharles.Forsyth 863*37da2899SCharles.Forsyth /* Check for a minus sign. */ 864*37da2899SCharles.Forsyth neg = 0; 865*37da2899SCharles.Forsyth if ( *s == '-' ) 866*37da2899SCharles.Forsyth { 867*37da2899SCharles.Forsyth s++; 868*37da2899SCharles.Forsyth neg = 1; 869*37da2899SCharles.Forsyth } 870*37da2899SCharles.Forsyth 871*37da2899SCharles.Forsyth /* Check for the special hex prefix. */ 872*37da2899SCharles.Forsyth if ( *s == '0' && 873*37da2899SCharles.Forsyth ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) ) 874*37da2899SCharles.Forsyth { 875*37da2899SCharles.Forsyth base = 16; 876*37da2899SCharles.Forsyth dmap = hdigits; 877*37da2899SCharles.Forsyth s += 2; 878*37da2899SCharles.Forsyth } 879*37da2899SCharles.Forsyth 880*37da2899SCharles.Forsyth for ( v = 0; isdigok( dmap, *s ); s++ ) 881*37da2899SCharles.Forsyth v = v * base + a2i[(int)*s]; 882*37da2899SCharles.Forsyth 883*37da2899SCharles.Forsyth if ( end != 0 ) 884*37da2899SCharles.Forsyth *end = s; 885*37da2899SCharles.Forsyth 886*37da2899SCharles.Forsyth return ( !neg ) ? v : -v; 887*37da2899SCharles.Forsyth } 888*37da2899SCharles.Forsyth 889*37da2899SCharles.Forsyth 890*37da2899SCharles.Forsyth /* Routine to convert an ASCII string into an signed short integer. */ 891*37da2899SCharles.Forsyth static short _bdf_atos(char * s,char ** end,int base)892*37da2899SCharles.Forsyth _bdf_atos( char* s, 893*37da2899SCharles.Forsyth char** end, 894*37da2899SCharles.Forsyth int base ) 895*37da2899SCharles.Forsyth { 896*37da2899SCharles.Forsyth short v, neg; 897*37da2899SCharles.Forsyth const unsigned char* dmap; 898*37da2899SCharles.Forsyth 899*37da2899SCharles.Forsyth 900*37da2899SCharles.Forsyth if ( s == 0 || *s == 0 ) 901*37da2899SCharles.Forsyth return 0; 902*37da2899SCharles.Forsyth 903*37da2899SCharles.Forsyth /* Make sure the radix is something recognizable. Default to 10. */ 904*37da2899SCharles.Forsyth switch ( base ) 905*37da2899SCharles.Forsyth { 906*37da2899SCharles.Forsyth case 8: 907*37da2899SCharles.Forsyth dmap = odigits; 908*37da2899SCharles.Forsyth break; 909*37da2899SCharles.Forsyth case 16: 910*37da2899SCharles.Forsyth dmap = hdigits; 911*37da2899SCharles.Forsyth break; 912*37da2899SCharles.Forsyth default: 913*37da2899SCharles.Forsyth base = 10; 914*37da2899SCharles.Forsyth dmap = ddigits; 915*37da2899SCharles.Forsyth break; 916*37da2899SCharles.Forsyth } 917*37da2899SCharles.Forsyth 918*37da2899SCharles.Forsyth /* Check for a minus. */ 919*37da2899SCharles.Forsyth neg = 0; 920*37da2899SCharles.Forsyth if ( *s == '-' ) 921*37da2899SCharles.Forsyth { 922*37da2899SCharles.Forsyth s++; 923*37da2899SCharles.Forsyth neg = 1; 924*37da2899SCharles.Forsyth } 925*37da2899SCharles.Forsyth 926*37da2899SCharles.Forsyth /* Check for the special hex prefix. */ 927*37da2899SCharles.Forsyth if ( *s == '0' && 928*37da2899SCharles.Forsyth ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) ) 929*37da2899SCharles.Forsyth { 930*37da2899SCharles.Forsyth base = 16; 931*37da2899SCharles.Forsyth dmap = hdigits; 932*37da2899SCharles.Forsyth s += 2; 933*37da2899SCharles.Forsyth } 934*37da2899SCharles.Forsyth 935*37da2899SCharles.Forsyth for ( v = 0; isdigok( dmap, *s ); s++ ) 936*37da2899SCharles.Forsyth v = (short)( v * base + a2i[(int)*s] ); 937*37da2899SCharles.Forsyth 938*37da2899SCharles.Forsyth if ( end != 0 ) 939*37da2899SCharles.Forsyth *end = s; 940*37da2899SCharles.Forsyth 941*37da2899SCharles.Forsyth return (short)( ( !neg ) ? v : -v ); 942*37da2899SCharles.Forsyth } 943*37da2899SCharles.Forsyth 944*37da2899SCharles.Forsyth 945*37da2899SCharles.Forsyth /* Routine to compare two glyphs by encoding so they can be sorted. */ 946*37da2899SCharles.Forsyth static int by_encoding(const void * a,const void * b)947*37da2899SCharles.Forsyth by_encoding( const void* a, 948*37da2899SCharles.Forsyth const void* b ) 949*37da2899SCharles.Forsyth { 950*37da2899SCharles.Forsyth bdf_glyph_t *c1, *c2; 951*37da2899SCharles.Forsyth 952*37da2899SCharles.Forsyth 953*37da2899SCharles.Forsyth c1 = (bdf_glyph_t *)a; 954*37da2899SCharles.Forsyth c2 = (bdf_glyph_t *)b; 955*37da2899SCharles.Forsyth 956*37da2899SCharles.Forsyth if ( c1->encoding < c2->encoding ) 957*37da2899SCharles.Forsyth return -1; 958*37da2899SCharles.Forsyth else if ( c1->encoding > c2->encoding ) 959*37da2899SCharles.Forsyth return 1; 960*37da2899SCharles.Forsyth 961*37da2899SCharles.Forsyth return 0; 962*37da2899SCharles.Forsyth } 963*37da2899SCharles.Forsyth 964*37da2899SCharles.Forsyth 965*37da2899SCharles.Forsyth static FT_Error bdf_create_property(char * name,int format,bdf_font_t * font)966*37da2899SCharles.Forsyth bdf_create_property( char* name, 967*37da2899SCharles.Forsyth int format, 968*37da2899SCharles.Forsyth bdf_font_t* font ) 969*37da2899SCharles.Forsyth { 970*37da2899SCharles.Forsyth unsigned long n; 971*37da2899SCharles.Forsyth bdf_property_t* p; 972*37da2899SCharles.Forsyth FT_Memory memory = font->memory; 973*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 974*37da2899SCharles.Forsyth 975*37da2899SCharles.Forsyth 976*37da2899SCharles.Forsyth /* First check to see if the property has */ 977*37da2899SCharles.Forsyth /* already been added or not. If it has, then */ 978*37da2899SCharles.Forsyth /* simply ignore it. */ 979*37da2899SCharles.Forsyth if ( hash_lookup( name, &(font->proptbl) ) ) 980*37da2899SCharles.Forsyth goto Exit; 981*37da2899SCharles.Forsyth 982*37da2899SCharles.Forsyth if ( font->nuser_props == 0 ) 983*37da2899SCharles.Forsyth { 984*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( font->user_props, 1 ) ) 985*37da2899SCharles.Forsyth goto Exit; 986*37da2899SCharles.Forsyth } 987*37da2899SCharles.Forsyth else 988*37da2899SCharles.Forsyth { 989*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( font->user_props, 990*37da2899SCharles.Forsyth font->nuser_props, 991*37da2899SCharles.Forsyth font->nuser_props + 1 ) ) 992*37da2899SCharles.Forsyth goto Exit; 993*37da2899SCharles.Forsyth } 994*37da2899SCharles.Forsyth 995*37da2899SCharles.Forsyth p = font->user_props + font->nuser_props; 996*37da2899SCharles.Forsyth FT_MEM_ZERO( p, sizeof ( bdf_property_t ) ); 997*37da2899SCharles.Forsyth 998*37da2899SCharles.Forsyth n = (unsigned long)( ft_strlen( name ) + 1 ); 999*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( p->name, n ) ) 1000*37da2899SCharles.Forsyth goto Exit; 1001*37da2899SCharles.Forsyth 1002*37da2899SCharles.Forsyth FT_MEM_COPY( (char *)p->name, name, n ); 1003*37da2899SCharles.Forsyth 1004*37da2899SCharles.Forsyth p->format = format; 1005*37da2899SCharles.Forsyth p->builtin = 0; 1006*37da2899SCharles.Forsyth 1007*37da2899SCharles.Forsyth n = _num_bdf_properties + font->nuser_props; 1008*37da2899SCharles.Forsyth 1009*37da2899SCharles.Forsyth error = hash_insert( p->name, (void *)n, &(font->proptbl), memory ); 1010*37da2899SCharles.Forsyth if ( error ) 1011*37da2899SCharles.Forsyth goto Exit; 1012*37da2899SCharles.Forsyth 1013*37da2899SCharles.Forsyth font->nuser_props++; 1014*37da2899SCharles.Forsyth 1015*37da2899SCharles.Forsyth Exit: 1016*37da2899SCharles.Forsyth return error; 1017*37da2899SCharles.Forsyth } 1018*37da2899SCharles.Forsyth 1019*37da2899SCharles.Forsyth 1020*37da2899SCharles.Forsyth FT_LOCAL_DEF( bdf_property_t * ) bdf_get_property(char * name,bdf_font_t * font)1021*37da2899SCharles.Forsyth bdf_get_property( char* name, 1022*37da2899SCharles.Forsyth bdf_font_t* font ) 1023*37da2899SCharles.Forsyth { 1024*37da2899SCharles.Forsyth hashnode hn; 1025*37da2899SCharles.Forsyth unsigned long propid; 1026*37da2899SCharles.Forsyth 1027*37da2899SCharles.Forsyth 1028*37da2899SCharles.Forsyth if ( name == 0 || *name == 0 ) 1029*37da2899SCharles.Forsyth return 0; 1030*37da2899SCharles.Forsyth 1031*37da2899SCharles.Forsyth if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 ) 1032*37da2899SCharles.Forsyth return 0; 1033*37da2899SCharles.Forsyth 1034*37da2899SCharles.Forsyth propid = (unsigned long)hn->data; 1035*37da2899SCharles.Forsyth if ( propid >= _num_bdf_properties ) 1036*37da2899SCharles.Forsyth return font->user_props + ( propid - _num_bdf_properties ); 1037*37da2899SCharles.Forsyth 1038*37da2899SCharles.Forsyth return (bdf_property_t*)_bdf_properties + propid; 1039*37da2899SCharles.Forsyth } 1040*37da2899SCharles.Forsyth 1041*37da2899SCharles.Forsyth 1042*37da2899SCharles.Forsyth /*************************************************************************/ 1043*37da2899SCharles.Forsyth /* */ 1044*37da2899SCharles.Forsyth /* BDF font file parsing flags and functions. */ 1045*37da2899SCharles.Forsyth /* */ 1046*37da2899SCharles.Forsyth /*************************************************************************/ 1047*37da2899SCharles.Forsyth 1048*37da2899SCharles.Forsyth 1049*37da2899SCharles.Forsyth /* Parse flags. */ 1050*37da2899SCharles.Forsyth 1051*37da2899SCharles.Forsyth #define _BDF_START 0x0001 1052*37da2899SCharles.Forsyth #define _BDF_FONT_NAME 0x0002 1053*37da2899SCharles.Forsyth #define _BDF_SIZE 0x0004 1054*37da2899SCharles.Forsyth #define _BDF_FONT_BBX 0x0008 1055*37da2899SCharles.Forsyth #define _BDF_PROPS 0x0010 1056*37da2899SCharles.Forsyth #define _BDF_GLYPHS 0x0020 1057*37da2899SCharles.Forsyth #define _BDF_GLYPH 0x0040 1058*37da2899SCharles.Forsyth #define _BDF_ENCODING 0x0080 1059*37da2899SCharles.Forsyth #define _BDF_SWIDTH 0x0100 1060*37da2899SCharles.Forsyth #define _BDF_DWIDTH 0x0200 1061*37da2899SCharles.Forsyth #define _BDF_BBX 0x0400 1062*37da2899SCharles.Forsyth #define _BDF_BITMAP 0x0800 1063*37da2899SCharles.Forsyth 1064*37da2899SCharles.Forsyth #define _BDF_SWIDTH_ADJ 0x1000 1065*37da2899SCharles.Forsyth 1066*37da2899SCharles.Forsyth #define _BDF_GLYPH_BITS ( _BDF_GLYPH | \ 1067*37da2899SCharles.Forsyth _BDF_ENCODING | \ 1068*37da2899SCharles.Forsyth _BDF_SWIDTH | \ 1069*37da2899SCharles.Forsyth _BDF_DWIDTH | \ 1070*37da2899SCharles.Forsyth _BDF_BBX | \ 1071*37da2899SCharles.Forsyth _BDF_BITMAP ) 1072*37da2899SCharles.Forsyth 1073*37da2899SCharles.Forsyth #define _BDF_GLYPH_WIDTH_CHECK 0x40000000L 1074*37da2899SCharles.Forsyth #define _BDF_GLYPH_HEIGHT_CHECK 0x80000000L 1075*37da2899SCharles.Forsyth 1076*37da2899SCharles.Forsyth 1077*37da2899SCharles.Forsyth /* Auto correction messages. */ 1078*37da2899SCharles.Forsyth #define ACMSG1 "FONT_ASCENT property missing. " \ 1079*37da2899SCharles.Forsyth "Added \"FONT_ASCENT %hd\".\n" 1080*37da2899SCharles.Forsyth #define ACMSG2 "FONT_DESCENT property missing. " \ 1081*37da2899SCharles.Forsyth "Added \"FONT_DESCENT %hd\".\n" 1082*37da2899SCharles.Forsyth #define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n" 1083*37da2899SCharles.Forsyth #define ACMSG4 "Font left bearing != actual left bearing. " \ 1084*37da2899SCharles.Forsyth "Old: %hd New: %hd.\n" 1085*37da2899SCharles.Forsyth #define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n" 1086*37da2899SCharles.Forsyth #define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n" 1087*37da2899SCharles.Forsyth #define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n" 1088*37da2899SCharles.Forsyth #define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n" 1089*37da2899SCharles.Forsyth #define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n" 1090*37da2899SCharles.Forsyth #define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n" 1091*37da2899SCharles.Forsyth #define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n" 1092*37da2899SCharles.Forsyth #define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n" 1093*37da2899SCharles.Forsyth #define ACMSG13 "Glyph %ld extra rows removed.\n" 1094*37da2899SCharles.Forsyth #define ACMSG14 "Glyph %ld extra columns removed.\n" 1095*37da2899SCharles.Forsyth #define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n" 1096*37da2899SCharles.Forsyth 1097*37da2899SCharles.Forsyth /* Error messages. */ 1098*37da2899SCharles.Forsyth #define ERRMSG1 "[line %ld] Missing \"%s\" line.\n" 1099*37da2899SCharles.Forsyth #define ERRMSG2 "[line %ld] Font header corrupted or missing fields.\n" 1100*37da2899SCharles.Forsyth #define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields.\n" 1101*37da2899SCharles.Forsyth 1102*37da2899SCharles.Forsyth 1103*37da2899SCharles.Forsyth static FT_Error _bdf_add_comment(bdf_font_t * font,char * comment,unsigned long len)1104*37da2899SCharles.Forsyth _bdf_add_comment( bdf_font_t* font, 1105*37da2899SCharles.Forsyth char* comment, 1106*37da2899SCharles.Forsyth unsigned long len ) 1107*37da2899SCharles.Forsyth { 1108*37da2899SCharles.Forsyth char* cp; 1109*37da2899SCharles.Forsyth FT_Memory memory = font->memory; 1110*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 1111*37da2899SCharles.Forsyth 1112*37da2899SCharles.Forsyth 1113*37da2899SCharles.Forsyth if ( font->comments_len == 0 ) 1114*37da2899SCharles.Forsyth { 1115*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( font->comments, len + 1 ) ) 1116*37da2899SCharles.Forsyth goto Exit; 1117*37da2899SCharles.Forsyth } 1118*37da2899SCharles.Forsyth else 1119*37da2899SCharles.Forsyth { 1120*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( font->comments, 1121*37da2899SCharles.Forsyth font->comments_len, 1122*37da2899SCharles.Forsyth font->comments_len + len + 1 ) ) 1123*37da2899SCharles.Forsyth goto Exit; 1124*37da2899SCharles.Forsyth } 1125*37da2899SCharles.Forsyth 1126*37da2899SCharles.Forsyth cp = font->comments + font->comments_len; 1127*37da2899SCharles.Forsyth FT_MEM_COPY( cp, comment, len ); 1128*37da2899SCharles.Forsyth cp += len; 1129*37da2899SCharles.Forsyth *cp++ = '\n'; 1130*37da2899SCharles.Forsyth font->comments_len += len + 1; 1131*37da2899SCharles.Forsyth 1132*37da2899SCharles.Forsyth Exit: 1133*37da2899SCharles.Forsyth return error; 1134*37da2899SCharles.Forsyth } 1135*37da2899SCharles.Forsyth 1136*37da2899SCharles.Forsyth 1137*37da2899SCharles.Forsyth /* Set the spacing from the font name if it exists, or set it to the */ 1138*37da2899SCharles.Forsyth /* default specified in the options. */ 1139*37da2899SCharles.Forsyth static FT_Error _bdf_set_default_spacing(bdf_font_t * font,bdf_options_t * opts)1140*37da2899SCharles.Forsyth _bdf_set_default_spacing( bdf_font_t* font, 1141*37da2899SCharles.Forsyth bdf_options_t* opts ) 1142*37da2899SCharles.Forsyth { 1143*37da2899SCharles.Forsyth unsigned long len; 1144*37da2899SCharles.Forsyth char name[128]; 1145*37da2899SCharles.Forsyth _bdf_list_t list; 1146*37da2899SCharles.Forsyth FT_Memory memory; 1147*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 1148*37da2899SCharles.Forsyth 1149*37da2899SCharles.Forsyth 1150*37da2899SCharles.Forsyth if ( font == 0 || font->name == 0 || font->name[0] == 0 ) 1151*37da2899SCharles.Forsyth { 1152*37da2899SCharles.Forsyth error = BDF_Err_Invalid_Argument; 1153*37da2899SCharles.Forsyth goto Exit; 1154*37da2899SCharles.Forsyth } 1155*37da2899SCharles.Forsyth 1156*37da2899SCharles.Forsyth memory = font->memory; 1157*37da2899SCharles.Forsyth 1158*37da2899SCharles.Forsyth font->spacing = opts->font_spacing; 1159*37da2899SCharles.Forsyth 1160*37da2899SCharles.Forsyth len = (unsigned long)( ft_strlen( font->name ) + 1 ); 1161*37da2899SCharles.Forsyth FT_MEM_COPY( name, font->name, len ); 1162*37da2899SCharles.Forsyth 1163*37da2899SCharles.Forsyth list.size = list.used = 0; 1164*37da2899SCharles.Forsyth 1165*37da2899SCharles.Forsyth error = _bdf_split( (char *)"-", name, len, &list, memory ); 1166*37da2899SCharles.Forsyth if ( error ) 1167*37da2899SCharles.Forsyth goto Exit; 1168*37da2899SCharles.Forsyth 1169*37da2899SCharles.Forsyth if ( list.used == 15 ) 1170*37da2899SCharles.Forsyth { 1171*37da2899SCharles.Forsyth switch ( list.field[11][0] ) 1172*37da2899SCharles.Forsyth { 1173*37da2899SCharles.Forsyth case 'C': 1174*37da2899SCharles.Forsyth case 'c': 1175*37da2899SCharles.Forsyth font->spacing = BDF_CHARCELL; 1176*37da2899SCharles.Forsyth break; 1177*37da2899SCharles.Forsyth case 'M': 1178*37da2899SCharles.Forsyth case 'm': 1179*37da2899SCharles.Forsyth font->spacing = BDF_MONOWIDTH; 1180*37da2899SCharles.Forsyth break; 1181*37da2899SCharles.Forsyth case 'P': 1182*37da2899SCharles.Forsyth case 'p': 1183*37da2899SCharles.Forsyth font->spacing = BDF_PROPORTIONAL; 1184*37da2899SCharles.Forsyth break; 1185*37da2899SCharles.Forsyth } 1186*37da2899SCharles.Forsyth } 1187*37da2899SCharles.Forsyth 1188*37da2899SCharles.Forsyth FT_FREE( list.field ); 1189*37da2899SCharles.Forsyth 1190*37da2899SCharles.Forsyth Exit: 1191*37da2899SCharles.Forsyth return error; 1192*37da2899SCharles.Forsyth } 1193*37da2899SCharles.Forsyth 1194*37da2899SCharles.Forsyth 1195*37da2899SCharles.Forsyth /* Determine whether the property is an atom or not. If it is, then */ 1196*37da2899SCharles.Forsyth /* clean it up so the double quotes are removed if they exist. */ 1197*37da2899SCharles.Forsyth static int _bdf_is_atom(char * line,unsigned long linelen,char ** name,char ** value,bdf_font_t * font)1198*37da2899SCharles.Forsyth _bdf_is_atom( char* line, 1199*37da2899SCharles.Forsyth unsigned long linelen, 1200*37da2899SCharles.Forsyth char** name, 1201*37da2899SCharles.Forsyth char** value, 1202*37da2899SCharles.Forsyth bdf_font_t* font ) 1203*37da2899SCharles.Forsyth { 1204*37da2899SCharles.Forsyth int hold; 1205*37da2899SCharles.Forsyth char *sp, *ep; 1206*37da2899SCharles.Forsyth bdf_property_t* p; 1207*37da2899SCharles.Forsyth 1208*37da2899SCharles.Forsyth 1209*37da2899SCharles.Forsyth *name = sp = ep = line; 1210*37da2899SCharles.Forsyth 1211*37da2899SCharles.Forsyth while ( *ep && *ep != ' ' && *ep != '\t' ) 1212*37da2899SCharles.Forsyth ep++; 1213*37da2899SCharles.Forsyth 1214*37da2899SCharles.Forsyth hold = -1; 1215*37da2899SCharles.Forsyth if ( *ep ) 1216*37da2899SCharles.Forsyth { 1217*37da2899SCharles.Forsyth hold = *ep; 1218*37da2899SCharles.Forsyth *ep = 0; 1219*37da2899SCharles.Forsyth } 1220*37da2899SCharles.Forsyth 1221*37da2899SCharles.Forsyth p = bdf_get_property( sp, font ); 1222*37da2899SCharles.Forsyth 1223*37da2899SCharles.Forsyth /* Restore the character that was saved before any return can happen. */ 1224*37da2899SCharles.Forsyth if ( hold != -1 ) 1225*37da2899SCharles.Forsyth *ep = (char)hold; 1226*37da2899SCharles.Forsyth 1227*37da2899SCharles.Forsyth /* If the property exists and is not an atom, just return here. */ 1228*37da2899SCharles.Forsyth if ( p && p->format != BDF_ATOM ) 1229*37da2899SCharles.Forsyth return 0; 1230*37da2899SCharles.Forsyth 1231*37da2899SCharles.Forsyth /* The property is an atom. Trim all leading and trailing whitespace */ 1232*37da2899SCharles.Forsyth /* and double quotes for the atom value. */ 1233*37da2899SCharles.Forsyth sp = ep; 1234*37da2899SCharles.Forsyth ep = line + linelen; 1235*37da2899SCharles.Forsyth 1236*37da2899SCharles.Forsyth /* Trim the leading whitespace if it exists. */ 1237*37da2899SCharles.Forsyth *sp++ = 0; 1238*37da2899SCharles.Forsyth while ( *sp && 1239*37da2899SCharles.Forsyth ( *sp == ' ' || *sp == '\t' ) ) 1240*37da2899SCharles.Forsyth sp++; 1241*37da2899SCharles.Forsyth 1242*37da2899SCharles.Forsyth /* Trim the leading double quote if it exists. */ 1243*37da2899SCharles.Forsyth if ( *sp == '"' ) 1244*37da2899SCharles.Forsyth sp++; 1245*37da2899SCharles.Forsyth *value = sp; 1246*37da2899SCharles.Forsyth 1247*37da2899SCharles.Forsyth /* Trim the trailing whitespace if it exists. */ 1248*37da2899SCharles.Forsyth while ( ep > sp && 1249*37da2899SCharles.Forsyth ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) ) 1250*37da2899SCharles.Forsyth *--ep = 0; 1251*37da2899SCharles.Forsyth 1252*37da2899SCharles.Forsyth /* Trim the trailing double quote if it exists. */ 1253*37da2899SCharles.Forsyth if ( ep > sp && *( ep - 1 ) == '"' ) 1254*37da2899SCharles.Forsyth *--ep = 0; 1255*37da2899SCharles.Forsyth 1256*37da2899SCharles.Forsyth return 1; 1257*37da2899SCharles.Forsyth } 1258*37da2899SCharles.Forsyth 1259*37da2899SCharles.Forsyth 1260*37da2899SCharles.Forsyth static FT_Error _bdf_add_property(bdf_font_t * font,char * name,char * value)1261*37da2899SCharles.Forsyth _bdf_add_property( bdf_font_t* font, 1262*37da2899SCharles.Forsyth char* name, 1263*37da2899SCharles.Forsyth char* value ) 1264*37da2899SCharles.Forsyth { 1265*37da2899SCharles.Forsyth unsigned long propid; 1266*37da2899SCharles.Forsyth hashnode hn; 1267*37da2899SCharles.Forsyth int len; 1268*37da2899SCharles.Forsyth bdf_property_t *prop, *fp; 1269*37da2899SCharles.Forsyth FT_Memory memory = font->memory; 1270*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 1271*37da2899SCharles.Forsyth 1272*37da2899SCharles.Forsyth 1273*37da2899SCharles.Forsyth /* First, check to see if the property already exists in the font. */ 1274*37da2899SCharles.Forsyth if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 ) 1275*37da2899SCharles.Forsyth { 1276*37da2899SCharles.Forsyth /* The property already exists in the font, so simply replace */ 1277*37da2899SCharles.Forsyth /* the value of the property with the current value. */ 1278*37da2899SCharles.Forsyth fp = font->props + (unsigned long)hn->data; 1279*37da2899SCharles.Forsyth 1280*37da2899SCharles.Forsyth switch ( fp->format ) 1281*37da2899SCharles.Forsyth { 1282*37da2899SCharles.Forsyth case BDF_ATOM: 1283*37da2899SCharles.Forsyth /* Delete the current atom if it exists. */ 1284*37da2899SCharles.Forsyth FT_FREE( fp->value.atom ); 1285*37da2899SCharles.Forsyth 1286*37da2899SCharles.Forsyth if ( value == 0 ) 1287*37da2899SCharles.Forsyth len = 1; 1288*37da2899SCharles.Forsyth else 1289*37da2899SCharles.Forsyth len = ft_strlen( value ) + 1; 1290*37da2899SCharles.Forsyth 1291*37da2899SCharles.Forsyth if ( len > 1 ) 1292*37da2899SCharles.Forsyth { 1293*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( fp->value.atom, len ) ) 1294*37da2899SCharles.Forsyth goto Exit; 1295*37da2899SCharles.Forsyth FT_MEM_COPY( fp->value.atom, value, len ); 1296*37da2899SCharles.Forsyth } 1297*37da2899SCharles.Forsyth else 1298*37da2899SCharles.Forsyth fp->value.atom = 0; 1299*37da2899SCharles.Forsyth break; 1300*37da2899SCharles.Forsyth 1301*37da2899SCharles.Forsyth case BDF_INTEGER: 1302*37da2899SCharles.Forsyth fp->value.int32 = _bdf_atol( value, 0, 10 ); 1303*37da2899SCharles.Forsyth break; 1304*37da2899SCharles.Forsyth 1305*37da2899SCharles.Forsyth case BDF_CARDINAL: 1306*37da2899SCharles.Forsyth fp->value.card32 = _bdf_atoul( value, 0, 10 ); 1307*37da2899SCharles.Forsyth break; 1308*37da2899SCharles.Forsyth 1309*37da2899SCharles.Forsyth default: 1310*37da2899SCharles.Forsyth ; 1311*37da2899SCharles.Forsyth } 1312*37da2899SCharles.Forsyth 1313*37da2899SCharles.Forsyth goto Exit; 1314*37da2899SCharles.Forsyth } 1315*37da2899SCharles.Forsyth 1316*37da2899SCharles.Forsyth /* See whether this property type exists yet or not. */ 1317*37da2899SCharles.Forsyth /* If not, create it. */ 1318*37da2899SCharles.Forsyth hn = hash_lookup( name, &(font->proptbl) ); 1319*37da2899SCharles.Forsyth if ( hn == 0 ) 1320*37da2899SCharles.Forsyth { 1321*37da2899SCharles.Forsyth error = bdf_create_property( name, BDF_ATOM, font ); 1322*37da2899SCharles.Forsyth if ( error ) 1323*37da2899SCharles.Forsyth goto Exit; 1324*37da2899SCharles.Forsyth hn = hash_lookup( name, &(font->proptbl) ); 1325*37da2899SCharles.Forsyth } 1326*37da2899SCharles.Forsyth 1327*37da2899SCharles.Forsyth /* Allocate another property if this is overflow. */ 1328*37da2899SCharles.Forsyth if ( font->props_used == font->props_size ) 1329*37da2899SCharles.Forsyth { 1330*37da2899SCharles.Forsyth if ( font->props_size == 0 ) 1331*37da2899SCharles.Forsyth { 1332*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( font->props, 1 ) ) 1333*37da2899SCharles.Forsyth goto Exit; 1334*37da2899SCharles.Forsyth } 1335*37da2899SCharles.Forsyth else 1336*37da2899SCharles.Forsyth { 1337*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( font->props, 1338*37da2899SCharles.Forsyth font->props_size, 1339*37da2899SCharles.Forsyth font->props_size + 1 ) ) 1340*37da2899SCharles.Forsyth goto Exit; 1341*37da2899SCharles.Forsyth } 1342*37da2899SCharles.Forsyth 1343*37da2899SCharles.Forsyth fp = font->props + font->props_size; 1344*37da2899SCharles.Forsyth FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) ); 1345*37da2899SCharles.Forsyth font->props_size++; 1346*37da2899SCharles.Forsyth } 1347*37da2899SCharles.Forsyth 1348*37da2899SCharles.Forsyth propid = (unsigned long)hn->data; 1349*37da2899SCharles.Forsyth if ( propid >= _num_bdf_properties ) 1350*37da2899SCharles.Forsyth prop = font->user_props + ( propid - _num_bdf_properties ); 1351*37da2899SCharles.Forsyth else 1352*37da2899SCharles.Forsyth prop = (bdf_property_t*)_bdf_properties + propid; 1353*37da2899SCharles.Forsyth 1354*37da2899SCharles.Forsyth fp = font->props + font->props_used; 1355*37da2899SCharles.Forsyth 1356*37da2899SCharles.Forsyth fp->name = prop->name; 1357*37da2899SCharles.Forsyth fp->format = prop->format; 1358*37da2899SCharles.Forsyth fp->builtin = prop->builtin; 1359*37da2899SCharles.Forsyth 1360*37da2899SCharles.Forsyth switch ( prop->format ) 1361*37da2899SCharles.Forsyth { 1362*37da2899SCharles.Forsyth case BDF_ATOM: 1363*37da2899SCharles.Forsyth if ( value == 0 ) 1364*37da2899SCharles.Forsyth len = 1; 1365*37da2899SCharles.Forsyth else 1366*37da2899SCharles.Forsyth len = ft_strlen( value ) + 1; 1367*37da2899SCharles.Forsyth 1368*37da2899SCharles.Forsyth if ( len > 1 ) 1369*37da2899SCharles.Forsyth { 1370*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( fp->value.atom, len ) ) 1371*37da2899SCharles.Forsyth goto Exit; 1372*37da2899SCharles.Forsyth FT_MEM_COPY( fp->value.atom, value, len ); 1373*37da2899SCharles.Forsyth } 1374*37da2899SCharles.Forsyth else 1375*37da2899SCharles.Forsyth fp->value.atom = 0; 1376*37da2899SCharles.Forsyth break; 1377*37da2899SCharles.Forsyth 1378*37da2899SCharles.Forsyth case BDF_INTEGER: 1379*37da2899SCharles.Forsyth fp->value.int32 = _bdf_atol( value, 0, 10 ); 1380*37da2899SCharles.Forsyth break; 1381*37da2899SCharles.Forsyth 1382*37da2899SCharles.Forsyth case BDF_CARDINAL: 1383*37da2899SCharles.Forsyth fp->value.card32 = _bdf_atoul( value, 0, 10 ); 1384*37da2899SCharles.Forsyth break; 1385*37da2899SCharles.Forsyth } 1386*37da2899SCharles.Forsyth 1387*37da2899SCharles.Forsyth /* If the property happens to be a comment, then it doesn't need */ 1388*37da2899SCharles.Forsyth /* to be added to the internal hash table. */ 1389*37da2899SCharles.Forsyth if ( ft_memcmp( name, "COMMENT", 7 ) != 0 ) { 1390*37da2899SCharles.Forsyth /* Add the property to the font property table. */ 1391*37da2899SCharles.Forsyth error = hash_insert( fp->name, 1392*37da2899SCharles.Forsyth (void *)font->props_used, 1393*37da2899SCharles.Forsyth (hashtable *)font->internal, 1394*37da2899SCharles.Forsyth memory ); 1395*37da2899SCharles.Forsyth if ( error ) 1396*37da2899SCharles.Forsyth goto Exit; 1397*37da2899SCharles.Forsyth } 1398*37da2899SCharles.Forsyth 1399*37da2899SCharles.Forsyth font->props_used++; 1400*37da2899SCharles.Forsyth 1401*37da2899SCharles.Forsyth /* Some special cases need to be handled here. The DEFAULT_CHAR */ 1402*37da2899SCharles.Forsyth /* property needs to be located if it exists in the property list, the */ 1403*37da2899SCharles.Forsyth /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are */ 1404*37da2899SCharles.Forsyth /* present, and the SPACING property should override the default */ 1405*37da2899SCharles.Forsyth /* spacing. */ 1406*37da2899SCharles.Forsyth if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 ) 1407*37da2899SCharles.Forsyth font->default_glyph = fp->value.int32; 1408*37da2899SCharles.Forsyth else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 ) 1409*37da2899SCharles.Forsyth font->font_ascent = fp->value.int32; 1410*37da2899SCharles.Forsyth else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 ) 1411*37da2899SCharles.Forsyth font->font_descent = fp->value.int32; 1412*37da2899SCharles.Forsyth else if ( ft_memcmp( name, "SPACING", 7 ) == 0 ) 1413*37da2899SCharles.Forsyth { 1414*37da2899SCharles.Forsyth if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' ) 1415*37da2899SCharles.Forsyth font->spacing = BDF_PROPORTIONAL; 1416*37da2899SCharles.Forsyth else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' ) 1417*37da2899SCharles.Forsyth font->spacing = BDF_MONOWIDTH; 1418*37da2899SCharles.Forsyth else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' ) 1419*37da2899SCharles.Forsyth font->spacing = BDF_CHARCELL; 1420*37da2899SCharles.Forsyth } 1421*37da2899SCharles.Forsyth 1422*37da2899SCharles.Forsyth Exit: 1423*37da2899SCharles.Forsyth return error; 1424*37da2899SCharles.Forsyth } 1425*37da2899SCharles.Forsyth 1426*37da2899SCharles.Forsyth 1427*37da2899SCharles.Forsyth static const unsigned char nibble_mask[8] = 1428*37da2899SCharles.Forsyth { 1429*37da2899SCharles.Forsyth 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE 1430*37da2899SCharles.Forsyth }; 1431*37da2899SCharles.Forsyth 1432*37da2899SCharles.Forsyth 1433*37da2899SCharles.Forsyth /* Actually parse the glyph info and bitmaps. */ 1434*37da2899SCharles.Forsyth static FT_Error _bdf_parse_glyphs(char * line,unsigned long linelen,unsigned long lineno,void * call_data,void * client_data)1435*37da2899SCharles.Forsyth _bdf_parse_glyphs( char* line, 1436*37da2899SCharles.Forsyth unsigned long linelen, 1437*37da2899SCharles.Forsyth unsigned long lineno, 1438*37da2899SCharles.Forsyth void* call_data, 1439*37da2899SCharles.Forsyth void* client_data ) 1440*37da2899SCharles.Forsyth { 1441*37da2899SCharles.Forsyth int c, mask_index; 1442*37da2899SCharles.Forsyth char* s; 1443*37da2899SCharles.Forsyth unsigned char* bp; 1444*37da2899SCharles.Forsyth unsigned long i, slen, nibbles; 1445*37da2899SCharles.Forsyth 1446*37da2899SCharles.Forsyth _bdf_line_func_t* next; 1447*37da2899SCharles.Forsyth _bdf_parse_t* p; 1448*37da2899SCharles.Forsyth bdf_glyph_t* glyph; 1449*37da2899SCharles.Forsyth bdf_font_t* font; 1450*37da2899SCharles.Forsyth 1451*37da2899SCharles.Forsyth FT_Memory memory; 1452*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 1453*37da2899SCharles.Forsyth 1454*37da2899SCharles.Forsyth FT_UNUSED( lineno ); /* only used in debug mode */ 1455*37da2899SCharles.Forsyth 1456*37da2899SCharles.Forsyth 1457*37da2899SCharles.Forsyth next = (_bdf_line_func_t *)call_data; 1458*37da2899SCharles.Forsyth p = (_bdf_parse_t *) client_data; 1459*37da2899SCharles.Forsyth 1460*37da2899SCharles.Forsyth font = p->font; 1461*37da2899SCharles.Forsyth memory = font->memory; 1462*37da2899SCharles.Forsyth 1463*37da2899SCharles.Forsyth /* Check for a comment. */ 1464*37da2899SCharles.Forsyth if ( ft_memcmp( line, "COMMENT", 7 ) == 0 ) 1465*37da2899SCharles.Forsyth { 1466*37da2899SCharles.Forsyth linelen -= 7; 1467*37da2899SCharles.Forsyth 1468*37da2899SCharles.Forsyth s = line + 7; 1469*37da2899SCharles.Forsyth if ( *s != 0 ) 1470*37da2899SCharles.Forsyth { 1471*37da2899SCharles.Forsyth s++; 1472*37da2899SCharles.Forsyth linelen--; 1473*37da2899SCharles.Forsyth } 1474*37da2899SCharles.Forsyth error = _bdf_add_comment( p->font, s, linelen ); 1475*37da2899SCharles.Forsyth goto Exit; 1476*37da2899SCharles.Forsyth } 1477*37da2899SCharles.Forsyth 1478*37da2899SCharles.Forsyth /* The very first thing expected is the number of glyphs. */ 1479*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_GLYPHS ) ) 1480*37da2899SCharles.Forsyth { 1481*37da2899SCharles.Forsyth if ( ft_memcmp( line, "CHARS", 5 ) != 0 ) 1482*37da2899SCharles.Forsyth { 1483*37da2899SCharles.Forsyth FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" )); 1484*37da2899SCharles.Forsyth error = BDF_Err_Missing_Chars_Field; 1485*37da2899SCharles.Forsyth goto Exit; 1486*37da2899SCharles.Forsyth } 1487*37da2899SCharles.Forsyth 1488*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); 1489*37da2899SCharles.Forsyth if ( error ) 1490*37da2899SCharles.Forsyth goto Exit; 1491*37da2899SCharles.Forsyth p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 ); 1492*37da2899SCharles.Forsyth 1493*37da2899SCharles.Forsyth /* Make sure the number of glyphs is non-zero. */ 1494*37da2899SCharles.Forsyth if ( p->cnt == 0 ) 1495*37da2899SCharles.Forsyth font->glyphs_size = 64; 1496*37da2899SCharles.Forsyth 1497*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) ) 1498*37da2899SCharles.Forsyth goto Exit; 1499*37da2899SCharles.Forsyth 1500*37da2899SCharles.Forsyth p->flags |= _BDF_GLYPHS; 1501*37da2899SCharles.Forsyth 1502*37da2899SCharles.Forsyth goto Exit; 1503*37da2899SCharles.Forsyth } 1504*37da2899SCharles.Forsyth 1505*37da2899SCharles.Forsyth /* Check for the ENDFONT field. */ 1506*37da2899SCharles.Forsyth if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 ) 1507*37da2899SCharles.Forsyth { 1508*37da2899SCharles.Forsyth /* Sort the glyphs by encoding. */ 1509*37da2899SCharles.Forsyth ft_qsort( (char *)font->glyphs, 1510*37da2899SCharles.Forsyth font->glyphs_used, 1511*37da2899SCharles.Forsyth sizeof ( bdf_glyph_t ), 1512*37da2899SCharles.Forsyth by_encoding ); 1513*37da2899SCharles.Forsyth 1514*37da2899SCharles.Forsyth p->flags &= ~_BDF_START; 1515*37da2899SCharles.Forsyth 1516*37da2899SCharles.Forsyth goto Exit; 1517*37da2899SCharles.Forsyth } 1518*37da2899SCharles.Forsyth 1519*37da2899SCharles.Forsyth /* Check for the ENDCHAR field. */ 1520*37da2899SCharles.Forsyth if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 ) 1521*37da2899SCharles.Forsyth { 1522*37da2899SCharles.Forsyth p->glyph_enc = 0; 1523*37da2899SCharles.Forsyth p->flags &= ~_BDF_GLYPH_BITS; 1524*37da2899SCharles.Forsyth 1525*37da2899SCharles.Forsyth goto Exit; 1526*37da2899SCharles.Forsyth } 1527*37da2899SCharles.Forsyth 1528*37da2899SCharles.Forsyth /* Check to see whether a glyph is being scanned but should be */ 1529*37da2899SCharles.Forsyth /* ignored because it is an unencoded glyph. */ 1530*37da2899SCharles.Forsyth if ( ( p->flags & _BDF_GLYPH ) && 1531*37da2899SCharles.Forsyth p->glyph_enc == -1 && 1532*37da2899SCharles.Forsyth p->opts->keep_unencoded == 0 ) 1533*37da2899SCharles.Forsyth goto Exit; 1534*37da2899SCharles.Forsyth 1535*37da2899SCharles.Forsyth /* Check for the STARTCHAR field. */ 1536*37da2899SCharles.Forsyth if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 ) 1537*37da2899SCharles.Forsyth { 1538*37da2899SCharles.Forsyth /* Set the character name in the parse info first until the */ 1539*37da2899SCharles.Forsyth /* encoding can be checked for an unencoded character. */ 1540*37da2899SCharles.Forsyth FT_FREE( p->glyph_name ); 1541*37da2899SCharles.Forsyth 1542*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list,memory ); 1543*37da2899SCharles.Forsyth if ( error ) 1544*37da2899SCharles.Forsyth goto Exit; 1545*37da2899SCharles.Forsyth _bdf_shift( 1, &p->list ); 1546*37da2899SCharles.Forsyth 1547*37da2899SCharles.Forsyth s = _bdf_join( ' ', &slen, &p->list ); 1548*37da2899SCharles.Forsyth 1549*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) ) 1550*37da2899SCharles.Forsyth goto Exit; 1551*37da2899SCharles.Forsyth FT_MEM_COPY( p->glyph_name, s, slen + 1 ); 1552*37da2899SCharles.Forsyth 1553*37da2899SCharles.Forsyth p->flags |= _BDF_GLYPH; 1554*37da2899SCharles.Forsyth 1555*37da2899SCharles.Forsyth goto Exit; 1556*37da2899SCharles.Forsyth } 1557*37da2899SCharles.Forsyth 1558*37da2899SCharles.Forsyth /* Check for the ENCODING field. */ 1559*37da2899SCharles.Forsyth if ( ft_memcmp( line, "ENCODING", 8 ) == 0 ) 1560*37da2899SCharles.Forsyth { 1561*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_GLYPH ) ) 1562*37da2899SCharles.Forsyth { 1563*37da2899SCharles.Forsyth /* Missing STARTCHAR field. */ 1564*37da2899SCharles.Forsyth FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" )); 1565*37da2899SCharles.Forsyth error = BDF_Err_Missing_Startchar_Field; 1566*37da2899SCharles.Forsyth goto Exit; 1567*37da2899SCharles.Forsyth } 1568*37da2899SCharles.Forsyth 1569*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); 1570*37da2899SCharles.Forsyth if ( error ) 1571*37da2899SCharles.Forsyth goto Exit; 1572*37da2899SCharles.Forsyth p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 ); 1573*37da2899SCharles.Forsyth 1574*37da2899SCharles.Forsyth /* Check to see whether this encoding has already been encountered. */ 1575*37da2899SCharles.Forsyth /* If it has then change it to unencoded so it gets added if */ 1576*37da2899SCharles.Forsyth /* indicated. */ 1577*37da2899SCharles.Forsyth if ( p->glyph_enc >= 0 ) 1578*37da2899SCharles.Forsyth { 1579*37da2899SCharles.Forsyth if ( _bdf_glyph_modified( p->have, p->glyph_enc ) ) 1580*37da2899SCharles.Forsyth { 1581*37da2899SCharles.Forsyth /* Emit a message saying a glyph has been moved to the */ 1582*37da2899SCharles.Forsyth /* unencoded area. */ 1583*37da2899SCharles.Forsyth FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12, 1584*37da2899SCharles.Forsyth p->glyph_enc, p->glyph_name )); 1585*37da2899SCharles.Forsyth p->glyph_enc = -1; 1586*37da2899SCharles.Forsyth font->modified = 1; 1587*37da2899SCharles.Forsyth } 1588*37da2899SCharles.Forsyth else 1589*37da2899SCharles.Forsyth _bdf_set_glyph_modified( p->have, p->glyph_enc ); 1590*37da2899SCharles.Forsyth } 1591*37da2899SCharles.Forsyth 1592*37da2899SCharles.Forsyth if ( p->glyph_enc >= 0 ) 1593*37da2899SCharles.Forsyth { 1594*37da2899SCharles.Forsyth /* Make sure there are enough glyphs allocated in case the */ 1595*37da2899SCharles.Forsyth /* number of characters happen to be wrong. */ 1596*37da2899SCharles.Forsyth if ( font->glyphs_used == font->glyphs_size ) 1597*37da2899SCharles.Forsyth { 1598*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( font->glyphs, 1599*37da2899SCharles.Forsyth font->glyphs_size, 1600*37da2899SCharles.Forsyth font->glyphs_size + 64 ) ) 1601*37da2899SCharles.Forsyth goto Exit; 1602*37da2899SCharles.Forsyth FT_MEM_ZERO( font->glyphs + font->glyphs_size, 1603*37da2899SCharles.Forsyth sizeof ( bdf_glyph_t ) * 64 ); /* FZ inutile */ 1604*37da2899SCharles.Forsyth font->glyphs_size += 64; 1605*37da2899SCharles.Forsyth } 1606*37da2899SCharles.Forsyth 1607*37da2899SCharles.Forsyth glyph = font->glyphs + font->glyphs_used++; 1608*37da2899SCharles.Forsyth glyph->name = p->glyph_name; 1609*37da2899SCharles.Forsyth glyph->encoding = p->glyph_enc; 1610*37da2899SCharles.Forsyth 1611*37da2899SCharles.Forsyth /* Reset the initial glyph info. */ 1612*37da2899SCharles.Forsyth p->glyph_name = 0; 1613*37da2899SCharles.Forsyth } 1614*37da2899SCharles.Forsyth else 1615*37da2899SCharles.Forsyth { 1616*37da2899SCharles.Forsyth /* Unencoded glyph. Check to see whether it should */ 1617*37da2899SCharles.Forsyth /* be added or not. */ 1618*37da2899SCharles.Forsyth if ( p->opts->keep_unencoded != 0 ) 1619*37da2899SCharles.Forsyth { 1620*37da2899SCharles.Forsyth /* Allocate the next unencoded glyph. */ 1621*37da2899SCharles.Forsyth if ( font->unencoded_used == font->unencoded_size ) 1622*37da2899SCharles.Forsyth { 1623*37da2899SCharles.Forsyth if ( font->unencoded_size == 0 ) 1624*37da2899SCharles.Forsyth { 1625*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( font->unencoded, 4 ) ) 1626*37da2899SCharles.Forsyth goto Exit; 1627*37da2899SCharles.Forsyth } 1628*37da2899SCharles.Forsyth else 1629*37da2899SCharles.Forsyth { 1630*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( font->unencoded , 1631*37da2899SCharles.Forsyth font->unencoded_size, 1632*37da2899SCharles.Forsyth font->unencoded_size + 4 ) ) 1633*37da2899SCharles.Forsyth goto Exit; 1634*37da2899SCharles.Forsyth } 1635*37da2899SCharles.Forsyth font->unencoded_size += 4; 1636*37da2899SCharles.Forsyth } 1637*37da2899SCharles.Forsyth 1638*37da2899SCharles.Forsyth glyph = font->unencoded + font->unencoded_used; 1639*37da2899SCharles.Forsyth glyph->name = p->glyph_name; 1640*37da2899SCharles.Forsyth glyph->encoding = font->unencoded_used++; 1641*37da2899SCharles.Forsyth } 1642*37da2899SCharles.Forsyth else 1643*37da2899SCharles.Forsyth /* Free up the glyph name if the unencoded shouldn't be */ 1644*37da2899SCharles.Forsyth /* kept. */ 1645*37da2899SCharles.Forsyth FT_FREE( p->glyph_name ); 1646*37da2899SCharles.Forsyth 1647*37da2899SCharles.Forsyth p->glyph_name = 0; 1648*37da2899SCharles.Forsyth } 1649*37da2899SCharles.Forsyth 1650*37da2899SCharles.Forsyth /* Clear the flags that might be added when width and height are */ 1651*37da2899SCharles.Forsyth /* checked for consistency. */ 1652*37da2899SCharles.Forsyth p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK ); 1653*37da2899SCharles.Forsyth 1654*37da2899SCharles.Forsyth p->flags |= _BDF_ENCODING; 1655*37da2899SCharles.Forsyth 1656*37da2899SCharles.Forsyth goto Exit; 1657*37da2899SCharles.Forsyth } 1658*37da2899SCharles.Forsyth 1659*37da2899SCharles.Forsyth /* Point at the glyph being constructed. */ 1660*37da2899SCharles.Forsyth if ( p->glyph_enc == -1 ) 1661*37da2899SCharles.Forsyth glyph = font->unencoded + ( font->unencoded_used - 1 ); 1662*37da2899SCharles.Forsyth else 1663*37da2899SCharles.Forsyth glyph = font->glyphs + ( font->glyphs_used - 1 ); 1664*37da2899SCharles.Forsyth 1665*37da2899SCharles.Forsyth /* Check to see whether a bitmap is being constructed. */ 1666*37da2899SCharles.Forsyth if ( p->flags & _BDF_BITMAP ) 1667*37da2899SCharles.Forsyth { 1668*37da2899SCharles.Forsyth /* If there are more rows than are specified in the glyph metrics, */ 1669*37da2899SCharles.Forsyth /* ignore the remaining lines. */ 1670*37da2899SCharles.Forsyth if ( p->row >= (unsigned long)glyph->bbx.height ) 1671*37da2899SCharles.Forsyth { 1672*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) ) 1673*37da2899SCharles.Forsyth { 1674*37da2899SCharles.Forsyth FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding )); 1675*37da2899SCharles.Forsyth p->flags |= _BDF_GLYPH_HEIGHT_CHECK; 1676*37da2899SCharles.Forsyth font->modified = 1; 1677*37da2899SCharles.Forsyth } 1678*37da2899SCharles.Forsyth 1679*37da2899SCharles.Forsyth goto Exit; 1680*37da2899SCharles.Forsyth } 1681*37da2899SCharles.Forsyth 1682*37da2899SCharles.Forsyth /* Only collect the number of nibbles indicated by the glyph */ 1683*37da2899SCharles.Forsyth /* metrics. If there are more columns, they are simply ignored. */ 1684*37da2899SCharles.Forsyth nibbles = glyph->bpr << 1; 1685*37da2899SCharles.Forsyth bp = glyph->bitmap + p->row * glyph->bpr; 1686*37da2899SCharles.Forsyth 1687*37da2899SCharles.Forsyth for ( i = 0, *bp = 0; i < nibbles; i++ ) 1688*37da2899SCharles.Forsyth { 1689*37da2899SCharles.Forsyth c = line[i]; 1690*37da2899SCharles.Forsyth *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] ); 1691*37da2899SCharles.Forsyth if ( i + 1 < nibbles && ( i & 1 ) ) 1692*37da2899SCharles.Forsyth *++bp = 0; 1693*37da2899SCharles.Forsyth } 1694*37da2899SCharles.Forsyth 1695*37da2899SCharles.Forsyth /* Remove possible garbage at the right. */ 1696*37da2899SCharles.Forsyth mask_index = ( glyph->bbx.width * p->font->bpp ) & 7; 1697*37da2899SCharles.Forsyth *bp &= nibble_mask[mask_index]; 1698*37da2899SCharles.Forsyth 1699*37da2899SCharles.Forsyth /* If any line has extra columns, indicate they have been removed. */ 1700*37da2899SCharles.Forsyth if ( ( line[nibbles] == '0' || a2i[(int)line[nibbles]] != 0 ) && 1701*37da2899SCharles.Forsyth !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) ) 1702*37da2899SCharles.Forsyth { 1703*37da2899SCharles.Forsyth FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding )); 1704*37da2899SCharles.Forsyth p->flags |= _BDF_GLYPH_WIDTH_CHECK; 1705*37da2899SCharles.Forsyth font->modified = 1; 1706*37da2899SCharles.Forsyth } 1707*37da2899SCharles.Forsyth 1708*37da2899SCharles.Forsyth p->row++; 1709*37da2899SCharles.Forsyth goto Exit; 1710*37da2899SCharles.Forsyth } 1711*37da2899SCharles.Forsyth 1712*37da2899SCharles.Forsyth /* Expect the SWIDTH (scalable width) field next. */ 1713*37da2899SCharles.Forsyth if ( ft_memcmp( line, "SWIDTH", 6 ) == 0 ) 1714*37da2899SCharles.Forsyth { 1715*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_ENCODING ) ) 1716*37da2899SCharles.Forsyth { 1717*37da2899SCharles.Forsyth /* Missing ENCODING field. */ 1718*37da2899SCharles.Forsyth FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" )); 1719*37da2899SCharles.Forsyth error = BDF_Err_Missing_Encoding_Field; 1720*37da2899SCharles.Forsyth goto Exit; 1721*37da2899SCharles.Forsyth } 1722*37da2899SCharles.Forsyth 1723*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); 1724*37da2899SCharles.Forsyth if ( error ) 1725*37da2899SCharles.Forsyth goto Exit; 1726*37da2899SCharles.Forsyth glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 ); 1727*37da2899SCharles.Forsyth p->flags |= _BDF_SWIDTH; 1728*37da2899SCharles.Forsyth 1729*37da2899SCharles.Forsyth goto Exit; 1730*37da2899SCharles.Forsyth } 1731*37da2899SCharles.Forsyth 1732*37da2899SCharles.Forsyth /* Expect the DWIDTH (scalable width) field next. */ 1733*37da2899SCharles.Forsyth if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 ) 1734*37da2899SCharles.Forsyth { 1735*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list,memory ); 1736*37da2899SCharles.Forsyth if ( error ) 1737*37da2899SCharles.Forsyth goto Exit; 1738*37da2899SCharles.Forsyth glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 ); 1739*37da2899SCharles.Forsyth 1740*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_SWIDTH ) ) 1741*37da2899SCharles.Forsyth { 1742*37da2899SCharles.Forsyth /* Missing SWIDTH field. Emit an auto correction message and set */ 1743*37da2899SCharles.Forsyth /* the scalable width from the device width. */ 1744*37da2899SCharles.Forsyth FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno )); 1745*37da2899SCharles.Forsyth 1746*37da2899SCharles.Forsyth glyph->swidth = (unsigned short)FT_MulDiv( 1747*37da2899SCharles.Forsyth glyph->dwidth, 72000L, 1748*37da2899SCharles.Forsyth (FT_Long)( font->point_size * 1749*37da2899SCharles.Forsyth font->resolution_x ) ); 1750*37da2899SCharles.Forsyth } 1751*37da2899SCharles.Forsyth 1752*37da2899SCharles.Forsyth p->flags |= _BDF_DWIDTH; 1753*37da2899SCharles.Forsyth goto Exit; 1754*37da2899SCharles.Forsyth } 1755*37da2899SCharles.Forsyth 1756*37da2899SCharles.Forsyth /* Expect the BBX field next. */ 1757*37da2899SCharles.Forsyth if ( ft_memcmp( line, "BBX", 3 ) == 0 ) 1758*37da2899SCharles.Forsyth { 1759*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); 1760*37da2899SCharles.Forsyth if ( error ) 1761*37da2899SCharles.Forsyth goto Exit; 1762*37da2899SCharles.Forsyth 1763*37da2899SCharles.Forsyth glyph->bbx.width = _bdf_atos( p->list.field[1], 0, 10 ); 1764*37da2899SCharles.Forsyth glyph->bbx.height = _bdf_atos( p->list.field[2], 0, 10 ); 1765*37da2899SCharles.Forsyth glyph->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 ); 1766*37da2899SCharles.Forsyth glyph->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 ); 1767*37da2899SCharles.Forsyth 1768*37da2899SCharles.Forsyth /* Generate the ascent and descent of the character. */ 1769*37da2899SCharles.Forsyth glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset ); 1770*37da2899SCharles.Forsyth glyph->bbx.descent = (short)( -glyph->bbx.y_offset ); 1771*37da2899SCharles.Forsyth 1772*37da2899SCharles.Forsyth /* Determine the overall font bounding box as the characters are */ 1773*37da2899SCharles.Forsyth /* loaded so corrections can be done later if indicated. */ 1774*37da2899SCharles.Forsyth p->maxas = (short)MAX( glyph->bbx.ascent, p->maxas ); 1775*37da2899SCharles.Forsyth p->maxds = (short)MAX( glyph->bbx.descent, p->maxds ); 1776*37da2899SCharles.Forsyth 1777*37da2899SCharles.Forsyth p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset ); 1778*37da2899SCharles.Forsyth 1779*37da2899SCharles.Forsyth p->maxrb = (short)MAX( p->rbearing, p->maxrb ); 1780*37da2899SCharles.Forsyth p->minlb = (short)MIN( glyph->bbx.x_offset, p->minlb ); 1781*37da2899SCharles.Forsyth p->maxlb = (short)MAX( glyph->bbx.x_offset, p->maxlb ); 1782*37da2899SCharles.Forsyth 1783*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_DWIDTH ) ) 1784*37da2899SCharles.Forsyth { 1785*37da2899SCharles.Forsyth /* Missing DWIDTH field. Emit an auto correction message and set */ 1786*37da2899SCharles.Forsyth /* the device width to the glyph width. */ 1787*37da2899SCharles.Forsyth FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno )); 1788*37da2899SCharles.Forsyth glyph->dwidth = glyph->bbx.width; 1789*37da2899SCharles.Forsyth } 1790*37da2899SCharles.Forsyth 1791*37da2899SCharles.Forsyth /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */ 1792*37da2899SCharles.Forsyth /* value if necessary. */ 1793*37da2899SCharles.Forsyth if ( p->opts->correct_metrics != 0 ) 1794*37da2899SCharles.Forsyth { 1795*37da2899SCharles.Forsyth /* Determine the point size of the glyph. */ 1796*37da2899SCharles.Forsyth unsigned short sw = (unsigned short)FT_MulDiv( 1797*37da2899SCharles.Forsyth glyph->dwidth, 72000L, 1798*37da2899SCharles.Forsyth (FT_Long)( font->point_size * 1799*37da2899SCharles.Forsyth font->resolution_x ) ); 1800*37da2899SCharles.Forsyth 1801*37da2899SCharles.Forsyth 1802*37da2899SCharles.Forsyth if ( sw != glyph->swidth ) 1803*37da2899SCharles.Forsyth { 1804*37da2899SCharles.Forsyth glyph->swidth = sw; 1805*37da2899SCharles.Forsyth 1806*37da2899SCharles.Forsyth if ( p->glyph_enc == -1 ) 1807*37da2899SCharles.Forsyth _bdf_set_glyph_modified( font->umod, 1808*37da2899SCharles.Forsyth font->unencoded_used - 1 ); 1809*37da2899SCharles.Forsyth else 1810*37da2899SCharles.Forsyth _bdf_set_glyph_modified( font->nmod, glyph->encoding ); 1811*37da2899SCharles.Forsyth 1812*37da2899SCharles.Forsyth p->flags |= _BDF_SWIDTH_ADJ; 1813*37da2899SCharles.Forsyth font->modified = 1; 1814*37da2899SCharles.Forsyth } 1815*37da2899SCharles.Forsyth } 1816*37da2899SCharles.Forsyth 1817*37da2899SCharles.Forsyth p->flags |= _BDF_BBX; 1818*37da2899SCharles.Forsyth goto Exit; 1819*37da2899SCharles.Forsyth } 1820*37da2899SCharles.Forsyth 1821*37da2899SCharles.Forsyth /* And finally, gather up the bitmap. */ 1822*37da2899SCharles.Forsyth if ( ft_memcmp( line, "BITMAP", 6 ) == 0 ) 1823*37da2899SCharles.Forsyth { 1824*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_BBX ) ) 1825*37da2899SCharles.Forsyth { 1826*37da2899SCharles.Forsyth /* Missing BBX field. */ 1827*37da2899SCharles.Forsyth FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" )); 1828*37da2899SCharles.Forsyth error = BDF_Err_Missing_Bbx_Field; 1829*37da2899SCharles.Forsyth goto Exit; 1830*37da2899SCharles.Forsyth } 1831*37da2899SCharles.Forsyth 1832*37da2899SCharles.Forsyth /* Allocate enough space for the bitmap. */ 1833*37da2899SCharles.Forsyth glyph->bpr = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3; 1834*37da2899SCharles.Forsyth glyph->bytes = (unsigned short)( glyph->bpr * glyph->bbx.height ); 1835*37da2899SCharles.Forsyth 1836*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) ) 1837*37da2899SCharles.Forsyth goto Exit; 1838*37da2899SCharles.Forsyth 1839*37da2899SCharles.Forsyth p->row = 0; 1840*37da2899SCharles.Forsyth p->flags |= _BDF_BITMAP; 1841*37da2899SCharles.Forsyth 1842*37da2899SCharles.Forsyth goto Exit; 1843*37da2899SCharles.Forsyth } 1844*37da2899SCharles.Forsyth 1845*37da2899SCharles.Forsyth error = BDF_Err_Invalid_File_Format; 1846*37da2899SCharles.Forsyth 1847*37da2899SCharles.Forsyth Exit: 1848*37da2899SCharles.Forsyth return error; 1849*37da2899SCharles.Forsyth } 1850*37da2899SCharles.Forsyth 1851*37da2899SCharles.Forsyth 1852*37da2899SCharles.Forsyth /* Load the font properties. */ 1853*37da2899SCharles.Forsyth static FT_Error _bdf_parse_properties(char * line,unsigned long linelen,unsigned long lineno,void * call_data,void * client_data)1854*37da2899SCharles.Forsyth _bdf_parse_properties( char* line, 1855*37da2899SCharles.Forsyth unsigned long linelen, 1856*37da2899SCharles.Forsyth unsigned long lineno, 1857*37da2899SCharles.Forsyth void* call_data, 1858*37da2899SCharles.Forsyth void* client_data ) 1859*37da2899SCharles.Forsyth { 1860*37da2899SCharles.Forsyth unsigned long vlen; 1861*37da2899SCharles.Forsyth _bdf_line_func_t* next; 1862*37da2899SCharles.Forsyth _bdf_parse_t* p; 1863*37da2899SCharles.Forsyth char* name; 1864*37da2899SCharles.Forsyth char* value; 1865*37da2899SCharles.Forsyth char nbuf[128]; 1866*37da2899SCharles.Forsyth FT_Memory memory; 1867*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 1868*37da2899SCharles.Forsyth 1869*37da2899SCharles.Forsyth FT_UNUSED( lineno ); 1870*37da2899SCharles.Forsyth 1871*37da2899SCharles.Forsyth 1872*37da2899SCharles.Forsyth next = (_bdf_line_func_t *)call_data; 1873*37da2899SCharles.Forsyth p = (_bdf_parse_t *) client_data; 1874*37da2899SCharles.Forsyth 1875*37da2899SCharles.Forsyth memory = p->font->memory; 1876*37da2899SCharles.Forsyth 1877*37da2899SCharles.Forsyth /* Check for the end of the properties. */ 1878*37da2899SCharles.Forsyth if ( ft_memcmp( line, "ENDPROPERTIES", 13 ) == 0 ) 1879*37da2899SCharles.Forsyth { 1880*37da2899SCharles.Forsyth /* If the FONT_ASCENT or FONT_DESCENT properties have not been */ 1881*37da2899SCharles.Forsyth /* encountered yet, then make sure they are added as properties and */ 1882*37da2899SCharles.Forsyth /* make sure they are set from the font bounding box info. */ 1883*37da2899SCharles.Forsyth /* */ 1884*37da2899SCharles.Forsyth /* This is *always* done regardless of the options, because X11 */ 1885*37da2899SCharles.Forsyth /* requires these two fields to compile fonts. */ 1886*37da2899SCharles.Forsyth if ( bdf_get_font_property( p->font, (char *)"FONT_ASCENT" ) == 0 ) 1887*37da2899SCharles.Forsyth { 1888*37da2899SCharles.Forsyth p->font->font_ascent = p->font->bbx.ascent; 1889*37da2899SCharles.Forsyth ft_sprintf( nbuf, "%hd", p->font->bbx.ascent ); 1890*37da2899SCharles.Forsyth error = _bdf_add_property( p->font, (char *)"FONT_ASCENT", nbuf ); 1891*37da2899SCharles.Forsyth if ( error ) 1892*37da2899SCharles.Forsyth goto Exit; 1893*37da2899SCharles.Forsyth 1894*37da2899SCharles.Forsyth FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent )); 1895*37da2899SCharles.Forsyth p->font->modified = 1; 1896*37da2899SCharles.Forsyth } 1897*37da2899SCharles.Forsyth 1898*37da2899SCharles.Forsyth if ( bdf_get_font_property( p->font, (char *)"FONT_DESCENT" ) == 0 ) 1899*37da2899SCharles.Forsyth { 1900*37da2899SCharles.Forsyth p->font->font_descent = p->font->bbx.descent; 1901*37da2899SCharles.Forsyth ft_sprintf( nbuf, "%hd", p->font->bbx.descent ); 1902*37da2899SCharles.Forsyth error = _bdf_add_property( p->font, (char *)"FONT_DESCENT", nbuf ); 1903*37da2899SCharles.Forsyth if ( error ) 1904*37da2899SCharles.Forsyth goto Exit; 1905*37da2899SCharles.Forsyth 1906*37da2899SCharles.Forsyth FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent )); 1907*37da2899SCharles.Forsyth p->font->modified = 1; 1908*37da2899SCharles.Forsyth } 1909*37da2899SCharles.Forsyth 1910*37da2899SCharles.Forsyth p->flags &= ~_BDF_PROPS; 1911*37da2899SCharles.Forsyth *next = _bdf_parse_glyphs; 1912*37da2899SCharles.Forsyth 1913*37da2899SCharles.Forsyth goto Exit; 1914*37da2899SCharles.Forsyth } 1915*37da2899SCharles.Forsyth 1916*37da2899SCharles.Forsyth /* Ignore the _XFREE86_GLYPH_RANGES properties. */ 1917*37da2899SCharles.Forsyth if ( ft_memcmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 ) 1918*37da2899SCharles.Forsyth goto Exit; 1919*37da2899SCharles.Forsyth 1920*37da2899SCharles.Forsyth /* Handle COMMENT fields and properties in a special way to preserve */ 1921*37da2899SCharles.Forsyth /* the spacing. */ 1922*37da2899SCharles.Forsyth if ( ft_memcmp( line, "COMMENT", 7 ) == 0 ) 1923*37da2899SCharles.Forsyth { 1924*37da2899SCharles.Forsyth name = value = line; 1925*37da2899SCharles.Forsyth value += 7; 1926*37da2899SCharles.Forsyth if ( *value ) 1927*37da2899SCharles.Forsyth *value++ = 0; 1928*37da2899SCharles.Forsyth error = _bdf_add_property( p->font, name, value ); 1929*37da2899SCharles.Forsyth if ( error ) 1930*37da2899SCharles.Forsyth goto Exit; 1931*37da2899SCharles.Forsyth } 1932*37da2899SCharles.Forsyth else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) ) 1933*37da2899SCharles.Forsyth { 1934*37da2899SCharles.Forsyth error = _bdf_add_property( p->font, name, value ); 1935*37da2899SCharles.Forsyth if ( error ) 1936*37da2899SCharles.Forsyth goto Exit; 1937*37da2899SCharles.Forsyth } 1938*37da2899SCharles.Forsyth else 1939*37da2899SCharles.Forsyth { 1940*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); 1941*37da2899SCharles.Forsyth if ( error ) 1942*37da2899SCharles.Forsyth goto Exit; 1943*37da2899SCharles.Forsyth name = p->list.field[0]; 1944*37da2899SCharles.Forsyth 1945*37da2899SCharles.Forsyth _bdf_shift( 1, &p->list ); 1946*37da2899SCharles.Forsyth value = _bdf_join( ' ', &vlen, &p->list ); 1947*37da2899SCharles.Forsyth 1948*37da2899SCharles.Forsyth error = _bdf_add_property( p->font, name, value ); 1949*37da2899SCharles.Forsyth if ( error ) 1950*37da2899SCharles.Forsyth goto Exit; 1951*37da2899SCharles.Forsyth } 1952*37da2899SCharles.Forsyth 1953*37da2899SCharles.Forsyth Exit: 1954*37da2899SCharles.Forsyth return error; 1955*37da2899SCharles.Forsyth } 1956*37da2899SCharles.Forsyth 1957*37da2899SCharles.Forsyth 1958*37da2899SCharles.Forsyth /* Load the font header. */ 1959*37da2899SCharles.Forsyth static FT_Error _bdf_parse_start(char * line,unsigned long linelen,unsigned long lineno,void * call_data,void * client_data)1960*37da2899SCharles.Forsyth _bdf_parse_start( char* line, 1961*37da2899SCharles.Forsyth unsigned long linelen, 1962*37da2899SCharles.Forsyth unsigned long lineno, 1963*37da2899SCharles.Forsyth void* call_data, 1964*37da2899SCharles.Forsyth void* client_data ) 1965*37da2899SCharles.Forsyth { 1966*37da2899SCharles.Forsyth unsigned long slen; 1967*37da2899SCharles.Forsyth _bdf_line_func_t* next; 1968*37da2899SCharles.Forsyth _bdf_parse_t* p; 1969*37da2899SCharles.Forsyth bdf_font_t* font; 1970*37da2899SCharles.Forsyth char *s; 1971*37da2899SCharles.Forsyth 1972*37da2899SCharles.Forsyth FT_Memory memory = NULL; 1973*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 1974*37da2899SCharles.Forsyth 1975*37da2899SCharles.Forsyth FT_UNUSED( lineno ); /* only used in debug mode */ 1976*37da2899SCharles.Forsyth 1977*37da2899SCharles.Forsyth 1978*37da2899SCharles.Forsyth next = (_bdf_line_func_t *)call_data; 1979*37da2899SCharles.Forsyth p = (_bdf_parse_t *) client_data; 1980*37da2899SCharles.Forsyth 1981*37da2899SCharles.Forsyth if ( p->font ) 1982*37da2899SCharles.Forsyth memory = p->font->memory; 1983*37da2899SCharles.Forsyth 1984*37da2899SCharles.Forsyth /* Check for a comment. This is done to handle those fonts that have */ 1985*37da2899SCharles.Forsyth /* comments before the STARTFONT line for some reason. */ 1986*37da2899SCharles.Forsyth if ( ft_memcmp( line, "COMMENT", 7 ) == 0 ) 1987*37da2899SCharles.Forsyth { 1988*37da2899SCharles.Forsyth if ( p->opts->keep_comments != 0 && p->font != 0 ) 1989*37da2899SCharles.Forsyth { 1990*37da2899SCharles.Forsyth linelen -= 7; 1991*37da2899SCharles.Forsyth 1992*37da2899SCharles.Forsyth s = line + 7; 1993*37da2899SCharles.Forsyth if ( *s != 0 ) 1994*37da2899SCharles.Forsyth { 1995*37da2899SCharles.Forsyth s++; 1996*37da2899SCharles.Forsyth linelen--; 1997*37da2899SCharles.Forsyth } 1998*37da2899SCharles.Forsyth 1999*37da2899SCharles.Forsyth error = _bdf_add_comment( p->font, s, linelen ); 2000*37da2899SCharles.Forsyth if ( error ) 2001*37da2899SCharles.Forsyth goto Exit; 2002*37da2899SCharles.Forsyth /* here font is not defined! */ 2003*37da2899SCharles.Forsyth } 2004*37da2899SCharles.Forsyth 2005*37da2899SCharles.Forsyth goto Exit; 2006*37da2899SCharles.Forsyth } 2007*37da2899SCharles.Forsyth 2008*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_START ) ) 2009*37da2899SCharles.Forsyth { 2010*37da2899SCharles.Forsyth memory = p->memory; 2011*37da2899SCharles.Forsyth 2012*37da2899SCharles.Forsyth if ( ft_memcmp( line, "STARTFONT", 9 ) != 0 ) 2013*37da2899SCharles.Forsyth { 2014*37da2899SCharles.Forsyth /* No STARTFONT field is a good indication of a problem. */ 2015*37da2899SCharles.Forsyth error = BDF_Err_Missing_Startfont_Field; 2016*37da2899SCharles.Forsyth goto Exit; 2017*37da2899SCharles.Forsyth } 2018*37da2899SCharles.Forsyth 2019*37da2899SCharles.Forsyth p->flags = _BDF_START; 2020*37da2899SCharles.Forsyth font = p->font = 0; 2021*37da2899SCharles.Forsyth 2022*37da2899SCharles.Forsyth if ( FT_NEW( font ) ) 2023*37da2899SCharles.Forsyth goto Exit; 2024*37da2899SCharles.Forsyth p->font = font; 2025*37da2899SCharles.Forsyth 2026*37da2899SCharles.Forsyth font->memory = p->memory; 2027*37da2899SCharles.Forsyth p->memory = 0; 2028*37da2899SCharles.Forsyth 2029*37da2899SCharles.Forsyth { /* setup */ 2030*37da2899SCharles.Forsyth unsigned long i; 2031*37da2899SCharles.Forsyth bdf_property_t* prop; 2032*37da2899SCharles.Forsyth 2033*37da2899SCharles.Forsyth 2034*37da2899SCharles.Forsyth error = hash_init( &(font->proptbl), memory ); 2035*37da2899SCharles.Forsyth if ( error ) 2036*37da2899SCharles.Forsyth goto Exit; 2037*37da2899SCharles.Forsyth for ( i = 0, prop = (bdf_property_t*)_bdf_properties; 2038*37da2899SCharles.Forsyth i < _num_bdf_properties; i++, prop++ ) 2039*37da2899SCharles.Forsyth { 2040*37da2899SCharles.Forsyth error = hash_insert( prop->name, (void *)i, 2041*37da2899SCharles.Forsyth &(font->proptbl), memory ); 2042*37da2899SCharles.Forsyth if ( error ) 2043*37da2899SCharles.Forsyth goto Exit; 2044*37da2899SCharles.Forsyth } 2045*37da2899SCharles.Forsyth } 2046*37da2899SCharles.Forsyth 2047*37da2899SCharles.Forsyth if ( FT_ALLOC( p->font->internal, sizeof ( hashtable ) ) ) 2048*37da2899SCharles.Forsyth goto Exit; 2049*37da2899SCharles.Forsyth error = hash_init( (hashtable *)p->font->internal,memory ); 2050*37da2899SCharles.Forsyth if ( error ) 2051*37da2899SCharles.Forsyth goto Exit; 2052*37da2899SCharles.Forsyth p->font->spacing = p->opts->font_spacing; 2053*37da2899SCharles.Forsyth p->font->default_glyph = -1; 2054*37da2899SCharles.Forsyth 2055*37da2899SCharles.Forsyth goto Exit; 2056*37da2899SCharles.Forsyth } 2057*37da2899SCharles.Forsyth 2058*37da2899SCharles.Forsyth /* Check for the start of the properties. */ 2059*37da2899SCharles.Forsyth if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 ) 2060*37da2899SCharles.Forsyth { 2061*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); 2062*37da2899SCharles.Forsyth if ( error ) 2063*37da2899SCharles.Forsyth goto Exit; 2064*37da2899SCharles.Forsyth p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 ); 2065*37da2899SCharles.Forsyth 2066*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( p->font->props, p->cnt ) ) 2067*37da2899SCharles.Forsyth goto Exit; 2068*37da2899SCharles.Forsyth 2069*37da2899SCharles.Forsyth p->flags |= _BDF_PROPS; 2070*37da2899SCharles.Forsyth *next = _bdf_parse_properties; 2071*37da2899SCharles.Forsyth 2072*37da2899SCharles.Forsyth goto Exit; 2073*37da2899SCharles.Forsyth } 2074*37da2899SCharles.Forsyth 2075*37da2899SCharles.Forsyth /* Check for the FONTBOUNDINGBOX field. */ 2076*37da2899SCharles.Forsyth if ( ft_memcmp( line, "FONTBOUNDINGBOX", 15 ) == 0 ) 2077*37da2899SCharles.Forsyth { 2078*37da2899SCharles.Forsyth if ( !(p->flags & _BDF_SIZE ) ) 2079*37da2899SCharles.Forsyth { 2080*37da2899SCharles.Forsyth /* Missing the SIZE field. */ 2081*37da2899SCharles.Forsyth FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" )); 2082*37da2899SCharles.Forsyth error = BDF_Err_Missing_Size_Field; 2083*37da2899SCharles.Forsyth goto Exit; 2084*37da2899SCharles.Forsyth } 2085*37da2899SCharles.Forsyth 2086*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list , memory ); 2087*37da2899SCharles.Forsyth if ( error ) 2088*37da2899SCharles.Forsyth goto Exit; 2089*37da2899SCharles.Forsyth 2090*37da2899SCharles.Forsyth p->font->bbx.width = _bdf_atos( p->list.field[1], 0, 10 ); 2091*37da2899SCharles.Forsyth p->font->bbx.height = _bdf_atos( p->list.field[2], 0, 10 ); 2092*37da2899SCharles.Forsyth 2093*37da2899SCharles.Forsyth p->font->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 ); 2094*37da2899SCharles.Forsyth p->font->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 ); 2095*37da2899SCharles.Forsyth 2096*37da2899SCharles.Forsyth p->font->bbx.ascent = (short)( p->font->bbx.height + 2097*37da2899SCharles.Forsyth p->font->bbx.y_offset ); 2098*37da2899SCharles.Forsyth 2099*37da2899SCharles.Forsyth p->font->bbx.descent = (short)( -p->font->bbx.y_offset ); 2100*37da2899SCharles.Forsyth 2101*37da2899SCharles.Forsyth p->flags |= _BDF_FONT_BBX; 2102*37da2899SCharles.Forsyth 2103*37da2899SCharles.Forsyth goto Exit; 2104*37da2899SCharles.Forsyth } 2105*37da2899SCharles.Forsyth 2106*37da2899SCharles.Forsyth /* The next thing to check for is the FONT field. */ 2107*37da2899SCharles.Forsyth if ( ft_memcmp( line, "FONT", 4 ) == 0 ) 2108*37da2899SCharles.Forsyth { 2109*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list , memory ); 2110*37da2899SCharles.Forsyth if ( error ) 2111*37da2899SCharles.Forsyth goto Exit; 2112*37da2899SCharles.Forsyth _bdf_shift( 1, &p->list ); 2113*37da2899SCharles.Forsyth 2114*37da2899SCharles.Forsyth s = _bdf_join( ' ', &slen, &p->list ); 2115*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) ) 2116*37da2899SCharles.Forsyth goto Exit; 2117*37da2899SCharles.Forsyth FT_MEM_COPY( p->font->name, s, slen + 1 ); 2118*37da2899SCharles.Forsyth 2119*37da2899SCharles.Forsyth /* If the font name is an XLFD name, set the spacing to the one in */ 2120*37da2899SCharles.Forsyth /* the font name. If there is no spacing fall back on the default. */ 2121*37da2899SCharles.Forsyth error = _bdf_set_default_spacing( p->font, p->opts ); 2122*37da2899SCharles.Forsyth if ( error ) 2123*37da2899SCharles.Forsyth goto Exit; 2124*37da2899SCharles.Forsyth 2125*37da2899SCharles.Forsyth p->flags |= _BDF_FONT_NAME; 2126*37da2899SCharles.Forsyth 2127*37da2899SCharles.Forsyth goto Exit; 2128*37da2899SCharles.Forsyth } 2129*37da2899SCharles.Forsyth 2130*37da2899SCharles.Forsyth /* Check for the SIZE field. */ 2131*37da2899SCharles.Forsyth if ( ft_memcmp( line, "SIZE", 4 ) == 0 ) 2132*37da2899SCharles.Forsyth { 2133*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_FONT_NAME ) ) 2134*37da2899SCharles.Forsyth { 2135*37da2899SCharles.Forsyth /* Missing the FONT field. */ 2136*37da2899SCharles.Forsyth FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" )); 2137*37da2899SCharles.Forsyth error = BDF_Err_Missing_Font_Field; 2138*37da2899SCharles.Forsyth goto Exit; 2139*37da2899SCharles.Forsyth } 2140*37da2899SCharles.Forsyth 2141*37da2899SCharles.Forsyth error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); 2142*37da2899SCharles.Forsyth if ( error ) 2143*37da2899SCharles.Forsyth goto Exit; 2144*37da2899SCharles.Forsyth 2145*37da2899SCharles.Forsyth p->font->point_size = _bdf_atoul( p->list.field[1], 0, 10 ); 2146*37da2899SCharles.Forsyth p->font->resolution_x = _bdf_atoul( p->list.field[2], 0, 10 ); 2147*37da2899SCharles.Forsyth p->font->resolution_y = _bdf_atoul( p->list.field[3], 0, 10 ); 2148*37da2899SCharles.Forsyth 2149*37da2899SCharles.Forsyth /* Check for the bits per pixel field. */ 2150*37da2899SCharles.Forsyth if ( p->list.used == 5 ) 2151*37da2899SCharles.Forsyth { 2152*37da2899SCharles.Forsyth unsigned short bitcount, i, shift; 2153*37da2899SCharles.Forsyth 2154*37da2899SCharles.Forsyth 2155*37da2899SCharles.Forsyth p->font->bpp = (unsigned short)_bdf_atos( p->list.field[4], 0, 10 ); 2156*37da2899SCharles.Forsyth 2157*37da2899SCharles.Forsyth /* Only values 1, 2, 4, 8 are allowed. */ 2158*37da2899SCharles.Forsyth shift = p->font->bpp; 2159*37da2899SCharles.Forsyth bitcount = 0; 2160*37da2899SCharles.Forsyth for ( i = 0; shift > 0; i++ ) 2161*37da2899SCharles.Forsyth { 2162*37da2899SCharles.Forsyth if ( shift & 1 ) 2163*37da2899SCharles.Forsyth bitcount = i; 2164*37da2899SCharles.Forsyth shift >>= 1; 2165*37da2899SCharles.Forsyth } 2166*37da2899SCharles.Forsyth 2167*37da2899SCharles.Forsyth shift = (short)( ( bitcount > 3 ) ? 8 : ( 1 << bitcount ) ); 2168*37da2899SCharles.Forsyth 2169*37da2899SCharles.Forsyth if ( p->font->bpp > shift || p->font->bpp != shift ) 2170*37da2899SCharles.Forsyth { 2171*37da2899SCharles.Forsyth /* select next higher value */ 2172*37da2899SCharles.Forsyth p->font->bpp = (unsigned short)( shift << 1 ); 2173*37da2899SCharles.Forsyth FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp )); 2174*37da2899SCharles.Forsyth } 2175*37da2899SCharles.Forsyth } 2176*37da2899SCharles.Forsyth else 2177*37da2899SCharles.Forsyth p->font->bpp = 1; 2178*37da2899SCharles.Forsyth 2179*37da2899SCharles.Forsyth p->flags |= _BDF_SIZE; 2180*37da2899SCharles.Forsyth 2181*37da2899SCharles.Forsyth goto Exit; 2182*37da2899SCharles.Forsyth } 2183*37da2899SCharles.Forsyth 2184*37da2899SCharles.Forsyth error = BDF_Err_Invalid_File_Format; 2185*37da2899SCharles.Forsyth 2186*37da2899SCharles.Forsyth Exit: 2187*37da2899SCharles.Forsyth return error; 2188*37da2899SCharles.Forsyth } 2189*37da2899SCharles.Forsyth 2190*37da2899SCharles.Forsyth 2191*37da2899SCharles.Forsyth /*************************************************************************/ 2192*37da2899SCharles.Forsyth /* */ 2193*37da2899SCharles.Forsyth /* API. */ 2194*37da2899SCharles.Forsyth /* */ 2195*37da2899SCharles.Forsyth /*************************************************************************/ 2196*37da2899SCharles.Forsyth 2197*37da2899SCharles.Forsyth 2198*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) bdf_load_font(FT_Stream stream,FT_Memory extmemory,bdf_options_t * opts,bdf_font_t ** font)2199*37da2899SCharles.Forsyth bdf_load_font( FT_Stream stream, 2200*37da2899SCharles.Forsyth FT_Memory extmemory, 2201*37da2899SCharles.Forsyth bdf_options_t* opts, 2202*37da2899SCharles.Forsyth bdf_font_t* *font ) 2203*37da2899SCharles.Forsyth { 2204*37da2899SCharles.Forsyth unsigned long lineno; 2205*37da2899SCharles.Forsyth _bdf_parse_t *p; 2206*37da2899SCharles.Forsyth 2207*37da2899SCharles.Forsyth FT_Memory memory = extmemory; 2208*37da2899SCharles.Forsyth FT_Error error = BDF_Err_Ok; 2209*37da2899SCharles.Forsyth 2210*37da2899SCharles.Forsyth 2211*37da2899SCharles.Forsyth if ( FT_ALLOC( p, sizeof ( _bdf_parse_t ) ) ) 2212*37da2899SCharles.Forsyth goto Exit; 2213*37da2899SCharles.Forsyth 2214*37da2899SCharles.Forsyth memory = NULL; 2215*37da2899SCharles.Forsyth p->opts = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts ); 2216*37da2899SCharles.Forsyth p->minlb = 32767; 2217*37da2899SCharles.Forsyth p->memory = extmemory; /* only during font creation */ 2218*37da2899SCharles.Forsyth 2219*37da2899SCharles.Forsyth error = _bdf_readstream( stream, _bdf_parse_start, 2220*37da2899SCharles.Forsyth (void *)p, &lineno ); 2221*37da2899SCharles.Forsyth if ( error ) 2222*37da2899SCharles.Forsyth goto Exit; 2223*37da2899SCharles.Forsyth 2224*37da2899SCharles.Forsyth if ( p->font != 0 ) 2225*37da2899SCharles.Forsyth { 2226*37da2899SCharles.Forsyth /* If the font is not proportional, set the font's monowidth */ 2227*37da2899SCharles.Forsyth /* field to the width of the font bounding box. */ 2228*37da2899SCharles.Forsyth memory = p->font->memory; 2229*37da2899SCharles.Forsyth 2230*37da2899SCharles.Forsyth if ( p->font->spacing != BDF_PROPORTIONAL ) 2231*37da2899SCharles.Forsyth p->font->monowidth = p->font->bbx.width; 2232*37da2899SCharles.Forsyth 2233*37da2899SCharles.Forsyth /* If the number of glyphs loaded is not that of the original count, */ 2234*37da2899SCharles.Forsyth /* indicate the difference. */ 2235*37da2899SCharles.Forsyth if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used ) 2236*37da2899SCharles.Forsyth { 2237*37da2899SCharles.Forsyth FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt, 2238*37da2899SCharles.Forsyth p->font->glyphs_used + p->font->unencoded_used )); 2239*37da2899SCharles.Forsyth p->font->modified = 1; 2240*37da2899SCharles.Forsyth } 2241*37da2899SCharles.Forsyth 2242*37da2899SCharles.Forsyth /* Once the font has been loaded, adjust the overall font metrics if */ 2243*37da2899SCharles.Forsyth /* necessary. */ 2244*37da2899SCharles.Forsyth if ( p->opts->correct_metrics != 0 && 2245*37da2899SCharles.Forsyth ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) ) 2246*37da2899SCharles.Forsyth { 2247*37da2899SCharles.Forsyth if ( p->maxrb - p->minlb != p->font->bbx.width ) 2248*37da2899SCharles.Forsyth { 2249*37da2899SCharles.Forsyth FT_TRACE2(( "bdf_load_font: " ACMSG3, 2250*37da2899SCharles.Forsyth p->font->bbx.width, p->maxrb - p->minlb )); 2251*37da2899SCharles.Forsyth p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb ); 2252*37da2899SCharles.Forsyth p->font->modified = 1; 2253*37da2899SCharles.Forsyth } 2254*37da2899SCharles.Forsyth 2255*37da2899SCharles.Forsyth if ( p->font->bbx.x_offset != p->minlb ) 2256*37da2899SCharles.Forsyth { 2257*37da2899SCharles.Forsyth FT_TRACE2(( "bdf_load_font: " ACMSG4, 2258*37da2899SCharles.Forsyth p->font->bbx.x_offset, p->minlb )); 2259*37da2899SCharles.Forsyth p->font->bbx.x_offset = p->minlb; 2260*37da2899SCharles.Forsyth p->font->modified = 1; 2261*37da2899SCharles.Forsyth } 2262*37da2899SCharles.Forsyth 2263*37da2899SCharles.Forsyth if ( p->font->bbx.ascent != p->maxas ) 2264*37da2899SCharles.Forsyth { 2265*37da2899SCharles.Forsyth FT_TRACE2(( "bdf_load_font: " ACMSG5, 2266*37da2899SCharles.Forsyth p->font->bbx.ascent, p->maxas )); 2267*37da2899SCharles.Forsyth p->font->bbx.ascent = p->maxas; 2268*37da2899SCharles.Forsyth p->font->modified = 1; 2269*37da2899SCharles.Forsyth } 2270*37da2899SCharles.Forsyth 2271*37da2899SCharles.Forsyth if ( p->font->bbx.descent != p->maxds ) 2272*37da2899SCharles.Forsyth { 2273*37da2899SCharles.Forsyth FT_TRACE2(( "bdf_load_font: " ACMSG6, 2274*37da2899SCharles.Forsyth p->font->bbx.descent, p->maxds )); 2275*37da2899SCharles.Forsyth p->font->bbx.descent = p->maxds; 2276*37da2899SCharles.Forsyth p->font->bbx.y_offset = (short)( -p->maxds ); 2277*37da2899SCharles.Forsyth p->font->modified = 1; 2278*37da2899SCharles.Forsyth } 2279*37da2899SCharles.Forsyth 2280*37da2899SCharles.Forsyth if ( p->maxas + p->maxds != p->font->bbx.height ) 2281*37da2899SCharles.Forsyth { 2282*37da2899SCharles.Forsyth FT_TRACE2(( "bdf_load_font: " ACMSG7, 2283*37da2899SCharles.Forsyth p->font->bbx.height, p->maxas + p->maxds )); 2284*37da2899SCharles.Forsyth p->font->bbx.height = (unsigned short)( p->maxas + p->maxds ); 2285*37da2899SCharles.Forsyth } 2286*37da2899SCharles.Forsyth 2287*37da2899SCharles.Forsyth if ( p->flags & _BDF_SWIDTH_ADJ ) 2288*37da2899SCharles.Forsyth FT_TRACE2(( "bdf_load_font: " ACMSG8 )); 2289*37da2899SCharles.Forsyth } 2290*37da2899SCharles.Forsyth } 2291*37da2899SCharles.Forsyth 2292*37da2899SCharles.Forsyth if ( p->flags & _BDF_START ) 2293*37da2899SCharles.Forsyth { 2294*37da2899SCharles.Forsyth { 2295*37da2899SCharles.Forsyth /* The ENDFONT field was never reached or did not exist. */ 2296*37da2899SCharles.Forsyth if ( !( p->flags & _BDF_GLYPHS ) ) 2297*37da2899SCharles.Forsyth /* Error happened while parsing header. */ 2298*37da2899SCharles.Forsyth FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno )); 2299*37da2899SCharles.Forsyth else 2300*37da2899SCharles.Forsyth /* Error happened when parsing glyphs. */ 2301*37da2899SCharles.Forsyth FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno )); 2302*37da2899SCharles.Forsyth } 2303*37da2899SCharles.Forsyth } 2304*37da2899SCharles.Forsyth 2305*37da2899SCharles.Forsyth /* Free up the list used during the parsing. */ 2306*37da2899SCharles.Forsyth if ( memory != NULL ) 2307*37da2899SCharles.Forsyth FT_FREE( p->list.field ); 2308*37da2899SCharles.Forsyth 2309*37da2899SCharles.Forsyth if ( p->font != 0 ) 2310*37da2899SCharles.Forsyth { 2311*37da2899SCharles.Forsyth /* Make sure the comments are NULL terminated if they exist. */ 2312*37da2899SCharles.Forsyth memory = p->font->memory; 2313*37da2899SCharles.Forsyth 2314*37da2899SCharles.Forsyth if ( p->font->comments_len > 0 ) { 2315*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( p->font->comments, 2316*37da2899SCharles.Forsyth p->font->comments_len, 2317*37da2899SCharles.Forsyth p->font->comments_len + 1 ) ) 2318*37da2899SCharles.Forsyth goto Exit; 2319*37da2899SCharles.Forsyth 2320*37da2899SCharles.Forsyth p->font->comments[p->font->comments_len] = 0; 2321*37da2899SCharles.Forsyth } 2322*37da2899SCharles.Forsyth } 2323*37da2899SCharles.Forsyth else if ( error == BDF_Err_Ok ) 2324*37da2899SCharles.Forsyth error = BDF_Err_Invalid_File_Format; 2325*37da2899SCharles.Forsyth 2326*37da2899SCharles.Forsyth *font = p->font; 2327*37da2899SCharles.Forsyth 2328*37da2899SCharles.Forsyth Exit: 2329*37da2899SCharles.Forsyth if ( p ) 2330*37da2899SCharles.Forsyth { 2331*37da2899SCharles.Forsyth memory = extmemory; 2332*37da2899SCharles.Forsyth FT_FREE( p ); 2333*37da2899SCharles.Forsyth } 2334*37da2899SCharles.Forsyth 2335*37da2899SCharles.Forsyth return error; 2336*37da2899SCharles.Forsyth } 2337*37da2899SCharles.Forsyth 2338*37da2899SCharles.Forsyth 2339*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) bdf_free_font(bdf_font_t * font)2340*37da2899SCharles.Forsyth bdf_free_font( bdf_font_t* font ) 2341*37da2899SCharles.Forsyth { 2342*37da2899SCharles.Forsyth bdf_property_t* prop; 2343*37da2899SCharles.Forsyth unsigned long i; 2344*37da2899SCharles.Forsyth bdf_glyph_t* glyphs; 2345*37da2899SCharles.Forsyth FT_Memory memory; 2346*37da2899SCharles.Forsyth 2347*37da2899SCharles.Forsyth 2348*37da2899SCharles.Forsyth if ( font == 0 ) 2349*37da2899SCharles.Forsyth return; 2350*37da2899SCharles.Forsyth 2351*37da2899SCharles.Forsyth memory = font->memory; 2352*37da2899SCharles.Forsyth 2353*37da2899SCharles.Forsyth FT_FREE( font->name ); 2354*37da2899SCharles.Forsyth 2355*37da2899SCharles.Forsyth /* Free up the internal hash table of property names. */ 2356*37da2899SCharles.Forsyth if ( font->internal ) 2357*37da2899SCharles.Forsyth { 2358*37da2899SCharles.Forsyth hash_free( (hashtable *)font->internal, memory ); 2359*37da2899SCharles.Forsyth FT_FREE( font->internal ); 2360*37da2899SCharles.Forsyth } 2361*37da2899SCharles.Forsyth 2362*37da2899SCharles.Forsyth /* Free up the comment info. */ 2363*37da2899SCharles.Forsyth FT_FREE( font->comments ); 2364*37da2899SCharles.Forsyth 2365*37da2899SCharles.Forsyth /* Free up the properties. */ 2366*37da2899SCharles.Forsyth for ( i = 0; i < font->props_size; i++ ) 2367*37da2899SCharles.Forsyth { 2368*37da2899SCharles.Forsyth if ( font->props[i].format == BDF_ATOM ) 2369*37da2899SCharles.Forsyth FT_FREE( font->props[i].value.atom ); 2370*37da2899SCharles.Forsyth } 2371*37da2899SCharles.Forsyth 2372*37da2899SCharles.Forsyth FT_FREE( font->props ); 2373*37da2899SCharles.Forsyth 2374*37da2899SCharles.Forsyth /* Free up the character info. */ 2375*37da2899SCharles.Forsyth for ( i = 0, glyphs = font->glyphs; 2376*37da2899SCharles.Forsyth i < font->glyphs_used; i++, glyphs++ ) 2377*37da2899SCharles.Forsyth { 2378*37da2899SCharles.Forsyth FT_FREE( glyphs->name ); 2379*37da2899SCharles.Forsyth FT_FREE( glyphs->bitmap ); 2380*37da2899SCharles.Forsyth } 2381*37da2899SCharles.Forsyth 2382*37da2899SCharles.Forsyth for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used; 2383*37da2899SCharles.Forsyth i++, glyphs++ ) 2384*37da2899SCharles.Forsyth { 2385*37da2899SCharles.Forsyth FT_FREE( glyphs->name ); 2386*37da2899SCharles.Forsyth FT_FREE( glyphs->bitmap ); 2387*37da2899SCharles.Forsyth } 2388*37da2899SCharles.Forsyth 2389*37da2899SCharles.Forsyth FT_FREE( font->glyphs ); 2390*37da2899SCharles.Forsyth FT_FREE( font->unencoded ); 2391*37da2899SCharles.Forsyth 2392*37da2899SCharles.Forsyth /* Free up the overflow storage if it was used. */ 2393*37da2899SCharles.Forsyth for ( i = 0, glyphs = font->overflow.glyphs; 2394*37da2899SCharles.Forsyth i < font->overflow.glyphs_used; i++, glyphs++ ) 2395*37da2899SCharles.Forsyth { 2396*37da2899SCharles.Forsyth FT_FREE( glyphs->name ); 2397*37da2899SCharles.Forsyth FT_FREE( glyphs->bitmap ); 2398*37da2899SCharles.Forsyth } 2399*37da2899SCharles.Forsyth 2400*37da2899SCharles.Forsyth FT_FREE( font->overflow.glyphs ); 2401*37da2899SCharles.Forsyth 2402*37da2899SCharles.Forsyth /* bdf_cleanup */ 2403*37da2899SCharles.Forsyth hash_free( &(font->proptbl), memory ); 2404*37da2899SCharles.Forsyth 2405*37da2899SCharles.Forsyth /* Free up the user defined properties. */ 2406*37da2899SCharles.Forsyth for (prop = font->user_props, i = 0; 2407*37da2899SCharles.Forsyth i < font->nuser_props; i++, prop++ ) 2408*37da2899SCharles.Forsyth { 2409*37da2899SCharles.Forsyth FT_FREE( prop->name ); 2410*37da2899SCharles.Forsyth if ( prop->format == BDF_ATOM ) 2411*37da2899SCharles.Forsyth FT_FREE( prop->value.atom ); 2412*37da2899SCharles.Forsyth } 2413*37da2899SCharles.Forsyth 2414*37da2899SCharles.Forsyth FT_FREE( font->user_props ); 2415*37da2899SCharles.Forsyth 2416*37da2899SCharles.Forsyth /* FREE( font ); */ /* XXX Fixme */ 2417*37da2899SCharles.Forsyth } 2418*37da2899SCharles.Forsyth 2419*37da2899SCharles.Forsyth 2420*37da2899SCharles.Forsyth FT_LOCAL_DEF( bdf_property_t * ) bdf_get_font_property(bdf_font_t * font,char * name)2421*37da2899SCharles.Forsyth bdf_get_font_property( bdf_font_t* font, 2422*37da2899SCharles.Forsyth char* name ) 2423*37da2899SCharles.Forsyth { 2424*37da2899SCharles.Forsyth hashnode hn; 2425*37da2899SCharles.Forsyth 2426*37da2899SCharles.Forsyth 2427*37da2899SCharles.Forsyth if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 ) 2428*37da2899SCharles.Forsyth return 0; 2429*37da2899SCharles.Forsyth 2430*37da2899SCharles.Forsyth hn = hash_lookup( name, (hashtable *)font->internal ); 2431*37da2899SCharles.Forsyth 2432*37da2899SCharles.Forsyth return hn ? ( font->props + (unsigned long)hn->data ) : 0; 2433*37da2899SCharles.Forsyth } 2434*37da2899SCharles.Forsyth 2435*37da2899SCharles.Forsyth 2436*37da2899SCharles.Forsyth /* END */ 2437