contrib/OWB: add correct SDL dependency, fix compilers used
[AROS-Contrib.git] / freetype1 / contrib / ttf2bdf / ttf2bdf.c
blobaf17a75d524fa8e8dd6f81c72cc91699ace3a5be
1 /*
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.
23 #ifndef lint
24 #ifdef __GNUC__
25 static char rcsid[] __attribute__ ((unused)) = "$Id$";
26 #else
27 static char rcsid[] = "$Id$";
28 #endif
29 #endif
31 #include <stdio.h>
33 #ifdef WIN32
34 #include <windows.h>
35 #else
36 #include <stdlib.h>
37 #include <unistd.h>
38 #endif
40 #include <string.h>
42 #include "freetype.h"
45 * Include the remapping support.
47 #include "remap.h"
49 /**************************************************************************
51 * Macros.
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
65 #endif
67 #ifndef DEFAULT_ENCODING_ID
68 #define DEFAULT_ENCODING_ID 1
69 #endif
71 #ifndef DEFAULT_POINT_SIZE
72 #define DEFAULT_POINT_SIZE 12
73 #endif
75 #ifndef DEFAULT_RESOLUTION
76 #define DEFAULT_RESOLUTION 100
77 #endif
80 * Used as a fallback for XLFD names where the character set/encoding can not
81 * be determined.
83 #ifndef DEFAULT_XLFD_CSET
84 #define DEFAULT_XLFD_CSET "-FontSpecific-0"
85 #endif
88 * nameID macros for getting strings from the TT font.
90 #define TTF_COPYRIGHT 0
91 #define TTF_TYPEFACE 1
92 #define TTF_PSNAME 6
94 #ifndef MAX
95 #define MAX(h,i) ((h) > (i) ? (h) : (i))
96 #endif
98 #ifndef MIN
99 #define MIN(l,o) ((l) < (o) ? (l) : (o))
100 #endif
102 /**************************************************************************
104 * General globals set from command line.
106 **************************************************************************/
109 * The program name.
111 static char *prog;
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,
168 * m = monospace).
170 static int spacing = 0;
173 * The dash character to use in the names retrieved from the font. Default is
174 * the space.
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
187 * reencode the font.
189 static int do_remap = 0;
191 /**************************************************************************
193 * Internal globals.
195 **************************************************************************/
198 * Structure used for calculating the font bounding box as the glyphs are
199 * generated.
201 typedef struct {
202 short minlb;
203 short maxlb;
204 short maxrb;
205 short maxas;
206 short maxds;
207 short rbearing;
208 } bbx_t;
210 static bbx_t bbx;
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
230 * for BDF glyphs.
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",
246 "-MacUninterp-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[] = {
274 "FOUNDRY",
275 "FAMILY_NAME",
276 "WEIGHT_NAME",
277 "SLANT",
278 "SETWIDTH_NAME",
279 "ADD_STYLE_NAME",
280 "PIXEL_SIZE",
281 "POINT_SIZE",
282 "RESOLUTION_X",
283 "RESOLUTION_Y",
284 "SPACING",
285 "AVERAGE_WIDTH",
286 "CHARSET_REGISTRY",
287 "CHARSET_ENCODING",
290 /**************************************************************************
292 * Freetype globals.
294 **************************************************************************/
296 static TT_Engine engine;
297 static TT_Face face;
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.
331 static int
332 #ifdef __STDC__
333 ttf_get_english_name(char *name, int nameID, int dash)
334 #else
335 ttf_get_english_name(name, nameID, dash)
336 char *name;
337 int nameID, dash;
338 #endif
340 TT_UShort slen;
341 int i, j, encid, nrec;
342 unsigned short nrPlatformID, nrEncodingID, nrLanguageID, nrNameID;
343 char *s;
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);
361 break;
365 if (i < nrec) {
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) {
372 if (dash)
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')
376 i += 2;
377 *name++ = ' ';
378 *name++ = ' ';
379 } else
380 *name++ = s[i];
382 *name = 0;
383 return (slen >> 1);
388 * No MS English name found, attempt to find an Apple Unicode English
389 * name.
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);
397 break;
401 if (i < nrec) {
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) {
408 if (dash)
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')
412 i += 2;
413 *name++ = ' ';
414 *name++ = ' ';
415 } else
416 *name++ = s[i];
418 *name = 0;
419 return (slen >> 1);
422 return 0;
425 /**************************************************************************
427 * General code.
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.
435 static void
436 #ifdef __STDC__
437 make_xlfd_name(char *name, TT_Long awidth, int ismono)
438 #else
439 make_xlfd_name(name, awidth, ismono)
440 char *name;
441 TT_Long awidth;
442 int ismono;
443 #endif
445 TT_Long i;
446 TT_ULong val;
447 char *r, *e;
448 double dr, dp;
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");
457 name += 9;
458 } else {
459 *(name++)='-';
460 strcpy(name,foundry_name);
461 name+=strlen(foundry_name);
465 * Add the typeface name from the font. The fallback default will be
466 * "Unknown".
468 *name++ = '-';
469 if (face_name == 0) {
470 if((i = ttf_get_english_name(name, TTF_TYPEFACE, dashchar)))
471 name += i;
472 else {
473 (void) strcpy(name, "Unknown");
474 name += 7;
476 } else {
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;
487 } else {
488 if (properties.os2->fsSelection & 0x20) {
489 (void) strcpy(name, "-Bold");
490 name += 5;
491 } else {
492 (void) strcpy(name, "-Medium");
493 name += 7;
498 * Add the slant name. The default will be 'R'.
500 if (slant_name) {
501 sprintf(name, "-%s", slant_name);
502 name += strlen(slant_name) + 1;
503 } else {
504 *name++ = '-';
505 if (properties.os2->fsSelection & 0x01)
506 *name++ = 'I';
507 else
508 *name++ = 'R';
512 * Default the setwidth name to "Normal" but user can specify one.
514 if (width_name == 0) {
515 (void) strcpy(name, "-Normal");
516 name += 7;
517 } else {
518 *(name++)='-';
519 strcpy(name,width_name);
520 name+=strlen(width_name);
524 * Default the additional style name to NULL but user can specify one.
526 *name++ = '-';
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.
535 dr = (double) vres;
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);
545 switch (spacing) {
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;
553 * Set the spacing.
555 if (!spacing)
556 spacing = (ismono) ? 'M' : 'P';
557 *name++ = '-';
558 *name++ = spacing;
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);
573 return;
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);
583 else {
585 * Finally, determine the character set registry and encoding from the
586 * platform and encoding ID.
588 switch (pid) {
589 case 0:
591 * Apple Unicode platform, so "Unicode-2.0" is the default.
593 (void) strcpy(name, "-Unicode-2.0");
594 break;
595 case 1:
597 * Macintosh platform, so choose from the Macintosh encoding
598 * strings.
600 if (eid < 0 || eid >= num_mac_encodings)
601 (void) strcpy(name, DEFAULT_XLFD_CSET);
602 else
603 (void) strcpy(name, mac_encodings[eid]);
604 break;
605 case 2:
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);
611 else
612 (void) strcpy(name, iso_encodings[eid]);
613 break;
614 case 3:
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);
620 else
621 (void) strcpy(name, ms_encodings[eid]);
622 break;
627 static int
628 #ifdef __STDC__
629 generate_font(FILE *out, char *iname, char *oname)
630 #else
631 generate_font(out, iname, oname)
632 FILE *out;
633 char *iname, *oname;
634 #endif
636 int eof, ismono, i;
637 FILE *tmp;
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;
643 unsigned char *bmap;
644 double dw;
645 char *xp, xlfd[256];
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)
653 tmpdir = "/tmp";
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",
657 prog, tmpfile);
658 return -1;
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
681 * monowidth font.
683 wd = 0xffff;
684 ismono = 1;
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;
692 raster.width = maxx;
693 raster.rows = maxy;
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))
706 continue;
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
711 * work.
713 if (do_subset && remapped_code > maxcode)
714 break;
717 * If a subset is being generated and the index is not in the subset
718 * bitmap, just continue.
720 if (do_subset &&
721 !(subset[remapped_code >> 5] & (1 << (remapped_code & 31))))
722 continue;
724 if (nocmap) {
725 if (code >= properties.num_Glyphs)
728 * At this point, all the glyphs are done.
730 break;
731 idx = code;
732 } else
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
738 * continue.
741 if (idx <= 0 || TT_Load_Glyph(instance, glyph, idx, load_flags))
742 continue;
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))
762 continue;
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!
776 sx = ey = 0xffff;
777 sy = ex = 0;
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))) {
783 if (minx < sx)
784 sx = minx;
785 if (minx > ex)
786 ex = minx;
787 if (miny > sy)
788 sy = miny;
789 if (miny < ey)
790 ey = miny;
796 * If the glyph is actually an empty bitmap, set the size to 0 all
797 * around.
799 if (sx == 0xffff && ey == 0xffff && sy == 0 && ex == 0)
800 sx = ex = sy = ey = 0;
803 * Increment the number of glyphs generated.
805 ng++;
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)
812 ismono = 0;
815 * Adjust the font bounding box.
817 wd = (ex - sx) + 1;
818 ht = (sy - ey) + 1;
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.
832 aw += wd;
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);
859 idx = 0;
861 if (bmap[(miny * raster.cols) + (minx >> 3)] &
862 (0x80 >> (minx & 7)))
863 idx |= 0x80 >> ((minx - sx) & 7);
865 if (eof != EOF)
867 * Because of the structure of the loop, the last byte should
868 * always be printed.
870 fprintf(tmp, "%02lX\n", idx & 0xff);
872 if (eof != EOF)
873 fprintf(tmp, "ENDCHAR\n");
876 fclose(tmp);
879 * If a write error occured, delete the temporary file and issue an error
880 * message.
882 if (eof == EOF) {
883 (void) unlink(tmpfile);
884 fprintf(stderr, "%s: problem writing to temporary file '%s'.\n",
885 prog, tmpfile);
886 if (raster.size > 0)
887 free((char *) raster.bitmap);
888 return -1;
892 * If no characters were generated, just unlink the temp file and issue a
893 * warning.
895 if (ng == 0) {
896 (void) unlink(tmpfile);
897 fprintf(stderr, "%s: no glyphs generated from '%s'.\n", prog, iname);
898 if (raster.size > 0)
899 free((char *) raster.bitmap);
900 return -1;
904 * Reopen the temporary file so it can be copied to the actual output
905 * file.
907 if ((tmp = fopen(tmpfile, "r")) == 0) {
909 * Unable to open the file for read, so attempt to delete it and issue
910 * an error message.
912 (void) unlink(tmpfile);
913 fprintf(stderr, "%s: unable to open temporary file '%s' for read.\n",
914 prog, tmpfile);
915 if (raster.size > 0)
916 free((char *) raster.bitmap);
917 return -1;
921 * Free up the raster storage.
923 if (raster.size > 0)
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)
977 putc('"', out);
980 * Skip the leading '-' in the XLFD name.
982 xp++;
985 * Skip until the next '-' or NULL.
987 for (; *xp && *xp != '-'; xp++)
988 putc(*xp, out);
991 * Make sure the ATOM properties are wrapped in double quotes.
993 if (i < 6 || i == 10 || i > 11)
994 putc('"', out);
996 putc('\n', out);
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)
1034 eof = EOF;
1038 * Close the temporary file and delete it.
1040 fclose(tmp);
1041 (void) unlink(tmpfile);
1044 * If an error occured when writing to the output file, issue a warning
1045 * and return.
1047 if (eof == EOF) {
1048 fprintf(stderr, "%s: problem writing to output file '%s'.\n",
1049 prog, oname);
1050 if (raster.size > 0)
1051 free((char *) raster.bitmap);
1052 return -1;
1056 * End the font and do memory cleanup on the glyph and raster structures.
1058 eof = fprintf(out, "ENDFONT\n");
1060 return eof;
1063 static int
1064 #ifdef __STDC__
1065 generate_bdf(FILE *out, char *iname, char *oname)
1066 #else
1067 generate_bdf(out, iname, oname)
1068 FILE *out;
1069 char *iname, *oname;
1070 #endif
1072 TT_Long i;
1073 TT_UShort p, e;
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)
1081 break;
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) &&
1092 p == pid && e == 0)
1093 break;
1095 if (i < TT_Get_CharMap_Count(face)) {
1096 if (!TT_Get_CharMap(face, i, &cmap))
1097 eid = 0;
1098 else
1099 nocmap = 1;
1101 } else {
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))
1106 nocmap = 1;
1107 else
1108 nocmap = 0;
1111 if (nocmap && verbose) {
1112 fprintf(stderr,
1113 "%s: no character map for platform %d encoding %d. ",
1114 prog, pid, eid);
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).
1131 * Example:
1133 * "60 70 80_90" means the glyphs at codes 60, 70, and between 80 and
1134 * 90 inclusive.
1136 static void
1137 #ifdef __STDC__
1138 parse_subset(char *s)
1139 #else
1140 parse_subset(s)
1141 char *s;
1142 #endif
1144 long l, r;
1147 * Make sure to clear the flag and bitmap in case more than one subset is
1148 * specified on the command line.
1150 maxcode = 0;
1151 do_subset = 0;
1152 (void) memset((char *) subset, 0, sizeof(unsigned long) * 2048);
1154 while (*s) {
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
1163 * specified range.
1165 if (*s == '_') {
1166 s++;
1167 for (; *s && isdig(*s); s++)
1168 r = (r * 10) + (*s - '0');
1169 } else
1170 r = l;
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++) {
1177 do_subset = 1;
1178 subset[l >> 5] |= (1 << (l & 31));
1179 if (l > maxcode)
1180 maxcode = l;
1184 * Skip all non-digit characters.
1186 while (*s && !isdig(*s))
1187 s++;
1191 static void
1192 #ifdef __STDC__
1193 usage(int eval)
1194 #else
1195 usage(eval)
1196 int eval;
1197 #endif
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");
1202 fprintf(stderr,
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");
1206 fprintf(stderr,
1207 "-c c\t\tSet the character spacing (default: from font).\n");
1208 fprintf(stderr,
1209 "-f name\t\tSet the foundry name (default: freetype).\n");
1210 fprintf(stderr,
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");
1215 fprintf(stderr,
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");
1219 fprintf(stderr,
1220 "-pid id\t\tSet the platform ID for encoding (default: %d).\n",
1221 DEFAULT_PLATFORM_ID);
1222 fprintf(stderr,
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);
1233 fprintf(stderr,
1234 "-o outfile\tSet the output filename (default: stdout).\n");
1235 exit(eval);
1239 #ifdef __STDC__
1240 main(int argc, char *argv[])
1241 #else
1242 main(argc, argv)
1243 int argc;
1244 char *argv[];
1245 #endif
1247 int res;
1248 char *infile, *outfile, *iname, *oname;
1249 FILE *out, *mapin;
1251 if ((prog = strrchr(argv[0], '/')))
1252 prog++;
1253 else
1254 prog = argv[0];
1256 out = stdout;
1257 infile = outfile = 0;
1259 argc--;
1260 argv++;
1262 while (argc > 0) {
1263 if (argv[0][0] == '-') {
1264 switch (argv[0][1]) {
1265 case 'v': case 'V':
1266 verbose = 1;
1267 break;
1268 case 'l': case 'L':
1269 argc--;
1270 argv++;
1271 parse_subset(argv[0]);
1272 break;
1273 case 'n': case 'N':
1274 load_flags &= ~TTLOAD_HINT_GLYPH;
1275 break;
1276 case 'c': case 'C':
1277 argc--;
1278 argv++;
1279 spacing = argv[0][0];
1280 break;
1281 case 't': case 'T':
1282 argc--;
1283 argv++;
1284 face_name = argv[0];
1285 break;
1286 case 'w': case 'W':
1287 argc--;
1288 argv++;
1289 weight_name = argv[0];
1290 break;
1291 case 's': case 'S':
1292 argc--;
1293 argv++;
1294 slant_name = argv[0];
1295 break;
1296 case 'k': case 'K':
1297 argc--;
1298 argv++;
1299 width_name = argv[0];
1300 break;
1301 case 'd': case 'D':
1302 argc--;
1303 argv++;
1304 style_name = argv[0];
1305 break;
1306 case 'f': case 'F':
1307 argc--;
1308 argv++;
1309 foundry_name = argv[0];
1310 break;
1311 case 'u': case 'U':
1312 argc--;
1313 argv++;
1314 dashchar = argv[0][0];
1315 break;
1316 case 'p': case 'P':
1317 res = argv[0][2];
1318 argc--;
1319 argv++;
1320 if (res == 'i' || res == 'I')
1322 * Set the platform ID.
1324 pid = atoi(argv[0]);
1325 else
1327 * Set the point size.
1329 point_size = atoi(argv[0]);
1330 break;
1331 case 'e': case 'E':
1333 * Set the encoding ID.
1335 argc--;
1336 argv++;
1337 eid = atoi(argv[0]);
1338 break;
1339 case 'r':
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]);
1347 else
1348 hres = vres = atoi(argv[1]);
1349 argc--;
1350 argv++;
1351 break;
1352 case 'm': case 'M':
1354 * Try to load a remap table.
1356 argc--;
1357 argv++;
1360 * Always reset the `do_remap' variable here in case more than
1361 * one map file appears on the command line.
1363 do_remap = 0;
1364 if ((mapin = fopen(argv[0], "r")) == 0)
1365 fprintf(stderr, "%s: unable to open the remap table '%s'.\n",
1366 prog, argv[0]);
1367 else {
1368 if (ttf2bdf_load_map(mapin) < 0) {
1369 fprintf(stderr,
1370 "%s: problem loading remap table '%s'.\n",
1371 prog, argv[0]);
1372 do_remap = 0;
1373 } else
1374 do_remap = 1;
1375 fclose(mapin);
1377 break;
1378 case 'o': case 'O':
1380 * Set the output file name.
1382 argc--;
1383 argv++;
1384 outfile = argv[0];
1385 break;
1386 default:
1387 usage(1);
1389 } else
1391 * Set the input file name.
1393 infile = argv[0];
1395 argc--;
1396 argv++;
1400 * Validate the values passed on the command line.
1402 if (infile == 0) {
1403 fprintf(stderr, "%s: no input file provided.\n", prog);
1404 usage(1);
1407 * Set the input filename that will be passed to the generator
1408 * routine.
1410 if ((iname = strrchr(infile, '/')))
1411 iname++;
1412 else
1413 iname = 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);
1420 exit(1);
1422 if (eid < 0 || eid > 65535) {
1423 fprintf(stderr, "%s: invalid encoding ID '%d'.\n", prog, eid);
1424 exit(1);
1428 * Arbitrarily limit the point size to a minimum of 2pt and maximum of
1429 * 256pt.
1431 if (point_size < 2 || point_size > 256) {
1432 fprintf(stderr, "%s: invalid point size '%dpt'.\n", prog, point_size);
1433 exit(1);
1437 * Arbitrarily limit the resolutions to a minimum of 10dpi and a maximum
1438 * of 1200dpi.
1440 if (hres < 10 || hres > 1200) {
1441 fprintf(stderr, "%s: invalid horizontal resolution '%ddpi'.\n",
1442 prog, hres);
1443 exit(1);
1445 if (vres < 10 || vres > 1200) {
1446 fprintf(stderr, "%s: invalid vertical resolution '%ddpi'.\n",
1447 prog, vres);
1448 exit(1);
1452 * Open the output file if specified.
1454 if (outfile != 0) {
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",
1460 prog, outfile);
1461 exit(1);
1464 * Set the output filename to be passed to the generator routine.
1466 if ((oname = strrchr(outfile, '/')))
1467 oname++;
1468 else
1469 oname = outfile;
1470 } else
1472 * Set the default output file name to <stdout>.
1474 oname = "<stdout>";
1477 * Intialize Freetype.
1479 if ((res = TT_Init_FreeType(&engine))) {
1481 * Close the output file.
1483 if (out != stdout) {
1484 fclose(out);
1485 (void) unlink(outfile);
1487 fprintf(stderr, "%s[%d]: unable to initialize renderer.\n",
1488 prog, res);
1489 exit(1);
1493 * Open the input file.
1495 if ((res = TT_Open_Face(engine, infile, &face))) {
1496 if (out != stdout) {
1497 fclose(out);
1498 (void) unlink(outfile);
1500 fprintf(stderr, "%s[%d]: unable to open input file '%s'.\n",
1501 prog, res, infile);
1502 exit(1);
1506 * Create a new instance.
1508 if ((res = TT_New_Instance(face, &instance))) {
1509 (void) TT_Close_Face(face);
1510 if (out != stdout) {
1511 fclose(out);
1512 (void) unlink(outfile);
1514 fprintf(stderr, "%s[%d]: unable to create instance.\n",
1515 prog, res);
1516 exit(1);
1520 * Set the instance resolution and point size and the relevant
1521 * metrics.
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
1529 * convenience.
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) {
1541 fclose(out);
1542 (void) unlink(outfile);
1544 fprintf(stderr, "%s[%d]: unable to create glyph.\n",
1545 prog, res);
1546 exit(1);
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.
1557 ttf2bdf_free_map();
1560 * Close the input and output files.
1562 (void) TT_Close_Face(face);
1563 if (out != stdout) {
1564 fclose(out);
1565 if (res < 0)
1567 * An error occured when generating the font, so delete the
1568 * output file.
1570 (void) unlink(outfile);
1574 * Shut down the renderer.
1576 (void) TT_Done_FreeType(engine);
1578 exit(res);
1580 return 0;