read.c revision 6ef05171
143f32c10Smrg/* $XdotOrg: xc/programs/fonttosfnt/read.c,v 1.2 2004/04/23 19:54:32 eich Exp $ */
243f32c10Smrg/*
343f32c10SmrgCopyright (c) 2002 by Juliusz Chroboczek
443f32c10Smrg
543f32c10SmrgPermission is hereby granted, free of charge, to any person obtaining a copy
643f32c10Smrgof this software and associated documentation files (the "Software"), to deal
743f32c10Smrgin the Software without restriction, including without limitation the rights
843f32c10Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
943f32c10Smrgcopies of the Software, and to permit persons to whom the Software is
1043f32c10Smrgfurnished to do so, subject to the following conditions:
1143f32c10Smrg
1243f32c10SmrgThe above copyright notice and this permission notice shall be included in
1343f32c10Smrgall copies or substantial portions of the Software.
1443f32c10Smrg
1543f32c10SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1643f32c10SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1743f32c10SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1843f32c10SmrgAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1943f32c10SmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2043f32c10SmrgOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2143f32c10SmrgTHE SOFTWARE.
2243f32c10Smrg*/
2343f32c10Smrg/* $XdotOrg: xc/programs/fonttosfnt/read.c,v 1.2 2004/04/23 19:54:32 eich Exp $ */
2443f32c10Smrg/* $XFree86: xc/programs/fonttosfnt/read.c,v 1.5 2003/12/19 02:05:39 dawes Exp $ */
2543f32c10Smrg
2643f32c10Smrg#include <stdio.h>
2743f32c10Smrg
2843f32c10Smrg#include <ft2build.h>
2943f32c10Smrg#include FT_FREETYPE_H
3043f32c10Smrg#include FT_BDF_H
3143f32c10Smrg#include "X11/Xos.h"
3243f32c10Smrg#include "fonttosfnt.h"
3343f32c10Smrg#include "X11/fonts/fontenc.h"
3443f32c10Smrg
3543f32c10Smrg#define FLOOR2(x, y) ((x) >= 0 ? (x) / (y) : -(((-(x)) + (y) - 1) / (y)))
3643f32c10Smrg#define CEIL2(x, y) (FLOOR2((x) + (y) - 1, (y)))
3743f32c10Smrg#define FT_Pos_DOWN(x) (FLOOR2((x),64))
3843f32c10Smrg#define FT_Pos_UP(x) (CEIL2((x), 64))
3943f32c10Smrg
4043f32c10Smrgstatic int ft_inited = 0;
4143f32c10Smrgstatic FT_Library ft_library;
4243f32c10Smrg
4343f32c10Smrgstatic int
4443f32c10SmrgFT_Ensure_Inited(void)
4543f32c10Smrg{
4643f32c10Smrg    int rc;
4743f32c10Smrg    if(ft_inited)
4843f32c10Smrg        return 0;
4943f32c10Smrg
5043f32c10Smrg    rc = FT_Init_FreeType(&ft_library);
5143f32c10Smrg    if(rc != 0)
5243f32c10Smrg        return rc;
5343f32c10Smrg
5443f32c10Smrg    ft_inited = 1;
5543f32c10Smrg    return 0;
5643f32c10Smrg}
5743f32c10Smrg
5843f32c10Smrgint
5943f32c10SmrgreadFile(char *filename, FontPtr font)
6043f32c10Smrg{
616ef05171Smrg    int j, k, index;
6243f32c10Smrg    int rc;
6343f32c10Smrg    FT_Face face;
6443f32c10Smrg    StrikePtr strike;
6543f32c10Smrg    BitmapPtr bitmap;
6643f32c10Smrg    int symbol = 0;
6743f32c10Smrg    char *encoding_name = NULL;
6843f32c10Smrg    FontMapPtr mapping = NULL;
6943f32c10Smrg    FontMapReversePtr reverse = NULL;
7043f32c10Smrg
7143f32c10Smrg
7243f32c10Smrg    rc = FT_Ensure_Inited();
7343f32c10Smrg    if(rc != 0)
7443f32c10Smrg        return rc;
7543f32c10Smrg
7643f32c10Smrg    rc = FT_New_Face(ft_library, filename, 0, &face);
7743f32c10Smrg    if(rc != 0) {
7843f32c10Smrg        fprintf(stderr, "Couldn't open face %s.\n", filename);
7943f32c10Smrg        return -1;
8043f32c10Smrg    }
8143f32c10Smrg
8243f32c10Smrg    encoding_name = faceEncoding(face);
8343f32c10Smrg    if(encoding_name == NULL) {
8443f32c10Smrg        symbol = 1;
8543f32c10Smrg    } else if(strcasecmp(encoding_name, "iso10646-1") != 0) {
8643f32c10Smrg        if(reencode_flag)
8743f32c10Smrg            mapping = FontEncMapFind(encoding_name,
8843f32c10Smrg                                     FONT_ENCODING_UNICODE, 0, 0, NULL);
8943f32c10Smrg        if(mapping == NULL) {
9043f32c10Smrg            symbol = 1;
9143f32c10Smrg        } else {
9243f32c10Smrg            reverse = FontMapReverse(mapping);
9343f32c10Smrg            if(reverse == NULL) {
9443f32c10Smrg                fprintf(stderr, "Couldn't reverse mapping.\n");
9543f32c10Smrg                return -1;
9643f32c10Smrg            }
9743f32c10Smrg        }
9843f32c10Smrg    }
9943f32c10Smrg
10043f32c10Smrg    if(verbose_flag) {
10143f32c10Smrg        fprintf(stderr, "%s %s %s: %d sizes%s\n",
10243f32c10Smrg                filename, face->family_name, face->style_name,
10343f32c10Smrg                face->num_fixed_sizes,
10443f32c10Smrg                symbol ? " (symbol)" : "");
10543f32c10Smrg    }
10643f32c10Smrg
10743f32c10Smrg    if(font->numNames == 0 && face->style_name && face->family_name) {
10843f32c10Smrg        char *full_name, *unique_name;
10943f32c10Smrg        BDF_PropertyRec prop;
1106ef05171Smrg        int i;
11143f32c10Smrg        if(strcmp(face->style_name, "Regular") == 0)
11243f32c10Smrg            full_name = sprintf_alloc("%s", face->family_name);
11343f32c10Smrg        else
11443f32c10Smrg            full_name = sprintf_alloc("%s %s",
11543f32c10Smrg                                      face->family_name, face->style_name);
11643f32c10Smrg
11743f32c10Smrg        /* The unique name doesn't actually need to be globally
11843f32c10Smrg           unique; it only needs to be unique among all installed fonts on a
11943f32c10Smrg           Windows system.  We don't bother getting it quite right. */
12043f32c10Smrg        if(face->num_fixed_sizes <= 0)
12143f32c10Smrg            unique_name = sprintf_alloc("%s "XVENDORNAMESHORT" bitmap",
12243f32c10Smrg                                        full_name);
12343f32c10Smrg        else if(face->available_sizes[0].width ==
12443f32c10Smrg                face->available_sizes[0].height)
12543f32c10Smrg            unique_name = sprintf_alloc("%s "XVENDORNAMESHORT
12643f32c10Smrg					   " bitmap size %d",
12743f32c10Smrg                                           full_name,
12843f32c10Smrg                                           face->available_sizes[0].height);
12943f32c10Smrg        else
13043f32c10Smrg            unique_name = sprintf_alloc("%s "XVENDORNAMESHORT
13143f32c10Smrg                                        " bitmap size %dx%d",
13243f32c10Smrg                                        full_name,
13343f32c10Smrg                                        face->available_sizes[0].width,
13443f32c10Smrg                                        face->available_sizes[0].height);
13543f32c10Smrg
13643f32c10Smrg        font->names = malloc(10 * sizeof(FontNameEntryRec));
13743f32c10Smrg        if(font->names == NULL) {
13843f32c10Smrg            fprintf(stderr, "Couldn't allocate names.\n");
13943f32c10Smrg            return -1;
14043f32c10Smrg        }
14143f32c10Smrg        i = 0;
14243f32c10Smrg
14343f32c10Smrg        rc = FT_Get_BDF_Property(face, "COPYRIGHT", &prop);
14443f32c10Smrg        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
14543f32c10Smrg            font->names[i].nid = 0;
14643f32c10Smrg            font->names[i].size = 2 * strlen(prop.u.atom);
14743f32c10Smrg            font->names[i].value = makeUTF16((char*)prop.u.atom);
14843f32c10Smrg            i++;
14943f32c10Smrg        }
15043f32c10Smrg
15143f32c10Smrg        font->names[i].nid = 1;
15243f32c10Smrg        font->names[i].size = 2 * strlen(face->family_name);
15343f32c10Smrg        font->names[i].value = makeUTF16(face->family_name);
15443f32c10Smrg        i++;
15543f32c10Smrg
15643f32c10Smrg        font->names[i].nid = 2;
15743f32c10Smrg        font->names[i].size = 2 * strlen(face->style_name);
15843f32c10Smrg        font->names[i].value = makeUTF16(face->style_name);
15943f32c10Smrg        i++;
16043f32c10Smrg
16143f32c10Smrg        font->names[i].nid = 3;
16243f32c10Smrg        font->names[i].size = 2 * strlen(unique_name);
16343f32c10Smrg        font->names[i].value = makeUTF16(unique_name);
16443f32c10Smrg        i++;
16543f32c10Smrg
16643f32c10Smrg        font->names[i].nid = 4;
16743f32c10Smrg        font->names[i].size = 2 * strlen(full_name);
16843f32c10Smrg        font->names[i].value = makeUTF16(full_name);
16943f32c10Smrg        i++;
17043f32c10Smrg
17143f32c10Smrg        font->names[i].nid = 5;
17243f32c10Smrg        font->names[i].size = 2 * strlen("Version 0.0");
17343f32c10Smrg        font->names[i].value = makeUTF16("Version 0.0");
17443f32c10Smrg        i++;
17543f32c10Smrg
17643f32c10Smrg        rc = FT_Get_BDF_Property(face, "FOUNDRY", &prop);
17743f32c10Smrg        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
17843f32c10Smrg            font->names[i].nid = 8;
17943f32c10Smrg            font->names[i].size = 2 * strlen(prop.u.atom);
18043f32c10Smrg            font->names[i].value = makeUTF16((char*)prop.u.atom);
18143f32c10Smrg            i++;
18243f32c10Smrg        }
18343f32c10Smrg
18443f32c10Smrg        font->names[i].nid = 10;
18543f32c10Smrg        font->names[i].size = 2 * strlen(XVENDORNAMESHORT
18643f32c10Smrg					 " converted bitmap font");
18743f32c10Smrg        font->names[i].value = makeUTF16(XVENDORNAMESHORT
18843f32c10Smrg					 "X converted bitmap font");
18943f32c10Smrg        i++;
19043f32c10Smrg#ifdef __VENDORWEBSUPPORT__
19143f32c10Smrg        font->names[i].nid = 11;
19243f32c10Smrg        font->names[i].size = 2 * strlen(__VENDORWEBSUPPORT__);
19343f32c10Smrg        font->names[i].value = makeUTF16(__VENDORWEBSUPPORT__);
19443f32c10Smrg        i++;
19543f32c10Smrg#endif
19643f32c10Smrg        font->numNames = i;
19743f32c10Smrg
19843f32c10Smrg        font->flags = faceFlags(face) | (symbol ? FACE_SYMBOL : 0);
19943f32c10Smrg        font->weight = faceWeight(face);
20043f32c10Smrg        font->width = faceWidth(face);
20143f32c10Smrg        font->foundry = faceFoundry(face);
20243f32c10Smrg        font->italicAngle = faceItalicAngle(face);
20343f32c10Smrg
20443f32c10Smrg        rc = FT_Get_BDF_Property(face, "UNDERLINE_POSITION", &prop);
20543f32c10Smrg        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
20643f32c10Smrg            font->underlinePosition =
20743f32c10Smrg                (double)prop.u.integer / face->available_sizes[0].height *
20843f32c10Smrg                TWO_SIXTEENTH;
20943f32c10Smrg        else
21043f32c10Smrg            font->underlinePosition =
21143f32c10Smrg                - 1.5 / face->available_sizes[0].height * TWO_SIXTEENTH;
21243f32c10Smrg
21343f32c10Smrg        rc = FT_Get_BDF_Property(face, "UNDERLINE_THICKNESS", &prop);
21443f32c10Smrg        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
21543f32c10Smrg            font->underlineThickness =
21643f32c10Smrg                (double)prop.u.integer / face->available_sizes[0].height *
21743f32c10Smrg                TWO_SIXTEENTH;
21843f32c10Smrg        else
21943f32c10Smrg            font->underlineThickness =
22043f32c10Smrg                1.0 / face->available_sizes[0].height * TWO_SIXTEENTH;
22143f32c10Smrg    }
22243f32c10Smrg
22343f32c10Smrg    if(face->num_fixed_sizes == 0) {
22443f32c10Smrg        fprintf(stderr, "No bitmaps in face.\n");
22543f32c10Smrg        return -1;
22643f32c10Smrg    }
22743f32c10Smrg
22843f32c10Smrg    if(!symbol && !mapping)
22943f32c10Smrg        rc = FT_Select_Charmap(face, ft_encoding_unicode);
23043f32c10Smrg    else
23143f32c10Smrg        rc = FT_Select_Charmap(face, ft_encoding_none);
23243f32c10Smrg    if(rc != 0) {
23343f32c10Smrg        fprintf(stderr, "Couldn't select character map: %x.\n", rc);
23443f32c10Smrg        return -1;
23543f32c10Smrg    }
23643f32c10Smrg
2376ef05171Smrg    for(int i = 0; i < face->num_fixed_sizes; i++) {
23843f32c10Smrg        if(verbose_flag)
23943f32c10Smrg            fprintf(stderr, "size %d: %dx%d\n",
24043f32c10Smrg                    i,
2416ef05171Smrg                    (int)(face->available_sizes[i].x_ppem >> 6),
2426ef05171Smrg                    (int)(face->available_sizes[i].y_ppem >> 6));
24343f32c10Smrg
24443f32c10Smrg        rc = FT_Set_Pixel_Sizes(face,
24543f32c10Smrg                                face->available_sizes[i].x_ppem >> 6,
24643f32c10Smrg                                face->available_sizes[i].y_ppem >> 6);
24743f32c10Smrg        if(rc != 0) {
24843f32c10Smrg            fprintf(stderr, "Couldn't set size.\n");
24943f32c10Smrg            return -1;
25043f32c10Smrg        }
25143f32c10Smrg
25243f32c10Smrg        strike = makeStrike(font,
25343f32c10Smrg                            face->available_sizes[i].x_ppem >> 6,
25443f32c10Smrg                            face->available_sizes[i].y_ppem >> 6);
25543f32c10Smrg        if(strike == NULL) {
25643f32c10Smrg            fprintf(stderr, "Couldn't allocate strike.\n");
25743f32c10Smrg            return -1;
25843f32c10Smrg        }
25943f32c10Smrg
26043f32c10Smrg        for(j = 0; j < FONT_CODES; j++) {
26143f32c10Smrg            if(mapping)
26243f32c10Smrg                k = reverse->reverse(j, reverse->data);
26343f32c10Smrg            else
26443f32c10Smrg                k = j;
26543f32c10Smrg            if(k <= 0 && j != 0)
26643f32c10Smrg                continue;
26743f32c10Smrg            index = FT_Get_Char_Index(face, k);
26843f32c10Smrg            if(j != 0 && index == 0)
26943f32c10Smrg                continue;
27043f32c10Smrg            rc = FT_Load_Glyph(face, index,
27143f32c10Smrg                               FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
27243f32c10Smrg            if(rc != 0) {
27343f32c10Smrg                fprintf(stderr, "Couldn't load glyph for U+%04X (%d)\n",
27443f32c10Smrg                        j, index);
27543f32c10Smrg                continue;
27643f32c10Smrg            }
27743f32c10Smrg            bitmap = makeBitmap(strike, j,
27843f32c10Smrg                                FT_Pos_UP(face->glyph->metrics.horiAdvance),
27943f32c10Smrg                                FT_Pos_DOWN(face->glyph->metrics.horiBearingX),
28043f32c10Smrg                                FT_Pos_DOWN(face->glyph->metrics.horiBearingY),
28143f32c10Smrg                                face->glyph->bitmap.width,
28243f32c10Smrg                                face->glyph->bitmap.rows,
28343f32c10Smrg                                face->glyph->bitmap.pitch,
28443f32c10Smrg                                face->glyph->bitmap.buffer,
28543f32c10Smrg                                crop_flag);
28643f32c10Smrg
28743f32c10Smrg            if(bitmap == NULL) {
28843f32c10Smrg                fprintf(stderr, "Couldn't create bitmap.\n");
28943f32c10Smrg                return -1;
29043f32c10Smrg            }
29143f32c10Smrg        }
29243f32c10Smrg    }
29343f32c10Smrg
29443f32c10Smrg    FT_Done_Face(face);
29543f32c10Smrg
29643f32c10Smrg    j = 0;
2976ef05171Smrg    for(int i = 0; i < FONT_CODES; i++) {
29843f32c10Smrg        int found = 0;
29943f32c10Smrg        strike = font->strikes;
30043f32c10Smrg        while(strike) {
30143f32c10Smrg            bitmap = STRIKE_BITMAP(strike, i);
30243f32c10Smrg            if(bitmap) {
30343f32c10Smrg                bitmap->index = j;
30443f32c10Smrg                found = 1;
30543f32c10Smrg            } else {
30643f32c10Smrg                if(i == 0) {
30743f32c10Smrg                    fprintf(stderr,
30843f32c10Smrg                            "Warning: no bitmap for the undefined glyph.\n");
30943f32c10Smrg                    found = 1;
31043f32c10Smrg                }
31143f32c10Smrg            }
31243f32c10Smrg            strike = strike->next;
31343f32c10Smrg        }
31443f32c10Smrg        if(found)
31543f32c10Smrg            j++;
31643f32c10Smrg    }
31743f32c10Smrg    return 0;
31843f32c10Smrg}
319