]> git.kernelconcepts.de Git - gbdfed.git/blob - bdfotf.c
Fixup several compile faults due to changes in recent distributions,
[gbdfed.git] / bdfotf.c
1 /*
2  * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 /*
23  * Only compile this if the FreeType library is available.
24  */
25 #ifdef HAVE_FREETYPE
26
27 #include "bdfP.h"
28 #include FT_GLYPH_H
29 #include FT_SFNT_NAMES_H
30 #include FT_TRUETYPE_TABLES_H
31
32 #undef MAX
33 #define MAX(h, i) ((h) > (i) ? (h) : (i))
34
35 #undef MIN
36 #define MIN(l, o) ((l) < (o) ? (l) : (o))
37
38 /**************************************************************************
39  *
40  * Local variables.
41  *
42  **************************************************************************/
43
44 static char *platform_names[] = {
45     "Apple Unicode", "Macintosh", "ISO", "Microsoft", "Unknown"
46 };
47 static int nplatform_names =
48 sizeof(platform_names) / sizeof(platform_names[0]);
49
50 /*
51  * Mac encoding names used when creating the BDF XLFD font name and when
52  * selecting an encoding from a font.
53  */
54 static char *mac_encodings[] = {
55     "MacRoman",    "MacJapanese",   "MacChinese",   "MacKorean",
56     "MacArabic",   "MacHebrew",     "MacGreek",     "MacRussian",
57     "MacRSymbol",  "MacDevanagari", "MacGurmukhi",  "MacGujarati",
58     "MacOriya",    "MacBengali",    "MacTamil",     "MacTelugu",
59     "MacKannada",  "MacMalayalam",  "MacSinhalese", "MacBurmese",
60     "MacKhmer",    "MacThai",       "MacLaotian",   "MacGeorgian",
61     "MacArmenian", "MacMaldivian",  "MacTibetan",   "MacMongolian",
62     "MacGeez",     "MacSlavic",     "MacVietnamese","MacSindhi",
63     "MacUninterp"
64 };
65 static int nmac_encodings = sizeof(mac_encodings) / sizeof(mac_encodings[0]);
66
67 /*
68  * ISO encoding names used when creating the BDF XLFD font name and when
69  * selecting an encoding from a font.
70  */
71 static char *iso_encodings[] = {
72     "ASCII", "ISO10646", "ISO8859-1"
73 };
74 static int niso_encodings = sizeof(iso_encodings) / sizeof(iso_encodings[0]);
75
76 /*
77  * Microsoft encoding names used when creating the BDF XLFD font name and
78  * when selecting an encoding from a font.
79  */
80 static char *ms_encodings[] = {
81     "Symbol", "ISO10646", "ShiftJIS", "GB2312.1980", "Big5",
82     "KSC5601.1987", "KSC5601.1992"
83 };
84 static int nms_encodings = sizeof(ms_encodings) / sizeof(ms_encodings[0]);
85
86 /**************************************************************************
87  *
88  * API.
89  *
90  **************************************************************************/
91
92 /*
93  * Routine to get the platform name from the platform ID.
94  */
95 char *
96 bdfotf_platform_name(short pid)
97 {
98     return (pid < nplatform_names) ?
99         platform_names[pid] : platform_names[nplatform_names - 1];
100 }
101
102 /*
103  * Routine to get the encoding name from the platform and encoding IDs.
104  */
105 char *
106 bdfotf_encoding_name(short pid, short eid)
107 {
108     int nnames;
109     char **names;
110
111     switch (pid) {
112       case 0: return "ISO10646";
113       case 1:
114         nnames = nmac_encodings;
115         names = mac_encodings;
116         break;
117       case 2:
118         nnames = niso_encodings;
119         names = iso_encodings;
120         break;
121       case 3:
122         nnames = nms_encodings;
123         names = ms_encodings;
124         break;
125       default: return "Unknown";
126     }
127
128     return (eid < nnames) ? names[eid] : "Unknown";
129 }
130
131 /*
132  * A generic routine to get a name from the TT name table.  This routine
133  * always looks for English language names and checks three possibilities:
134  * 1. English names with the MS Unicode encoding ID.
135  * 2. English names with the MS unknown encoding ID.
136  * 3. English names with the Apple Unicode encoding ID.
137  *
138  * The particular name ID mut be provided (e.g. nameID = 0 for copyright
139  * string, nameID = 6 for Postscript name, nameID = 1 for typeface name.
140  *
141  * If the `dash_to_space' flag is set, all dashes (-) in the name will be
142  * replaced with spaces.
143  *
144  * Returns the number of bytes added.
145  */
146 int
147 bdfotf_get_english_string(FT_Face face, int nameID, int dash_to_space,
148                           char *name)
149 {
150     int j, encid;
151     FT_UInt i, nrec;
152     FT_SfntName sfntName;
153     unsigned char *s;
154     unsigned short slen;
155
156     nrec = FT_Get_Sfnt_Name_Count(face);
157
158     for (encid = 1, j = 0; j < 2; j++, encid--) {
159         /*
160          * Locate one of the MS English font names.
161          */
162         for (i = 0; i < nrec; i++) {
163            FT_Get_Sfnt_Name(face, i, &sfntName);
164            if (sfntName.platform_id == 3 &&
165                sfntName.encoding_id == encid &&
166                sfntName.name_id == nameID &&
167                (sfntName.language_id == 0x0409 ||
168                 sfntName.language_id == 0x0809 ||
169                 sfntName.language_id == 0x0c09 ||
170                 sfntName.language_id == 0x1009 ||
171                 sfntName.language_id == 0x1409 ||
172                 sfntName.language_id == 0x1809)) {
173                s = sfntName.string;
174                slen = sfntName.string_len;
175                break;
176            }
177         }
178
179         if (i < nrec) {
180             /*
181              * Found one of the MS English font names.  The name is by
182              * definition encoded in Unicode, so copy every second byte into
183              * the `name' parameter, assuming there is enough space.
184              */
185             for (i = 1; i < slen; i += 2) {
186                 if (dash_to_space)
187                   *name++ = (s[i] != '-') ? s[i] : ' ';
188                 else if (s[i] == '\r' || s[i] == '\n') {
189                     if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
190                       i += 2;
191                     *name++ = ' ';
192                     *name++ = ' ';
193                 } else
194                   *name++ = s[i];
195             }
196             *name = 0;
197             return (slen >> 1);
198         }
199     }
200
201     /*
202      * No MS English name found, attempt to find an Apple Unicode English
203      * name.
204      */
205     for (i = 0; i < nrec; i++) {
206         FT_Get_Sfnt_Name(face, i, &sfntName);
207         if (sfntName.platform_id == 0 && sfntName.language_id == 0 &&
208             sfntName.name_id == nameID) {
209             s = sfntName.string;
210             slen = sfntName.string_len;
211             break;
212         }
213     }
214
215     if (i < nrec) {
216         /*
217          * Found the Apple Unicode English name.  The name is by definition
218          * encoded in Unicode, so copy every second byte into the `name'
219          * parameter, assuming there is enough space.
220          */
221         for (i = 1; i < slen; i += 2) {
222             if (dash_to_space)
223               *name++ = (s[i] != '-') ? s[i] : ' ';
224             else if (s[i] == '\r' || s[i] == '\n') {
225                 if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
226                   i += 2;
227                 *name++ = ' ';
228                 *name++ = ' ';
229             } else
230               *name++ = s[i];
231         }
232         *name = 0;
233         return (slen >> 1);
234     }
235
236     return 0;
237 }
238
239 static int
240 _bdfotf_generate(FT_Face face, int nocmap, bdf_options_t *opts,
241                  bdf_callback_t callback, void *data, bdf_font_t *fp)
242 {
243     int ismono;
244     int awidth, code, idx;
245     short maxrb, maxlb, minlb, y, x;
246     short x_off, y_off, maxas, maxds;
247     int upm, bpr, wd, ht, sx, ex, sy, ey;
248     unsigned char *bmap;
249     bdf_glyph_t *gp;
250     double swscale;
251     bdf_callback_struct_t cb;
252     bdf_property_t prop;
253
254     FT_Size_Metrics imetrics;
255     TT_HoriHeader *horizontal = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
256
257     /*
258      * Set the instance resolution and point size.
259      */
260     FT_Set_Char_Size(face, 0, opts->point_size * 64,
261                      opts->resolution_x, opts->resolution_y);
262     imetrics = face->size->metrics;
263
264     /*
265      * Set up the initialization callback.
266      */
267     if (callback != 0) {
268         cb.reason = BDF_LOAD_START;
269         cb.current = 0;
270         cb.total = face->num_glyphs;
271         (*callback)(&cb, data);
272     }
273
274     /*
275      * Get the units per em value.
276      */
277     upm = face->units_per_EM;
278
279     ismono = 1;
280     wd = 0xffff;
281     awidth = 0;
282     maxrb = maxlb = maxas = maxds = 0;
283     minlb = 32767;
284
285     /*
286      * Calculate the SWIDTH scaling factor.
287      */
288     swscale = ((double) opts->resolution_y) * ((double) opts->point_size);
289
290     for (code = fp->glyphs_used = 0; code < 0xffff; code++) {
291         if (nocmap) {
292             /*
293              * No cmap is being used, so do each index in turn.
294              */
295             if (code >= face->num_glyphs)
296               break;
297             idx = code;
298         } else
299           idx = FT_Get_Char_Index(face, code);
300
301         if (idx <= 0 ||
302             FT_Load_Glyph(face, idx, opts->otf_flags))
303           continue;
304
305         if (FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO))
306           continue;
307
308         /*
309          * Increase the amount of storage by 128 every time.
310          */
311         if (fp->glyphs_used == fp->glyphs_size) {
312             fp->glyphs = (bdf_glyph_t *)
313                 realloc((char *) fp->glyphs,
314                         sizeof(bdf_glyph_t) * (fp->glyphs_size + 128));
315             gp = fp->glyphs + fp->glyphs_size;
316             (void) memset((char *) gp, 0, sizeof(bdf_glyph_t) << 7);
317             fp->glyphs_size += 128;
318         }
319
320         /*
321          * Point at the next glyph.
322          */
323         gp = fp->glyphs + fp->glyphs_used++;
324         gp->encoding = code;
325         gp->dwidth = face->glyph->metrics.horiAdvance >> 6;
326         gp->swidth = (unsigned short)
327             (((double) gp->dwidth) * 72000.0) / swscale;
328
329         /*
330          * Determine the actual bounding box of the glyph bitmap.  Do not
331          * forget that the glyph is rendered upside down!
332          */
333         sx = sy = 0xffff;
334         ex = ey = 0;
335         bmap = face->glyph->bitmap.buffer;
336         for (y = 0; y <  face->glyph->bitmap.rows; y++) {
337             for (x = 0; x < face->glyph->bitmap.width; x++) {
338                 if (bmap[x >> 3] & (0x80 >> (x & 7))) {
339                     if (x < sx) sx = x;
340                     if (x > ex) ex = x;
341                     if (y < sy) sy = y;
342                     if (y > ey) ey = y;
343                 }
344             }
345             bmap += face->glyph->bitmap.pitch;
346         }
347
348         /*
349          * If the glyph is actually an empty bitmap, set the size to 0 all
350          * around.
351          */
352         if (sx == 0xffff && sy == 0xffff && ex == 0 && ey == 0)
353           sx = ex = sy = ey = 0;
354         else {
355             /*
356              * Adjust the end points.
357              */
358             ex++;
359             ey++;
360         }
361
362         /*
363          * Test to see if the font is going to be monowidth or not by
364          * comparing the current glyph width against the last one.
365          */
366         if (ismono && (ex - sx) + 1 != wd)
367           ismono = 0;
368
369         /*
370          * Set the initial metrics.
371          */
372         wd = ex - sx;
373         ht = ey - sy;
374         x_off = sx + face->glyph->bitmap_left;
375         y_off = sy + face->glyph->bitmap_top - face->glyph->bitmap.rows;
376
377         /*
378          * Adjust the overall bounding box.
379          */
380         maxas = MAX(maxas, ht + y_off);
381         maxds = MAX(maxds, -y_off);
382         maxrb = MAX(maxrb, wd + x_off);
383         minlb = MIN(minlb, x_off);
384         maxlb = MAX(maxlb, x_off);
385
386         /*
387          * Accumulate the average width value.
388          */
389         awidth += wd;
390
391         /*
392          * Set the glyph metrics.
393          */
394         gp->bbx.width = wd;
395         gp->bbx.height = ht;
396         gp->bbx.x_offset = x_off;
397         gp->bbx.y_offset = y_off;
398         gp->bbx.ascent = ht + y_off;
399         gp->bbx.descent = -y_off;
400
401         /*
402          * Allocate the bitmap for the glyph.
403          */
404         bpr = (wd + 7) >> 3;
405         gp->bytes = bpr * ht;
406         gp->bitmap = (unsigned char *) malloc(gp->bytes);
407         (void) memset((char *) gp->bitmap, 0, gp->bytes);
408
409         /*
410          * Shift the bits into the glyph bitmap.
411          */
412         bmap = face->glyph->bitmap.buffer + sy * face->glyph->bitmap.pitch;
413         for (y = 0; y < ey - sy; y++) {
414             for (x = 0; x < ex - sx; x++) {
415                 if (bmap[(x+sx) >> 3] & (0x80 >> ((x+sx) & 7)))
416                   gp->bitmap[(y * bpr) + (x >> 3)] |= (0x80 >> (x & 7));
417             }
418             bmap += face->glyph->bitmap.pitch;
419         }
420
421         /*
422          * Call the callback if it was provided.
423          */
424         if (callback != 0) {
425             cb.reason = BDF_LOADING;
426             cb.current = fp->glyphs_used;
427             cb.total = face->num_glyphs;
428             (*callback)(&cb, data);
429         }
430     }
431
432     /*
433      * Calculate the font average width.
434      */
435     awidth =
436         (int) ((((double) awidth / (double) fp->glyphs_used) + 0.5) * 10.0);
437
438     /*
439      * Set the font bounding box.
440      */
441     fp->bbx.width = maxrb - minlb;
442     fp->bbx.height = maxas + maxds;
443     fp->bbx.x_offset = minlb;
444     fp->bbx.y_offset = -maxds;
445     fp->bbx.ascent = maxas;
446     fp->bbx.descent = maxds;
447
448     /*
449      * Set the font ascent and descent.
450      */
451     fp->font_ascent =
452         (horizontal->Ascender * imetrics.y_ppem) / upm;
453     fp->font_descent =
454         -((horizontal->Descender * imetrics.y_ppem) / upm);
455
456     /*
457      * Determine if the font is monowidth.
458      */
459     if (ismono) {
460         fp->spacing = BDF_MONOWIDTH;
461         fp->monowidth = fp->bbx.width;
462     }
463
464     /*
465      * Add the properties needed for the XLFD name.
466      */
467     prop.name = "POINT_SIZE";
468     prop.format = BDF_INTEGER;
469     prop.value.int32 = fp->point_size * 10;
470     bdf_add_font_property(fp, &prop);
471
472     prop.name = "PIXEL_SIZE";
473     prop.format = BDF_INTEGER;
474     prop.value.int32 = (int)
475         ((((double) (fp->point_size * 10) *
476            (double) fp->resolution_y) / 722.7) + 0.5);
477     bdf_add_font_property(fp, &prop);
478
479     prop.name = "RESOLUTION_X";
480     prop.format = BDF_CARDINAL;
481     prop.value.card32 = (unsigned int) fp->resolution_x;
482     bdf_add_font_property(fp, &prop);
483
484     prop.name = "RESOLUTION_Y";
485     prop.format = BDF_CARDINAL;
486     prop.value.card32 = (unsigned int) fp->resolution_y;
487     bdf_add_font_property(fp, &prop);
488
489     prop.name = "FONT_ASCENT";
490     prop.format = BDF_INTEGER;
491     prop.value.int32 = fp->font_ascent;
492     bdf_add_font_property(fp, &prop);
493
494     prop.name = "FONT_DESCENT";
495     prop.format = BDF_INTEGER;
496     prop.value.int32 = fp->font_descent;
497     bdf_add_font_property(fp, &prop);
498
499     prop.name = "AVERAGE_WIDTH";
500     prop.format = BDF_INTEGER;
501     prop.value.int32 = awidth;
502     bdf_add_font_property(fp, &prop);
503
504     prop.name = "SPACING";
505     prop.format = BDF_ATOM;
506     prop.value.atom = "P";
507     switch (fp->spacing) {
508       case BDF_PROPORTIONAL: prop.value.atom = "P"; break;
509       case BDF_MONOWIDTH: prop.value.atom = "M"; break;
510       case BDF_CHARCELL: prop.value.atom = "C"; break;
511     }
512     bdf_add_font_property(fp, &prop);
513
514     return 1;
515 }
516
517 int
518 bdfotf_load_font(FT_Face face, short pid, short eid, bdf_options_t *opts,
519                  bdf_callback_t callback, void *data, bdf_font_t **font)
520 {
521     int i, nocmap, res, slen;
522     bdf_font_t *fp;
523     char *np, str[256];
524     bdf_property_t prop;
525     bdf_callback_struct_t cb;
526     TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
527
528     /*
529      * First get the requested cmap from the font.
530      */
531     for (nocmap = i = 0; i < face->num_charmaps; i++) {
532         if (face->charmaps[i]->platform_id == pid &&
533             face->charmaps[i]->encoding_id == eid)
534           break;
535     }
536
537     /*
538      * If the requested cmap was not found, attempt to fall back on the
539      * Microsoft Unicode cmap.
540      */
541     if (i == face->num_charmaps) {
542         for (i = 0; i < face->num_charmaps; i++) {
543             if (face->charmaps[i]->platform_id == 3 &&
544                 face->charmaps[i]->encoding_id == 1)
545               break;
546         }
547         if (i == face->num_charmaps) {
548             /*
549              * No cmap was found.
550              */
551             nocmap = 1;
552             pid = eid = -1;
553         } else {
554             /*
555              * Found the Microsoft Unicode cmap.
556              */
557             pid = 3;
558             eid = 1;
559             FT_Set_Charmap(face, face->charmaps[i]);
560         }
561     } else
562       FT_Set_Charmap(face, face->charmaps[i]);
563
564     /*
565      * Create the font.
566      */
567     *font = fp = (bdf_font_t *) malloc(sizeof(bdf_font_t));
568     (void) memset((char *) fp, 0, sizeof(bdf_font_t));
569
570     /*
571      * Do some initializations by defaulting to proportional spacing and
572      * allocate at least the reported number of glyphs so reallocations will
573      * be minimal.
574      */
575     fp->bpp = 1;
576     fp->default_glyph = -1;
577     fp->spacing = BDF_PROPORTIONAL;
578     fp->glyphs_size = face->num_glyphs;
579     fp->glyphs = (bdf_glyph_t *)
580         malloc(sizeof(bdf_glyph_t) * face->num_glyphs);
581     (void) memset((char *) fp->glyphs, 0,
582                   sizeof(bdf_glyph_t) * face->num_glyphs);
583
584     /*
585      * Set the metrics.
586      */
587     fp->point_size = opts->point_size;
588     fp->resolution_x = opts->resolution_x;
589     fp->resolution_y = opts->resolution_y;
590
591     /*
592      * Actually generate the font.
593      */
594     res = _bdfotf_generate(face, nocmap, opts, callback, data, fp);
595
596     /*
597      * If the number of glyphs loaded is less than the reported number of
598      * glyphs, force a callback if one was provided.
599      */
600     if (callback != 0 && fp->glyphs_used < face->num_glyphs) {
601         cb.reason = BDF_LOADING;
602         cb.total = cb.current = face->num_glyphs;
603         (*callback)(&cb, data);
604     }
605
606     /*
607      * If the font did not load successfully, free up the font.
608      */
609     if (!res) {
610         bdf_free_font(fp);
611         *font = 0;
612     } else {
613         /*
614          * Add other sundry properties so the XLFD name can be generated.
615          */
616         prop.name = "FOUNDRY";
617         prop.format = BDF_ATOM;
618         prop.value.atom = "FreeType";
619         bdf_add_font_property(fp, &prop);
620
621         /*
622          * Get the typeface name.
623          */
624         slen = bdfotf_get_english_string(face, BDFOTF_FAMILY_STRING, 1, str);
625         prop.name = "FAMILY_NAME";
626         prop.format = BDF_ATOM;
627         if (slen > 0)
628           prop.value.atom = str;
629         else
630           prop.value.atom = "Unknown";
631         bdf_add_font_property(fp, &prop);
632
633         /*
634          * Add the CHARSET_REGISTRY and CHARSET_ENCODING properties.
635          */
636         np = bdfotf_encoding_name(pid, eid);
637         if (strcmp(np, "ISO8859-1") == 0) {
638             prop.name = "CHARSET_REGISTRY";
639             prop.format = BDF_ATOM;
640             prop.value.atom = "ISO8859";
641             bdf_add_font_property(fp, &prop);
642             prop.name = "CHARSET_ENCODING";
643             prop.format = BDF_ATOM;
644             prop.value.atom = "1";
645             bdf_add_font_property(fp, &prop);
646         } else if (strcmp(np, "ISO10646") == 0) {
647             prop.name = "CHARSET_REGISTRY";
648             prop.format = BDF_ATOM;
649             prop.value.atom = np;
650             bdf_add_font_property(fp, &prop);
651             prop.name = "CHARSET_ENCODING";
652             prop.format = BDF_ATOM;
653             prop.value.atom = "1";
654             bdf_add_font_property(fp, &prop);
655         } else {
656             prop.name = "CHARSET_REGISTRY";
657             prop.format = BDF_ATOM;
658             prop.value.atom = np;
659             bdf_add_font_property(fp, &prop);
660             prop.name = "CHARSET_ENCODING";
661             prop.format = BDF_ATOM;
662             prop.value.atom = "0";
663             bdf_add_font_property(fp, &prop);
664         }
665
666         /*
667          * Determine the weight name.
668          */
669         prop.name = "WEIGHT_NAME";
670         prop.format = BDF_ATOM;
671         slen = bdfotf_get_english_string(face, BDFOTF_SUBFAMILY_STRING,
672                                          1, str);
673         if (strcmp(str, "Regular") == 0)
674           prop.value.atom = "Medium";
675         else if (os2->fsSelection & 0x20)
676           prop.value.atom = "Bold";
677         else if (slen > 0)
678           prop.value.atom = str;
679         else
680           prop.value.atom = "Medium";
681         bdf_add_font_property(fp, &prop);
682
683         /*
684          * Determine the slant name.
685          */
686         prop.name = "SLANT";
687         prop.format = BDF_ATOM;
688         if (os2->fsSelection & 0x01)
689           prop.value.atom = "I";
690         else
691           prop.value.atom = "R";
692         bdf_add_font_property(fp, &prop);
693
694         /*
695          * Add the default SETWIDTH_NAME.
696          */
697         prop.name = "SETWIDTH_NAME";
698         prop.format = BDF_ATOM;
699         prop.value.atom = "Normal";
700         bdf_add_font_property(fp, &prop);
701
702         /*
703          * Create the XLFD font name for the font.
704          */
705         fp->name = bdf_make_xlfd_name(fp, 0, 0);
706
707         /*
708          * Add the COPYRIGHT notice.
709          */
710         slen = bdfotf_get_english_string(face, BDFOTF_COPYRIGHT_STRING,
711                                          0, str);
712         if (slen > 0) {
713             prop.name = "COPYRIGHT";
714             prop.format = BDF_ATOM;
715             prop.value.atom = str;
716             bdf_add_font_property(fp, &prop);
717         }
718
719         /*
720          * Add the special _TTF_PSNAME atom with the font Postscript name.
721          */
722         slen = bdfotf_get_english_string(face, BDFOTF_POSTSCRIPT_STRING,
723                                          0, str);
724         if (slen > 0) {
725             prop.name = "_TTF_PSNAME";
726             prop.format = BDF_ATOM;
727             prop.value.atom = str;
728             bdf_add_font_property(fp, &prop);
729         }
730
731         /*
732          * Add a message indicating the font was converted.
733          */
734         _bdf_add_comment(fp, "Font converted from OTF to BDF.", 31);
735         _bdf_add_acmsg(fp, "Font converted from OTF to BDF.", 31);
736
737         /*
738          * Finally, mark the font as being modified.
739          */
740         fp->modified = 1;
741     }
742
743     return res;
744 }
745
746 #endif /* HAVE_FREETYPE */