2 * Copyright 1996, 1997, 1998, 1999 Computing Research Labs,
3 * New Mexico State University
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
20 * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 static char rcsid
[] __attribute__ ((unused
)) = "$Id$";
27 static char rcsid
[] = "$Id$";
45 * Include the remapping support.
49 /**************************************************************************
53 **************************************************************************/
56 * The version of ttf2bdf.
58 #define TTF2BDF_VERSION "2.8"
61 * Set the default values used to generate a BDF font.
63 #ifndef DEFAULT_PLATFORM_ID
64 #define DEFAULT_PLATFORM_ID 3
67 #ifndef DEFAULT_ENCODING_ID
68 #define DEFAULT_ENCODING_ID 1
71 #ifndef DEFAULT_POINT_SIZE
72 #define DEFAULT_POINT_SIZE 12
75 #ifndef DEFAULT_RESOLUTION
76 #define DEFAULT_RESOLUTION 100
80 * Used as a fallback for XLFD names where the character set/encoding can not
83 #ifndef DEFAULT_XLFD_CSET
84 #define DEFAULT_XLFD_CSET "-FontSpecific-0"
88 * nameID macros for getting strings from the TT font.
90 #define TTF_COPYRIGHT 0
91 #define TTF_TYPEFACE 1
95 #define MAX(h,i) ((h) > (i) ? (h) : (i))
99 #define MIN(l,o) ((l) < (o) ? (l) : (o))
102 /**************************************************************************
104 * General globals set from command line.
106 **************************************************************************/
114 * The flag indicating whether messages should be printed or not.
116 static int verbose
= 0;
119 * Flags used when loading glyphs.
121 static int load_flags
= TTLOAD_SCALE_GLYPH
| TTLOAD_HINT_GLYPH
;
124 * The default platform and encoding ID's.
126 static int pid
= DEFAULT_PLATFORM_ID
;
127 static int eid
= DEFAULT_ENCODING_ID
;
130 * Default point size and resolutions.
132 static int point_size
= DEFAULT_POINT_SIZE
;
133 static int hres
= DEFAULT_RESOLUTION
;
134 static int vres
= DEFAULT_RESOLUTION
;
137 * The user supplied foundry name to use in the XLFD name.
139 static char *foundry_name
= 0;
142 * The user supplied typeface name to use in the XLFD name.
144 static char *face_name
= 0;
147 * The user supplied weight name to use in the XLFD name.
149 static char *weight_name
= 0;
152 * The user supplied slant name to use in the XLFD name.
154 static char *slant_name
= 0;
157 * The user supplied width name to use in the XLFD name.
159 static char *width_name
= 0;
162 * The user supplied additional style name to use in the XLFD name.
164 static char *style_name
= 0;
167 * The user supplied spacing (p = proportional, c = character cell,
170 static int spacing
= 0;
173 * The dash character to use in the names retrieved from the font. Default is
176 static int dashchar
= ' ';
179 * Flag, bitmask, and max code for generating a subset of the glyphs in a font.
181 static int do_subset
= 0;
182 static unsigned short maxcode
;
183 static unsigned long subset
[2048];
186 * The flag that indicates the remapping table should be used to
189 static int do_remap
= 0;
191 /**************************************************************************
195 **************************************************************************/
198 * Structure used for calculating the font bounding box as the glyphs are
213 * The buffer used to transfer the temporary file to the actual output file.
215 #define TTF2BDF_IOBUFSIZ 8192
216 static char iobuf
[TTF2BDF_IOBUFSIZ
];
219 * The Units Per Em value used in numerous places.
221 static TT_UShort upm
;
224 * A flag indicating if a CMap was found or not.
226 static TT_UShort nocmap
;
229 * The scaling factor needed to compute the SWIDTH (scalable width) value
232 static double swscale
;
235 * Mac encoding names used when creating the BDF XLFD font name.
237 static char *mac_encodings
[] = {
238 "-MacRoman-0", "-MacJapanese-0", "-MacChinese-0", "-MacKorean-0",
239 "-MacArabic-0", "-MacHebrew-0", "-MacGreek-0", "-MacRussian-0",
240 "-MacRSymbol-0", "-MacDevanagari-0", "-MacGurmukhi-0", "-MacGujarati-0",
241 "-MacOriya-0", "-MacBengali-0", "-MacTamil-0", "-MacTelugu-0",
242 "-MacKannada-0", "-MacMalayalam-0", "-MacSinhalese-0", "-MacBurmese-0",
243 "-MacKhmer-0", "-MacThai-0", "-MacLaotian-0", "-MacGeorgian-0",
244 "-MacArmenian-0", "-MacMaldivian-0", "-MacTibetan-0", "-MacMongolian-0",
245 "-MacGeez-0", "-MacSlavic-0", "-MacVietnamese-0","-MacSindhi-0",
248 static int num_mac_encodings
= sizeof(mac_encodings
) /
249 sizeof(mac_encodings
[0]);
252 * ISO encoding names used when creating the BDF XLFD font name.
254 static char *iso_encodings
[] = {
255 "-ASCII-0", "-ISO10646-0", "-ISO8859-1"
257 static int num_iso_encodings
= sizeof(iso_encodings
) /
258 sizeof(iso_encodings
[0]);
261 * Microsoft encoding names used when creating the BDF XLFD font name.
263 static char *ms_encodings
[] = {
264 "-Symbol-0", "-ISO10646-1", "-ShiftJIS-0", "-GB2312.1980-0", "-Big5-0",
265 "-KSC5601.1987-0", "-KSC5601.1992-0"
267 static int num_ms_encodings
= sizeof(ms_encodings
) /
268 sizeof(ms_encodings
[0]);
271 * The propery names for all the XLFD properties.
273 static char *xlfd_props
[] = {
290 /**************************************************************************
294 **************************************************************************/
296 static TT_Engine engine
;
298 static TT_Face_Properties properties
;
300 static TT_Instance instance
;
302 static TT_Glyph glyph
;
303 static TT_Glyph_Metrics metrics
;
304 static TT_Instance_Metrics imetrics
;
306 static TT_Raster_Map raster
;
308 static TT_CharMap cmap
;
310 /**************************************************************************
312 * Freetype related code.
314 **************************************************************************/
317 * A generic routine to get a name from the TT name table. This routine
318 * always looks for English language names and checks three possibilities:
319 * 1. English names with the MS Unicode encoding ID.
320 * 2. English names with the MS unknown encoding ID.
321 * 3. English names with the Apple Unicode encoding ID.
323 * The particular name ID mut be provided (e.g. nameID = 0 for copyright
324 * string, nameID = 6 for Postscript name, nameID = 1 for typeface name.
326 * If the `dash' flag is non-zero, all dashes (-) in the name will be replaced
327 * with the character passed.
329 * Returns the number of bytes added.
333 ttf_get_english_name(char *name
, int nameID
, int dash
)
335 ttf_get_english_name(name
, nameID
, dash
)
341 int i
, j
, encid
, nrec
;
342 unsigned short nrPlatformID
, nrEncodingID
, nrLanguageID
, nrNameID
;
345 nrec
= TT_Get_Name_Count(face
);
347 for (encid
= 1, j
= 0; j
< 2; j
++, encid
--) {
349 * Locate one of the MS English font names.
351 for (i
= 0; i
< nrec
; i
++) {
352 TT_Get_Name_ID(face
, i
, &nrPlatformID
, &nrEncodingID
,
353 &nrLanguageID
, &nrNameID
);
354 if (nrPlatformID
== 3 &&
355 nrEncodingID
== encid
&&
356 nrNameID
== nameID
&&
357 (nrLanguageID
== 0x0409 || nrLanguageID
== 0x0809 ||
358 nrLanguageID
== 0x0c09 || nrLanguageID
== 0x1009 ||
359 nrLanguageID
== 0x1409 || nrLanguageID
== 0x1809)) {
360 TT_Get_Name_String(face
, i
, &s
, &slen
);
367 * Found one of the MS English font names. The name is by
368 * definition encoded in Unicode, so copy every second byte into
369 * the `name' parameter, assuming there is enough space.
371 for (i
= 1; s
!= 0 && i
< slen
; i
+= 2) {
373 *name
++ = (s
[i
] == '-' || s
[i
] == ' ') ? dash
: s
[i
];
374 else if (s
[i
] == '\r' || s
[i
] == '\n') {
375 if (s
[i
] == '\r' && i
+ 2 < slen
&& s
[i
+ 2] == '\n')
388 * No MS English name found, attempt to find an Apple Unicode English
391 for (i
= 0; i
< nrec
; i
++) {
392 TT_Get_Name_ID(face
, i
, &nrPlatformID
, &nrEncodingID
,
393 &nrLanguageID
, &nrNameID
);
394 if (nrPlatformID
== 0 && nrLanguageID
== 0 &&
395 nrNameID
== nameID
) {
396 TT_Get_Name_String(face
, i
, &s
, &slen
);
403 * Found the Apple Unicode English name. The name is by definition
404 * encoded in Unicode, so copy every second byte into the `name'
405 * parameter, assuming there is enough space.
407 for (i
= 1; s
!= 0 && i
< slen
; i
+= 2) {
409 *name
++ = (s
[i
] == '-' || s
[i
] == ' ') ? dash
: s
[i
];
410 else if (s
[i
] == '\r' || s
[i
] == '\n') {
411 if (s
[i
] == '\r' && i
+ 2 < slen
&& s
[i
+ 2] == '\n')
425 /**************************************************************************
429 **************************************************************************/
432 * Create an XLFD name. Assumes there is enough space in the string passed
433 * to fit a reasonably long XLFD name into, up to the 256 byte maximum.
437 make_xlfd_name(char *name
, TT_Long awidth
, int ismono
)
439 make_xlfd_name(name
, awidth
, ismono
)
451 * Default the foundry name to "FreeType" in honor of the project and
452 * because the foundry name is too difficult to automatically determine
453 * from the names in TT fonts. But the user can provide his own.
455 if (foundry_name
== 0) {
456 (void) strcpy(name
, "-FreeType");
460 strcpy(name
,foundry_name
);
461 name
+=strlen(foundry_name
);
465 * Add the typeface name from the font. The fallback default will be
469 if (face_name
== 0) {
470 if((i
= ttf_get_english_name(name
, TTF_TYPEFACE
, dashchar
)))
473 (void) strcpy(name
, "Unknown");
477 (void) strcpy(name
, face_name
);
478 name
+= strlen(face_name
);
482 * Add the weight name. The default will be "Medium".
484 if (weight_name
!= 0) {
485 sprintf(name
, "-%s", weight_name
);
486 name
+= strlen(weight_name
) + 1;
488 if (properties
.os2
->fsSelection
& 0x20) {
489 (void) strcpy(name
, "-Bold");
492 (void) strcpy(name
, "-Medium");
498 * Add the slant name. The default will be 'R'.
501 sprintf(name
, "-%s", slant_name
);
502 name
+= strlen(slant_name
) + 1;
505 if (properties
.os2
->fsSelection
& 0x01)
512 * Default the setwidth name to "Normal" but user can specify one.
514 if (width_name
== 0) {
515 (void) strcpy(name
, "-Normal");
519 strcpy(name
,width_name
);
520 name
+=strlen(width_name
);
524 * Default the additional style name to NULL but user can specify one.
527 if (style_name
!= 0) {
528 strcpy(name
,style_name
);
529 name
+=strlen(style_name
);
533 * Determine the pixel size from the point size and resolution.
536 dp
= (double) (point_size
* 10);
537 val
= (unsigned long) (((dp
* dr
) / 722.7) + 0.5);
540 * Set the pixel size, point size, and resolution.
542 sprintf(name
, "-%ld-%d-%d-%d", val
, point_size
* 10, hres
, vres
);
543 name
+= strlen(name
);
546 case 'p': case 'P': spacing
= 'P'; break;
547 case 'm': case 'M': spacing
= 'M'; break;
548 case 'c': case 'C': spacing
= 'C'; break;
549 default: spacing
= 0; break;
556 spacing
= (ismono
) ? 'M' : 'P';
561 * Add the average width.
563 sprintf(name
, "-%ld", awidth
);
564 name
+= strlen(name
);
567 * Check to see if the remapping table specified a registry and encoding
568 * and use those if they both exist.
570 ttf2bdf_remap_charset(&r
, &e
);
571 if (r
!= 0 && e
!= 0) {
572 sprintf(name
, "-%s-%s", r
, e
);
577 * If the cmap for the platform and encoding id was not found, or the
578 * platform id is unknown, assume the character set registry and encoding
579 * are the XLFD default.
581 if (nocmap
|| pid
> 3)
582 (void) strcpy(name
, DEFAULT_XLFD_CSET
);
585 * Finally, determine the character set registry and encoding from the
586 * platform and encoding ID.
591 * Apple Unicode platform, so "Unicode-2.0" is the default.
593 (void) strcpy(name
, "-Unicode-2.0");
597 * Macintosh platform, so choose from the Macintosh encoding
600 if (eid
< 0 || eid
>= num_mac_encodings
)
601 (void) strcpy(name
, DEFAULT_XLFD_CSET
);
603 (void) strcpy(name
, mac_encodings
[eid
]);
607 * ISO platform, so choose from the ISO encoding strings.
609 if (eid
< 0 || eid
>= num_iso_encodings
)
610 (void) strcpy(name
, DEFAULT_XLFD_CSET
);
612 (void) strcpy(name
, iso_encodings
[eid
]);
616 * Microsoft platform, so choose from the MS encoding strings.
618 if (eid
< 0 || eid
>= num_ms_encodings
)
619 (void) strcpy(name
, DEFAULT_XLFD_CSET
);
621 (void) strcpy(name
, ms_encodings
[eid
]);
629 generate_font(FILE *out
, char *iname
, char *oname
)
631 generate_font(out
, iname
, oname
)
638 TT_Short maxx
, maxy
, minx
, miny
, xoff
, yoff
, dwidth
, swidth
;
639 TT_Short y_off
, x_off
;
640 TT_UShort sx
, sy
, ex
, ey
, wd
, ht
;
641 TT_Long code
, idx
, ng
, aw
;
642 TT_UShort remapped_code
;
646 char *tmpdir
, tmpfile
[BUFSIZ
];
649 * Open a temporary file to store the bitmaps in until the exact number
650 * of bitmaps are known.
652 if ((tmpdir
= getenv("TMPDIR")) == 0)
654 sprintf(tmpfile
, "%s/ttf2bdf%ld", tmpdir
, (long) getpid());
655 if ((tmp
= fopen(tmpfile
, "w")) == 0) {
656 fprintf(stderr
, "%s: unable to open temporary file '%s'.\n",
662 * Calculate the scale factor for the SWIDTH field.
664 swscale
= ((double) vres
) * ((double) point_size
);
667 * Calculate the font bounding box again so enough storage for the largest
668 * bitmap can be allocated.
670 minx
= (properties
.header
->xMin
* imetrics
.x_ppem
) / upm
;
671 miny
= (properties
.header
->yMin
* imetrics
.y_ppem
) / upm
;
672 maxx
= (properties
.header
->xMax
* imetrics
.x_ppem
) / upm
;
673 maxy
= (properties
.header
->yMax
* imetrics
.y_ppem
) / upm
;
675 maxx
-= minx
; ++maxx
;
676 maxy
-= miny
; ++maxy
;
679 * Initialize the flag that tracks if the font is monowidth or not and
680 * initialize the glyph width variable that is used for testing for a
687 * Use the upward flow because the version of FreeType being used when
688 * this was written did not support TT_Flow_Down. This insures that this
689 * routine will not mess up if TT_Flow_Down is implemented at some point.
691 raster
.flow
= TT_Flow_Up
;
694 raster
.cols
= (maxx
+ 7) >> 3;
695 raster
.size
= raster
.cols
* raster
.rows
;
696 raster
.bitmap
= (void *) malloc(raster
.size
);
698 for (ng
= code
= 0, eof
= 0, aw
= 0; eof
!= EOF
&& code
< 0xffff; code
++) {
701 * If a remap is indicated, attempt to remap the code. If a remapped
702 * code is not found, then skip generating the glyph.
704 remapped_code
= (TT_UShort
) code
;
705 if (do_remap
&& !ttf2bdf_remap(&remapped_code
))
709 * If a subset is being generated and the code is greater than the max
710 * code of the subset, break out of the loop to avoid doing any more
713 if (do_subset
&& remapped_code
> maxcode
)
717 * If a subset is being generated and the index is not in the subset
718 * bitmap, just continue.
721 !(subset
[remapped_code
>> 5] & (1 << (remapped_code
& 31))))
725 if (code
>= properties
.num_Glyphs
)
728 * At this point, all the glyphs are done.
733 idx
= TT_Char_Index(cmap
, code
);
736 * If the glyph could not be loaded for some reason, or a subset is
737 * being generated and the index is not in the subset bitmap, just
741 if (idx
<= 0 || TT_Load_Glyph(instance
, glyph
, idx
, load_flags
))
744 (void) TT_Get_Glyph_Metrics(glyph
, &metrics
);
747 * Clear the raster bitmap.
749 (void) memset((char *) raster
.bitmap
, 0, raster
.size
);
752 * Grid fit to determine the x and y offsets that will force the
753 * bitmap to fit into the storage provided.
755 xoff
= (63 - metrics
.bbox
.xMin
) & -64;
756 yoff
= (63 - metrics
.bbox
.yMin
) & -64;
759 * If the bitmap cannot be generated, simply continue.
761 if (TT_Get_Glyph_Bitmap(glyph
, &raster
, xoff
, yoff
))
765 * Determine the DWIDTH (device width, or advance width in TT terms)
766 * and the SWIDTH (scalable width) values.
768 dwidth
= metrics
.advance
>> 6;
769 dw
= (double) dwidth
;
770 swidth
= (TT_Short
) ((dw
* 72000.0) / swscale
);
773 * Determine the actual bounding box of the glyph bitmap. Do not
774 * forget that the glyph is rendered upside down!
778 bmap
= (unsigned char *) raster
.bitmap
;
779 for (miny
= 0; miny
< raster
.rows
; miny
++) {
780 for (minx
= 0; minx
< raster
.width
; minx
++) {
781 if (bmap
[(miny
* raster
.cols
) + (minx
>> 3)] &
782 (0x80 >> (minx
& 7))) {
796 * If the glyph is actually an empty bitmap, set the size to 0 all
799 if (sx
== 0xffff && ey
== 0xffff && sy
== 0 && ex
== 0)
800 sx
= ex
= sy
= ey
= 0;
803 * Increment the number of glyphs generated.
808 * Test to see if the font is going to be monowidth or not by
809 * comparing the current glyph width against the last one.
811 if (ismono
&& (ex
- sx
) + 1 != wd
)
815 * Adjust the font bounding box.
819 x_off
= sx
- (xoff
>> 6);
820 y_off
= ey
- (yoff
>> 6);
822 bbx
.maxas
= MAX(bbx
.maxas
, ht
+ y_off
);
823 bbx
.maxds
= MAX(bbx
.maxds
, -y_off
);
824 bbx
.rbearing
= wd
+ x_off
;
825 bbx
.maxrb
= MAX(bbx
.maxrb
, bbx
.rbearing
);
826 bbx
.minlb
= MIN(bbx
.minlb
, x_off
);
827 bbx
.maxlb
= MAX(bbx
.maxlb
, x_off
);
830 * Add to the average width accumulator.
835 * Print the bitmap header.
837 fprintf(tmp
, "STARTCHAR %04lX\nENCODING %ld\n", code
,
838 (long) remapped_code
);
839 fprintf(tmp
, "SWIDTH %hd 0\n", swidth
);
840 fprintf(tmp
, "DWIDTH %hd 0\n", dwidth
);
841 fprintf(tmp
, "BBX %hd %hd %hd %hd\n", wd
, ht
, x_off
, y_off
);
844 * Check for an error return here in case the temporary file system
845 * fills up or the file is deleted while it is being used.
847 eof
= fprintf(tmp
, "BITMAP\n");
850 * Now collect the bits so they can be printed.
852 for (miny
= sy
; eof
!= EOF
&& miny
>= ey
; miny
--) {
853 for (idx
= 0, minx
= sx
; eof
!= EOF
&& minx
<= ex
; minx
++) {
854 if (minx
> sx
&& ((minx
- sx
) & 7) == 0) {
856 * Print the next byte.
858 eof
= fprintf(tmp
, "%02lX", idx
& 0xff);
861 if (bmap
[(miny
* raster
.cols
) + (minx
>> 3)] &
862 (0x80 >> (minx
& 7)))
863 idx
|= 0x80 >> ((minx
- sx
) & 7);
867 * Because of the structure of the loop, the last byte should
870 fprintf(tmp
, "%02lX\n", idx
& 0xff);
873 fprintf(tmp
, "ENDCHAR\n");
879 * If a write error occured, delete the temporary file and issue an error
883 (void) unlink(tmpfile
);
884 fprintf(stderr
, "%s: problem writing to temporary file '%s'.\n",
887 free((char *) raster
.bitmap
);
892 * If no characters were generated, just unlink the temp file and issue a
896 (void) unlink(tmpfile
);
897 fprintf(stderr
, "%s: no glyphs generated from '%s'.\n", prog
, iname
);
899 free((char *) raster
.bitmap
);
904 * Reopen the temporary file so it can be copied to the actual output
907 if ((tmp
= fopen(tmpfile
, "r")) == 0) {
909 * Unable to open the file for read, so attempt to delete it and issue
912 (void) unlink(tmpfile
);
913 fprintf(stderr
, "%s: unable to open temporary file '%s' for read.\n",
916 free((char *) raster
.bitmap
);
921 * Free up the raster storage.
924 free((char *) raster
.bitmap
);
927 * Calculate the average width.
929 aw
= (TT_Long
) ((((double) aw
/ (double) ng
) + 0.5) * 10.0);
932 * Generate the XLFD font name.
934 make_xlfd_name(xlfd
, aw
, ismono
);
937 * Start writing the font out.
939 fprintf(out
, "STARTFONT 2.1\n");
942 * Add the vanity comments.
944 fprintf(out
, "COMMENT\n");
945 fprintf(out
, "COMMENT Converted from TrueType font \"%s\" by \"%s %s\".\n",
946 iname
, prog
, TTF2BDF_VERSION
);
947 fprintf(out
, "COMMENT\n");
949 fprintf(out
, "FONT %s\n", xlfd
);
950 fprintf(out
, "SIZE %d %d %d\n", point_size
, hres
, vres
);
953 * Generate the font bounding box.
955 fprintf(out
, "FONTBOUNDINGBOX %hd %hd %hd %hd\n",
956 bbx
.maxrb
- bbx
.minlb
, bbx
.maxas
+ bbx
.maxds
,
957 bbx
.minlb
, -bbx
.maxds
);
960 * Print the properties.
962 fprintf(out
, "STARTPROPERTIES %hd\n", 19);
965 * Print the font properties from the XLFD name.
967 for (i
= 0, xp
= xlfd
; i
< 14; i
++) {
969 * Print the XLFD property name.
971 fprintf(out
, "%s ", xlfd_props
[i
]);
974 * Make sure the ATOM properties are wrapped in double quotes.
976 if (i
< 6 || i
== 10 || i
> 11)
980 * Skip the leading '-' in the XLFD name.
985 * Skip until the next '-' or NULL.
987 for (; *xp
&& *xp
!= '-'; xp
++)
991 * Make sure the ATOM properties are wrapped in double quotes.
993 if (i
< 6 || i
== 10 || i
> 11)
1000 * Make sure to add the FONT_ASCENT and FONT_DESCENT properties
1001 * because X11 can not live without them.
1003 fprintf(out
, "FONT_ASCENT %hd\nFONT_DESCENT %hd\n",
1004 (properties
.horizontal
->Ascender
* imetrics
.y_ppem
) / upm
,
1005 -((properties
.horizontal
->Descender
* imetrics
.y_ppem
) / upm
));
1008 * Get the copyright string from the font.
1010 (void) ttf_get_english_name(xlfd
, TTF_COPYRIGHT
, 0);
1011 fprintf(out
, "COPYRIGHT \"%s\"\n", xlfd
);
1014 * Last, print the two user-defined properties _TTF_FONTFILE and
1015 * _TTF_PSNAME. _TTF_FONTFILE provides a reference to the original TT
1016 * font file which some systems can take advantage of, and _TTF_PSNAME
1017 * provides the Postscript name of the font if it exists.
1019 (void) ttf_get_english_name(xlfd
, TTF_PSNAME
, 0);
1020 fprintf(out
, "_TTF_FONTFILE \"%s\"\n_TTF_PSNAME \"%s\"\n", iname
, xlfd
);
1022 fprintf(out
, "ENDPROPERTIES\n");
1025 * Print the actual number of glyphs to the output file.
1027 eof
= fprintf(out
, "CHARS %ld\n", ng
);
1030 * Copy the temporary file to the output file.
1032 while (eof
!= EOF
&& (ng
= fread(iobuf
, 1, TTF2BDF_IOBUFSIZ
, tmp
))) {
1033 if (fwrite(iobuf
, 1, ng
, out
) == 0)
1038 * Close the temporary file and delete it.
1041 (void) unlink(tmpfile
);
1044 * If an error occured when writing to the output file, issue a warning
1048 fprintf(stderr
, "%s: problem writing to output file '%s'.\n",
1050 if (raster
.size
> 0)
1051 free((char *) raster
.bitmap
);
1056 * End the font and do memory cleanup on the glyph and raster structures.
1058 eof
= fprintf(out
, "ENDFONT\n");
1065 generate_bdf(FILE *out
, char *iname
, char *oname
)
1067 generate_bdf(out
, iname
, oname
)
1069 char *iname
, *oname
;
1076 * Get the requested cmap.
1078 for (i
= 0; i
< TT_Get_CharMap_Count(face
); i
++) {
1079 if (!TT_Get_CharMap_ID(face
, i
, &p
, &e
) &&
1080 p
== pid
&& e
== eid
)
1083 if (i
== TT_Get_CharMap_Count(face
) && pid
== 3 && eid
== 1) {
1085 * Make a special case when this fails with pid == 3 and eid == 1.
1086 * Change to eid == 0 and try again. This captures the two possible
1087 * cases for MS fonts. Some other method should be used to cycle
1088 * through all the alternatives later.
1090 for (i
= 0; i
< TT_Get_CharMap_Count(face
); i
++) {
1091 if (!TT_Get_CharMap_ID(face
, i
, &p
, &e
) &&
1095 if (i
< TT_Get_CharMap_Count(face
)) {
1096 if (!TT_Get_CharMap(face
, i
, &cmap
))
1103 * A CMap was found for the platform and encoding IDs.
1105 if (i
< TT_Get_CharMap_Count(face
) && TT_Get_CharMap(face
, i
, &cmap
))
1111 if (nocmap
&& verbose
) {
1113 "%s: no character map for platform %d encoding %d. ",
1115 fprintf(stderr
, "Generating all glyphs.\n");
1119 * Now go through and generate the glyph bitmaps themselves.
1121 return generate_font(out
, iname
, oname
);
1124 #define isdig(cc) ((cc) >= '0' && (cc) <= '9')
1127 * Routine to parse a subset specification supplied on the command line.
1128 * The syntax for this specification is the same as the syntax used for
1129 * the XLFD font names (XLFD documentation, page 9).
1133 * "60 70 80_90" means the glyphs at codes 60, 70, and between 80 and
1138 parse_subset(char *s
)
1147 * Make sure to clear the flag and bitmap in case more than one subset is
1148 * specified on the command line.
1152 (void) memset((char *) subset
, 0, sizeof(unsigned long) * 2048);
1156 * Collect the next code value.
1158 for (l
= r
= 0; *s
&& isdig(*s
); s
++)
1159 l
= (l
* 10) + (*s
- '0');
1162 * If the next character is an '_', advance and collect the end of the
1167 for (; *s
&& isdig(*s
); s
++)
1168 r
= (r
* 10) + (*s
- '0');
1173 * Add the range just collected to the subset bitmap and set the flag
1174 * that indicates a subset is wanted.
1176 for (; l
<= r
; l
++) {
1178 subset
[l
>> 5] |= (1 << (l
& 31));
1184 * Skip all non-digit characters.
1186 while (*s
&& !isdig(*s
))
1199 fprintf(stderr
, "Usage: %s [options below] font.ttf\n", prog
);
1200 fprintf(stderr
, "-h\t\tThis message.\n");
1201 fprintf(stderr
, "-v\t\tPrint warning messages during conversion.\n");
1203 "-l \"subset\"\tSpecify a subset of glyphs to generate.\n");
1204 fprintf(stderr
, "-m mapfile\tGlyph reencoding file.\n");
1205 fprintf(stderr
, "-n\t\tTurn off glyph hinting.\n");
1207 "-c c\t\tSet the character spacing (default: from font).\n");
1209 "-f name\t\tSet the foundry name (default: freetype).\n");
1211 "-t name\t\tSet the typeface name (default: from font).\n");
1212 fprintf(stderr
, "-w name\t\tSet the weight name (default: Medium).\n");
1213 fprintf(stderr
, "-s name\t\tSet the slant name (default: R).\n");
1214 fprintf(stderr
, "-k name\t\tSet the width name (default: Normal).\n");
1216 "-d name\t\tSet the additional style name (default: empty).\n");
1217 fprintf(stderr
, "-u char\t\tSet the character to replace '-' in names ");
1218 fprintf(stderr
, "(default: space).\n");
1220 "-pid id\t\tSet the platform ID for encoding (default: %d).\n",
1221 DEFAULT_PLATFORM_ID
);
1223 "-eid id\t\tSet the encoding ID for encoding (default: %d).\n",
1224 DEFAULT_ENCODING_ID
);
1225 fprintf(stderr
, "-p n\t\tSet the point size (default: %dpt).\n",
1226 DEFAULT_POINT_SIZE
);
1227 fprintf(stderr
, "-r n\t\tSet the horizontal and vertical resolution ");
1228 fprintf(stderr
, "(default: %ddpi).\n", DEFAULT_RESOLUTION
);
1229 fprintf(stderr
, "-rh n\t\tSet the horizontal resolution ");
1230 fprintf(stderr
, "(default: %ddpi)\n", DEFAULT_RESOLUTION
);
1231 fprintf(stderr
, "-rv n\t\tSet the vertical resolution ");
1232 fprintf(stderr
, "(default: %ddpi)\n", DEFAULT_RESOLUTION
);
1234 "-o outfile\tSet the output filename (default: stdout).\n");
1240 main(int argc
, char *argv
[])
1248 char *infile
, *outfile
, *iname
, *oname
;
1251 if ((prog
= strrchr(argv
[0], '/')))
1257 infile
= outfile
= 0;
1263 if (argv
[0][0] == '-') {
1264 switch (argv
[0][1]) {
1271 parse_subset(argv
[0]);
1274 load_flags
&= ~TTLOAD_HINT_GLYPH
;
1279 spacing
= argv
[0][0];
1284 face_name
= argv
[0];
1289 weight_name
= argv
[0];
1294 slant_name
= argv
[0];
1299 width_name
= argv
[0];
1304 style_name
= argv
[0];
1309 foundry_name
= argv
[0];
1314 dashchar
= argv
[0][0];
1320 if (res
== 'i' || res
== 'I')
1322 * Set the platform ID.
1324 pid
= atoi(argv
[0]);
1327 * Set the point size.
1329 point_size
= atoi(argv
[0]);
1333 * Set the encoding ID.
1337 eid
= atoi(argv
[0]);
1341 * Set the horizontal and vertical resolutions.
1343 if (argv
[0][2] == 'h')
1344 hres
= atoi(argv
[1]);
1345 else if (argv
[0][2] == 'v')
1346 vres
= atoi(argv
[1]);
1348 hres
= vres
= atoi(argv
[1]);
1354 * Try to load a remap table.
1360 * Always reset the `do_remap' variable here in case more than
1361 * one map file appears on the command line.
1364 if ((mapin
= fopen(argv
[0], "r")) == 0)
1365 fprintf(stderr
, "%s: unable to open the remap table '%s'.\n",
1368 if (ttf2bdf_load_map(mapin
) < 0) {
1370 "%s: problem loading remap table '%s'.\n",
1380 * Set the output file name.
1391 * Set the input file name.
1400 * Validate the values passed on the command line.
1403 fprintf(stderr
, "%s: no input file provided.\n", prog
);
1407 * Set the input filename that will be passed to the generator
1410 if ((iname
= strrchr(infile
, '/')))
1416 * Check the platform and encoding IDs.
1418 if (pid
< 0 || pid
> 255) {
1419 fprintf(stderr
, "%s: invalid platform ID '%d'.\n", prog
, pid
);
1422 if (eid
< 0 || eid
> 65535) {
1423 fprintf(stderr
, "%s: invalid encoding ID '%d'.\n", prog
, eid
);
1428 * Arbitrarily limit the point size to a minimum of 2pt and maximum of
1431 if (point_size
< 2 || point_size
> 256) {
1432 fprintf(stderr
, "%s: invalid point size '%dpt'.\n", prog
, point_size
);
1437 * Arbitrarily limit the resolutions to a minimum of 10dpi and a maximum
1440 if (hres
< 10 || hres
> 1200) {
1441 fprintf(stderr
, "%s: invalid horizontal resolution '%ddpi'.\n",
1445 if (vres
< 10 || vres
> 1200) {
1446 fprintf(stderr
, "%s: invalid vertical resolution '%ddpi'.\n",
1452 * Open the output file if specified.
1456 * Attempt to open the output file.
1458 if ((out
= fopen(outfile
, "w")) == 0) {
1459 fprintf(stderr
, "%s: unable to open the output file '%s'.\n",
1464 * Set the output filename to be passed to the generator routine.
1466 if ((oname
= strrchr(outfile
, '/')))
1472 * Set the default output file name to <stdout>.
1477 * Intialize Freetype.
1479 if ((res
= TT_Init_FreeType(&engine
))) {
1481 * Close the output file.
1483 if (out
!= stdout
) {
1485 (void) unlink(outfile
);
1487 fprintf(stderr
, "%s[%d]: unable to initialize renderer.\n",
1493 * Open the input file.
1495 if ((res
= TT_Open_Face(engine
, infile
, &face
))) {
1496 if (out
!= stdout
) {
1498 (void) unlink(outfile
);
1500 fprintf(stderr
, "%s[%d]: unable to open input file '%s'.\n",
1506 * Create a new instance.
1508 if ((res
= TT_New_Instance(face
, &instance
))) {
1509 (void) TT_Close_Face(face
);
1510 if (out
!= stdout
) {
1512 (void) unlink(outfile
);
1514 fprintf(stderr
, "%s[%d]: unable to create instance.\n",
1520 * Set the instance resolution and point size and the relevant
1523 (void) TT_Set_Instance_Resolutions(instance
, hres
, vres
);
1524 (void) TT_Set_Instance_CharSize(instance
, point_size
*64);
1525 (void) TT_Get_Instance_Metrics(instance
, &imetrics
);
1528 * Get the face properties and set the global units per em value for
1531 (void) TT_Get_Face_Properties(face
, &properties
);
1532 upm
= properties
.header
->Units_Per_EM
;
1535 * Create a new glyph container.
1537 if ((res
= TT_New_Glyph(face
, &glyph
))) {
1538 (void) TT_Done_Instance(instance
);
1539 (void) TT_Close_Face(face
);
1540 if (out
!= stdout
) {
1542 (void) unlink(outfile
);
1544 fprintf(stderr
, "%s[%d]: unable to create glyph.\n",
1550 * Generate the BDF font from the TrueType font.
1552 res
= generate_bdf(out
, iname
, oname
);
1555 * Free up the mapping table if one was loaded.
1560 * Close the input and output files.
1562 (void) TT_Close_Face(face
);
1563 if (out
!= stdout
) {
1567 * An error occured when generating the font, so delete the
1570 (void) unlink(outfile
);
1574 * Shut down the renderer.
1576 (void) TT_Done_FreeType(engine
);