00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <ft2build.h>
00035
00036 #include FT_FREETYPE_H
00037 #include FT_INTERNAL_DEBUG_H
00038 #include FT_INTERNAL_STREAM_H
00039 #include FT_INTERNAL_OBJECTS_H
00040
00041 #include "bdf.h"
00042 #include "bdferror.h"
00043
00044
00045
00046
00047
00048
00049
00050
00051 #undef FT_COMPONENT
00052 #define FT_COMPONENT trace_bdflib
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 static const bdf_options_t _bdf_opts =
00063 {
00064 1,
00065 1,
00066 0,
00067 BDF_PROPORTIONAL
00068 };
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 static const bdf_property_t _bdf_properties[] =
00081 {
00082 { (char *)"ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } },
00083 { (char *)"AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
00084 { (char *)"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
00085 { (char *)"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
00086 { (char *)"CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
00087 { (char *)"CHARSET_COLLECTIONS", BDF_ATOM, 1, { 0 } },
00088 { (char *)"CHARSET_ENCODING", BDF_ATOM, 1, { 0 } },
00089 { (char *)"CHARSET_REGISTRY", BDF_ATOM, 1, { 0 } },
00090 { (char *)"COMMENT", BDF_ATOM, 1, { 0 } },
00091 { (char *)"COPYRIGHT", BDF_ATOM, 1, { 0 } },
00092 { (char *)"DEFAULT_CHAR", BDF_CARDINAL, 1, { 0 } },
00093 { (char *)"DESTINATION", BDF_CARDINAL, 1, { 0 } },
00094 { (char *)"DEVICE_FONT_NAME", BDF_ATOM, 1, { 0 } },
00095 { (char *)"END_SPACE", BDF_INTEGER, 1, { 0 } },
00096 { (char *)"FACE_NAME", BDF_ATOM, 1, { 0 } },
00097 { (char *)"FAMILY_NAME", BDF_ATOM, 1, { 0 } },
00098 { (char *)"FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
00099 { (char *)"FONT", BDF_ATOM, 1, { 0 } },
00100 { (char *)"FONTNAME_REGISTRY", BDF_ATOM, 1, { 0 } },
00101 { (char *)"FONT_ASCENT", BDF_INTEGER, 1, { 0 } },
00102 { (char *)"FONT_DESCENT", BDF_INTEGER, 1, { 0 } },
00103 { (char *)"FOUNDRY", BDF_ATOM, 1, { 0 } },
00104 { (char *)"FULL_NAME", BDF_ATOM, 1, { 0 } },
00105 { (char *)"ITALIC_ANGLE", BDF_INTEGER, 1, { 0 } },
00106 { (char *)"MAX_SPACE", BDF_INTEGER, 1, { 0 } },
00107 { (char *)"MIN_SPACE", BDF_INTEGER, 1, { 0 } },
00108 { (char *)"NORM_SPACE", BDF_INTEGER, 1, { 0 } },
00109 { (char *)"NOTICE", BDF_ATOM, 1, { 0 } },
00110 { (char *)"PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
00111 { (char *)"POINT_SIZE", BDF_INTEGER, 1, { 0 } },
00112 { (char *)"QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
00113 { (char *)"RAW_ASCENT", BDF_INTEGER, 1, { 0 } },
00114 { (char *)"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
00115 { (char *)"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
00116 { (char *)"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
00117 { (char *)"RAW_CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
00118 { (char *)"RAW_DESCENT", BDF_INTEGER, 1, { 0 } },
00119 { (char *)"RAW_END_SPACE", BDF_INTEGER, 1, { 0 } },
00120 { (char *)"RAW_FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
00121 { (char *)"RAW_MAX_SPACE", BDF_INTEGER, 1, { 0 } },
00122 { (char *)"RAW_MIN_SPACE", BDF_INTEGER, 1, { 0 } },
00123 { (char *)"RAW_NORM_SPACE", BDF_INTEGER, 1, { 0 } },
00124 { (char *)"RAW_PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
00125 { (char *)"RAW_POINT_SIZE", BDF_INTEGER, 1, { 0 } },
00126 { (char *)"RAW_PIXELSIZE", BDF_INTEGER, 1, { 0 } },
00127 { (char *)"RAW_POINTSIZE", BDF_INTEGER, 1, { 0 } },
00128 { (char *)"RAW_QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
00129 { (char *)"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
00130 { (char *)"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
00131 { (char *)"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
00132 { (char *)"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
00133 { (char *)"RAW_SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
00134 { (char *)"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
00135 { (char *)"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
00136 { (char *)"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
00137 { (char *)"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
00138 { (char *)"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
00139 { (char *)"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
00140 { (char *)"RAW_X_HEIGHT", BDF_INTEGER, 1, { 0 } },
00141 { (char *)"RELATIVE_SETWIDTH", BDF_CARDINAL, 1, { 0 } },
00142 { (char *)"RELATIVE_WEIGHT", BDF_CARDINAL, 1, { 0 } },
00143 { (char *)"RESOLUTION", BDF_INTEGER, 1, { 0 } },
00144 { (char *)"RESOLUTION_X", BDF_CARDINAL, 1, { 0 } },
00145 { (char *)"RESOLUTION_Y", BDF_CARDINAL, 1, { 0 } },
00146 { (char *)"SETWIDTH_NAME", BDF_ATOM, 1, { 0 } },
00147 { (char *)"SLANT", BDF_ATOM, 1, { 0 } },
00148 { (char *)"SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
00149 { (char *)"SPACING", BDF_ATOM, 1, { 0 } },
00150 { (char *)"STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
00151 { (char *)"STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
00152 { (char *)"SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
00153 { (char *)"SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
00154 { (char *)"SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
00155 { (char *)"SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
00156 { (char *)"SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
00157 { (char *)"SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
00158 { (char *)"UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
00159 { (char *)"UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
00160 { (char *)"WEIGHT", BDF_CARDINAL, 1, { 0 } },
00161 { (char *)"WEIGHT_NAME", BDF_ATOM, 1, { 0 } },
00162 { (char *)"X_HEIGHT", BDF_INTEGER, 1, { 0 } },
00163 { (char *)"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1, { 0 } },
00164 { (char *)"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } },
00165 };
00166
00167 static const unsigned long
00168 _num_bdf_properties = sizeof ( _bdf_properties ) /
00169 sizeof ( _bdf_properties[0] );
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 #define INITIAL_HT_SIZE 241
00182
00183 typedef void
00184 (*hash_free_func)( hashnode node );
00185
00186 static hashnode*
00187 hash_bucket( const char* key,
00188 hashtable* ht )
00189 {
00190 const char* kp = key;
00191 unsigned long res = 0;
00192 hashnode* bp = ht->table, *ndp;
00193
00194
00195
00196 while ( *kp )
00197 res = ( res << 5 ) - res + *kp++;
00198
00199 ndp = bp + ( res % ht->size );
00200 while ( *ndp )
00201 {
00202 kp = (*ndp)->key;
00203 if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 )
00204 break;
00205 ndp--;
00206 if ( ndp < bp )
00207 ndp = bp + ( ht->size - 1 );
00208 }
00209
00210 return ndp;
00211 }
00212
00213
00214 static FT_Error
00215 hash_rehash( hashtable* ht,
00216 FT_Memory memory )
00217 {
00218 hashnode* obp = ht->table, *bp, *nbp;
00219 int i, sz = ht->size;
00220 FT_Error error = BDF_Err_Ok;
00221
00222
00223 ht->size <<= 1;
00224 ht->limit = ht->size / 3;
00225
00226 if ( FT_NEW_ARRAY( ht->table, ht->size ) )
00227 goto Exit;
00228
00229 for ( i = 0, bp = obp; i < sz; i++, bp++ )
00230 {
00231 if ( *bp )
00232 {
00233 nbp = hash_bucket( (*bp)->key, ht );
00234 *nbp = *bp;
00235 }
00236 }
00237 FT_FREE( obp );
00238
00239 Exit:
00240 return error;
00241 }
00242
00243
00244 static FT_Error
00245 hash_init( hashtable* ht,
00246 FT_Memory memory )
00247 {
00248 int sz = INITIAL_HT_SIZE;
00249 FT_Error error = BDF_Err_Ok;
00250
00251
00252 ht->size = sz;
00253 ht->limit = sz / 3;
00254 ht->used = 0;
00255
00256 if ( FT_NEW_ARRAY( ht->table, sz ) )
00257 goto Exit;
00258
00259 Exit:
00260 return error;
00261 }
00262
00263
00264 static void
00265 hash_free( hashtable* ht,
00266 FT_Memory memory )
00267 {
00268 if ( ht != 0 )
00269 {
00270 int i, sz = ht->size;
00271 hashnode* bp = ht->table;
00272
00273
00274 for ( i = 0; i < sz; i++, bp++ )
00275 FT_FREE( *bp );
00276
00277 FT_FREE( ht->table );
00278 }
00279 }
00280
00281
00282 static FT_Error
00283 hash_insert( char* key,
00284 size_t data,
00285 hashtable* ht,
00286 FT_Memory memory )
00287 {
00288 hashnode nn, *bp = hash_bucket( key, ht );
00289 FT_Error error = BDF_Err_Ok;
00290
00291
00292 nn = *bp;
00293 if ( !nn )
00294 {
00295 if ( FT_NEW( nn ) )
00296 goto Exit;
00297 *bp = nn;
00298
00299 nn->key = key;
00300 nn->data = data;
00301
00302 if ( ht->used >= ht->limit )
00303 {
00304 error = hash_rehash( ht, memory );
00305 if ( error )
00306 goto Exit;
00307 }
00308 ht->used++;
00309 }
00310 else
00311 nn->data = data;
00312
00313 Exit:
00314 return error;
00315 }
00316
00317
00318 static hashnode
00319 hash_lookup( const char* key,
00320 hashtable* ht )
00321 {
00322 hashnode *np = hash_bucket( key, ht );
00323
00324
00325 return *np;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 typedef FT_Error
00339 (*_bdf_line_func_t)( char* line,
00340 unsigned long linelen,
00341 unsigned long lineno,
00342 void* call_data,
00343 void* client_data );
00344
00345
00346
00347
00348 typedef struct _bdf_list_t_
00349 {
00350 char** field;
00351 unsigned long size;
00352 unsigned long used;
00353 FT_Memory memory;
00354
00355 } _bdf_list_t;
00356
00357
00358
00359
00360 typedef struct _bdf_parse_t_
00361 {
00362 unsigned long flags;
00363 unsigned long cnt;
00364 unsigned long row;
00365
00366 short minlb;
00367 short maxlb;
00368 short maxrb;
00369 short maxas;
00370 short maxds;
00371
00372 short rbearing;
00373
00374 char* glyph_name;
00375 long glyph_enc;
00376
00377 bdf_font_t* font;
00378 bdf_options_t* opts;
00379
00380 unsigned long have[2048];
00381 _bdf_list_t list;
00382
00383 FT_Memory memory;
00384
00385 } _bdf_parse_t;
00386
00387
00388 #define setsbit( m, cc ) \
00389 ( m[(FT_Byte)(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) )
00390 #define sbitset( m, cc ) \
00391 ( m[(FT_Byte)(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) )
00392
00393
00394 static void
00395 _bdf_list_init( _bdf_list_t* list,
00396 FT_Memory memory )
00397 {
00398 FT_ZERO( list );
00399 list->memory = memory;
00400 }
00401
00402
00403 static void
00404 _bdf_list_done( _bdf_list_t* list )
00405 {
00406 FT_Memory memory = list->memory;
00407
00408
00409 if ( memory )
00410 {
00411 FT_FREE( list->field );
00412 FT_ZERO( list );
00413 }
00414 }
00415
00416
00417 static FT_Error
00418 _bdf_list_ensure( _bdf_list_t* list,
00419 unsigned long num_items )
00420 {
00421 FT_Error error = BDF_Err_Ok;
00422
00423
00424 if ( num_items > list->size )
00425 {
00426 unsigned long oldsize = list->size;
00427 unsigned long newsize = oldsize + ( oldsize >> 1 ) + 4;
00428 unsigned long bigsize = (unsigned long)( FT_INT_MAX / sizeof ( char* ) );
00429 FT_Memory memory = list->memory;
00430
00431
00432 if ( oldsize == bigsize )
00433 {
00434 error = BDF_Err_Out_Of_Memory;
00435 goto Exit;
00436 }
00437 else if ( newsize < oldsize || newsize > bigsize )
00438 newsize = bigsize;
00439
00440 if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) )
00441 goto Exit;
00442
00443 list->size = newsize;
00444 }
00445
00446 Exit:
00447 return error;
00448 }
00449
00450
00451 static void
00452 _bdf_list_shift( _bdf_list_t* list,
00453 unsigned long n )
00454 {
00455 unsigned long i, u;
00456
00457
00458 if ( list == 0 || list->used == 0 || n == 0 )
00459 return;
00460
00461 if ( n >= list->used )
00462 {
00463 list->used = 0;
00464 return;
00465 }
00466
00467 for ( u = n, i = 0; u < list->used; i++, u++ )
00468 list->field[i] = list->field[u];
00469 list->used -= n;
00470 }
00471
00472
00473 static char *
00474 _bdf_list_join( _bdf_list_t* list,
00475 int c,
00476 unsigned long *alen )
00477 {
00478 unsigned long i, j;
00479 char *fp, *dp;
00480
00481
00482 *alen = 0;
00483
00484 if ( list == 0 || list->used == 0 )
00485 return 0;
00486
00487 dp = list->field[0];
00488 for ( i = j = 0; i < list->used; i++ )
00489 {
00490 fp = list->field[i];
00491 while ( *fp )
00492 dp[j++] = *fp++;
00493
00494 if ( i + 1 < list->used )
00495 dp[j++] = (char)c;
00496 }
00497 dp[j] = 0;
00498
00499 *alen = j;
00500 return dp;
00501 }
00502
00503
00504
00505
00506 static const char empty[1] = { 0 };
00507
00508
00509 static FT_Error
00510 _bdf_list_split( _bdf_list_t* list,
00511 char* separators,
00512 char* line,
00513 unsigned long linelen )
00514 {
00515 int mult, final_empty;
00516 char *sp, *ep, *end;
00517 char seps[32];
00518 FT_Error error = BDF_Err_Ok;
00519
00520
00521
00522 list->used = 0;
00523
00524
00525 if ( linelen == 0 || line[0] == 0 )
00526 goto Exit;
00527
00528
00529
00530
00531 if ( separators == 0 || *separators == 0 )
00532 {
00533 error = BDF_Err_Invalid_Argument;
00534 goto Exit;
00535 }
00536
00537
00538 FT_MEM_ZERO( seps, 32 );
00539
00540
00541
00542
00543 for ( mult = 0, sp = separators; sp && *sp; sp++ )
00544 {
00545 if ( *sp == '+' && *( sp + 1 ) == 0 )
00546 mult = 1;
00547 else
00548 setsbit( seps, *sp );
00549 }
00550
00551
00552 for ( final_empty = 0, sp = ep = line, end = sp + linelen;
00553 sp < end && *sp; )
00554 {
00555
00556 for ( ; *ep && !sbitset( seps, *ep ); ep++ )
00557 ;
00558
00559
00560 if ( list->used == list->size )
00561 {
00562 error = _bdf_list_ensure( list, list->used + 1 );
00563 if ( error )
00564 goto Exit;
00565 }
00566
00567
00568 list->field[list->used++] = ( ep > sp ) ? sp : (char*)empty;
00569
00570 sp = ep;
00571
00572 if ( mult )
00573 {
00574
00575
00576 for ( ; *ep && sbitset( seps, *ep ); ep++ )
00577 *ep = 0;
00578 }
00579 else if ( *ep != 0 )
00580
00581
00582 *ep++ = 0;
00583
00584 final_empty = ( ep > sp && *ep == 0 );
00585 sp = ep;
00586 }
00587
00588
00589 if ( list->used + final_empty >= list->size )
00590 {
00591 error = _bdf_list_ensure( list, list->used + final_empty + 1 );
00592 if ( error )
00593 goto Exit;
00594 }
00595
00596 if ( final_empty )
00597 list->field[list->used++] = (char*)empty;
00598
00599 list->field[list->used] = 0;
00600
00601 Exit:
00602 return error;
00603 }
00604
00605
00606 #define NO_SKIP 256
00607
00608
00609 static FT_Error
00610 _bdf_readstream( FT_Stream stream,
00611 _bdf_line_func_t callback,
00612 void* client_data,
00613 unsigned long *lno )
00614 {
00615 _bdf_line_func_t cb;
00616 unsigned long lineno, buf_size;
00617 int refill, hold, to_skip;
00618 ptrdiff_t bytes, start, end, cursor, avail;
00619 char* buf = 0;
00620 FT_Memory memory = stream->memory;
00621 FT_Error error = BDF_Err_Ok;
00622
00623
00624 if ( callback == 0 )
00625 {
00626 error = BDF_Err_Invalid_Argument;
00627 goto Exit;
00628 }
00629
00630
00631 buf_size = 1024;
00632
00633 if ( FT_NEW_ARRAY( buf, buf_size ) )
00634 goto Exit;
00635
00636 cb = callback;
00637 lineno = 1;
00638 buf[0] = 0;
00639 start = 0;
00640 end = 0;
00641 avail = 0;
00642 cursor = 0;
00643 refill = 1;
00644 to_skip = NO_SKIP;
00645 bytes = 0;
00646
00647 for (;;)
00648 {
00649 if ( refill )
00650 {
00651 bytes = (ptrdiff_t)FT_Stream_TryRead( stream, (FT_Byte*)buf + cursor,
00652 (FT_ULong)(buf_size - cursor) );
00653 avail = cursor + bytes;
00654 cursor = 0;
00655 refill = 0;
00656 }
00657
00658 end = start;
00659
00660
00661 if ( start < avail && buf[start] == to_skip )
00662 {
00663 start += 1;
00664 to_skip = NO_SKIP;
00665 continue;
00666 }
00667
00668
00669 while ( end < avail && buf[end] != '\n' && buf[end] != '\r' )
00670 end++;
00671
00672
00673
00674 if ( end >= avail )
00675 {
00676 if ( bytes == 0 )
00677 break;
00678
00679 if ( start == 0 )
00680 {
00681
00682
00683 FT_ULong new_size;
00684
00685
00686 if ( buf_size >= 65536UL )
00687 {
00688 error = BDF_Err_Invalid_Argument;
00689 goto Exit;
00690 }
00691
00692 new_size = buf_size * 2;
00693 if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) )
00694 goto Exit;
00695
00696 cursor = buf_size;
00697 buf_size = new_size;
00698 }
00699 else
00700 {
00701 bytes = avail - start;
00702
00703 FT_MEM_COPY( buf, buf + start, bytes );
00704
00705 cursor = bytes;
00706 avail -= bytes;
00707 start = 0;
00708 }
00709 refill = 1;
00710 continue;
00711 }
00712
00713
00714 hold = buf[end];
00715 buf[end] = 0;
00716
00717
00718 if ( buf[start] != '#' && buf[start] != 0x1a && end > start )
00719 {
00720 error = (*cb)( buf + start, end - start, lineno,
00721 (void*)&cb, client_data );
00722 if ( error )
00723 break;
00724 }
00725
00726 lineno += 1;
00727 buf[end] = (char)hold;
00728 start = end + 1;
00729
00730 if ( hold == '\n' )
00731 to_skip = '\r';
00732 else if ( hold == '\r' )
00733 to_skip = '\n';
00734 else
00735 to_skip = NO_SKIP;
00736 }
00737
00738 *lno = lineno;
00739
00740 Exit:
00741 FT_FREE( buf );
00742 return error;
00743 }
00744
00745
00746
00747
00748 static const unsigned char a2i[128] =
00749 {
00750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00754 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
00755 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
00756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00758 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
00759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00761 };
00762
00763 static const unsigned char odigits[32] =
00764 {
00765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
00766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00769 };
00770
00771 static const unsigned char ddigits[32] =
00772 {
00773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
00774 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00777 };
00778
00779 static const unsigned char hdigits[32] =
00780 {
00781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
00782 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
00783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00784 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00785 };
00786
00787
00788 #define isdigok( m, d ) (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) )
00789
00790
00791
00792 static unsigned long
00793 _bdf_atoul( char* s,
00794 char** end,
00795 int base )
00796 {
00797 unsigned long v;
00798 const unsigned char* dmap;
00799
00800
00801 if ( s == 0 || *s == 0 )
00802 return 0;
00803
00804
00805 switch ( base )
00806 {
00807 case 8:
00808 dmap = odigits;
00809 break;
00810 case 16:
00811 dmap = hdigits;
00812 break;
00813 default:
00814 base = 10;
00815 dmap = ddigits;
00816 break;
00817 }
00818
00819
00820 if ( *s == '0' &&
00821 ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
00822 {
00823 base = 16;
00824 dmap = hdigits;
00825 s += 2;
00826 }
00827
00828 for ( v = 0; isdigok( dmap, *s ); s++ )
00829 v = v * base + a2i[(int)*s];
00830
00831 if ( end != 0 )
00832 *end = s;
00833
00834 return v;
00835 }
00836
00837
00838
00839 static long
00840 _bdf_atol( char* s,
00841 char** end,
00842 int base )
00843 {
00844 long v, neg;
00845 const unsigned char* dmap;
00846
00847
00848 if ( s == 0 || *s == 0 )
00849 return 0;
00850
00851
00852 switch ( base )
00853 {
00854 case 8:
00855 dmap = odigits;
00856 break;
00857 case 16:
00858 dmap = hdigits;
00859 break;
00860 default:
00861 base = 10;
00862 dmap = ddigits;
00863 break;
00864 }
00865
00866
00867 neg = 0;
00868 if ( *s == '-' )
00869 {
00870 s++;
00871 neg = 1;
00872 }
00873
00874
00875 if ( *s == '0' &&
00876 ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
00877 {
00878 base = 16;
00879 dmap = hdigits;
00880 s += 2;
00881 }
00882
00883 for ( v = 0; isdigok( dmap, *s ); s++ )
00884 v = v * base + a2i[(int)*s];
00885
00886 if ( end != 0 )
00887 *end = s;
00888
00889 return ( !neg ) ? v : -v;
00890 }
00891
00892
00893
00894 static short
00895 _bdf_atos( char* s,
00896 char** end,
00897 int base )
00898 {
00899 short v, neg;
00900 const unsigned char* dmap;
00901
00902
00903 if ( s == 0 || *s == 0 )
00904 return 0;
00905
00906
00907 switch ( base )
00908 {
00909 case 8:
00910 dmap = odigits;
00911 break;
00912 case 16:
00913 dmap = hdigits;
00914 break;
00915 default:
00916 base = 10;
00917 dmap = ddigits;
00918 break;
00919 }
00920
00921
00922 neg = 0;
00923 if ( *s == '-' )
00924 {
00925 s++;
00926 neg = 1;
00927 }
00928
00929
00930 if ( *s == '0' &&
00931 ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
00932 {
00933 base = 16;
00934 dmap = hdigits;
00935 s += 2;
00936 }
00937
00938 for ( v = 0; isdigok( dmap, *s ); s++ )
00939 v = (short)( v * base + a2i[(int)*s] );
00940
00941 if ( end != 0 )
00942 *end = s;
00943
00944 return (short)( ( !neg ) ? v : -v );
00945 }
00946
00947
00948
00949 static int
00950 by_encoding( const void* a,
00951 const void* b )
00952 {
00953 bdf_glyph_t *c1, *c2;
00954
00955
00956 c1 = (bdf_glyph_t *)a;
00957 c2 = (bdf_glyph_t *)b;
00958
00959 if ( c1->encoding < c2->encoding )
00960 return -1;
00961
00962 if ( c1->encoding > c2->encoding )
00963 return 1;
00964
00965 return 0;
00966 }
00967
00968
00969 static FT_Error
00970 bdf_create_property( char* name,
00971 int format,
00972 bdf_font_t* font )
00973 {
00974 size_t n;
00975 bdf_property_t* p;
00976 FT_Memory memory = font->memory;
00977 FT_Error error = BDF_Err_Ok;
00978
00979
00980
00981
00982
00983 if ( hash_lookup( name, &(font->proptbl) ) )
00984 goto Exit;
00985
00986 if ( FT_RENEW_ARRAY( font->user_props,
00987 font->nuser_props,
00988 font->nuser_props + 1 ) )
00989 goto Exit;
00990
00991 p = font->user_props + font->nuser_props;
00992 FT_ZERO( p );
00993
00994 n = ft_strlen( name ) + 1;
00995 if ( n > FT_ULONG_MAX )
00996 return BDF_Err_Invalid_Argument;
00997
00998 if ( FT_NEW_ARRAY( p->name, n ) )
00999 goto Exit;
01000
01001 FT_MEM_COPY( (char *)p->name, name, n );
01002
01003 p->format = format;
01004 p->builtin = 0;
01005
01006 n = _num_bdf_properties + font->nuser_props;
01007
01008 error = hash_insert( p->name, n, &(font->proptbl), memory );
01009 if ( error )
01010 goto Exit;
01011
01012 font->nuser_props++;
01013
01014 Exit:
01015 return error;
01016 }
01017
01018
01019 FT_LOCAL_DEF( bdf_property_t * )
01020 bdf_get_property( char* name,
01021 bdf_font_t* font )
01022 {
01023 hashnode hn;
01024 size_t propid;
01025
01026
01027 if ( name == 0 || *name == 0 )
01028 return 0;
01029
01030 if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 )
01031 return 0;
01032
01033 propid = hn->data;
01034 if ( propid >= _num_bdf_properties )
01035 return font->user_props + ( propid - _num_bdf_properties );
01036
01037 return (bdf_property_t*)_bdf_properties + propid;
01038 }
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 #define _BDF_START 0x0001
01051 #define _BDF_FONT_NAME 0x0002
01052 #define _BDF_SIZE 0x0004
01053 #define _BDF_FONT_BBX 0x0008
01054 #define _BDF_PROPS 0x0010
01055 #define _BDF_GLYPHS 0x0020
01056 #define _BDF_GLYPH 0x0040
01057 #define _BDF_ENCODING 0x0080
01058 #define _BDF_SWIDTH 0x0100
01059 #define _BDF_DWIDTH 0x0200
01060 #define _BDF_BBX 0x0400
01061 #define _BDF_BITMAP 0x0800
01062
01063 #define _BDF_SWIDTH_ADJ 0x1000
01064
01065 #define _BDF_GLYPH_BITS ( _BDF_GLYPH | \
01066 _BDF_ENCODING | \
01067 _BDF_SWIDTH | \
01068 _BDF_DWIDTH | \
01069 _BDF_BBX | \
01070 _BDF_BITMAP )
01071
01072 #define _BDF_GLYPH_WIDTH_CHECK 0x40000000UL
01073 #define _BDF_GLYPH_HEIGHT_CHECK 0x80000000UL
01074
01075
01076
01077 #define ACMSG1 "FONT_ASCENT property missing. " \
01078 "Added \"FONT_ASCENT %hd\".\n"
01079 #define ACMSG2 "FONT_DESCENT property missing. " \
01080 "Added \"FONT_DESCENT %hd\".\n"
01081 #define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n"
01082 #define ACMSG4 "Font left bearing != actual left bearing. " \
01083 "Old: %hd New: %hd.\n"
01084 #define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n"
01085 #define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n"
01086 #define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n"
01087 #define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n"
01088 #define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n"
01089 #define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n"
01090 #define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n"
01091 #define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n"
01092 #define ACMSG13 "Glyph %ld extra rows removed.\n"
01093 #define ACMSG14 "Glyph %ld extra columns removed.\n"
01094 #define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n"
01095
01096
01097 #define ERRMSG1 "[line %ld] Missing \"%s\" line.\n"
01098 #define ERRMSG2 "[line %ld] Font header corrupted or missing fields.\n"
01099 #define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields.\n"
01100 #define ERRMSG4 "[line %ld] BBX too big.\n"
01101
01102
01103 static FT_Error
01104 _bdf_add_comment( bdf_font_t* font,
01105 char* comment,
01106 unsigned long len )
01107 {
01108 char* cp;
01109 FT_Memory memory = font->memory;
01110 FT_Error error = BDF_Err_Ok;
01111
01112
01113 if ( FT_RENEW_ARRAY( font->comments,
01114 font->comments_len,
01115 font->comments_len + len + 1 ) )
01116 goto Exit;
01117
01118 cp = font->comments + font->comments_len;
01119
01120 FT_MEM_COPY( cp, comment, len );
01121 cp[len] = '\n';
01122
01123 font->comments_len += len + 1;
01124
01125 Exit:
01126 return error;
01127 }
01128
01129
01130
01131
01132 static FT_Error
01133 _bdf_set_default_spacing( bdf_font_t* font,
01134 bdf_options_t* opts )
01135 {
01136 size_t len;
01137 char name[256];
01138 _bdf_list_t list;
01139 FT_Memory memory;
01140 FT_Error error = BDF_Err_Ok;
01141
01142
01143 if ( font == 0 || font->name == 0 || font->name[0] == 0 )
01144 {
01145 error = BDF_Err_Invalid_Argument;
01146 goto Exit;
01147 }
01148
01149 memory = font->memory;
01150
01151 _bdf_list_init( &list, memory );
01152
01153 font->spacing = opts->font_spacing;
01154
01155 len = ft_strlen( font->name ) + 1;
01156
01157 if ( len >= 256 )
01158 {
01159 error = BDF_Err_Invalid_Argument;
01160 goto Exit;
01161 }
01162
01163 FT_MEM_COPY( name, font->name, len );
01164
01165 error = _bdf_list_split( &list, (char *)"-", name, len );
01166 if ( error )
01167 goto Fail;
01168
01169 if ( list.used == 15 )
01170 {
01171 switch ( list.field[11][0] )
01172 {
01173 case 'C':
01174 case 'c':
01175 font->spacing = BDF_CHARCELL;
01176 break;
01177 case 'M':
01178 case 'm':
01179 font->spacing = BDF_MONOWIDTH;
01180 break;
01181 case 'P':
01182 case 'p':
01183 font->spacing = BDF_PROPORTIONAL;
01184 break;
01185 }
01186 }
01187
01188 Fail:
01189 _bdf_list_done( &list );
01190
01191 Exit:
01192 return error;
01193 }
01194
01195
01196
01197
01198 static int
01199 _bdf_is_atom( char* line,
01200 unsigned long linelen,
01201 char** name,
01202 char** value,
01203 bdf_font_t* font )
01204 {
01205 int hold;
01206 char *sp, *ep;
01207 bdf_property_t* p;
01208
01209
01210 *name = sp = ep = line;
01211
01212 while ( *ep && *ep != ' ' && *ep != '\t' )
01213 ep++;
01214
01215 hold = -1;
01216 if ( *ep )
01217 {
01218 hold = *ep;
01219 *ep = 0;
01220 }
01221
01222 p = bdf_get_property( sp, font );
01223
01224
01225 if ( hold != -1 )
01226 *ep = (char)hold;
01227
01228
01229 if ( p && p->format != BDF_ATOM )
01230 return 0;
01231
01232
01233
01234 sp = ep;
01235 ep = line + linelen;
01236
01237
01238 *sp++ = 0;
01239 while ( *sp &&
01240 ( *sp == ' ' || *sp == '\t' ) )
01241 sp++;
01242
01243
01244 if ( *sp == '"' )
01245 sp++;
01246 *value = sp;
01247
01248
01249 while ( ep > sp &&
01250 ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) )
01251 *--ep = 0;
01252
01253
01254 if ( ep > sp && *( ep - 1 ) == '"' )
01255 *--ep = 0;
01256
01257 return 1;
01258 }
01259
01260
01261 static FT_Error
01262 _bdf_add_property( bdf_font_t* font,
01263 char* name,
01264 char* value )
01265 {
01266 size_t propid;
01267 hashnode hn;
01268 bdf_property_t *prop, *fp;
01269 FT_Memory memory = font->memory;
01270 FT_Error error = BDF_Err_Ok;
01271
01272
01273
01274 if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 )
01275 {
01276
01277
01278 fp = font->props + hn->data;
01279
01280 switch ( fp->format )
01281 {
01282 case BDF_ATOM:
01283
01284 FT_FREE( fp->value.atom );
01285
01286 if ( value && value[0] != 0 )
01287 {
01288 if ( FT_STRDUP( fp->value.atom, value ) )
01289 goto Exit;
01290 }
01291 break;
01292
01293 case BDF_INTEGER:
01294 fp->value.l = _bdf_atol( value, 0, 10 );
01295 break;
01296
01297 case BDF_CARDINAL:
01298 fp->value.ul = _bdf_atoul( value, 0, 10 );
01299 break;
01300
01301 default:
01302 ;
01303 }
01304
01305 goto Exit;
01306 }
01307
01308
01309
01310 hn = hash_lookup( name, &(font->proptbl) );
01311 if ( hn == 0 )
01312 {
01313 error = bdf_create_property( name, BDF_ATOM, font );
01314 if ( error )
01315 goto Exit;
01316 hn = hash_lookup( name, &(font->proptbl) );
01317 }
01318
01319
01320 if ( font->props_used == font->props_size )
01321 {
01322 if ( font->props_size == 0 )
01323 {
01324 if ( FT_NEW_ARRAY( font->props, 1 ) )
01325 goto Exit;
01326 }
01327 else
01328 {
01329 if ( FT_RENEW_ARRAY( font->props,
01330 font->props_size,
01331 font->props_size + 1 ) )
01332 goto Exit;
01333 }
01334
01335 fp = font->props + font->props_size;
01336 FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) );
01337 font->props_size++;
01338 }
01339
01340 propid = hn->data;
01341 if ( propid >= _num_bdf_properties )
01342 prop = font->user_props + ( propid - _num_bdf_properties );
01343 else
01344 prop = (bdf_property_t*)_bdf_properties + propid;
01345
01346 fp = font->props + font->props_used;
01347
01348 fp->name = prop->name;
01349 fp->format = prop->format;
01350 fp->builtin = prop->builtin;
01351
01352 switch ( prop->format )
01353 {
01354 case BDF_ATOM:
01355 fp->value.atom = 0;
01356 if ( value != 0 && value[0] )
01357 {
01358 if ( FT_STRDUP( fp->value.atom, value ) )
01359 goto Exit;
01360 }
01361 break;
01362
01363 case BDF_INTEGER:
01364 fp->value.l = _bdf_atol( value, 0, 10 );
01365 break;
01366
01367 case BDF_CARDINAL:
01368 fp->value.ul = _bdf_atoul( value, 0, 10 );
01369 break;
01370 }
01371
01372
01373
01374 if ( ft_memcmp( name, "COMMENT", 7 ) != 0 ) {
01375
01376 error = hash_insert( fp->name,
01377 font->props_used,
01378 (hashtable *)font->internal,
01379 memory );
01380 if ( error )
01381 goto Exit;
01382 }
01383
01384 font->props_used++;
01385
01386
01387
01388
01389
01390
01391 if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 )
01392 font->default_char = fp->value.l;
01393 else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 )
01394 font->font_ascent = fp->value.l;
01395 else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 )
01396 font->font_descent = fp->value.l;
01397 else if ( ft_memcmp( name, "SPACING", 7 ) == 0 )
01398 {
01399 if ( !fp->value.atom )
01400 {
01401 error = BDF_Err_Invalid_File_Format;
01402 goto Exit;
01403 }
01404
01405 if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' )
01406 font->spacing = BDF_PROPORTIONAL;
01407 else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' )
01408 font->spacing = BDF_MONOWIDTH;
01409 else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' )
01410 font->spacing = BDF_CHARCELL;
01411 }
01412
01413 Exit:
01414 return error;
01415 }
01416
01417
01418 static const unsigned char nibble_mask[8] =
01419 {
01420 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE
01421 };
01422
01423
01424
01425 static FT_Error
01426 _bdf_parse_glyphs( char* line,
01427 unsigned long linelen,
01428 unsigned long lineno,
01429 void* call_data,
01430 void* client_data )
01431 {
01432 int c, mask_index;
01433 char* s;
01434 unsigned char* bp;
01435 unsigned long i, slen, nibbles;
01436
01437 _bdf_parse_t* p;
01438 bdf_glyph_t* glyph;
01439 bdf_font_t* font;
01440
01441 FT_Memory memory;
01442 FT_Error error = BDF_Err_Ok;
01443
01444 FT_UNUSED( call_data );
01445 FT_UNUSED( lineno );
01446
01447
01448 p = (_bdf_parse_t *)client_data;
01449
01450 font = p->font;
01451 memory = font->memory;
01452
01453
01454 if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
01455 {
01456 linelen -= 7;
01457
01458 s = line + 7;
01459 if ( *s != 0 )
01460 {
01461 s++;
01462 linelen--;
01463 }
01464 error = _bdf_add_comment( p->font, s, linelen );
01465 goto Exit;
01466 }
01467
01468
01469 if ( !( p->flags & _BDF_GLYPHS ) )
01470 {
01471 if ( ft_memcmp( line, "CHARS", 5 ) != 0 )
01472 {
01473 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" ));
01474 error = BDF_Err_Missing_Chars_Field;
01475 goto Exit;
01476 }
01477
01478 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
01479 if ( error )
01480 goto Exit;
01481 p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 );
01482
01483
01484 if ( p->cnt == 0 )
01485 font->glyphs_size = 64;
01486
01487
01488
01489 if ( p->cnt >= 1114112UL )
01490 {
01491 error = BDF_Err_Invalid_Argument;
01492 goto Exit;
01493 }
01494
01495 if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) )
01496 goto Exit;
01497
01498 p->flags |= _BDF_GLYPHS;
01499
01500 goto Exit;
01501 }
01502
01503
01504 if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 )
01505 {
01506
01507 ft_qsort( (char *)font->glyphs,
01508 font->glyphs_used,
01509 sizeof ( bdf_glyph_t ),
01510 by_encoding );
01511
01512 p->flags &= ~_BDF_START;
01513
01514 goto Exit;
01515 }
01516
01517
01518 if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 )
01519 {
01520 p->glyph_enc = 0;
01521 p->flags &= ~_BDF_GLYPH_BITS;
01522
01523 goto Exit;
01524 }
01525
01526
01527
01528 if ( ( p->flags & _BDF_GLYPH ) &&
01529 p->glyph_enc == -1 &&
01530 p->opts->keep_unencoded == 0 )
01531 goto Exit;
01532
01533
01534 if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 )
01535 {
01536
01537
01538 FT_FREE( p->glyph_name );
01539
01540 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
01541 if ( error )
01542 goto Exit;
01543
01544 _bdf_list_shift( &p->list, 1 );
01545
01546 s = _bdf_list_join( &p->list, ' ', &slen );
01547
01548 if ( !s )
01549 {
01550 error = BDF_Err_Invalid_File_Format;
01551 goto Exit;
01552 }
01553
01554 if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )
01555 goto Exit;
01556
01557 FT_MEM_COPY( p->glyph_name, s, slen + 1 );
01558
01559 p->flags |= _BDF_GLYPH;
01560
01561 goto Exit;
01562 }
01563
01564
01565 if ( ft_memcmp( line, "ENCODING", 8 ) == 0 )
01566 {
01567 if ( !( p->flags & _BDF_GLYPH ) )
01568 {
01569
01570 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" ));
01571 error = BDF_Err_Missing_Startchar_Field;
01572 goto Exit;
01573 }
01574
01575 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
01576 if ( error )
01577 goto Exit;
01578
01579 p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 );
01580
01581
01582
01583 if ( (size_t)p->glyph_enc >= sizeof ( p->have ) * 8 )
01584 {
01585 error = BDF_Err_Invalid_File_Format;
01586 goto Exit;
01587 }
01588
01589
01590
01591
01592 if ( p->glyph_enc >= 0 )
01593 {
01594 if ( _bdf_glyph_modified( p->have, p->glyph_enc ) )
01595 {
01596
01597
01598 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12,
01599 p->glyph_enc, p->glyph_name ));
01600 p->glyph_enc = -1;
01601 font->modified = 1;
01602 }
01603 else
01604 _bdf_set_glyph_modified( p->have, p->glyph_enc );
01605 }
01606
01607 if ( p->glyph_enc >= 0 )
01608 {
01609
01610
01611 if ( font->glyphs_used == font->glyphs_size )
01612 {
01613 if ( FT_RENEW_ARRAY( font->glyphs,
01614 font->glyphs_size,
01615 font->glyphs_size + 64 ) )
01616 goto Exit;
01617
01618 font->glyphs_size += 64;
01619 }
01620
01621 glyph = font->glyphs + font->glyphs_used++;
01622 glyph->name = p->glyph_name;
01623 glyph->encoding = p->glyph_enc;
01624
01625
01626 p->glyph_name = 0;
01627 }
01628 else
01629 {
01630
01631
01632 if ( p->opts->keep_unencoded != 0 )
01633 {
01634
01635 if ( font->unencoded_used == font->unencoded_size )
01636 {
01637 if ( FT_RENEW_ARRAY( font->unencoded ,
01638 font->unencoded_size,
01639 font->unencoded_size + 4 ) )
01640 goto Exit;
01641
01642 font->unencoded_size += 4;
01643 }
01644
01645 glyph = font->unencoded + font->unencoded_used;
01646 glyph->name = p->glyph_name;
01647 glyph->encoding = font->unencoded_used++;
01648 }
01649 else
01650
01651
01652 FT_FREE( p->glyph_name );
01653
01654 p->glyph_name = 0;
01655 }
01656
01657
01658
01659 p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK );
01660
01661 p->flags |= _BDF_ENCODING;
01662
01663 goto Exit;
01664 }
01665
01666
01667 if ( p->glyph_enc == -1 )
01668 glyph = font->unencoded + ( font->unencoded_used - 1 );
01669 else
01670 glyph = font->glyphs + ( font->glyphs_used - 1 );
01671
01672
01673 if ( p->flags & _BDF_BITMAP )
01674 {
01675
01676
01677 if ( p->row >= (unsigned long)glyph->bbx.height )
01678 {
01679 if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) )
01680 {
01681 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding ));
01682 p->flags |= _BDF_GLYPH_HEIGHT_CHECK;
01683 font->modified = 1;
01684 }
01685
01686 goto Exit;
01687 }
01688
01689
01690
01691 nibbles = glyph->bpr << 1;
01692 bp = glyph->bitmap + p->row * glyph->bpr;
01693
01694 for ( i = 0; i < nibbles; i++ )
01695 {
01696 c = line[i];
01697 *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] );
01698 if ( i + 1 < nibbles && ( i & 1 ) )
01699 *++bp = 0;
01700 }
01701
01702
01703 mask_index = ( glyph->bbx.width * p->font->bpp ) & 7;
01704 if ( glyph->bbx.width )
01705 *bp &= nibble_mask[mask_index];
01706
01707
01708 if ( ( line[nibbles] == '0' || a2i[(int)line[nibbles]] != 0 ) &&
01709 !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) )
01710 {
01711 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding ));
01712 p->flags |= _BDF_GLYPH_WIDTH_CHECK;
01713 font->modified = 1;
01714 }
01715
01716 p->row++;
01717 goto Exit;
01718 }
01719
01720
01721 if ( ft_memcmp( line, "SWIDTH", 6 ) == 0 )
01722 {
01723 if ( !( p->flags & _BDF_ENCODING ) )
01724 {
01725
01726 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" ));
01727 error = BDF_Err_Missing_Encoding_Field;
01728 goto Exit;
01729 }
01730
01731 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
01732 if ( error )
01733 goto Exit;
01734
01735 glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
01736 p->flags |= _BDF_SWIDTH;
01737
01738 goto Exit;
01739 }
01740
01741
01742 if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 )
01743 {
01744 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
01745 if ( error )
01746 goto Exit;
01747
01748 glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
01749
01750 if ( !( p->flags & _BDF_SWIDTH ) )
01751 {
01752
01753
01754 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno ));
01755
01756 glyph->swidth = (unsigned short)FT_MulDiv(
01757 glyph->dwidth, 72000L,
01758 (FT_Long)( font->point_size *
01759 font->resolution_x ) );
01760 }
01761
01762 p->flags |= _BDF_DWIDTH;
01763 goto Exit;
01764 }
01765
01766
01767 if ( ft_memcmp( line, "BBX", 3 ) == 0 )
01768 {
01769 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
01770 if ( error )
01771 goto Exit;
01772
01773 glyph->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );
01774 glyph->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );
01775 glyph->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
01776 glyph->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
01777
01778
01779 glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset );
01780 glyph->bbx.descent = (short)( -glyph->bbx.y_offset );
01781
01782
01783
01784 p->maxas = (short)FT_MAX( glyph->bbx.ascent, p->maxas );
01785 p->maxds = (short)FT_MAX( glyph->bbx.descent, p->maxds );
01786
01787 p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset );
01788
01789 p->maxrb = (short)FT_MAX( p->rbearing, p->maxrb );
01790 p->minlb = (short)FT_MIN( glyph->bbx.x_offset, p->minlb );
01791 p->maxlb = (short)FT_MAX( glyph->bbx.x_offset, p->maxlb );
01792
01793 if ( !( p->flags & _BDF_DWIDTH ) )
01794 {
01795
01796
01797 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno ));
01798 glyph->dwidth = glyph->bbx.width;
01799 }
01800
01801
01802
01803 if ( p->opts->correct_metrics != 0 )
01804 {
01805
01806 unsigned short sw = (unsigned short)FT_MulDiv(
01807 glyph->dwidth, 72000L,
01808 (FT_Long)( font->point_size *
01809 font->resolution_x ) );
01810
01811
01812 if ( sw != glyph->swidth )
01813 {
01814 glyph->swidth = sw;
01815
01816 if ( p->glyph_enc == -1 )
01817 _bdf_set_glyph_modified( font->umod,
01818 font->unencoded_used - 1 );
01819 else
01820 _bdf_set_glyph_modified( font->nmod, glyph->encoding );
01821
01822 p->flags |= _BDF_SWIDTH_ADJ;
01823 font->modified = 1;
01824 }
01825 }
01826
01827 p->flags |= _BDF_BBX;
01828 goto Exit;
01829 }
01830
01831
01832 if ( ft_memcmp( line, "BITMAP", 6 ) == 0 )
01833 {
01834 unsigned long bitmap_size;
01835
01836
01837 if ( !( p->flags & _BDF_BBX ) )
01838 {
01839
01840 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" ));
01841 error = BDF_Err_Missing_Bbx_Field;
01842 goto Exit;
01843 }
01844
01845
01846 glyph->bpr = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3;
01847
01848 bitmap_size = glyph->bpr * glyph->bbx.height;
01849 if ( bitmap_size > 0xFFFFU )
01850 {
01851 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG4, lineno ));
01852 error = BDF_Err_Bbx_Too_Big;
01853 goto Exit;
01854 }
01855 else
01856 glyph->bytes = (unsigned short)bitmap_size;
01857
01858 if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) )
01859 goto Exit;
01860
01861 p->row = 0;
01862 p->flags |= _BDF_BITMAP;
01863
01864 goto Exit;
01865 }
01866
01867 error = BDF_Err_Invalid_File_Format;
01868
01869 Exit:
01870 return error;
01871 }
01872
01873
01874
01875 static FT_Error
01876 _bdf_parse_properties( char* line,
01877 unsigned long linelen,
01878 unsigned long lineno,
01879 void* call_data,
01880 void* client_data )
01881 {
01882 unsigned long vlen;
01883 _bdf_line_func_t* next;
01884 _bdf_parse_t* p;
01885 char* name;
01886 char* value;
01887 char nbuf[128];
01888 FT_Error error = BDF_Err_Ok;
01889
01890 FT_UNUSED( lineno );
01891
01892
01893 next = (_bdf_line_func_t *)call_data;
01894 p = (_bdf_parse_t *) client_data;
01895
01896
01897 if ( ft_memcmp( line, "ENDPROPERTIES", 13 ) == 0 )
01898 {
01899
01900
01901
01902
01903
01904
01905 if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 )
01906 {
01907 p->font->font_ascent = p->font->bbx.ascent;
01908 ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );
01909 error = _bdf_add_property( p->font, (char *)"FONT_ASCENT", nbuf );
01910 if ( error )
01911 goto Exit;
01912
01913 FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));
01914 p->font->modified = 1;
01915 }
01916
01917 if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 )
01918 {
01919 p->font->font_descent = p->font->bbx.descent;
01920 ft_sprintf( nbuf, "%hd", p->font->bbx.descent );
01921 error = _bdf_add_property( p->font, (char *)"FONT_DESCENT", nbuf );
01922 if ( error )
01923 goto Exit;
01924
01925 FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
01926 p->font->modified = 1;
01927 }
01928
01929 p->flags &= ~_BDF_PROPS;
01930 *next = _bdf_parse_glyphs;
01931
01932 goto Exit;
01933 }
01934
01935
01936 if ( ft_memcmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 )
01937 goto Exit;
01938
01939
01940
01941 if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
01942 {
01943 name = value = line;
01944 value += 7;
01945 if ( *value )
01946 *value++ = 0;
01947 error = _bdf_add_property( p->font, name, value );
01948 if ( error )
01949 goto Exit;
01950 }
01951 else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) )
01952 {
01953 error = _bdf_add_property( p->font, name, value );
01954 if ( error )
01955 goto Exit;
01956 }
01957 else
01958 {
01959 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
01960 if ( error )
01961 goto Exit;
01962 name = p->list.field[0];
01963
01964 _bdf_list_shift( &p->list, 1 );
01965 value = _bdf_list_join( &p->list, ' ', &vlen );
01966
01967 error = _bdf_add_property( p->font, name, value );
01968 if ( error )
01969 goto Exit;
01970 }
01971
01972 Exit:
01973 return error;
01974 }
01975
01976
01977
01978 static FT_Error
01979 _bdf_parse_start( char* line,
01980 unsigned long linelen,
01981 unsigned long lineno,
01982 void* call_data,
01983 void* client_data )
01984 {
01985 unsigned long slen;
01986 _bdf_line_func_t* next;
01987 _bdf_parse_t* p;
01988 bdf_font_t* font;
01989 char *s;
01990
01991 FT_Memory memory = NULL;
01992 FT_Error error = BDF_Err_Ok;
01993
01994 FT_UNUSED( lineno );
01995
01996
01997 next = (_bdf_line_func_t *)call_data;
01998 p = (_bdf_parse_t *) client_data;
01999
02000 if ( p->font )
02001 memory = p->font->memory;
02002
02003
02004
02005 if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
02006 {
02007 if ( p->opts->keep_comments != 0 && p->font != 0 )
02008 {
02009 linelen -= 7;
02010
02011 s = line + 7;
02012 if ( *s != 0 )
02013 {
02014 s++;
02015 linelen--;
02016 }
02017
02018 error = _bdf_add_comment( p->font, s, linelen );
02019 if ( error )
02020 goto Exit;
02021
02022 }
02023
02024 goto Exit;
02025 }
02026
02027 if ( !( p->flags & _BDF_START ) )
02028 {
02029 memory = p->memory;
02030
02031 if ( ft_memcmp( line, "STARTFONT", 9 ) != 0 )
02032 {
02033
02034 error = BDF_Err_Missing_Startfont_Field;
02035 goto Exit;
02036 }
02037
02038 p->flags = _BDF_START;
02039 font = p->font = 0;
02040
02041 if ( FT_NEW( font ) )
02042 goto Exit;
02043 p->font = font;
02044
02045 font->memory = p->memory;
02046 p->memory = 0;
02047
02048 {
02049 size_t i;
02050 bdf_property_t* prop;
02051
02052
02053 error = hash_init( &(font->proptbl), memory );
02054 if ( error )
02055 goto Exit;
02056 for ( i = 0, prop = (bdf_property_t*)_bdf_properties;
02057 i < _num_bdf_properties; i++, prop++ )
02058 {
02059 error = hash_insert( prop->name, i,
02060 &(font->proptbl), memory );
02061 if ( error )
02062 goto Exit;
02063 }
02064 }
02065
02066 if ( FT_ALLOC( p->font->internal, sizeof ( hashtable ) ) )
02067 goto Exit;
02068 error = hash_init( (hashtable *)p->font->internal,memory );
02069 if ( error )
02070 goto Exit;
02071 p->font->spacing = p->opts->font_spacing;
02072 p->font->default_char = -1;
02073
02074 goto Exit;
02075 }
02076
02077
02078 if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 )
02079 {
02080 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
02081 if ( error )
02082 goto Exit;
02083
02084 p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 );
02085
02086 if ( FT_NEW_ARRAY( p->font->props, p->cnt ) )
02087 goto Exit;
02088
02089 p->flags |= _BDF_PROPS;
02090 *next = _bdf_parse_properties;
02091
02092 goto Exit;
02093 }
02094
02095
02096 if ( ft_memcmp( line, "FONTBOUNDINGBOX", 15 ) == 0 )
02097 {
02098 if ( !(p->flags & _BDF_SIZE ) )
02099 {
02100
02101 FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" ));
02102 error = BDF_Err_Missing_Size_Field;
02103 goto Exit;
02104 }
02105
02106 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
02107 if ( error )
02108 goto Exit;
02109
02110 p->font->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );
02111 p->font->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );
02112
02113 p->font->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
02114 p->font->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
02115
02116 p->font->bbx.ascent = (short)( p->font->bbx.height +
02117 p->font->bbx.y_offset );
02118
02119 p->font->bbx.descent = (short)( -p->font->bbx.y_offset );
02120
02121 p->flags |= _BDF_FONT_BBX;
02122
02123 goto Exit;
02124 }
02125
02126
02127 if ( ft_memcmp( line, "FONT", 4 ) == 0 )
02128 {
02129 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
02130 if ( error )
02131 goto Exit;
02132 _bdf_list_shift( &p->list, 1 );
02133
02134 s = _bdf_list_join( &p->list, ' ', &slen );
02135
02136 if ( !s )
02137 {
02138 error = BDF_Err_Invalid_File_Format;
02139 goto Exit;
02140 }
02141
02142 if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) )
02143 goto Exit;
02144 FT_MEM_COPY( p->font->name, s, slen + 1 );
02145
02146
02147
02148 error = _bdf_set_default_spacing( p->font, p->opts );
02149 if ( error )
02150 goto Exit;
02151
02152 p->flags |= _BDF_FONT_NAME;
02153
02154 goto Exit;
02155 }
02156
02157
02158 if ( ft_memcmp( line, "SIZE", 4 ) == 0 )
02159 {
02160 if ( !( p->flags & _BDF_FONT_NAME ) )
02161 {
02162
02163 FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" ));
02164 error = BDF_Err_Missing_Font_Field;
02165 goto Exit;
02166 }
02167
02168 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
02169 if ( error )
02170 goto Exit;
02171
02172 p->font->point_size = _bdf_atoul( p->list.field[1], 0, 10 );
02173 p->font->resolution_x = _bdf_atoul( p->list.field[2], 0, 10 );
02174 p->font->resolution_y = _bdf_atoul( p->list.field[3], 0, 10 );
02175
02176
02177 if ( p->list.used == 5 )
02178 {
02179 unsigned short bitcount, i, shift;
02180
02181
02182 p->font->bpp = (unsigned short)_bdf_atos( p->list.field[4], 0, 10 );
02183
02184
02185 shift = p->font->bpp;
02186 bitcount = 0;
02187 for ( i = 0; shift > 0; i++ )
02188 {
02189 if ( shift & 1 )
02190 bitcount = i;
02191 shift >>= 1;
02192 }
02193
02194 shift = (short)( ( bitcount > 3 ) ? 8 : ( 1 << bitcount ) );
02195
02196 if ( p->font->bpp > shift || p->font->bpp != shift )
02197 {
02198
02199 p->font->bpp = (unsigned short)( shift << 1 );
02200 FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp ));
02201 }
02202 }
02203 else
02204 p->font->bpp = 1;
02205
02206 p->flags |= _BDF_SIZE;
02207
02208 goto Exit;
02209 }
02210
02211 error = BDF_Err_Invalid_File_Format;
02212
02213 Exit:
02214 return error;
02215 }
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225 FT_LOCAL_DEF( FT_Error )
02226 bdf_load_font( FT_Stream stream,
02227 FT_Memory extmemory,
02228 bdf_options_t* opts,
02229 bdf_font_t* *font )
02230 {
02231 unsigned long lineno = 0;
02232 _bdf_parse_t *p;
02233
02234 FT_Memory memory = extmemory;
02235 FT_Error error = BDF_Err_Ok;
02236
02237
02238 if ( FT_NEW( p ) )
02239 goto Exit;
02240
02241 memory = NULL;
02242 p->opts = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts );
02243 p->minlb = 32767;
02244 p->memory = extmemory;
02245
02246 _bdf_list_init( &p->list, extmemory );
02247
02248 error = _bdf_readstream( stream, _bdf_parse_start,
02249 (void *)p, &lineno );
02250 if ( error )
02251 goto Fail;
02252
02253 if ( p->font != 0 )
02254 {
02255
02256
02257 memory = p->font->memory;
02258
02259 if ( p->font->spacing != BDF_PROPORTIONAL )
02260 p->font->monowidth = p->font->bbx.width;
02261
02262
02263
02264 if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used )
02265 {
02266 FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt,
02267 p->font->glyphs_used + p->font->unencoded_used ));
02268 p->font->modified = 1;
02269 }
02270
02271
02272
02273 if ( p->opts->correct_metrics != 0 &&
02274 ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) )
02275 {
02276 if ( p->maxrb - p->minlb != p->font->bbx.width )
02277 {
02278 FT_TRACE2(( "bdf_load_font: " ACMSG3,
02279 p->font->bbx.width, p->maxrb - p->minlb ));
02280 p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb );
02281 p->font->modified = 1;
02282 }
02283
02284 if ( p->font->bbx.x_offset != p->minlb )
02285 {
02286 FT_TRACE2(( "bdf_load_font: " ACMSG4,
02287 p->font->bbx.x_offset, p->minlb ));
02288 p->font->bbx.x_offset = p->minlb;
02289 p->font->modified = 1;
02290 }
02291
02292 if ( p->font->bbx.ascent != p->maxas )
02293 {
02294 FT_TRACE2(( "bdf_load_font: " ACMSG5,
02295 p->font->bbx.ascent, p->maxas ));
02296 p->font->bbx.ascent = p->maxas;
02297 p->font->modified = 1;
02298 }
02299
02300 if ( p->font->bbx.descent != p->maxds )
02301 {
02302 FT_TRACE2(( "bdf_load_font: " ACMSG6,
02303 p->font->bbx.descent, p->maxds ));
02304 p->font->bbx.descent = p->maxds;
02305 p->font->bbx.y_offset = (short)( -p->maxds );
02306 p->font->modified = 1;
02307 }
02308
02309 if ( p->maxas + p->maxds != p->font->bbx.height )
02310 {
02311 FT_TRACE2(( "bdf_load_font: " ACMSG7,
02312 p->font->bbx.height, p->maxas + p->maxds ));
02313 p->font->bbx.height = (unsigned short)( p->maxas + p->maxds );
02314 }
02315
02316 if ( p->flags & _BDF_SWIDTH_ADJ )
02317 FT_TRACE2(( "bdf_load_font: " ACMSG8 ));
02318 }
02319 }
02320
02321 if ( p->flags & _BDF_START )
02322 {
02323 {
02324
02325 if ( !( p->flags & _BDF_GLYPHS ) )
02326 {
02327
02328 FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno ));
02329 error = BDF_Err_Corrupted_Font_Header;
02330 goto Exit;
02331 }
02332 else
02333 {
02334
02335 FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno ));
02336 error = BDF_Err_Corrupted_Font_Glyphs;
02337 goto Exit;
02338 }
02339 }
02340 }
02341
02342 if ( p->font != 0 )
02343 {
02344
02345 memory = p->font->memory;
02346
02347 if ( p->font->comments_len > 0 ) {
02348 if ( FT_RENEW_ARRAY( p->font->comments,
02349 p->font->comments_len,
02350 p->font->comments_len + 1 ) )
02351 goto Fail;
02352
02353 p->font->comments[p->font->comments_len] = 0;
02354 }
02355 }
02356 else if ( error == BDF_Err_Ok )
02357 error = BDF_Err_Invalid_File_Format;
02358
02359 *font = p->font;
02360
02361 Exit:
02362 if ( p )
02363 {
02364 _bdf_list_done( &p->list );
02365
02366 memory = extmemory;
02367
02368 FT_FREE( p );
02369 }
02370
02371 return error;
02372
02373 Fail:
02374 bdf_free_font( p->font );
02375
02376 memory = extmemory;
02377
02378 FT_FREE( p->font );
02379
02380 goto Exit;
02381 }
02382
02383
02384 FT_LOCAL_DEF( void )
02385 bdf_free_font( bdf_font_t* font )
02386 {
02387 bdf_property_t* prop;
02388 unsigned long i;
02389 bdf_glyph_t* glyphs;
02390 FT_Memory memory;
02391
02392
02393 if ( font == 0 )
02394 return;
02395
02396 memory = font->memory;
02397
02398 FT_FREE( font->name );
02399
02400
02401 if ( font->internal )
02402 {
02403 hash_free( (hashtable *)font->internal, memory );
02404 FT_FREE( font->internal );
02405 }
02406
02407
02408 FT_FREE( font->comments );
02409
02410
02411 for ( i = 0; i < font->props_size; i++ )
02412 {
02413 if ( font->props[i].format == BDF_ATOM )
02414 FT_FREE( font->props[i].value.atom );
02415 }
02416
02417 FT_FREE( font->props );
02418
02419
02420 for ( i = 0, glyphs = font->glyphs;
02421 i < font->glyphs_used; i++, glyphs++ )
02422 {
02423 FT_FREE( glyphs->name );
02424 FT_FREE( glyphs->bitmap );
02425 }
02426
02427 for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used;
02428 i++, glyphs++ )
02429 {
02430 FT_FREE( glyphs->name );
02431 FT_FREE( glyphs->bitmap );
02432 }
02433
02434 FT_FREE( font->glyphs );
02435 FT_FREE( font->unencoded );
02436
02437
02438 for ( i = 0, glyphs = font->overflow.glyphs;
02439 i < font->overflow.glyphs_used; i++, glyphs++ )
02440 {
02441 FT_FREE( glyphs->name );
02442 FT_FREE( glyphs->bitmap );
02443 }
02444
02445 FT_FREE( font->overflow.glyphs );
02446
02447
02448 hash_free( &(font->proptbl), memory );
02449
02450
02451 for (prop = font->user_props, i = 0;
02452 i < font->nuser_props; i++, prop++ )
02453 {
02454 FT_FREE( prop->name );
02455 if ( prop->format == BDF_ATOM )
02456 FT_FREE( prop->value.atom );
02457 }
02458
02459 FT_FREE( font->user_props );
02460
02461
02462 }
02463
02464
02465 FT_LOCAL_DEF( bdf_property_t * )
02466 bdf_get_font_property( bdf_font_t* font,
02467 const char* name )
02468 {
02469 hashnode hn;
02470
02471
02472 if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 )
02473 return 0;
02474
02475 hn = hash_lookup( name, (hashtable *)font->internal );
02476
02477 return hn ? ( font->props + hn->data ) : 0;
02478 }
02479
02480
02481