remove set but unused variable
[maemo-rb.git] / tools / convttf.c
blob24cf14ab9c5b59b3bacf7d03a33cd82015a29293
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 FT_Long max_char = 65535;
93 int pixel_size = 15;
94 FT_Long start_char = 0;
95 FT_Long limit_char;
96 FT_Long firstchar = 0;
97 FT_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 digits_equally_wide = 1; /* Try to make digits equally wide */
108 int trimming = 0;
109 int trim_dp = 0; /* trim descent percent */
110 int trim_da = 0; /* trim descnet actual */
111 int trim_ap = 0; /* trim ascent precent */
112 int trim_aa = 0; /* trim ascent actual */
114 struct font_header_struct {
115 char header[4]; /* magic number and version bytes */
116 unsigned short maxwidth; /* max width in pixels */
117 unsigned short height; /* height in pixels */
118 unsigned short ascent; /* ascent (baseline) height */
119 unsigned short depth; /* depth 0=1-bit, 1=4-bit */
120 unsigned long firstchar; /* first character in font */
121 unsigned long defaultchar; /* default character in font */
122 unsigned long size; /* # characters in font */
123 unsigned long nbits; /* # bytes imagebits data in file */ /* = bits_size */
125 FT_Long noffset; /* # longs offset data in file */
126 FT_Long nwidth; /* # bytes width data in file */
129 struct font_struct {
130 struct font_header_struct header;
131 unsigned char *chars_data;
132 unsigned short *offset;
133 FT_Long *offset_long;
134 unsigned char *width;
137 struct ttc_table{
138 FT_Long ttc_count;
139 char **ttf_name;
142 /* exit the program with given message */
143 static void
144 panic( const char* message)
146 fprintf( stderr, "%s\n", message );
147 exit( 1 );
150 static void
151 arg_panic( const char* message, const char* arg )
153 fprintf( stderr, "%s: %s\n", message, arg );
154 exit( 1 );
157 static int writebyte(FILE *fp, unsigned char c)
159 return putc(c, fp) != EOF;
162 static int writeshort(FILE *fp, unsigned short s)
164 putc(s, fp);
165 return putc(s>>8, fp) != EOF;
168 static int writeint(FILE *fp, unsigned int l)
170 putc(l, fp);
171 putc(l>>8, fp);
172 putc(l>>16, fp);
173 return putc(l>>24, fp) != EOF;
176 static int writestr(FILE *fp, char *str, int count)
178 return (int)fwrite(str, 1, count, fp) == count;
181 /* print usage information */
182 void usage(void)
184 char help[] = {
185 "Usage: convttf [options] [input-files]\n"
186 " convttf [options] [-o output-file] [single-input-file]\n\n"
187 " Default output-file : <font-size>-<basename>.fnt.\n"
188 " When '-ta' or '-tc' is specified in command line,\n "
189 " default output-file is: \n"
190 " <font-size>-<internal postscript-name of input-file>.fnt.\n"
191 "Options:\n"
192 " -s N Start output at character encodings >= N\n"
193 " -l N Limit output to character encodings <= N\n"
194 " -p N Font size N in pixel (default N=15)\n"
195 " -c N Character separation in pixel.Insert space between lines.\n"
196 " -x Trim glyphs horizontally of nearly empty space\n"
197 " (to improve spacing on V's W's, etc.)\n"
198 " -X Set the horizontal and vertical resolution (default: 60)\n"
199 " -TA N Trim vertical ascent (N percent)\n"
200 " -TD N Trim vertical descent (N percent)\n"
201 " -Ta N Trim vertical ascent (N pixels)\n"
202 " -Td N Trim vertical descent (N pixels)\n"
203 " -r N Row separation in pixel.Insert space between characters\n"
204 " -d Debug: print converted glyph images\n"
205 " -tt Display the True Type Collection tables available in the font\n"
206 " -t N Index of true type collection. It must be start from 0.(default N=0).\n"
207 " -ta Convert all fonts in ttc (ignores outfile option)\n"
208 " -w Don't try to make digits (0-9) equally wide\n"
210 fprintf(stderr, "%s", help);
211 exit( 1 );
214 /* remove directory prefix and file suffix from full path*/
215 char *basename(char *path)
217 char *p, *b;
218 static char base[256];
220 /* remove prepended path and extension*/
221 b = path;
222 for (p=path; *p; ++p) {
223 if (*p == '/')
224 b = p + 1;
226 strcpy(base, b);
227 for (p=base; *p; ++p) {
228 if (*p == '.') {
229 *p = 0;
230 break;
233 return base;
237 void setcharmap(FT_Face face)
239 FT_Long i;
242 * Get the requested cmap.
244 for (i = 0; i < face->num_charmaps; i++) {
245 if (face->charmaps[i]->platform_id == pid &&
246 face->charmaps[i]->encoding_id == eid)
247 break;
250 if (i == face->num_charmaps && pid == 3 && eid == 1) {
252 * Make a special case when this fails with pid == 3 and eid == 1.
253 * Change to eid == 0 and try again. This captures the two possible
254 * cases for MS fonts. Some other method should be used to cycle
255 * through all the alternatives later.
257 for (i = 0; i < face->num_charmaps; i++) {
258 if (face->charmaps[i]->platform_id == pid &&
259 face->charmaps[i]->encoding_id == 0)
260 break;
262 if (i < face->num_charmaps) {
263 pid = 3;
264 eid = 1;
265 FT_Set_Charmap(face, face->charmaps[i]);
266 } else {
268 * No CMAP was found.
270 nocmap = 1;
271 pid = eid = -1;
273 } else {
274 FT_Set_Charmap(face, face->charmaps[i]);
275 nocmap = 0;
281 * quote in otf2bdf.
282 * A generic routine to get a name from the OT name table. This routine
283 * always looks for English language names and checks three possibilities:
284 * 1. English names with the MS Unicode encoding ID.
285 * 2. English names with the MS unknown encoding ID.
286 * 3. English names with the Apple Unicode encoding ID.
288 * The particular name ID mut be provided (e.g. nameID = 0 for copyright
289 * string, nameID = 6 for Postscript name, nameID = 1 for typeface name.
291 * If the `dash_to_space' flag is non-zero, all dashes (-) in the name will be
292 * replaced with the character passed.
294 * Returns the number of bytes added.
296 static int
297 otf_get_english_string(FT_Face face, int nameID, int dash_to_space,
298 char *name, int name_size)
301 int j, encid;
302 FT_UInt i, nrec;
303 FT_SfntName sfntName;
304 unsigned char *s;
305 unsigned short slen;
307 nrec = FT_Get_Sfnt_Name_Count(face);
309 for (encid = 1, j = 0; j < 2; j++, encid--) {
311 * Locate one of the MS English font names.
313 for (i = 0; i < nrec; i++) {
314 FT_Get_Sfnt_Name(face, i, &sfntName);
315 if (sfntName.platform_id == 3 &&
316 sfntName.encoding_id == encid &&
317 sfntName.name_id == nameID &&
318 (sfntName.language_id == 0x0409 ||
319 sfntName.language_id == 0x0809 ||
320 sfntName.language_id == 0x0c09 ||
321 sfntName.language_id == 0x1009 ||
322 sfntName.language_id == 0x1409 ||
323 sfntName.language_id == 0x1809)) {
324 s = sfntName.string;
325 slen = sfntName.string_len;
326 break;
330 if (i < nrec) {
331 if (slen >> 1 >= name_size) {
332 fprintf(stderr, "warning: %s string longer than buffer."
333 "Truncating to %d bytes.\n", string_names[nameID], name_size);
334 slen = name_size << 1;
338 * Found one of the MS English font names. The name is by
339 * definition encoded in Unicode, so copy every second byte into
340 * the `name' parameter, assuming there is enough space.
342 for (i = 1; i < slen; i += 2) {
343 if (dash_to_space)
344 *name++ = (s[i] != '-') ? s[i] : ' ';
345 else if (s[i] == '\r' || s[i] == '\n') {
346 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
347 i += 2;
348 *name++ = ' ';
349 *name++ = ' ';
350 } else
351 *name++ = s[i];
353 *name = 0;
354 return (slen >> 1);
359 * No MS English name found, attempt to find an Apple Unicode English
360 * name.
362 for (i = 0; i < nrec; i++) {
363 FT_Get_Sfnt_Name(face, i, &sfntName);
364 if (sfntName.platform_id == 0 && sfntName.language_id == 0 &&
365 sfntName.name_id == nameID) {
366 s = sfntName.string;
367 slen = sfntName.string_len;
368 break;
372 if (i < nrec) {
373 if (slen >> 1 >= name_size) {
374 fprintf(stderr, "warning: %s string longer than buffer."
375 "Truncating to %d bytes.\n", string_names[nameID], name_size);
376 slen = name_size << 1;
380 * Found the Apple Unicode English name. The name is by definition
381 * encoded in Unicode, so copy every second byte into the `name'
382 * parameter, assuming there is enough space.
384 for (i = 1; i < slen; i += 2) {
385 if (dash_to_space)
386 *name++ = (s[i] != '-') ? s[i] : ' ';
387 else if (s[i] == '\r' || s[i] == '\n') {
388 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
389 i += 2;
390 *name++ = ' ';
391 *name++ = ' ';
392 } else
393 *name++ = s[i];
395 *name = 0;
396 return (slen >> 1);
399 return 0;
403 int get_ttc_table(char *path, struct ttc_table *ttcname )
407 FT_Error error;
408 FT_Library library;
409 FT_Face face;
410 FT_Long i;
411 char xlfd[BUFSIZ];
413 /* init number of ttf in ttc */
414 ttcname->ttc_count = 0;
416 /* Initialize engine */
417 if ( ( error = FT_Init_FreeType( &library ) ) != 0 )
419 panic( "Error while initializing engine" );
420 return error;
424 /* Load face */
425 error = FT_New_Face( library, path, (FT_Long) 0, &face );
426 if ( error )
428 arg_panic( "Could not find/open font", path );
429 return error;
432 ttcname->ttc_count = face->num_faces;
433 ttcname->ttf_name = malloc( sizeof(char*) * ttcname->ttc_count);
435 for(i = 0; i < ttcname->ttc_count; i++)
437 error = FT_New_Face( library, path, i, &face );
438 if ( error == FT_Err_Cannot_Open_Stream )
439 arg_panic( "Could not find/open font", path );
440 otf_get_english_string(face, BDFOTF_POSTSCRIPT_STRING, 0, xlfd,
441 sizeof(xlfd));
442 ttcname->ttf_name[i] = malloc(sizeof(char) * (strlen(xlfd) + 1 ));
443 strcpy(ttcname->ttf_name[i], xlfd);
445 return 0;
448 void print_ttc_table(char* path)
450 struct ttc_table ttcname;
451 FT_Long i;
453 get_ttc_table(path, &ttcname);
454 printf("ttc header count = %ld \n\n", ttcname.ttc_count);
455 printf("Encoding tables available in the true type collection\n\n");
456 printf("INDEX\tPOSTSCRIPT NAME\n");
457 printf("-----------------------------------------------------\n");
458 for(i = 0; i < ttcname.ttc_count; i++)
460 printf("%ld\t%s\n", i, ttcname.ttf_name[i]);
462 for(i = 0; i < ttcname.ttc_count; i++)
464 free(ttcname.ttf_name[i]);
466 printf("\n\n");
467 free(ttcname.ttf_name);
469 return;
472 FT_Long getcharindex(FT_Face face, FT_Long code)
474 FT_Long idx;
475 if (nocmap) {
476 if (code >= face->num_glyphs)
477 idx = 0;
478 else
479 idx = code;
480 } else
481 idx = FT_Get_Char_Index( face, code);
483 if ( idx <= 0 || idx > face->num_glyphs)
484 return 0;
485 else
486 return idx;
489 void print_raw_glyph( FT_Face face)
491 int pixel,row,col,width;
492 width = face->glyph->metrics.width >> 6;
494 printf("\n---Raw-Glyph---\n");
495 for(row=0; row < face->glyph->metrics.height >> 6; row++)
497 printf("_");
498 for(col=0; col < width; col++)
500 pixel = *(face->glyph->bitmap.buffer+width*row+col)/26;
501 if ( pixel ) printf("%d",pixel); else printf(" ");
503 printf("_\n");
505 printf("----End-----\n");
508 int glyph_width( FT_Face face, FT_Long code, FT_Long digit_width )
510 int width;
512 if (code >= '0' && code <= '9' && digit_width)
514 width = digit_width;
516 else
518 int pitch, h_adv;
519 unsigned spacing = (unsigned)(between_chr * (1<<6));/* convert to fixed point */
521 pitch = ABS(face->glyph->bitmap.pitch);
522 h_adv = face->glyph->metrics.horiAdvance >> 6;
523 width = (face->glyph->metrics.width + spacing) >> 6;
525 if(pitch == 0) pitch = h_adv;
526 if(width < pitch) width = pitch;
529 return width;
532 FT_Long check_digit_width( FT_Face face )
534 FT_Long code;
535 FT_Long last_advance = -1;
537 for (code='0'; code <= '9'; ++code)
539 FT_Glyph_Metrics* metrics;
541 FT_Load_Char(face, code, FT_LOAD_RENDER | FT_LOAD_NO_BITMAP);
542 metrics = &face->glyph->metrics;
544 if ((last_advance != -1 && last_advance != metrics->horiAdvance) ||
545 metrics->horiBearingX < 0)
547 last_advance = 0;
548 break;
551 last_advance = metrics->horiAdvance;
554 return last_advance >> 6;
557 void trim_glyph( FT_GlyphSlot glyph, int *empty_first_col,
558 int *empty_last_col, int *width )
560 int row;
561 int stride = glyph->bitmap.pitch;
562 int end = stride-1;
563 int trim_left = 2, trim_right = 2;
565 const unsigned char limit = 64u;
566 const unsigned char *image = glyph->bitmap.buffer;
568 if (*width < 2)
569 return; /* nothing to do? */
571 for(row=0; row< glyph->metrics.height >> 6; row++)
573 const unsigned char *column = image+row*stride;
574 if (*column++ < limit && trim_left)
576 if (*column >= limit/2)
577 trim_left = 1;
579 else
580 trim_left = 0;
582 column = image+row*stride+end;
583 if (*column-- < limit && trim_right)
585 if (*column >= limit/2)
586 trim_right = 1;
588 else
589 trim_right = 0;
593 (*width) -= trim_left + trim_right;
594 if (*width < 0) *width = 0;
596 *empty_first_col = trim_left;
597 *empty_last_col = trim_right;
600 void convttf(char* path, char* destfile, FT_Long face_index)
602 FT_Error error;
603 FT_Library library;
604 FT_Face face;
605 int w,h;
606 int row,col;
607 int empty_first_col, empty_last_col;
608 FT_Long charindex;
609 FT_Long index = 0;
610 FT_Long code;
611 FT_Long digit_width = 0;
613 int depth = 2;
614 unsigned char bit_shift = 1 << depth;
615 unsigned char pixel_per_byte = CHAR_BIT / bit_shift;
617 /* Initialize engine */
618 if ( ( error = FT_Init_FreeType( &library ) ) != 0 )
619 panic( "Error while initializing engine" );
621 /* Load face */
622 error = FT_New_Face( library, path, (FT_Long) face_index, &face );
623 if ( error == FT_Err_Cannot_Open_Stream )
624 arg_panic( "Could not find/open font\n", path );
625 else if ( error )
626 arg_panic( "Error while opening font\n", path );
629 setcharmap( face );
630 /* Set font header data */
631 struct font_struct export_font;
632 export_font.header.header[0] = 'R';
633 export_font.header.header[1] = 'B';
634 export_font.header.header[2] = '1';
635 export_font.header.header[3] = '2';
636 //export_font.header.height = 0;
637 //export_font.header.ascent = 0;
639 float extra_space = (float)(between_row-trim_aa-trim_da);
640 FT_Set_Char_Size( face, 0, pixel_size << 6, hv_resolution, hv_resolution );
641 export_font.header.ascent =
642 ((face->size->metrics.ascender*(100-trim_ap)/100) >> 6) - trim_aa;
644 export_font.header.height =
645 (((face->size->metrics.ascender*(100-trim_ap)/100) -
646 (face->size->metrics.descender*(100-trim_dp)/100)) >> 6) + extra_space;
648 printf("\n");
649 printf("Please wait, converting %s:\n", path);
651 /* "face->num_glyphs" is NG.; */
652 if ( limit_char == 0 ) limit_char = max_char;
653 if ( limit_char > max_char ) limit_char = max_char;
655 FT_Long char_count = 0;
659 export_font.header.maxwidth = 1;
660 export_font.header.depth = 1;
661 firstchar = limit_char;
662 lastchar = start_char;
664 if (digits_equally_wide)
665 digit_width = check_digit_width(face);
667 /* calculate memory usage */
668 for(code = start_char; code <= limit_char ; code++ )
670 charindex = getcharindex( face, code);
671 if ( !(charindex) ) continue;
672 error = FT_Load_Glyph( face, charindex,
673 (FT_LOAD_RENDER | FT_LOAD_NO_BITMAP) );
674 if ( error ) continue;
676 w = glyph_width( face, code, digit_width );
677 if (w == 0) continue;
678 empty_first_col = empty_last_col = 0;
679 if(trimming)
680 trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w);
682 if (export_font.header.maxwidth < w)
683 export_font.header.maxwidth = w;
686 char_count++;
687 index += (w*export_font.header.height + pixel_per_byte - 1)/pixel_per_byte;
689 if (code >= lastchar)
690 lastchar = code;
692 if (code <= firstchar)
693 firstchar = code;
695 export_font.header.defaultchar = firstchar;
696 export_font.header.firstchar = firstchar;
697 export_font.header.size = lastchar - firstchar + 1;
698 export_font.header.nbits = index;
699 export_font.header.noffset = export_font.header.size;
700 export_font.header.nwidth = export_font.header.size;
702 /* check if we need to use long offsets */
703 char use_long_offset = (export_font.header.nbits >= 0xFFDB );
705 /* allocate memory */
706 export_font.offset = NULL;
707 export_font.offset_long = NULL;
708 if (use_long_offset)
709 export_font.offset_long =
710 malloc( sizeof(FT_Long)* export_font.header.noffset );
711 else
712 export_font.offset =
713 malloc( sizeof(unsigned short)* export_font.header.noffset );
715 export_font.width =
716 malloc( sizeof(unsigned char) * export_font.header.nwidth );
717 export_font.chars_data =
718 malloc( sizeof(unsigned char) * export_font.header.nbits );
720 /* for now we use the full height for each character */
721 h = export_font.header.height;
723 index = 0;
724 int done = 0;
725 char char_name[1024];
726 int converted_char_count = 0;
727 int failed_char_count = 0;
729 for( code = firstchar; code <= lastchar; code++ )
731 /* Get gylph index from the char and render it */
732 charindex = getcharindex( face, code);
733 if ( !charindex )
735 if ( use_long_offset )
736 export_font.offset_long[code - firstchar] = export_font.offset_long[0];
737 else
738 export_font.offset[code - firstchar] = export_font.offset[0];
739 export_font.width[code - firstchar] = export_font.width[0];
740 continue;
743 error = FT_Load_Glyph( face, charindex ,
744 (FT_LOAD_RENDER | FT_LOAD_NO_BITMAP) );
745 if ( error ) {
746 continue;
748 if FT_HAS_GLYPH_NAMES( face )
749 FT_Get_Glyph_Name( face, charindex, char_name, 16);
750 else
751 char_name[0] = '\0';
753 FT_GlyphSlot slot = face->glyph;
754 FT_Bitmap* source = &slot->bitmap;
755 //print_raw_glyph( face );
756 w = glyph_width( face, code, digit_width );
757 if (w == 0) continue;
758 empty_first_col = empty_last_col = 0;
760 if(trimming)
761 trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w );
763 if ( use_long_offset )
764 export_font.offset_long[code - firstchar] = index;
765 else
766 export_font.offset[code - firstchar] = index;
768 export_font.width[code - firstchar] = w;
770 /* copy the glyph bitmap to a full sized glyph bitmap */
771 unsigned char* src = source->buffer;
772 unsigned char* tmpbuf = malloc(sizeof(unsigned char) * w * h);
773 memset(tmpbuf, 0xff, w*h);
774 int start_y = export_font.header.ascent - slot->bitmap_top;
776 int glyph_height = source->rows;
777 int stride = source->pitch;
778 unsigned char* buf = tmpbuf;
779 unsigned char* endbuf = tmpbuf + w*h;
781 int error = 0;
782 /* insert empty pixels on the left */
783 int col_off = w - stride;
784 if (col_off > 1) col_off /= 2;
785 if (col_off < 0) col_off = 0;
787 for(row=0; row < glyph_height; row++)
789 if(row+start_y < 0 || row+start_y >= h)
790 continue;
791 for(col = empty_first_col; col < stride; col++)
793 unsigned char *tsrc, *dst;
794 dst = buf + (w*(start_y+row)) + col + col_off;
795 tsrc = src + stride*row + col;
796 if (dst < endbuf && dst >= tmpbuf)
797 *dst = 0xff - *tsrc;
798 else {
799 error = 1;
800 printf("Error! row: %3d col: %3d\n", row, col);
804 if(error) print_raw_glyph(face);
806 buf = tmpbuf;
807 int numbits;
808 unsigned int field;
809 field = 0;
810 numbits = pixel_per_byte;
812 for(row=0; row < h; row++)
814 for(col=0; col < w; col++)
816 unsigned int src = *buf++;
817 unsigned int cur_col = (src + 8) / 17;
818 field |= (cur_col << (bit_shift*(pixel_per_byte-numbits)));
820 if (--numbits == 0)
822 export_font.chars_data[index++] = (unsigned char)field;
823 numbits = pixel_per_byte;
824 field = 0;
829 /* Pad last byte */
830 if (numbits != pixel_per_byte)
832 export_font.chars_data[index++] = (unsigned char)field;
835 if( dump_glyphs )
837 /* debug: dump char */
838 printf("\n---Converted Glyph Dump---\n");
839 unsigned char bit_max = (1 << bit_shift) - 1;
840 if ( code > 32 && code < 255 ) {
841 row = h;
842 if(use_long_offset)
843 buf = &(export_font.chars_data[export_font.offset_long[
844 code - firstchar]]);
845 else
846 buf = &(export_font.chars_data[export_font.offset[
847 code - firstchar]]);
848 unsigned char current_data;
849 unsigned char font_bits;
850 numbits = pixel_per_byte;
851 current_data = *buf;
854 col = w;
855 printf("-");
858 font_bits = current_data & bit_max;
859 if (font_bits==bit_max)
860 printf(" ");
861 else
863 if(font_bits > bit_max/2)
864 printf(".");
865 else
866 printf("@");
868 if (--numbits == 0)
870 current_data = *(++buf);
871 numbits = pixel_per_byte;
873 else
875 current_data >>= bit_shift;
877 } while (--col);
878 printf("-\n");
879 } while (--row);
881 buf = NULL;
882 printf("---End Glyph Dump---\n");
885 free(tmpbuf);
886 converted_char_count++;
887 done = (100*(converted_char_count))/char_count;
888 printf("Converted %s %d (%d%%)\e[K\r",
889 char_name,converted_char_count,done); fflush(stdout);
892 FILE *file = fopen(destfile, "w");
893 printf("Writing %s\n", destfile);
895 /* font info */
896 writestr(file, VERSION, 4);
897 writeshort(file, export_font.header.maxwidth);
898 writeshort(file, export_font.header.height);
899 writeshort(file, export_font.header.ascent);
900 writeshort(file, export_font.header.depth);
901 writeint(file, export_font.header.firstchar);
902 writeint(file, export_font.header.defaultchar);
903 writeint(file, export_font.header.size);
904 writeint(file, export_font.header.nbits);
905 writeint(file, export_font.header.noffset);
906 writeint(file, export_font.header.nwidth);
908 fwrite( (char*)export_font.chars_data, 1,
909 export_font.header.nbits, file);
910 free(export_font.chars_data);
912 int skip,i;
913 char pad[] = {0,0,0,0};
914 if ( use_long_offset )
916 skip = ((export_font.header.nbits + 3) & ~3) -
917 export_font.header.nbits;
918 fwrite(pad, 1, skip, file); /* pad */
919 for(i = 0; i < export_font.header.noffset; i++)
920 writeint(file, export_font.offset_long[i]);
922 else
924 skip = ((export_font.header.nbits + 1) & ~1) -
925 export_font.header.nbits;
926 fwrite(pad, 1, skip, file); /* pad */
927 for(i = 0; i < export_font.header.noffset; i++)
928 writeshort(file, export_font.offset[i]);
931 for(i = 0; i < export_font.header.nwidth; i++)
932 writebyte(file, export_font.width[i]);
933 free(export_font.width);
935 if ( use_long_offset )
936 free(export_font.offset_long);
937 else
938 free(export_font.offset);
940 fclose(file);
941 FT_Done_Face( face );
942 FT_Done_FreeType( library );
943 printf("done (converted %d glyphs, %d errors).\e[K\n\n",
944 converted_char_count, failed_char_count);
948 void convttc(char* path)
950 struct ttc_table ttcname;
951 FT_Long i;
953 get_ttc_table(path, &ttcname);
955 if (ttcname.ttc_count == 0)
957 printf("This file is a not true type font.\n");
958 return;
961 /* default */
962 if (!flg_all_ttc && ttc_index == -1)
964 if (!oflag)
965 { /* generate filename */
966 snprintf(outfile, sizeof(outfile),
967 "%d-%s.fnt", pixel_size, basename(path));
969 convttf(path, outfile, (FT_Long) 0);
972 /* set face_index of ttc */
973 else if (!flg_all_ttc)
975 print_ttc_table(path);
976 if ( !oflag )
978 if (ttc_index >= 0 &&
979 ttc_index < ttcname.ttc_count)
981 if (strcmp(ttcname.ttf_name[ttc_index], "") != 0)
983 snprintf(outfile, sizeof(outfile), "%d-%s.fnt",
984 pixel_size, ttcname.ttf_name[ttc_index]);
986 else
988 snprintf(outfile, sizeof(outfile), "%d-%s-%ld.fnt",
989 pixel_size, basename(path), ttc_index);
992 else
994 printf("illegal face index of ttc.\n");
997 convttf(path, outfile, ttc_index);
999 else { /* convert all fonts */
1000 print_ttc_table(path);
1001 for(i = 0; i < ttcname.ttc_count; i++)
1003 snprintf(outfile, sizeof(outfile), "%d-%s.fnt",
1004 pixel_size, ttcname.ttf_name[i]);
1005 convttf(path, outfile, i);
1009 for(i = 0; i < ttcname.ttc_count; i++)
1011 free(ttcname.ttf_name[i]);
1013 free(ttcname.ttf_name);
1018 /* parse command line options*/
1019 void getopts(int *pac, char ***pav)
1021 char *p;
1022 char **av;
1023 int ac;
1024 ac = *pac;
1025 av = *pav;
1027 limit_char = max_char;
1028 start_char = 0;
1030 while (ac > 0 && av[0][0] == '-') {
1031 p = &av[0][1];
1032 while( *p)
1033 switch(*p++) {
1034 case 'h':case 'H':
1035 usage();
1036 break;
1037 case ' ': /* multiple -args on av[]*/
1038 while( *p && *p == ' ')
1039 p++;
1040 if( *p++ != '-') /* next option must have dash*/
1041 p = "";
1042 break; /* proceed to next option*/
1043 case 'o': /* set output file*/
1044 oflag = 1;
1045 if (*p) {
1046 strcpy(outfile, p);
1047 while (*p && *p != ' ')
1048 p++;
1050 else {
1051 av++; ac--;
1052 if (ac > 0)
1053 strcpy(outfile, av[0]);
1055 break;
1056 case 'l': /* set encoding limit*/
1057 if (*p) {
1058 limit_char = atoi(p);
1059 while (*p && *p != ' ')
1060 p++;
1062 else {
1063 av++; ac--;
1064 if (ac > 0)
1065 limit_char = atoi(av[0]);
1067 break;
1068 case 's': /* set encoding start*/
1069 if (*p) {
1070 start_char = atol(p);
1071 while (*p && *p != ' ')
1072 p++;
1074 else {
1075 av++; ac--;
1076 if (ac > 0)
1077 start_char = atol(av[0]);
1079 break;
1080 case 'p': /* set pixel size*/
1081 if (*p) {
1082 pixel_size = atoi(p);
1083 while (*p && *p != ' ')
1084 p++;
1086 else {
1087 av++; ac--;
1088 if (ac > 0)
1089 pixel_size = atoi(av[0]);
1091 break;
1092 case 'c': /* set spaece between characters */
1094 if (*p) {
1095 between_chr = atof(p);
1096 while (*p && *p != ' ')
1097 p++;
1099 else {
1100 av++; ac--;
1101 if (ac > 0)
1102 between_chr = atof(av[0]);
1104 break;
1106 case 'd':
1107 dump_glyphs = 1;
1108 while (*p && *p != ' ')
1109 p++;
1110 break;
1111 case 'x':
1112 trimming = 1;
1113 while (*p && *p != ' ')
1114 p++;
1115 break;
1116 case 'X':
1117 if (*p) {
1118 hv_resolution = atoi(p);
1119 while (*p && *p != ' ')
1120 p++;
1122 else {
1123 av++; ac--;
1124 if (ac > 0)
1125 hv_resolution = atoi(av[0]);
1127 break;
1128 case 'r':
1129 if (*p) {
1130 between_row = atof(p);
1131 while (*p && *p != ' ')
1132 p++;
1134 else {
1135 av++; ac--;
1136 if (ac > 0)
1137 between_row = atof(av[0]);
1139 break;
1140 case 'T':
1141 if(*p == 'A') {
1142 if(*(++p)) {
1143 trim_ap = atoi(p);
1144 while (*p && *p != ' ')
1145 p++;
1147 else {
1148 av++; ac--;
1149 if (ac > 0)
1150 trim_ap = atoi(av[0]);
1152 break;
1154 if(*p == 'D') {
1155 if(*(++p)) {
1156 trim_dp = atoi(p);
1157 while (*p && *p != ' ')
1158 p++;
1160 else {
1161 av++; ac--;
1162 if (ac > 0)
1163 trim_dp = atoi(av[0]);
1165 break;
1167 if(*p == 'a') {
1168 if(*(++p)) {
1169 trim_aa = atoi(p);
1170 while (*p && *p != ' ')
1171 p++;
1173 else {
1174 av++; ac--;
1175 if (ac > 0)
1176 trim_aa = atoi(av[0]);
1178 break;
1180 if(*p == 'd') {
1181 if(*(++p)) {
1182 trim_da = atoi(p);
1185 else {
1186 av++; ac--;
1187 if (ac > 0)
1188 trim_da = atoi(av[0]);
1190 break;
1192 fprintf(stderr, "Unknown option ignored: %s\n", p-1);
1193 while (*p && *p != ' ')
1194 p++;
1195 break;
1196 case 't': /* display ttc table */
1197 if (*p == 't') {
1198 pct = 1;
1199 while (*p && *p != ' ')
1200 p++;
1203 else if (*p == 'a') {
1204 flg_all_ttc = 1;
1205 while (*p && *p != ' ')
1206 p++;
1209 else if (*p) {
1210 ttc_index = atoi(p);
1211 while (*p && *p != ' ')
1212 p++;
1214 else {
1215 av++; ac--;
1216 if (ac > 0)
1217 ttc_index = atoi(av[0]);
1219 break;
1220 case 'w': /* Don't try to make digits equally wide */
1221 digits_equally_wide = 0;
1222 while (*p && *p != ' ')
1223 p++;
1224 break;
1226 default:
1227 fprintf(stderr, "Unknown option ignored: %s\n", p-1);
1228 while (*p && *p != ' ')
1229 p++;
1231 ++av; --ac;
1233 *pac = ac;
1234 *pav = av;
1238 int main(int ac, char **av)
1240 int ret = 0;
1242 ++av; --ac; /* skip av[0]*/
1244 getopts(&ac, &av); /* read command line options*/
1246 if (ac < 1)
1248 usage();
1250 if (oflag)
1252 if (ac > 1)
1254 usage();
1258 if (limit_char < start_char)
1260 usage();
1261 exit(0);
1264 while (pct && ac > 0)
1266 print_ttc_table(av[0]);
1267 ++av; --ac;
1268 exit(0);
1271 while (ac > 0)
1273 convttc(av[0]);
1274 ++av; --ac;
1277 exit(ret);
1283 * Trie node structure.
1285 typedef struct {
1286 unsigned short key; /* Key value. */
1287 unsigned short val; /* Data for the key. */
1288 unsigned long sibs; /* Offset of siblings from trie beginning. */
1289 unsigned long kids; /* Offset of children from trie beginning. */
1290 } node_t;
1293 * The trie used for remapping codes.
1295 static node_t *nodes;
1296 static unsigned long nodes_used = 0;
1298 int
1299 otf2bdf_remap(unsigned short *code)
1301 unsigned long i, n, t;
1302 unsigned short c, codes[2];
1305 * If no mapping table was loaded, then simply return the code.
1307 if (nodes_used == 0)
1308 return 1;
1310 c = *code;
1311 codes[0] = (c >> 8) & 0xff;
1312 codes[1] = c & 0xff;
1314 for (i = n = 0; i < 2; i++) {
1315 t = nodes[n].kids;
1316 if (t == 0)
1317 return 0;
1318 for (; nodes[t].sibs && nodes[t].key != codes[i]; t = nodes[t].sibs);
1319 if (nodes[t].key != codes[i])
1320 return 0;
1321 n = t;
1324 *code = nodes[n].val;
1325 return 1;