read.c revision 6ef05171
1/* $XdotOrg: xc/programs/fonttosfnt/read.c,v 1.2 2004/04/23 19:54:32 eich Exp $ */
2/*
3Copyright (c) 2002 by Juliusz Chroboczek
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22*/
23/* $XdotOrg: xc/programs/fonttosfnt/read.c,v 1.2 2004/04/23 19:54:32 eich Exp $ */
24/* $XFree86: xc/programs/fonttosfnt/read.c,v 1.5 2003/12/19 02:05:39 dawes Exp $ */
25
26#include <stdio.h>
27
28#include <ft2build.h>
29#include FT_FREETYPE_H
30#include FT_BDF_H
31#include "X11/Xos.h"
32#include "fonttosfnt.h"
33#include "X11/fonts/fontenc.h"
34
35#define FLOOR2(x, y) ((x) >= 0 ? (x) / (y) : -(((-(x)) + (y) - 1) / (y)))
36#define CEIL2(x, y) (FLOOR2((x) + (y) - 1, (y)))
37#define FT_Pos_DOWN(x) (FLOOR2((x),64))
38#define FT_Pos_UP(x) (CEIL2((x), 64))
39
40static int ft_inited = 0;
41static FT_Library ft_library;
42
43static int
44FT_Ensure_Inited(void)
45{
46    int rc;
47    if(ft_inited)
48        return 0;
49
50    rc = FT_Init_FreeType(&ft_library);
51    if(rc != 0)
52        return rc;
53
54    ft_inited = 1;
55    return 0;
56}
57
58int
59readFile(char *filename, FontPtr font)
60{
61    int j, k, index;
62    int rc;
63    FT_Face face;
64    StrikePtr strike;
65    BitmapPtr bitmap;
66    int symbol = 0;
67    char *encoding_name = NULL;
68    FontMapPtr mapping = NULL;
69    FontMapReversePtr reverse = NULL;
70
71
72    rc = FT_Ensure_Inited();
73    if(rc != 0)
74        return rc;
75
76    rc = FT_New_Face(ft_library, filename, 0, &face);
77    if(rc != 0) {
78        fprintf(stderr, "Couldn't open face %s.\n", filename);
79        return -1;
80    }
81
82    encoding_name = faceEncoding(face);
83    if(encoding_name == NULL) {
84        symbol = 1;
85    } else if(strcasecmp(encoding_name, "iso10646-1") != 0) {
86        if(reencode_flag)
87            mapping = FontEncMapFind(encoding_name,
88                                     FONT_ENCODING_UNICODE, 0, 0, NULL);
89        if(mapping == NULL) {
90            symbol = 1;
91        } else {
92            reverse = FontMapReverse(mapping);
93            if(reverse == NULL) {
94                fprintf(stderr, "Couldn't reverse mapping.\n");
95                return -1;
96            }
97        }
98    }
99
100    if(verbose_flag) {
101        fprintf(stderr, "%s %s %s: %d sizes%s\n",
102                filename, face->family_name, face->style_name,
103                face->num_fixed_sizes,
104                symbol ? " (symbol)" : "");
105    }
106
107    if(font->numNames == 0 && face->style_name && face->family_name) {
108        char *full_name, *unique_name;
109        BDF_PropertyRec prop;
110        int i;
111        if(strcmp(face->style_name, "Regular") == 0)
112            full_name = sprintf_alloc("%s", face->family_name);
113        else
114            full_name = sprintf_alloc("%s %s",
115                                      face->family_name, face->style_name);
116
117        /* The unique name doesn't actually need to be globally
118           unique; it only needs to be unique among all installed fonts on a
119           Windows system.  We don't bother getting it quite right. */
120        if(face->num_fixed_sizes <= 0)
121            unique_name = sprintf_alloc("%s "XVENDORNAMESHORT" bitmap",
122                                        full_name);
123        else if(face->available_sizes[0].width ==
124                face->available_sizes[0].height)
125            unique_name = sprintf_alloc("%s "XVENDORNAMESHORT
126					   " bitmap size %d",
127                                           full_name,
128                                           face->available_sizes[0].height);
129        else
130            unique_name = sprintf_alloc("%s "XVENDORNAMESHORT
131                                        " bitmap size %dx%d",
132                                        full_name,
133                                        face->available_sizes[0].width,
134                                        face->available_sizes[0].height);
135
136        font->names = malloc(10 * sizeof(FontNameEntryRec));
137        if(font->names == NULL) {
138            fprintf(stderr, "Couldn't allocate names.\n");
139            return -1;
140        }
141        i = 0;
142
143        rc = FT_Get_BDF_Property(face, "COPYRIGHT", &prop);
144        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
145            font->names[i].nid = 0;
146            font->names[i].size = 2 * strlen(prop.u.atom);
147            font->names[i].value = makeUTF16((char*)prop.u.atom);
148            i++;
149        }
150
151        font->names[i].nid = 1;
152        font->names[i].size = 2 * strlen(face->family_name);
153        font->names[i].value = makeUTF16(face->family_name);
154        i++;
155
156        font->names[i].nid = 2;
157        font->names[i].size = 2 * strlen(face->style_name);
158        font->names[i].value = makeUTF16(face->style_name);
159        i++;
160
161        font->names[i].nid = 3;
162        font->names[i].size = 2 * strlen(unique_name);
163        font->names[i].value = makeUTF16(unique_name);
164        i++;
165
166        font->names[i].nid = 4;
167        font->names[i].size = 2 * strlen(full_name);
168        font->names[i].value = makeUTF16(full_name);
169        i++;
170
171        font->names[i].nid = 5;
172        font->names[i].size = 2 * strlen("Version 0.0");
173        font->names[i].value = makeUTF16("Version 0.0");
174        i++;
175
176        rc = FT_Get_BDF_Property(face, "FOUNDRY", &prop);
177        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
178            font->names[i].nid = 8;
179            font->names[i].size = 2 * strlen(prop.u.atom);
180            font->names[i].value = makeUTF16((char*)prop.u.atom);
181            i++;
182        }
183
184        font->names[i].nid = 10;
185        font->names[i].size = 2 * strlen(XVENDORNAMESHORT
186					 " converted bitmap font");
187        font->names[i].value = makeUTF16(XVENDORNAMESHORT
188					 "X converted bitmap font");
189        i++;
190#ifdef __VENDORWEBSUPPORT__
191        font->names[i].nid = 11;
192        font->names[i].size = 2 * strlen(__VENDORWEBSUPPORT__);
193        font->names[i].value = makeUTF16(__VENDORWEBSUPPORT__);
194        i++;
195#endif
196        font->numNames = i;
197
198        font->flags = faceFlags(face) | (symbol ? FACE_SYMBOL : 0);
199        font->weight = faceWeight(face);
200        font->width = faceWidth(face);
201        font->foundry = faceFoundry(face);
202        font->italicAngle = faceItalicAngle(face);
203
204        rc = FT_Get_BDF_Property(face, "UNDERLINE_POSITION", &prop);
205        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
206            font->underlinePosition =
207                (double)prop.u.integer / face->available_sizes[0].height *
208                TWO_SIXTEENTH;
209        else
210            font->underlinePosition =
211                - 1.5 / face->available_sizes[0].height * TWO_SIXTEENTH;
212
213        rc = FT_Get_BDF_Property(face, "UNDERLINE_THICKNESS", &prop);
214        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
215            font->underlineThickness =
216                (double)prop.u.integer / face->available_sizes[0].height *
217                TWO_SIXTEENTH;
218        else
219            font->underlineThickness =
220                1.0 / face->available_sizes[0].height * TWO_SIXTEENTH;
221    }
222
223    if(face->num_fixed_sizes == 0) {
224        fprintf(stderr, "No bitmaps in face.\n");
225        return -1;
226    }
227
228    if(!symbol && !mapping)
229        rc = FT_Select_Charmap(face, ft_encoding_unicode);
230    else
231        rc = FT_Select_Charmap(face, ft_encoding_none);
232    if(rc != 0) {
233        fprintf(stderr, "Couldn't select character map: %x.\n", rc);
234        return -1;
235    }
236
237    for(int i = 0; i < face->num_fixed_sizes; i++) {
238        if(verbose_flag)
239            fprintf(stderr, "size %d: %dx%d\n",
240                    i,
241                    (int)(face->available_sizes[i].x_ppem >> 6),
242                    (int)(face->available_sizes[i].y_ppem >> 6));
243
244        rc = FT_Set_Pixel_Sizes(face,
245                                face->available_sizes[i].x_ppem >> 6,
246                                face->available_sizes[i].y_ppem >> 6);
247        if(rc != 0) {
248            fprintf(stderr, "Couldn't set size.\n");
249            return -1;
250        }
251
252        strike = makeStrike(font,
253                            face->available_sizes[i].x_ppem >> 6,
254                            face->available_sizes[i].y_ppem >> 6);
255        if(strike == NULL) {
256            fprintf(stderr, "Couldn't allocate strike.\n");
257            return -1;
258        }
259
260        for(j = 0; j < FONT_CODES; j++) {
261            if(mapping)
262                k = reverse->reverse(j, reverse->data);
263            else
264                k = j;
265            if(k <= 0 && j != 0)
266                continue;
267            index = FT_Get_Char_Index(face, k);
268            if(j != 0 && index == 0)
269                continue;
270            rc = FT_Load_Glyph(face, index,
271                               FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
272            if(rc != 0) {
273                fprintf(stderr, "Couldn't load glyph for U+%04X (%d)\n",
274                        j, index);
275                continue;
276            }
277            bitmap = makeBitmap(strike, j,
278                                FT_Pos_UP(face->glyph->metrics.horiAdvance),
279                                FT_Pos_DOWN(face->glyph->metrics.horiBearingX),
280                                FT_Pos_DOWN(face->glyph->metrics.horiBearingY),
281                                face->glyph->bitmap.width,
282                                face->glyph->bitmap.rows,
283                                face->glyph->bitmap.pitch,
284                                face->glyph->bitmap.buffer,
285                                crop_flag);
286
287            if(bitmap == NULL) {
288                fprintf(stderr, "Couldn't create bitmap.\n");
289                return -1;
290            }
291        }
292    }
293
294    FT_Done_Face(face);
295
296    j = 0;
297    for(int i = 0; i < FONT_CODES; i++) {
298        int found = 0;
299        strike = font->strikes;
300        while(strike) {
301            bitmap = STRIKE_BITMAP(strike, i);
302            if(bitmap) {
303                bitmap->index = j;
304                found = 1;
305            } else {
306                if(i == 0) {
307                    fprintf(stderr,
308                            "Warning: no bitmap for the undefined glyph.\n");
309                    found = 1;
310                }
311            }
312            strike = strike->next;
313        }
314        if(found)
315            j++;
316    }
317    return 0;
318}
319