1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 /* 29 * TrueTypeCreator method implementation 30 * 31 * @author: Alexander Gelfenbain 32 * 33 */ 34 35 #if OSL_DEBUG_LEVEL == 0 36 # ifndef NDEBUG 37 # define NDEBUG 38 # endif 39 #endif 40 #include <assert.h> 41 42 #include "ttcr.hxx" 43 #include "list.h" 44 #include "string.h" 45 46 47 48 namespace vcl 49 { 50 51 /* 52 * Private Data Types 53 */ 54 55 struct _TrueTypeCreator { 56 sal_uInt32 tag; /**< TrueType file tag */ 57 list tables; /**< List of table tags and pointers */ 58 }; 59 60 /* These must be #defined so that they can be used in initializers */ 61 #define T_maxp 0x6D617870 62 #define T_glyf 0x676C7966 63 #define T_head 0x68656164 64 #define T_loca 0x6C6F6361 65 #define T_name 0x6E616D65 66 #define T_hhea 0x68686561 67 #define T_hmtx 0x686D7478 68 #define T_cmap 0x636D6170 69 #define T_vhea 0x76686561 70 #define T_vmtx 0x766D7478 71 #define T_OS2 0x4F532F32 72 #define T_post 0x706F7374 73 #define T_kern 0x6B65726E 74 #define T_cvt 0x63767420 75 76 typedef struct { 77 sal_uInt32 tag; 78 sal_uInt32 length; 79 sal_uInt8 *data; 80 } TableEntry; 81 82 /* 83 * this is a duplicate code from sft.c but it is left here for performance reasons 84 */ 85 #ifdef __GNUC__ 86 #define _inline static __inline__ 87 #else 88 #define _inline static 89 #endif 90 91 _inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) { 92 return (a << 24) | (b << 16) | (c << 8) | d; 93 } 94 95 /*- Data access macros for data stored in big-endian or little-endian format */ 96 _inline sal_Int16 GetInt16( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian) 97 { 98 sal_Int16 t; 99 assert(ptr != 0); 100 101 if (bigendian) { 102 t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; 103 } else { 104 t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; 105 } 106 107 return t; 108 } 109 110 _inline sal_uInt16 GetUInt16( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian) 111 { 112 sal_uInt16 t; 113 assert(ptr != 0); 114 115 if (bigendian) { 116 t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; 117 } else { 118 t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; 119 } 120 121 return t; 122 } 123 124 _inline sal_Int32 GetInt32( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian) 125 { 126 sal_Int32 t; 127 assert(ptr != 0); 128 129 if (bigendian) { 130 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | 131 (ptr+offset)[2] << 8 | (ptr+offset)[3]; 132 } else { 133 t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | 134 (ptr+offset)[1] << 8 | (ptr+offset)[0]; 135 } 136 137 return t; 138 } 139 140 _inline sal_uInt32 GetUInt32( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian) 141 { 142 sal_uInt32 t; 143 assert(ptr != 0); 144 145 146 if (bigendian) { 147 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | 148 (ptr+offset)[2] << 8 | (ptr+offset)[3]; 149 } else { 150 t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | 151 (ptr+offset)[1] << 8 | (ptr+offset)[0]; 152 } 153 154 return t; 155 } 156 157 158 _inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) 159 { 160 assert(ptr != 0); 161 162 if (bigendian) { 163 ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); 164 ptr[offset+1] = (sal_uInt8)(val & 0xFF); 165 } else { 166 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); 167 ptr[offset] = (sal_uInt8)(val & 0xFF); 168 } 169 } 170 171 _inline void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) 172 { 173 assert(ptr != 0); 174 175 if (bigendian) { 176 ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); 177 ptr[offset+1] = (sal_uInt8)(val & 0xFF); 178 } else { 179 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); 180 ptr[offset] = (sal_uInt8)(val & 0xFF); 181 } 182 } 183 184 _inline void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) 185 { 186 assert(ptr != 0); 187 188 if (bigendian) { 189 ptr[offset] = (sal_uInt8)((val >> 24) & 0xFF); 190 ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF); 191 ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF); 192 ptr[offset+3] = (sal_uInt8)(val & 0xFF); 193 } else { 194 ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF); 195 ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF); 196 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); 197 ptr[offset] = (sal_uInt8)(val & 0xFF); 198 } 199 200 } 201 202 203 _inline void PutInt32(sal_Int32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) 204 { 205 assert(ptr != 0); 206 207 if (bigendian) { 208 ptr[offset] = (sal_uInt8)((val >> 24) & 0xFF); 209 ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF); 210 ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF); 211 ptr[offset+3] = (sal_uInt8)(val & 0xFF); 212 } else { 213 ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF); 214 ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF); 215 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); 216 ptr[offset] = (sal_uInt8)(val & 0xFF); 217 } 218 219 } 220 221 static int TableEntryCompareF(const void *l, const void *r) 222 { 223 return ((const TableEntry *) l)->tag - ((const TableEntry *) r)->tag; 224 } 225 226 static int NameRecordCompareF(const void *l, const void *r) 227 { 228 NameRecord *ll = (NameRecord *) l; 229 NameRecord *rr = (NameRecord *) r; 230 231 if (ll->platformID != rr->platformID) { 232 return ll->platformID - rr->platformID; 233 } else if (ll->encodingID != rr->encodingID) { 234 return ll->encodingID - rr->encodingID; 235 } else if (ll->languageID != rr->languageID) { 236 return ll->languageID - rr->languageID; 237 } else if (ll->nameID != rr->nameID) { 238 return ll->nameID - rr->nameID; 239 } 240 return 0; 241 } 242 243 244 static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length) 245 { 246 sal_uInt32 sum = 0; 247 sal_uInt32 *endptr = ptr + ((length + 3) & (sal_uInt32) ~3) / 4; 248 249 while (ptr < endptr) sum += *ptr++; 250 251 return sum; 252 } 253 254 _inline void *smalloc(sal_uInt32 size) 255 { 256 void *res = malloc(size); 257 assert(res != 0); 258 return res; 259 } 260 261 _inline void *scalloc(sal_uInt32 n, sal_uInt32 size) 262 { 263 void *res = calloc(n, size); 264 assert(res != 0); 265 return res; 266 } 267 268 /* 269 * Public functions 270 */ 271 272 void TrueTypeCreatorNewEmpty(sal_uInt32 tag, TrueTypeCreator **_this) 273 { 274 TrueTypeCreator* ptr = (TrueTypeCreator*)smalloc(sizeof(TrueTypeCreator)); 275 276 ptr->tables = listNewEmpty(); 277 listSetElementDtor(ptr->tables, (list_destructor)TrueTypeTableDispose); 278 279 ptr->tag = tag; 280 281 *_this = ptr; 282 } 283 284 int AddTable(TrueTypeCreator *_this, TrueTypeTable *table) 285 { 286 if (table != 0) { 287 listAppend(_this->tables, table); 288 } 289 return SF_OK; 290 } 291 292 void RemoveTable(TrueTypeCreator *_this, sal_uInt32 tag) 293 { 294 int done = 0; 295 296 if (listCount(_this->tables)) { 297 listToFirst(_this->tables); 298 do { 299 if (((TrueTypeTable *) listCurrent(_this->tables))->tag == tag) { 300 listRemove(_this->tables); 301 } else { 302 if (listNext(_this->tables)) { 303 done = 1; 304 } 305 } 306 } while (!done); 307 } 308 } 309 310 static void ProcessTables(TrueTypeCreator *); 311 312 int StreamToMemory(TrueTypeCreator *_this, sal_uInt8 **ptr, sal_uInt32 *length) 313 { 314 sal_uInt16 numTables, searchRange=1, entrySelector=0, rangeShift; 315 sal_uInt32 s, offset, checkSumAdjustment = 0; 316 sal_uInt32 *p; 317 int i=0, n; 318 sal_uInt8 *head = NULL; /* saved pointer to the head table data for checkSumAdjustment calculation */ 319 320 if ((n = listCount(_this->tables)) == 0) return SF_TTFORMAT; 321 322 ProcessTables(_this); 323 324 /* ProcessTables() adds 'loca' and 'hmtx' */ 325 326 n = listCount(_this->tables); 327 numTables = (sal_uInt16) n; 328 329 330 TableEntry* te = (TableEntry*)scalloc(n, sizeof(TableEntry)); 331 332 listToFirst(_this->tables); 333 for (i = 0; i < n; i++) { 334 GetRawData((TrueTypeTable *) listCurrent(_this->tables), &te[i].data, &te[i].length, &te[i].tag); 335 listNext(_this->tables); 336 } 337 338 qsort(te, n, sizeof(TableEntry), TableEntryCompareF); 339 340 do { 341 searchRange *= 2; 342 entrySelector++; 343 } while (searchRange <= numTables); 344 345 searchRange *= 8; 346 entrySelector--; 347 rangeShift = numTables * 16 - searchRange; 348 349 s = offset = 12 + 16 * n; 350 351 for (i = 0; i < n; i++) { 352 s += (te[i].length + 3) & (sal_uInt32) ~3; 353 /* if ((te[i].length & 3) != 0) s += (4 - (te[i].length & 3)) & 3; */ 354 } 355 356 sal_uInt8* ttf = (sal_uInt8*)smalloc(s); 357 358 /* Offset Table */ 359 PutUInt32(_this->tag, ttf, 0, 1); 360 PutUInt16(numTables, ttf, 4, 1); 361 PutUInt16(searchRange, ttf, 6, 1); 362 PutUInt16(entrySelector, ttf, 8, 1); 363 PutUInt16(rangeShift, ttf, 10, 1); 364 365 /* Table Directory */ 366 for (i = 0; i < n; i++) { 367 PutUInt32(te[i].tag, ttf + 12, 16 * i, 1); 368 PutUInt32(CheckSum((sal_uInt32 *) te[i].data, te[i].length), ttf + 12, 16 * i + 4, 1); 369 PutUInt32(offset, ttf + 12, 16 * i + 8, 1); 370 PutUInt32(te[i].length, ttf + 12, 16 * i + 12, 1); 371 372 if (te[i].tag == T_head) { 373 head = ttf + offset; 374 } 375 376 memcpy(ttf+offset, te[i].data, (te[i].length + 3) & (sal_uInt32) ~3 ); 377 offset += (te[i].length + 3) & (sal_uInt32) ~3; 378 /* if ((te[i].length & 3) != 0) offset += (4 - (te[i].length & 3)) & 3; */ 379 } 380 381 free(te); 382 383 p = (sal_uInt32 *) ttf; 384 for (i = 0; i < (int)s / 4; i++) checkSumAdjustment += p[i]; 385 PutUInt32(0xB1B0AFBA - checkSumAdjustment, head, 8, 1); 386 387 *ptr = ttf; 388 *length = s; 389 390 return SF_OK; 391 } 392 393 int StreamToFile(TrueTypeCreator *_this, const char* fname) 394 { 395 sal_uInt8 *ptr; 396 sal_uInt32 length; 397 int r; 398 FILE* fd; 399 400 if ((r = StreamToMemory(_this, &ptr, &length)) != SF_OK) return r; 401 if (!fname) return SF_BADFILE; 402 if ((fd = fopen(fname, "wb")) == NULL) return SF_BADFILE; 403 404 if (fwrite(ptr, 1, length, fd) != length) { 405 r = SF_FILEIO; 406 } else { 407 r = SF_OK; 408 } 409 410 fclose(fd); 411 free(ptr); 412 return r; 413 } 414 415 416 417 /* 418 * TrueTypeTable private methods 419 */ 420 421 #define TABLESIZE_head 54 422 #define TABLESIZE_hhea 36 423 #define TABLESIZE_maxp 32 424 425 426 427 /* Table data points to 428 * -------------------------------------------- 429 * generic tdata_generic struct 430 * 'head' TABLESIZE_head bytes of memory 431 * 'hhea' TABLESIZE_hhea bytes of memory 432 * 'loca' tdata_loca struct 433 * 'maxp' TABLESIZE_maxp bytes of memory 434 * 'glyf' list of GlyphData structs (defined in sft.h) 435 * 'name' list of NameRecord structs (defined in sft.h) 436 * 'post' tdata_post struct 437 * 438 */ 439 440 441 #define CMAP_SUBTABLE_INIT 10 442 #define CMAP_SUBTABLE_INCR 10 443 #define CMAP_PAIR_INIT 500 444 #define CMAP_PAIR_INCR 500 445 446 typedef struct { 447 sal_uInt32 id; /* subtable ID (platform/encoding ID) */ 448 sal_uInt32 n; /* number of used translation pairs */ 449 sal_uInt32 m; /* number of allocated translation pairs */ 450 sal_uInt32 *xc; /* character array */ 451 sal_uInt32 *xg; /* glyph array */ 452 } CmapSubTable; 453 454 typedef struct { 455 sal_uInt32 n; /* number of used CMAP sub-tables */ 456 sal_uInt32 m; /* number of allocated CMAP sub-tables */ 457 CmapSubTable *s; /* sotred array of sub-tables */ 458 } table_cmap; 459 460 typedef struct { 461 sal_uInt32 tag; 462 sal_uInt32 nbytes; 463 sal_uInt8 *ptr; 464 } tdata_generic; 465 466 typedef struct { 467 sal_uInt32 nbytes; /* number of bytes in loca table */ 468 sal_uInt8 *ptr; /* pointer to the data */ 469 } tdata_loca; 470 471 typedef struct { 472 sal_uInt32 format; 473 sal_uInt32 italicAngle; 474 sal_Int16 underlinePosition; 475 sal_Int16 underlineThickness; 476 sal_uInt32 isFixedPitch; 477 void *ptr; /* format-specific pointer */ 478 } tdata_post; 479 480 481 /* allocate memory for a TT table */ 482 static sal_uInt8 *ttmalloc(sal_uInt32 nbytes) 483 { 484 sal_uInt32 n; 485 486 n = (nbytes + 3) & (sal_uInt32) ~3; 487 sal_uInt8* res = (sal_uInt8*)malloc(n); 488 assert(res != 0); 489 memset(res, 0, n); 490 491 return res; 492 } 493 494 static void FreeGlyphData(void *ptr) 495 { 496 GlyphData *p = (GlyphData *) ptr; 497 if (p->ptr) free(p->ptr); 498 free(p); 499 } 500 501 static void TrueTypeTableDispose_generic(TrueTypeTable *_this) 502 { 503 if (_this) { 504 if (_this->data) { 505 tdata_generic *pdata = (tdata_generic *) _this->data; 506 if (pdata->nbytes) free(pdata->ptr); 507 free(_this->data); 508 } 509 free(_this); 510 } 511 } 512 513 static void TrueTypeTableDispose_head(TrueTypeTable *_this) 514 { 515 if (_this) { 516 if (_this->data) free(_this->data); 517 free(_this); 518 } 519 } 520 521 static void TrueTypeTableDispose_hhea(TrueTypeTable *_this) 522 { 523 if (_this) { 524 if (_this->data) free(_this->data); 525 free(_this); 526 } 527 } 528 529 static void TrueTypeTableDispose_loca(TrueTypeTable *_this) 530 { 531 if (_this) { 532 if (_this->data) { 533 tdata_loca *p = (tdata_loca *) _this->data; 534 if (p->ptr) free(p->ptr); 535 free(_this->data); 536 } 537 free(_this); 538 } 539 } 540 541 static void TrueTypeTableDispose_maxp(TrueTypeTable *_this) 542 { 543 if (_this) { 544 if (_this->data) free(_this->data); 545 free(_this); 546 } 547 } 548 549 static void TrueTypeTableDispose_glyf(TrueTypeTable *_this) 550 { 551 if (_this) { 552 if (_this->data) listDispose((list) _this->data); 553 free(_this); 554 } 555 } 556 557 static void TrueTypeTableDispose_cmap(TrueTypeTable *_this) 558 { 559 table_cmap *t; 560 CmapSubTable *s; 561 sal_uInt32 i; 562 563 if (_this) { 564 t = (table_cmap *) _this->data; 565 if (t) { 566 s = t->s; 567 if (s) { 568 for (i = 0; i < t->m; i++) { 569 if (s[i].xc) free(s[i].xc); 570 if (s[i].xg) free(s[i].xg); 571 } 572 free(s); 573 } 574 free(t); 575 } 576 free(_this); 577 } 578 } 579 580 static void TrueTypeTableDispose_name(TrueTypeTable *_this) 581 { 582 if (_this) { 583 if (_this->data) listDispose((list) _this->data); 584 free(_this); 585 } 586 } 587 588 static void TrueTypeTableDispose_post(TrueTypeTable *_this) 589 { 590 if (_this) { 591 tdata_post *p = (tdata_post *) _this->data; 592 if (p) { 593 if (p->format == 0x00030000) { 594 /* do nothing */ 595 } else { 596 fprintf(stderr, "Unsupported format of a 'post' table: %08X.\n", (int)p->format); 597 } 598 free(p); 599 } 600 free(_this); 601 } 602 } 603 604 /* destructor vtable */ 605 606 static struct { 607 sal_uInt32 tag; 608 void (*f)(TrueTypeTable *); 609 } vtable1[] = 610 { 611 {0, TrueTypeTableDispose_generic}, 612 {T_head, TrueTypeTableDispose_head}, 613 {T_hhea, TrueTypeTableDispose_hhea}, 614 {T_loca, TrueTypeTableDispose_loca}, 615 {T_maxp, TrueTypeTableDispose_maxp}, 616 {T_glyf, TrueTypeTableDispose_glyf}, 617 {T_cmap, TrueTypeTableDispose_cmap}, 618 {T_name, TrueTypeTableDispose_name}, 619 {T_post, TrueTypeTableDispose_post} 620 621 }; 622 623 static int GetRawData_generic(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 624 { 625 assert(_this != 0); 626 assert(_this->data != 0); 627 628 *ptr = ((tdata_generic *) _this->data)->ptr; 629 *len = ((tdata_generic *) _this->data)->nbytes; 630 *tag = ((tdata_generic *) _this->data)->tag; 631 632 return TTCR_OK; 633 } 634 635 636 static int GetRawData_head(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 637 { 638 *len = TABLESIZE_head; 639 *ptr = (sal_uInt8 *) _this->data; 640 *tag = T_head; 641 642 return TTCR_OK; 643 } 644 645 static int GetRawData_hhea(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 646 { 647 *len = TABLESIZE_hhea; 648 *ptr = (sal_uInt8 *) _this->data; 649 *tag = T_hhea; 650 651 return TTCR_OK; 652 } 653 654 static int GetRawData_loca(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 655 { 656 tdata_loca *p; 657 658 assert(_this->data != 0); 659 660 p = (tdata_loca *) _this->data; 661 662 if (p->nbytes == 0) return TTCR_ZEROGLYPHS; 663 664 *ptr = p->ptr; 665 *len = p->nbytes; 666 *tag = T_loca; 667 668 return TTCR_OK; 669 } 670 671 static int GetRawData_maxp(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 672 { 673 *len = TABLESIZE_maxp; 674 *ptr = (sal_uInt8 *) _this->data; 675 *tag = T_maxp; 676 677 return TTCR_OK; 678 } 679 680 static int GetRawData_glyf(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 681 { 682 sal_uInt32 n, nbytes = 0; 683 list l = (list) _this->data; 684 /* sal_uInt16 curID = 0; */ /* to check if glyph IDs are sequential and start from zero */ 685 sal_uInt8 *p; 686 687 *ptr = 0; 688 *len = 0; 689 *tag = 0; 690 691 if (listCount(l) == 0) return TTCR_ZEROGLYPHS; 692 693 listToFirst(l); 694 do { 695 /* if (((GlyphData *) listCurrent(l))->glyphID != curID++) return TTCR_GLYPHSEQ; */ 696 nbytes += ((GlyphData *) listCurrent(l))->nbytes; 697 } while (listNext(l)); 698 699 p = _this->rawdata = ttmalloc(nbytes); 700 701 listToFirst(l); 702 do { 703 n = ((GlyphData *) listCurrent(l))->nbytes; 704 if (n != 0) { 705 memcpy(p, ((GlyphData *) listCurrent(l))->ptr, n); 706 p += n; 707 } 708 } while (listNext(l)); 709 710 *len = nbytes; 711 *ptr = _this->rawdata; 712 *tag = T_glyf; 713 714 return TTCR_OK; 715 } 716 717 /* cmap packers */ 718 static sal_uInt8 *PackCmapType0(CmapSubTable *s, sal_uInt32 *length) 719 { 720 sal_uInt8* ptr = (sal_uInt8*)smalloc(262); 721 sal_uInt8 *p = ptr + 6; 722 sal_uInt32 i, j; 723 sal_uInt16 g; 724 725 PutUInt16(0, ptr, 0, 1); 726 PutUInt16(262, ptr, 2, 1); 727 PutUInt16(0, ptr, 4, 1); 728 729 for (i = 0; i < 256; i++) { 730 g = 0; 731 for (j = 0; j < s->n; j++) { 732 if (s->xc[j] == i) { 733 g = (sal_uInt16) s->xg[j]; 734 } 735 } 736 p[i] = (sal_uInt8) g; 737 } 738 *length = 262; 739 return ptr; 740 } 741 742 static sal_uInt8 *PackCmapType6(CmapSubTable *s, sal_uInt32 *length) 743 { 744 sal_uInt8* ptr = (sal_uInt8*)smalloc(s->n*2 + 10); 745 sal_uInt8 *p = ptr + 10; 746 sal_uInt32 i, j; 747 sal_uInt16 g; 748 749 PutUInt16(6, ptr, 0, 1); 750 PutUInt16((sal_uInt16)(s->n*2+10), ptr, 2, 1); 751 PutUInt16(0, ptr, 4, 1); 752 PutUInt16(0, ptr, 6, 1); 753 PutUInt16((sal_uInt16)(s->n), ptr, 8, 1 ); 754 755 for (i = 0; i < s->n; i++) { 756 g = 0; 757 for (j = 0; j < s->n; j++) { 758 if (s->xc[j] == i) { 759 g = (sal_uInt16) s->xg[j]; 760 } 761 } 762 PutUInt16( g, p, 2*i, 1 ); 763 } 764 *length = s->n*2+10; 765 return ptr; 766 } 767 768 769 770 /* XXX it only handles Format 0 encoding tables */ 771 static sal_uInt8 *PackCmap(CmapSubTable *s, sal_uInt32 *length) 772 { 773 if( s->xg[s->n-1] > 0xff ) 774 return PackCmapType6(s, length); 775 else 776 return PackCmapType0(s, length); 777 } 778 779 static int GetRawData_cmap(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 780 { 781 table_cmap *t; 782 sal_uInt32 i; 783 sal_uInt32 tlen = 0; 784 sal_uInt32 l; 785 sal_uInt32 cmapsize; 786 sal_uInt8 *cmap; 787 sal_uInt32 coffset; 788 789 assert(_this != 0); 790 t = (table_cmap *) _this->data; 791 assert(t != 0); 792 assert(t->n != 0); 793 794 sal_uInt8** subtables = (sal_uInt8**)scalloc(t->n, sizeof(sal_uInt8 *)); 795 sal_uInt32* sizes = (sal_uInt32*)scalloc(t->n, sizeof(sal_uInt32)); 796 797 for (i = 0; i < t->n; i++) { 798 subtables[i] = PackCmap(t->s+i, &l); 799 sizes[i] = l; 800 tlen += l; 801 } 802 803 cmapsize = tlen + 4 + 8 * t->n; 804 _this->rawdata = cmap = ttmalloc(cmapsize); 805 806 PutUInt16(0, cmap, 0, 1); 807 PutUInt16((sal_uInt16)t->n, cmap, 2, 1); 808 coffset = 4 + t->n * 8; 809 810 for (i = 0; i < t->n; i++) { 811 PutUInt16((sal_uInt16)(t->s[i].id >> 16), cmap + 4, i * 8, 1); 812 PutUInt16((sal_uInt16)(t->s[i].id & 0xFF), cmap + 4, 2 + i * 8, 1); 813 PutUInt32(coffset, cmap + 4, 4 + i * 8, 1); 814 memcpy(cmap + coffset, subtables[i], sizes[i]); 815 free(subtables[i]); 816 coffset += sizes[i]; 817 } 818 819 free(subtables); 820 free(sizes); 821 822 *ptr = cmap; 823 *len = cmapsize; 824 *tag = T_cmap; 825 826 return TTCR_OK; 827 } 828 829 830 static int GetRawData_name(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 831 { 832 list l; 833 sal_Int16 i=0, n; /* number of Name Records */ 834 int stringLen = 0; 835 sal_uInt8 *p1, *p2; 836 837 *ptr = 0; 838 *len = 0; 839 *tag = 0; 840 841 assert(_this != 0); 842 l = (list) _this->data; 843 assert(l != 0); 844 845 if ((n = (sal_Int16)listCount(l)) == 0) return TTCR_NONAMES; 846 847 NameRecord* nr = (NameRecord*)scalloc(n, sizeof(NameRecord)); 848 849 listToFirst(l); 850 851 do { 852 memcpy(nr+i, listCurrent(l), sizeof(NameRecord)); 853 stringLen += nr[i].slen; 854 i++; 855 } while (listNext(l)); 856 857 if (stringLen > 65535) { 858 free(nr); 859 return TTCR_NAMETOOLONG; 860 } 861 862 qsort(nr, n, sizeof(NameRecord), NameRecordCompareF); 863 864 int nameLen = stringLen + 12 * n + 6; 865 sal_uInt8* name = (sal_uInt8*)ttmalloc(nameLen); 866 867 PutUInt16(0, name, 0, 1); 868 PutUInt16(n, name, 2, 1); 869 PutUInt16((sal_uInt16)(6 + 12 * n), name, 4, 1); 870 871 p1 = name + 6; 872 p2 = p1 + 12 * n; 873 874 for (i = 0; i < n; i++) { 875 PutUInt16(nr[i].platformID, p1, 0, 1); 876 PutUInt16(nr[i].encodingID, p1, 2, 1); 877 PutUInt16(nr[i].languageID, p1, 4, 1); 878 PutUInt16(nr[i].nameID, p1, 6, 1); 879 PutUInt16(nr[i].slen, p1, 8, 1); 880 PutUInt16((sal_uInt16)(p2 - (name + 6 + 12 * n)), p1, 10, 1); 881 memcpy(p2, nr[i].sptr, nr[i].slen); 882 /* {int j; for(j=0; j<nr[i].slen; j++) printf("%c", nr[i].sptr[j]); printf("\n"); }; */ 883 p2 += nr[i].slen; 884 p1 += 12; 885 } 886 887 free(nr); 888 _this->rawdata = name; 889 890 *ptr = name; 891 *len = (sal_uInt16)nameLen; 892 *tag = T_name; 893 894 /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */ 895 896 return TTCR_OK; 897 } 898 899 static int GetRawData_post(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 900 { 901 tdata_post *p = (tdata_post *) _this->data; 902 sal_uInt8 *post = 0; 903 sal_uInt32 postLen = 0; 904 int ret; 905 906 if (_this->rawdata) free(_this->rawdata); 907 908 if (p->format == 0x00030000) { 909 postLen = 32; 910 post = ttmalloc(postLen); 911 PutUInt32(0x00030000, post, 0, 1); 912 PutUInt32(p->italicAngle, post, 4, 1); 913 PutUInt16(p->underlinePosition, post, 8, 1); 914 PutUInt16(p->underlineThickness, post, 10, 1); 915 PutUInt16((sal_uInt16)p->isFixedPitch, post, 12, 1); 916 ret = TTCR_OK; 917 } else { 918 fprintf(stderr, "Unrecognized format of a post table: %08X.\n", (int)p->format); 919 ret = TTCR_POSTFORMAT; 920 } 921 922 *ptr = _this->rawdata = post; 923 *len = postLen; 924 *tag = T_post; 925 926 return ret; 927 } 928 929 930 931 932 933 static struct { 934 sal_uInt32 tag; 935 int (*f)(TrueTypeTable *, sal_uInt8 **, sal_uInt32 *, sal_uInt32 *); 936 } vtable2[] = 937 { 938 {0, GetRawData_generic}, 939 {T_head, GetRawData_head}, 940 {T_hhea, GetRawData_hhea}, 941 {T_loca, GetRawData_loca}, 942 {T_maxp, GetRawData_maxp}, 943 {T_glyf, GetRawData_glyf}, 944 {T_cmap, GetRawData_cmap}, 945 {T_name, GetRawData_name}, 946 {T_post, GetRawData_post} 947 948 949 }; 950 951 /* 952 * TrueTypeTable public methods 953 */ 954 955 /* Note: Type42 fonts only need these tables: 956 * head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm 957 * 958 * Microsoft required tables 959 * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post, OS/2 960 * 961 * Apple required tables 962 * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post 963 * 964 */ 965 966 TrueTypeTable *TrueTypeTableNew(sal_uInt32 tag, 967 sal_uInt32 nbytes, 968 const sal_uInt8* ptr) 969 { 970 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); 971 tdata_generic* pdata = (tdata_generic*)smalloc(sizeof(tdata_generic)); 972 pdata->nbytes = nbytes; 973 pdata->tag = tag; 974 if (nbytes) { 975 pdata->ptr = ttmalloc(nbytes); 976 memcpy(pdata->ptr, ptr, nbytes); 977 } else { 978 pdata->ptr = 0; 979 } 980 981 table->tag = 0; 982 table->data = pdata; 983 table->rawdata = 0; 984 985 return table; 986 } 987 988 TrueTypeTable *TrueTypeTableNew_head(sal_uInt32 fontRevision, 989 sal_uInt16 flags, 990 sal_uInt16 unitsPerEm, 991 const sal_uInt8* created, 992 sal_uInt16 macStyle, 993 sal_uInt16 lowestRecPPEM, 994 sal_Int16 fontDirectionHint) 995 { 996 assert(created != 0); 997 998 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); 999 sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_head); 1000 1001 1002 PutUInt32(0x00010000, ptr, 0, 1); /* version */ 1003 PutUInt32(fontRevision, ptr, 4, 1); 1004 PutUInt32(0x5F0F3CF5, ptr, 12, 1); /* magic number */ 1005 PutUInt16(flags, ptr, 16, 1); 1006 PutUInt16(unitsPerEm, ptr, 18, 1); 1007 memcpy(ptr+20, created, 8); /* Created Long Date */ 1008 memset(ptr+28, 0, 8); /* Modified Long Date */ 1009 PutUInt16(macStyle, ptr, 44, 1); 1010 PutUInt16(lowestRecPPEM, ptr, 46, 1); 1011 PutUInt16(fontDirectionHint, ptr, 48, 1); 1012 PutUInt16(0, ptr, 52, 1); /* glyph data format: 0 */ 1013 1014 table->data = (void *) ptr; 1015 table->tag = T_head; 1016 table->rawdata = 0; 1017 1018 return table; 1019 } 1020 1021 TrueTypeTable *TrueTypeTableNew_hhea(sal_Int16 ascender, 1022 sal_Int16 descender, 1023 sal_Int16 linegap, 1024 sal_Int16 caretSlopeRise, 1025 sal_Int16 caretSlopeRun) 1026 { 1027 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); 1028 sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_hhea); 1029 1030 PutUInt32(0x00010000, ptr, 0, 1); /* version */ 1031 PutUInt16(ascender, ptr, 4, 1); 1032 PutUInt16(descender, ptr, 6, 1); 1033 PutUInt16(linegap, ptr, 8, 1); 1034 PutUInt16(caretSlopeRise, ptr, 18, 1); 1035 PutUInt16(caretSlopeRun, ptr, 20, 1); 1036 PutUInt16(0, ptr, 22, 1); /* reserved 1 */ 1037 PutUInt16(0, ptr, 24, 1); /* reserved 2 */ 1038 PutUInt16(0, ptr, 26, 1); /* reserved 3 */ 1039 PutUInt16(0, ptr, 28, 1); /* reserved 4 */ 1040 PutUInt16(0, ptr, 30, 1); /* reserved 5 */ 1041 PutUInt16(0, ptr, 32, 1); /* metricDataFormat */ 1042 1043 table->data = (void *) ptr; 1044 table->tag = T_hhea; 1045 table->rawdata = 0; 1046 1047 return table; 1048 } 1049 1050 TrueTypeTable *TrueTypeTableNew_loca(void) 1051 { 1052 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); 1053 table->data = smalloc(sizeof(tdata_loca)); 1054 1055 ((tdata_loca *)table->data)->nbytes = 0; 1056 ((tdata_loca *)table->data)->ptr = 0; 1057 1058 table->tag = T_loca; 1059 table->rawdata = 0; 1060 1061 return table; 1062 } 1063 1064 TrueTypeTable *TrueTypeTableNew_maxp( const sal_uInt8* maxp, int size) 1065 { 1066 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); 1067 table->data = ttmalloc(TABLESIZE_maxp); 1068 1069 if (maxp && size == TABLESIZE_maxp) { 1070 memcpy(table->data, maxp, TABLESIZE_maxp); 1071 } 1072 1073 table->tag = T_maxp; 1074 table->rawdata = 0; 1075 1076 return table; 1077 } 1078 1079 TrueTypeTable *TrueTypeTableNew_glyf(void) 1080 { 1081 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); 1082 list l = listNewEmpty(); 1083 1084 assert(l != 0); 1085 1086 listSetElementDtor(l, (list_destructor)FreeGlyphData); 1087 1088 table->data = l; 1089 table->rawdata = 0; 1090 table->tag = T_glyf; 1091 1092 return table; 1093 } 1094 1095 TrueTypeTable *TrueTypeTableNew_cmap(void) 1096 { 1097 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); 1098 table_cmap* cmap = (table_cmap*)smalloc(sizeof(table_cmap)); 1099 1100 cmap->n = 0; 1101 cmap->m = CMAP_SUBTABLE_INIT; 1102 cmap->s = (CmapSubTable *) scalloc(CMAP_SUBTABLE_INIT, sizeof(CmapSubTable)); 1103 memset(cmap->s, 0, sizeof(CmapSubTable) * CMAP_SUBTABLE_INIT); 1104 1105 table->data = (table_cmap *) cmap; 1106 1107 table->rawdata = 0; 1108 table->tag = T_cmap; 1109 1110 return table; 1111 } 1112 1113 static void DisposeNameRecord(void *ptr) 1114 { 1115 if (ptr != 0) { 1116 NameRecord *nr = (NameRecord *) ptr; 1117 if (nr->sptr) free(nr->sptr); 1118 free(ptr); 1119 } 1120 } 1121 1122 static NameRecord* NameRecordNewCopy(NameRecord *nr) 1123 { 1124 NameRecord* p = (NameRecord*)smalloc(sizeof(NameRecord)); 1125 1126 memcpy(p, nr, sizeof(NameRecord)); 1127 1128 if (p->slen) { 1129 p->sptr = (sal_uInt8*)smalloc(p->slen); 1130 memcpy(p->sptr, nr->sptr, p->slen); 1131 } 1132 1133 return p; 1134 } 1135 1136 TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr) 1137 { 1138 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); 1139 list l = listNewEmpty(); 1140 1141 assert(l != 0); 1142 1143 listSetElementDtor(l, (list_destructor)DisposeNameRecord); 1144 1145 if (n != 0) { 1146 int i; 1147 for (i = 0; i < n; i++) { 1148 listAppend(l, NameRecordNewCopy(nr+i)); 1149 } 1150 } 1151 1152 table->data = l; 1153 table->rawdata = 0; 1154 table->tag = T_name; 1155 1156 return table; 1157 } 1158 1159 TrueTypeTable *TrueTypeTableNew_post(sal_uInt32 format, 1160 sal_uInt32 italicAngle, 1161 sal_Int16 underlinePosition, 1162 sal_Int16 underlineThickness, 1163 sal_uInt32 isFixedPitch) 1164 { 1165 assert(format == 0x00030000); /* Only format 3.0 is supported at this time */ 1166 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); 1167 tdata_post* post = (tdata_post*)smalloc(sizeof(tdata_post)); 1168 1169 post->format = format; 1170 post->italicAngle = italicAngle; 1171 post->underlinePosition = underlinePosition; 1172 post->underlineThickness = underlineThickness; 1173 post->isFixedPitch = isFixedPitch; 1174 post->ptr = 0; 1175 1176 table->data = post; 1177 table->rawdata = 0; 1178 table->tag = T_post; 1179 1180 return table; 1181 } 1182 1183 int GetRawData(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) 1184 { 1185 /* XXX do a binary search */ 1186 unsigned int i; 1187 1188 assert(_this != 0); 1189 assert(ptr != 0); 1190 assert(len != 0); 1191 assert(tag != 0); 1192 1193 *ptr = 0; *len = 0; *tag = 0; 1194 1195 if (_this->rawdata) { 1196 free(_this->rawdata); 1197 _this->rawdata = 0; 1198 } 1199 1200 for(i=0; i < sizeof(vtable2)/sizeof(*vtable2); i++) { 1201 if (_this->tag == vtable2[i].tag) { 1202 return vtable2[i].f(_this, ptr, len, tag); 1203 } 1204 } 1205 1206 assert(!"Unknwon TrueType table.\n"); 1207 return TTCR_UNKNOWN; 1208 } 1209 1210 void cmapAdd(TrueTypeTable *table, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g) 1211 { 1212 sal_uInt32 i, found; 1213 table_cmap *t; 1214 CmapSubTable *s; 1215 1216 assert(table != 0); 1217 assert(table->tag == T_cmap); 1218 t = (table_cmap *) table->data; assert(t != 0); 1219 s = t->s; assert(s != 0); 1220 1221 found = 0; 1222 1223 for (i = 0; i < t->n; i++) { 1224 if (s[i].id == id) { 1225 found = 1; 1226 break; 1227 } 1228 } 1229 1230 if (!found) { 1231 if (t->n == t->m) { 1232 CmapSubTable* tmp = (CmapSubTable*)scalloc(t->m + CMAP_SUBTABLE_INCR, sizeof(CmapSubTable)); 1233 memset(tmp, 0, t->m + CMAP_SUBTABLE_INCR * sizeof(CmapSubTable)); 1234 memcpy(tmp, s, sizeof(CmapSubTable) * t->m); 1235 t->m += CMAP_SUBTABLE_INCR; 1236 free(s); 1237 s = tmp; 1238 t->s = s; 1239 } 1240 1241 for (i = 0; i < t->n; i++) { 1242 if (s[i].id > id) break; 1243 } 1244 1245 if (i < t->n) { 1246 memmove(s+i+1, s+i, t->n-i); 1247 } 1248 1249 t->n++; 1250 1251 s[i].id = id; 1252 s[i].n = 0; 1253 s[i].m = CMAP_PAIR_INIT; 1254 s[i].xc = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32)); 1255 s[i].xg = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32)); 1256 } 1257 1258 if (s[i].n == s[i].m) { 1259 sal_uInt32* tmp1 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32)); 1260 sal_uInt32* tmp2 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32)); 1261 assert(tmp1 != 0); 1262 assert(tmp2 != 0); 1263 memcpy(tmp1, s[i].xc, sizeof(sal_uInt32) * s[i].m); 1264 memcpy(tmp2, s[i].xg, sizeof(sal_uInt32) * s[i].m); 1265 s[i].m += CMAP_PAIR_INCR; 1266 free(s[i].xc); 1267 free(s[i].xg); 1268 s[i].xc = tmp1; 1269 s[i].xg = tmp2; 1270 } 1271 1272 s[i].xc[s[i].n] = c; 1273 s[i].xg[s[i].n] = g; 1274 s[i].n++; 1275 } 1276 1277 sal_uInt32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, TrueTypeFont *fnt) 1278 { 1279 list l; 1280 sal_uInt32 currentID; 1281 int ret, n, ncomponents; 1282 GlyphData *gd; 1283 1284 assert(table != 0); 1285 assert(table->tag == T_glyf); 1286 1287 if (!glyphdata) return (sal_uInt32)~0; 1288 1289 std::vector< sal_uInt32 > glyphlist; 1290 1291 ncomponents = GetTTGlyphComponents(fnt, glyphdata->glyphID, glyphlist); 1292 1293 l = (list) table->data; 1294 if (listCount(l) > 0) { 1295 listToLast(l); 1296 ret = n = ((GlyphData *) listCurrent(l))->newID + 1; 1297 } else { 1298 ret = n = 0; 1299 } 1300 glyphdata->newID = n++; 1301 listAppend(l, glyphdata); 1302 1303 if (ncomponents > 1 && glyphlist.size() > 1 ) 1304 { 1305 std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin(); 1306 ++it; 1307 /* glyphData->glyphID is always the first glyph on the list */ 1308 do 1309 { 1310 int found = 0; 1311 currentID = *it; 1312 /* XXX expensive! should be rewritten with sorted arrays! */ 1313 listToFirst(l); 1314 do { 1315 if (((GlyphData *) listCurrent(l))->glyphID == currentID) { 1316 found = 1; 1317 break; 1318 } 1319 } while (listNext(l)); 1320 1321 if (!found) { 1322 gd = GetTTRawGlyphData(fnt, currentID); 1323 gd->newID = n++; 1324 listAppend(l, gd); 1325 } 1326 } while( ++it != glyphlist.end() ); 1327 } 1328 1329 return ret; 1330 } 1331 1332 sal_uInt32 glyfCount(const TrueTypeTable *table) 1333 { 1334 assert(table != 0); 1335 assert(table->tag == T_glyf); 1336 return listCount((list) table->data); 1337 } 1338 1339 1340 void nameAdd(TrueTypeTable *table, NameRecord *nr) 1341 { 1342 list l; 1343 1344 assert(table != 0); 1345 assert(table->tag == T_name); 1346 1347 l = (list) table->data; 1348 1349 listAppend(l, NameRecordNewCopy(nr)); 1350 } 1351 1352 static TrueTypeTable *FindTable(TrueTypeCreator *tt, sal_uInt32 tag) 1353 { 1354 if (listIsEmpty(tt->tables)) return 0; 1355 1356 listToFirst(tt->tables); 1357 1358 do { 1359 if (((TrueTypeTable *) listCurrent(tt->tables))->tag == tag) { 1360 return (TrueTypeTable*)listCurrent(tt->tables); 1361 } 1362 } while (listNext(tt->tables)); 1363 1364 return 0; 1365 } 1366 1367 /* This function processes all the tables and synchronizes them before creating 1368 * the output TrueType stream. 1369 * 1370 * *** It adds two TrueType tables to the font: 'loca' and 'hmtx' *** 1371 * 1372 * It does: 1373 * 1374 * - Re-numbers glyph IDs and creates 'glyf', 'loca', and 'hmtx' tables. 1375 * - Calculates xMin, yMin, xMax, and yMax and stores values in 'head' table. 1376 * - Stores indexToLocFormat in 'head' 1377 * - updates 'maxp' table 1378 * - Calculates advanceWidthMax, minLSB, minRSB, xMaxExtent and numberOfHMetrics 1379 * in 'hhea' table 1380 * 1381 */ 1382 static void ProcessTables(TrueTypeCreator *tt) 1383 { 1384 TrueTypeTable *glyf, *loca, *head, *maxp, *hhea; 1385 list glyphlist; 1386 sal_uInt32 nGlyphs, locaLen = 0, glyfLen = 0; 1387 sal_Int16 xMin = 0, yMin = 0, xMax = 0, yMax = 0; 1388 sal_uInt32 i = 0; 1389 sal_Int16 indexToLocFormat; 1390 sal_uInt8 *hmtxPtr, *hheaPtr; 1391 sal_uInt32 hmtxSize; 1392 sal_uInt8 *p1, *p2; 1393 sal_uInt16 maxPoints = 0, maxContours = 0, maxCompositePoints = 0, maxCompositeContours = 0; 1394 int nlsb = 0; 1395 sal_uInt32 *gid; /* array of old glyphIDs */ 1396 1397 glyf = FindTable(tt, T_glyf); 1398 glyphlist = (list) glyf->data; 1399 nGlyphs = listCount(glyphlist); 1400 assert(nGlyphs != 0); 1401 gid = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32)); 1402 1403 RemoveTable(tt, T_loca); 1404 RemoveTable(tt, T_hmtx); 1405 1406 /* XXX Need to make sure that composite glyphs do not break during glyph renumbering */ 1407 1408 listToFirst(glyphlist); 1409 do { 1410 GlyphData *gd = (GlyphData *) listCurrent(glyphlist); 1411 sal_Int16 z; 1412 glyfLen += gd->nbytes; 1413 /* XXX if (gd->nbytes & 1) glyfLen++; */ 1414 1415 1416 assert(gd->newID == i); 1417 gid[i++] = gd->glyphID; 1418 /* gd->glyphID = i++; */ 1419 1420 /* printf("IDs: %d %d.\n", gd->glyphID, gd->newID); */ 1421 1422 if (gd->nbytes != 0) { 1423 z = GetInt16(gd->ptr, 2, 1); 1424 if (z < xMin) xMin = z; 1425 1426 z = GetInt16(gd->ptr, 4, 1); 1427 if (z < yMin) yMin = z; 1428 1429 z = GetInt16(gd->ptr, 6, 1); 1430 if (z > xMax) xMax = z; 1431 1432 z = GetInt16(gd->ptr, 8, 1); 1433 if (z > yMax) yMax = z; 1434 } 1435 1436 if (gd->compflag == 0) { /* non-composite glyph */ 1437 if (gd->npoints > maxPoints) maxPoints = gd->npoints; 1438 if (gd->ncontours > maxContours) maxContours = gd->ncontours; 1439 } else { /* composite glyph */ 1440 if (gd->npoints > maxCompositePoints) maxCompositePoints = gd->npoints; 1441 if (gd->ncontours > maxCompositeContours) maxCompositeContours = gd->ncontours; 1442 } 1443 1444 } while (listNext(glyphlist)); 1445 1446 indexToLocFormat = (glyfLen / 2 > 0xFFFF) ? 1 : 0; 1447 locaLen = indexToLocFormat ? (nGlyphs + 1) << 2 : (nGlyphs + 1) << 1; 1448 1449 sal_uInt8* glyfPtr = ttmalloc(glyfLen); 1450 sal_uInt8* locaPtr = ttmalloc(locaLen); 1451 TTSimpleGlyphMetrics* met = (TTSimpleGlyphMetrics*)scalloc(nGlyphs, sizeof(TTSimpleGlyphMetrics)); 1452 i = 0; 1453 1454 listToFirst(glyphlist); 1455 p1 = glyfPtr; 1456 p2 = locaPtr; 1457 do { 1458 GlyphData *gd = (GlyphData *) listCurrent(glyphlist); 1459 1460 if (gd->compflag) { /* re-number all components */ 1461 sal_uInt16 flags, index; 1462 sal_uInt8 *ptr = gd->ptr + 10; 1463 do { 1464 sal_uInt32 j; 1465 flags = GetUInt16(ptr, 0, 1); 1466 index = GetUInt16(ptr, 2, 1); 1467 /* XXX use the sorted array of old to new glyphID mapping and do a binary search */ 1468 for (j = 0; j < nGlyphs; j++) { 1469 if (gid[j] == index) { 1470 break; 1471 } 1472 } 1473 /* printf("X: %d -> %d.\n", index, j); */ 1474 1475 PutUInt16((sal_uInt16) j, ptr, 2, 1); 1476 1477 ptr += 4; 1478 1479 if (flags & ARG_1_AND_2_ARE_WORDS) { 1480 ptr += 4; 1481 } else { 1482 ptr += 2; 1483 } 1484 1485 if (flags & WE_HAVE_A_SCALE) { 1486 ptr += 2; 1487 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { 1488 ptr += 4; 1489 } else if (flags & WE_HAVE_A_TWO_BY_TWO) { 1490 ptr += 8; 1491 } 1492 } while (flags & MORE_COMPONENTS); 1493 } 1494 1495 if (gd->nbytes != 0) { 1496 memcpy(p1, gd->ptr, gd->nbytes); 1497 } 1498 if (indexToLocFormat == 1) { 1499 PutUInt32(p1 - glyfPtr, p2, 0, 1); 1500 p2 += 4; 1501 } else { 1502 PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1); 1503 p2 += 2; 1504 } 1505 p1 += gd->nbytes; 1506 1507 /* fill the array of metrics */ 1508 met[i].adv = gd->aw; 1509 met[i].sb = gd->lsb; 1510 i++; 1511 } while (listNext(glyphlist)); 1512 1513 free(gid); 1514 1515 if (indexToLocFormat == 1) { 1516 PutUInt32(p1 - glyfPtr, p2, 0, 1); 1517 } else { 1518 PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1); 1519 } 1520 1521 glyf->rawdata = glyfPtr; 1522 1523 loca = TrueTypeTableNew_loca(); assert(loca != 0); 1524 ((tdata_loca *) loca->data)->ptr = locaPtr; 1525 ((tdata_loca *) loca->data)->nbytes = locaLen; 1526 1527 AddTable(tt, loca); 1528 1529 head = FindTable(tt, T_head); 1530 sal_uInt8* const pHeadData = (sal_uInt8*)head->data; 1531 PutInt16(xMin, pHeadData, 36, 1); 1532 PutInt16(yMin, pHeadData, 38, 1); 1533 PutInt16(xMax, pHeadData, 40, 1); 1534 PutInt16(yMax, pHeadData, 42, 1); 1535 PutInt16(indexToLocFormat, pHeadData, 50, 1); 1536 1537 maxp = FindTable(tt, T_maxp); 1538 1539 sal_uInt8* const pMaxpData = (sal_uInt8*)maxp->data; 1540 PutUInt16((sal_uInt16)nGlyphs, pMaxpData, 4, 1); 1541 PutUInt16(maxPoints, pMaxpData, 6, 1); 1542 PutUInt16(maxContours, pMaxpData, 8, 1); 1543 PutUInt16(maxCompositePoints, pMaxpData, 10, 1); 1544 PutUInt16(maxCompositeContours, pMaxpData, 12, 1); 1545 1546 #if 0 1547 /* XXX do not overwrite the existing data. Fix: re-calculate these numbers here */ 1548 PutUInt16(2, maxp->data, 14, 1); /* maxZones is always 2 */ 1549 PutUInt16(0, maxp->data, 16, 1); /* maxTwilightPoints */ 1550 PutUInt16(0, maxp->data, 18, 1); /* maxStorage */ 1551 PutUInt16(0, maxp->data, 20, 1); /* maxFunctionDefs */ 1552 PutUint16(0, maxp->data, 22, 1); /* maxInstructionDefs */ 1553 PutUint16(0, maxp->data, 24, 1); /* maxStackElements */ 1554 PutUint16(0, maxp->data, 26, 1); /* maxSizeOfInstructions */ 1555 PutUint16(0, maxp->data, 28, 1); /* maxComponentElements */ 1556 PutUint16(0, maxp->data, 30, 1); /* maxComponentDepth */ 1557 #endif 1558 1559 /* 1560 * Generate an htmx table and update hhea table 1561 */ 1562 hhea = FindTable(tt, T_hhea); assert(hhea != 0); 1563 hheaPtr = (sal_uInt8 *) hhea->data; 1564 if (nGlyphs > 2) { 1565 for (i = nGlyphs - 1; i > 0; i--) { 1566 if (met[i].adv != met[i-1].adv) break; 1567 } 1568 nlsb = nGlyphs - 1 - i; 1569 } 1570 hmtxSize = (nGlyphs - nlsb) * 4 + nlsb * 2; 1571 hmtxPtr = ttmalloc(hmtxSize); 1572 p1 = hmtxPtr; 1573 1574 for (i = 0; i < nGlyphs; i++) { 1575 if (i < nGlyphs - nlsb) { 1576 PutUInt16(met[i].adv, p1, 0, 1); 1577 PutUInt16(met[i].sb, p1, 2, 1); 1578 p1 += 4; 1579 } else { 1580 PutUInt16(met[i].sb, p1, 0, 1); 1581 p1 += 2; 1582 } 1583 } 1584 1585 AddTable(tt, TrueTypeTableNew(T_hmtx, hmtxSize, hmtxPtr)); 1586 PutUInt16((sal_uInt16)(nGlyphs - nlsb), hheaPtr, 34, 1); 1587 free(hmtxPtr); 1588 free(met); 1589 } 1590 1591 } // namespace vcl 1592 1593 extern "C" 1594 { 1595 /** 1596 * TrueTypeCreator destructor. It calls destructors for all TrueTypeTables added to it. 1597 */ 1598 void TrueTypeCreatorDispose(vcl::TrueTypeCreator *_this) 1599 { 1600 listDispose(_this->tables); 1601 free(_this); 1602 } 1603 1604 1605 /** 1606 * Destructor for the TrueTypeTable object. 1607 */ 1608 void TrueTypeTableDispose(vcl::TrueTypeTable *_this) 1609 { 1610 /* XXX do a binary search */ 1611 unsigned int i; 1612 1613 assert(_this != 0); 1614 1615 if (_this->rawdata) free(_this->rawdata); 1616 1617 for(i=0; i < sizeof(vcl::vtable1)/sizeof(*vcl::vtable1); i++) { 1618 if (_this->tag == vcl::vtable1[i].tag) { 1619 vcl::vtable1[i].f(_this); 1620 return; 1621 } 1622 } 1623 assert(!"Unknown TrueType table.\n"); 1624 } 1625 } 1626 1627 1628 #ifdef TEST_TTCR 1629 int main(void) 1630 { 1631 TrueTypeCreator *ttcr; 1632 sal_uInt8 *t1, *t2, *t3, *t4, *t5, *t6, *t7; 1633 1634 TrueTypeCreatorNewEmpty(mkTag('t','r','u','e'), &ttcr); 1635 1636 t1 = malloc(1000); memset(t1, 'a', 1000); 1637 t2 = malloc(2000); memset(t2, 'b', 2000); 1638 t3 = malloc(3000); memset(t3, 'c', 3000); 1639 t4 = malloc(4000); memset(t4, 'd', 4000); 1640 t5 = malloc(5000); memset(t5, 'e', 5000); 1641 t6 = malloc(6000); memset(t6, 'f', 6000); 1642 t7 = malloc(7000); memset(t7, 'g', 7000); 1643 1644 AddTable(ttcr, TrueTypeTableNew(0x6D617870, 1000, t1)); 1645 AddTable(ttcr, TrueTypeTableNew(0x4F532F32, 2000, t2)); 1646 AddTable(ttcr, TrueTypeTableNew(0x636D6170, 3000, t3)); 1647 AddTable(ttcr, TrueTypeTableNew(0x6C6F6361, 4000, t4)); 1648 AddTable(ttcr, TrueTypeTableNew(0x68686561, 5000, t5)); 1649 AddTable(ttcr, TrueTypeTableNew(0x676C7966, 6000, t6)); 1650 AddTable(ttcr, TrueTypeTableNew(0x6B65726E, 7000, t7)); 1651 1652 free(t1); 1653 free(t2); 1654 free(t3); 1655 free(t4); 1656 free(t5); 1657 free(t6); 1658 free(t7); 1659 1660 1661 StreamToFile(ttcr, "ttcrout.ttf"); 1662 1663 TrueTypeCreatorDispose(ttcr); 1664 return 0; 1665 } 1666 #endif 1667