Android: no need to keep RockboxPCM_class around
[maemo-rb.git] / tools / convttf.c
blobca9e4fbb4d51b03e306daed8b282ae56223f2fc7
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Jonas Hurrelmann
12 * A command-line tool to convert ttf file to bitmap fonts
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include <ft2build.h>
22 #include FT_FREETYPE_H
23 #include FT_GLYPH_H
25 #include <stdbool.h>
26 #include <stdio.h>
27 #ifdef WIN32
28 #include <windows.h>
29 #else
30 #include <stdlib.h>
31 #include <unistd.h>
32 #endif
33 #include FT_SFNT_NAMES_H
34 #include FT_TRUETYPE_TABLES_H
36 #include <string.h>
38 * Set the default values used to generate a BDF font.
40 #ifndef DEFAULT_PLATFORM_ID
41 #define DEFAULT_PLATFORM_ID 3
42 #endif
44 #ifndef DEFAULT_ENCODING_ID
45 #define DEFAULT_ENCODING_ID 1
46 #endif
48 #define ABS(x) (((x) < 0) ? -(x) : (x))
50 #define VERSION "RB12"
52 * nameID macros for getting strings from the OT font.
54 enum {
55 BDFOTF_COPYRIGHT_STRING = 0,
56 BDFOTF_FAMILY_STRING,
57 BDFOTF_SUBFAMILY_STRING,
58 BDFOTF_UNIQUEID_STRING,
59 BDFOTF_FULLNAME_STRING,
60 BDFOTF_VENDOR_STRING,
61 BDFOTF_POSTSCRIPT_STRING,
62 BDFOTF_TRADEMARK_STRING,
65 * String names for the string indexes. Used for error messages.
67 static char *string_names[] = {
68 "\"Copyright\"",
69 "\"Family\"",
70 "\"SubFamily\"",
71 "\"Unique ID\"",
72 "\"Full Name\"",
73 "\"Vendor\"",
74 "\"Postscript Name\"",
75 "\"Trademark\""
80 * The default platform and encoding ID's.
82 static int pid = DEFAULT_PLATFORM_ID;
83 static int eid = DEFAULT_ENCODING_ID;
87 * A flag indicating if a CMap was found or not.
89 static FT_UShort nocmap;
91 int pct = 0; /* display ttc table if it is not zero. */
92 unsigned long max_char = 65535;
93 int pixel_size = 15;
94 unsigned long start_char = 0;
95 unsigned long limit_char;
96 unsigned long firstchar = 0;
97 unsigned long lastchar;
98 FT_Long ttc_index = -1;
99 int flg_all_ttc = 0;
100 short antialias = 1; /* smooth fonts with gray levels */
101 int oflag = 0;
102 char outfile[1024];
103 float between_chr = 0.0f;
104 float between_row = 0.0f;
105 int hv_resolution = 60;
106 int dump_glyphs = 0;
107 int trimming = 0;
108 int trim_dp = 0; /* trim descent percent */
109 int trim_da = 0; /* trim descnet actual */
110 int trim_ap = 0; /* trim ascent precent */
111 int trim_aa = 0; /* trim ascent actual */
113 struct font_header_struct {
114 char header[4]; /* magic number and version bytes */
115 unsigned short maxwidth; /* max width in pixels */
116 unsigned short height; /* height in pixels */
117 unsigned short ascent; /* ascent (baseline) height */
118 unsigned short depth; /* depth 0=1-bit, 1=4-bit */
119 unsigned long firstchar; /* first character in font */
120 unsigned long defaultchar; /* default character in font */
121 unsigned long size; /* # characters in font */
122 unsigned long nbits; /* # bytes imagebits data in file */ /* = bits_size */
124 FT_Long noffset; /* # longs offset data in file */
125 FT_Long nwidth; /* # bytes width data in file */
128 struct font_struct {
129 struct font_header_struct header;
130 unsigned char *chars_data;
131 unsigned short *offset;
132 FT_Long *offset_long;
133 unsigned char *width;
136 struct ttc_table{
137 FT_Long ttc_count;
138 char **ttf_name;
141 /* exit the program with given message */
142 static void
143 panic( const char* message)
145 fprintf( stderr, "%s\n", message );
146 exit( 1 );
149 static void
150 arg_panic( const char* message, const char* arg )
152 fprintf( stderr, "%s: %s\n", message, arg );
153 exit( 1 );
156 static int writebyte(FILE *fp, unsigned char c)
158 return putc(c, fp) != EOF;
161 static int writeshort(FILE *fp, unsigned short s)
163 putc(s, fp);
164 return putc(s>>8, fp) != EOF;
167 static int writeint(FILE *fp, unsigned int l)
169 putc(l, fp);
170 putc(l>>8, fp);
171 putc(l>>16, fp);
172 return putc(l>>24, fp) != EOF;
175 static int writestr(FILE *fp, char *str, int count)
177 return (int)fwrite(str, 1, count, fp) == count;
180 /* print usage information */
181 void usage(void)
183 char help[] = {
184 "Usage: convttf [options] [input-files]\n"
185 " convttf [options] [-o output-file] [single-input-file]\n\n"
186 " Default output-file : <font-size>-<basename>.fnt.\n"
187 " When '-ta' or '-tc' is specified in command line,\n "
188 " default output-file is: \n"
189 " <font-size>-<internal postscript-name of input-file>.fnt.\n"
190 "Options:\n"
191 " -s N Start output at character encodings >= N\n"
192 " -l N Limit output to character encodings <= N\n"
193 " -p N Font size N in pixel (default N=15)\n"
194 " -c N Character separation in pixel.Insert space between lines.\n"
195 " -x Trim glyphs horizontally of nearly empty space\n"
196 " (to improve spacing on V's W's, etc.)\n"
197 " -X Set the horizontal and vertical resolution (default: 60)\n"
198 " -TA N Trim vertical ascent (N percent)\n"
199 " -TD N Trim vertical descent (N percent)\n"
200 " -Ta N Trim vertical ascent (N pixels)\n"
201 " -Td N Trim vertical descent (N pixels)\n"
202 " -r N Row separation in pixel.Insert space between characters\n"
203 " -d Debug: print converted glyph images\n"
204 " -tt Display the True Type Collection tables available in the font\n"
205 " -t N Index of true type collection. It must be start from 0.(default N=0).\n"
206 " -ta Convert all fonts in ttc (ignores outfile option)\n"
208 fprintf(stderr, "%s", help);
209 exit( 1 );
212 /* remove directory prefix and file suffix from full path*/
213 char *basename(char *path)
215 char *p, *b;
216 static char base[256];
218 /* remove prepended path and extension*/
219 b = path;
220 for (p=path; *p; ++p) {
221 if (*p == '/')
222 b = p + 1;
224 strcpy(base, b);
225 for (p=base; *p; ++p) {
226 if (*p == '.') {
227 *p = 0;
228 break;
231 return base;
235 void setcharmap(FT_Face face)
237 FT_Long i;
240 * Get the requested cmap.
242 for (i = 0; i < face->num_charmaps; i++) {
243 if (face->charmaps[i]->platform_id == pid &&
244 face->charmaps[i]->encoding_id == eid)
245 break;
248 if (i == face->num_charmaps && pid == 3 && eid == 1) {
250 * Make a special case when this fails with pid == 3 and eid == 1.
251 * Change to eid == 0 and try again. This captures the two possible
252 * cases for MS fonts. Some other method should be used to cycle
253 * through all the alternatives later.
255 for (i = 0; i < face->num_charmaps; i++) {
256 if (face->charmaps[i]->platform_id == pid &&
257 face->charmaps[i]->encoding_id == 0)
258 break;
260 if (i < face->num_charmaps) {
261 pid = 3;
262 eid = 1;
263 FT_Set_Charmap(face, face->charmaps[i]);
264 } else {
266 * No CMAP was found.
268 nocmap = 1;
269 pid = eid = -1;
271 } else {
272 FT_Set_Charmap(face, face->charmaps[i]);
273 nocmap = 0;
279 * quote in otf2bdf.
280 * A generic routine to get a name from the OT name table. This routine
281 * always looks for English language names and checks three possibilities:
282 * 1. English names with the MS Unicode encoding ID.
283 * 2. English names with the MS unknown encoding ID.
284 * 3. English names with the Apple Unicode encoding ID.
286 * The particular name ID mut be provided (e.g. nameID = 0 for copyright
287 * string, nameID = 6 for Postscript name, nameID = 1 for typeface name.
289 * If the `dash_to_space' flag is non-zero, all dashes (-) in the name will be
290 * replaced with the character passed.
292 * Returns the number of bytes added.
294 static int
295 otf_get_english_string(FT_Face face, int nameID, int dash_to_space,
296 char *name, int name_size)
299 int j, encid;
300 FT_UInt i, nrec;
301 FT_SfntName sfntName;
302 unsigned char *s;
303 unsigned short slen;
305 nrec = FT_Get_Sfnt_Name_Count(face);
307 for (encid = 1, j = 0; j < 2; j++, encid--) {
309 * Locate one of the MS English font names.
311 for (i = 0; i < nrec; i++) {
312 FT_Get_Sfnt_Name(face, i, &sfntName);
313 if (sfntName.platform_id == 3 &&
314 sfntName.encoding_id == encid &&
315 sfntName.name_id == nameID &&
316 (sfntName.language_id == 0x0409 ||
317 sfntName.language_id == 0x0809 ||
318 sfntName.language_id == 0x0c09 ||
319 sfntName.language_id == 0x1009 ||
320 sfntName.language_id == 0x1409 ||
321 sfntName.language_id == 0x1809)) {
322 s = sfntName.string;
323 slen = sfntName.string_len;
324 break;
328 if (i < nrec) {
329 if (slen >> 1 >= name_size) {
330 fprintf(stderr, "warning: %s string longer than buffer."
331 "Truncating to %d bytes.\n", string_names[nameID], name_size);
332 slen = name_size << 1;
336 * Found one of the MS English font names. The name is by
337 * definition encoded in Unicode, so copy every second byte into
338 * the `name' parameter, assuming there is enough space.
340 for (i = 1; i < slen; i += 2) {
341 if (dash_to_space)
342 *name++ = (s[i] != '-') ? s[i] : ' ';
343 else if (s[i] == '\r' || s[i] == '\n') {
344 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
345 i += 2;
346 *name++ = ' ';
347 *name++ = ' ';
348 } else
349 *name++ = s[i];
351 *name = 0;
352 return (slen >> 1);
357 * No MS English name found, attempt to find an Apple Unicode English
358 * name.
360 for (i = 0; i < nrec; i++) {
361 FT_Get_Sfnt_Name(face, i, &sfntName);
362 if (sfntName.platform_id == 0 && sfntName.language_id == 0 &&
363 sfntName.name_id == nameID) {
364 s = sfntName.string;
365 slen = sfntName.string_len;
366 break;
370 if (i < nrec) {
371 if (slen >> 1 >= name_size) {
372 fprintf(stderr, "warning: %s string longer than buffer."
373 "Truncating to %d bytes.\n", string_names[nameID], name_size);
374 slen = name_size << 1;
378 * Found the Apple Unicode English name. The name is by definition
379 * encoded in Unicode, so copy every second byte into the `name'
380 * parameter, assuming there is enough space.
382 for (i = 1; i < slen; i += 2) {
383 if (dash_to_space)
384 *name++ = (s[i] != '-') ? s[i] : ' ';
385 else if (s[i] == '\r' || s[i] == '\n') {
386 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
387 i += 2;
388 *name++ = ' ';
389 *name++ = ' ';
390 } else
391 *name++ = s[i];
393 *name = 0;
394 return (slen >> 1);
397 return 0;
401 int get_ttc_table(char *path, struct ttc_table *ttcname )
405 FT_Error error;
406 FT_Library library;
407 FT_Face face;
408 FT_Long i;
409 char xlfd[BUFSIZ];
411 /* init number of ttf in ttc */
412 ttcname->ttc_count = 0;
414 /* Initialize engine */
415 if ( ( error = FT_Init_FreeType( &library ) ) != 0 )
417 panic( "Error while initializing engine" );
418 return error;
422 /* Load face */
423 error = FT_New_Face( library, path, (FT_Long) 0, &face );
424 if ( error )
426 arg_panic( "Could not find/open font", path );
427 return error;
430 ttcname->ttc_count = face->num_faces;
431 ttcname->ttf_name = malloc( sizeof(char*) * ttcname->ttc_count);
433 for(i = 0; i < ttcname->ttc_count; i++)
435 error = FT_New_Face( library, path, i, &face );
436 if ( error == FT_Err_Cannot_Open_Stream )
437 arg_panic( "Could not find/open font", path );
438 otf_get_english_string(face, BDFOTF_POSTSCRIPT_STRING, 0, xlfd,
439 sizeof(xlfd));
440 ttcname->ttf_name[i] = malloc(sizeof(char) * (strlen(xlfd) + 1 ));
441 strcpy(ttcname->ttf_name[i], xlfd);
443 return 0;
446 void print_ttc_table(char* path)
448 struct ttc_table ttcname;
449 FT_Long i;
451 get_ttc_table(path, &ttcname);
452 printf("ttc header count = %ld \n\n", ttcname.ttc_count);
453 printf("Encoding tables available in the true type collection\n\n");
454 printf("INDEX\tPOSTSCRIPT NAME\n");
455 printf("-----------------------------------------------------\n");
456 for(i = 0; i < ttcname.ttc_count; i++)
458 printf("%ld\t%s\n", i, ttcname.ttf_name[i]);
460 for(i = 0; i < ttcname.ttc_count; i++)
462 free(ttcname.ttf_name[i]);
464 printf("\n\n");
465 free(ttcname.ttf_name);
467 return;
470 FT_Long getcharindex(FT_Face face, FT_Long code)
472 FT_Long idx;
473 if (nocmap) {
474 if (code >= face->num_glyphs)
475 idx = 0;
476 else
477 idx = code;
478 } else
479 idx = FT_Get_Char_Index( face, code);
481 if ( idx <= 0 || idx > face->num_glyphs)
482 return 0;
483 else
484 return idx;
487 void print_raw_glyph( FT_Face face)
489 int pixel,row,col,width;
490 width = face->glyph->metrics.width >> 6;
492 printf("\n---Raw-Glyph---\n");
493 for(row=0; row < face->glyph->metrics.height >> 6; row++)
495 printf("_");
496 for(col=0; col < width; col++)
498 pixel = *(face->glyph->bitmap.buffer+width*row+col)/26;
499 if ( pixel ) printf("%d",pixel); else printf(" ");
501 printf("_\n");
503 printf("----End-----\n");
506 int glyph_width( FT_Face face)
508 int pitch, h_adv, width;
509 unsigned spacing = (unsigned)(between_chr * (1<<6));/* convert to fixed point */
511 pitch = ABS(face->glyph->bitmap.pitch);
512 h_adv = face->glyph->metrics.horiAdvance >> 6;
513 width = (face->glyph->metrics.width + spacing) >> 6;
515 if(pitch == 0) pitch = h_adv;
516 if(width < pitch) width = pitch;
517 if(width == 0) return 0;
519 return width;
523 void trim_glyph( FT_GlyphSlot glyph, int *empty_first_col,
524 int *empty_last_col, int *width )
526 int row;
527 int stride = glyph->bitmap.pitch;
528 int end = stride-1;
529 int trim_left = 2, trim_right = 2;
531 const unsigned char limit = 64u;
532 const unsigned char *image = glyph->bitmap.buffer;
534 if (*width < 2)
535 return; /* nothing to do? */
537 for(row=0; row< glyph->metrics.height >> 6; row++)
539 const unsigned char *column = image+row*stride;
540 if (*column++ < limit && trim_left)
542 if (*column >= limit/2)
543 trim_left = 1;
545 else
546 trim_left = 0;
548 column = image+row*stride+end;
549 if (*column-- < limit && trim_right)
551 if (*column >= limit/2)
552 trim_right = 1;
554 else
555 trim_right = 0;
559 (*width) -= trim_left + trim_right;
560 if (*width < 0) *width = 0;
562 *empty_first_col = trim_left;
563 *empty_last_col = trim_right;
566 void convttf(char* path, char* destfile, FT_Long face_index)
568 FT_Error error;
569 FT_Library library;
570 FT_Face face;
571 int w,h;
572 int row,col;
573 int empty_first_col, empty_last_col;
574 FT_Long charindex;
575 FT_Long index = 0;
576 FT_Long code;
578 int depth = 2;
579 unsigned char bit_shift = 1 << depth;
580 unsigned char pixel_per_byte = CHAR_BIT / bit_shift;
582 /* Initialize engine */
583 if ( ( error = FT_Init_FreeType( &library ) ) != 0 )
584 panic( "Error while initializing engine" );
586 /* Load face */
587 error = FT_New_Face( library, path, (FT_Long) face_index, &face );
588 if ( error == FT_Err_Cannot_Open_Stream )
589 arg_panic( "Could not find/open font\n", path );
590 else if ( error )
591 arg_panic( "Error while opening font\n", path );
594 setcharmap( face );
595 /* Set font header data */
596 struct font_struct export_font;
597 export_font.header.header[0] = 'R';
598 export_font.header.header[1] = 'B';
599 export_font.header.header[2] = '1';
600 export_font.header.header[3] = '2';
601 //export_font.header.height = 0;
602 //export_font.header.ascent = 0;
604 float extra_space = (float)(between_row-trim_aa-trim_da);
605 FT_Set_Char_Size( face, 0, pixel_size << 6, hv_resolution, hv_resolution );
606 export_font.header.ascent =
607 ((face->size->metrics.ascender*(100-trim_ap)/100) >> 6) - trim_aa;
609 export_font.header.height =
610 (((face->size->metrics.ascender*(100-trim_ap)/100) -
611 (face->size->metrics.descender*(100-trim_dp)/100)) >> 6) + extra_space;
613 printf("\n");
614 printf("Please wait, converting %s:\n", path);
616 /* "face->num_glyphs" is NG.; */
617 if ( limit_char == 0 ) limit_char = max_char;
618 if ( limit_char > max_char ) limit_char = max_char;
620 FT_Long char_count = 0;
624 export_font.header.maxwidth = 1;
625 export_font.header.depth = 1;
626 firstchar = limit_char;
627 lastchar = start_char;
629 /* calculate memory usage */
630 for(code = start_char; code <= limit_char ; code++ )
632 charindex = getcharindex( face, code);
633 if ( !(charindex) ) continue;
634 error = FT_Load_Glyph( face, charindex,
635 (FT_LOAD_RENDER | FT_LOAD_NO_BITMAP) );
636 if ( error ) continue;
638 w = glyph_width( face );
639 if (w == 0) continue;
640 empty_first_col = empty_last_col = 0;
641 if(trimming)
642 trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w);
644 if (export_font.header.maxwidth < w)
645 export_font.header.maxwidth = w;
648 char_count++;
649 index += (w*export_font.header.height + pixel_per_byte - 1)/pixel_per_byte;
651 if (code >= lastchar)
652 lastchar = code;
654 if (code <= firstchar)
655 firstchar = code;
657 export_font.header.defaultchar = firstchar;
658 export_font.header.firstchar = firstchar;
659 export_font.header.size = lastchar - firstchar + 1;
660 export_font.header.nbits = index;
661 export_font.header.noffset = export_font.header.size;
662 export_font.header.nwidth = export_font.header.size;
664 /* check if we need to use long offsets */
665 char use_long_offset = (export_font.header.nbits >= 0xFFDB );
667 /* allocate memory */
668 export_font.offset = NULL;
669 export_font.offset_long = NULL;
670 if (use_long_offset)
671 export_font.offset_long =
672 malloc( sizeof(FT_Long)* export_font.header.noffset );
673 else
674 export_font.offset =
675 malloc( sizeof(unsigned short)* export_font.header.noffset );
677 export_font.width =
678 malloc( sizeof(unsigned char) * export_font.header.nwidth );
679 export_font.chars_data =
680 malloc( sizeof(unsigned char) * export_font.header.nbits );
682 /* for now we use the full height for each character */
683 h = export_font.header.height;
685 index = 0;
686 int done = 0;
687 char char_name[1024];
688 int converted_char_count = 0;
689 int failed_char_count = 0;
691 for( code = firstchar; code <= lastchar; code++ )
693 /* Get gylph index from the char and render it */
694 charindex = getcharindex( face, code);
695 if ( !charindex )
697 if ( use_long_offset )
698 export_font.offset_long[code - firstchar] = export_font.offset_long[0];
699 else
700 export_font.offset[code - firstchar] = export_font.offset[0];
701 export_font.width[code - firstchar] = export_font.width[0];
702 continue;
705 error = FT_Load_Glyph( face, charindex ,
706 (FT_LOAD_RENDER | FT_LOAD_NO_BITMAP) );
707 if ( error ) {
708 continue;
710 if FT_HAS_GLYPH_NAMES( face )
711 FT_Get_Glyph_Name( face, charindex, char_name, 16);
712 else
713 char_name[0] = '\0';
715 FT_GlyphSlot slot = face->glyph;
716 FT_Bitmap* source = &slot->bitmap;
717 //print_raw_glyph( face );
718 w = glyph_width( face );
719 if (w == 0) continue;
720 empty_first_col = empty_last_col = 0;
722 if(trimming)
723 trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w );
725 if ( use_long_offset )
726 export_font.offset_long[code - firstchar] = index;
727 else
728 export_font.offset[code - firstchar] = index;
730 export_font.width[code - firstchar] = w;
732 /* copy the glyph bitmap to a full sized glyph bitmap */
733 unsigned char* src = source->buffer;
734 unsigned char* tmpbuf = malloc(sizeof(unsigned char) * w * h);
735 memset(tmpbuf, 0xff, w*h);
736 int start_y = export_font.header.ascent - slot->bitmap_top;
738 int glyph_height = source->rows;
739 int stride = source->pitch;
740 unsigned char* buf = tmpbuf;
741 unsigned char* endbuf = tmpbuf + w*h;
743 int error = 0;
744 /* insert empty pixels on the left */
745 int col_off = w - stride;
746 if (col_off > 1) col_off /= 2;
747 if (col_off < 0) col_off = 0;
749 for(row=0; row < glyph_height; row++)
751 if(row+start_y < 0 || row+start_y >= h)
752 continue;
753 for(col = empty_first_col; col < stride; col++)
755 unsigned char *tsrc, *dst;
756 dst = buf + (w*(start_y+row)) + col + col_off;
757 tsrc = src + stride*row + col;
758 if (dst < endbuf && dst >= tmpbuf)
759 *dst = 0xff - *tsrc;
760 else {
761 error = 1;
762 printf("Error! row: %3d col: %3d\n", row, col);
766 if(error) print_raw_glyph(face);
768 buf = tmpbuf;
769 int numbits;
770 unsigned int field;
771 field = 0;
772 numbits = pixel_per_byte;
774 for(row=0; row < h; row++)
776 for(col=0; col < w; col++)
778 unsigned int src = *buf++;
779 unsigned int cur_col = (src + 8) / 17;
780 field |= (cur_col << (bit_shift*(pixel_per_byte-numbits)));
782 if (--numbits == 0)
784 export_font.chars_data[index++] = (unsigned char)field;
785 numbits = pixel_per_byte;
786 field = 0;
791 /* Pad last byte */
792 if (numbits != pixel_per_byte)
794 export_font.chars_data[index++] = (unsigned char)field;
797 if( dump_glyphs )
799 /* debug: dump char */
800 printf("\n---Converted Glyph Dump---\n");
801 unsigned char bit_max = (1 << bit_shift) - 1;
802 if ( code > 32 && code < 255 ) {
803 row = h;
804 if(use_long_offset)
805 buf = &(export_font.chars_data[export_font.offset_long[
806 code - firstchar]]);
807 else
808 buf = &(export_font.chars_data[export_font.offset[
809 code - firstchar]]);
810 unsigned char current_data;
811 unsigned char font_bits;
812 numbits = pixel_per_byte;
813 current_data = *buf;
816 col = w;
817 printf("-");
820 font_bits = current_data & bit_max;
821 if (font_bits==bit_max)
822 printf(" ");
823 else
825 if(font_bits > bit_max/2)
826 printf(".");
827 else
828 printf("@");
830 if (--numbits == 0)
832 current_data = *(++buf);
833 numbits = pixel_per_byte;
835 else
837 current_data >>= bit_shift;
839 } while (--col);
840 printf("-\n");
841 } while (--row);
843 buf = NULL;
844 printf("---End Glyph Dump---\n");
847 free(tmpbuf);
848 converted_char_count++;
849 done = (100*(converted_char_count))/char_count;
850 printf("Converted %s %d (%d%%)\e[K\r",
851 char_name,converted_char_count,done); fflush(stdout);
854 FILE *file = fopen(destfile, "w");
855 printf("Writing %s\n", destfile);
857 /* font info */
858 writestr(file, VERSION, 4);
859 writeshort(file, export_font.header.maxwidth);
860 writeshort(file, export_font.header.height);
861 writeshort(file, export_font.header.ascent);
862 writeshort(file, export_font.header.depth);
863 writeint(file, export_font.header.firstchar);
864 writeint(file, export_font.header.defaultchar);
865 writeint(file, export_font.header.size);
866 writeint(file, export_font.header.nbits);
867 writeint(file, export_font.header.noffset);
868 writeint(file, export_font.header.nwidth);
870 fwrite( (char*)export_font.chars_data, 1,
871 export_font.header.nbits, file);
872 free(export_font.chars_data);
874 int skip,i;
875 char pad[] = {0,0,0,0};
876 if ( use_long_offset )
878 skip = ((export_font.header.nbits + 3) & ~3) -
879 export_font.header.nbits;
880 fwrite(pad, 1, skip, file); /* pad */
881 for(i = 0; i < export_font.header.noffset; i++)
882 writeint(file, export_font.offset_long[i]);
884 else
886 skip = ((export_font.header.nbits + 1) & ~1) -
887 export_font.header.nbits;
888 fwrite(pad, 1, skip, file); /* pad */
889 for(i = 0; i < export_font.header.noffset; i++)
890 writeshort(file, export_font.offset[i]);
893 for(i = 0; i < export_font.header.nwidth; i++)
894 writebyte(file, export_font.width[i]);
895 free(export_font.width);
897 if ( use_long_offset )
898 free(export_font.offset_long);
899 else
900 free(export_font.offset);
902 fclose(file);
903 FT_Done_Face( face );
904 FT_Done_FreeType( library );
905 printf("done (converted %d glyphs, %d errors).\e[K\n\n",
906 converted_char_count, failed_char_count);
910 void convttc(char* path)
912 struct ttc_table ttcname;
913 FT_Long i;
915 get_ttc_table(path, &ttcname);
917 if (ttcname.ttc_count == 0)
919 printf("This file is a not true type font.\n");
920 return;
923 /* default */
924 if (!flg_all_ttc && ttc_index == -1)
926 if (!oflag)
927 { /* generate filename */
928 snprintf(outfile, sizeof(outfile),
929 "%d-%s.fnt", pixel_size, basename(path));
931 convttf(path, outfile, (FT_Long) 0);
934 /* set face_index of ttc */
935 else if (!flg_all_ttc)
937 print_ttc_table(path);
938 if ( !oflag )
940 if (ttc_index >= 0 &&
941 ttc_index < ttcname.ttc_count)
943 if (strcmp(ttcname.ttf_name[ttc_index], "") != 0)
945 snprintf(outfile, sizeof(outfile), "%d-%s.fnt",
946 pixel_size, ttcname.ttf_name[ttc_index]);
948 else
950 snprintf(outfile, sizeof(outfile), "%d-%s-%ld.fnt",
951 pixel_size, basename(path), ttc_index);
954 else
956 printf("illegal face index of ttc.\n");
959 convttf(path, outfile, ttc_index);
961 else { /* convert all fonts */
962 print_ttc_table(path);
963 for(i = 0; i < ttcname.ttc_count; i++)
965 snprintf(outfile, sizeof(outfile), "%d-%s.fnt",
966 pixel_size, ttcname.ttf_name[i]);
967 convttf(path, outfile, i);
971 for(i = 0; i < ttcname.ttc_count; i++)
973 free(ttcname.ttf_name[i]);
975 free(ttcname.ttf_name);
980 /* parse command line options*/
981 void getopts(int *pac, char ***pav)
983 char *p;
984 char **av;
985 int ac;
986 ac = *pac;
987 av = *pav;
989 limit_char = max_char;
990 start_char = 0;
992 while (ac > 0 && av[0][0] == '-') {
993 p = &av[0][1];
994 while( *p)
995 switch(*p++) {
996 case 'h':case 'H':
997 usage();
998 break;
999 case ' ': /* multiple -args on av[]*/
1000 while( *p && *p == ' ')
1001 p++;
1002 if( *p++ != '-') /* next option must have dash*/
1003 p = "";
1004 break; /* proceed to next option*/
1005 case 'o': /* set output file*/
1006 oflag = 1;
1007 if (*p) {
1008 strcpy(outfile, p);
1009 while (*p && *p != ' ')
1010 p++;
1012 else {
1013 av++; ac--;
1014 if (ac > 0)
1015 strcpy(outfile, av[0]);
1017 break;
1018 case 'l': /* set encoding limit*/
1019 if (*p) {
1020 limit_char = atoi(p);
1021 while (*p && *p != ' ')
1022 p++;
1024 else {
1025 av++; ac--;
1026 if (ac > 0)
1027 limit_char = atoi(av[0]);
1029 break;
1030 case 's': /* set encoding start*/
1031 if (*p) {
1032 start_char = atol(p);
1033 while (*p && *p != ' ')
1034 p++;
1036 else {
1037 av++; ac--;
1038 if (ac > 0)
1039 start_char = atol(av[0]);
1041 break;
1042 case 'p': /* set pixel size*/
1043 if (*p) {
1044 pixel_size = atoi(p);
1045 while (*p && *p != ' ')
1046 p++;
1048 else {
1049 av++; ac--;
1050 if (ac > 0)
1051 pixel_size = atoi(av[0]);
1053 break;
1054 case 'c': /* set spaece between characters */
1056 if (*p) {
1057 between_chr = atof(p);
1058 while (*p && *p != ' ')
1059 p++;
1061 else {
1062 av++; ac--;
1063 if (ac > 0)
1064 between_chr = atof(av[0]);
1066 break;
1068 case 'd':
1069 dump_glyphs = 1;
1070 while (*p && *p != ' ')
1071 p++;
1072 break;
1073 case 'x':
1074 trimming = 1;
1075 while (*p && *p != ' ')
1076 p++;
1077 break;
1078 case 'X':
1079 if (*p) {
1080 hv_resolution = atoi(p);
1081 while (*p && *p != ' ')
1082 p++;
1084 else {
1085 av++; ac--;
1086 if (ac > 0)
1087 hv_resolution = atoi(av[0]);
1089 break;
1090 case 'r':
1091 if (*p) {
1092 between_row = atof(p);
1093 while (*p && *p != ' ')
1094 p++;
1096 else {
1097 av++; ac--;
1098 if (ac > 0)
1099 between_row = atof(av[0]);
1101 break;
1102 case 'T':
1103 if(*p == 'A') {
1104 if(*(++p)) {
1105 trim_ap = atoi(p);
1106 while (*p && *p != ' ')
1107 p++;
1109 else {
1110 av++; ac--;
1111 if (ac > 0)
1112 trim_ap = atoi(av[0]);
1114 break;
1116 if(*p == 'D') {
1117 if(*(++p)) {
1118 trim_dp = atoi(p);
1119 while (*p && *p != ' ')
1120 p++;
1122 else {
1123 av++; ac--;
1124 if (ac > 0)
1125 trim_dp = atoi(av[0]);
1127 break;
1129 if(*p == 'a') {
1130 if(*(++p)) {
1131 trim_aa = atoi(p);
1132 while (*p && *p != ' ')
1133 p++;
1135 else {
1136 av++; ac--;
1137 if (ac > 0)
1138 trim_aa = atoi(av[0]);
1140 break;
1142 if(*p == 'd') {
1143 if(*(++p)) {
1144 trim_da = atoi(p);
1147 else {
1148 av++; ac--;
1149 if (ac > 0)
1150 trim_da = atoi(av[0]);
1152 break;
1154 fprintf(stderr, "Unknown option ignored: %s\n", p-1);
1155 while (*p && *p != ' ')
1156 p++;
1157 break;
1158 case 't': /* display ttc table */
1159 if (*p == 't') {
1160 pct = 1;
1161 while (*p && *p != ' ')
1162 p++;
1165 else if (*p == 'a') {
1166 flg_all_ttc = 1;
1167 while (*p && *p != ' ')
1168 p++;
1171 else if (*p) {
1172 ttc_index = atoi(p);
1173 while (*p && *p != ' ')
1174 p++;
1176 else {
1177 av++; ac--;
1178 if (ac > 0)
1179 ttc_index = atoi(av[0]);
1181 break;
1183 default:
1184 fprintf(stderr, "Unknown option ignored: %s\n", p-1);
1185 while (*p && *p != ' ')
1186 p++;
1188 ++av; --ac;
1190 *pac = ac;
1191 *pav = av;
1195 int main(int ac, char **av)
1197 int ret = 0;
1199 ++av; --ac; /* skip av[0]*/
1201 getopts(&ac, &av); /* read command line options*/
1203 if (ac < 1)
1205 usage();
1207 if (oflag)
1209 if (ac > 1)
1211 usage();
1215 if (limit_char < start_char)
1217 usage();
1218 exit(0);
1221 while (pct && ac > 0)
1223 print_ttc_table(av[0]);
1224 ++av; --ac;
1225 exit(0);
1228 while (ac > 0)
1230 convttc(av[0]);
1231 ++av; --ac;
1234 exit(ret);
1240 * Trie node structure.
1242 typedef struct {
1243 unsigned short key; /* Key value. */
1244 unsigned short val; /* Data for the key. */
1245 unsigned long sibs; /* Offset of siblings from trie beginning. */
1246 unsigned long kids; /* Offset of children from trie beginning. */
1247 } node_t;
1250 * The trie used for remapping codes.
1252 static node_t *nodes;
1253 static unsigned long nodes_used = 0;
1255 int
1256 otf2bdf_remap(unsigned short *code)
1258 unsigned long i, n, t;
1259 unsigned short c, codes[2];
1262 * If no mapping table was loaded, then simply return the code.
1264 if (nodes_used == 0)
1265 return 1;
1267 c = *code;
1268 codes[0] = (c >> 8) & 0xff;
1269 codes[1] = c & 0xff;
1271 for (i = n = 0; i < 2; i++) {
1272 t = nodes[n].kids;
1273 if (t == 0)
1274 return 0;
1275 for (; nodes[t].sibs && nodes[t].key != codes[i]; t = nodes[t].sibs);
1276 if (nodes[t].key != codes[i])
1277 return 0;
1278 n = t;
1281 *code = nodes[n].val;
1282 return 1;