A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1362 lines 39 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2007 Jonas Hurrelmann 11 * 12 * A command-line tool to convert ttf file to bitmap fonts 13 * 14 * All files in this archive are subject to the GNU General Public License. 15 * See the file COPYING in the source tree root for full license agreement. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include <ft2build.h> 22#include FT_FREETYPE_H 23#include FT_GLYPH_H 24 25#include <stdio.h> 26#ifdef WIN32 27#ifdef _MSC_VER 28#define snprintf _snprintf 29#endif 30#else 31#include <stdlib.h> 32#include <unistd.h> 33#endif 34#include FT_SFNT_NAMES_H 35#include FT_TRUETYPE_TABLES_H 36 37#include <string.h> 38#include <stdint.h> 39/* 40 * Set the default values used to generate a BDF font. 41 */ 42#ifndef DEFAULT_PLATFORM_ID 43#define DEFAULT_PLATFORM_ID 3 44#endif 45 46#ifndef DEFAULT_ENCODING_ID 47#define DEFAULT_ENCODING_ID 1 48#endif 49 50#define ABS(x) (((x) < 0) ? -(x) : (x)) 51 52#define VERSION "RB12" 53/* 54 * nameID macros for getting strings from the OT font. 55 */ 56enum { 57 BDFOTF_COPYRIGHT_STRING = 0, 58 BDFOTF_FAMILY_STRING, 59 BDFOTF_SUBFAMILY_STRING, 60 BDFOTF_UNIQUEID_STRING, 61 BDFOTF_FULLNAME_STRING, 62 BDFOTF_VENDOR_STRING, 63 BDFOTF_POSTSCRIPT_STRING, 64 BDFOTF_TRADEMARK_STRING, 65}; 66/* 67 * String names for the string indexes. Used for error messages. 68 */ 69static char *string_names[] = { 70 "\"Copyright\"", 71 "\"Family\"", 72 "\"SubFamily\"", 73 "\"Unique ID\"", 74 "\"Full Name\"", 75 "\"Vendor\"", 76 "\"Postscript Name\"", 77 "\"Trademark\"" 78}; 79 80 81/* 82 * The default platform and encoding ID's. 83 */ 84static int pid = DEFAULT_PLATFORM_ID; 85static int eid = DEFAULT_ENCODING_ID; 86 87 88/* 89 * A flag indicating if a CMap was found or not. 90 */ 91static FT_UShort nocmap; 92 93int pct = 0; /* display ttc table if it is not zero. */ 94FT_Long max_char = 0x10FFFF; 95int pixel_size = 15; 96FT_Long start_char = 0; 97FT_Long limit_char; 98FT_Long firstchar = 0; 99FT_Long lastchar; 100FT_Long ttc_index = -1; 101int flg_all_ttc = 0; 102short antialias = 1; /* smooth fonts with gray levels */ 103int oflag = 0; 104char outfile[1024]; 105float between_chr = 0.0f; 106float between_row = 0.0f; 107int hv_resolution = 60; 108int dump_glyphs = 0; 109int digits_equally_wide = 1; /* Try to make digits equally wide */ 110int trimming = 0; 111int trim_dp = 0; /* trim descent percent */ 112int trim_da = 0; /* trim descnet actual */ 113int trim_ap = 0; /* trim ascent precent */ 114int trim_aa = 0; /* trim ascent actual */ 115int ft_load_opts = FT_LOAD_RENDER | FT_LOAD_NO_BITMAP; 116 117struct font_header_struct { 118 uint8_t header[4]; /* magic number and version bytes */ 119 uint16_t maxwidth; /* max width in pixels */ 120 uint16_t height; /* height in pixels */ 121 uint16_t ascent; /* ascent (baseline) height */ 122 uint16_t depth; /* depth 0=1-bit, 1=4-bit */ 123 uint32_t firstchar; /* first character in font */ 124 uint32_t defaultchar; /* default character in font */ 125 uint32_t size; /* # characters in font */ 126 uint32_t nbits; /* # bytes imagebits data in file */ /* = bits_size */ 127 128 uint32_t noffset; /* # longs offset data in file */ 129 uint32_t nwidth; /* # bytes width data in file */ 130}; 131 132struct font_struct { 133 struct font_header_struct header; 134 uint8_t *chars_data; 135 uint16_t *offset; 136 uint32_t *offset_long; 137 uint8_t *width; 138}; 139 140struct ttc_table{ 141 FT_Long ttc_count; 142 char **ttf_name; 143}; 144 145/* exit the program with given message */ 146static void 147panic( const char* message) 148{ 149 fprintf( stderr, "%s\n", message ); 150 exit( 1 ); 151} 152 153static void 154arg_panic( const char* message, const char* arg ) 155{ 156 fprintf( stderr, "%s: %s\n", message, arg ); 157 exit( 1 ); 158} 159 160static int writebyte(FILE *fp, unsigned char c) 161{ 162 return putc(c, fp) != EOF; 163} 164 165static int writeshort(FILE *fp, unsigned short s) 166{ 167 putc(s, fp); 168 return putc(s>>8, fp) != EOF; 169} 170 171static int writeint(FILE *fp, unsigned int l) 172{ 173 putc(l, fp); 174 putc(l>>8, fp); 175 putc(l>>16, fp); 176 return putc(l>>24, fp) != EOF; 177} 178 179static int writestr(FILE *fp, char *str, int count) 180{ 181 return (int)fwrite(str, 1, count, fp) == count; 182} 183 184/* print usage information */ 185void usage(void) 186{ 187 char help[] = { 188 "Usage: convttf [options] [input-files]\n" 189 " convttf [options] [-o output-file] [single-input-file]\n\n" 190 " Default output-file : <font-size>-<basename>.fnt.\n" 191 " When '-ta' or '-tc' is specified in command line,\n " 192 " default output-file is: \n" 193 " <font-size>-<internal postscript-name of input-file>.fnt.\n" 194 "Options:\n" 195 " -s N Start output at character encodings >= N\n" 196 " -l N Limit output to character encodings <= N\n" 197 " -p N Font size N in pixel (default N=15)\n" 198 " -c N Character separation in pixel.Insert space between lines.\n" 199 " -x Trim glyphs horizontally of nearly empty space\n" 200 " (to improve spacing on V's W's, etc.)\n" 201 " -X Set the horizontal and vertical resolution (default: 60)\n" 202 " -TA N Trim vertical ascent (N percent)\n" 203 " -TD N Trim vertical descent (N percent)\n" 204 " -Ta N Trim vertical ascent (N pixels)\n" 205 " -Td N Trim vertical descent (N pixels)\n" 206 " -r N Row separation in pixel.Insert space between characters\n" 207 " -d Debug: print converted glyph images\n" 208 " -tt Display the True Type Collection tables available in the font\n" 209 " -t N Index of true type collection. It must be start from 0.(default N=0).\n" 210 " -ta Convert all fonts in ttc (ignores outfile option)\n" 211 " -w Don't try to make digits (0-9) equally wide\n" 212 " -L Use lighter hinting algorithm\n" 213 }; 214 fprintf(stderr, "%s", help); 215 exit( 1 ); 216} 217 218/* remove directory prefix and file suffix from full path*/ 219char *basename(char *path) 220{ 221 char *p, *b; 222 static char base[256]; 223 224 /* remove prepended path and extension*/ 225 b = path; 226 for (p=path; *p; ++p) { 227#ifdef WIN32 228 if (*p == '/' || *p == '\\') 229#else 230 if (*p == '/') 231#endif 232 b = p + 1; 233 } 234 strcpy(base, b); 235 for (p=base; *p; ++p) { 236 if (*p == '.') { 237 *p = 0; 238 break; 239 } 240 } 241 return base; 242} 243 244 245void setcharmap(FT_Face face) 246{ 247 FT_Long i; 248 249 /* 250 * Get the requested cmap. 251 */ 252 for (i = 0; i < face->num_charmaps; i++) { 253 if (face->charmaps[i]->platform_id == pid && 254 face->charmaps[i]->encoding_id == eid) 255 break; 256 } 257 258 if (i == face->num_charmaps && pid == 3 && eid == 1) { 259 /* 260 * Make a special case when this fails with pid == 3 and eid == 1. 261 * Change to eid == 0 and try again. This captures the two possible 262 * cases for MS fonts. Some other method should be used to cycle 263 * through all the alternatives later. 264 */ 265 for (i = 0; i < face->num_charmaps; i++) { 266 if (face->charmaps[i]->platform_id == pid && 267 face->charmaps[i]->encoding_id == 0) 268 break; 269 } 270 if (i < face->num_charmaps) { 271 pid = 3; 272 eid = 1; 273 FT_Set_Charmap(face, face->charmaps[i]); 274 } else { 275 /* 276 * No CMAP was found. 277 */ 278 nocmap = 1; 279 pid = eid = -1; 280 } 281 } else { 282 FT_Set_Charmap(face, face->charmaps[i]); 283 nocmap = 0; 284 } 285 286} 287 288/* 289 * quote in otf2bdf. 290 * A generic routine to get a name from the OT name table. This routine 291 * always looks for English language names and checks three possibilities: 292 * 1. English names with the MS Unicode encoding ID. 293 * 2. English names with the MS unknown encoding ID. 294 * 3. English names with the Apple Unicode encoding ID. 295 * 296 * The particular name ID mut be provided (e.g. nameID = 0 for copyright 297 * string, nameID = 6 for Postscript name, nameID = 1 for typeface name. 298 * 299 * If the `dash_to_space' flag is non-zero, all dashes (-) in the name will be 300 * replaced with the character passed. 301 * 302 * Returns the number of bytes added. 303 */ 304static int 305otf_get_english_string(FT_Face face, int nameID, int dash_to_space, 306 char *name, int name_size) 307{ 308 309 int j, encid; 310 FT_UInt i, nrec; 311 FT_SfntName sfntName; 312 unsigned char *s = NULL; 313 unsigned short slen = 0; 314 315 nrec = FT_Get_Sfnt_Name_Count(face); 316 317 for (encid = 1, j = 0; j < 2; j++, encid--) { 318 /* 319 * Locate one of the MS English font names. 320 */ 321 for (i = 0; i < nrec; i++) { 322 FT_Get_Sfnt_Name(face, i, &sfntName); 323 if (sfntName.platform_id == 3 && 324 sfntName.encoding_id == encid && 325 sfntName.name_id == nameID && 326 (sfntName.language_id == 0x0409 || 327 sfntName.language_id == 0x0809 || 328 sfntName.language_id == 0x0c09 || 329 sfntName.language_id == 0x1009 || 330 sfntName.language_id == 0x1409 || 331 sfntName.language_id == 0x1809)) { 332 s = sfntName.string; 333 slen = sfntName.string_len; 334 break; 335 } 336 } 337 338 if (i < nrec) { 339 if (slen >> 1 >= name_size) { 340 fprintf(stderr, "warning: %s string longer than buffer." 341 "Truncating to %d bytes.\n", string_names[nameID], name_size); 342 slen = name_size << 1; 343 } 344 345 /* 346 * Found one of the MS English font names. The name is by 347 * definition encoded in Unicode, so copy every second byte into 348 * the `name' parameter, assuming there is enough space. 349 */ 350 for (i = 1; i < slen; i += 2) { 351 if (dash_to_space) 352 *name++ = (s[i] != '-') ? s[i] : ' '; 353 else if (s[i] == '\r' || s[i] == '\n') { 354 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n') 355 i += 2; 356 *name++ = ' '; 357 *name++ = ' '; 358 } else 359 *name++ = s[i]; 360 } 361 *name = 0; 362 return (slen >> 1); 363 } 364 } 365 366 /* 367 * No MS English name found, attempt to find an Apple Unicode English 368 * name. 369 */ 370 for (i = 0; i < nrec; i++) { 371 FT_Get_Sfnt_Name(face, i, &sfntName); 372 if (sfntName.platform_id == 0 && sfntName.language_id == 0 && 373 sfntName.name_id == nameID) { 374 s = sfntName.string; 375 slen = sfntName.string_len; 376 break; 377 } 378 } 379 380 if (i < nrec) { 381 if (slen >> 1 >= name_size) { 382 fprintf(stderr, "warning: %s string longer than buffer." 383 "Truncating to %d bytes.\n", string_names[nameID], name_size); 384 slen = name_size << 1; 385 } 386 387 /* 388 * Found the Apple Unicode English name. The name is by definition 389 * encoded in Unicode, so copy every second byte into the `name' 390 * parameter, assuming there is enough space. 391 */ 392 for (i = 1; i < slen; i += 2) { 393 if (dash_to_space) 394 *name++ = (s[i] != '-') ? s[i] : ' '; 395 else if (s[i] == '\r' || s[i] == '\n') { 396 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n') 397 i += 2; 398 *name++ = ' '; 399 *name++ = ' '; 400 } else 401 *name++ = s[i]; 402 } 403 *name = 0; 404 return (slen >> 1); 405 } 406 407 return 0; 408} 409 410 411int get_ttc_table(char *path, struct ttc_table *ttcname ) 412{ 413 414 415 FT_Error err; 416 FT_Library library; 417 FT_Face face; 418 FT_Long i; 419 char xlfd[BUFSIZ]; 420 421 /* init number of ttf in ttc */ 422 ttcname->ttc_count = 0; 423 424 /* Initialize engine */ 425 if ( ( err = FT_Init_FreeType( &library ) ) != 0 ) 426 { 427 panic( "Error while initializing engine" ); 428 return err; 429 } 430 431 432 /* Load face */ 433 err = FT_New_Face( library, path, (FT_Long) 0, &face ); 434 if ( err ) 435 { 436 arg_panic( "Could not find/open font", path ); 437 return err; 438 } 439 440 ttcname->ttc_count = face->num_faces; 441 ttcname->ttf_name = malloc( sizeof(char*) * ttcname->ttc_count); 442 443 for(i = 0; i < ttcname->ttc_count; i++) 444 { 445 err = FT_New_Face( library, path, i, &face ); 446 if ( err == FT_Err_Cannot_Open_Stream ) 447 arg_panic( "Could not find/open font", path ); 448 otf_get_english_string(face, BDFOTF_POSTSCRIPT_STRING, 0, xlfd, 449 sizeof(xlfd)); 450 ttcname->ttf_name[i] = malloc(sizeof(char) * (strlen(xlfd) + 1 )); 451 strcpy(ttcname->ttf_name[i], xlfd); 452 } 453 return 0; 454} 455 456void print_ttc_table(char* path) 457{ 458 struct ttc_table ttcname; 459 FT_Long i; 460 461 get_ttc_table(path, &ttcname); 462 printf("ttc header count = %ld \n\n", ttcname.ttc_count); 463 printf("Encoding tables available in the true type collection\n\n"); 464 printf("INDEX\tPOSTSCRIPT NAME\n"); 465 printf("-----------------------------------------------------\n"); 466 for(i = 0; i < ttcname.ttc_count; i++) 467 { 468 printf("%ld\t%s\n", i, ttcname.ttf_name[i]); 469 } 470 for(i = 0; i < ttcname.ttc_count; i++) 471 { 472 free(ttcname.ttf_name[i]); 473 } 474 printf("\n\n"); 475 free(ttcname.ttf_name); 476 477 return; 478} 479 480FT_Long getcharindex(FT_Face face, FT_Long code) 481{ 482 FT_Long idx; 483 if (nocmap) { 484 if (code >= face->num_glyphs) 485 idx = 0; 486 else 487 idx = code; 488 } else 489 idx = FT_Get_Char_Index( face, code); 490 491 if ( idx <= 0 || idx > face->num_glyphs) 492 return 0; 493 else 494 return idx; 495} 496 497void print_raw_glyph( FT_Face face) 498{ 499 int pixel,row,col,width; 500 width = face->glyph->metrics.width >> 6; 501 502 printf("\n---Raw-Glyph---\n"); 503 for(row=0; row < face->glyph->metrics.height >> 6; row++) 504 { 505 printf("_"); 506 for(col=0; col < width; col++) 507 { 508 pixel = *(face->glyph->bitmap.buffer+width*row+col)/26; 509 if ( pixel ) printf("%d",pixel); else printf(" "); 510 } 511 printf("_\n"); 512 } 513 printf("----End-----\n"); 514} 515 516int glyph_width( FT_Face face, FT_Long code, FT_Long digit_width ) 517{ 518 int width; 519 520 if (code >= '0' && code <= '9' && digit_width) 521 { 522 width = digit_width; 523 } 524 else 525 { 526 int pitch, h_adv; 527 unsigned spacing = (unsigned)(between_chr * (1<<6));/* convert to fixed point */ 528 529 pitch = ABS(face->glyph->bitmap.pitch); 530 h_adv = face->glyph->metrics.horiAdvance >> 6; 531 width = (face->glyph->metrics.width + spacing) >> 6; 532 533 if(pitch == 0) pitch = h_adv; 534 if(width < pitch) width = pitch; 535 } 536 537 return width; 538} 539 540FT_Long check_digit_width( FT_Face face ) 541{ 542 FT_Long code; 543 FT_Long last_advance = -1; 544 545 for (code='0'; code <= '9'; ++code) 546 { 547 FT_Glyph_Metrics* metrics; 548 549 FT_Load_Char(face, code, ft_load_opts); 550 metrics = &face->glyph->metrics; 551 552 if ((last_advance != -1 && last_advance != metrics->horiAdvance) || 553 metrics->horiBearingX < 0) 554 { 555 last_advance = 0; 556 break; 557 } 558 559 last_advance = metrics->horiAdvance; 560 } 561 562 return last_advance >> 6; 563} 564 565void trim_glyph( FT_GlyphSlot glyph, int *empty_first_col, 566 int *empty_last_col, int *width ) 567{ 568 int row; 569 int stride = glyph->bitmap.pitch; 570 int end = stride-1; 571 int trim_left = 2, trim_right = 2; 572 573 const unsigned char limit = 64u; 574 const unsigned char *image = glyph->bitmap.buffer; 575 576 if (*width < 2) 577 return; /* nothing to do? */ 578 579 for(row=0; row< glyph->metrics.height >> 6; row++) 580 { 581 const unsigned char *column = image+row*stride; 582 if (*column++ < limit && trim_left) 583 { 584 if (*column >= limit/2) 585 trim_left = 1; 586 } 587 else 588 trim_left = 0; 589 590 column = image+row*stride+end; 591 if (*column-- < limit && trim_right) 592 { 593 if (*column >= limit/2) 594 trim_right = 1; 595 } 596 else 597 trim_right = 0; 598 } 599 600 601 (*width) -= trim_left + trim_right; 602 if (*width < 0) *width = 0; 603 604 *empty_first_col = trim_left; 605 *empty_last_col = trim_right; 606} 607 608void convttf(char* path, char* destfile, FT_Long face_index) 609{ 610 FT_Error err; 611 FT_Library library; 612 FT_Face face; 613 int w,h; 614 int row,col; 615 int empty_first_col, empty_last_col; 616 FT_Long charindex; 617 FT_Long idx = 0; 618 FT_Long code; 619 FT_Long digit_width = 0; 620 float extra_space; 621 FT_Long char_count; 622 char use_long_offset; 623 int done = 0; 624 char char_name[1024]; 625 int converted_char_count = 0; 626 int failed_char_count = 0; 627 628 int depth = 2; 629 unsigned char bit_shift = 1u << depth; 630 unsigned char pixel_per_byte = CHAR_BIT / bit_shift; 631 struct font_struct export_font; 632 char pad[] = {0,0,0,0}; 633 unsigned int skip,i; 634 FILE *file; 635 636 /* Initialize engine */ 637 if ( ( err = FT_Init_FreeType( &library ) ) != 0 ) 638 panic( "Error while initializing engine" ); 639 640 /* Load face */ 641 err = FT_New_Face( library, path, (FT_Long) face_index, &face ); 642 if ( err == FT_Err_Cannot_Open_Stream ) 643 arg_panic( "Could not find/open font\n", path ); 644 else if ( err ) 645 arg_panic( "Error while opening font\n", path ); 646 647 648 setcharmap( face ); 649 /* Set font header data */ 650 651 export_font.header.header[0] = 'R'; 652 export_font.header.header[1] = 'B'; 653 export_font.header.header[2] = '1'; 654 export_font.header.header[3] = '2'; 655#if 0 656 export_font.header.height = 0; 657 export_font.header.ascent = 0; 658#endif 659 660 extra_space = (float)(between_row-trim_aa-trim_da); 661 FT_Set_Char_Size( face, 0, pixel_size << 6, hv_resolution, hv_resolution ); 662 export_font.header.ascent = 663 ((face->size->metrics.ascender*(100-trim_ap)/100) >> 6) - trim_aa; 664 665 export_font.header.height = 666 (((face->size->metrics.ascender*(100-trim_ap)/100) - 667 (face->size->metrics.descender*(100-trim_dp)/100)) >> 6) + extra_space; 668 669 printf("\n"); 670 printf("Please wait, converting %s:\n", path); 671 672 /* "face->num_glyphs" is NG.; */ 673 if ( limit_char == 0 ) limit_char = max_char; 674 if ( limit_char > max_char ) limit_char = max_char; 675 676 char_count = 0; 677 678 679 680 export_font.header.maxwidth = 1; 681 export_font.header.depth = 1; 682 firstchar = limit_char; 683 lastchar = start_char; 684 685 if (digits_equally_wide) 686 digit_width = check_digit_width(face); 687 688 /* calculate memory usage */ 689 for(code = start_char; code <= limit_char ; code++ ) 690 { 691 charindex = getcharindex( face, code); 692 if ( !(charindex) ) continue; 693 err = FT_Load_Glyph(face, charindex, ft_load_opts); 694 if ( err ) continue; 695 696 w = glyph_width( face, code, digit_width ); 697 if (w == 0) continue; 698 empty_first_col = empty_last_col = 0; 699 if(trimming) 700 trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w); 701 702 if (export_font.header.maxwidth < w) 703 export_font.header.maxwidth = w; 704 705 706 char_count++; 707 idx += (w*export_font.header.height + pixel_per_byte - 1)/pixel_per_byte; 708 709 if (code >= lastchar) 710 lastchar = code; 711 712 if (code <= firstchar) 713 firstchar = code; 714 } 715 export_font.header.defaultchar = firstchar; 716 export_font.header.firstchar = firstchar; 717 export_font.header.size = lastchar - firstchar + 1; 718 export_font.header.nbits = idx; 719 export_font.header.noffset = export_font.header.size; 720 export_font.header.nwidth = export_font.header.size; 721 722 /* check if we need to use long offsets */ 723 use_long_offset = (export_font.header.nbits >= 0xFFDB ); 724 725 /* allocate memory */ 726 export_font.offset = NULL; 727 export_font.offset_long = NULL; 728 if (use_long_offset) 729 export_font.offset_long = 730 malloc( sizeof(FT_Long)* export_font.header.noffset ); 731 else 732 export_font.offset = 733 malloc( sizeof(unsigned short)* export_font.header.noffset ); 734 735 export_font.width = 736 malloc( sizeof(unsigned char) * export_font.header.nwidth ); 737 export_font.chars_data = 738 malloc( sizeof(unsigned char) * export_font.header.nbits ); 739 740 /* for now we use the full height for each character */ 741 h = export_font.header.height; 742 743 idx = 0; 744 745 for( code = firstchar; code <= lastchar; code++ ) 746 { 747 FT_GlyphSlot slot; 748 FT_Bitmap* source; 749 unsigned char* src; 750 unsigned char* tmpbuf; 751 int start_y; 752 753 int glyph_height; 754 int stride; 755 unsigned char* buf; 756 unsigned char* endbuf; 757 758 /* insert empty pixels on the left */ 759 int col_off; 760 int numbits; 761 unsigned int field; 762 763 /* Get gylph index from the char and render it */ 764 charindex = getcharindex( face, code); 765 if ( !charindex ) 766 { 767 if ( use_long_offset ) 768 export_font.offset_long[code - firstchar] = export_font.offset_long[0]; 769 else 770 export_font.offset[code - firstchar] = export_font.offset[0]; 771 export_font.width[code - firstchar] = export_font.width[0]; 772 continue; 773 } 774 775 err = FT_Load_Glyph(face, charindex, ft_load_opts); 776 if ( err ) { 777 continue; 778 } 779 if FT_HAS_GLYPH_NAMES( face ) 780 FT_Get_Glyph_Name( face, charindex, char_name, 16); 781 else 782 char_name[0] = '\0'; 783 784 slot = face->glyph; 785 source = &slot->bitmap; 786#if 0 787 print_raw_glyph( face ); 788#endif 789 w = glyph_width( face, code, digit_width ); 790 if (w == 0) continue; 791 empty_first_col = empty_last_col = 0; 792 793 if(trimming) 794 trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w ); 795 796 if ( use_long_offset ) 797 export_font.offset_long[code - firstchar] = idx; 798 else 799 export_font.offset[code - firstchar] = idx; 800 801 export_font.width[code - firstchar] = w; 802 803 /* copy the glyph bitmap to a full sized glyph bitmap */ 804 src = source->buffer; 805 tmpbuf = malloc(sizeof(unsigned char) * w * h); 806 memset(tmpbuf, 0xff, w*h); 807 start_y = export_font.header.ascent - slot->bitmap_top; 808 809 glyph_height = source->rows; 810 stride = source->pitch; 811 buf = tmpbuf; 812 endbuf = tmpbuf + w*h; 813 814 err = 0; 815 /* insert empty pixels on the left */ 816 col_off = w - stride; 817 if (col_off > 1) col_off /= 2; 818 if (col_off < 0) col_off = 0; 819 820 for(row=0; row < glyph_height; row++) 821 { 822 if(row+start_y < 0 || row+start_y >= h) 823 continue; 824 for(col = empty_first_col; col < stride; col++) 825 { 826 unsigned char *tsrc, *dst; 827 dst = buf + (w*(start_y+row)) + col + col_off; 828 tsrc = src + stride*row + col; 829 if (dst < endbuf && dst >= tmpbuf) 830 *dst = 0xff - *tsrc; 831 else { 832 err = 1; 833 printf("Error! row: %3d col: %3d\n", row, col); 834 } 835 } 836 } 837 if(err) print_raw_glyph(face); 838 839 buf = tmpbuf; 840 field = 0; 841 numbits = pixel_per_byte; 842 843 for(row=0; row < h; row++) 844 { 845 for(col=0; col < w; col++) 846 { 847 unsigned int src2 = *buf++; 848 unsigned int cur_col = (src2 + 8) / 17; 849 field |= (cur_col << (bit_shift*(pixel_per_byte-numbits))); 850 851 if (--numbits == 0) 852 { 853 export_font.chars_data[idx++] = (unsigned char)field; 854 numbits = pixel_per_byte; 855 field = 0; 856 } 857 } 858 } 859 860 /* Pad last byte */ 861 if (numbits != pixel_per_byte) 862 { 863 export_font.chars_data[idx++] = (unsigned char)field; 864 } 865 866 if( dump_glyphs ) 867 { 868 /* debug: dump char */ 869 unsigned char bit_max = (1 << bit_shift) - 1; 870 printf("\n---Converted Glyph Dump---\n"); 871 872 if ( code > 32 && code < 255 ) { 873 unsigned char current_data; 874 unsigned char font_bits; 875 876 row = h; 877 if(use_long_offset) 878 buf = &(export_font.chars_data[export_font.offset_long[ 879 code - firstchar]]); 880 else 881 buf = &(export_font.chars_data[export_font.offset[ 882 code - firstchar]]); 883 numbits = pixel_per_byte; 884 current_data = *buf; 885 do 886 { 887 col = w; 888 printf("-"); 889 do 890 { 891 font_bits = current_data & bit_max; 892 if (font_bits==bit_max) 893 printf(" "); 894 else 895 { 896 if(font_bits > bit_max/2) 897 printf("."); 898 else 899 printf("@"); 900 } 901 if (--numbits == 0) 902 { 903 current_data = *(++buf); 904 numbits = pixel_per_byte; 905 } 906 else 907 { 908 current_data >>= bit_shift; 909 } 910 } while (--col); 911 printf("-\n"); 912 } while (--row); 913 } 914 buf = NULL; 915 printf("---End Glyph Dump---\n"); 916 } 917 918 free(tmpbuf); 919 converted_char_count++; 920 done = (100*(converted_char_count))/char_count; 921 printf("Converted %s %d (%d%%)\e[K\r", 922 char_name,converted_char_count,done); fflush(stdout); 923 } 924 925 file = fopen(destfile, "wb"); 926 printf("Writing %s\n", destfile); 927 928 /* font info */ 929 writestr(file, VERSION, 4); 930 writeshort(file, export_font.header.maxwidth); 931 writeshort(file, export_font.header.height); 932 writeshort(file, export_font.header.ascent); 933 writeshort(file, export_font.header.depth); 934 writeint(file, export_font.header.firstchar); 935 writeint(file, export_font.header.defaultchar); 936 writeint(file, export_font.header.size); 937 writeint(file, export_font.header.nbits); 938 writeint(file, export_font.header.noffset); 939 writeint(file, export_font.header.nwidth); 940 941 fwrite( (char*)export_font.chars_data, 1, 942 export_font.header.nbits, file); 943 free(export_font.chars_data); 944 945 946 947 if ( use_long_offset ) 948 { 949 skip = ((export_font.header.nbits + 3) & ~3) - 950 export_font.header.nbits; 951 fwrite(pad, 1, skip, file); /* pad */ 952 for(i = 0; i < export_font.header.noffset; i++) 953 writeint(file, export_font.offset_long[i]); 954 } 955 else 956 { 957 skip = ((export_font.header.nbits + 1) & ~1) - 958 export_font.header.nbits; 959 fwrite(pad, 1, skip, file); /* pad */ 960 for(i = 0; i < export_font.header.noffset; i++) 961 writeshort(file, export_font.offset[i]); 962 } 963 964 for(i = 0; i < export_font.header.nwidth; i++) 965 writebyte(file, export_font.width[i]); 966 free(export_font.width); 967 968 if ( use_long_offset ) 969 free(export_font.offset_long); 970 else 971 free(export_font.offset); 972 973 fclose(file); 974 FT_Done_Face( face ); 975 FT_Done_FreeType( library ); 976 printf("done (converted %d glyphs, %d errors).\e[K\n\n", 977 converted_char_count, failed_char_count); 978 979} 980 981void convttc(char* path) 982{ 983 struct ttc_table ttcname; 984 FT_Long i; 985 986 get_ttc_table(path, &ttcname); 987 988 if (ttcname.ttc_count == 0) 989 { 990 printf("This file is a not true type font.\n"); 991 return; 992 } 993 994 /* default */ 995 if (!flg_all_ttc && ttc_index == -1) 996 { 997 if (!oflag) 998 { /* generate filename */ 999 snprintf(outfile, sizeof(outfile), 1000 "%d-%s.fnt", pixel_size, basename(path)); 1001 } 1002 convttf(path, outfile, (FT_Long) 0); 1003 } 1004 1005 /* set face_index of ttc */ 1006 else if (!flg_all_ttc) 1007 { 1008 print_ttc_table(path); 1009 if ( !oflag ) 1010 { 1011 if (ttc_index >= 0 && 1012 ttc_index < ttcname.ttc_count) 1013 { 1014 if (strcmp(ttcname.ttf_name[ttc_index], "") != 0) 1015 { 1016 snprintf(outfile, sizeof(outfile), "%d-%s.fnt", 1017 pixel_size, ttcname.ttf_name[ttc_index]); 1018 } 1019 else 1020 { 1021 snprintf(outfile, sizeof(outfile), "%d-%s-%ld.fnt", 1022 pixel_size, basename(path), ttc_index); 1023 } 1024 } 1025 else 1026 { 1027 printf("illegal face index of ttc.\n"); 1028 } 1029 } 1030 convttf(path, outfile, ttc_index); 1031 } 1032 else { /* convert all fonts */ 1033 print_ttc_table(path); 1034 for(i = 0; i < ttcname.ttc_count; i++) 1035 { 1036 snprintf(outfile, sizeof(outfile), "%d-%s.fnt", 1037 pixel_size, ttcname.ttf_name[i]); 1038 convttf(path, outfile, i); 1039 } 1040 } 1041 1042 for(i = 0; i < ttcname.ttc_count; i++) 1043 { 1044 free(ttcname.ttf_name[i]); 1045 } 1046 free(ttcname.ttf_name); 1047} 1048 1049 1050 1051/* parse command line options*/ 1052void getopts(int *pac, char ***pav) 1053{ 1054 char *p; 1055 char **av; 1056 int ac; 1057 ac = *pac; 1058 av = *pav; 1059 1060 limit_char = max_char; 1061 start_char = 0; 1062 1063 while (ac > 0 && av[0][0] == '-') { 1064 p = &av[0][1]; 1065 while( *p) 1066 switch(*p++) { 1067 case 'h':case 'H': 1068 usage(); 1069 break; 1070 case ' ': /* multiple -args on av[]*/ 1071 while( *p && *p == ' ') 1072 p++; 1073 if( *p++ != '-') /* next option must have dash*/ 1074 p = ""; 1075 break; /* proceed to next option*/ 1076 case 'o': /* set output file*/ 1077 oflag = 1; 1078 if (*p) { 1079 strcpy(outfile, p); 1080 while (*p && *p != ' ') 1081 p++; 1082 } 1083 else { 1084 av++; ac--; 1085 if (ac > 0) 1086 strcpy(outfile, av[0]); 1087 } 1088 break; 1089 case 'l': /* set encoding limit*/ 1090 if (*p) { 1091 limit_char = atoi(p); 1092 while (*p && *p != ' ') 1093 p++; 1094 } 1095 else { 1096 av++; ac--; 1097 if (ac > 0) 1098 limit_char = atoi(av[0]); 1099 } 1100 break; 1101 case 's': /* set encoding start*/ 1102 if (*p) { 1103 start_char = atol(p); 1104 while (*p && *p != ' ') 1105 p++; 1106 } 1107 else { 1108 av++; ac--; 1109 if (ac > 0) 1110 start_char = atol(av[0]); 1111 } 1112 break; 1113 case 'p': /* set pixel size*/ 1114 if (*p) { 1115 pixel_size = atoi(p); 1116 while (*p && *p != ' ') 1117 p++; 1118 } 1119 else { 1120 av++; ac--; 1121 if (ac > 0) 1122 pixel_size = atoi(av[0]); 1123 } 1124 break; 1125 case 'c': /* set spaece between characters */ 1126 { 1127 if (*p) { 1128 between_chr = atof(p); 1129 while (*p && *p != ' ') 1130 p++; 1131 } 1132 else { 1133 av++; ac--; 1134 if (ac > 0) 1135 between_chr = atof(av[0]); 1136 } 1137 break; 1138 } 1139 case 'd': 1140 dump_glyphs = 1; 1141 while (*p && *p != ' ') 1142 p++; 1143 break; 1144 case 'x': 1145 trimming = 1; 1146 while (*p && *p != ' ') 1147 p++; 1148 break; 1149 case 'X': 1150 if (*p) { 1151 hv_resolution = atoi(p); 1152 while (*p && *p != ' ') 1153 p++; 1154 } 1155 else { 1156 av++; ac--; 1157 if (ac > 0) 1158 hv_resolution = atoi(av[0]); 1159 } 1160 break; 1161 case 'r': 1162 if (*p) { 1163 between_row = atof(p); 1164 while (*p && *p != ' ') 1165 p++; 1166 } 1167 else { 1168 av++; ac--; 1169 if (ac > 0) 1170 between_row = atof(av[0]); 1171 } 1172 break; 1173 case 'T': 1174 if(*p == 'A') { 1175 if(*(++p)) { 1176 trim_ap = atoi(p); 1177 while (*p && *p != ' ') 1178 p++; 1179 } 1180 else { 1181 av++; ac--; 1182 if (ac > 0) 1183 trim_ap = atoi(av[0]); 1184 } 1185 break; 1186 } 1187 if(*p == 'D') { 1188 if(*(++p)) { 1189 trim_dp = atoi(p); 1190 while (*p && *p != ' ') 1191 p++; 1192 } 1193 else { 1194 av++; ac--; 1195 if (ac > 0) 1196 trim_dp = atoi(av[0]); 1197 } 1198 break; 1199 } 1200 if(*p == 'a') { 1201 if(*(++p)) { 1202 trim_aa = atoi(p); 1203 while (*p && *p != ' ') 1204 p++; 1205 } 1206 else { 1207 av++; ac--; 1208 if (ac > 0) 1209 trim_aa = atoi(av[0]); 1210 } 1211 break; 1212 } 1213 if(*p == 'd') { 1214 if(*(++p)) { 1215 trim_da = atoi(p); 1216 1217 } 1218 else { 1219 av++; ac--; 1220 if (ac > 0) 1221 trim_da = atoi(av[0]); 1222 } 1223 break; 1224 } 1225 fprintf(stderr, "Unknown option ignored: %s\n", p-1); 1226 while (*p && *p != ' ') 1227 p++; 1228 break; 1229 case 't': /* display ttc table */ 1230 if (*p == 't') { 1231 pct = 1; 1232 while (*p && *p != ' ') 1233 p++; 1234 } 1235 1236 else if (*p == 'a') { 1237 flg_all_ttc = 1; 1238 while (*p && *p != ' ') 1239 p++; 1240 } 1241 1242 else if (*p) { 1243 ttc_index = atoi(p); 1244 while (*p && *p != ' ') 1245 p++; 1246 } 1247 else { 1248 av++; ac--; 1249 if (ac > 0) 1250 ttc_index = atoi(av[0]); 1251 } 1252 break; 1253 case 'w': /* Don't try to make digits equally wide */ 1254 digits_equally_wide = 0; 1255 while (*p && *p != ' ') 1256 p++; 1257 break; 1258 case 'L': /* Light rendering algorithm */ 1259 ft_load_opts |= FT_LOAD_TARGET_LIGHT; 1260 break; 1261 1262 default: 1263 fprintf(stderr, "Unknown option ignored: %s\n", p-1); 1264 while (*p && *p != ' ') 1265 p++; 1266 } 1267 ++av; --ac; 1268 } 1269 *pac = ac; 1270 *pav = av; 1271} 1272 1273 1274int main(int ac, char **av) 1275{ 1276 int ret = 0; 1277 1278 ++av; --ac; /* skip av[0]*/ 1279 1280 getopts(&ac, &av); /* read command line options*/ 1281 1282 if (ac < 1) 1283 { 1284 usage(); 1285 } 1286 if (oflag) 1287 { 1288 if (ac > 1) 1289 { 1290 usage(); 1291 } 1292 } 1293 1294 if (limit_char < start_char) 1295 { 1296 usage(); 1297 exit(0); 1298 } 1299 1300 while (pct && ac > 0) 1301 { 1302 print_ttc_table(av[0]); 1303 ++av; --ac; 1304 exit(0); 1305 } 1306 1307 while (ac > 0) 1308 { 1309 convttc(av[0]); 1310 ++av; --ac; 1311 } 1312 1313 exit(ret); 1314} 1315 1316 1317 1318/* 1319 * Trie node structure. 1320 */ 1321typedef struct { 1322 unsigned short key; /* Key value. */ 1323 unsigned short val; /* Data for the key. */ 1324 unsigned long sibs; /* Offset of siblings from trie beginning. */ 1325 unsigned long kids; /* Offset of children from trie beginning. */ 1326} node_t; 1327 1328/* 1329 * The trie used for remapping codes. 1330 */ 1331static node_t *nodes; 1332static unsigned long nodes_used = 0; 1333 1334int 1335otf2bdf_remap(unsigned short *code) 1336{ 1337 unsigned long i, n, t; 1338 unsigned short c, codes[2]; 1339 1340 /* 1341 * If no mapping table was loaded, then simply return the code. 1342 */ 1343 if (nodes_used == 0) 1344 return 1; 1345 1346 c = *code; 1347 codes[0] = (c >> 8) & 0xff; 1348 codes[1] = c & 0xff; 1349 1350 for (i = n = 0; i < 2; i++) { 1351 t = nodes[n].kids; 1352 if (t == 0) 1353 return 0; 1354 for (; nodes[t].sibs && nodes[t].key != codes[i]; t = nodes[t].sibs); 1355 if (nodes[t].key != codes[i]) 1356 return 0; 1357 n = t; 1358 } 1359 1360 *code = nodes[n].val; 1361 return 1; 1362}