read.c revision d2f28e1b
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_MODULE_H 31#include FT_BDF_H 32#include FT_FONT_FORMATS_H 33#include "X11/Xos.h" 34#include "fonttosfnt.h" 35#include "X11/fonts/fontenc.h" 36 37#define FLOOR2(x, y) ((x) >= 0 ? (x) / (y) : -(((-(x)) + (y) - 1) / (y))) 38#define CEIL2(x, y) (FLOOR2((x) + (y) - 1, (y))) 39#define FT_Pos_DOWN(x) (FLOOR2((x),64)) 40#define FT_Pos_UP(x) (CEIL2((x), 64)) 41#define MIN(x, y) (((x) <= (y)) ? (x) : (y)) 42#define STREAM_FILE(stream) ((FILE*)stream->descriptor.pointer) 43 44static int ft_inited = 0; 45static FT_Library ft_library; 46 47static int 48FT_Ensure_Inited(void) 49{ 50 int rc; 51 if(ft_inited) 52 return 0; 53 54 rc = FT_Init_FreeType(&ft_library); 55 if(rc != 0) 56 return rc; 57 58 ft_inited = 1; 59 return 0; 60} 61 62static unsigned long 63forwardRead(FT_Stream stream, unsigned long offset, unsigned char *buffer, 64 unsigned long count) { 65 unsigned char skip_buffer[BUFSIZ]; 66 unsigned long skip_count; 67 FILE *file = STREAM_FILE(stream); 68 69 /* We may be asked to skip forward, but by not doing so we increase our 70 chance of survival. */ 71 if(count == 0) 72 return ferror(file) == 0 ? 0 : 1; 73 74 if(offset < stream->pos) { 75 fprintf(stderr, "Cannot move backward in input stream.\n"); 76 return 0; 77 } 78 while((skip_count = MIN(BUFSIZ, offset - stream->pos))) { 79 if(fread(skip_buffer, sizeof(*skip_buffer), skip_count, file) < 80 skip_count) 81 return 0; 82 stream->pos += sizeof(*skip_buffer) * skip_count; 83 } 84 85 return (unsigned long)fread(buffer, sizeof(*buffer), count, file); 86} 87 88static void 89streamClose(FT_Stream stream) { 90 fclose(STREAM_FILE(stream)); 91 stream->descriptor.pointer = NULL; 92 stream->size = 0; 93} 94 95int 96readFile(char *filename, FontPtr font) 97{ 98 int j, k, index; 99 int rc; 100 FT_Open_Args input = { 0 }; 101 FT_Face face; 102 StrikePtr strike; 103 BitmapPtr bitmap; 104 int symbol = 0; 105 int force_unicode = 1; 106 const char *family_name, *encoding_name, *file_format; 107 FontMapPtr mapping = NULL; 108 FontMapReversePtr reverse = NULL; 109 110 111 rc = FT_Ensure_Inited(); 112 if(rc != 0) 113 return rc; 114 115 if(filename != NULL) { 116 input.pathname = filename; 117 input.flags = FT_OPEN_PATHNAME; 118 } else { 119 input.flags = FT_OPEN_STREAM | FT_OPEN_DRIVER; 120 input.driver = FT_Get_Module(ft_library, "bdf"); 121 input.stream = calloc(1, sizeof(FT_StreamRec)); 122 if(input.stream == NULL) 123 return -1; 124 125 input.stream->size = 0x7FFFFFFF; 126 input.stream->descriptor.pointer = stdin; 127 input.stream->read = forwardRead; 128 input.stream->close = streamClose; 129 } 130 rc = FT_Open_Face(ft_library, &input, 0, &face); 131 if(rc != 0) { 132 fprintf(stderr, "Couldn't open face %s.\n", 133 filename ? filename : "<stdin>"); 134 return -1; 135 } 136 137 file_format = FT_Get_Font_Format(face); 138 if(strcmp(file_format, "BDF") != 0) 139 fprintf(stderr, 140 "font file %s is of format %s.\n" 141 "It's recommended to convert directly from a BDF font.\n" 142 "Some font properties may get lost when converting via a PCF font.\n", 143 filename ? filename : "<stdin>", 144 file_format); 145 146 /* FreeType will insist on encodings which are simple subsets of unicode 147 * to be read as unicode regardless of what we call them. */ 148 for(j = 0; j < face->num_charmaps; ++j) { 149 if((face->charmaps[j]->encoding == ft_encoding_none) || 150 (face->charmaps[j]->encoding == ft_encoding_adobe_standard)) { 151 force_unicode = 0; 152 break; 153 } 154 } 155 156 encoding_name = faceEncoding(face); 157 if(encoding_name == NULL) { 158 symbol = 1; 159 } else if(strcasecmp(encoding_name, "iso10646-1") != 0) { 160 if(reencode_flag) 161 mapping = FontEncMapFind(encoding_name, 162 FONT_ENCODING_UNICODE, 0, 0, NULL); 163 if(mapping == NULL) { 164 symbol = 1; 165 } else { 166 reverse = FontMapReverse(mapping); 167 if(reverse == NULL) { 168 fprintf(stderr, "Couldn't reverse mapping.\n"); 169 return -1; 170 } 171 } 172 } 173 174 if(face->family_name) 175 family_name = face->family_name; 176 else 177 family_name = faceStringProp(face, "FONT"); 178 179 if(verbose_flag) { 180 fprintf(stderr, "%s %s %s: %d sizes%s\n", 181 filename ? filename : "<stdin>", 182 face->family_name, face->style_name, face->num_fixed_sizes, 183 symbol ? " (symbol)" : ""); 184 } 185 186 if(font->numNames == 0 && face->style_name && family_name) { 187 char *full_name, *unique_name, *buf; 188 int i; 189 if(strcmp(face->style_name, "Regular") == 0) 190 full_name = sprintf_alloc("%s", family_name); 191 else 192 full_name = sprintf_alloc("%s %s", 193 family_name, face->style_name); 194 195 /* The unique name doesn't actually need to be globally 196 unique; it only needs to be unique among all installed fonts on a 197 Windows system. We don't bother getting it quite right. */ 198 if(face->num_fixed_sizes <= 0) 199 unique_name = sprintf_alloc("%s "XVENDORNAMESHORT" bitmap", 200 full_name); 201 else if(face->available_sizes[0].width == 202 face->available_sizes[0].height) 203 unique_name = sprintf_alloc("%s "XVENDORNAMESHORT 204 " bitmap size %d", 205 full_name, 206 face->available_sizes[0].height); 207 else 208 unique_name = sprintf_alloc("%s "XVENDORNAMESHORT 209 " bitmap size %dx%d", 210 full_name, 211 face->available_sizes[0].width, 212 face->available_sizes[0].height); 213 214 font->names = malloc(10 * sizeof(FontNameEntryRec)); 215 if(font->names == NULL) { 216 fprintf(stderr, "Couldn't allocate names.\n"); 217 return -1; 218 } 219 i = 0; 220 221 buf = faceStringProp(face, "COPYRIGHT"); 222 if(buf) { 223 font->names[i].nid = 0; 224 font->names[i].size = 2 * strlen(buf); 225 font->names[i].value = makeUTF16(buf); 226 free(buf); 227 i++; 228 } 229 230 font->names[i].nid = 1; 231 font->names[i].size = 2 * strlen(family_name); 232 font->names[i].value = makeUTF16(family_name); 233 i++; 234 235 font->names[i].nid = 2; 236 font->names[i].size = 2 * strlen(face->style_name); 237 font->names[i].value = makeUTF16(face->style_name); 238 i++; 239 240 font->names[i].nid = 3; 241 font->names[i].size = 2 * strlen(unique_name); 242 font->names[i].value = makeUTF16(unique_name); 243 i++; 244 245 font->names[i].nid = 4; 246 font->names[i].size = 2 * strlen(full_name); 247 font->names[i].value = makeUTF16(full_name); 248 i++; 249 250 font->names[i].nid = 5; 251 font->names[i].size = 2 * strlen("Version 0.0"); 252 font->names[i].value = makeUTF16("Version 0.0"); 253 i++; 254 255 buf = faceStringProp(face, "FOUNDRY"); 256 if(buf) { 257 font->names[i].nid = 8; 258 font->names[i].size = 2 * strlen(buf); 259 font->names[i].value = makeUTF16(buf); 260 free(buf); 261 i++; 262 } 263 264 font->names[i].nid = 10; 265 font->names[i].size = 2 * strlen(XVENDORNAMESHORT 266 " converted bitmap font"); 267 font->names[i].value = makeUTF16(XVENDORNAMESHORT 268 " converted bitmap font"); 269 i++; 270#ifdef __VENDORWEBSUPPORT__ 271 font->names[i].nid = 11; 272 font->names[i].size = 2 * strlen(__VENDORWEBSUPPORT__); 273 font->names[i].value = makeUTF16(__VENDORWEBSUPPORT__); 274 i++; 275#endif 276 font->numNames = i; 277 } 278 279 if(face->num_fixed_sizes == 0) { 280 fprintf(stderr, "No bitmaps in face.\n"); 281 return -1; 282 } 283 284 if((!symbol && !mapping) || force_unicode) { 285 rc = FT_Select_Charmap(face, ft_encoding_unicode); 286 } else { 287 rc = FT_Select_Charmap(face, ft_encoding_none); 288 if(rc != 0) { 289 /* BDF will default to Adobe Standard even for nonstandard 290 * encodings, so try that as a last resort. */ 291 rc = FT_Select_Charmap(face, ft_encoding_adobe_standard); 292 } 293 } 294 if(rc != 0) { 295 fprintf(stderr, "Couldn't select character map: %x.\n", rc); 296 return -1; 297 } 298 299 font->flags = faceFlags(face) | (symbol ? FACE_SYMBOL : 0); 300 font->weight = faceWeight(face); 301 font->width = faceWidth(face); 302 font->foundry = faceFoundry(face); 303 font->italicAngle = faceItalicAngle(face); 304 font->pxMetrics.height = face->available_sizes[0].height; 305 font->pxMetrics.size = faceIntProp(face, "PIXEL_SIZE"); 306 font->pxMetrics.xHeight = faceIntProp(face, "X_HEIGHT"); 307 font->pxMetrics.capHeight = faceIntProp(face, "CAP_HEIGHT"); 308 font->pxMetrics.ascent = faceIntProp(face, "FONT_ASCENT"); 309 font->pxMetrics.descent = faceIntProp(face, "FONT_DESCENT"); 310 font->pxMetrics.underlinePosition = faceIntProp(face, "UNDERLINE_POSITION"); 311 font->pxMetrics.underlineThickness = faceIntProp(face, "UNDERLINE_THICKNESS"); 312 313 for(int i = 0; i < face->num_fixed_sizes; i++) { 314 if(verbose_flag) 315 fprintf(stderr, "size %d: %dx%d\n", 316 i, 317 (int)((face->available_sizes[i].x_ppem + 32) >> 6), 318 (int)((face->available_sizes[i].y_ppem + 32) >> 6)); 319 320 rc = FT_Set_Pixel_Sizes(face, 321 (face->available_sizes[i].x_ppem + 32) >> 6, 322 (face->available_sizes[i].y_ppem + 32) >> 6); 323 if(rc != 0) { 324 fprintf(stderr, "Couldn't set size.\n"); 325 return -1; 326 } 327 328 strike = makeStrike(font, 329 (face->available_sizes[i].x_ppem + 32) >> 6, 330 (face->available_sizes[i].y_ppem + 32) >> 6); 331 if(strike == NULL) { 332 fprintf(stderr, "Couldn't allocate strike.\n"); 333 return -1; 334 } 335 336 for(j = 0; j < FONT_CODES; j++) { 337 if(mapping) 338 k = reverse->reverse(j, reverse->data); 339 else 340 k = j; 341 if(k <= 0 && j != 0) 342 continue; 343 index = FT_Get_Char_Index(face, k); 344 if(j != 0 && index == 0) 345 continue; 346 rc = FT_Load_Glyph(face, index, 347 FT_LOAD_RENDER | FT_LOAD_MONOCHROME); 348 if(rc != 0) { 349 fprintf(stderr, "Couldn't load glyph for U+%04X (%d)\n", 350 j, index); 351 continue; 352 } 353 bitmap = makeBitmap(strike, j, 354 FT_Pos_UP(face->glyph->metrics.horiAdvance), 355 FT_Pos_DOWN(face->glyph->metrics.horiBearingX), 356 FT_Pos_DOWN(face->glyph->metrics.horiBearingY), 357 face->glyph->bitmap.width, 358 face->glyph->bitmap.rows, 359 face->glyph->bitmap.pitch, 360 face->glyph->bitmap.buffer, 361 crop_flag); 362 363 if(bitmap == NULL) { 364 fprintf(stderr, "Couldn't create bitmap.\n"); 365 return -1; 366 } 367 } 368 } 369 370 FT_Done_Face(face); 371 free(input.stream); 372 373 j = 0; 374 for(int i = 0; i < FONT_CODES; i++) { 375 int found = 0; 376 strike = font->strikes; 377 while(strike) { 378 bitmap = STRIKE_BITMAP(strike, i); 379 if(bitmap) { 380 bitmap->index = j; 381 found = 1; 382 } else { 383 if(i == 0) { 384 fprintf(stderr, 385 "Warning: no bitmap for the undefined glyph.\n"); 386 found = 1; 387 } 388 } 389 strike = strike->next; 390 } 391 if(found) 392 j++; 393 } 394 return 0; 395} 396