Integrate convttf into tools/.
[kugel-rb.git] / tools / convttf.c
blobfdc45ed39c2d2c1049d6fb5d16b9bff706586875
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 #define BITMAP_WORDS(x) (((x)+15)/16) /* image size in words*/
23 #include <stdint.h>
24 #include <ft2build.h>
25 #include <math.h>
26 #include FT_FREETYPE_H
27 #include FT_GLYPH_H
29 #include <stdio.h>
30 #ifdef WIN32
31 #include <windows.h>
32 #else
33 #include <stdlib.h>
34 #include <unistd.h>
35 #endif
36 #include FT_SFNT_NAMES_H
37 #include FT_TRUETYPE_TABLES_H
39 #include <string.h>
41 * Set the default values used to generate a BDF font.
43 #ifndef DEFAULT_PLATFORM_ID
44 #define DEFAULT_PLATFORM_ID 3
45 #endif
47 #ifndef DEFAULT_ENCODING_ID
48 #define DEFAULT_ENCODING_ID 1
49 #endif
51 #define log_level_nolog 0
52 #define log_level_warnning 1
53 #define log_level_header 2
54 #define log_level_description1 3
55 #define log_level_description2 4
57 #ifndef log_level
58 #define log_level log_level_nolog
59 #endif
61 #define MIN(a,b) ((a)<(b) ? (a) : (b))
62 #define MAX(a,b) ((a)>(b) ? (a) : (b))
65 * nameID macros for getting strings from the OT font.
67 enum {
68 BDFOTF_COPYRIGHT_STRING = 0,
69 BDFOTF_FAMILY_STRING,
70 BDFOTF_SUBFAMILY_STRING,
71 BDFOTF_UNIQUEID_STRING,
72 BDFOTF_FULLNAME_STRING,
73 BDFOTF_VENDOR_STRING,
74 BDFOTF_POSTSCRIPT_STRING,
75 BDFOTF_TRADEMARK_STRING,
78 * String names for the string indexes. Used for error messages.
80 static char *string_names[] = {
81 "\"Copyright\"",
82 "\"Family\"",
83 "\"SubFamily\"",
84 "\"Unique ID\"",
85 "\"Full Name\"",
86 "\"Vendor\"",
87 "\"Postscript Name\"",
88 "\"Trademark\""
93 * The default platform and encoding ID's.
95 static int pid = DEFAULT_PLATFORM_ID;
96 static int eid = DEFAULT_ENCODING_ID;
100 * A flag indicating if a CMap was found or not.
102 static FT_UShort nocmap;
104 #define MAX_CHAR 65535
105 int pct = 0; /* display ttc table if it is not zero. */
106 int pixel_size = 15;
107 unsigned long start_char = 0;
108 unsigned long limit_char;
109 unsigned long firstchar = 0;
110 unsigned long lastchar;
111 FT_Long ttc_index = -1;
112 int flg_all_ttc = 0;
113 const int depth = 1;
114 short antialias = 1; /* smooth fonts with gray levels */
115 int oflag = 0;
116 char outfile[1024];
117 int between_chr = 0;
118 int between_row = 1;
120 struct font_header_struct {
121 char header[4]; /* magic number and version bytes */
122 unsigned short maxwidth; /* max width in pixels */
123 unsigned short height; /* height in pixels */
124 unsigned short ascent; /* ascent (baseline) height */
125 unsigned short depth; /* depth 0=1-bit, 1=4-bit */
126 unsigned long firstchar; /* first character in font */
127 unsigned long defaultchar; /* default character in font */
128 unsigned long size; /* # characters in font */
129 unsigned long nbits; /* # bytes imagebits data in file */
131 FT_Long noffset; /* # longs offset data in file */
132 FT_Long nwidth; /* # bytes width data in file */
135 struct ttc_table {
136 FT_Long ttc_count;
137 char **ttf_name;
140 /* exit the program with given message */
141 static void
142 panic( const char* message )
144 fprintf( stderr, "%s\n", message );
145 exit( 1 );
148 /* print usage information */
149 void usage(void)
151 char help[] = {
152 "Usage: convttf [options] [input-files]\n"
153 " convttf [options] [-o output-file] [single-input-file]\n\n"
154 " Default output-filename : \n"
155 " 'input-files name removed extension'_'font-size'.fnt.\n"
156 " but default output-filename become \n "
157 " 'internal postscript-name of input-file'_'font-size'.fnt.\n"
158 " if '-ta' or '-tc' options are described.\n"
159 "Options:\n"
160 " -s N Start output at character encodings >= N\n"
161 " -l N Limit output to character encodings <= N\n"
162 " -p N Character height N in pixel (default N=15)\n"
163 " -c N Character separation in pixel.Insert space between lines. (default N=1)\n"
164 " -r N Row separation in pixel.Insert space between characters\n"
165 " -tt Display the True Type Collection tables available in the font\n"
166 " -t N Index of true type collection. It must be start from 0.(default N=0).\n"
167 " -ta Convert all fonts in ttc\n"
168 " \"-o output-file\" specified is ignored when \"-ta\" is specified.\n"
170 fprintf(stderr, help);
171 exit( 1 );
174 /* remove directory prefix and file suffix from full path*/
175 char *basename(char *path)
177 char *p, *b;
178 static char base[256];
180 /* remove prepended path and extension*/
181 b = path;
182 for (p=path; *p; ++p) {
183 if (*p == '/')
184 b = p + 1;
186 strcpy(base, b);
187 for (p=base; *p; ++p) {
188 if (*p == '.') {
189 *p = 0;
190 break;
193 return base;
197 void setcharmap(FT_Face face)
199 FT_Long i;
202 * Get the requested cmap.
204 for (i = 0; i < face->num_charmaps; i++) {
205 if (face->charmaps[i]->platform_id == pid &&
206 face->charmaps[i]->encoding_id == eid)
207 break;
210 if (i == face->num_charmaps && pid == 3 && eid == 1) {
212 * Make a special case when this fails with pid == 3 and eid == 1.
213 * Change to eid == 0 and try again. This captures the two possible
214 * cases for MS fonts. Some other method should be used to cycle
215 * through all the alternatives later.
217 for (i = 0; i < face->num_charmaps; i++) {
218 if (face->charmaps[i]->platform_id == pid &&
219 face->charmaps[i]->encoding_id == 0)
220 break;
222 if (i < face->num_charmaps) {
223 pid = 3;
224 eid = 1;
225 FT_Set_Charmap(face, face->charmaps[i]);
226 } else {
228 * No CMAP was found.
230 nocmap = 1;
231 pid = eid = -1;
233 } else {
234 FT_Set_Charmap(face, face->charmaps[i]);
235 nocmap = 0;
241 * quote in otf2bdf.
242 * A generic routine to get a name from the OT name table. This routine
243 * always looks for English language names and checks three possibilities:
244 * 1. English names with the MS Unicode encoding ID.
245 * 2. English names with the MS unknown encoding ID.
246 * 3. English names with the Apple Unicode encoding ID.
248 * The particular name ID mut be provided (e.g. nameID = 0 for copyright
249 * string, nameID = 6 for Postscript name, nameID = 1 for typeface name.
251 * If the `dash_to_space' flag is non-zero, all dashes (-) in the name will be
252 * replaced with the character passed.
254 * Returns the number of bytes added.
256 static int
257 otf_get_english_string(FT_Face face, int nameID, int dash_to_space,
258 char *name, int name_size)
261 int j, encid;
262 FT_UInt i, nrec;
263 FT_SfntName sfntName;
264 unsigned char *s;
265 unsigned short slen;
267 nrec = FT_Get_Sfnt_Name_Count(face);
269 for (encid = 1, j = 0; j < 2; j++, encid--) {
271 * Locate one of the MS English font names.
273 for (i = 0; i < nrec; i++) {
274 FT_Get_Sfnt_Name(face, i, &sfntName);
275 if (sfntName.platform_id == 3 &&
276 sfntName.encoding_id == encid &&
277 sfntName.name_id == nameID &&
278 (sfntName.language_id == 0x0409 ||
279 sfntName.language_id == 0x0809 ||
280 sfntName.language_id == 0x0c09 ||
281 sfntName.language_id == 0x1009 ||
282 sfntName.language_id == 0x1409 ||
283 sfntName.language_id == 0x1809)) {
284 s = sfntName.string;
285 slen = sfntName.string_len;
286 break;
290 if (i < nrec) {
291 if (slen >> 1 >= name_size) {
292 fprintf(stderr, "warning: %s string longer than buffer. "
293 "Truncating to %d bytes.\n", string_names[nameID],
294 name_size);
295 slen = name_size << 1;
299 * Found one of the MS English font names. The name is by
300 * definition encoded in Unicode, so copy every second byte into
301 * the `name' parameter, assuming there is enough space.
303 for (i = 1; i < slen; i += 2) {
304 if (dash_to_space)
305 *name++ = (s[i] != '-') ? s[i] : ' ';
306 else if (s[i] == '\r' || s[i] == '\n') {
307 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
308 i += 2;
309 *name++ = ' ';
310 *name++ = ' ';
311 } else
312 *name++ = s[i];
314 *name = 0;
315 return (slen >> 1);
320 * No MS English name found, attempt to find an Apple Unicode English
321 * name.
323 for (i = 0; i < nrec; i++) {
324 FT_Get_Sfnt_Name(face, i, &sfntName);
325 if (sfntName.platform_id == 0 && sfntName.language_id == 0 &&
326 sfntName.name_id == nameID) {
327 s = sfntName.string;
328 slen = sfntName.string_len;
329 break;
333 if (i < nrec) {
334 if (slen >> 1 >= name_size) {
335 fprintf(stderr, "warning: %s string longer than buffer. "
336 "Truncating to %d bytes.\n", string_names[nameID], name_size);
337 slen = name_size << 1;
341 * Found the Apple Unicode English name. The name is by definition
342 * encoded in Unicode, so copy every second byte into the `name'
343 * parameter, assuming there is enough space.
345 for (i = 1; i < slen; i += 2) {
346 if (dash_to_space)
347 *name++ = (s[i] != '-') ? s[i] : ' ';
348 else if (s[i] == '\r' || s[i] == '\n') {
349 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
350 i += 2;
351 *name++ = ' ';
352 *name++ = ' ';
353 } else
354 *name++ = s[i];
356 *name = 0;
357 return (slen >> 1);
360 return 0;
364 int get_ttc_table(char *path, struct ttc_table *ttcname )
368 FT_Error error;
369 FT_Library library;
370 FT_Face face;
371 FT_Long i;
372 char xlfd[BUFSIZ];
374 /* init number of ttf in ttc */
375 ttcname->ttc_count = 0;
377 /* Initialize engine */
378 if ( ( error = FT_Init_FreeType( &library ) ) != 0 )
380 panic( "Error while initializing engine" );
381 return error;
385 /* Load face */
386 error = FT_New_Face( library, path, (FT_Long) 0, &face );
387 if ( error == FT_Err_Cannot_Open_Stream )
389 panic( "Could not find/open font resource" );
390 return error;
393 ttcname->ttc_count = face->num_faces;
394 ttcname->ttf_name = malloc( sizeof(char*) * ttcname->ttc_count);
396 for(i = 0; i < ttcname->ttc_count; i++)
398 error = FT_New_Face( library, path, i, &face );
399 if ( error == FT_Err_Cannot_Open_Stream )
400 panic( "Could not find/open font resource\n" );
401 otf_get_english_string(face, BDFOTF_POSTSCRIPT_STRING, 0, xlfd,
402 sizeof(xlfd));
403 ttcname->ttf_name[i] = malloc(sizeof(char) * (strlen(xlfd) + 1 ));
404 strcpy(ttcname->ttf_name[i], xlfd);
406 return 0;
409 void print_ttc_table(char* path)
411 struct ttc_table ttcname;
412 FT_Long i;
414 get_ttc_table(path, &ttcname);
415 printf("ttc header count = %ld \n\n", ttcname.ttc_count);
416 printf("Encoding tables available in the true type collection\n\n");
417 printf("INDEX\tPOSTSCRIPT NAME\n");
418 printf("-----------------------------------------------------\n");
419 for(i = 0; i < ttcname.ttc_count; i++)
421 printf("%ld\t%s\n", i, ttcname.ttf_name[i]);
423 for(i = 0; i < ttcname.ttc_count; i++)
425 free(ttcname.ttf_name[i]);
427 printf("\n\n");
428 free(ttcname.ttf_name);
430 return;
433 FT_Long getcharindex(FT_Face face, FT_Long code)
435 FT_Long idx;
436 if (nocmap) {
437 if (code >= face->num_glyphs)
438 idx = 0;
439 else
440 idx = code;
441 } else
442 idx = FT_Get_Char_Index( face, code);
444 if ( idx <= 0 || idx > face->num_glyphs)
445 return 0;
446 else
447 return idx;
450 int calculate_output_glyph_data(FT_GlyphSlot glyph, int *start_x)
452 int ow, ow1, osx;
453 ow = glyph->bitmap.pitch;
454 if (ow == 0)
455 ow = glyph->metrics.horiAdvance >> 6;
456 ow1 = glyph->metrics.width >> 6;
457 ow = MAX(ow, ow1);
458 if (!ow)
459 return 0;
460 osx = glyph->metrics.horiBearingX >> 6;
461 osx = MAX(osx, 0);
462 ow += osx + between_chr;
463 if (!start_x)
464 return ow;
465 osx += between_chr >> 1;
466 *start_x = osx;
467 return ow;
470 void convttf(char* path, FT_Long face_index)
472 FT_Error error;
473 FT_Library library;
474 FT_Face face;
475 int w, h;
476 int row,col;
477 FT_Long charindex;
478 FT_Long index = 0;
479 FT_Long code;
480 FT_Long min_start_y;
481 FT_Long max_end_y;
482 FT_Long glyph_index[MAX_CHAR] = {0};
483 FT_Size_RequestRec req = {
484 FT_SIZE_REQUEST_TYPE_REAL_DIM,
486 ((pixel_size - between_row) << 10),
490 char char_name[16];
491 int empty_glyphs[256] = {0};
492 int glyph_buffer_size = 0;
493 unsigned char *glyph_buffer = NULL;
494 int got_default = 0;
495 int default_char;
497 #if log_level > log_level_nolog
498 FILE *pTmplog;
499 char logfile[256];
500 strcpy(logfile, basename(path));
501 char log_suf[20];
502 sprintf(log_suf, "_%d.log", pixel_size);
503 strcat(logfile, log_suf);
504 if ((pTmplog = fopen(logfile, "w")) == 0) {
505 fprintf(stderr, "unable to open temporary file '%s'.\n",
506 logfile);
507 return;
509 else
511 printf("log_file is %s\n\n", logfile);
514 #endif
515 /* Initialize engine */
516 if ( ( error = FT_Init_FreeType( &library ) ) != 0 )
517 panic( "Error while initializing engine" );
519 /* Load face */
520 error = FT_New_Face( library, path, (FT_Long) face_index, &face );
521 if ( error == FT_Err_Cannot_Open_Stream )
522 panic( "Could not find/open font resource" );
523 else if ( error )
524 panic( "Error while opening font resource" );
527 setcharmap( face );
528 /* create size */
529 error = FT_Request_Size( face, &req );
530 if ( error )
531 panic( "Could not reset instance" );
533 printf("Please wait, converting %s to %s:\n",path,outfile);
535 if ( limit_char == 0 ) limit_char = MAX_CHAR;
536 if ( limit_char > MAX_CHAR ) limit_char = MAX_CHAR;
538 FT_Long char_count = 0;
540 /* Set font header data */
541 struct font_header_struct export_font;
542 export_font.header[0] = 'R';
543 export_font.header[1] = 'B';
544 export_font.header[2] = '1';
545 export_font.header[3] = '2';
547 export_font.maxwidth = 0;
548 h = min_start_y = ((face->size->metrics.ascender
549 - face->size->metrics.descender + 63) >> 6);
550 max_end_y = 0;
551 /* + between_row; */
552 export_font.ascent = (face->size->metrics.ascender + 63) >> 6;
553 export_font.depth = depth;
554 firstchar = limit_char;
555 lastchar = limit_char;
556 default_char = limit_char;
557 #if log_level >= log_level_header
558 fprintf(pTmplog, "limit_char=%ld\n", limit_char);
559 fprintf(pTmplog, "face->size->metrics.ascender>>6=%ld\n",
560 face->size->metrics.ascender>>6);
561 fprintf(pTmplog, "face->size->metrics.descender>>6=%ld\n",
562 face->size->metrics.descender>>6);
564 #endif
567 /* decide common height, first_char and last_char, char_count */
568 FT_Long tmp_count = 0;
569 printf("calculating height...\n"); fflush(stdout);
571 error = FT_Load_Glyph( face, 0, (FT_LOAD_NO_BITMAP) );
572 if (!error)
574 FT_Long glyph_height = face->glyph->metrics.height >> 6;
575 FT_Long start_y = export_font.ascent - face->glyph->bitmap_top;
576 FT_Long end_y = start_y + glyph_height;
577 if (glyph_height)
579 if (end_y > max_end_y) max_end_y = end_y;
580 if (start_y < min_start_y) min_start_y = start_y;
582 got_default = 1;
585 for(code = start_char; code <= limit_char ; code++ )
587 switch(code)
589 /* combining diacritical marks */
590 case 0x0300:
591 code = 0x36f;
592 continue;
593 /* combining diacritical marks supplement */
594 case 0x1dc0:
595 code = 0x1dff;
596 continue;
597 /* combining diacritical marks for symbols */
598 case 0x20d0:
599 code = 0x20ff;
600 continue;
601 /* high surrogates */
602 case 0xd800:
603 code = 0xdbff;
604 continue;
605 /* low surrogates */
606 case 0xdc00:
607 code = 0xdfff;
608 continue;
609 /* combining half marks */
610 case 0xfe20:
611 code = 0xfe2f;
612 continue;
614 /* Is there glyph of this code in this ttf? */
615 charindex = getcharindex( face, code);
616 if ( !(charindex) ) goto check_default;
618 printf("\t%3d%% \e[K\r", (int) (tmp_count++
619 * 100 / face->num_glyphs) );
620 fflush(stdout);
622 error = FT_Load_Glyph( face, charindex, (FT_LOAD_RENDER |
623 FT_LOAD_NO_BITMAP) );
624 if ( error ) goto check_default;
626 /* Is this glyph available? */
627 if (!(w = calculate_output_glyph_data(face->glyph, NULL)))
628 goto check_default;
630 /* count this font */
631 glyph_index[code] = charindex;
632 char_count++;
634 /* decide height */
635 FT_Long glyph_height = face->glyph->metrics.height >> 6;
636 FT_Long start_y = export_font.ascent - face->glyph->bitmap_top;
637 FT_Long end_y = start_y + glyph_height;
639 #if log_level >= log_level_description1
640 fprintf(pTmplog, "code=%ld\n", code);
641 fflush(pTmplog);
642 #endif
644 #if log_level >= log_level_description2
645 fprintf(pTmplog, "\t glyph_height =%ld \n",
646 (face->glyph->metrics.height) >> 6);
647 fprintf(pTmplog, "\t horiBearingY =%ld \n",
648 (face->glyph->metrics.horiBearingY >>6) );
649 fprintf(pTmplog, "\t vertBearingY =%ld \n",
650 (face->glyph->metrics.vertBearingY >>6));
651 fprintf(pTmplog, "\t vertAdvance =%ld \n",
652 (face->glyph->metrics.vertAdvance >>6));
653 fprintf(pTmplog, "\t start_y =%ld \n", start_y);
654 fprintf(pTmplog, "\t height =%ld \n",
655 (face->glyph->metrics.height >> 6));
656 fprintf(pTmplog, "\t end_y =%ld \n", end_y);
658 if (face->glyph->bitmap_top != (face->glyph->metrics.horiBearingY >>6))
659 fprintf(pTmplog, "\t bitmap_top =%d \n",
660 face->glyph->bitmap_top);
661 if (face->glyph->bitmap.rows != glyph_height)
662 fprintf(pTmplog, "\t bitmap.rows =%d \n",
663 face->glyph->bitmap.rows);
665 fflush(pTmplog);
666 #endif
667 if (code < firstchar) firstchar = code;
668 lastchar = code;
669 if (end_y > max_end_y) max_end_y = end_y;
670 if (start_y < min_start_y) min_start_y = start_y;
671 continue;
672 check_default:
673 if (firstchar < limit_char && default_char == limit_char)
674 default_char = code;
676 min_start_y = MAX(min_start_y, 0);
677 max_end_y = MIN(max_end_y, h);
678 h = (max_end_y - min_start_y);
679 req.type = FT_SIZE_REQUEST_TYPE_SCALES;
680 req.height = req.width = face->size->metrics.x_scale
681 * (pixel_size - between_row) / h;
682 min_start_y = min_start_y * (pixel_size - between_row) / h;
683 h = export_font.height = pixel_size;
684 if (default_char == limit_char)
685 default_char = --firstchar;
686 error = FT_Request_Size( face, &req );
687 if ( error )
688 panic( "Could not reset instance" );
689 export_font.ascent = face->size->metrics.ascender >> 6;
691 export_font.height = h;
692 int extra_top = between_row >> 1; /* about half of between_row */
693 printf("\t done.\t\n");
694 printf("\t%ld glyphs are encoded in this source file according to a source"
695 " font property.\n", face->num_glyphs);
696 printf("\t%ld characters can be converted.\n", char_count);
697 printf("\tfirst character = %ld\n", firstchar);
698 printf("\tlast character = %ld\n", lastchar);
699 printf("\tdefault character = %d\n", default_char);
700 printf("\tline height = %d\n\n", h);
701 fflush(stdout);
703 #if log_level >= log_level_header
704 fprintf(pTmplog, "requested size=%.2f\n", req.height / 64.0);
705 fprintf(pTmplog, "max_end_y=%ld\n", max_end_y);
706 fprintf(pTmplog, "min_start_y=%ld\n", min_start_y);
707 fprintf(pTmplog, "ascender - descender = %ld \n",
708 (face->size->metrics.ascender - face->size->metrics.descender)>>6);
709 fprintf(pTmplog, "h = %ld \n", (FT_Long) h);
710 fflush(pTmplog);
711 #endif
712 export_font.size = lastchar - firstchar + 1;
713 export_font.noffset = export_font.size;
714 export_font.nwidth = export_font.size;
715 export_font.defaultchar = default_char;
716 export_font.firstchar = firstchar;
717 uint32_t offsets[export_font.size];
718 uint8_t widths[export_font.size];
719 memset(offsets, 0, sizeof(offsets));
720 memset(widths, 0, sizeof(widths));
721 index = 0;
723 fprintf(stderr,"converting font...\n"); fflush(stdout);
724 for( code = firstchar; code <= lastchar; code++)
726 printf("\t%3d%% \e[K\r", (int)((code - firstchar + 1)
727 * 100 / export_font.size));
728 fflush(stdout);
729 offsets[code - firstchar] = offsets[default_char];
730 widths[code - firstchar] = widths[default_char];
731 if (!(charindex = glyph_index[code])
732 && (!got_default || code != default_char))
733 continue;
734 error = FT_Load_Glyph( face, charindex,
735 FT_LOAD_RENDER|FT_LOAD_NO_BITMAP );
736 if (error)
737 continue;
738 if FT_HAS_GLYPH_NAMES(face)
739 FT_Get_Glyph_Name(face, charindex, char_name, 16);
740 else
741 char_name[0] = '\0';
743 FT_Bitmap *source = &face->glyph->bitmap;
744 int start_x;
745 if (!(w = calculate_output_glyph_data(face->glyph, &start_x)))
746 continue;
748 export_font.maxwidth = MAX(w, export_font.maxwidth);
749 unsigned char* src = source->buffer;
750 unsigned char tmpbuf[w * h];
751 memset(tmpbuf, 0xff, w * h);
752 FT_Long start_y = export_font.ascent - face->glyph->bitmap_top;
753 FT_Long glyph_height = face->glyph->metrics.height >> 6;
754 FT_Long glyph_width = face->glyph->metrics.width >> 6;
755 unsigned char *buf = tmpbuf;
756 int offset = extra_top + (start_y - min_start_y);
757 row = 0;
758 if (offset > 0)
759 buf += w * offset;
760 else
761 src += -offset * glyph_width;
762 int max_col = MIN(glyph_width, w - start_x);
763 int max_row = MIN(h - MAX(offset, 0), glyph_height + MIN(offset, 0));
764 unsigned char *endbuf = buf + w * max_row;
765 if (glyph_height)
767 for(; buf < endbuf ; buf += w, src += glyph_width)
768 for(col=0; col < max_col; col++)
769 buf[col + start_x]= 0xff - src[col];
771 else {
773 if (!empty_glyphs[w])
775 int glyph_size = (w * h + 1) / 2;
776 empty_glyphs[w] = index;
777 if (glyph_buffer_size < index + glyph_size)
778 if (!(glyph_buffer = realloc(glyph_buffer,
779 glyph_buffer_size += (glyph_size * 2 + 1023) & ~1023)))
780 panic("Failed to allocate memory for glyphs");
781 memset(&glyph_buffer[index], 0xff, glyph_size);
782 index += glyph_size;
784 offsets[code - firstchar] = empty_glyphs[w];
785 widths[code - firstchar] = w;
786 continue;
788 offsets[code - firstchar] = index;
789 widths[code - firstchar] = w;
790 int i;
791 int field = 0;
792 buf = tmpbuf;
793 int glyph_size = (w * h + 1) / 2;
794 if (glyph_buffer_size < index + glyph_size)
795 if (!(glyph_buffer = realloc(glyph_buffer, glyph_buffer_size
796 += (glyph_size * 2 + 1023) & ~1023)))
797 panic("Failed to allocate memory for glyphs");
798 for (i = 0; i < w * h; i++)
800 int subcol = i % 2;
801 unsigned char pixel = ((unsigned)(*buf++) + 8) / 17;
802 field |= pixel << (subcol << 2);
803 if (i % 2)
805 glyph_buffer[index++] = field;
806 field = 0;
810 if (i % 2)
811 glyph_buffer[index++] = field;
813 printf("\t done.\t\n");
814 export_font.nbits = index;
815 int n;
816 FILE *file = fopen(outfile, "w");
817 n = fwrite(&export_font, 1, sizeof(struct font_header_struct), file);
818 /* This prevents valgrind from triggering on the write from uninitialized
819 * memory.
821 memset(glyph_buffer + index, 0, glyph_buffer_size - index);
822 n = fwrite(glyph_buffer, 1, (index + 3) & ~3, file);
823 int offsets_size = export_font.noffset * 4;
824 if ( index < 0xFFDB )
826 uint16_t * short_offsets = (uint16_t *)offsets;
827 int i;
828 for (i = 0; i < export_font.noffset; i++)
829 short_offsets[i] = offsets[i];
830 offsets_size /= 2;
832 n = fwrite(offsets, 1, offsets_size, file);
833 n = fwrite(widths, 1, export_font.nwidth, file);
834 fclose(file);
835 #if log_level > log_level_nolog
836 fclose(pTmplog);
837 #endif
840 void convttc(char* path)
842 struct ttc_table ttcname;
843 FT_Long i;
845 get_ttc_table(path, &ttcname);
847 if (ttcname.ttc_count == 0)
849 printf("This file is a not true type font.\n");
850 return;
853 /* defalut */
854 if (!flg_all_ttc &&
855 ttc_index == -1)
857 if (!oflag)
859 printf("path: %s\n", path);
860 sprintf(outfile, "%d-%s.fnt", pixel_size, basename(path));
862 convttf(path, (FT_Long) 0);
865 /* set face_index of ttc */
866 else if (!flg_all_ttc)
868 print_ttc_table(path);
869 if ( !oflag )
871 if (ttc_index >= 0 &&
872 ttc_index < ttcname.ttc_count)
874 if (strcmp(ttcname.ttf_name[ttc_index], "") != 0)
876 sprintf(outfile, "%d-%s.fnt", pixel_size,
877 ttcname.ttf_name[ttc_index]);
879 else
881 sprintf(outfile, "%d-%s-%ld.fnt",
882 pixel_size,basename(path),ttc_index);
885 else
887 printf("illegal face index of ttc.\n");
890 convttf(path, ttc_index);
892 else { /* convert all fonts */
893 print_ttc_table(path);
894 for(i = 0; i < ttcname.ttc_count; i++)
896 convttf(path, i);
897 sprintf(outfile, "%d-%s.fnt", pixel_size, ttcname.ttf_name[i]);
901 for(i = 0; i < ttcname.ttc_count; i++)
903 free(ttcname.ttf_name[i]);
905 free(ttcname.ttf_name);
910 /* parse command line options*/
911 void getopts(int *pac, char ***pav)
913 char *p;
914 char **av;
915 int ac;
916 ac = *pac;
917 av = *pav;
919 limit_char = MAX_CHAR;
920 start_char = 0;
922 while (ac > 0 && av[0][0] == '-') {
923 p = &av[0][1];
924 while( *p)
925 switch(*p++) {
926 case 'h':case 'H':
927 usage();
928 break;
929 case ' ': /* multiple -args on av[]*/
930 while( *p && *p == ' ')
931 p++;
932 if( *p++ != '-') /* next option must have dash*/
933 p = "";
934 break; /* proceed to next option*/
935 case 'o':case 'O': /* set output file*/
936 oflag = 1;
937 if (*p) {
938 strcpy(outfile, p);
939 while (*p && *p != ' ')
940 p++;
942 else {
943 av++; ac--;
944 if (ac > 0)
945 strcpy(outfile, av[0]);
947 break;
948 case 'l':case 'L': /* set encoding limit*/
949 if (*p) {
950 limit_char = atoi(p);
951 while (*p && *p != ' ')
952 p++;
954 else {
955 av++; ac--;
956 if (ac > 0)
957 limit_char = atoi(av[0]);
959 break;
960 case 's':case 'S': /* set encoding start*/
961 if (*p) {
962 start_char = atol(p);
963 while (*p && *p != ' ')
964 p++;
966 else {
967 av++; ac--;
968 if (ac > 0)
969 start_char = atol(av[0]);
971 break;
972 case 'p':case 'P': /* set pixel size*/
973 if (*p) {
974 pixel_size = atoi(p);
975 while (*p && *p != ' ')
976 p++;
978 else {
979 av++; ac--;
980 if (ac > 0)
981 pixel_size = atoi(av[0]);
983 break;
984 case 'c':case 'C': /* set spaece between characters */
985 if (*p) {
986 between_chr = atoi(p);
987 while (*p && *p != ' ')
988 p++;
990 else {
991 av++; ac--;
992 if (ac > 0)
993 between_chr = atoi(av[0]);
995 break;
996 case 'r':case 'R': /* set spaece between rows */
997 if (*p) {
998 between_row = atoi(p);
999 while (*p && *p != ' ')
1000 p++;
1002 else {
1003 av++; ac--;
1004 if (ac > 0)
1005 between_row = atoi(av[0]);
1007 break;
1008 case 't':case 'T': /* display ttc table */
1009 if (*p == 't' || *p == 'T') {
1010 pct = 1;
1011 while (*p && *p != ' ')
1012 p++;
1015 else if (*p == 'a' || *p == 'A') {
1016 flg_all_ttc = 1;
1017 while (*p && *p != ' ')
1018 p++;
1021 else if (*p) {
1022 ttc_index = atoi(p);
1023 while (*p && *p != ' ')
1024 p++;
1026 else {
1027 av++; ac--;
1028 if (ac > 0)
1029 ttc_index = atoi(av[0]);
1031 break;
1033 default:
1034 fprintf(stderr, "Unknown option ignored: %c\r\n", *(p-1));
1036 ++av; --ac;
1038 *pac = ac;
1039 *pav = av;
1043 int main(int ac, char **av)
1045 int ret = 0;
1047 ++av; --ac; /* skip av[0]*/
1049 getopts(&ac, &av); /* read command line options*/
1051 if (ac < 1)
1053 usage();
1055 if (oflag)
1057 if (ac > 1)
1059 usage();
1063 if (limit_char < start_char)
1065 usage();
1066 exit(0);
1069 while (pct && ac > 0)
1071 print_ttc_table(av[0]);
1072 ++av; --ac;
1073 exit(0);
1076 while (ac > 0)
1078 convttc(av[0]);
1079 ++av; --ac;
1082 exit(ret);
1088 * Trie node structure.
1090 typedef struct {
1091 unsigned short key; /* Key value. */
1092 unsigned short val; /* Data for the key. */
1093 unsigned long sibs; /* Offset of siblings from trie beginning. */
1094 unsigned long kids; /* Offset of children from trie beginning. */
1095 } node_t;
1098 * The trie used for remapping codes.
1100 static node_t *nodes;
1101 static unsigned long nodes_used = 0;
1104 otf2bdf_remap(unsigned short *code)
1106 unsigned long i, n, t;
1107 unsigned short c, codes[2];
1110 * If no mapping table was loaded, then simply return the code.
1112 if (nodes_used == 0)
1113 return 1;
1115 c = *code;
1116 codes[0] = (c >> 8) & 0xff;
1117 codes[1] = c & 0xff;
1119 for (i = n = 0; i < 2; i++) {
1120 t = nodes[n].kids;
1121 if (t == 0)
1122 return 0;
1123 for (; nodes[t].sibs && nodes[t].key != codes[i]; t = nodes[t].sibs);
1124 if (nodes[t].key != codes[i])
1125 return 0;
1126 n = t;
1129 *code = nodes[n].val;
1130 return 1;