read.c revision ea148d1d
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 30ea148d1dSmrg#include FT_MODULE_H 3143f32c10Smrg#include FT_BDF_H 3243f32c10Smrg#include "X11/Xos.h" 3343f32c10Smrg#include "fonttosfnt.h" 3443f32c10Smrg#include "X11/fonts/fontenc.h" 3543f32c10Smrg 3643f32c10Smrg#define FLOOR2(x, y) ((x) >= 0 ? (x) / (y) : -(((-(x)) + (y) - 1) / (y))) 3743f32c10Smrg#define CEIL2(x, y) (FLOOR2((x) + (y) - 1, (y))) 3843f32c10Smrg#define FT_Pos_DOWN(x) (FLOOR2((x),64)) 3943f32c10Smrg#define FT_Pos_UP(x) (CEIL2((x), 64)) 40ea148d1dSmrg#define MIN(x, y) (((x) <= (y)) ? (x) : (y)) 41ea148d1dSmrg#define STREAM_FILE(stream) ((FILE*)stream->descriptor.pointer) 4243f32c10Smrg 4343f32c10Smrgstatic int ft_inited = 0; 4443f32c10Smrgstatic FT_Library ft_library; 4543f32c10Smrg 4643f32c10Smrgstatic int 4743f32c10SmrgFT_Ensure_Inited(void) 4843f32c10Smrg{ 4943f32c10Smrg int rc; 5043f32c10Smrg if(ft_inited) 5143f32c10Smrg return 0; 5243f32c10Smrg 5343f32c10Smrg rc = FT_Init_FreeType(&ft_library); 5443f32c10Smrg if(rc != 0) 5543f32c10Smrg return rc; 5643f32c10Smrg 5743f32c10Smrg ft_inited = 1; 5843f32c10Smrg return 0; 5943f32c10Smrg} 6043f32c10Smrg 61ea148d1dSmrgstatic unsigned long 62ea148d1dSmrgforwardRead(FT_Stream stream, unsigned long offset, unsigned char *buffer, 63ea148d1dSmrg unsigned long count) { 64ea148d1dSmrg unsigned char skip_buffer[BUFSIZ]; 65ea148d1dSmrg unsigned long skip_count; 66ea148d1dSmrg FILE *file = STREAM_FILE(stream); 67ea148d1dSmrg 68ea148d1dSmrg /* We may be asked to skip forward, but by not doing so we increase our 69ea148d1dSmrg chance of survival. */ 70ea148d1dSmrg if(count == 0) 71ea148d1dSmrg return ferror(file) == 0 ? 0 : 1; 72ea148d1dSmrg 73ea148d1dSmrg if(offset < stream->pos) { 74ea148d1dSmrg fprintf(stderr, "Cannot move backward in input stream.\n"); 75ea148d1dSmrg return 0; 76ea148d1dSmrg } 77ea148d1dSmrg while((skip_count = MIN(BUFSIZ, offset - stream->pos))) { 78ea148d1dSmrg if(fread(skip_buffer, sizeof(*skip_buffer), skip_count, file) < 79ea148d1dSmrg skip_count) 80ea148d1dSmrg return 0; 81ea148d1dSmrg stream->pos += sizeof(*skip_buffer) * skip_count; 82ea148d1dSmrg } 83ea148d1dSmrg 84ea148d1dSmrg return (unsigned long)fread(buffer, sizeof(*buffer), count, file); 85ea148d1dSmrg} 86ea148d1dSmrg 87ea148d1dSmrgstatic void 88ea148d1dSmrgstreamClose(FT_Stream stream) { 89ea148d1dSmrg fclose(STREAM_FILE(stream)); 90ea148d1dSmrg stream->descriptor.pointer = NULL; 91ea148d1dSmrg stream->size = 0; 92ea148d1dSmrg} 93ea148d1dSmrg 9443f32c10Smrgint 9543f32c10SmrgreadFile(char *filename, FontPtr font) 9643f32c10Smrg{ 976ef05171Smrg int j, k, index; 9843f32c10Smrg int rc; 99ea148d1dSmrg FT_Open_Args input = { 0 }; 10043f32c10Smrg FT_Face face; 10143f32c10Smrg StrikePtr strike; 10243f32c10Smrg BitmapPtr bitmap; 10343f32c10Smrg int symbol = 0; 104ea148d1dSmrg int force_unicode = 1; 10543f32c10Smrg char *encoding_name = NULL; 10643f32c10Smrg FontMapPtr mapping = NULL; 10743f32c10Smrg FontMapReversePtr reverse = NULL; 10843f32c10Smrg 10943f32c10Smrg 11043f32c10Smrg rc = FT_Ensure_Inited(); 11143f32c10Smrg if(rc != 0) 11243f32c10Smrg return rc; 11343f32c10Smrg 114ea148d1dSmrg if(filename != NULL) { 115ea148d1dSmrg input.pathname = filename; 116ea148d1dSmrg input.flags = FT_OPEN_PATHNAME; 117ea148d1dSmrg } else { 118ea148d1dSmrg input.flags = FT_OPEN_STREAM | FT_OPEN_DRIVER; 119ea148d1dSmrg input.driver = FT_Get_Module(ft_library, "bdf"); 120ea148d1dSmrg input.stream = calloc(1, sizeof(FT_StreamRec)); 121ea148d1dSmrg if(input.stream == NULL) 122ea148d1dSmrg return -1; 123ea148d1dSmrg 124ea148d1dSmrg input.stream->size = 0x7FFFFFFF; 125ea148d1dSmrg input.stream->descriptor.pointer = stdin; 126ea148d1dSmrg input.stream->read = forwardRead; 127ea148d1dSmrg input.stream->close = streamClose; 128ea148d1dSmrg } 129ea148d1dSmrg rc = FT_Open_Face(ft_library, &input, 0, &face); 13043f32c10Smrg if(rc != 0) { 131ea148d1dSmrg fprintf(stderr, "Couldn't open face %s.\n", 132ea148d1dSmrg filename ? filename : "<stdin>"); 13343f32c10Smrg return -1; 13443f32c10Smrg } 13543f32c10Smrg 136ea148d1dSmrg /* FreeType will insist on encodings which are simple subsets of unicode 137ea148d1dSmrg * to be read as unicode regardless of what we call them. */ 138ea148d1dSmrg for(j = 0; j < face->num_charmaps; ++j) { 139ea148d1dSmrg if((face->charmaps[j]->encoding == ft_encoding_none) || 140ea148d1dSmrg (face->charmaps[j]->encoding == ft_encoding_adobe_standard)) { 141ea148d1dSmrg force_unicode = 0; 142ea148d1dSmrg break; 143ea148d1dSmrg } 144ea148d1dSmrg } 145ea148d1dSmrg 14643f32c10Smrg encoding_name = faceEncoding(face); 14743f32c10Smrg if(encoding_name == NULL) { 14843f32c10Smrg symbol = 1; 14943f32c10Smrg } else if(strcasecmp(encoding_name, "iso10646-1") != 0) { 15043f32c10Smrg if(reencode_flag) 15143f32c10Smrg mapping = FontEncMapFind(encoding_name, 15243f32c10Smrg FONT_ENCODING_UNICODE, 0, 0, NULL); 15343f32c10Smrg if(mapping == NULL) { 15443f32c10Smrg symbol = 1; 15543f32c10Smrg } else { 15643f32c10Smrg reverse = FontMapReverse(mapping); 15743f32c10Smrg if(reverse == NULL) { 15843f32c10Smrg fprintf(stderr, "Couldn't reverse mapping.\n"); 15943f32c10Smrg return -1; 16043f32c10Smrg } 16143f32c10Smrg } 16243f32c10Smrg } 16343f32c10Smrg 16443f32c10Smrg if(verbose_flag) { 16543f32c10Smrg fprintf(stderr, "%s %s %s: %d sizes%s\n", 166ea148d1dSmrg filename ? filename : "<stdin>", 167ea148d1dSmrg face->family_name, face->style_name, face->num_fixed_sizes, 16843f32c10Smrg symbol ? " (symbol)" : ""); 16943f32c10Smrg } 17043f32c10Smrg 17143f32c10Smrg if(font->numNames == 0 && face->style_name && face->family_name) { 17243f32c10Smrg char *full_name, *unique_name; 17343f32c10Smrg BDF_PropertyRec prop; 1746ef05171Smrg int i; 17543f32c10Smrg if(strcmp(face->style_name, "Regular") == 0) 17643f32c10Smrg full_name = sprintf_alloc("%s", face->family_name); 17743f32c10Smrg else 17843f32c10Smrg full_name = sprintf_alloc("%s %s", 17943f32c10Smrg face->family_name, face->style_name); 18043f32c10Smrg 18143f32c10Smrg /* The unique name doesn't actually need to be globally 18243f32c10Smrg unique; it only needs to be unique among all installed fonts on a 18343f32c10Smrg Windows system. We don't bother getting it quite right. */ 18443f32c10Smrg if(face->num_fixed_sizes <= 0) 18543f32c10Smrg unique_name = sprintf_alloc("%s "XVENDORNAMESHORT" bitmap", 18643f32c10Smrg full_name); 18743f32c10Smrg else if(face->available_sizes[0].width == 18843f32c10Smrg face->available_sizes[0].height) 18943f32c10Smrg unique_name = sprintf_alloc("%s "XVENDORNAMESHORT 19043f32c10Smrg " bitmap size %d", 19143f32c10Smrg full_name, 19243f32c10Smrg face->available_sizes[0].height); 19343f32c10Smrg else 19443f32c10Smrg unique_name = sprintf_alloc("%s "XVENDORNAMESHORT 19543f32c10Smrg " bitmap size %dx%d", 19643f32c10Smrg full_name, 19743f32c10Smrg face->available_sizes[0].width, 19843f32c10Smrg face->available_sizes[0].height); 19943f32c10Smrg 20043f32c10Smrg font->names = malloc(10 * sizeof(FontNameEntryRec)); 20143f32c10Smrg if(font->names == NULL) { 20243f32c10Smrg fprintf(stderr, "Couldn't allocate names.\n"); 20343f32c10Smrg return -1; 20443f32c10Smrg } 20543f32c10Smrg i = 0; 20643f32c10Smrg 20743f32c10Smrg rc = FT_Get_BDF_Property(face, "COPYRIGHT", &prop); 20843f32c10Smrg if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { 20943f32c10Smrg font->names[i].nid = 0; 21043f32c10Smrg font->names[i].size = 2 * strlen(prop.u.atom); 21143f32c10Smrg font->names[i].value = makeUTF16((char*)prop.u.atom); 21243f32c10Smrg i++; 21343f32c10Smrg } 21443f32c10Smrg 21543f32c10Smrg font->names[i].nid = 1; 21643f32c10Smrg font->names[i].size = 2 * strlen(face->family_name); 21743f32c10Smrg font->names[i].value = makeUTF16(face->family_name); 21843f32c10Smrg i++; 21943f32c10Smrg 22043f32c10Smrg font->names[i].nid = 2; 22143f32c10Smrg font->names[i].size = 2 * strlen(face->style_name); 22243f32c10Smrg font->names[i].value = makeUTF16(face->style_name); 22343f32c10Smrg i++; 22443f32c10Smrg 22543f32c10Smrg font->names[i].nid = 3; 22643f32c10Smrg font->names[i].size = 2 * strlen(unique_name); 22743f32c10Smrg font->names[i].value = makeUTF16(unique_name); 22843f32c10Smrg i++; 22943f32c10Smrg 23043f32c10Smrg font->names[i].nid = 4; 23143f32c10Smrg font->names[i].size = 2 * strlen(full_name); 23243f32c10Smrg font->names[i].value = makeUTF16(full_name); 23343f32c10Smrg i++; 23443f32c10Smrg 23543f32c10Smrg font->names[i].nid = 5; 23643f32c10Smrg font->names[i].size = 2 * strlen("Version 0.0"); 23743f32c10Smrg font->names[i].value = makeUTF16("Version 0.0"); 23843f32c10Smrg i++; 23943f32c10Smrg 24043f32c10Smrg rc = FT_Get_BDF_Property(face, "FOUNDRY", &prop); 24143f32c10Smrg if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { 24243f32c10Smrg font->names[i].nid = 8; 24343f32c10Smrg font->names[i].size = 2 * strlen(prop.u.atom); 24443f32c10Smrg font->names[i].value = makeUTF16((char*)prop.u.atom); 24543f32c10Smrg i++; 24643f32c10Smrg } 24743f32c10Smrg 24843f32c10Smrg font->names[i].nid = 10; 24943f32c10Smrg font->names[i].size = 2 * strlen(XVENDORNAMESHORT 25043f32c10Smrg " converted bitmap font"); 25143f32c10Smrg font->names[i].value = makeUTF16(XVENDORNAMESHORT 252ea148d1dSmrg " converted bitmap font"); 25343f32c10Smrg i++; 25443f32c10Smrg#ifdef __VENDORWEBSUPPORT__ 25543f32c10Smrg font->names[i].nid = 11; 25643f32c10Smrg font->names[i].size = 2 * strlen(__VENDORWEBSUPPORT__); 25743f32c10Smrg font->names[i].value = makeUTF16(__VENDORWEBSUPPORT__); 25843f32c10Smrg i++; 25943f32c10Smrg#endif 26043f32c10Smrg font->numNames = i; 26143f32c10Smrg 26243f32c10Smrg font->flags = faceFlags(face) | (symbol ? FACE_SYMBOL : 0); 26343f32c10Smrg font->weight = faceWeight(face); 26443f32c10Smrg font->width = faceWidth(face); 26543f32c10Smrg font->foundry = faceFoundry(face); 26643f32c10Smrg font->italicAngle = faceItalicAngle(face); 26743f32c10Smrg 26843f32c10Smrg rc = FT_Get_BDF_Property(face, "UNDERLINE_POSITION", &prop); 26943f32c10Smrg if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER) 27043f32c10Smrg font->underlinePosition = 27143f32c10Smrg (double)prop.u.integer / face->available_sizes[0].height * 27243f32c10Smrg TWO_SIXTEENTH; 27343f32c10Smrg else 27443f32c10Smrg font->underlinePosition = 27543f32c10Smrg - 1.5 / face->available_sizes[0].height * TWO_SIXTEENTH; 27643f32c10Smrg 27743f32c10Smrg rc = FT_Get_BDF_Property(face, "UNDERLINE_THICKNESS", &prop); 27843f32c10Smrg if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER) 27943f32c10Smrg font->underlineThickness = 28043f32c10Smrg (double)prop.u.integer / face->available_sizes[0].height * 28143f32c10Smrg TWO_SIXTEENTH; 28243f32c10Smrg else 28343f32c10Smrg font->underlineThickness = 28443f32c10Smrg 1.0 / face->available_sizes[0].height * TWO_SIXTEENTH; 28543f32c10Smrg } 28643f32c10Smrg 28743f32c10Smrg if(face->num_fixed_sizes == 0) { 28843f32c10Smrg fprintf(stderr, "No bitmaps in face.\n"); 28943f32c10Smrg return -1; 29043f32c10Smrg } 29143f32c10Smrg 292ea148d1dSmrg if((!symbol && !mapping) || force_unicode) { 29343f32c10Smrg rc = FT_Select_Charmap(face, ft_encoding_unicode); 294ea148d1dSmrg } else { 29543f32c10Smrg rc = FT_Select_Charmap(face, ft_encoding_none); 296ea148d1dSmrg if(rc != 0) { 297ea148d1dSmrg /* BDF will default to Adobe Standard even for nonstandard 298ea148d1dSmrg * encodings, so try that as a last resort. */ 299ea148d1dSmrg rc = FT_Select_Charmap(face, ft_encoding_adobe_standard); 300ea148d1dSmrg } 301ea148d1dSmrg } 30243f32c10Smrg if(rc != 0) { 30343f32c10Smrg fprintf(stderr, "Couldn't select character map: %x.\n", rc); 30443f32c10Smrg return -1; 30543f32c10Smrg } 30643f32c10Smrg 3076ef05171Smrg for(int i = 0; i < face->num_fixed_sizes; i++) { 30843f32c10Smrg if(verbose_flag) 30943f32c10Smrg fprintf(stderr, "size %d: %dx%d\n", 31043f32c10Smrg i, 311ea148d1dSmrg (int)((face->available_sizes[i].x_ppem + 32) >> 6), 312ea148d1dSmrg (int)((face->available_sizes[i].y_ppem + 32) >> 6)); 31343f32c10Smrg 31443f32c10Smrg rc = FT_Set_Pixel_Sizes(face, 315ea148d1dSmrg (face->available_sizes[i].x_ppem + 32) >> 6, 316ea148d1dSmrg (face->available_sizes[i].y_ppem + 32) >> 6); 31743f32c10Smrg if(rc != 0) { 31843f32c10Smrg fprintf(stderr, "Couldn't set size.\n"); 31943f32c10Smrg return -1; 32043f32c10Smrg } 32143f32c10Smrg 32243f32c10Smrg strike = makeStrike(font, 323ea148d1dSmrg (face->available_sizes[i].x_ppem + 32) >> 6, 324ea148d1dSmrg (face->available_sizes[i].y_ppem + 32) >> 6); 32543f32c10Smrg if(strike == NULL) { 32643f32c10Smrg fprintf(stderr, "Couldn't allocate strike.\n"); 32743f32c10Smrg return -1; 32843f32c10Smrg } 32943f32c10Smrg 33043f32c10Smrg for(j = 0; j < FONT_CODES; j++) { 33143f32c10Smrg if(mapping) 33243f32c10Smrg k = reverse->reverse(j, reverse->data); 33343f32c10Smrg else 33443f32c10Smrg k = j; 33543f32c10Smrg if(k <= 0 && j != 0) 33643f32c10Smrg continue; 33743f32c10Smrg index = FT_Get_Char_Index(face, k); 33843f32c10Smrg if(j != 0 && index == 0) 33943f32c10Smrg continue; 34043f32c10Smrg rc = FT_Load_Glyph(face, index, 34143f32c10Smrg FT_LOAD_RENDER | FT_LOAD_MONOCHROME); 34243f32c10Smrg if(rc != 0) { 34343f32c10Smrg fprintf(stderr, "Couldn't load glyph for U+%04X (%d)\n", 34443f32c10Smrg j, index); 34543f32c10Smrg continue; 34643f32c10Smrg } 34743f32c10Smrg bitmap = makeBitmap(strike, j, 34843f32c10Smrg FT_Pos_UP(face->glyph->metrics.horiAdvance), 34943f32c10Smrg FT_Pos_DOWN(face->glyph->metrics.horiBearingX), 35043f32c10Smrg FT_Pos_DOWN(face->glyph->metrics.horiBearingY), 35143f32c10Smrg face->glyph->bitmap.width, 35243f32c10Smrg face->glyph->bitmap.rows, 35343f32c10Smrg face->glyph->bitmap.pitch, 35443f32c10Smrg face->glyph->bitmap.buffer, 35543f32c10Smrg crop_flag); 35643f32c10Smrg 35743f32c10Smrg if(bitmap == NULL) { 35843f32c10Smrg fprintf(stderr, "Couldn't create bitmap.\n"); 35943f32c10Smrg return -1; 36043f32c10Smrg } 36143f32c10Smrg } 36243f32c10Smrg } 36343f32c10Smrg 36443f32c10Smrg FT_Done_Face(face); 365ea148d1dSmrg free(input.stream); 36643f32c10Smrg 36743f32c10Smrg j = 0; 3686ef05171Smrg for(int i = 0; i < FONT_CODES; i++) { 36943f32c10Smrg int found = 0; 37043f32c10Smrg strike = font->strikes; 37143f32c10Smrg while(strike) { 37243f32c10Smrg bitmap = STRIKE_BITMAP(strike, i); 37343f32c10Smrg if(bitmap) { 37443f32c10Smrg bitmap->index = j; 37543f32c10Smrg found = 1; 37643f32c10Smrg } else { 37743f32c10Smrg if(i == 0) { 37843f32c10Smrg fprintf(stderr, 37943f32c10Smrg "Warning: no bitmap for the undefined glyph.\n"); 38043f32c10Smrg found = 1; 38143f32c10Smrg } 38243f32c10Smrg } 38343f32c10Smrg strike = strike->next; 38443f32c10Smrg } 38543f32c10Smrg if(found) 38643f32c10Smrg j++; 38743f32c10Smrg } 38843f32c10Smrg return 0; 38943f32c10Smrg} 390