| 26 | | #define FT_PIXELS(x) (x >> 6) |
| 27 | | |
| 28 | | |
| 29 | | #ifdef KERN |
| 30 | | typedef struct |
| 31 | | { |
| 32 | | uint32_t avail; |
| 33 | | uint32_t used; |
| 34 | | char* ptr; |
| 35 | | } |
| 36 | | Array; |
| 37 | | |
| 38 | | |
| 39 | | static void arrayReserve( Array* arr, size_t nsize ) |
| 40 | | { |
| 41 | | if( nsize > arr->avail ) |
| 42 | | { |
| 43 | | size_t count; |
| 44 | | |
| 45 | | count = arr->avail * 2; |
| 46 | | if( count < nsize ) |
| 47 | | count = (nsize < 8) ? 8 : nsize; |
| 48 | | |
| 49 | | arr->ptr = (char*) realloc( arr->ptr, count ); |
| 50 | | assert( arr->ptr ); |
| 51 | | } |
| 52 | | } |
| 53 | | #endif |
| | 25 | #define FT_PIXELS(x) (x >> 6) |
| | 26 | |
| | 27 | #define GLYPHS(tf) ((TexGlyphInfo*) (tf + 1)) |
| | 28 | #define TABLE(tf) (((uint16_t*) tf) + tf->table_offset) |
| | 29 | #define KERN(tf) (((int16_t*) tf) + tf->kern_offset) |
| 57 | | |
| 58 | | |
| 59 | | void txf_init( TexFont* txf, int w, int h ) |
| 60 | | { |
| 61 | | txf->tex_width = w; |
| 62 | | txf->tex_height = h; |
| 63 | | txf->tgi = 0; |
| 64 | | txf->table = 0; |
| 65 | | txf->kerning = 0; |
| 66 | | } |
| 67 | | |
| 68 | | |
| 69 | | void txf_free( TexFont* txf ) |
| 70 | | { |
| 71 | | #define FREE(n) if(n) { free(n); n=0; } |
| 72 | | |
| 73 | | FREE( txf->tgi ) |
| 74 | | FREE( txf->table ) |
| 75 | | FREE( txf->kerning ) |
| 76 | | } |
| 77 | | |
| 78 | | |
| 79 | | void txf_setGlyphCount( TexFont* txf, int n ) |
| 80 | | { |
| 81 | | if( txf->tgi ) |
| 82 | | free( txf->tgi ); |
| 83 | | txf->tgi = (TexGlyphInfo*) malloc( sizeof(TexGlyphInfo) * n ); |
| 84 | | txf->num_glyphs = n; |
| 85 | | } |
| 86 | | |
| 87 | | |
| 88 | | /** |
| 89 | | Build glyph lookup table. |
| 90 | | */ |
| 91 | | static void _buildGlyphTable( TexFont* txf ) |
| 92 | | { |
| 93 | | int min_glyph; |
| 94 | | int max_glyph; |
| 95 | | TexGlyphInfo* it; |
| 96 | | TexGlyphInfo* end; |
| 97 | | |
| 98 | | //assert( txf->num_glyphs ); |
| 99 | | |
| 100 | | // Find high & low glyph. |
| 101 | | min_glyph = txf->tgi[0].c; |
| 102 | | max_glyph = txf->tgi[0].c; |
| 103 | | |
| 104 | | it = txf->tgi; |
| 105 | | end = it + txf->num_glyphs; |
| 106 | | |
| 107 | | while( it != end ) |
| 108 | | { |
| 109 | | if( it->c < min_glyph ) |
| 110 | | min_glyph = it->c; |
| 111 | | if( it->c > max_glyph ) |
| 112 | | max_glyph = it->c; |
| 113 | | ++it; |
| 114 | | } |
| 115 | | |
| 116 | | txf->min_glyph = min_glyph; |
| 117 | | txf->table_size = max_glyph - min_glyph + 1; |
| 118 | | |
| 119 | | // Allocate table. |
| 120 | | if( txf->table ) |
| 121 | | free( txf->table ); |
| 122 | | txf->table = (TexGlyphInfo**) |
| 123 | | malloc( sizeof(TexGlyphInfo*) * txf->table_size ); |
| 124 | | |
| 125 | | // Fill table. |
| 126 | | memset( txf->table, 0, sizeof(TexGlyphInfo*) * txf->table_size ); |
| 127 | | |
| 128 | | it = txf->tgi; |
| 129 | | while( it != end ) |
| 130 | | { |
| 131 | | txf->table[ it->c - txf->min_glyph ] = it; |
| 132 | | ++it; |
| 133 | | } |
| 134 | | } |
| 142 | | TexGlyphInfo* txf_glyph( const TexFont* txf, int c ) |
| 143 | | { |
| 144 | | TexGlyphInfo* tgi; |
| 145 | | int max_glyph = txf->min_glyph + txf->table_size; |
| 146 | | |
| 147 | | if( (c >= txf->min_glyph) && (c < max_glyph) ) |
| 148 | | { |
| 149 | | tgi = txf->table[c - txf->min_glyph]; |
| 150 | | if( tgi ) |
| 151 | | return tgi; |
| | 40 | TexGlyphInfo* txf_glyph( const TexFont* tf, int c ) |
| | 41 | { |
| | 42 | uint16_t n; |
| | 43 | uint16_t* table = TABLE(tf); |
| | 44 | int min_glyph = tf->min_glyph; |
| | 45 | int max_glyph = min_glyph + tf->table_size; |
| | 46 | |
| | 47 | if( (c >= min_glyph) && (c < max_glyph) ) |
| | 48 | { |
| | 49 | n = table[ c - min_glyph ]; |
| | 50 | if( n < 0xffff ) |
| | 51 | return GLYPHS(tf) + n; |
| | 93 | static void swap16( uint16_t* it, uint16_t* end ) |
| | 94 | { |
| | 95 | uint8_t* bp; |
| | 96 | while( it != end ) |
| | 97 | { |
| | 98 | bp = (uint8_t*) it; |
| | 99 | *it++ = (bp[0] << 8) | bp[1]; |
| | 100 | } |
| | 101 | } |
| | 102 | |
| | 103 | |
| | 104 | /** |
| | 105 | Swap endianess of TexFont data if not native. |
| | 106 | */ |
| | 107 | void txf_swap( TexFont* tf ) |
| | 108 | { |
| | 109 | if( tf && (tf->glyph_offset == (sizeof(TexFont) << 8)) ) |
| | 110 | { |
| | 111 | TexGlyphInfo* tgi; |
| | 112 | TexGlyphInfo* end; |
| | 113 | uint16_t* it; |
| | 114 | |
| | 115 | it = &tf->glyph_offset; |
| | 116 | swap16( it, it + (sizeof(TexFont) / sizeof(uint16_t)) ); |
| | 117 | |
| | 118 | tgi = GLYPHS(tf); |
| | 119 | end = tgi + tf->glyph_count; |
| | 120 | while( tgi != end ) |
| | 121 | { |
| | 122 | it = &tgi->c; |
| | 123 | swap16( it, it + 4 ); |
| | 124 | ++tgi; |
| | 125 | } |
| | 126 | |
| | 127 | it = TABLE(tf); |
| | 128 | swap16( it, it + tf->table_size ); |
| | 129 | |
| | 130 | it = (uint16_t*) KERN(tf); |
| | 131 | swap16( it, it + tf->kern_size ); |
| | 132 | } |
| | 133 | } |
| | 134 | |
| | 135 | |
| 311 | | if( kern.x || kern.y ) |
| 312 | | { |
| 313 | | //printf(" %c %ld %ld\n", *ci, FT_PIXELS(kern.x), FT_PIXELS(kern.y)); |
| 314 | | |
| 315 | | arrayReserve( table, table->used + 3 ); |
| 316 | | entry = table->ptr + table->used; |
| 317 | | table->used += 2; |
| 318 | | |
| 319 | | // NOTE: kern.y is ignored since is it almost always zero. |
| | 241 | |
| | 242 | // NOTE: kern.y is ignored since is it almost always zero. |
| | 243 | if( kern.x /*|| kern.y*/ ) |
| | 244 | { |
| | 245 | #ifdef DUMP |
| | 246 | printf(" %c %ld %ld\n", *ci, FT_PIXELS(kern.x), FT_PIXELS(kern.y)); |
| | 247 | #endif |
| | 248 | if( space < 3 ) |
| | 249 | { |
| | 250 | ktable[ tf->kern_size ] = 0; |
| | 251 | fprintf( stderr, "txf_build: Kerning table full\n" ); |
| | 252 | return -1; |
| | 253 | } |
| | 254 | |
| | 255 | entry = ktable + tf->kern_size; |
| | 256 | tf->kern_size += 2; |
| | 257 | space -= 2; |
| | 258 | |
| 342 | | int txf_build( TexFont* txf, const char* file, |
| 343 | | const char* codes, FT_Bitmap* img, int psize, int gap, |
| 344 | | int asBitmap ) |
| | 279 | TexFont* txf_build( const char* file, const char* codes, |
| | 280 | FT_Bitmap* img, int psize, int gap, int antialias ) |
| 377 | | printf( "FT_Face [\n" ); |
| 378 | | printf( " family_name: \"%s\"\n", face->family_name ); |
| 379 | | printf( " style_name: \"%s\"\n", face->style_name ); |
| 380 | | printf( " num_glyphs: %ld\n", face->num_glyphs ); |
| 381 | | printf( " units_per_EM: %d (%d)\n", EM_PIX(face->units_per_EM) ); |
| 382 | | printf( " ascender: %d (%d)\n", EM_PIX(face->ascender) ); |
| 383 | | printf( " descender: %d (%d)\n", EM_PIX(face->descender) ); |
| 384 | | printf( " height: %d (%d)\n", EM_PIX(face->height) ); |
| 385 | | dumpCharMaps( face ); |
| 386 | | printf( "]\n" ); |
| | 314 | printf( "FT_Face [\n" ); |
| | 315 | printf( " family_name: \"%s\"\n", face->family_name ); |
| | 316 | printf( " style_name: \"%s\"\n", face->style_name ); |
| | 317 | printf( " num_glyphs: %ld\n", face->num_glyphs ); |
| | 318 | printf( " units_per_EM: %d (%d)\n", EM_PIX(face->units_per_EM) ); |
| | 319 | printf( " ascender: %d (%d)\n", EM_PIX(face->ascender) ); |
| | 320 | printf( " descender: %d (%d)\n", EM_PIX(face->descender) ); |
| | 321 | printf( " height: %d (%d)\n", EM_PIX(face->height) ); |
| | 322 | dumpCharMaps( face ); |
| | 323 | printf( "]\n" ); |
| 406 | | txf_setGlyphCount( txf, face->num_glyphs ); |
| | 335 | // Count glyphs and find the high & low. |
| | 336 | gmin = 0xffff; |
| | 337 | gmax = 0; |
| | 338 | ci = codes; |
| | 339 | while( *ci ) |
| | 340 | { |
| | 341 | ch = *ci++; |
| | 342 | if( ch < gmin ) |
| | 343 | gmin = ch; |
| | 344 | if( ch > gmax ) |
| | 345 | gmax = ch; |
| | 346 | } |
| | 347 | count = ci - codes; |
| | 348 | |
| | 349 | |
| | 350 | // Most glyphs have no kerning adjustment, and those with it have only |
| | 351 | // a handful (at least at small font sizes). |
| | 352 | kern_space = count * 5; // 5 = 2 glyphs + terminator |
| | 353 | |
| | 354 | txf = (TexFont*) malloc( sizeof(TexFont) + |
| | 355 | (sizeof(TexGlyphInfo) * count) + |
| | 356 | (sizeof(uint16_t) * (gmax - gmin + 1)) + |
| | 357 | (sizeof(int16_t) * kern_space) ); |
| | 358 | |
| | 359 | txf->glyph_offset = sizeof(TexFont); |
| | 360 | txf->glyph_count = count; |
| | 361 | txf->table_offset = (txf->glyph_offset + (sizeof(TexGlyphInfo) * count)) |
| | 362 | / sizeof(uint16_t); |
| | 363 | txf->table_size = gmax - gmin + 1; |
| | 364 | txf->kern_offset = txf->table_offset + txf->table_size; |
| | 365 | txf->kern_size = 0; |
| | 366 | |
| 453 | | _renderGlyph( img, glyph, x, y, ! asBitmap ); |
| 454 | | |
| 455 | | tgi = txf->tgi + count; |
| 456 | | count++; |
| 457 | | |
| 458 | | tgi->c = *ci; |
| 459 | | tgi->width = FT_PIXELS(glyph->metrics.width); |
| 460 | | tgi->height = FT_PIXELS(glyph->metrics.height); |
| 461 | | tgi->xoffset = FT_PIXELS(glyph->metrics.horiBearingX); |
| 462 | | tgi->yoffset = FT_PIXELS(glyph->metrics.horiBearingY) - tgi->height; |
| 463 | | tgi->advance = FT_PIXELS(glyph->metrics.horiAdvance); |
| 464 | | tgi->x = x /*+ tgi->xoffset*/; |
| 465 | | tgi->y = img->rows - y + tgi->yoffset; |
| | 425 | nextX = x + FT_PIXELS(glyph->metrics.width) + gap; |
| | 426 | } |
| | 427 | |
| | 428 | _renderGlyph( img, glyph, x, y, antialias ); |
| | 429 | |
| | 430 | tgi->c = ch; |
| | 431 | tgi->width = FT_PIXELS(glyph->metrics.width); |
| | 432 | tgi->height = FT_PIXELS(glyph->metrics.height); |
| | 433 | tgi->xoffset = FT_PIXELS(glyph->metrics.horiBearingX); |
| | 434 | tgi->yoffset = FT_PIXELS(glyph->metrics.horiBearingY) - tgi->height; |
| | 435 | tgi->advance = FT_PIXELS(glyph->metrics.horiAdvance); |
| | 436 | tgi->x = x /*+ tgi->xoffset*/; |
| | 437 | tgi->y = img->rows - y + tgi->yoffset; |
| | 438 | |
| | 439 | #ifdef DUMP |
| | 440 | printf( "Glyph %c %d,%d %d,%d %d %d,%d\n", ch, |
| | 441 | tgi->width, tgi->height, |
| | 442 | tgi->xoffset, tgi->yoffset, |
| | 443 | tgi->advance, tgi->x, tgi->y ); |
| | 444 | #endif |
| | 445 | |
| | 446 | table[ ch - txf->min_glyph ] = count++; |
| | 447 | |
| | 448 | if( FT_HAS_KERNING( face ) ) |
| | 449 | { |
| | 450 | #ifdef DUMP |
| | 451 | printf( "Kern %c\n", ch ); |
| | 452 | #endif |
| | 453 | tgi->kern_index = _loadKerning( txf, |
| | 454 | kern_space - txf->kern_size, |
| | 455 | face, glyph_index, codes ); |
| | 456 | } |
| | 457 | else |
| | 458 | { |