1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
22 #include FT_FREETYPE_H
33 #include FT_SFNT_NAMES_H
34 #include FT_TRUETYPE_TABLES_H
38 * Set the default values used to generate a BDF font.
40 #ifndef DEFAULT_PLATFORM_ID
41 #define DEFAULT_PLATFORM_ID 3
44 #ifndef DEFAULT_ENCODING_ID
45 #define DEFAULT_ENCODING_ID 1
48 #define ABS(x) (((x) < 0) ? -(x) : (x))
50 #define VERSION "RB12"
52 * nameID macros for getting strings from the OT font.
55 BDFOTF_COPYRIGHT_STRING
= 0,
57 BDFOTF_SUBFAMILY_STRING
,
58 BDFOTF_UNIQUEID_STRING
,
59 BDFOTF_FULLNAME_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
[] = {
74 "\"Postscript Name\"",
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;
94 FT_Long start_char
= 0;
96 FT_Long firstchar
= 0;
98 FT_Long ttc_index
= -1;
100 short antialias
= 1; /* smooth fonts with gray levels */
103 float between_chr
= 0.0f
;
104 float between_row
= 0.0f
;
105 int hv_resolution
= 60;
107 int digits_equally_wide
= 1; /* Try to make digits equally wide */
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 */
130 struct font_header_struct header
;
131 unsigned char *chars_data
;
132 unsigned short *offset
;
133 FT_Long
*offset_long
;
134 unsigned char *width
;
142 /* exit the program with given message */
144 panic( const char* message
)
146 fprintf( stderr
, "%s\n", message
);
151 arg_panic( const char* message
, const char* arg
)
153 fprintf( stderr
, "%s: %s\n", message
, arg
);
157 static int writebyte(FILE *fp
, unsigned char c
)
159 return putc(c
, fp
) != EOF
;
162 static int writeshort(FILE *fp
, unsigned short s
)
165 return putc(s
>>8, fp
) != EOF
;
168 static int writeint(FILE *fp
, unsigned int l
)
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 */
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"
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
);
214 /* remove directory prefix and file suffix from full path*/
215 char *basename(char *path
)
218 static char base
[256];
220 /* remove prepended path and extension*/
222 for (p
=path
; *p
; ++p
) {
227 for (p
=base
; *p
; ++p
) {
237 void setcharmap(FT_Face face
)
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
)
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)
262 if (i
< face
->num_charmaps
) {
265 FT_Set_Charmap(face
, face
->charmaps
[i
]);
274 FT_Set_Charmap(face
, face
->charmaps
[i
]);
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.
297 otf_get_english_string(FT_Face face
, int nameID
, int dash_to_space
,
298 char *name
, int name_size
)
303 FT_SfntName sfntName
;
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)) {
325 slen
= sfntName
.string_len
;
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) {
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')
359 * No MS English name found, attempt to find an Apple Unicode English
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
) {
367 slen
= sfntName
.string_len
;
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) {
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')
403 int get_ttc_table(char *path
, struct ttc_table
*ttcname
)
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" );
425 error
= FT_New_Face( library
, path
, (FT_Long
) 0, &face
);
428 arg_panic( "Could not find/open font", path
);
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
,
442 ttcname
->ttf_name
[i
] = malloc(sizeof(char) * (strlen(xlfd
) + 1 ));
443 strcpy(ttcname
->ttf_name
[i
], xlfd
);
448 void print_ttc_table(char* path
)
450 struct ttc_table ttcname
;
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
]);
467 free(ttcname
.ttf_name
);
472 FT_Long
getcharindex(FT_Face face
, FT_Long code
)
476 if (code
>= face
->num_glyphs
)
481 idx
= FT_Get_Char_Index( face
, code
);
483 if ( idx
<= 0 || idx
> face
->num_glyphs
)
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
++)
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(" ");
505 printf("----End-----\n");
508 int glyph_width( FT_Face face
, FT_Long code
, FT_Long digit_width
)
512 if (code
>= '0' && code
<= '9' && digit_width
)
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
;
532 FT_Long
check_digit_width( FT_Face face
)
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)
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
)
561 int stride
= glyph
->bitmap
.pitch
;
563 int trim_left
= 2, trim_right
= 2;
565 const unsigned char limit
= 64u;
566 const unsigned char *image
= glyph
->bitmap
.buffer
;
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)
582 column
= image
+row
*stride
+end
;
583 if (*column
-- < limit
&& trim_right
)
585 if (*column
>= limit
/2)
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
)
607 int empty_first_col
, empty_last_col
;
611 FT_Long digit_width
= 0;
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" );
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
);
626 arg_panic( "Error while opening font\n", path
);
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
;
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;
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
;
687 index
+= (w
*export_font
.header
.height
+ pixel_per_byte
- 1)/pixel_per_byte
;
689 if (code
>= lastchar
)
692 if (code
<= firstchar
)
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
;
709 export_font
.offset_long
=
710 malloc( sizeof(FT_Long
)* export_font
.header
.noffset
);
713 malloc( sizeof(unsigned short)* export_font
.header
.noffset
);
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
;
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
);
735 if ( use_long_offset
)
736 export_font
.offset_long
[code
- firstchar
] = export_font
.offset_long
[0];
738 export_font
.offset
[code
- firstchar
] = export_font
.offset
[0];
739 export_font
.width
[code
- firstchar
] = export_font
.width
[0];
743 error
= FT_Load_Glyph( face
, charindex
,
744 (FT_LOAD_RENDER
| FT_LOAD_NO_BITMAP
) );
748 if FT_HAS_GLYPH_NAMES( face
)
749 FT_Get_Glyph_Name( face
, charindex
, char_name
, 16);
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;
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
;
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
;
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
)
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
)
800 printf("Error! row: %3d col: %3d\n", row
, col
);
804 if(error
) print_raw_glyph(face
);
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
)));
822 export_font
.chars_data
[index
++] = (unsigned char)field
;
823 numbits
= pixel_per_byte
;
830 if (numbits
!= pixel_per_byte
)
832 export_font
.chars_data
[index
++] = (unsigned char)field
;
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 ) {
843 buf
= &(export_font
.chars_data
[export_font
.offset_long
[
846 buf
= &(export_font
.chars_data
[export_font
.offset
[
848 unsigned char current_data
;
849 unsigned char font_bits
;
850 numbits
= pixel_per_byte
;
858 font_bits
= current_data
& bit_max
;
859 if (font_bits
==bit_max
)
863 if(font_bits
> bit_max
/2)
870 current_data
= *(++buf
);
871 numbits
= pixel_per_byte
;
875 current_data
>>= bit_shift
;
882 printf("---End Glyph Dump---\n");
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
);
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
);
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
]);
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
);
938 free(export_font
.offset
);
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
;
953 get_ttc_table(path
, &ttcname
);
955 if (ttcname
.ttc_count
== 0)
957 printf("This file is a not true type font.\n");
962 if (!flg_all_ttc
&& ttc_index
== -1)
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
);
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
]);
988 snprintf(outfile
, sizeof(outfile
), "%d-%s-%ld.fnt",
989 pixel_size
, basename(path
), ttc_index
);
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
)
1027 limit_char
= max_char
;
1030 while (ac
> 0 && av
[0][0] == '-') {
1037 case ' ': /* multiple -args on av[]*/
1038 while( *p
&& *p
== ' ')
1040 if( *p
++ != '-') /* next option must have dash*/
1042 break; /* proceed to next option*/
1043 case 'o': /* set output file*/
1047 while (*p
&& *p
!= ' ')
1053 strcpy(outfile
, av
[0]);
1056 case 'l': /* set encoding limit*/
1058 limit_char
= atoi(p
);
1059 while (*p
&& *p
!= ' ')
1065 limit_char
= atoi(av
[0]);
1068 case 's': /* set encoding start*/
1070 start_char
= atol(p
);
1071 while (*p
&& *p
!= ' ')
1077 start_char
= atol(av
[0]);
1080 case 'p': /* set pixel size*/
1082 pixel_size
= atoi(p
);
1083 while (*p
&& *p
!= ' ')
1089 pixel_size
= atoi(av
[0]);
1092 case 'c': /* set spaece between characters */
1095 between_chr
= atof(p
);
1096 while (*p
&& *p
!= ' ')
1102 between_chr
= atof(av
[0]);
1108 while (*p
&& *p
!= ' ')
1113 while (*p
&& *p
!= ' ')
1118 hv_resolution
= atoi(p
);
1119 while (*p
&& *p
!= ' ')
1125 hv_resolution
= atoi(av
[0]);
1130 between_row
= atof(p
);
1131 while (*p
&& *p
!= ' ')
1137 between_row
= atof(av
[0]);
1144 while (*p
&& *p
!= ' ')
1150 trim_ap
= atoi(av
[0]);
1157 while (*p
&& *p
!= ' ')
1163 trim_dp
= atoi(av
[0]);
1170 while (*p
&& *p
!= ' ')
1176 trim_aa
= atoi(av
[0]);
1188 trim_da
= atoi(av
[0]);
1192 fprintf(stderr
, "Unknown option ignored: %s\n", p
-1);
1193 while (*p
&& *p
!= ' ')
1196 case 't': /* display ttc table */
1199 while (*p
&& *p
!= ' ')
1203 else if (*p
== 'a') {
1205 while (*p
&& *p
!= ' ')
1210 ttc_index
= atoi(p
);
1211 while (*p
&& *p
!= ' ')
1217 ttc_index
= atoi(av
[0]);
1220 case 'w': /* Don't try to make digits equally wide */
1221 digits_equally_wide
= 0;
1222 while (*p
&& *p
!= ' ')
1227 fprintf(stderr
, "Unknown option ignored: %s\n", p
-1);
1228 while (*p
&& *p
!= ' ')
1238 int main(int ac
, char **av
)
1242 ++av
; --ac
; /* skip av[0]*/
1244 getopts(&ac
, &av
); /* read command line options*/
1258 if (limit_char
< start_char
)
1264 while (pct
&& ac
> 0)
1266 print_ttc_table(av
[0]);
1283 * Trie node structure.
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. */
1293 * The trie used for remapping codes.
1295 static node_t
*nodes
;
1296 static unsigned long nodes_used
= 0;
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)
1311 codes
[0] = (c
>> 8) & 0xff;
1312 codes
[1] = c
& 0xff;
1314 for (i
= n
= 0; i
< 2; i
++) {
1318 for (; nodes
[t
].sibs
&& nodes
[t
].key
!= codes
[i
]; t
= nodes
[t
].sibs
);
1319 if (nodes
[t
].key
!= codes
[i
])
1324 *code
= nodes
[n
].val
;