Prepare new maemo release
[maemo-rb.git] / tools / convttf.c
blob66f0ad2176d2682967fe9f457b9187e64fcfe98d
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 <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
37 #include <string.h>
39 * Set the default values used to generate a BDF font.
41 #ifndef DEFAULT_PLATFORM_ID
42 #define DEFAULT_PLATFORM_ID 3
43 #endif
45 #ifndef DEFAULT_ENCODING_ID
46 #define DEFAULT_ENCODING_ID 1
47 #endif
49 #define ABS(x) (((x) < 0) ? -(x) : (x))
51 #define VERSION "RB12"
53 * nameID macros for getting strings from the OT font.
55 enum {
56 BDFOTF_COPYRIGHT_STRING = 0,
57 BDFOTF_FAMILY_STRING,
58 BDFOTF_SUBFAMILY_STRING,
59 BDFOTF_UNIQUEID_STRING,
60 BDFOTF_FULLNAME_STRING,
61 BDFOTF_VENDOR_STRING,
62 BDFOTF_POSTSCRIPT_STRING,
63 BDFOTF_TRADEMARK_STRING,
66 * String names for the string indexes. Used for error messages.
68 static char *string_names[] = {
69 "\"Copyright\"",
70 "\"Family\"",
71 "\"SubFamily\"",
72 "\"Unique ID\"",
73 "\"Full Name\"",
74 "\"Vendor\"",
75 "\"Postscript Name\"",
76 "\"Trademark\""
81 * The default platform and encoding ID's.
83 static int pid = DEFAULT_PLATFORM_ID;
84 static int eid = DEFAULT_ENCODING_ID;
88 * A flag indicating if a CMap was found or not.
90 static FT_UShort nocmap;
92 int pct = 0; /* display ttc table if it is not zero. */
93 FT_Long max_char = 65535;
94 int pixel_size = 15;
95 FT_Long start_char = 0;
96 FT_Long limit_char;
97 FT_Long firstchar = 0;
98 FT_Long lastchar;
99 FT_Long ttc_index = -1;
100 int flg_all_ttc = 0;
101 short antialias = 1; /* smooth fonts with gray levels */
102 int oflag = 0;
103 char outfile[1024];
104 float between_chr = 0.0f;
105 float between_row = 0.0f;
106 int hv_resolution = 60;
107 int dump_glyphs = 0;
108 int digits_equally_wide = 1; /* Try to make digits equally wide */
109 int trimming = 0;
110 int trim_dp = 0; /* trim descent percent */
111 int trim_da = 0; /* trim descnet actual */
112 int trim_ap = 0; /* trim ascent precent */
113 int trim_aa = 0; /* trim ascent actual */
115 struct font_header_struct {
116 char header[4]; /* magic number and version bytes */
117 unsigned short maxwidth; /* max width in pixels */
118 unsigned short height; /* height in pixels */
119 unsigned short ascent; /* ascent (baseline) height */
120 unsigned short depth; /* depth 0=1-bit, 1=4-bit */
121 unsigned long firstchar; /* first character in font */
122 unsigned long defaultchar; /* default character in font */
123 unsigned long size; /* # characters in font */
124 unsigned long nbits; /* # bytes imagebits data in file */ /* = bits_size */
126 FT_Long noffset; /* # longs offset data in file */
127 FT_Long nwidth; /* # bytes width data in file */
130 struct font_struct {
131 struct font_header_struct header;
132 unsigned char *chars_data;
133 unsigned short *offset;
134 FT_Long *offset_long;
135 unsigned char *width;
138 struct ttc_table{
139 FT_Long ttc_count;
140 char **ttf_name;
143 /* exit the program with given message */
144 static void
145 panic( const char* message)
147 fprintf( stderr, "%s\n", message );
148 exit( 1 );
151 static void
152 arg_panic( const char* message, const char* arg )
154 fprintf( stderr, "%s: %s\n", message, arg );
155 exit( 1 );
158 static int writebyte(FILE *fp, unsigned char c)
160 return putc(c, fp) != EOF;
163 static int writeshort(FILE *fp, unsigned short s)
165 putc(s, fp);
166 return putc(s>>8, fp) != EOF;
169 static int writeint(FILE *fp, unsigned int l)
171 putc(l, fp);
172 putc(l>>8, fp);
173 putc(l>>16, fp);
174 return putc(l>>24, fp) != EOF;
177 static int writestr(FILE *fp, char *str, int count)
179 return (int)fwrite(str, 1, count, fp) == count;
182 /* print usage information */
183 void usage(void)
185 char help[] = {
186 "Usage: convttf [options] [input-files]\n"
187 " convttf [options] [-o output-file] [single-input-file]\n\n"
188 " Default output-file : <font-size>-<basename>.fnt.\n"
189 " When '-ta' or '-tc' is specified in command line,\n "
190 " default output-file is: \n"
191 " <font-size>-<internal postscript-name of input-file>.fnt.\n"
192 "Options:\n"
193 " -s N Start output at character encodings >= N\n"
194 " -l N Limit output to character encodings <= N\n"
195 " -p N Font size N in pixel (default N=15)\n"
196 " -c N Character separation in pixel.Insert space between lines.\n"
197 " -x Trim glyphs horizontally of nearly empty space\n"
198 " (to improve spacing on V's W's, etc.)\n"
199 " -X Set the horizontal and vertical resolution (default: 60)\n"
200 " -TA N Trim vertical ascent (N percent)\n"
201 " -TD N Trim vertical descent (N percent)\n"
202 " -Ta N Trim vertical ascent (N pixels)\n"
203 " -Td N Trim vertical descent (N pixels)\n"
204 " -r N Row separation in pixel.Insert space between characters\n"
205 " -d Debug: print converted glyph images\n"
206 " -tt Display the True Type Collection tables available in the font\n"
207 " -t N Index of true type collection. It must be start from 0.(default N=0).\n"
208 " -ta Convert all fonts in ttc (ignores outfile option)\n"
209 " -w Don't try to make digits (0-9) equally wide\n"
211 fprintf(stderr, "%s", help);
212 exit( 1 );
215 /* remove directory prefix and file suffix from full path*/
216 char *basename(char *path)
218 char *p, *b;
219 static char base[256];
221 /* remove prepended path and extension*/
222 b = path;
223 for (p=path; *p; ++p) {
224 #ifdef WIN32
225 if (*p == '/' || *p == '\\')
226 #else
227 if (*p == '/')
228 #endif
229 b = p + 1;
231 strcpy(base, b);
232 for (p=base; *p; ++p) {
233 if (*p == '.') {
234 *p = 0;
235 break;
238 return base;
242 void setcharmap(FT_Face face)
244 FT_Long i;
247 * Get the requested cmap.
249 for (i = 0; i < face->num_charmaps; i++) {
250 if (face->charmaps[i]->platform_id == pid &&
251 face->charmaps[i]->encoding_id == eid)
252 break;
255 if (i == face->num_charmaps && pid == 3 && eid == 1) {
257 * Make a special case when this fails with pid == 3 and eid == 1.
258 * Change to eid == 0 and try again. This captures the two possible
259 * cases for MS fonts. Some other method should be used to cycle
260 * through all the alternatives later.
262 for (i = 0; i < face->num_charmaps; i++) {
263 if (face->charmaps[i]->platform_id == pid &&
264 face->charmaps[i]->encoding_id == 0)
265 break;
267 if (i < face->num_charmaps) {
268 pid = 3;
269 eid = 1;
270 FT_Set_Charmap(face, face->charmaps[i]);
271 } else {
273 * No CMAP was found.
275 nocmap = 1;
276 pid = eid = -1;
278 } else {
279 FT_Set_Charmap(face, face->charmaps[i]);
280 nocmap = 0;
286 * quote in otf2bdf.
287 * A generic routine to get a name from the OT name table. This routine
288 * always looks for English language names and checks three possibilities:
289 * 1. English names with the MS Unicode encoding ID.
290 * 2. English names with the MS unknown encoding ID.
291 * 3. English names with the Apple Unicode encoding ID.
293 * The particular name ID mut be provided (e.g. nameID = 0 for copyright
294 * string, nameID = 6 for Postscript name, nameID = 1 for typeface name.
296 * If the `dash_to_space' flag is non-zero, all dashes (-) in the name will be
297 * replaced with the character passed.
299 * Returns the number of bytes added.
301 static int
302 otf_get_english_string(FT_Face face, int nameID, int dash_to_space,
303 char *name, int name_size)
306 int j, encid;
307 FT_UInt i, nrec;
308 FT_SfntName sfntName;
309 unsigned char *s = NULL;
310 unsigned short slen = 0;
312 nrec = FT_Get_Sfnt_Name_Count(face);
314 for (encid = 1, j = 0; j < 2; j++, encid--) {
316 * Locate one of the MS English font names.
318 for (i = 0; i < nrec; i++) {
319 FT_Get_Sfnt_Name(face, i, &sfntName);
320 if (sfntName.platform_id == 3 &&
321 sfntName.encoding_id == encid &&
322 sfntName.name_id == nameID &&
323 (sfntName.language_id == 0x0409 ||
324 sfntName.language_id == 0x0809 ||
325 sfntName.language_id == 0x0c09 ||
326 sfntName.language_id == 0x1009 ||
327 sfntName.language_id == 0x1409 ||
328 sfntName.language_id == 0x1809)) {
329 s = sfntName.string;
330 slen = sfntName.string_len;
331 break;
335 if (i < nrec) {
336 if (slen >> 1 >= name_size) {
337 fprintf(stderr, "warning: %s string longer than buffer."
338 "Truncating to %d bytes.\n", string_names[nameID], name_size);
339 slen = name_size << 1;
343 * Found one of the MS English font names. The name is by
344 * definition encoded in Unicode, so copy every second byte into
345 * the `name' parameter, assuming there is enough space.
347 for (i = 1; i < slen; i += 2) {
348 if (dash_to_space)
349 *name++ = (s[i] != '-') ? s[i] : ' ';
350 else if (s[i] == '\r' || s[i] == '\n') {
351 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
352 i += 2;
353 *name++ = ' ';
354 *name++ = ' ';
355 } else
356 *name++ = s[i];
358 *name = 0;
359 return (slen >> 1);
364 * No MS English name found, attempt to find an Apple Unicode English
365 * name.
367 for (i = 0; i < nrec; i++) {
368 FT_Get_Sfnt_Name(face, i, &sfntName);
369 if (sfntName.platform_id == 0 && sfntName.language_id == 0 &&
370 sfntName.name_id == nameID) {
371 s = sfntName.string;
372 slen = sfntName.string_len;
373 break;
377 if (i < nrec) {
378 if (slen >> 1 >= name_size) {
379 fprintf(stderr, "warning: %s string longer than buffer."
380 "Truncating to %d bytes.\n", string_names[nameID], name_size);
381 slen = name_size << 1;
385 * Found the Apple Unicode English name. The name is by definition
386 * encoded in Unicode, so copy every second byte into the `name'
387 * parameter, assuming there is enough space.
389 for (i = 1; i < slen; i += 2) {
390 if (dash_to_space)
391 *name++ = (s[i] != '-') ? s[i] : ' ';
392 else if (s[i] == '\r' || s[i] == '\n') {
393 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
394 i += 2;
395 *name++ = ' ';
396 *name++ = ' ';
397 } else
398 *name++ = s[i];
400 *name = 0;
401 return (slen >> 1);
404 return 0;
408 int get_ttc_table(char *path, struct ttc_table *ttcname )
412 FT_Error err;
413 FT_Library library;
414 FT_Face face;
415 FT_Long i;
416 char xlfd[BUFSIZ];
418 /* init number of ttf in ttc */
419 ttcname->ttc_count = 0;
421 /* Initialize engine */
422 if ( ( err = FT_Init_FreeType( &library ) ) != 0 )
424 panic( "Error while initializing engine" );
425 return err;
429 /* Load face */
430 err = FT_New_Face( library, path, (FT_Long) 0, &face );
431 if ( err )
433 arg_panic( "Could not find/open font", path );
434 return err;
437 ttcname->ttc_count = face->num_faces;
438 ttcname->ttf_name = malloc( sizeof(char*) * ttcname->ttc_count);
440 for(i = 0; i < ttcname->ttc_count; i++)
442 err = FT_New_Face( library, path, i, &face );
443 if ( err == FT_Err_Cannot_Open_Stream )
444 arg_panic( "Could not find/open font", path );
445 otf_get_english_string(face, BDFOTF_POSTSCRIPT_STRING, 0, xlfd,
446 sizeof(xlfd));
447 ttcname->ttf_name[i] = malloc(sizeof(char) * (strlen(xlfd) + 1 ));
448 strcpy(ttcname->ttf_name[i], xlfd);
450 return 0;
453 void print_ttc_table(char* path)
455 struct ttc_table ttcname;
456 FT_Long i;
458 get_ttc_table(path, &ttcname);
459 printf("ttc header count = %ld \n\n", ttcname.ttc_count);
460 printf("Encoding tables available in the true type collection\n\n");
461 printf("INDEX\tPOSTSCRIPT NAME\n");
462 printf("-----------------------------------------------------\n");
463 for(i = 0; i < ttcname.ttc_count; i++)
465 printf("%ld\t%s\n", i, ttcname.ttf_name[i]);
467 for(i = 0; i < ttcname.ttc_count; i++)
469 free(ttcname.ttf_name[i]);
471 printf("\n\n");
472 free(ttcname.ttf_name);
474 return;
477 FT_Long getcharindex(FT_Face face, FT_Long code)
479 FT_Long idx;
480 if (nocmap) {
481 if (code >= face->num_glyphs)
482 idx = 0;
483 else
484 idx = code;
485 } else
486 idx = FT_Get_Char_Index( face, code);
488 if ( idx <= 0 || idx > face->num_glyphs)
489 return 0;
490 else
491 return idx;
494 void print_raw_glyph( FT_Face face)
496 int pixel,row,col,width;
497 width = face->glyph->metrics.width >> 6;
499 printf("\n---Raw-Glyph---\n");
500 for(row=0; row < face->glyph->metrics.height >> 6; row++)
502 printf("_");
503 for(col=0; col < width; col++)
505 pixel = *(face->glyph->bitmap.buffer+width*row+col)/26;
506 if ( pixel ) printf("%d",pixel); else printf(" ");
508 printf("_\n");
510 printf("----End-----\n");
513 int glyph_width( FT_Face face, FT_Long code, FT_Long digit_width )
515 int width;
517 if (code >= '0' && code <= '9' && digit_width)
519 width = digit_width;
521 else
523 int pitch, h_adv;
524 unsigned spacing = (unsigned)(between_chr * (1<<6));/* convert to fixed point */
526 pitch = ABS(face->glyph->bitmap.pitch);
527 h_adv = face->glyph->metrics.horiAdvance >> 6;
528 width = (face->glyph->metrics.width + spacing) >> 6;
530 if(pitch == 0) pitch = h_adv;
531 if(width < pitch) width = pitch;
534 return width;
537 FT_Long check_digit_width( FT_Face face )
539 FT_Long code;
540 FT_Long last_advance = -1;
542 for (code='0'; code <= '9'; ++code)
544 FT_Glyph_Metrics* metrics;
546 FT_Load_Char(face, code, FT_LOAD_RENDER | FT_LOAD_NO_BITMAP);
547 metrics = &face->glyph->metrics;
549 if ((last_advance != -1 && last_advance != metrics->horiAdvance) ||
550 metrics->horiBearingX < 0)
552 last_advance = 0;
553 break;
556 last_advance = metrics->horiAdvance;
559 return last_advance >> 6;
562 void trim_glyph( FT_GlyphSlot glyph, int *empty_first_col,
563 int *empty_last_col, int *width )
565 int row;
566 int stride = glyph->bitmap.pitch;
567 int end = stride-1;
568 int trim_left = 2, trim_right = 2;
570 const unsigned char limit = 64u;
571 const unsigned char *image = glyph->bitmap.buffer;
573 if (*width < 2)
574 return; /* nothing to do? */
576 for(row=0; row< glyph->metrics.height >> 6; row++)
578 const unsigned char *column = image+row*stride;
579 if (*column++ < limit && trim_left)
581 if (*column >= limit/2)
582 trim_left = 1;
584 else
585 trim_left = 0;
587 column = image+row*stride+end;
588 if (*column-- < limit && trim_right)
590 if (*column >= limit/2)
591 trim_right = 1;
593 else
594 trim_right = 0;
598 (*width) -= trim_left + trim_right;
599 if (*width < 0) *width = 0;
601 *empty_first_col = trim_left;
602 *empty_last_col = trim_right;
605 void convttf(char* path, char* destfile, FT_Long face_index)
607 FT_Error err;
608 FT_Library library;
609 FT_Face face;
610 int w,h;
611 int row,col;
612 int empty_first_col, empty_last_col;
613 FT_Long charindex;
614 FT_Long idx = 0;
615 FT_Long code;
616 FT_Long digit_width = 0;
617 float extra_space;
618 FT_Long char_count;
619 char use_long_offset;
620 int done = 0;
621 char char_name[1024];
622 int converted_char_count = 0;
623 int failed_char_count = 0;
625 int depth = 2;
626 unsigned char bit_shift = 1u << depth;
627 unsigned char pixel_per_byte = CHAR_BIT / bit_shift;
628 struct font_struct export_font;
629 char pad[] = {0,0,0,0};
630 int skip,i;
631 FILE *file;
633 /* Initialize engine */
634 if ( ( err = FT_Init_FreeType( &library ) ) != 0 )
635 panic( "Error while initializing engine" );
637 /* Load face */
638 err = FT_New_Face( library, path, (FT_Long) face_index, &face );
639 if ( err == FT_Err_Cannot_Open_Stream )
640 arg_panic( "Could not find/open font\n", path );
641 else if ( err )
642 arg_panic( "Error while opening font\n", path );
645 setcharmap( face );
646 /* Set font header data */
648 export_font.header.header[0] = 'R';
649 export_font.header.header[1] = 'B';
650 export_font.header.header[2] = '1';
651 export_font.header.header[3] = '2';
652 #if 0
653 export_font.header.height = 0;
654 export_font.header.ascent = 0;
655 #endif
657 extra_space = (float)(between_row-trim_aa-trim_da);
658 FT_Set_Char_Size( face, 0, pixel_size << 6, hv_resolution, hv_resolution );
659 export_font.header.ascent =
660 ((face->size->metrics.ascender*(100-trim_ap)/100) >> 6) - trim_aa;
662 export_font.header.height =
663 (((face->size->metrics.ascender*(100-trim_ap)/100) -
664 (face->size->metrics.descender*(100-trim_dp)/100)) >> 6) + extra_space;
666 printf("\n");
667 printf("Please wait, converting %s:\n", path);
669 /* "face->num_glyphs" is NG.; */
670 if ( limit_char == 0 ) limit_char = max_char;
671 if ( limit_char > max_char ) limit_char = max_char;
673 char_count = 0;
677 export_font.header.maxwidth = 1;
678 export_font.header.depth = 1;
679 firstchar = limit_char;
680 lastchar = start_char;
682 if (digits_equally_wide)
683 digit_width = check_digit_width(face);
685 /* calculate memory usage */
686 for(code = start_char; code <= limit_char ; code++ )
688 charindex = getcharindex( face, code);
689 if ( !(charindex) ) continue;
690 err = FT_Load_Glyph( face, charindex,
691 (FT_LOAD_RENDER | FT_LOAD_NO_BITMAP) );
692 if ( err ) continue;
694 w = glyph_width( face, code, digit_width );
695 if (w == 0) continue;
696 empty_first_col = empty_last_col = 0;
697 if(trimming)
698 trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w);
700 if (export_font.header.maxwidth < w)
701 export_font.header.maxwidth = w;
704 char_count++;
705 idx += (w*export_font.header.height + pixel_per_byte - 1)/pixel_per_byte;
707 if (code >= lastchar)
708 lastchar = code;
710 if (code <= firstchar)
711 firstchar = code;
713 export_font.header.defaultchar = firstchar;
714 export_font.header.firstchar = firstchar;
715 export_font.header.size = lastchar - firstchar + 1;
716 export_font.header.nbits = idx;
717 export_font.header.noffset = export_font.header.size;
718 export_font.header.nwidth = export_font.header.size;
720 /* check if we need to use long offsets */
721 use_long_offset = (export_font.header.nbits >= 0xFFDB );
723 /* allocate memory */
724 export_font.offset = NULL;
725 export_font.offset_long = NULL;
726 if (use_long_offset)
727 export_font.offset_long =
728 malloc( sizeof(FT_Long)* export_font.header.noffset );
729 else
730 export_font.offset =
731 malloc( sizeof(unsigned short)* export_font.header.noffset );
733 export_font.width =
734 malloc( sizeof(unsigned char) * export_font.header.nwidth );
735 export_font.chars_data =
736 malloc( sizeof(unsigned char) * export_font.header.nbits );
738 /* for now we use the full height for each character */
739 h = export_font.header.height;
741 idx = 0;
743 for( code = firstchar; code <= lastchar; code++ )
745 FT_GlyphSlot slot;
746 FT_Bitmap* source;
747 unsigned char* src;
748 unsigned char* tmpbuf;
749 int start_y;
751 int glyph_height;
752 int stride;
753 unsigned char* buf;
754 unsigned char* endbuf;
756 /* insert empty pixels on the left */
757 int col_off;
758 int numbits;
759 unsigned int field;
761 /* Get gylph index from the char and render it */
762 charindex = getcharindex( face, code);
763 if ( !charindex )
765 if ( use_long_offset )
766 export_font.offset_long[code - firstchar] = export_font.offset_long[0];
767 else
768 export_font.offset[code - firstchar] = export_font.offset[0];
769 export_font.width[code - firstchar] = export_font.width[0];
770 continue;
773 err = FT_Load_Glyph( face, charindex ,
774 (FT_LOAD_RENDER | FT_LOAD_NO_BITMAP) );
775 if ( err ) {
776 continue;
778 if FT_HAS_GLYPH_NAMES( face )
779 FT_Get_Glyph_Name( face, charindex, char_name, 16);
780 else
781 char_name[0] = '\0';
783 slot = face->glyph;
784 source = &slot->bitmap;
785 #if 0
786 print_raw_glyph( face );
787 #endif
788 w = glyph_width( face, code, digit_width );
789 if (w == 0) continue;
790 empty_first_col = empty_last_col = 0;
792 if(trimming)
793 trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w );
795 if ( use_long_offset )
796 export_font.offset_long[code - firstchar] = idx;
797 else
798 export_font.offset[code - firstchar] = idx;
800 export_font.width[code - firstchar] = w;
802 /* copy the glyph bitmap to a full sized glyph bitmap */
803 src = source->buffer;
804 tmpbuf = malloc(sizeof(unsigned char) * w * h);
805 memset(tmpbuf, 0xff, w*h);
806 start_y = export_font.header.ascent - slot->bitmap_top;
808 glyph_height = source->rows;
809 stride = source->pitch;
810 buf = tmpbuf;
811 endbuf = tmpbuf + w*h;
813 err = 0;
814 /* insert empty pixels on the left */
815 col_off = w - stride;
816 if (col_off > 1) col_off /= 2;
817 if (col_off < 0) col_off = 0;
819 for(row=0; row < glyph_height; row++)
821 if(row+start_y < 0 || row+start_y >= h)
822 continue;
823 for(col = empty_first_col; col < stride; col++)
825 unsigned char *tsrc, *dst;
826 dst = buf + (w*(start_y+row)) + col + col_off;
827 tsrc = src + stride*row + col;
828 if (dst < endbuf && dst >= tmpbuf)
829 *dst = 0xff - *tsrc;
830 else {
831 err = 1;
832 printf("Error! row: %3d col: %3d\n", row, col);
836 if(err) print_raw_glyph(face);
838 buf = tmpbuf;
839 field = 0;
840 numbits = pixel_per_byte;
842 for(row=0; row < h; row++)
844 for(col=0; col < w; col++)
846 unsigned int src2 = *buf++;
847 unsigned int cur_col = (src2 + 8) / 17;
848 field |= (cur_col << (bit_shift*(pixel_per_byte-numbits)));
850 if (--numbits == 0)
852 export_font.chars_data[idx++] = (unsigned char)field;
853 numbits = pixel_per_byte;
854 field = 0;
859 /* Pad last byte */
860 if (numbits != pixel_per_byte)
862 export_font.chars_data[idx++] = (unsigned char)field;
865 if( dump_glyphs )
867 /* debug: dump char */
868 unsigned char bit_max = (1 << bit_shift) - 1;
869 printf("\n---Converted Glyph Dump---\n");
871 if ( code > 32 && code < 255 ) {
872 unsigned char current_data;
873 unsigned char font_bits;
875 row = h;
876 if(use_long_offset)
877 buf = &(export_font.chars_data[export_font.offset_long[
878 code - firstchar]]);
879 else
880 buf = &(export_font.chars_data[export_font.offset[
881 code - firstchar]]);
882 numbits = pixel_per_byte;
883 current_data = *buf;
886 col = w;
887 printf("-");
890 font_bits = current_data & bit_max;
891 if (font_bits==bit_max)
892 printf(" ");
893 else
895 if(font_bits > bit_max/2)
896 printf(".");
897 else
898 printf("@");
900 if (--numbits == 0)
902 current_data = *(++buf);
903 numbits = pixel_per_byte;
905 else
907 current_data >>= bit_shift;
909 } while (--col);
910 printf("-\n");
911 } while (--row);
913 buf = NULL;
914 printf("---End Glyph Dump---\n");
917 free(tmpbuf);
918 converted_char_count++;
919 done = (100*(converted_char_count))/char_count;
920 printf("Converted %s %d (%d%%)\e[K\r",
921 char_name,converted_char_count,done); fflush(stdout);
924 file = fopen(destfile, "wb");
925 printf("Writing %s\n", destfile);
927 /* font info */
928 writestr(file, VERSION, 4);
929 writeshort(file, export_font.header.maxwidth);
930 writeshort(file, export_font.header.height);
931 writeshort(file, export_font.header.ascent);
932 writeshort(file, export_font.header.depth);
933 writeint(file, export_font.header.firstchar);
934 writeint(file, export_font.header.defaultchar);
935 writeint(file, export_font.header.size);
936 writeint(file, export_font.header.nbits);
937 writeint(file, export_font.header.noffset);
938 writeint(file, export_font.header.nwidth);
940 fwrite( (char*)export_font.chars_data, 1,
941 export_font.header.nbits, file);
942 free(export_font.chars_data);
946 if ( use_long_offset )
948 skip = ((export_font.header.nbits + 3) & ~3) -
949 export_font.header.nbits;
950 fwrite(pad, 1, skip, file); /* pad */
951 for(i = 0; i < export_font.header.noffset; i++)
952 writeint(file, export_font.offset_long[i]);
954 else
956 skip = ((export_font.header.nbits + 1) & ~1) -
957 export_font.header.nbits;
958 fwrite(pad, 1, skip, file); /* pad */
959 for(i = 0; i < export_font.header.noffset; i++)
960 writeshort(file, export_font.offset[i]);
963 for(i = 0; i < export_font.header.nwidth; i++)
964 writebyte(file, export_font.width[i]);
965 free(export_font.width);
967 if ( use_long_offset )
968 free(export_font.offset_long);
969 else
970 free(export_font.offset);
972 fclose(file);
973 FT_Done_Face( face );
974 FT_Done_FreeType( library );
975 printf("done (converted %d glyphs, %d errors).\e[K\n\n",
976 converted_char_count, failed_char_count);
980 void convttc(char* path)
982 struct ttc_table ttcname;
983 FT_Long i;
985 get_ttc_table(path, &ttcname);
987 if (ttcname.ttc_count == 0)
989 printf("This file is a not true type font.\n");
990 return;
993 /* default */
994 if (!flg_all_ttc && ttc_index == -1)
996 if (!oflag)
997 { /* generate filename */
998 snprintf(outfile, sizeof(outfile),
999 "%d-%s.fnt", pixel_size, basename(path));
1001 convttf(path, outfile, (FT_Long) 0);
1004 /* set face_index of ttc */
1005 else if (!flg_all_ttc)
1007 print_ttc_table(path);
1008 if ( !oflag )
1010 if (ttc_index >= 0 &&
1011 ttc_index < ttcname.ttc_count)
1013 if (strcmp(ttcname.ttf_name[ttc_index], "") != 0)
1015 snprintf(outfile, sizeof(outfile), "%d-%s.fnt",
1016 pixel_size, ttcname.ttf_name[ttc_index]);
1018 else
1020 snprintf(outfile, sizeof(outfile), "%d-%s-%ld.fnt",
1021 pixel_size, basename(path), ttc_index);
1024 else
1026 printf("illegal face index of ttc.\n");
1029 convttf(path, outfile, ttc_index);
1031 else { /* convert all fonts */
1032 print_ttc_table(path);
1033 for(i = 0; i < ttcname.ttc_count; i++)
1035 snprintf(outfile, sizeof(outfile), "%d-%s.fnt",
1036 pixel_size, ttcname.ttf_name[i]);
1037 convttf(path, outfile, i);
1041 for(i = 0; i < ttcname.ttc_count; i++)
1043 free(ttcname.ttf_name[i]);
1045 free(ttcname.ttf_name);
1050 /* parse command line options*/
1051 void getopts(int *pac, char ***pav)
1053 char *p;
1054 char **av;
1055 int ac;
1056 ac = *pac;
1057 av = *pav;
1059 limit_char = max_char;
1060 start_char = 0;
1062 while (ac > 0 && av[0][0] == '-') {
1063 p = &av[0][1];
1064 while( *p)
1065 switch(*p++) {
1066 case 'h':case 'H':
1067 usage();
1068 break;
1069 case ' ': /* multiple -args on av[]*/
1070 while( *p && *p == ' ')
1071 p++;
1072 if( *p++ != '-') /* next option must have dash*/
1073 p = "";
1074 break; /* proceed to next option*/
1075 case 'o': /* set output file*/
1076 oflag = 1;
1077 if (*p) {
1078 strcpy(outfile, p);
1079 while (*p && *p != ' ')
1080 p++;
1082 else {
1083 av++; ac--;
1084 if (ac > 0)
1085 strcpy(outfile, av[0]);
1087 break;
1088 case 'l': /* set encoding limit*/
1089 if (*p) {
1090 limit_char = atoi(p);
1091 while (*p && *p != ' ')
1092 p++;
1094 else {
1095 av++; ac--;
1096 if (ac > 0)
1097 limit_char = atoi(av[0]);
1099 break;
1100 case 's': /* set encoding start*/
1101 if (*p) {
1102 start_char = atol(p);
1103 while (*p && *p != ' ')
1104 p++;
1106 else {
1107 av++; ac--;
1108 if (ac > 0)
1109 start_char = atol(av[0]);
1111 break;
1112 case 'p': /* set pixel size*/
1113 if (*p) {
1114 pixel_size = atoi(p);
1115 while (*p && *p != ' ')
1116 p++;
1118 else {
1119 av++; ac--;
1120 if (ac > 0)
1121 pixel_size = atoi(av[0]);
1123 break;
1124 case 'c': /* set spaece between characters */
1126 if (*p) {
1127 between_chr = atof(p);
1128 while (*p && *p != ' ')
1129 p++;
1131 else {
1132 av++; ac--;
1133 if (ac > 0)
1134 between_chr = atof(av[0]);
1136 break;
1138 case 'd':
1139 dump_glyphs = 1;
1140 while (*p && *p != ' ')
1141 p++;
1142 break;
1143 case 'x':
1144 trimming = 1;
1145 while (*p && *p != ' ')
1146 p++;
1147 break;
1148 case 'X':
1149 if (*p) {
1150 hv_resolution = atoi(p);
1151 while (*p && *p != ' ')
1152 p++;
1154 else {
1155 av++; ac--;
1156 if (ac > 0)
1157 hv_resolution = atoi(av[0]);
1159 break;
1160 case 'r':
1161 if (*p) {
1162 between_row = atof(p);
1163 while (*p && *p != ' ')
1164 p++;
1166 else {
1167 av++; ac--;
1168 if (ac > 0)
1169 between_row = atof(av[0]);
1171 break;
1172 case 'T':
1173 if(*p == 'A') {
1174 if(*(++p)) {
1175 trim_ap = atoi(p);
1176 while (*p && *p != ' ')
1177 p++;
1179 else {
1180 av++; ac--;
1181 if (ac > 0)
1182 trim_ap = atoi(av[0]);
1184 break;
1186 if(*p == 'D') {
1187 if(*(++p)) {
1188 trim_dp = atoi(p);
1189 while (*p && *p != ' ')
1190 p++;
1192 else {
1193 av++; ac--;
1194 if (ac > 0)
1195 trim_dp = atoi(av[0]);
1197 break;
1199 if(*p == 'a') {
1200 if(*(++p)) {
1201 trim_aa = atoi(p);
1202 while (*p && *p != ' ')
1203 p++;
1205 else {
1206 av++; ac--;
1207 if (ac > 0)
1208 trim_aa = atoi(av[0]);
1210 break;
1212 if(*p == 'd') {
1213 if(*(++p)) {
1214 trim_da = atoi(p);
1217 else {
1218 av++; ac--;
1219 if (ac > 0)
1220 trim_da = atoi(av[0]);
1222 break;
1224 fprintf(stderr, "Unknown option ignored: %s\n", p-1);
1225 while (*p && *p != ' ')
1226 p++;
1227 break;
1228 case 't': /* display ttc table */
1229 if (*p == 't') {
1230 pct = 1;
1231 while (*p && *p != ' ')
1232 p++;
1235 else if (*p == 'a') {
1236 flg_all_ttc = 1;
1237 while (*p && *p != ' ')
1238 p++;
1241 else if (*p) {
1242 ttc_index = atoi(p);
1243 while (*p && *p != ' ')
1244 p++;
1246 else {
1247 av++; ac--;
1248 if (ac > 0)
1249 ttc_index = atoi(av[0]);
1251 break;
1252 case 'w': /* Don't try to make digits equally wide */
1253 digits_equally_wide = 0;
1254 while (*p && *p != ' ')
1255 p++;
1256 break;
1258 default:
1259 fprintf(stderr, "Unknown option ignored: %s\n", p-1);
1260 while (*p && *p != ' ')
1261 p++;
1263 ++av; --ac;
1265 *pac = ac;
1266 *pav = av;
1270 int main(int ac, char **av)
1272 int ret = 0;
1274 ++av; --ac; /* skip av[0]*/
1276 getopts(&ac, &av); /* read command line options*/
1278 if (ac < 1)
1280 usage();
1282 if (oflag)
1284 if (ac > 1)
1286 usage();
1290 if (limit_char < start_char)
1292 usage();
1293 exit(0);
1296 while (pct && ac > 0)
1298 print_ttc_table(av[0]);
1299 ++av; --ac;
1300 exit(0);
1303 while (ac > 0)
1305 convttc(av[0]);
1306 ++av; --ac;
1309 exit(ret);
1315 * Trie node structure.
1317 typedef struct {
1318 unsigned short key; /* Key value. */
1319 unsigned short val; /* Data for the key. */
1320 unsigned long sibs; /* Offset of siblings from trie beginning. */
1321 unsigned long kids; /* Offset of children from trie beginning. */
1322 } node_t;
1325 * The trie used for remapping codes.
1327 static node_t *nodes;
1328 static unsigned long nodes_used = 0;
1330 int
1331 otf2bdf_remap(unsigned short *code)
1333 unsigned long i, n, t;
1334 unsigned short c, codes[2];
1337 * If no mapping table was loaded, then simply return the code.
1339 if (nodes_used == 0)
1340 return 1;
1342 c = *code;
1343 codes[0] = (c >> 8) & 0xff;
1344 codes[1] = c & 0xff;
1346 for (i = n = 0; i < 2; i++) {
1347 t = nodes[n].kids;
1348 if (t == 0)
1349 return 0;
1350 for (; nodes[t].sibs && nodes[t].key != codes[i]; t = nodes[t].sibs);
1351 if (nodes[t].key != codes[i])
1352 return 0;
1353 n = t;
1356 *code = nodes[n].val;
1357 return 1;