struct.c revision 3ef3f551
1/* 2Copyright (c) 2002-2003 by Juliusz Chroboczek 3 4Permission is hereby granted, free of charge, to any person obtaining a copy 5of this software and associated documentation files (the "Software"), to deal 6in the Software without restriction, including without limitation the rights 7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8copies of the Software, and to permit persons to whom the Software is 9furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20THE SOFTWARE. 21*/ 22/* $XFree86: xc/programs/fonttosfnt/struct.c,v 1.3 2003/10/24 20:38:11 tsi Exp $ */ 23 24#include <stdlib.h> 25#include <stdio.h> 26#include <ft2build.h> 27#include FT_FREETYPE_H 28#include "fonttosfnt.h" 29 30FontPtr 31makeFont(void) 32{ 33 FontPtr font; 34 35 font = malloc(sizeof(FontRec)); 36 if(font == NULL) 37 return NULL; 38 39 font->numNames = 0; 40 font->names = NULL; 41 font->flags = 0; 42 font->weight = 500; 43 font->width = 5; 44 font->italicAngle = 0; 45 font->pxMetrics.height = UNDEF; 46 font->pxMetrics.maxX = UNDEF; 47 font->pxMetrics.minX = UNDEF; 48 font->pxMetrics.maxY = UNDEF; 49 font->pxMetrics.minY = UNDEF; 50 font->pxMetrics.xHeight = UNDEF; 51 font->pxMetrics.capHeight = UNDEF; 52 font->pxMetrics.maxAwidth = UNDEF; 53 font->pxMetrics.awidth = UNDEF; 54 font->pxMetrics.ascent = UNDEF; 55 font->pxMetrics.descent = UNDEF; 56 font->pxMetrics.underlinePosition = UNDEF; 57 font->pxMetrics.underlineThickness = UNDEF; 58 font->metrics.height = UNDEF; 59 font->metrics.maxX = UNDEF; 60 font->metrics.minX = UNDEF; 61 font->metrics.maxY = UNDEF; 62 font->metrics.minY = UNDEF; 63 font->metrics.xHeight = UNDEF; 64 font->metrics.capHeight = UNDEF; 65 font->metrics.maxAwidth = UNDEF; 66 font->metrics.awidth = UNDEF; 67 font->metrics.ascent = UNDEF; 68 font->metrics.descent = UNDEF; 69 font->metrics.underlinePosition = UNDEF; 70 font->metrics.underlineThickness = UNDEF; 71 font->foundry = makeName("UNKN"); 72 font->strikes = NULL; 73 return font; 74} 75 76StrikePtr 77makeStrike(FontPtr font, int sizeX, int sizeY) 78{ 79 StrikePtr strike, last_strike; 80 81 strike = font->strikes; 82 last_strike = NULL; 83 while(strike) { 84 if(strike->sizeX == sizeX && strike->sizeY == sizeY) 85 return strike; 86 last_strike = strike; 87 strike = strike->next; 88 } 89 90 strike = malloc(sizeof(StrikeRec)); 91 if(strike == NULL) 92 return NULL; 93 strike->sizeX = sizeX; 94 strike->sizeY = sizeY; 95 strike->bitmaps = 96 calloc(FONT_CODES / FONT_SEGMENT_SIZE, sizeof(BitmapPtr*)); 97 if(strike->bitmaps == NULL) { 98 free(strike); 99 return NULL; 100 } 101 strike->numSbits = 0; 102 strike->next = NULL; 103 strike->bitmapSizeTableLocation = 0xDEADFACE; 104 strike->indexSubTables = NULL; 105 if(last_strike) 106 last_strike->next = strike; 107 else 108 font->strikes = strike; 109 return strike; 110} 111 112BitmapPtr 113makeBitmap(StrikePtr strike, int code, 114 int advanceWidth, int horiBearingX, int horiBearingY, 115 int width, int height, int stride, unsigned char *raster, int crop) 116{ 117 BitmapPtr bitmap; 118 int i, j, x, y; 119 int dx, dy, new_width, new_height; 120 121 bitmap = malloc(sizeof(BitmapRec)); 122 if(bitmap == NULL) 123 return NULL; 124 125 bitmap->index = -1; 126 bitmap->width = 0; 127 bitmap->height = 0; 128 bitmap->stride = 0; 129 bitmap->raster = NULL; 130 bitmap->location = 0xDEADFACE; 131 132 i = code / FONT_SEGMENT_SIZE; 133 j = code % FONT_SEGMENT_SIZE; 134 135 if(strike->bitmaps[i] == NULL) { 136 strike->bitmaps[i] = calloc(FONT_SEGMENT_SIZE, sizeof(BitmapPtr)); 137 } 138 if(strike->bitmaps[i] == NULL) { 139 free(bitmap); 140 return NULL; 141 } 142 if(strike->bitmaps[i][j] != NULL) { 143 if(verbose_flag) 144 fprintf(stderr, "Duplicate bitmap %d.\n", code); 145 free(bitmap); 146 return strike->bitmaps[i][j]; 147 } 148 149 dx = 0; 150 dy = 0; 151 new_width = width; 152 new_height = height; 153 154 if(crop) { 155 int empty; 156 while(new_width > 0) { 157 empty = 1; 158 x = new_width - 1; 159 for(y = 0; y < new_height; y++) { 160 if(BITREF(raster, stride, x + dx, y + dy)) { 161 empty = 0; 162 break; 163 } 164 } 165 if(empty) 166 new_width--; 167 else 168 break; 169 } 170 while(new_height > 0) { 171 empty = 1; 172 y = new_height - 1; 173 for(x = 0; x < new_width; x++) { 174 if(BITREF(raster, stride, x + dx, y + dy)) { 175 empty = 0; 176 break; 177 } 178 } 179 if(empty) 180 new_height--; 181 else 182 break; 183 } 184 while(new_width > 0) { 185 empty = 1; 186 x = 0; 187 for(y = 0; y < new_height; y++) { 188 if(BITREF(raster, stride, x + dx, y + dy)) { 189 empty = 0; 190 break; 191 } 192 } 193 if(empty) { 194 dx++; 195 new_width--; 196 } else 197 break; 198 } 199 while(new_height > 0) { 200 empty = 1; 201 y = 0; 202 for(x = 0; x < new_width; x++) { 203 if(BITREF(raster, stride, x + dx, y + dy)) { 204 empty = 0; 205 break; 206 } 207 } 208 if(empty) { 209 dy++; 210 new_height--; 211 } else 212 break; 213 } 214 } 215 216 217 bitmap->advanceWidth = advanceWidth; 218 bitmap->horiBearingX = horiBearingX + dx; 219 bitmap->horiBearingY = horiBearingY - dy; 220 bitmap->width = new_width; 221 bitmap->height = new_height; 222 bitmap->stride = (new_width + 7) / 8; 223 224 bitmap->raster = malloc(bitmap->height * bitmap->stride); 225 if(bitmap->raster == NULL) { 226 free(bitmap); 227 return NULL; 228 } 229 memset(bitmap->raster, 0, bitmap->height * bitmap->stride); 230 for(y = 0; y < new_height; y++) { 231 for(x = 0; x < new_width; x++) { 232 if(BITREF(raster, stride, x + dx, y + dy)) 233 bitmap->raster[y * bitmap->stride + x / 8] |= 234 1 << (7 - (x % 8)); 235 } 236 } 237 strike->bitmaps[i][j] = bitmap; 238 strike->numSbits++; 239 240 return bitmap; 241} 242 243IndexSubTablePtr 244makeIndexSubTables(StrikePtr strike, CmapPtr cmap) 245{ 246 IndexSubTablePtr table, first, last; 247 BitmapPtr bitmap0, bitmap; 248 int index, n; 249 250 first = NULL; 251 last = NULL; 252 253 /* Assuming that we're writing bit-aligned data, small metrics 254 and short offsets, a constant metrics segment saves 5 bytes 255 per glyph in the EBDT table, and 2 bytes per glyph in the EBLC 256 table. On the other hand, the overhead for a supplementary 257 type 2 indexSubTable is 8 bytes for the indexSubTableArray 258 entry and 20 bytes for the subtable itself. It's worth 259 splitting at 5 glyphs. There's no analogue of a type 2 260 indexSubTable with byte-aligned data, so we don't bother 261 splitting when byte-aligning. */ 262 index = 0; 263 while(index < 0xFFFF) { 264 int constantMetrics = 1; 265 bitmap0 = strikeBitmapIndex(strike, cmap, index); 266 if(bitmap0 == NULL) { 267 index++; 268 continue; 269 } 270 n = 1; 271 while((bitmap = strikeBitmapIndex(strike, cmap, index + n)) != NULL) { 272 if(constantMetrics) { 273 if(!SAME_METRICS(bitmap0, bitmap)) { 274 if(bit_aligned_flag && n >= 4) 275 break; 276 else 277 constantMetrics = 0; 278 } 279 } else if(bit_aligned_flag) { 280 BitmapPtr b1 = strikeBitmapIndex(strike, cmap, index + n + 1); 281 BitmapPtr b2 = strikeBitmapIndex(strike, cmap, index + n + 2); 282 BitmapPtr b3 = strikeBitmapIndex(strike, cmap, index + n + 3); 283 BitmapPtr b4 = strikeBitmapIndex(strike, cmap, index + n + 4); 284 if(b1 && b2 && b3 && b4 && 285 SAME_METRICS(bitmap, b1) && 286 SAME_METRICS(bitmap, b2) && 287 SAME_METRICS(bitmap, b3) && 288 SAME_METRICS(bitmap, b4)) { 289 break; 290 } 291 } 292 n++; 293 } 294 if(n <= 1) 295 constantMetrics = 0; 296 297 table = malloc(sizeof(IndexSubTableRec)); 298 table->firstGlyphIndex = index; 299 table->lastGlyphIndex = index + n - 1; 300 table->constantMetrics = constantMetrics; 301 table->location = 0xDEADFACE; 302 table->lastLocation = 0xDEADFACE; 303 table->next = NULL; 304 305 if(first == NULL) { 306 first = table; 307 last = table; 308 } else { 309 last->next = table; 310 last = table; 311 } 312 index += n; 313 } 314 return first; 315} 316 317int 318fontIndex(FontPtr font, int code) 319{ 320 StrikePtr strike; 321 BitmapPtr bitmap; 322 323 if(code == 0) 324 return 0; 325 strike = font->strikes; 326 while(strike) { 327 bitmap = STRIKE_BITMAP(strike, code); 328 if(bitmap) 329 return bitmap->index; 330 strike = strike->next; 331 } 332 return -1; 333} 334 335CmapPtr 336makeCmap(FontPtr font) 337{ 338 CmapPtr cmap_head = NULL; 339 CmapPtr cmap_last = NULL; 340 CmapPtr cmap; 341 int code, i, index, maxindex = 0; 342 343 code = 0; 344 while(code < FONT_CODES) { 345 index = fontIndex(font, code); 346 if(index < 0) { 347 code++; 348 continue; 349 } 350 i = 1; 351 while(code + i < FONT_CODES && 352 fontIndex(font, code + i) == index + i) { 353 i++; 354 } 355 cmap = malloc(sizeof(CmapRec)); 356 if(cmap == NULL) 357 return NULL; 358 cmap->startCode = code; 359 cmap->endCode = code + i - 1; 360 cmap->index = index; 361 cmap->next = NULL; 362 cmap->maxindex = 0; 363 if(maxindex < index + i - 1) 364 maxindex = index + i - 1; 365 if(cmap_head == NULL) 366 cmap_head = cmap; 367 else 368 cmap_last->next = cmap; 369 cmap_last = cmap; 370 371 code += i; 372 } 373 cmap_head->maxindex = maxindex; 374 cmap_head->inverse = calloc(maxindex + 1, sizeof(int)); 375 cmap = cmap_head; 376 while(cmap) { 377 for(i = cmap->index; 378 i <= cmap->endCode - cmap->startCode + cmap->index; i++) { 379 cmap_head->inverse[i] = 380 i - cmap->index + cmap->startCode; 381 } 382 cmap = cmap->next; 383 } 384 385 return cmap_head; 386} 387 388int 389findIndex(CmapPtr cmap_head, int code) 390{ 391 CmapPtr cmap; 392 cmap = cmap_head; 393 while(cmap) { 394 if(cmap->endCode > code) 395 return -1; 396 if(cmap->startCode <= code) 397 return cmap->index + code - cmap->startCode; 398 cmap = cmap->next; 399 } 400 return -1; 401} 402 403int 404findCode(CmapPtr cmap_head, int index) 405{ 406 if(index < 0 || index > cmap_head->maxindex) 407 return -1; 408 return cmap_head->inverse[index]; 409 410} 411 412int 413maxIndex(CmapPtr cmap_head) 414{ 415 return cmap_head->maxindex; 416} 417 418BitmapPtr 419strikeBitmapIndex(StrikePtr strike, CmapPtr cmap, int index) 420{ 421 int code = findCode(cmap, index); 422 if(code < 0) 423 return NULL; 424 425 return STRIKE_BITMAP(strike, code); 426} 427 428int 429strikeMaxWidth(StrikePtr strike) 430{ 431 BitmapPtr bitmap; 432 int i; 433 int width_max = 0; 434 435 for(i = 0; i < FONT_CODES; i++) { 436 bitmap = STRIKE_BITMAP(strike, i); 437 if(!bitmap) 438 continue; 439 if(bitmap->advanceWidth > width_max) 440 width_max = bitmap->advanceWidth; 441 } 442 443 return width_max; 444} 445 446int 447glyphMetrics(FontPtr font, int code, 448 int *width_return, 449 int *x_min_return, int *y_min_return, 450 int *x_max_return, int *y_max_return) 451{ 452 StrikePtr strike; 453 BitmapPtr bitmap; 454 455 strike = font->strikes; 456 while(strike) { 457 bitmap = STRIKE_BITMAP(strike, code); 458 if(bitmap) { 459 if(width_return) 460 *width_return = 461 (((float)bitmap->advanceWidth) / strike->sizeX) * 462 TWO_SIXTEENTH; 463 if(x_min_return) 464 *x_min_return = 465 ((float)bitmap->horiBearingX / strike->sizeX) * 466 TWO_SIXTEENTH; 467 if(y_min_return) 468 *y_min_return = 469 (((float)bitmap->horiBearingY - bitmap->height) 470 / strike->sizeY) * TWO_SIXTEENTH; 471 if(x_max_return) 472 *x_max_return = 473 (((float)bitmap->horiBearingX + bitmap->width) 474 / strike->sizeX) * TWO_SIXTEENTH; 475 if(y_max_return) 476 *y_max_return = 477 (((float)bitmap->horiBearingY) / strike->sizeY) * 478 TWO_SIXTEENTH; 479 return 1; 480 } 481 strike = strike->next; 482 } 483 484 return -1; 485} 486