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
28 #define snprintf _snprintf
34 #include FT_SFNT_NAMES_H
35 #include FT_TRUETYPE_TABLES_H
39 * Set the default values used to generate a BDF font.
41 #ifndef DEFAULT_PLATFORM_ID
42 #define DEFAULT_PLATFORM_ID 3
45 #ifndef DEFAULT_ENCODING_ID
46 #define DEFAULT_ENCODING_ID 1
49 #define ABS(x) (((x) < 0) ? -(x) : (x))
51 #define VERSION "RB12"
53 * nameID macros for getting strings from the OT font.
56 BDFOTF_COPYRIGHT_STRING
= 0,
58 BDFOTF_SUBFAMILY_STRING
,
59 BDFOTF_UNIQUEID_STRING
,
60 BDFOTF_FULLNAME_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
[] = {
75 "\"Postscript Name\"",
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;
95 FT_Long start_char
= 0;
97 FT_Long firstchar
= 0;
99 FT_Long ttc_index
= -1;
101 short antialias
= 1; /* smooth fonts with gray levels */
104 float between_chr
= 0.0f
;
105 float between_row
= 0.0f
;
106 int hv_resolution
= 60;
108 int digits_equally_wide
= 1; /* Try to make digits equally wide */
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 */
131 struct font_header_struct header
;
132 unsigned char *chars_data
;
133 unsigned short *offset
;
134 FT_Long
*offset_long
;
135 unsigned char *width
;
143 /* exit the program with given message */
145 panic( const char* message
)
147 fprintf( stderr
, "%s\n", message
);
152 arg_panic( const char* message
, const char* arg
)
154 fprintf( stderr
, "%s: %s\n", message
, arg
);
158 static int writebyte(FILE *fp
, unsigned char c
)
160 return putc(c
, fp
) != EOF
;
163 static int writeshort(FILE *fp
, unsigned short s
)
166 return putc(s
>>8, fp
) != EOF
;
169 static int writeint(FILE *fp
, unsigned int l
)
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 */
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"
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
);
215 /* remove directory prefix and file suffix from full path*/
216 char *basename(char *path
)
219 static char base
[256];
221 /* remove prepended path and extension*/
223 for (p
=path
; *p
; ++p
) {
225 if (*p
== '/' || *p
== '\\')
232 for (p
=base
; *p
; ++p
) {
242 void setcharmap(FT_Face face
)
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
)
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)
267 if (i
< face
->num_charmaps
) {
270 FT_Set_Charmap(face
, face
->charmaps
[i
]);
279 FT_Set_Charmap(face
, face
->charmaps
[i
]);
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.
302 otf_get_english_string(FT_Face face
, int nameID
, int dash_to_space
,
303 char *name
, int name_size
)
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)) {
330 slen
= sfntName
.string_len
;
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) {
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')
364 * No MS English name found, attempt to find an Apple Unicode English
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
) {
372 slen
= sfntName
.string_len
;
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) {
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')
408 int get_ttc_table(char *path
, struct ttc_table
*ttcname
)
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" );
430 err
= FT_New_Face( library
, path
, (FT_Long
) 0, &face
);
433 arg_panic( "Could not find/open font", path
);
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
,
447 ttcname
->ttf_name
[i
] = malloc(sizeof(char) * (strlen(xlfd
) + 1 ));
448 strcpy(ttcname
->ttf_name
[i
], xlfd
);
453 void print_ttc_table(char* path
)
455 struct ttc_table ttcname
;
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
]);
472 free(ttcname
.ttf_name
);
477 FT_Long
getcharindex(FT_Face face
, FT_Long code
)
481 if (code
>= face
->num_glyphs
)
486 idx
= FT_Get_Char_Index( face
, code
);
488 if ( idx
<= 0 || idx
> face
->num_glyphs
)
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
++)
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(" ");
510 printf("----End-----\n");
513 int glyph_width( FT_Face face
, FT_Long code
, FT_Long digit_width
)
517 if (code
>= '0' && code
<= '9' && digit_width
)
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
;
537 FT_Long
check_digit_width( FT_Face face
)
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)
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
)
566 int stride
= glyph
->bitmap
.pitch
;
568 int trim_left
= 2, trim_right
= 2;
570 const unsigned char limit
= 64u;
571 const unsigned char *image
= glyph
->bitmap
.buffer
;
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)
587 column
= image
+row
*stride
+end
;
588 if (*column
-- < limit
&& trim_right
)
590 if (*column
>= limit
/2)
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
)
612 int empty_first_col
, empty_last_col
;
616 FT_Long digit_width
= 0;
619 char use_long_offset
;
621 char char_name
[1024];
622 int converted_char_count
= 0;
623 int failed_char_count
= 0;
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};
633 /* Initialize engine */
634 if ( ( err
= FT_Init_FreeType( &library
) ) != 0 )
635 panic( "Error while initializing engine" );
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
);
642 arg_panic( "Error while opening font\n", path
);
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';
653 export_font
.header
.height
= 0;
654 export_font
.header
.ascent
= 0;
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
;
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
;
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
) );
694 w
= glyph_width( face
, code
, digit_width
);
695 if (w
== 0) continue;
696 empty_first_col
= empty_last_col
= 0;
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
;
705 idx
+= (w
*export_font
.header
.height
+ pixel_per_byte
- 1)/pixel_per_byte
;
707 if (code
>= lastchar
)
710 if (code
<= firstchar
)
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
;
727 export_font
.offset_long
=
728 malloc( sizeof(FT_Long
)* export_font
.header
.noffset
);
731 malloc( sizeof(unsigned short)* export_font
.header
.noffset
);
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
;
743 for( code
= firstchar
; code
<= lastchar
; code
++ )
748 unsigned char* tmpbuf
;
754 unsigned char* endbuf
;
756 /* insert empty pixels on the left */
761 /* Get gylph index from the char and render it */
762 charindex
= getcharindex( face
, code
);
765 if ( use_long_offset
)
766 export_font
.offset_long
[code
- firstchar
] = export_font
.offset_long
[0];
768 export_font
.offset
[code
- firstchar
] = export_font
.offset
[0];
769 export_font
.width
[code
- firstchar
] = export_font
.width
[0];
773 err
= FT_Load_Glyph( face
, charindex
,
774 (FT_LOAD_RENDER
| FT_LOAD_NO_BITMAP
) );
778 if FT_HAS_GLYPH_NAMES( face
)
779 FT_Get_Glyph_Name( face
, charindex
, char_name
, 16);
784 source
= &slot
->bitmap
;
786 print_raw_glyph( face
);
788 w
= glyph_width( face
, code
, digit_width
);
789 if (w
== 0) continue;
790 empty_first_col
= empty_last_col
= 0;
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
;
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
;
811 endbuf
= tmpbuf
+ w
*h
;
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
)
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
)
832 printf("Error! row: %3d col: %3d\n", row
, col
);
836 if(err
) print_raw_glyph(face
);
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
)));
852 export_font
.chars_data
[idx
++] = (unsigned char)field
;
853 numbits
= pixel_per_byte
;
860 if (numbits
!= pixel_per_byte
)
862 export_font
.chars_data
[idx
++] = (unsigned char)field
;
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
;
877 buf
= &(export_font
.chars_data
[export_font
.offset_long
[
880 buf
= &(export_font
.chars_data
[export_font
.offset
[
882 numbits
= pixel_per_byte
;
890 font_bits
= current_data
& bit_max
;
891 if (font_bits
==bit_max
)
895 if(font_bits
> bit_max
/2)
902 current_data
= *(++buf
);
903 numbits
= pixel_per_byte
;
907 current_data
>>= bit_shift
;
914 printf("---End Glyph Dump---\n");
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
);
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
]);
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
);
970 free(export_font
.offset
);
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
;
985 get_ttc_table(path
, &ttcname
);
987 if (ttcname
.ttc_count
== 0)
989 printf("This file is a not true type font.\n");
994 if (!flg_all_ttc
&& ttc_index
== -1)
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
);
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
]);
1020 snprintf(outfile
, sizeof(outfile
), "%d-%s-%ld.fnt",
1021 pixel_size
, basename(path
), ttc_index
);
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
)
1059 limit_char
= max_char
;
1062 while (ac
> 0 && av
[0][0] == '-') {
1069 case ' ': /* multiple -args on av[]*/
1070 while( *p
&& *p
== ' ')
1072 if( *p
++ != '-') /* next option must have dash*/
1074 break; /* proceed to next option*/
1075 case 'o': /* set output file*/
1079 while (*p
&& *p
!= ' ')
1085 strcpy(outfile
, av
[0]);
1088 case 'l': /* set encoding limit*/
1090 limit_char
= atoi(p
);
1091 while (*p
&& *p
!= ' ')
1097 limit_char
= atoi(av
[0]);
1100 case 's': /* set encoding start*/
1102 start_char
= atol(p
);
1103 while (*p
&& *p
!= ' ')
1109 start_char
= atol(av
[0]);
1112 case 'p': /* set pixel size*/
1114 pixel_size
= atoi(p
);
1115 while (*p
&& *p
!= ' ')
1121 pixel_size
= atoi(av
[0]);
1124 case 'c': /* set spaece between characters */
1127 between_chr
= atof(p
);
1128 while (*p
&& *p
!= ' ')
1134 between_chr
= atof(av
[0]);
1140 while (*p
&& *p
!= ' ')
1145 while (*p
&& *p
!= ' ')
1150 hv_resolution
= atoi(p
);
1151 while (*p
&& *p
!= ' ')
1157 hv_resolution
= atoi(av
[0]);
1162 between_row
= atof(p
);
1163 while (*p
&& *p
!= ' ')
1169 between_row
= atof(av
[0]);
1176 while (*p
&& *p
!= ' ')
1182 trim_ap
= atoi(av
[0]);
1189 while (*p
&& *p
!= ' ')
1195 trim_dp
= atoi(av
[0]);
1202 while (*p
&& *p
!= ' ')
1208 trim_aa
= atoi(av
[0]);
1220 trim_da
= atoi(av
[0]);
1224 fprintf(stderr
, "Unknown option ignored: %s\n", p
-1);
1225 while (*p
&& *p
!= ' ')
1228 case 't': /* display ttc table */
1231 while (*p
&& *p
!= ' ')
1235 else if (*p
== 'a') {
1237 while (*p
&& *p
!= ' ')
1242 ttc_index
= atoi(p
);
1243 while (*p
&& *p
!= ' ')
1249 ttc_index
= atoi(av
[0]);
1252 case 'w': /* Don't try to make digits equally wide */
1253 digits_equally_wide
= 0;
1254 while (*p
&& *p
!= ' ')
1259 fprintf(stderr
, "Unknown option ignored: %s\n", p
-1);
1260 while (*p
&& *p
!= ' ')
1270 int main(int ac
, char **av
)
1274 ++av
; --ac
; /* skip av[0]*/
1276 getopts(&ac
, &av
); /* read command line options*/
1290 if (limit_char
< start_char
)
1296 while (pct
&& ac
> 0)
1298 print_ttc_table(av
[0]);
1315 * Trie node structure.
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. */
1325 * The trie used for remapping codes.
1327 static node_t
*nodes
;
1328 static unsigned long nodes_used
= 0;
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)
1343 codes
[0] = (c
>> 8) & 0xff;
1344 codes
[1] = c
& 0xff;
1346 for (i
= n
= 0; i
< 2; i
++) {
1350 for (; nodes
[t
].sibs
&& nodes
[t
].key
!= codes
[i
]; t
= nodes
[t
].sibs
);
1351 if (nodes
[t
].key
!= codes
[i
])
1356 *code
= nodes
[n
].val
;