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: ttf2bdf.c,v 1.25 1999/10/21 16:31:54 mleisher Exp $";
27
static char rcsid[] = "Id: ttf2bdf.c,v 1.25 1999/10/21 16:31:54 mleisher Exp $";
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);