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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 /* 32 * Sun Font Tools 33 * 34 * Author: Alexander Gelfenbain 35 * 36 */ 37 38 #if OSL_DEBUG_LEVEL == 0 39 # ifndef NDEBUG 40 # define NDEBUG 41 # endif 42 #endif 43 #include <assert.h> 44 45 #include <stdlib.h> 46 #include <string.h> 47 #include <fcntl.h> 48 #ifdef UNX 49 #include <sys/mman.h> 50 #include <sys/stat.h> 51 #endif 52 #include "sft.hxx" 53 #include "gsub.h" 54 #if ! (defined(NO_TTCR) && defined(NO_TYPE42)) 55 #include "ttcr.hxx" 56 #endif 57 #ifndef NO_MAPPERS /* include MapChar() and MapString() */ 58 #include "xlat.hxx" 59 #endif 60 #ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */ 61 #include <rtl/crc.h> 62 #endif 63 64 #include <osl/endian.h> 65 #include <algorithm> 66 67 #ifdef TEST7 68 #include <ctype.h> 69 #endif 70 71 namespace vcl 72 { 73 74 /*- module identification */ 75 76 static const char *modname = "SunTypeTools-TT"; 77 static const char *modver = "1.0"; 78 static const char *modextra = "gelf"; 79 80 /*- private functions, constants and data types */ /*FOLD00*/ 81 82 enum PathSegmentType { 83 PS_NOOP = 0, 84 PS_MOVETO = 1, 85 PS_LINETO = 2, 86 PS_CURVETO = 3, 87 PS_CLOSEPATH = 4 88 }; 89 90 struct PSPathElement 91 { 92 PathSegmentType type; 93 int x1, y1; 94 int x2, y2; 95 int x3, y3; 96 97 PSPathElement( PathSegmentType i_eType ) : type( i_eType ), 98 x1( 0 ), y1( 0 ), 99 x2( 0 ), y2( 0 ), 100 x3( 0 ), y3( 0 ) 101 { 102 } 103 }; 104 105 /*- In horisontal writing mode right sidebearing is calculated using this formula 106 *- rsb = aw - (lsb + xMax - xMin) -*/ 107 typedef struct { 108 sal_Int16 xMin; 109 sal_Int16 yMin; 110 sal_Int16 xMax; 111 sal_Int16 yMax; 112 sal_uInt16 aw; /*- Advance Width (horisontal writing mode) */ 113 sal_Int16 lsb; /*- Left sidebearing (horisontal writing mode) */ 114 sal_uInt16 ah; /*- advance height (vertical writing mode) */ 115 sal_Int16 tsb; /*- top sidebearing (vertical writing mode) */ 116 } TTGlyphMetrics; 117 118 #define HFORMAT_LINELEN 64 119 120 typedef struct { 121 FILE *o; 122 char buffer[HFORMAT_LINELEN]; 123 int bufpos; 124 int total; 125 } HexFmt; 126 127 typedef struct { 128 sal_uInt32 nGlyphs; /* number of glyphs in the font + 1 */ 129 sal_uInt32 *offs; /* array of nGlyphs offsets */ 130 } GlyphOffsets; 131 132 /* private tags */ 133 static const sal_uInt32 TTFontClassTag = 0x74746663; /* 'ttfc' */ 134 135 static const sal_uInt32 T_true = 0x74727565; /* 'true' */ 136 static const sal_uInt32 T_ttcf = 0x74746366; /* 'ttcf' */ 137 static const sal_uInt32 T_otto = 0x4f54544f; /* 'OTTO' */ 138 139 /* standard TrueType table tags */ 140 #define T_maxp 0x6D617870 141 #define T_glyf 0x676C7966 142 #define T_head 0x68656164 143 #define T_loca 0x6C6F6361 144 #define T_name 0x6E616D65 145 #define T_hhea 0x68686561 146 #define T_hmtx 0x686D7478 147 #define T_cmap 0x636D6170 148 #define T_vhea 0x76686561 149 #define T_vmtx 0x766D7478 150 #define T_OS2 0x4F532F32 151 #define T_post 0x706F7374 152 #define T_kern 0x6B65726E 153 #define T_cvt 0x63767420 154 #define T_prep 0x70726570 155 #define T_fpgm 0x6670676D 156 #define T_gsub 0x47535542 157 #define T_CFF 0x43464620 158 159 #define LAST_URANGE_BIT 69 160 const char *ulcodes[LAST_URANGE_BIT+2] = { 161 /* 0 */ "Basic Latin", 162 /* 1 */ "Latin-1 Supplement", 163 /* 2 */ "Latin Extended-A", 164 /* 3 */ "Latin Extended-B", 165 /* 4 */ "IPA Extensions", 166 /* 5 */ "Spacing Modifier Letters", 167 /* 6 */ "Combining Diacritical Marks", 168 /* 7 */ "Basic Greek", 169 /* 8 */ "Greek Symbols And Coptic", 170 /* 9 */ "Cyrillic", 171 /* 10 */ "Armenian", 172 /* 11 */ "Basic Hebrew", 173 /* 12 */ "Hebrew Extended (A and B blocks combined)", 174 /* 13 */ "Basic Arabic", 175 /* 14 */ "Arabic Extended", 176 /* 15 */ "Devanagari", 177 /* 16 */ "Bengali", 178 /* 17 */ "Gurmukhi", 179 /* 18 */ "Gujarati", 180 /* 19 */ "Oriya", 181 /* 20 */ "Tamil", 182 /* 21 */ "Telugu", 183 /* 22 */ "Kannada", 184 /* 23 */ "Malayalam", 185 /* 24 */ "Thai", 186 /* 25 */ "Lao", 187 /* 26 */ "Basic Georgian", 188 /* 27 */ "Georgian Extended", 189 /* 28 */ "Hangul Jamo", 190 /* 29 */ "Latin Extended Additional", 191 /* 30 */ "Greek Extended", 192 /* 31 */ "General Punctuation", 193 /* 32 */ "Superscripts And Subscripts", 194 /* 33 */ "Currency Symbols", 195 /* 34 */ "Combining Diacritical Marks For Symbols", 196 /* 35 */ "Letterlike Symbols", 197 /* 36 */ "Number Forms", 198 /* 37 */ "Arrows", 199 /* 38 */ "Mathematical Operators", 200 /* 39 */ "Miscellaneous Technical", 201 /* 40 */ "Control Pictures", 202 /* 41 */ "Optical Character Recognition", 203 /* 42 */ "Enclosed Alphanumerics", 204 /* 43 */ "Box Drawing", 205 /* 44 */ "Block Elements", 206 /* 45 */ "Geometric Shapes", 207 /* 46 */ "Miscellaneous Symbols", 208 /* 47 */ "Dingbats", 209 /* 48 */ "CJK Symbols And Punctuation", 210 /* 49 */ "Hiragana", 211 /* 50 */ "Katakana", 212 /* 51 */ "Bopomofo", 213 /* 52 */ "Hangul Compatibility Jamo", 214 /* 53 */ "CJK Miscellaneous", 215 /* 54 */ "Enclosed CJK Letters And Months", 216 /* 55 */ "CJK Compatibility", 217 /* 56 */ "Hangul", 218 /* 57 */ "Reserved for Unicode SubRanges", 219 /* 58 */ "Reserved for Unicode SubRanges", 220 /* 59 */ "CJK Unified Ideographs", 221 /* 60 */ "Private Use Area", 222 /* 61 */ "CJK Compatibility Ideographs", 223 /* 62 */ "Alphabetic Presentation Forms", 224 /* 63 */ "Arabic Presentation Forms-A", 225 /* 64 */ "Combining Half Marks", 226 /* 65 */ "CJK Compatibility Forms", 227 /* 66 */ "Small Form Variants", 228 /* 67 */ "Arabic Presentation Forms-B", 229 /* 68 */ "Halfwidth And Fullwidth Forms", 230 /* 69 */ "Specials", 231 /*70-127*/ "Reserved for Unicode SubRanges" 232 }; 233 234 235 236 /*- inline functions */ /*FOLD01*/ 237 #ifdef __GNUC__ 238 #define _inline static __inline__ 239 #else 240 #define _inline static 241 #endif 242 243 _inline void *smalloc(size_t size) 244 { 245 void *res = malloc(size); 246 assert(res != 0); 247 return res; 248 } 249 250 _inline void *scalloc(size_t n, size_t size) 251 { 252 void *res = calloc(n, size); 253 assert(res != 0); 254 return res; 255 } 256 257 _inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) { 258 return (a << 24) | (b << 16) | (c << 8) | d; 259 } 260 261 /*- Data access macros for data stored in big-endian or little-endian format */ 262 _inline sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset, int bigendian) 263 { 264 sal_Int16 t; 265 assert(ptr != 0); 266 267 if (bigendian) { 268 t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; 269 } else { 270 t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; 271 } 272 273 return t; 274 } 275 276 _inline sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset, int bigendian) 277 { 278 sal_uInt16 t; 279 assert(ptr != 0); 280 281 if (bigendian) { 282 t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; 283 } else { 284 t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; 285 } 286 287 return t; 288 } 289 290 _inline sal_Int32 GetInt32(const sal_uInt8 *ptr, size_t offset, int bigendian) 291 { 292 sal_Int32 t; 293 assert(ptr != 0); 294 295 if (bigendian) { 296 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | 297 (ptr+offset)[2] << 8 | (ptr+offset)[3]; 298 } else { 299 t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | 300 (ptr+offset)[1] << 8 | (ptr+offset)[0]; 301 } 302 303 return t; 304 } 305 306 _inline sal_uInt32 GetUInt32(const sal_uInt8 *ptr, size_t offset, int bigendian) 307 { 308 sal_uInt32 t; 309 assert(ptr != 0); 310 311 312 if (bigendian) { 313 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | 314 (ptr+offset)[2] << 8 | (ptr+offset)[3]; 315 } else { 316 t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | 317 (ptr+offset)[1] << 8 | (ptr+offset)[0]; 318 } 319 320 return t; 321 } 322 323 _inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, size_t offset, int bigendian) 324 { 325 assert(ptr != 0); 326 327 if (bigendian) { 328 ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); 329 ptr[offset+1] = (sal_uInt8)(val & 0xFF); 330 } else { 331 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); 332 ptr[offset] = (sal_uInt8)(val & 0xFF); 333 } 334 335 } 336 337 #if defined(OSL_BIGENDIAN) 338 #define Int16FromMOTA(a) (a) 339 #define Int32FromMOTA(a) (a) 340 #else 341 static sal_uInt16 Int16FromMOTA(sal_uInt16 a) { 342 return (sal_uInt16) (((sal_uInt8)((a) >> 8)) | ((sal_uInt8)(a) << 8)); 343 } 344 static sal_uInt32 Int32FromMOTA(sal_uInt32 a) { 345 return ((a>>24)&0xFF) | (((a>>8)&0xFF00) | ((a&0xFF00)<<8) | ((a&0xFF)<<24)); 346 } 347 #endif 348 349 _inline F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b) 350 { 351 unsigned int a1, b1; 352 unsigned int a2, b2; 353 F16Dot16 res; 354 int sign; 355 356 sign = (a & 0x80000000) ^ (b & 0x80000000); 357 if (a < 0) a = -a; 358 if (b < 0) b = -b; 359 360 a1 = a >> 16; 361 b1 = a & 0xFFFF; 362 a2 = b >> 16; 363 b2 = b & 0xFFFF; 364 365 res = a1 * a2; 366 367 /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */ 368 369 res <<= 16; 370 res += a1 * b2 + b1 * a2 + ((b1 * b2) >> 16); 371 372 return sign ? -res : res; 373 } 374 375 376 _inline F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b) 377 { 378 unsigned int f, r; 379 F16Dot16 res; 380 int sign; 381 382 sign = (a & 0x80000000) ^ (b & 0x80000000); 383 if (a < 0) a = -a; 384 if (b < 0) b = -b; 385 386 f = a / b; 387 r = a % b; 388 389 /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */ 390 391 while (r > 0xFFFF) { 392 r >>= 1; 393 b >>= 1; 394 } 395 396 res = (f << 16) + (r << 16) / b; 397 398 return sign ? -res : res; 399 } 400 401 /*- returns a * b / c -*/ 402 /* XXX provide a real implementation that preserves accuracy */ 403 _inline F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c) 404 { 405 F16Dot16 res; 406 407 res = fixedMul(a, b); 408 return fixedDiv(res, c); 409 } 410 411 /*- Translate units from TT to PS (standard 1/1000) -*/ 412 _inline int XUnits(int unitsPerEm, int n) 413 { 414 return (n * 1000) / unitsPerEm; 415 } 416 417 _inline const char *UnicodeRangeName(sal_uInt16 bit) 418 { 419 if (bit > LAST_URANGE_BIT) bit = LAST_URANGE_BIT+1; 420 421 return ulcodes[bit]; 422 } 423 424 _inline const sal_uInt8* getTable( TrueTypeFont *ttf, sal_uInt32 ord) 425 { 426 return (sal_uInt8*)ttf->tables[ord]; 427 } 428 429 _inline sal_uInt32 getTableSize(TrueTypeFont *ttf, sal_uInt32 ord) 430 { 431 return ttf->tlens[ord]; 432 } 433 434 #ifndef NO_TYPE42 435 /* Hex Formatter functions */ 436 static char HexChars[] = "0123456789ABCDEF"; 437 438 static HexFmt *HexFmtNew(FILE *outf) 439 { 440 HexFmt* res = (HexFmt*)smalloc(sizeof(HexFmt)); 441 res->bufpos = res->total = 0; 442 res->o = outf; 443 return res; 444 } 445 446 static void HexFmtFlush(HexFmt *_this) 447 { 448 if (_this->bufpos) { 449 fwrite(_this->buffer, 1, _this->bufpos, _this->o); 450 _this->bufpos = 0; 451 } 452 } 453 454 455 _inline void HexFmtOpenString(HexFmt *_this) 456 { 457 fputs("<\n", _this->o); 458 } 459 460 _inline void HexFmtCloseString(HexFmt *_this) 461 { 462 HexFmtFlush(_this); 463 fputs("00\n>\n", _this->o); 464 } 465 466 _inline void HexFmtDispose(HexFmt *_this) 467 { 468 HexFmtFlush(_this); 469 free(_this); 470 } 471 472 static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size) 473 { 474 sal_uInt8 Ch; 475 sal_uInt32 i; 476 477 if (_this->total + size > 65534) { 478 HexFmtFlush(_this); 479 HexFmtCloseString(_this); 480 _this->total = 0; 481 HexFmtOpenString(_this); 482 } 483 for (i=0; i<size; i++) { 484 Ch = ((sal_uInt8 *) ptr)[i]; 485 _this->buffer[_this->bufpos++] = HexChars[Ch >> 4]; 486 _this->buffer[_this->bufpos++] = HexChars[Ch & 0xF]; 487 if (_this->bufpos == HFORMAT_LINELEN) { 488 HexFmtFlush(_this); 489 fputc('\n', _this->o); 490 } 491 492 } 493 _this->total += size; 494 } 495 #endif 496 497 498 499 /* Outline Extraction functions */ /*FOLD01*/ 500 501 /* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/ 502 static void GetMetrics(TrueTypeFont *ttf, sal_uInt32 glyphID, TTGlyphMetrics *metrics) 503 { 504 const sal_uInt8* table = getTable( ttf, O_hmtx ); 505 506 metrics->aw = metrics->lsb = metrics->ah = metrics->tsb = 0; 507 if (!table || !ttf->numberOfHMetrics) return; 508 509 if (glyphID < ttf->numberOfHMetrics) { 510 metrics->aw = GetUInt16(table, 4 * glyphID, 1); 511 metrics->lsb = GetInt16(table, 4 * glyphID + 2, 1); 512 } else { 513 metrics->aw = GetUInt16(table, 4 * (ttf->numberOfHMetrics - 1), 1); 514 metrics->lsb = GetInt16(table + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1); 515 } 516 517 table = getTable(ttf, O_vmtx); 518 if( !table || !ttf->numOfLongVerMetrics ) 519 return; 520 521 if (glyphID < ttf->numOfLongVerMetrics) { 522 metrics->ah = GetUInt16(table, 4 * glyphID, 1); 523 metrics->tsb = GetInt16(table, 4 * glyphID + 2, 1); 524 } else { 525 metrics->ah = GetUInt16(table, 4 * (ttf->numOfLongVerMetrics - 1), 1); 526 metrics->tsb = GetInt16(table + ttf->numOfLongVerMetrics * 4, (glyphID - ttf->numOfLongVerMetrics) * 2, 1); 527 } 528 } 529 530 static int GetTTGlyphOutline(TrueTypeFont *, sal_uInt32 , ControlPoint **, TTGlyphMetrics *, std::vector< sal_uInt32 >* ); 531 532 /* returns the number of control points, allocates the pointArray */ 533 static int GetSimpleTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics) /*FOLD02*/ 534 { 535 const sal_uInt8* table = getTable( ttf, O_glyf ); 536 sal_uInt8 flag, n; 537 sal_uInt16 t, lastPoint=0; 538 int i, j, z; 539 540 *pointArray = 0; 541 542 /* printf("GetSimpleTTOutline(%d)\n", glyphID); */ 543 544 if( glyphID >= ttf->nglyphs ) /*- glyph is not present in the font */ 545 return 0; 546 const sal_uInt8* ptr = table + ttf->goffsets[glyphID]; 547 const sal_Int16 numberOfContours = GetInt16(ptr, 0, 1); 548 if( numberOfContours <= 0 ) /*- glyph is not simple */ 549 return 0; 550 551 if (metrics) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/ 552 metrics->xMin = GetInt16(ptr, 2, 1); 553 metrics->yMin = GetInt16(ptr, 4, 1); 554 metrics->xMax = GetInt16(ptr, 6, 1); 555 metrics->yMax = GetInt16(ptr, 8, 1); 556 GetMetrics(ttf, glyphID, metrics); 557 } 558 559 /* determine the last point and be extra safe about it. But probably this code is not needed */ 560 561 for (i=0; i<numberOfContours; i++) { 562 if ((t = GetUInt16(ptr, 10+i*2, 1)) > lastPoint) lastPoint = t; 563 } 564 565 sal_uInt16 instLen = GetUInt16(ptr, 10 + numberOfContours*2, 1); 566 const sal_uInt8* p = ptr + 10 + 2 * numberOfContours + 2 + instLen; 567 ControlPoint* pa = (ControlPoint*)calloc(lastPoint+1, sizeof(ControlPoint)); 568 569 i = 0; 570 while (i <= lastPoint) { 571 pa[i++].flags = (sal_uInt32) (flag = *p++); 572 if (flag & 8) { /*- repeat flag */ 573 n = *p++; 574 for (j=0; j<n; j++) { 575 if (i > lastPoint) { /*- if the font is really broken */ 576 free(pa); 577 return 0; 578 } 579 pa[i++].flags = flag; 580 } 581 } 582 } 583 584 /*- Process the X coordinate */ 585 z = 0; 586 for (i = 0; i <= lastPoint; i++) { 587 if (pa[i].flags & 0x02) { 588 if (pa[i].flags & 0x10) { 589 z += (int) (*p++); 590 } else { 591 z -= (int) (*p++); 592 } 593 } else if ( !(pa[i].flags & 0x10)) { 594 z += GetInt16(p, 0, 1); 595 p += 2; 596 } 597 pa[i].x = (sal_Int16)z; 598 } 599 600 /*- Process the Y coordinate */ 601 z = 0; 602 for (i = 0; i <= lastPoint; i++) { 603 if (pa[i].flags & 0x04) { 604 if (pa[i].flags & 0x20) { 605 z += *p++; 606 } else { 607 z -= *p++; 608 } 609 } else if ( !(pa[i].flags & 0x20)) { 610 z += GetInt16(p, 0, 1); 611 p += 2; 612 } 613 pa[i].y = (sal_Int16)z; 614 } 615 616 for (i=0; i<numberOfContours; i++) { 617 pa[GetUInt16(ptr, 10 + i * 2, 1)].flags |= 0x00008000; /*- set the end contour flag */ 618 } 619 620 *pointArray = pa; 621 return lastPoint + 1; 622 } 623 624 static int GetCompoundTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >& glyphlist) /*FOLD02*/ 625 { 626 sal_uInt16 flags, index; 627 sal_Int16 e, f, numberOfContours; 628 const sal_uInt8* table = getTable( ttf, O_glyf ); 629 std::vector<ControlPoint> myPoints; 630 ControlPoint *nextComponent, *pa; 631 int i, np; 632 F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3; 633 634 *pointArray = 0; 635 /* printf("GetCompoundTTOutline(%d)\n", glyphID); */ 636 637 if (glyphID >= ttf->nglyphs) /*- incorrect glyphID */ 638 return 0; 639 640 const sal_uInt8* ptr = table + ttf->goffsets[glyphID]; 641 if ((numberOfContours = GetInt16(ptr, 0, 1)) != -1) /*- glyph is not compound */ 642 return 0; 643 644 if (metrics) { 645 metrics->xMin = GetInt16(ptr, 2, 1); 646 metrics->yMin = GetInt16(ptr, 4, 1); 647 metrics->xMax = GetInt16(ptr, 6, 1); 648 metrics->yMax = GetInt16(ptr, 8, 1); 649 GetMetrics(ttf, glyphID, metrics); 650 } 651 652 ptr += 10; 653 654 do { 655 flags = GetUInt16(ptr, 0, 1); 656 /* printf("flags: 0x%X\n", flags); */ 657 index = GetUInt16(ptr, 2, 1); 658 ptr += 4; 659 660 if( std::find( glyphlist.begin(), glyphlist.end(), index ) != glyphlist.end() ) 661 { 662 #if OSL_DEBUG_LEVEL > 1 663 fprintf(stderr, "Endless loop found in a compound glyph.\n"); 664 fprintf(stderr, "%d -> ", index); 665 fprintf(stderr," ["); 666 for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin(); 667 it != glyphlist.end(); ++it ) 668 { 669 fprintf( stderr,"%d ", (int) *it ); 670 } 671 fprintf(stderr,"]\n"); 672 /**/ 673 #endif 674 } 675 676 glyphlist.push_back( index ); 677 678 #ifdef DEBUG2 679 fprintf(stderr,"glyphlist: += %d\n", index); 680 #endif 681 682 if ((np = GetTTGlyphOutline(ttf, index, &nextComponent, 0, &glyphlist)) == 0) 683 { 684 /* XXX that probably indicates a corrupted font */ 685 #if OSL_DEBUG_LEVEL > 1 686 fprintf(stderr, "An empty compound!\n"); 687 /* assert(!"An empty compound"); */ 688 #endif 689 } 690 691 #ifdef DEBUG2 692 fprintf(stderr,"%d [", (int)glyphlist.size() ); 693 for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin(); 694 it != glyphlist.end(); ++it ) 695 { 696 fprintf( stderr,"%d ", (int) *it ); 697 } 698 fprintf(stderr, "]\n"); 699 if( ! glyphlist.empty() ) 700 fprintf(stderr, "glyphlist: -= %d\n", (int) glyphlist.back()); 701 702 #endif 703 if( ! glyphlist.empty() ) 704 glyphlist.pop_back(); 705 706 if (flags & USE_MY_METRICS) { 707 if (metrics) GetMetrics(ttf, index, metrics); 708 } 709 710 if (flags & ARG_1_AND_2_ARE_WORDS) { 711 e = GetInt16(ptr, 0, 1); 712 f = GetInt16(ptr, 2, 1); 713 /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */ 714 ptr += 4; 715 } else { 716 if (flags & ARGS_ARE_XY_VALUES) { /* args are signed */ 717 e = (sal_Int8) *ptr++; 718 f = (sal_Int8) *ptr++; 719 /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */ 720 } else { /* args are unsigned */ 721 /* printf("!ARGS_ARE_XY_VALUES\n"); */ 722 e = *ptr++; 723 f = *ptr++; 724 } 725 726 } 727 728 a = d = 0x10000; 729 b = c = 0; 730 731 if (flags & WE_HAVE_A_SCALE) { 732 #ifdef DEBUG2 733 fprintf(stderr, "WE_HAVE_A_SCALE\n"); 734 #endif 735 a = GetInt16(ptr, 0, 1) << 2; 736 d = a; 737 ptr += 2; 738 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { 739 #ifdef DEBUG2 740 fprintf(stderr, "WE_HAVE_AN_X_AND_Y_SCALE\n"); 741 #endif 742 a = GetInt16(ptr, 0, 1) << 2; 743 d = GetInt16(ptr, 2, 1) << 2; 744 ptr += 4; 745 } else if (flags & WE_HAVE_A_TWO_BY_TWO) { 746 #ifdef DEBUG2 747 fprintf(stderr, "WE_HAVE_A_TWO_BY_TWO\n"); 748 #endif 749 a = GetInt16(ptr, 0, 1) << 2; 750 b = GetInt16(ptr, 2, 1) << 2; 751 c = GetInt16(ptr, 4, 1) << 2; 752 d = GetInt16(ptr, 6, 1) << 2; 753 ptr += 8; 754 } 755 756 abs1 = (a < 0) ? -a : a; 757 abs2 = (b < 0) ? -b : b; 758 m = (abs1 > abs2) ? abs1 : abs2; 759 abs3 = abs1 - abs2; 760 if (abs3 < 0) abs3 = -abs3; 761 if (abs3 <= 33) m *= 2; 762 763 abs1 = (c < 0) ? -c : c; 764 abs2 = (d < 0) ? -d : d; 765 n = (abs1 > abs2) ? abs1 : abs2; 766 abs3 = abs1 - abs2; 767 if (abs3 < 0) abs3 = -abs3; 768 if (abs3 <= 33) n *= 2; 769 770 if (!ARGS_ARE_XY_VALUES) { /* match the points */ 771 assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n"); 772 } 773 774 #ifdef DEBUG2 775 fprintf(stderr, "a: %f, b: %f, c: %f, d: %f, e: %f, f: %f, m: %f, n: %f\n", 776 ((double) a) / 65536, 777 ((double) b) / 65536, 778 ((double) c) / 65536, 779 ((double) d) / 65536, 780 ((double) e) / 65536, 781 ((double) f) / 65536, 782 ((double) m) / 65536, 783 ((double) n) / 65536); 784 #endif 785 786 for (i=0; i<np; i++) { 787 F16Dot16 t; 788 ControlPoint cp; 789 cp.flags = nextComponent[i].flags; 790 t = fixedMulDiv(a, nextComponent[i].x << 16, m) + fixedMulDiv(c, nextComponent[i].y << 16, m) + (e << 16); 791 cp.x = (sal_Int16)(fixedMul(t, m) >> 16); 792 t = fixedMulDiv(b, nextComponent[i].x << 16, n) + fixedMulDiv(d, nextComponent[i].y << 16, n) + (f << 16); 793 cp.y = (sal_Int16)(fixedMul(t, n) >> 16); 794 795 #ifdef DEBUG2 796 fprintf(stderr, "( %d %d ) -> ( %d %d )\n", nextComponent[i].x, nextComponent[i].y, cp.x, cp.y); 797 #endif 798 799 myPoints.push_back( cp ); 800 } 801 802 free(nextComponent); 803 804 } while (flags & MORE_COMPONENTS); 805 806 807 808 np = myPoints.size(); 809 810 pa = (ControlPoint*)calloc(np, sizeof(ControlPoint)); 811 assert(pa != 0); 812 813 memcpy( pa, &myPoints[0], np*sizeof(ControlPoint) ); 814 815 *pointArray = pa; 816 return np; 817 } 818 819 /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect, 820 * but Get{Simple|Compound}GlyphOutline returns 0 in such a case. 821 * 822 * NOTE: glyphlist is the stack of glyphs traversed while constructing 823 * a composite glyph. This is a safequard against endless recursion 824 * in corrupted fonts. 825 */ 826 static int GetTTGlyphOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >* glyphlist) 827 { 828 const sal_uInt8 *table = getTable( ttf, O_glyf ); 829 sal_Int16 numberOfContours; 830 int res; 831 *pointArray = 0; 832 833 if (metrics) { 834 memset(metrics, 0, sizeof(TTGlyphMetrics)); /*- metrics is initialized to all zeroes */ 835 } 836 837 if (glyphID >= ttf->nglyphs) return -1; /**/ 838 839 const sal_uInt8* ptr = table + ttf->goffsets[glyphID]; 840 int length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; 841 842 if (length == 0) { /*- empty glyphs still have hmtx and vmtx metrics values */ 843 if (metrics) GetMetrics(ttf, glyphID, metrics); 844 return 0; 845 } 846 847 numberOfContours = GetInt16(ptr, 0, 1); 848 849 if (numberOfContours >= 0) 850 { 851 res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics); 852 } 853 else 854 { 855 std::vector< sal_uInt32 > aPrivList; 856 aPrivList.push_back( glyphID ); 857 res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist ? *glyphlist : aPrivList ); 858 } 859 860 #ifdef DEBUG3 861 { 862 int i; 863 FILE *out = fopen("points.dat", "a"); 864 assert(out != 0); 865 fprintf(out, "Glyph: %d\nPoints: %d\n", glyphID, res); 866 for (i=0; i<res; i++) { 867 fprintf(out, "%c ", ((*pointArray)[i].flags & 0x8000) ? 'X' : '.'); 868 fprintf(out, "%c ", ((*pointArray)[i].flags & 1) ? '+' : '-'); 869 fprintf(out, "%d %d\n", (*pointArray)[i].x, (*pointArray)[i].y); 870 } 871 fclose(out); 872 } 873 #endif 874 875 return res; 876 } 877 878 #ifndef NO_TYPE3 879 880 /*- returns the number of items in the path -*/ 881 882 static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path) 883 { 884 std::vector< PSPathElement > aPathList; 885 int nPathCount = 0; 886 PSPathElement p( PS_NOOP ); 887 888 int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury; 889 int lastOff = 0; /*- last point was off-contour */ 890 int scflag = 1; /*- start contour flag */ 891 int ecflag = 0; /*- end contour flag */ 892 int cp = 0; /*- current point */ 893 int StartContour = 0, EndContour = 1; 894 895 *path = 0; 896 897 /* if (srcCount > 0) for(;;) */ 898 while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */ 899 if (scflag) { 900 int l = cp; 901 StartContour = cp; 902 while (!(srcA[l].flags & 0x8000)) l++; 903 EndContour = l; 904 if (StartContour == EndContour) { 905 if (cp + 1 < srcCount) { 906 cp++; 907 continue; 908 } else { 909 break; 910 } 911 } 912 p = PSPathElement(PS_MOVETO); 913 if (!(srcA[cp].flags & 1)) { 914 if (!(srcA[EndContour].flags & 1)) { 915 p.x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2; 916 p.y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2; 917 } else { 918 p.x1 = x0 = srcA[EndContour].x; 919 p.y1 = y0 = srcA[EndContour].y; 920 } 921 } else { 922 p.x1 = x0 = srcA[cp].x; 923 p.y1 = y0 = srcA[cp].y; 924 cp++; 925 } 926 aPathList.push_back( p ); 927 lastOff = 0; 928 scflag = 0; 929 } 930 931 curx = srcA[cp].x; 932 cury = srcA[cp].y; 933 934 if (srcA[cp].flags & 1) 935 { 936 if (lastOff) 937 { 938 p = PSPathElement(PS_CURVETO); 939 p.x1 = x0 + (2 * (x1 - x0) + 1) / 3; 940 p.y1 = y0 + (2 * (y1 - y0) + 1) / 3; 941 p.x2 = x1 + (curx - x1 + 1) / 3; 942 p.y2 = y1 + (cury - y1 + 1) / 3; 943 p.x3 = curx; 944 p.y3 = cury; 945 aPathList.push_back( p ); 946 } 947 else 948 { 949 if (!(x0 == curx && y0 == cury)) 950 { /* eliminate empty lines */ 951 p = PSPathElement(PS_LINETO); 952 p.x1 = curx; 953 p.y1 = cury; 954 aPathList.push_back( p ); 955 } 956 } 957 x0 = curx; y0 = cury; lastOff = 0; 958 } 959 else 960 { 961 if (lastOff) 962 { 963 x2 = (x1 + curx + 1) / 2; 964 y2 = (y1 + cury + 1) / 2; 965 p = PSPathElement(PS_CURVETO); 966 p.x1 = x0 + (2 * (x1 - x0) + 1) / 3; 967 p.y1 = y0 + (2 * (y1 - y0) + 1) / 3; 968 p.x2 = x1 + (x2 - x1 + 1) / 3; 969 p.y2 = y1 + (y2 - y1 + 1) / 3; 970 p.x3 = x2; 971 p.y3 = y2; 972 aPathList.push_back( p ); 973 x0 = x2; y0 = y2; 974 x1 = curx; y1 = cury; 975 } else { 976 x1 = curx; y1 = cury; 977 } 978 lastOff = true; 979 } 980 981 if (ecflag) { 982 aPathList.push_back( PSPathElement(PS_CLOSEPATH) ); 983 scflag = 1; 984 ecflag = 0; 985 cp = EndContour + 1; 986 if (cp >= srcCount) break; 987 continue; 988 } 989 990 991 if (cp == EndContour) { 992 cp = StartContour; 993 ecflag = true; 994 } else { 995 cp++; 996 } 997 } 998 999 if( (nPathCount = (int)aPathList.size()) > 0) 1000 { 1001 *path = (PSPathElement*)calloc(nPathCount, sizeof(PSPathElement)); 1002 assert(*path != 0); 1003 memcpy( *path, &aPathList[0], nPathCount * sizeof(PSPathElement) ); 1004 } 1005 1006 return nPathCount; 1007 } 1008 1009 #endif 1010 1011 /*- Extracts a string from the name table and allocates memory for it -*/ 1012 1013 static char *nameExtract( const sal_uInt8* name, int nTableSize, int n, int dbFlag, sal_uInt16** ucs2result ) 1014 { 1015 int i; 1016 char *res; 1017 const sal_uInt8* ptr = name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1); 1018 int len = GetUInt16(name+6, 12 * n + 8, 1); 1019 1020 // sanity check 1021 if( (len <= 0) || ((ptr+len) > (name+nTableSize)) ) 1022 { 1023 if( ucs2result ) 1024 *ucs2result = NULL; 1025 return NULL; 1026 } 1027 1028 if( ucs2result ) 1029 *ucs2result = NULL; 1030 if (dbFlag) { 1031 res = (char*)malloc(1 + len/2); 1032 assert(res != 0); 1033 for (i = 0; i < len/2; i++) res[i] = *(ptr + i * 2 + 1); 1034 res[len/2] = 0; 1035 if( ucs2result ) 1036 { 1037 *ucs2result = (sal_uInt16*)malloc( len+2 ); 1038 for (i = 0; i < len/2; i++ ) (*ucs2result)[i] = GetUInt16( ptr, 2*i, 1 ); 1039 (*ucs2result)[len/2] = 0; 1040 } 1041 } else { 1042 res = (char*)malloc(1 + len); 1043 assert(res != 0); 1044 memcpy(res, ptr, len); 1045 res[len] = 0; 1046 } 1047 1048 return res; 1049 } 1050 1051 static int findname( const sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID, 1052 sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID ) 1053 { 1054 int l = 0, r = n-1, i; 1055 sal_uInt32 t1, t2; 1056 sal_uInt32 m1, m2; 1057 1058 if (n == 0) return -1; 1059 1060 m1 = (platformID << 16) | encodingID; 1061 m2 = (languageID << 16) | nameID; 1062 1063 do { 1064 i = (l + r) >> 1; 1065 t1 = GetUInt32(name + 6, i * 12 + 0, 1); 1066 t2 = GetUInt32(name + 6, i * 12 + 4, 1); 1067 1068 if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1; 1069 if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1; 1070 } while (l <= r); 1071 1072 if (l - r == 2) { 1073 return l - 1; 1074 } 1075 1076 return -1; 1077 } 1078 1079 /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables. 1080 * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033) 1081 * 1082 * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0) 1083 * and does not have (3, 1, 1033) 1084 * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will 1085 * require a change in algorithm 1086 * 1087 * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID, 1088 * but (1, 0, 1042) strings usable 1089 * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found 1090 */ 1091 1092 static void GetNames(TrueTypeFont *t) 1093 { 1094 const sal_uInt8* table = getTable( t, O_name ); 1095 int nTableSize = getTableSize(t, O_name); 1096 1097 if (nTableSize < 4) 1098 { 1099 #if OSL_DEBUG_LEVEL > 1 1100 fprintf(stderr, "O_name table too small\n"); 1101 #endif 1102 return; 1103 } 1104 1105 sal_uInt16 n = GetUInt16(table, 2, 1); 1106 int i, r; 1107 sal_Bool bPSNameOK = sal_True; 1108 1109 /* #129743# simple sanity check for name table entry count */ 1110 if( nTableSize <= n * 12 + 6 ) 1111 n = 0; 1112 1113 /* PostScript name: preferred Microsoft */ 1114 t->psname = NULL; 1115 if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1) 1116 t->psname = nameExtract(table, nTableSize, r, 1, NULL); 1117 if ( ! t->psname && (r = findname(table, n, 1, 0, 0, 6)) != -1) 1118 t->psname = nameExtract(table, nTableSize, r, 0, NULL); 1119 if ( ! t->psname && (r = findname(table, n, 3, 0, 0x0409, 6)) != -1) 1120 { 1121 // some symbol fonts like Marlett have a 3,0 name! 1122 t->psname = nameExtract(table, nTableSize, r, 1, NULL); 1123 } 1124 // for embedded font in Ghostscript PDFs 1125 if ( ! t->psname && (r = findname(table, n, 2, 2, 0, 6)) != -1) 1126 { 1127 t->psname = nameExtract(table, nTableSize, r, 0, NULL); 1128 } 1129 if ( ! t->psname ) 1130 { 1131 if ( t->fname ) 1132 { 1133 char* pReverse = t->fname + strlen(t->fname); 1134 /* take only last token of filename */ 1135 while(pReverse != t->fname && *pReverse != '/') pReverse--; 1136 if(*pReverse == '/') pReverse++; 1137 t->psname = strdup(pReverse); 1138 assert(t->psname != 0); 1139 for (i=strlen(t->psname) - 1; i > 0; i--) 1140 { 1141 /*- Remove the suffix -*/ 1142 if (t->psname[i] == '.' ) { 1143 t->psname[i] = 0; 1144 break; 1145 } 1146 } 1147 } 1148 else 1149 t->psname = strdup( "Unknown" ); 1150 } 1151 1152 /* Font family and subfamily names: preferred Apple */ 1153 t->family = NULL; 1154 if ((r = findname(table, n, 0, 0, 0, 1)) != -1) 1155 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1156 if ( ! t->family && (r = findname(table, n, 3, 1, 0x0409, 1)) != -1) 1157 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1158 if ( ! t->family && (r = findname(table, n, 1, 0, 0, 1)) != -1) 1159 t->family = nameExtract(table, nTableSize, r, 0, NULL); 1160 if ( ! t->family && (r = findname(table, n, 3, 1, 0x0411, 1)) != -1) 1161 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1162 if ( ! t->family && (r = findname(table, n, 3, 0, 0x0409, 1)) != -1) 1163 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1164 if ( ! t->family ) 1165 { 1166 t->family = strdup(t->psname); 1167 assert(t->family != 0); 1168 } 1169 1170 t->subfamily = NULL; 1171 t->usubfamily = NULL; 1172 if ((r = findname(table, n, 1, 0, 0, 2)) != -1) 1173 t->subfamily = nameExtract(table, nTableSize, r, 0, &t->usubfamily); 1174 if ( ! t->subfamily && (r = findname(table, n, 3, 1, 0x0409, 2)) != -1) 1175 t->subfamily = nameExtract(table, nTableSize, r, 1, &t->usubfamily); 1176 if ( ! t->subfamily ) 1177 { 1178 t->subfamily = strdup(""); 1179 } 1180 1181 /* #i60349# sanity check psname 1182 * psname parctically has to be 7bit ascii and should not contains spaces 1183 * there is a class of broken fonts which do not fullfill that at all, so let's try 1184 * if the family name is 7bit ascii and take it instead if so 1185 */ 1186 /* check psname */ 1187 for( i = 0; t->psname[i] != 0 && bPSNameOK; i++ ) 1188 if( t->psname[ i ] < 33 || (t->psname[ i ] & 0x80) ) 1189 bPSNameOK = sal_False; 1190 if( bPSNameOK == sal_False ) 1191 { 1192 sal_Bool bReplace = sal_True; 1193 /* check if family is a suitable replacement */ 1194 if( t->ufamily && t->family ) 1195 { 1196 for( i = 0; t->ufamily[ i ] != 0 && bReplace; i++ ) 1197 if( t->ufamily[ i ] < 33 || t->ufamily[ i ] > 127 ) 1198 bReplace = sal_False; 1199 if( bReplace ) 1200 { 1201 free( t->psname ); 1202 t->psname = strdup( t->family ); 1203 } 1204 } 1205 } 1206 } 1207 1208 enum cmapType { 1209 CMAP_NOT_USABLE = -1, 1210 CMAP_MS_Symbol = 10, 1211 CMAP_MS_Unicode = 11, 1212 CMAP_MS_ShiftJIS = 12, 1213 CMAP_MS_Big5 = 13, 1214 CMAP_MS_PRC = 14, 1215 CMAP_MS_Wansung = 15, 1216 CMAP_MS_Johab = 16 1217 }; 1218 1219 #define MISSING_GLYPH_INDEX 0 1220 1221 /* 1222 * getGlyph[0246]() functions and freinds are implemented by: 1223 * @author Manpreet Singh 1224 * getGlyph12() function and friends by: 1225 * @author HDU 1226 */ 1227 static sal_uInt32 getGlyph0(const sal_uInt8* cmap, sal_uInt32 c) { 1228 if (c <= 255) { 1229 return *(cmap + 6 + c); 1230 } else { 1231 return MISSING_GLYPH_INDEX; 1232 } 1233 } 1234 1235 typedef struct _subHeader2 { 1236 sal_uInt16 firstCode; 1237 sal_uInt16 entryCount; 1238 sal_uInt16 idDelta; 1239 sal_uInt16 idRangeOffset; 1240 } subHeader2; 1241 1242 static sal_uInt32 getGlyph2(const sal_uInt8 *cmap, sal_uInt32 c) { 1243 sal_uInt16 *CMAP2 = (sal_uInt16 *) cmap; 1244 sal_uInt8 theHighByte; 1245 1246 sal_uInt8 theLowByte; 1247 subHeader2* subHeader2s; 1248 sal_uInt16* subHeader2Keys; 1249 sal_uInt16 firstCode; 1250 int k; 1251 sal_uInt32 ToReturn; 1252 1253 theHighByte = (sal_uInt8)((c >> 8) & 0x00ff); 1254 theLowByte = (sal_uInt8)(c & 0x00ff); 1255 subHeader2Keys = CMAP2 + 3; 1256 subHeader2s = (subHeader2 *)(subHeader2Keys + 256); 1257 k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8; 1258 1259 if(k == 0) { 1260 firstCode = Int16FromMOTA(subHeader2s[k].firstCode); 1261 if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { 1262 return *((&(subHeader2s[0].idRangeOffset)) 1263 + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) /* + offset */ 1264 + theLowByte /* + to_look */ 1265 - Int16FromMOTA(subHeader2s[0].firstCode) 1266 ); 1267 } else { 1268 return MISSING_GLYPH_INDEX; 1269 } 1270 } else if (k > 0) { 1271 firstCode = Int16FromMOTA(subHeader2s[k].firstCode); 1272 if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { 1273 ToReturn = *((&(subHeader2s[k].idRangeOffset)) 1274 + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2) 1275 + theLowByte - firstCode); 1276 if(ToReturn == 0) { 1277 return MISSING_GLYPH_INDEX; 1278 } else { 1279 ToReturn += Int16FromMOTA(subHeader2s[k].idDelta); 1280 return (ToReturn & 0xFFFF); 1281 } 1282 } else { 1283 return MISSING_GLYPH_INDEX; 1284 } 1285 } else { 1286 return MISSING_GLYPH_INDEX; 1287 } 1288 } 1289 1290 static sal_uInt32 getGlyph6(const sal_uInt8 *cmap, sal_uInt32 c) { 1291 sal_uInt16 firstCode, lastCode, count; 1292 sal_uInt16 *CMAP6 = (sal_uInt16 *) cmap; 1293 1294 firstCode = Int16FromMOTA(*(CMAP6 + 3)); 1295 count = Int16FromMOTA(*(CMAP6 + 4)); 1296 lastCode = firstCode + count - 1; 1297 if (c < firstCode || c > lastCode) { 1298 return MISSING_GLYPH_INDEX; 1299 } else { 1300 return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode)); 1301 } 1302 } 1303 1304 static sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch) { 1305 signed int low, mid, high, lastfound = 0xffff; 1306 sal_uInt16 res; 1307 if(length == (sal_uInt16)0 || length == (sal_uInt16)0xFFFF) { 1308 return (sal_uInt16)0xFFFF; 1309 } 1310 low = 0; 1311 high = length - 1; 1312 while(high >= low) { 1313 mid = (high + low)/2; 1314 res = Int16FromMOTA(*(ar+mid)); 1315 if(res >= toSearch) { 1316 lastfound = mid; 1317 high = --mid; 1318 } else { 1319 low = ++mid; 1320 } 1321 } 1322 return (sal_uInt16)lastfound; 1323 } 1324 1325 1326 static sal_uInt32 getGlyph4(const sal_uInt8 *cmap, sal_uInt32 c) { 1327 sal_uInt16 i; 1328 int ToReturn; 1329 sal_uInt16 segCount; 1330 sal_uInt16 * startCode; 1331 sal_uInt16 * endCode; 1332 sal_uInt16 * idDelta; 1333 /* sal_uInt16 * glyphIdArray; */ 1334 sal_uInt16 * idRangeOffset; 1335 sal_uInt16 * glyphIndexArray; 1336 sal_uInt16 *CMAP4 = (sal_uInt16 *) cmap; 1337 /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */ 1338 1339 segCount = Int16FromMOTA(*(CMAP4 + 3))/2; 1340 endCode = CMAP4 + 7; 1341 i = GEbinsearch(endCode, segCount, (sal_uInt16)c); 1342 1343 if (i == (sal_uInt16) 0xFFFF) { 1344 return MISSING_GLYPH_INDEX; 1345 } 1346 startCode = endCode + segCount + 1; 1347 1348 if(Int16FromMOTA(startCode[i]) > c) { 1349 return MISSING_GLYPH_INDEX; 1350 } 1351 idDelta = startCode + segCount; 1352 idRangeOffset = idDelta + segCount; 1353 glyphIndexArray = idRangeOffset + segCount; 1354 1355 if(Int16FromMOTA(idRangeOffset[i]) != 0) { 1356 c = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i]))))); 1357 } 1358 1359 ToReturn = (Int16FromMOTA(idDelta[i]) + c) & 0xFFFF; 1360 return ToReturn; 1361 } 1362 1363 static sal_uInt32 getGlyph12(const sal_uInt8 *pCmap, sal_uInt32 cChar) { 1364 const sal_uInt32* pCMAP12 = (const sal_uInt32*)pCmap; 1365 int nLength = Int32FromMOTA( pCMAP12[1] ); 1366 int nGroups = Int32FromMOTA( pCMAP12[3] ); 1367 int nLower = 0; 1368 int nUpper = nGroups; 1369 1370 if( nUpper > (nLength-16)/12 ) 1371 nUpper = (nLength-16)/12; 1372 1373 /* binary search in "segmented coverage" subtable */ 1374 while( nLower < nUpper ) { 1375 int nIndex = (nLower + nUpper) / 2; 1376 const sal_uInt32* pEntry = &pCMAP12[ 4 + 3*nIndex ]; 1377 sal_uInt32 cStart = Int32FromMOTA( pEntry[0] ); 1378 sal_uInt32 cLast = Int32FromMOTA( pEntry[1] ); 1379 if( cChar < cStart ) 1380 nUpper = nIndex; 1381 else if( cChar > cLast ) 1382 nLower = nIndex + 1; 1383 else { /* found matching entry! */ 1384 sal_uInt32 nGlyph = Int32FromMOTA( pEntry[2] ); 1385 nGlyph += cChar - cStart; 1386 return nGlyph; 1387 } 1388 } 1389 1390 return MISSING_GLYPH_INDEX; 1391 } 1392 1393 1394 static void FindCmap(TrueTypeFont *ttf) 1395 { 1396 const sal_uInt8* table = getTable(ttf, O_cmap); 1397 sal_uInt32 table_size = getTableSize(ttf, O_cmap); 1398 sal_uInt16 ncmaps = GetUInt16(table, 2, 1); 1399 unsigned int i; 1400 sal_uInt32 AppleUni = 0; // Apple Unicode 1401 sal_uInt32 ThreeZero = 0; /* MS Symbol */ 1402 sal_uInt32 ThreeOne = 0; /* MS UCS-2 */ 1403 sal_uInt32 ThreeTwo = 0; /* MS ShiftJIS */ 1404 sal_uInt32 ThreeThree = 0; /* MS Big5 */ 1405 sal_uInt32 ThreeFour = 0; /* MS PRC */ 1406 sal_uInt32 ThreeFive = 0; /* MS Wansung */ 1407 sal_uInt32 ThreeSix = 0; /* MS Johab */ 1408 1409 for (i = 0; i < ncmaps; i++) { 1410 sal_uInt32 offset; 1411 sal_uInt16 pID, eID; 1412 1413 /* sanity check, cmap entry must lie within table */ 1414 if( i*8+4 > table_size ) 1415 break; 1416 1417 pID = GetUInt16(table, 4 + i * 8, 1); 1418 eID = GetUInt16(table, 6 + i * 8, 1); 1419 offset = GetUInt32(table, 8 + i * 8, 1); 1420 1421 /* sanity check, cmap must lie within file */ 1422 if( (table - ttf->ptr) + offset > (sal_uInt32)ttf->fsize ) 1423 continue; 1424 1425 /* Unicode tables in Apple fonts */ 1426 if (pID == 0) { 1427 AppleUni = offset; 1428 } 1429 1430 if (pID == 3) { 1431 switch (eID) { 1432 case 0: ThreeZero = offset; break; 1433 case 10: // UCS-4 1434 case 1: ThreeOne = offset; break; 1435 case 2: ThreeTwo = offset; break; 1436 case 3: ThreeThree = offset; break; 1437 case 4: ThreeFour = offset; break; 1438 case 5: ThreeFive = offset; break; 1439 case 6: ThreeSix = offset; break; 1440 } 1441 } 1442 } 1443 1444 // fall back to AppleUnicode if there are no ThreeOne/Threezero tables 1445 if( AppleUni && !ThreeZero && !ThreeOne) 1446 ThreeOne = AppleUni; 1447 1448 if (ThreeOne) { 1449 ttf->cmapType = CMAP_MS_Unicode; 1450 ttf->cmap = table + ThreeOne; 1451 } else if (ThreeTwo) { 1452 ttf->cmapType = CMAP_MS_ShiftJIS; 1453 ttf->cmap = table + ThreeTwo; 1454 } else if (ThreeThree) { 1455 ttf->cmapType = CMAP_MS_Big5; 1456 ttf->cmap = table + ThreeThree; 1457 } else if (ThreeFour) { 1458 ttf->cmapType = CMAP_MS_PRC; 1459 ttf->cmap = table + ThreeFour; 1460 } else if (ThreeFive) { 1461 ttf->cmapType = CMAP_MS_Wansung; 1462 ttf->cmap = table + ThreeFive; 1463 } else if (ThreeSix) { 1464 ttf->cmapType = CMAP_MS_Johab; 1465 ttf->cmap = table + ThreeSix; 1466 } else if (ThreeZero) { 1467 ttf->cmapType = CMAP_MS_Symbol; 1468 ttf->cmap = table + ThreeZero; 1469 } else { 1470 ttf->cmapType = CMAP_NOT_USABLE; 1471 ttf->cmap = 0; 1472 } 1473 1474 if (ttf->cmapType != CMAP_NOT_USABLE) { 1475 switch (GetUInt16(ttf->cmap, 0, 1)) { 1476 case 0: ttf->mapper = getGlyph0; break; 1477 case 2: ttf->mapper = getGlyph2; break; 1478 case 4: ttf->mapper = getGlyph4; break; 1479 case 6: ttf->mapper = getGlyph6; break; 1480 case 12: ttf->mapper= getGlyph12; break; 1481 default: 1482 #if OSL_DEBUG_LEVEL > 1 1483 /*- if the cmap table is really broken */ 1484 printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1)); 1485 #endif 1486 ttf->cmapType = CMAP_NOT_USABLE; 1487 ttf->cmap = 0; 1488 ttf->mapper = 0; 1489 } 1490 } 1491 } 1492 1493 static void GetKern(TrueTypeFont *ttf) 1494 { 1495 const sal_uInt8* table = getTable(ttf, O_kern); 1496 const sal_uInt8 *ptr; 1497 1498 if( !table ) 1499 goto badtable; 1500 1501 if (GetUInt16(table, 0, 1) == 0) { /* Traditional Microsoft style table with sal_uInt16 version and nTables fields */ 1502 ttf->nkern = GetUInt16(table, 2, 1); 1503 ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8 *)); 1504 assert(ttf->kerntables != 0); 1505 memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); 1506 ttf->kerntype = KT_MICROSOFT; 1507 ptr = table + 4; 1508 for( unsigned i = 0; i < ttf->nkern; ++i) { 1509 ttf->kerntables[i] = ptr; 1510 ptr += GetUInt16(ptr, 2, 1); 1511 /* sanity check */ 1512 if( ptr > ttf->ptr+ttf->fsize ) 1513 { 1514 free( ttf->kerntables ); 1515 goto badtable; 1516 } 1517 } 1518 return; 1519 } 1520 1521 if (GetUInt32(table, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */ 1522 ttf->nkern = GetUInt32(table, 4, 1); 1523 ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8*)); 1524 assert(ttf->kerntables != 0); 1525 memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); 1526 ttf->kerntype = KT_APPLE_NEW; 1527 ptr = table + 8; 1528 for( unsigned i = 0; i < ttf->nkern; ++i) { 1529 ttf->kerntables[i] = ptr; 1530 ptr += GetUInt32(ptr, 0, 1); 1531 /* sanity check; there are some fonts that are broken in this regard */ 1532 if( ptr > ttf->ptr+ttf->fsize ) 1533 { 1534 free( ttf->kerntables ); 1535 goto badtable; 1536 } 1537 } 1538 return; 1539 } 1540 1541 badtable: 1542 ttf->kerntype = KT_NONE; 1543 ttf->kerntables = 0; 1544 1545 return; 1546 } 1547 1548 #ifdef TEST5 1549 /* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and 1550 * that x and y elements of the kern array are initialized to zeroes 1551 */ 1552 static void KernGlyphsPrim1(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) 1553 { 1554 (void)ttf; /* avoid warning */ 1555 (void)glyphs; /* avoid warning */ 1556 (void)nglyphs; /* avoid warning */ 1557 (void)wmode; /* avoid warning */ 1558 (void)nglyphs; /* avoid warning */ 1559 (void)kern; /* avoid warning */ 1560 fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n"); 1561 } 1562 1563 static void KernGlyphsPrim2(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) 1564 { 1565 sal_uInt32 i, j; 1566 sal_uInt32 gpair; 1567 1568 if( ! nglyphs ) 1569 return; 1570 1571 for (i = 0; i < (sal_uInt32)nglyphs - 1; i++) { 1572 gpair = (glyphs[i] << 16) | glyphs[i+1]; 1573 #ifdef DEBUG2 1574 /* All fonts with MS kern table that I've seen so far contain just one kern subtable. 1575 * MS kern documentation is very poor and I doubt that font developers will be using 1576 * several subtables. I expect them to be using OpenType tables instead. 1577 * According to MS documention, format 2 subtables are not supported by Windows and OS/2. 1578 */ 1579 if (ttf->nkern > 1) { 1580 fprintf(stderr, "KernGlyphsPrim2: %d kern tables found.\n", ttf->nkern); 1581 } 1582 #endif 1583 for (j = 0; j < ttf->nkern; j++) { 1584 sal_uInt16 coverage = GetUInt16(ttf->kerntables[j], 4, 1); 1585 sal_uInt8 *ptr; 1586 int npairs; 1587 sal_uInt32 t; 1588 int l, r, k; 1589 1590 if (! ((coverage & 1) ^ wmode)) continue; 1591 if ((coverage & 0xFFFE) != 0) { 1592 #ifdef DEBUG2 1593 fprintf(stderr, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage); 1594 #endif 1595 continue; 1596 } 1597 ptr = ttf->kerntables[j]; 1598 npairs = GetUInt16(ptr, 6, 1); 1599 ptr += 14; 1600 l = 0; 1601 r = npairs; 1602 do { 1603 k = (l + r) >> 1; 1604 t = GetUInt32(ptr, k * 6, 1); 1605 if (gpair >= t) l = k + 1; 1606 if (gpair <= t) r = k - 1; 1607 } while (l <= r); 1608 if (l - r == 2) { 1609 if (!wmode) { 1610 kern[i].x = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); 1611 } else { 1612 kern[i].y = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); 1613 } 1614 /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */ 1615 } 1616 } 1617 } 1618 } 1619 #endif 1620 1621 /*- Public functions */ /*FOLD00*/ 1622 1623 int CountTTCFonts(const char* fname) 1624 { 1625 int nFonts = 0; 1626 sal_uInt8 buffer[12]; 1627 FILE* fd = fopen(fname, "rb"); 1628 if( fd ) { 1629 if (fread(buffer, 1, 12, fd) == 12) { 1630 if(GetUInt32(buffer, 0, 1) == T_ttcf ) 1631 nFonts = GetUInt32(buffer, 8, 1); 1632 } 1633 fclose(fd); 1634 } 1635 return nFonts; 1636 } 1637 1638 static void allocTrueTypeFont( TrueTypeFont** ttf ) 1639 { 1640 *ttf = (TrueTypeFont*)calloc(1,sizeof(TrueTypeFont)); 1641 if( *ttf != NULL ) 1642 { 1643 (*ttf)->tag = 0; 1644 (*ttf)->fname = 0; 1645 (*ttf)->fsize = -1; 1646 (*ttf)->ptr = 0; 1647 (*ttf)->nglyphs = 0xFFFFFFFF; 1648 (*ttf)->pGSubstitution = 0; 1649 } 1650 } 1651 1652 /* forward declariotn for the two entry points to use*/ 1653 static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ); 1654 1655 #if !defined(WIN32) && !defined(OS2) 1656 int OpenTTFontFile( const char* fname, sal_uInt32 facenum, TrueTypeFont** ttf ) 1657 { 1658 int ret, fd = -1; 1659 struct stat st; 1660 1661 if (!fname || !*fname) return SF_BADFILE; 1662 1663 allocTrueTypeFont( ttf ); 1664 if( ! *ttf ) 1665 return SF_MEMORY; 1666 1667 (*ttf)->fname = strdup(fname); 1668 if( ! (*ttf)->fname ) 1669 { 1670 ret = SF_MEMORY; 1671 goto cleanup; 1672 } 1673 1674 fd = open(fname, O_RDONLY); 1675 1676 if (fd == -1) { 1677 ret = SF_BADFILE; 1678 goto cleanup; 1679 } 1680 1681 if (fstat(fd, &st) == -1) { 1682 ret = SF_FILEIO; 1683 goto cleanup; 1684 } 1685 1686 (*ttf)->fsize = st.st_size; 1687 1688 /* On Mac OS, most likely will happen if a Mac user renames a font file 1689 * to be .ttf when its really a Mac resource-based font. 1690 * Size will be 0, but fonts smaller than 4 bytes would be broken anyway. 1691 */ 1692 if ((*ttf)->fsize == 0) { 1693 ret = SF_BADFILE; 1694 goto cleanup; 1695 } 1696 1697 if (((*ttf)->ptr = (sal_uInt8 *) mmap(0, (*ttf)->fsize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 1698 ret = SF_MEMORY; 1699 goto cleanup; 1700 } 1701 close(fd); 1702 1703 return doOpenTTFont( facenum, *ttf ); 1704 1705 cleanup: 1706 if (fd != -1) close(fd); 1707 /*- t and t->fname have been allocated! */ 1708 free((*ttf)->fname); 1709 free(*ttf); 1710 *ttf = NULL; 1711 return ret; 1712 } 1713 #endif 1714 1715 int OpenTTFontBuffer(void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf) 1716 { 1717 allocTrueTypeFont( ttf ); 1718 if( *ttf == NULL ) 1719 return SF_MEMORY; 1720 1721 (*ttf)->fname = NULL; 1722 (*ttf)->fsize = nLen; 1723 (*ttf)->ptr = (sal_uInt8*)pBuffer; 1724 1725 return doOpenTTFont( facenum, *ttf ); 1726 } 1727 1728 static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) 1729 { 1730 int i; 1731 sal_uInt32 length, tag; 1732 sal_uInt32 tdoffset = 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */ 1733 int indexfmt, k; 1734 1735 sal_uInt32 version = GetInt32(t->ptr, 0, 1); 1736 1737 if ((version == 0x00010000) || (version == T_true)) { 1738 tdoffset = 0; 1739 } else if (version == T_otto) { /* PS-OpenType font */ 1740 tdoffset = 0; 1741 } else if (version == T_ttcf) { /* TrueType collection */ 1742 if (GetUInt32(t->ptr, 4, 1) != 0x00010000) { 1743 CloseTTFont(t); 1744 return SF_TTFORMAT; 1745 } 1746 if (facenum >= GetUInt32(t->ptr, 8, 1)) { 1747 CloseTTFont(t); 1748 return SF_FONTNO; 1749 } 1750 tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1); 1751 } else { 1752 CloseTTFont(t); 1753 return SF_TTFORMAT; 1754 } 1755 1756 #ifdef DEBUG2 1757 fprintf(stderr, "tdoffset: %d\n", tdoffset); 1758 #endif 1759 1760 /* magic number */ 1761 t->tag = TTFontClassTag; 1762 1763 t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1); 1764 if( t->ntables >= 128 ) 1765 return SF_TTFORMAT; 1766 1767 t->tables = (const sal_uInt8**)calloc(NUM_TAGS, sizeof(sal_uInt8*)); 1768 assert(t->tables != 0); 1769 t->tlens = (sal_uInt32*)calloc(NUM_TAGS, sizeof(sal_uInt32)); 1770 assert(t->tlens != 0); 1771 1772 memset(t->tables, 0, NUM_TAGS * sizeof(void *)); 1773 memset(t->tlens, 0, NUM_TAGS * sizeof(sal_uInt32)); 1774 1775 /* parse the tables */ 1776 for (i=0; i<(int)t->ntables; i++) { 1777 int nIndex; 1778 tag = GetUInt32(t->ptr + tdoffset + 12, 16 * i, 1); 1779 switch( tag ) { 1780 case T_maxp: nIndex = O_maxp; break; 1781 case T_glyf: nIndex = O_glyf; break; 1782 case T_head: nIndex = O_head; break; 1783 case T_loca: nIndex = O_loca; break; 1784 case T_name: nIndex = O_name; break; 1785 case T_hhea: nIndex = O_hhea; break; 1786 case T_hmtx: nIndex = O_hmtx; break; 1787 case T_cmap: nIndex = O_cmap; break; 1788 case T_vhea: nIndex = O_vhea; break; 1789 case T_vmtx: nIndex = O_vmtx; break; 1790 case T_OS2 : nIndex = O_OS2; break; 1791 case T_post: nIndex = O_post; break; 1792 case T_kern: nIndex = O_kern; break; 1793 case T_cvt : nIndex = O_cvt; break; 1794 case T_prep: nIndex = O_prep; break; 1795 case T_fpgm: nIndex = O_fpgm; break; 1796 case T_gsub: nIndex = O_gsub; break; 1797 case T_CFF: nIndex = O_CFF; break; 1798 default: nIndex = -1; break; 1799 } 1800 if( nIndex >= 0 ) { 1801 sal_uInt32 nTableOffset = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8, 1); 1802 length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12, 1); 1803 t->tables[nIndex] = t->ptr + nTableOffset; 1804 t->tlens[nIndex] = length; 1805 } 1806 } 1807 1808 /* Fixup offsets when only a TTC extract was provided */ 1809 if( facenum == (sal_uInt32)~0 ) { 1810 sal_uInt8* pHead = (sal_uInt8*)t->tables[O_head]; 1811 if( !pHead ) 1812 return SF_TTFORMAT; 1813 /* limit Head candidate to TTC extract's limits */ 1814 if( pHead > t->ptr + (t->fsize - 54) ) 1815 pHead = t->ptr + (t->fsize - 54); 1816 /* TODO: find better method than searching head table's magic */ 1817 sal_uInt8* p = NULL; 1818 for( p = pHead + 12; p > t->ptr; --p ) { 1819 if( p[0]==0x5F && p[1]==0x0F && p[2]==0x3C && p[3]==0xF5 ) { 1820 int nDelta = (pHead + 12) - p, j; 1821 if( nDelta ) 1822 for( j=0; j<NUM_TAGS; ++j ) 1823 if( t->tables[j] ) 1824 *(char**)&t->tables[j] -= nDelta; 1825 break; 1826 } 1827 } 1828 if( p <= t->ptr ) 1829 return SF_TTFORMAT; 1830 } 1831 1832 /* Check the table offsets after TTC correction */ 1833 for (i=0; i<NUM_TAGS; i++) { 1834 /* sanity check: table must lay completely within the file 1835 * at this point one could check the checksum of all contained 1836 * tables, but this would be quite time intensive. 1837 * Try to fix tables, so we can cope with minor problems. 1838 */ 1839 1840 if( (sal_uInt8*)t->tables[i] < t->ptr ) 1841 { 1842 #if OSL_DEBUG_LEVEL > 1 1843 if( t->tables[i] ) 1844 fprintf( stderr, "font file %s has bad table offset %d (tagnum=%d)\n", t->fname, (sal_uInt8*)t->tables[i]-t->ptr, i ); 1845 #endif 1846 t->tlens[i] = 0; 1847 t->tables[i] = NULL; 1848 } 1849 else if( (sal_uInt8*)t->tables[i] + t->tlens[i] > t->ptr + t->fsize ) 1850 { 1851 int nMaxLen = (t->ptr + t->fsize) - (sal_uInt8*)t->tables[i]; 1852 if( nMaxLen < 0 ) 1853 nMaxLen = 0; 1854 t->tlens[i] = nMaxLen; 1855 #if OSL_DEBUG_LEVEL > 1 1856 fprintf( stderr, "font file %s has too big table (tagnum=%d)\n", t->fname, i ); 1857 #endif 1858 } 1859 } 1860 1861 /* At this point TrueTypeFont is constructed, now need to verify the font format 1862 and read the basic font properties */ 1863 1864 /* The following tables are absolutely required: 1865 * maxp, head, name, cmap 1866 */ 1867 1868 if( !(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_name) && getTable(t, O_cmap)) ) { 1869 CloseTTFont(t); 1870 return SF_TTFORMAT; 1871 } 1872 1873 const sal_uInt8* table = getTable(t, O_maxp); 1874 t->nglyphs = GetUInt16(table, 4, 1); 1875 1876 table = getTable(t, O_head); 1877 t->unitsPerEm = GetUInt16(table, 18, 1); 1878 indexfmt = GetInt16(table, 50, 1); 1879 1880 if( ((indexfmt != 0) && (indexfmt != 1)) || (t->unitsPerEm <= 0) ) { 1881 CloseTTFont(t); 1882 return SF_TTFORMAT; 1883 } 1884 1885 if( getTable(t, O_glyf) && getTable(t, O_loca) ) { /* TTF or TTF-OpenType */ 1886 k = (getTableSize(t, O_loca) / (indexfmt ? 4 : 2)) - 1; 1887 if( k < (int)t->nglyphs ) /* Hack for broken Chinese fonts */ 1888 t->nglyphs = k; 1889 1890 table = getTable(t, O_loca); 1891 t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32)); 1892 assert(t->goffsets != 0); 1893 1894 for( i = 0; i <= (int)t->nglyphs; ++i ) 1895 t->goffsets[i] = indexfmt ? GetUInt32(table, i << 2, 1) : (sal_uInt32)GetUInt16(table, i << 1, 1) << 1; 1896 } else if( getTable(t, O_CFF) ) { /* PS-OpenType */ 1897 t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32)); 1898 /* TODO: implement to get subsetting */ 1899 assert(t->goffsets != 0); 1900 } else { 1901 CloseTTFont(t); 1902 return SF_TTFORMAT; 1903 } 1904 1905 table = getTable(t, O_hhea); 1906 t->numberOfHMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; 1907 1908 table = getTable(t, O_vhea); 1909 t->numOfLongVerMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; 1910 1911 GetNames(t); 1912 FindCmap(t); 1913 GetKern(t); 1914 ReadGSUB( t, 0, 0 ); 1915 1916 return SF_OK; 1917 } 1918 1919 void CloseTTFont(TrueTypeFont *ttf) /*FOLD01*/ 1920 { 1921 if (ttf->tag != TTFontClassTag) return; 1922 1923 #if !defined(WIN32) && !defined(OS2) 1924 if( ttf->fname ) 1925 munmap((char *) ttf->ptr, ttf->fsize); 1926 #endif 1927 free(ttf->fname); 1928 free(ttf->goffsets); 1929 free(ttf->psname); 1930 free(ttf->family); 1931 if( ttf->ufamily ) 1932 free( ttf->ufamily ); 1933 free(ttf->subfamily); 1934 if( ttf->usubfamily ) 1935 free( ttf->usubfamily ); 1936 free(ttf->tables); 1937 free(ttf->tlens); 1938 free(ttf->kerntables); 1939 1940 ReleaseGSUB(ttf); 1941 1942 free(ttf); 1943 return; 1944 } 1945 1946 int GetTTGlyphPoints(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray) 1947 { 1948 return GetTTGlyphOutline(ttf, glyphID, pointArray, 0, 0); 1949 } 1950 1951 int GetTTGlyphComponents(TrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal_uInt32 >& glyphlist) 1952 { 1953 int n = 1; 1954 1955 if( glyphID >= ttf->nglyphs ) 1956 return 0; 1957 1958 const sal_uInt8* glyf = getTable(ttf, O_glyf); 1959 const sal_uInt8* ptr = glyf + ttf->goffsets[glyphID]; 1960 1961 glyphlist.push_back( glyphID ); 1962 1963 if (GetInt16(ptr, 0, 1) == -1) { 1964 sal_uInt16 flags, index; 1965 ptr += 10; 1966 do { 1967 flags = GetUInt16(ptr, 0, 1); 1968 index = GetUInt16(ptr, 2, 1); 1969 1970 ptr += 4; 1971 n += GetTTGlyphComponents(ttf, index, glyphlist); 1972 1973 if (flags & ARG_1_AND_2_ARE_WORDS) { 1974 ptr += 4; 1975 } else { 1976 ptr += 2; 1977 } 1978 1979 if (flags & WE_HAVE_A_SCALE) { 1980 ptr += 2; 1981 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { 1982 ptr += 4; 1983 } else if (flags & WE_HAVE_A_TWO_BY_TWO) { 1984 ptr += 8; 1985 } 1986 } while (flags & MORE_COMPONENTS); 1987 } 1988 1989 return n; 1990 } 1991 1992 #ifndef NO_TYPE3 1993 int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, /*FOLD00*/ 1994 sal_uInt16 *glyphArray, sal_uInt8 *encoding, int nGlyphs, 1995 int wmode) 1996 { 1997 ControlPoint *pa; 1998 PSPathElement *path; 1999 int i, j, r, n; 2000 const sal_uInt8* table = getTable(ttf, O_head); 2001 TTGlyphMetrics metrics; 2002 int UPEm = ttf->unitsPerEm; 2003 2004 const char *h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n"; 2005 const char *h02 = "%% Creator: %s %s %s\n"; 2006 const char *h09 = "%% Original font name: %s\n"; 2007 2008 const char *h10 = 2009 "30 dict begin\n" 2010 "/PaintType 0 def\n" 2011 "/FontType 3 def\n" 2012 "/StrokeWidth 0 def\n"; 2013 2014 const char *h11 = "/FontName (%s) cvn def\n"; 2015 2016 /* 2017 const char *h12 = "%/UniqueID %d def\n"; 2018 */ 2019 const char *h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n"; 2020 const char *h14 = "/FontBBox [%d %d %d %d] def\n"; 2021 2022 const char *h15= 2023 "/Encoding 256 array def\n" 2024 " 0 1 255 {Encoding exch /.notdef put} for\n"; 2025 2026 const char *h16 = " Encoding %d /glyph%d put\n"; 2027 const char *h17 = "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n"; 2028 2029 const char *h30 = "/CharProcs %d dict def\n"; 2030 const char *h31 = " CharProcs begin\n"; 2031 const char *h32 = " /.notdef {} def\n"; 2032 const char *h33 = " /glyph%d {\n"; 2033 const char *h34 = " } bind def\n"; 2034 const char *h35 = " end\n"; 2035 2036 const char *h40 = 2037 "/BuildGlyph {\n" 2038 " exch /CharProcs get exch\n" 2039 " 2 copy known not\n" 2040 " {pop /.notdef} if\n" 2041 " get exec\n" 2042 "} bind def\n" 2043 "/BuildChar {\n" 2044 " 1 index /Encoding get exch get\n" 2045 " 1 index /BuildGlyph get exec\n" 2046 "} bind def\n" 2047 "currentdict end\n"; 2048 2049 const char *h41 = "(%s) cvn exch definefont pop\n"; 2050 2051 2052 if (!((nGlyphs > 0) && (nGlyphs <= 256))) return SF_GLYPHNUM; 2053 if (!glyphArray) return SF_BADARG; 2054 if (!fname) fname = ttf->psname; 2055 2056 fprintf(outf, h01, GetInt16(table, 0, 1), GetUInt16(table, 2, 1), GetInt16(table, 4, 1), GetUInt16(table, 6, 1)); 2057 fprintf(outf, h02, modname, modver, modextra); 2058 fprintf(outf, h09, ttf->psname); 2059 2060 fprintf(outf, h10); 2061 fprintf(outf, h11, fname); 2062 /* fprintf(outf, h12, 4000000); */ 2063 2064 /* XUID generation: 2065 * 103 0 0 C1 C2 C3 C4 2066 * C1 - CRC-32 of the entire source TrueType font 2067 * C2 - number of glyphs in the subset 2068 * C3 - CRC-32 of the glyph array 2069 * C4 - CRC-32 of the encoding array 2070 * 2071 * All CRC-32 numbers are presented as hexadecimal numbers 2072 */ 2073 2074 fprintf(outf, h17, rtl_crc32(0, ttf->ptr, ttf->fsize), nGlyphs, rtl_crc32(0, glyphArray, nGlyphs * 2), rtl_crc32(0, encoding, nGlyphs)); 2075 fprintf(outf, h13); 2076 fprintf(outf, h14, XUnits(UPEm, GetInt16(table, 36, 1)), XUnits(UPEm, GetInt16(table, 38, 1)), XUnits(UPEm, GetInt16(table, 40, 1)), XUnits(UPEm, GetInt16(table, 42, 1))); 2077 fprintf(outf, h15); 2078 2079 for (i = 0; i < nGlyphs; i++) { 2080 fprintf(outf, h16, encoding[i], i); 2081 } 2082 2083 fprintf(outf, h30, nGlyphs+1); 2084 fprintf(outf, h31); 2085 fprintf(outf, h32); 2086 2087 for (i = 0; i < nGlyphs; i++) { 2088 fprintf(outf, h33, i); 2089 r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->nglyphs ? glyphArray[i] : 0, &pa, &metrics, 0); 2090 2091 if (r > 0) { 2092 n = BSplineToPSPath(pa, r, &path); 2093 } else { 2094 n = 0; /* glyph might have zero contours but valid metrics ??? */ 2095 path = 0; 2096 if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */ 2097 continue; 2098 } 2099 } 2100 fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n", 2101 wmode == 0 ? XUnits(UPEm, metrics.aw) : 0, 2102 wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah), 2103 XUnits(UPEm, metrics.xMin), 2104 XUnits(UPEm, metrics.yMin), 2105 XUnits(UPEm, metrics.xMax), 2106 XUnits(UPEm, metrics.yMax)); 2107 2108 for (j = 0; j < n; j++) 2109 { 2110 switch (path[j].type) 2111 { 2112 case PS_MOVETO: 2113 fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); 2114 break; 2115 2116 case PS_LINETO: 2117 fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); 2118 break; 2119 2120 case PS_CURVETO: 2121 fprintf(outf, "\t%d %d %d %d %d %d curveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1), XUnits(UPEm, path[j].x2), XUnits(UPEm, path[j].y2), XUnits(UPEm, path[j].x3), XUnits(UPEm, path[j].y3)); 2122 break; 2123 2124 case PS_CLOSEPATH: 2125 fprintf(outf, "\tclosepath\n"); 2126 break; 2127 case PS_NOOP: 2128 break; 2129 } 2130 } 2131 if (n > 0) fprintf(outf, "\tfill\n"); /* if glyph is not a whitespace character */ 2132 2133 fprintf(outf, h34); 2134 2135 free(pa); 2136 free(path); 2137 } 2138 fprintf(outf, h35); 2139 2140 fprintf(outf, h40); 2141 fprintf(outf, h41, fname); 2142 2143 return SF_OK; 2144 } 2145 #endif 2146 2147 #ifndef NO_TTCR 2148 int CreateTTFromTTGlyphs(TrueTypeFont *ttf, 2149 const char *fname, 2150 sal_uInt16 *glyphArray, 2151 sal_uInt8 *encoding, 2152 int nGlyphs, 2153 int nNameRecs, 2154 NameRecord *nr, 2155 sal_uInt32 flags) 2156 { 2157 TrueTypeCreator *ttcr; 2158 TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0, *cmap=0, *name=0, *post = 0, *os2 = 0; 2159 int i; 2160 int res; 2161 2162 TrueTypeCreatorNewEmpty(T_true, &ttcr); 2163 2164 /** name **/ 2165 2166 if (flags & TTCF_AutoName) { 2167 /* not implemented yet 2168 NameRecord *names; 2169 NameRecord newname; 2170 int n = GetTTNameRecords(ttf, &names); 2171 int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0; 2172 sal_uInt8 *cp1; 2173 sal_uInt8 suffix[32]; 2174 sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2); 2175 sal_uInt32 c2 = crc32(encoding, nGlyphs); 2176 int len; 2177 snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs); 2178 2179 name = TrueTypeTableNew_name(0, 0); 2180 for (i = 0; i < n; i++) { 2181 if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) { 2182 2183 memcpy(newname, names+i, sizeof(NameRecord)); 2184 newname.slen = name[i].slen + strlen(suffix); 2185 */ 2186 const sal_uInt8 ptr[] = {0,'T',0,'r',0,'u',0,'e',0,'T',0,'y',0,'p',0,'e',0,'S',0,'u',0,'b',0,'s',0,'e',0,'t'}; 2187 NameRecord n1 = {1, 0, 0, 6, 14, (sal_uInt8*)"TrueTypeSubset"}; 2188 NameRecord n2 = {3, 1, 1033, 6, 28, 0}; 2189 n2.sptr = (sal_uInt8 *) ptr; 2190 name = TrueTypeTableNew_name(0, 0); 2191 nameAdd(name, &n1); 2192 nameAdd(name, &n2); 2193 } else { 2194 if (nNameRecs == 0) { 2195 NameRecord *names; 2196 int n = GetTTNameRecords(ttf, &names); 2197 name = TrueTypeTableNew_name(n, names); 2198 DisposeNameRecords(names, n); 2199 } else { 2200 name = TrueTypeTableNew_name(nNameRecs, nr); 2201 } 2202 } 2203 2204 /** maxp **/ 2205 maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); 2206 2207 /** hhea **/ 2208 const sal_uInt8* p = getTable(ttf, O_hhea); 2209 if (p) { 2210 hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); 2211 } else { 2212 hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); 2213 } 2214 2215 /** head **/ 2216 2217 p = getTable(ttf, O_head); 2218 assert(p != 0); 2219 head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), 2220 GetUInt16(p, 16, 1), 2221 GetUInt16(p, 18, 1), 2222 p+20, 2223 GetUInt16(p, 44, 1), 2224 GetUInt16(p, 46, 1), 2225 GetInt16(p, 48, 1)); 2226 2227 2228 /** glyf **/ 2229 2230 glyf = TrueTypeTableNew_glyf(); 2231 sal_uInt32* gID = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32)); 2232 2233 for (i = 0; i < nGlyphs; i++) { 2234 gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); 2235 } 2236 2237 /** cmap **/ 2238 cmap = TrueTypeTableNew_cmap(); 2239 2240 for (i=0; i < nGlyphs; i++) { 2241 cmapAdd(cmap, 0x010000, encoding[i], gID[i]); 2242 } 2243 2244 /** cvt **/ 2245 if ((p = getTable(ttf, O_cvt)) != 0) { 2246 cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); 2247 } 2248 2249 /** prep **/ 2250 if ((p = getTable(ttf, O_prep)) != 0) { 2251 prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); 2252 } 2253 2254 /** fpgm **/ 2255 if ((p = getTable(ttf, O_fpgm)) != 0) { 2256 fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); 2257 } 2258 2259 /** post **/ 2260 if ((p = getTable(ttf, O_post)) != 0) { 2261 post = TrueTypeTableNew_post(0x00030000, 2262 GetUInt32(p, 4, 1), 2263 GetUInt16(p, 8, 1), 2264 GetUInt16(p, 10, 1), 2265 GetUInt16(p, 12, 1)); 2266 } else { 2267 post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0); 2268 } 2269 2270 if (flags & TTCF_IncludeOS2) { 2271 if ((p = getTable(ttf, O_OS2)) != 0) { 2272 os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p); 2273 } 2274 } 2275 2276 AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea); 2277 AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap); 2278 AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm); 2279 AddTable(ttcr, post); AddTable(ttcr, os2); 2280 2281 if ((res = StreamToFile(ttcr, fname)) != SF_OK) { 2282 #if OSL_DEBUG_LEVEL > 1 2283 fprintf(stderr, "StreamToFile: error code: %d.\n", res); 2284 #endif 2285 } 2286 2287 TrueTypeCreatorDispose(ttcr); 2288 free(gID); 2289 2290 return res; 2291 } 2292 #endif 2293 2294 2295 #ifndef NO_TYPE42 2296 static GlyphOffsets *GlyphOffsetsNew(sal_uInt8 *sfntP) 2297 { 2298 GlyphOffsets* res = (GlyphOffsets*)smalloc(sizeof(GlyphOffsets)); 2299 sal_uInt8 *loca = NULL; 2300 sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); 2301 sal_uInt32 locaLen = 0; 2302 sal_Int16 indexToLocFormat = 0; 2303 2304 for (i = 0; i < numTables; i++) { 2305 sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); 2306 sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); 2307 sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); 2308 2309 if (tag == T_loca) { 2310 loca = sfntP + off; 2311 locaLen = len; 2312 } else if (tag == T_head) { 2313 indexToLocFormat = GetInt16(sfntP + off, 50, 1); 2314 } 2315 } 2316 2317 res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2); 2318 assert(res->nGlyphs != 0); 2319 res->offs = (sal_uInt32*)scalloc(res->nGlyphs, sizeof(sal_uInt32)); 2320 2321 for (i = 0; i < res->nGlyphs; i++) { 2322 if (indexToLocFormat == 1) { 2323 res->offs[i] = GetUInt32(loca, i * 4, 1); 2324 } else { 2325 res->offs[i] = GetUInt16(loca, i * 2, 1) << 1; 2326 } 2327 } 2328 return res; 2329 } 2330 2331 static void GlyphOffsetsDispose(GlyphOffsets *_this) 2332 { 2333 if (_this) { 2334 free(_this->offs); 2335 free(_this); 2336 } 2337 } 2338 2339 static void DumpSfnts(FILE *outf, sal_uInt8 *sfntP) 2340 { 2341 HexFmt *h = HexFmtNew(outf); 2342 sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); 2343 GlyphOffsets *go = GlyphOffsetsNew(sfntP); 2344 sal_uInt8 pad[] = {0,0,0,0}; /* zeroes */ 2345 2346 assert(numTables <= 9); /* Type42 has 9 required tables */ 2347 2348 sal_uInt32* offs = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32)); 2349 // sal_uInt32* lens = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32)); 2350 2351 fputs("/sfnts [", outf); 2352 HexFmtOpenString(h); 2353 HexFmtBlockWrite(h, sfntP, 12); /* stream out the Offset Table */ 2354 HexFmtBlockWrite(h, sfntP+12, 16 * numTables); /* stream out the Table Directory */ 2355 2356 for (i=0; i<numTables; i++) { 2357 sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); 2358 sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); 2359 sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); 2360 2361 if (tag != T_glyf) { 2362 HexFmtBlockWrite(h, sfntP + off, len); 2363 } else { 2364 sal_uInt8 *glyf = sfntP + off; 2365 sal_uInt32 o, l, j; 2366 for (j = 0; j < go->nGlyphs - 1; j++) { 2367 o = go->offs[j]; 2368 l = go->offs[j + 1] - o; 2369 HexFmtBlockWrite(h, glyf + o, l); 2370 } 2371 } 2372 HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3); 2373 } 2374 HexFmtCloseString(h); 2375 fputs("] def\n", outf); 2376 GlyphOffsetsDispose(go); 2377 HexFmtDispose(h); 2378 free(offs); 2379 // free(lens); 2380 } 2381 2382 int CreateT42FromTTGlyphs(TrueTypeFont *ttf, 2383 FILE *outf, 2384 const char *psname, 2385 sal_uInt16 *glyphArray, 2386 sal_uInt8 *encoding, 2387 int nGlyphs) 2388 { 2389 TrueTypeCreator *ttcr; 2390 TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0; 2391 int i; 2392 int res; 2393 2394 sal_uInt32 ver, rev; 2395 2396 sal_uInt8 *sfntP; 2397 sal_uInt32 sfntLen; 2398 int UPEm = ttf->unitsPerEm; 2399 2400 if (nGlyphs >= 256) return SF_GLYPHNUM; 2401 2402 assert(psname != 0); 2403 2404 TrueTypeCreatorNewEmpty(T_true, &ttcr); 2405 2406 /* head */ 2407 const sal_uInt8* p = getTable(ttf, O_head); 2408 const sal_uInt8* headP = p; 2409 assert(p != 0); 2410 head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), GetUInt16(p, 16, 1), GetUInt16(p, 18, 1), p+20, GetUInt16(p, 44, 1), GetUInt16(p, 46, 1), GetInt16(p, 48, 1)); 2411 ver = GetUInt32(p, 0, 1); 2412 rev = GetUInt32(p, 4, 1); 2413 2414 /** hhea **/ 2415 p = getTable(ttf, O_hhea); 2416 if (p) { 2417 hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); 2418 } else { 2419 hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); 2420 } 2421 2422 /** maxp **/ 2423 maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); 2424 2425 /** cvt **/ 2426 if ((p = getTable(ttf, O_cvt)) != 0) { 2427 cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); 2428 } 2429 2430 /** prep **/ 2431 if ((p = getTable(ttf, O_prep)) != 0) { 2432 prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); 2433 } 2434 2435 /** fpgm **/ 2436 if ((p = getTable(ttf, O_fpgm)) != 0) { 2437 fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); 2438 } 2439 2440 /** glyf **/ 2441 glyf = TrueTypeTableNew_glyf(); 2442 sal_uInt16* gID = (sal_uInt16*)scalloc(nGlyphs, sizeof(sal_uInt32)); 2443 2444 for (i = 0; i < nGlyphs; i++) { 2445 gID[i] = (sal_uInt16)glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); 2446 } 2447 2448 AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt); 2449 AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm); 2450 2451 if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SF_OK) { 2452 TrueTypeCreatorDispose(ttcr); 2453 free(gID); 2454 return res; 2455 } 2456 2457 fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver>>16), (int)(ver & 0xFFFF), (int)(rev>>16), (int)(rev & 0xFFFF)); 2458 fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra); 2459 fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fname); 2460 fprintf(outf, "%%- Original font name: %s\n", ttf->psname); 2461 fprintf(outf, "%%- Original font family: %s\n", ttf->family); 2462 fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily); 2463 fprintf(outf, "11 dict begin\n"); 2464 fprintf(outf, "/FontName (%s) cvn def\n", psname); 2465 fprintf(outf, "/PaintType 0 def\n"); 2466 fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n"); 2467 fprintf(outf, "/FontBBox [%d %d %d %d] def\n", XUnits(UPEm, GetInt16(headP, 36, 1)), XUnits(UPEm, GetInt16(headP, 38, 1)), XUnits(UPEm, GetInt16(headP, 40, 1)), XUnits(UPEm, GetInt16(headP, 42, 1))); 2468 fprintf(outf, "/FontType 42 def\n"); 2469 fprintf(outf, "/Encoding 256 array def\n"); 2470 fprintf(outf, " 0 1 255 {Encoding exch /.notdef put} for\n"); 2471 2472 for (i = 1; i<nGlyphs; i++) { 2473 fprintf(outf, "Encoding %d /glyph%d put\n", encoding[i], gID[i]); 2474 } 2475 fprintf(outf, "/XUID [103 0 1 16#%08X %d 16#%08X 16#%08X] def\n", (unsigned int)rtl_crc32(0, ttf->ptr, ttf->fsize), (unsigned int)nGlyphs, (unsigned int)rtl_crc32(0, glyphArray, nGlyphs * 2), (unsigned int)rtl_crc32(0, encoding, nGlyphs)); 2476 2477 DumpSfnts(outf, sfntP); 2478 2479 /* dump charstrings */ 2480 fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs); 2481 fprintf(outf, "/.notdef 0 def\n"); 2482 for (i = 1; i < (int)glyfCount(glyf); i++) { 2483 fprintf(outf,"/glyph%d %d def\n", i, i); 2484 } 2485 fprintf(outf, "end readonly def\n"); 2486 2487 fprintf(outf, "FontName currentdict end definefont pop\n"); 2488 TrueTypeCreatorDispose(ttcr); 2489 free(gID); 2490 free(sfntP); 2491 return SF_OK; 2492 } 2493 #endif 2494 2495 2496 #ifndef NO_MAPPERS 2497 int MapString(TrueTypeFont *ttf, sal_uInt16 *str, int nchars, sal_uInt16 *glyphArray, int bvertical) 2498 { 2499 int i; 2500 sal_uInt16 *cp; 2501 2502 if (ttf->cmapType == CMAP_NOT_USABLE ) return -1; 2503 if (!nchars) return 0; 2504 2505 if (glyphArray == 0) { 2506 cp = str; 2507 } else { 2508 cp = glyphArray; 2509 } 2510 2511 switch (ttf->cmapType) { 2512 case CMAP_MS_Symbol: 2513 if( ttf->mapper == getGlyph0 ) { 2514 sal_uInt16 aChar; 2515 for( i = 0; i < nchars; i++ ) { 2516 aChar = str[i]; 2517 if( ( aChar & 0xf000 ) == 0xf000 ) 2518 aChar &= 0x00ff; 2519 cp[i] = aChar; 2520 } 2521 } 2522 else if( glyphArray ) 2523 memcpy(glyphArray, str, nchars * 2); 2524 break; 2525 2526 case CMAP_MS_Unicode: 2527 if (glyphArray != 0) { 2528 memcpy(glyphArray, str, nchars * 2); 2529 } 2530 break; 2531 2532 case CMAP_MS_ShiftJIS: TranslateString12(str, cp, nchars); break; 2533 case CMAP_MS_Big5: TranslateString13(str, cp, nchars); break; 2534 case CMAP_MS_PRC: TranslateString14(str, cp, nchars); break; 2535 case CMAP_MS_Wansung: TranslateString15(str, cp, nchars); break; 2536 case CMAP_MS_Johab: TranslateString16(str, cp, nchars); break; 2537 } 2538 2539 for (i = 0; i < nchars; i++) { 2540 cp[i] = (sal_uInt16)ttf->mapper(ttf->cmap, cp[i]); 2541 if (cp[i]!=0 && bvertical!=0) 2542 cp[i] = (sal_uInt16)UseGSUB(ttf,cp[i],bvertical); 2543 } 2544 return nchars; 2545 } 2546 2547 sal_uInt16 MapChar(TrueTypeFont *ttf, sal_uInt16 ch, int bvertical) 2548 { 2549 switch (ttf->cmapType) { 2550 case CMAP_MS_Symbol: 2551 2552 if( ttf->mapper == getGlyph0 && ( ch & 0xf000 ) == 0xf000 ) 2553 ch &= 0x00ff; 2554 return (sal_uInt16)ttf->mapper(ttf->cmap, ch ); 2555 2556 case CMAP_MS_Unicode: break; 2557 case CMAP_MS_ShiftJIS: ch = TranslateChar12(ch); break; 2558 case CMAP_MS_Big5: ch = TranslateChar13(ch); break; 2559 case CMAP_MS_PRC: ch = TranslateChar14(ch); break; 2560 case CMAP_MS_Wansung: ch = TranslateChar15(ch); break; 2561 case CMAP_MS_Johab: ch = TranslateChar16(ch); break; 2562 default: return 0; 2563 } 2564 ch = (sal_uInt16)ttf->mapper(ttf->cmap, ch); 2565 if (ch!=0 && bvertical!=0) 2566 ch = (sal_uInt16)UseGSUB(ttf,ch,bvertical); 2567 return ch; 2568 } 2569 2570 int DoesVerticalSubstitution( TrueTypeFont *ttf, int bvertical) 2571 { 2572 int nRet = 0; 2573 if( bvertical) 2574 nRet = HasVerticalGSUB( ttf); 2575 return nRet; 2576 } 2577 2578 #endif 2579 2580 int GetTTGlyphCount( TrueTypeFont* ttf ) 2581 { 2582 return ttf->nglyphs; 2583 } 2584 2585 bool GetSfntTable( TrueTypeFont* ttf, int nSubtableIndex, 2586 const sal_uInt8** ppRawBytes, int* pRawLength ) 2587 { 2588 if( (nSubtableIndex < 0) || (nSubtableIndex >= NUM_TAGS) ) 2589 return false; 2590 *pRawLength = ttf->tlens[ nSubtableIndex ]; 2591 *ppRawBytes = ttf->tables[ nSubtableIndex ]; 2592 bool bOk = (*pRawLength > 0) && (ppRawBytes != NULL); 2593 return bOk; 2594 } 2595 2596 TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, sal_uInt16 *glyphArray, int nGlyphs, int mode) 2597 { 2598 const sal_uInt8* pTable; 2599 sal_uInt32 n; 2600 int nTableSize; 2601 2602 if (mode == 0) { 2603 n = ttf->numberOfHMetrics; 2604 pTable = getTable( ttf, O_hmtx ); 2605 nTableSize = getTableSize( ttf, O_hmtx ); 2606 } else { 2607 n = ttf->numOfLongVerMetrics; 2608 pTable = getTable( ttf, O_vmtx ); 2609 nTableSize = getTableSize( ttf, O_vmtx ); 2610 } 2611 2612 if (!nGlyphs || !glyphArray) return 0; /* invalid parameters */ 2613 if (!n || !pTable) return 0; /* the font does not contain the requested metrics */ 2614 2615 TTSimpleGlyphMetrics* res = (TTSimpleGlyphMetrics*)calloc(nGlyphs, sizeof(TTSimpleGlyphMetrics)); 2616 assert(res != 0); 2617 2618 const int UPEm = ttf->unitsPerEm; 2619 for( int i = 0; i < nGlyphs; ++i) { 2620 int nAdvOffset, nLsbOffset; 2621 sal_uInt16 glyphID = glyphArray[i]; 2622 2623 if (glyphID < n) { 2624 nAdvOffset = 4 * glyphID; 2625 nLsbOffset = nAdvOffset + 2; 2626 } else { 2627 nAdvOffset = 4 * (n - 1); 2628 if( glyphID < ttf->nglyphs ) 2629 nLsbOffset = 4 * n + 2 * (glyphID - n); 2630 else /* font is broken -> use lsb of last hmetrics */ 2631 nLsbOffset = nAdvOffset + 2; 2632 } 2633 2634 if( nAdvOffset >= nTableSize) 2635 res[i].adv = 0; /* better than a crash for buggy fonts */ 2636 else 2637 res[i].adv = static_cast<sal_uInt16>( 2638 XUnits( UPEm, GetUInt16( pTable, nAdvOffset, 1) ) ); 2639 2640 if( nLsbOffset >= nTableSize) 2641 res[i].sb = 0; /* better than a crash for buggy fonts */ 2642 else 2643 res[i].sb = static_cast<sal_Int16>( 2644 XUnits( UPEm, GetInt16( pTable, nLsbOffset, 1) ) ); 2645 } 2646 2647 return res; 2648 } 2649 2650 #ifndef NO_MAPPERS 2651 TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, sal_uInt16 firstChar, int nChars, int mode) 2652 { 2653 TTSimpleGlyphMetrics *res = 0; 2654 int i, n; 2655 2656 sal_uInt16* str = (sal_uInt16*)malloc(nChars * 2); 2657 assert(str != 0); 2658 2659 for (i=0; i<nChars; i++) str[i] = (sal_uInt16)(firstChar + i); 2660 if ((n = MapString(ttf, str, nChars, 0, mode)) != -1) { 2661 res = GetTTSimpleGlyphMetrics(ttf, str, n, mode); 2662 } 2663 2664 free(str); 2665 2666 return res; 2667 } 2668 #endif 2669 2670 void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info) 2671 { 2672 int UPEm = ttf->unitsPerEm; 2673 2674 memset(info, 0, sizeof(TTGlobalFontInfo)); 2675 2676 info->family = ttf->family; 2677 info->ufamily = ttf->ufamily; 2678 info->subfamily = ttf->subfamily; 2679 info->usubfamily = ttf->usubfamily; 2680 info->psname = ttf->psname; 2681 info->symbolEncoded = (ttf->cmapType == CMAP_MS_Symbol); 2682 2683 const sal_uInt8* table = getTable(ttf, O_OS2); 2684 if (table) { 2685 info->weight = GetUInt16(table, 4, 1); 2686 info->width = GetUInt16(table, 6, 1); 2687 2688 /* There are 3 different versions of OS/2 table: original (68 bytes long), 2689 * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,) 2690 * Apple's documentation recommends looking at the table length. 2691 */ 2692 if (getTableSize(ttf, O_OS2) > 68) { 2693 info->typoAscender = XUnits(UPEm,GetInt16(table, 68, 1)); 2694 info->typoDescender = XUnits(UPEm, GetInt16(table, 70, 1)); 2695 info->typoLineGap = XUnits(UPEm, GetInt16(table, 72, 1)); 2696 info->winAscent = XUnits(UPEm, GetUInt16(table, 74, 1)); 2697 info->winDescent = XUnits(UPEm, GetUInt16(table, 76, 1)); 2698 /* sanity check; some fonts treat winDescent as signed 2699 * violating the standard */ 2700 if( info->winDescent > 5*UPEm ) 2701 info->winDescent = XUnits(UPEm, GetInt16(table, 76,1)); 2702 } 2703 if (ttf->cmapType == CMAP_MS_Unicode) { 2704 info->rangeFlag = 1; 2705 info->ur1 = GetUInt32(table, 42, 1); 2706 info->ur2 = GetUInt32(table, 46, 1); 2707 info->ur3 = GetUInt32(table, 50, 1); 2708 info->ur4 = GetUInt32(table, 54, 1); 2709 } 2710 memcpy(info->panose, table + 32, 10); 2711 info->typeFlags = GetUInt16( table, 8, 1 ); 2712 if( getTable(ttf, O_CFF) ) 2713 info->typeFlags |= TYPEFLAG_PS_OPENTYPE; 2714 } 2715 2716 table = getTable(ttf, O_post); 2717 if (table && getTableSize(ttf, O_post) >= 12+sizeof(sal_uInt32)) { 2718 info->pitch = GetUInt32(table, 12, 1); 2719 info->italicAngle = GetInt32(table, 4, 1); 2720 } 2721 2722 table = getTable(ttf, O_head); /* 'head' tables is always there */ 2723 info->xMin = XUnits(UPEm, GetInt16(table, 36, 1)); 2724 info->yMin = XUnits(UPEm, GetInt16(table, 38, 1)); 2725 info->xMax = XUnits(UPEm, GetInt16(table, 40, 1)); 2726 info->yMax = XUnits(UPEm, GetInt16(table, 42, 1)); 2727 info->macStyle = GetInt16(table, 44, 1); 2728 2729 table = getTable(ttf, O_hhea); 2730 if (table) { 2731 info->ascender = XUnits(UPEm, GetInt16(table, 4, 1)); 2732 info->descender = XUnits(UPEm, GetInt16(table, 6, 1)); 2733 info->linegap = XUnits(UPEm, GetInt16(table, 8, 1)); 2734 } 2735 2736 table = getTable(ttf, O_vhea); 2737 if (table) { 2738 info->vascent = XUnits(UPEm, GetInt16(table, 4, 1)); 2739 info->vdescent = XUnits(UPEm, GetInt16(table, 6, 1)); 2740 } 2741 } 2742 2743 #ifdef TEST5 2744 void KernGlyphs(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) 2745 { 2746 int i; 2747 2748 if (!nglyphs || !glyphs || !kern) return; 2749 2750 for (i = 0; i < nglyphs-1; i++) kern[i].x = kern[i].y = 0; 2751 2752 switch (ttf->kerntype) { 2753 case KT_APPLE_NEW: KernGlyphsPrim1(ttf, glyphs, nglyphs, wmode, kern); return; 2754 case KT_MICROSOFT: KernGlyphsPrim2(ttf, glyphs, nglyphs, wmode, kern); return; 2755 default: return; 2756 } 2757 } 2758 #endif 2759 2760 GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, sal_uInt32 glyphID) 2761 { 2762 const sal_uInt8* glyf = getTable(ttf, O_glyf); 2763 const sal_uInt8* hmtx = getTable(ttf, O_hmtx); 2764 int i, n, m; 2765 2766 if( glyphID >= ttf->nglyphs ) 2767 return 0; 2768 2769 /* #127161# check the glyph offsets */ 2770 sal_uInt32 length = getTableSize( ttf, O_glyf ); 2771 if( length < ttf->goffsets[ glyphID+1 ] ) 2772 return 0; 2773 2774 length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; 2775 2776 GlyphData* d = (GlyphData*)malloc(sizeof(GlyphData)); assert(d != 0); 2777 2778 if (length > 0) { 2779 const sal_uInt8* srcptr = glyf + ttf->goffsets[glyphID]; 2780 d->ptr = (sal_uInt8*)malloc((length + 1) & ~1); assert(d->ptr != 0); 2781 memcpy( d->ptr, srcptr, length ); 2782 d->compflag = (GetInt16( srcptr, 0, 1 ) < 0); 2783 } else { 2784 d->ptr = 0; 2785 d->compflag = 0; 2786 } 2787 2788 d->glyphID = glyphID; 2789 d->nbytes = (sal_uInt16)((length + 1) & ~1); 2790 2791 /* now calculate npoints and ncontours */ 2792 ControlPoint *cp; 2793 n = GetTTGlyphPoints(ttf, glyphID, &cp); 2794 if (n != -1) { 2795 m = 0; 2796 for (i = 0; i < n; i++) { 2797 if (cp[i].flags & 0x8000) m++; 2798 } 2799 d->npoints = (sal_uInt16)n; 2800 d->ncontours = (sal_uInt16)m; 2801 free(cp); 2802 } else { 2803 d->npoints = 0; 2804 d->ncontours = 0; 2805 } 2806 2807 /* get advance width and left sidebearing */ 2808 if (glyphID < ttf->numberOfHMetrics) { 2809 d->aw = GetUInt16(hmtx, 4 * glyphID, 1); 2810 d->lsb = GetInt16(hmtx, 4 * glyphID + 2, 1); 2811 } else { 2812 d->aw = GetUInt16(hmtx, 4 * (ttf->numberOfHMetrics - 1), 1); 2813 d->lsb = GetInt16(hmtx + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1); 2814 } 2815 2816 return d; 2817 } 2818 2819 int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr) 2820 { 2821 const sal_uInt8* table = getTable(ttf, O_name); 2822 int nTableSize = getTableSize(ttf, O_name ); 2823 2824 if (nTableSize < 6) 2825 { 2826 #if OSL_DEBUG_LEVEL > 1 2827 fprintf(stderr, "O_name table too small\n"); 2828 #endif 2829 return 0; 2830 } 2831 2832 sal_uInt16 n = GetUInt16(table, 2, 1); 2833 int nStrBase = GetUInt16(table, 4, 1); 2834 int i; 2835 2836 *nr = 0; 2837 if (n == 0) return 0; 2838 2839 NameRecord* rec = (NameRecord*)calloc(n, sizeof(NameRecord)); 2840 2841 for (i = 0; i < n; i++) { 2842 int nStrOffset = GetUInt16(table + 6, 10 + 12 * i, 1); 2843 rec[i].platformID = GetUInt16(table + 6, 12 * i, 1); 2844 rec[i].encodingID = GetUInt16(table + 6, 2 + 12 * i, 1); 2845 rec[i].languageID = GetUInt16(table + 6, 4 + 12 * i, 1); 2846 rec[i].nameID = GetUInt16(table + 6, 6 + 12 * i, 1); 2847 rec[i].slen = GetUInt16(table + 6, 8 + 12 * i, 1); 2848 if (rec[i].slen) { 2849 if( nStrBase+nStrOffset+rec[i].slen >= nTableSize ) { 2850 rec[i].sptr = 0; 2851 rec[i].slen = 0; 2852 continue; 2853 } 2854 2855 const sal_uInt8* rec_string = table + nStrBase + nStrOffset; 2856 // sanity check 2857 if( rec_string > (sal_uInt8*)ttf->ptr && rec_string < ((sal_uInt8*)ttf->ptr + ttf->fsize - rec[i].slen ) ) 2858 { 2859 rec[i].sptr = (sal_uInt8 *) malloc(rec[i].slen); assert(rec[i].sptr != 0); 2860 memcpy(rec[i].sptr, rec_string, rec[i].slen); 2861 } 2862 else 2863 { 2864 #ifdef DEBUG 2865 fprintf( stderr, "found invalid name record %d with name id %d for file %s\n", 2866 i, rec[i].nameID, ttf->fname ); 2867 #endif 2868 rec[i].sptr = 0; 2869 rec[i].slen = 0; 2870 } 2871 } else { 2872 rec[i].sptr = 0; 2873 } 2874 // some fonts have 3.0 names => fix them to 3.1 2875 if( (rec[i].platformID == 3) && (rec[i].encodingID == 0) ) 2876 rec[i].encodingID = 1; 2877 } 2878 2879 *nr = rec; 2880 return n; 2881 } 2882 2883 void DisposeNameRecords(NameRecord* nr, int n) 2884 { 2885 int i; 2886 for (i = 0; i < n; i++) { 2887 if (nr[i].sptr) free(nr[i].sptr); 2888 } 2889 free(nr); 2890 } 2891 2892 } // namespace vcl 2893 2894 2895 #ifdef TEST1 2896 /* This example creates a subset of a TrueType font with two encoded characters */ 2897 int main(int ac, char **av) 2898 { 2899 TrueTypeFont *fnt; 2900 int r; 2901 2902 /* Array of Unicode source characters */ 2903 sal_uInt16 chars[2]; 2904 2905 /* Encoding vector maps character encoding to the ordinal number 2906 * of the glyph in the output file */ 2907 sal_uInt8 encoding[2]; 2908 2909 /* This array is for glyph IDs that source characters map to */ 2910 sal_uInt16 g[2]; 2911 2912 2913 if (ac < 2) return 0; 2914 2915 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 2916 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 2917 return 0; 2918 } 2919 2920 2921 /* We want to create the output file that only contains two Unicode characters: 2922 * L'a' and L'A' */ 2923 2924 chars[0] = L'a'; 2925 chars[1] = L'A'; 2926 2927 /* Figure out what glyphs do these characters map in our font */ 2928 MapString(fnt, chars, 2, g); 2929 2930 /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the 2931 * newly generated font */ 2932 encoding[0] = chars[0]; 2933 encoding[1] = chars[1]; 2934 2935 2936 /* Generate a subset */ 2937 CreateT3FromTTGlyphs(fnt, stdout, 0, g, encoding, 2, 0); 2938 2939 /* Now call the dtor for the font */ 2940 CloseTTFont(fnt); 2941 return 0; 2942 } 2943 #endif 2944 2945 #ifdef TEST2 2946 /* This example extracts first 224 glyphs from a TT fonts and encodes them starting at 32 */ 2947 int main(int ac, char **av) 2948 { 2949 TrueTypeFont *fnt; 2950 int i, r; 2951 2952 /* Array of Unicode source characters */ 2953 sal_uInt16 glyphs[224]; 2954 2955 /* Encoding vector maps character encoding to the ordinal number 2956 * of the glyph in the output file */ 2957 sal_uInt8 encoding[224]; 2958 2959 2960 2961 for (i=0; i<224; i++) { 2962 glyphs[i] = i; 2963 encoding[i] = 32 + i; 2964 } 2965 2966 if (ac < 2) return 0; 2967 2968 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 2969 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 2970 return 0; 2971 } 2972 2973 2974 /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the 2975 * newly generated font */ 2976 2977 /* Generate a subset */ 2978 CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 224, 0); 2979 2980 /* Now call the dtor for the font */ 2981 CloseTTFont(fnt); 2982 return 0; 2983 } 2984 #endif 2985 2986 #ifdef TEST3 2987 /* Glyph metrics example */ 2988 int main(int ac, char **av) 2989 { 2990 TrueTypeFont *fnt; 2991 int i, r; 2992 sal_uInt16 glyphs[224]; 2993 TTSimpleGlyphMetrics *m; 2994 2995 for (i=0; i<224; i++) { 2996 glyphs[i] = i; 2997 } 2998 2999 if (ac < 2) return 0; 3000 3001 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3002 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3003 return 0; 3004 } 3005 3006 if ((m = GetTTSimpleGlyphMetrics(fnt, glyphs, 224, 0)) == 0) { 3007 printf("Requested metrics is not available\n"); 3008 } else { 3009 for (i=0; i<224; i++) { 3010 printf("%d. advWid: %5d, LSBear: %5d\n", i, m[i].adv, m[i].sb); 3011 } 3012 } 3013 3014 /* Now call the dtor for the font */ 3015 free(m); 3016 CloseTTFont(fnt); 3017 return 0; 3018 } 3019 #endif 3020 3021 #ifdef TEST4 3022 int main(int ac, char **av) 3023 { 3024 TrueTypeFont *fnt; 3025 TTGlobalFontInfo info; 3026 int i, r; 3027 3028 3029 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3030 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3031 return 0; 3032 } 3033 3034 printf("Font file: %s\n", av[1]); 3035 3036 #ifdef PRINT_KERN 3037 switch (fnt->kerntype) { 3038 case KT_MICROSOFT: 3039 printf("\tkern: MICROSOFT, ntables: %d.", fnt->nkern); 3040 if (fnt->nkern) { 3041 printf(" ["); 3042 for (i=0; i<fnt->nkern; i++) { 3043 printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); 3044 } 3045 printf("]"); 3046 } 3047 printf("\n"); 3048 break; 3049 3050 case KT_APPLE_NEW: 3051 printf("\tkern: APPLE_NEW, ntables: %d.", fnt->nkern); 3052 if (fnt->nkern) { 3053 printf(" ["); 3054 for (i=0; i<fnt->nkern; i++) { 3055 printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); 3056 } 3057 printf("]"); 3058 } 3059 printf("\n"); 3060 break; 3061 3062 case KT_NONE: 3063 printf("\tkern: none.\n"); 3064 break; 3065 3066 default: 3067 printf("\tkern: unrecoginzed.\n"); 3068 break; 3069 } 3070 printf("\n"); 3071 #endif 3072 3073 GetTTGlobalFontInfo(fnt, &info); 3074 printf("\tfamily name: `%s`\n", info.family); 3075 printf("\tsubfamily name: `%s`\n", info.subfamily); 3076 printf("\tpostscript name: `%s`\n", info.psname); 3077 printf("\tweight: %d\n", info.weight); 3078 printf("\twidth: %d\n", info.width); 3079 printf("\tpitch: %d\n", info.pitch); 3080 printf("\titalic angle: %d\n", info.italicAngle); 3081 printf("\tbouding box: [%d %d %d %d]\n", info.xMin, info.yMin, info.xMax, info.yMax); 3082 printf("\tascender: %d\n", info.ascender); 3083 printf("\tdescender: %d\n", info.descender); 3084 printf("\tlinegap: %d\n", info.linegap); 3085 printf("\tvascent: %d\n", info.vascent); 3086 printf("\tvdescent: %d\n", info.vdescent); 3087 printf("\ttypoAscender: %d\n", info.typoAscender); 3088 printf("\ttypoDescender: %d\n", info.typoDescender); 3089 printf("\ttypoLineGap: %d\n", info.typoLineGap); 3090 printf("\twinAscent: %d\n", info.winAscent); 3091 printf("\twinDescent: %d\n", info.winDescent); 3092 printf("\tUnicode ranges:\n"); 3093 for (i = 0; i < 32; i++) { 3094 if ((info.ur1 >> i) & 1) { 3095 printf("\t\t\t%s\n", UnicodeRangeName(i)); 3096 } 3097 } 3098 for (i = 0; i < 32; i++) { 3099 if ((info.ur2 >> i) & 1) { 3100 printf("\t\t\t%s\n", UnicodeRangeName(i+32)); 3101 } 3102 } 3103 for (i = 0; i < 32; i++) { 3104 if ((info.ur3 >> i) & 1) { 3105 printf("\t\t\t%s\n", UnicodeRangeName(i+64)); 3106 } 3107 } 3108 for (i = 0; i < 32; i++) { 3109 if ((info.ur4 >> i) & 1) { 3110 printf("\t\t\t%s\n", UnicodeRangeName(i+96)); 3111 } 3112 } 3113 3114 CloseTTFont(fnt); 3115 return 0; 3116 } 3117 #endif 3118 3119 #ifdef TEST5 3120 /* Kerning example */ 3121 int main(int ac, char **av) 3122 { 3123 TrueTypeFont *fnt; 3124 sal_uInt16 g[224]; 3125 KernData d[223]; 3126 int r, i, k = 0; 3127 3128 g[k++] = 11; 3129 g[k++] = 36; 3130 g[k++] = 11; 3131 g[k++] = 98; 3132 g[k++] = 11; 3133 g[k++] = 144; 3134 g[k++] = 41; 3135 g[k++] = 171; 3136 g[k++] = 51; 3137 g[k++] = 15; 3138 3139 if (ac < 2) return 0; 3140 3141 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3142 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3143 return 0; 3144 } 3145 3146 KernGlyphs(fnt, g, k, 0, d); 3147 3148 for (i = 0; i < k-1; i++) { 3149 printf("%3d %3d: [%3d %3d]\n", g[i], g[i+1], d[i].x, d[i].y); 3150 } 3151 3152 CloseTTFont(fnt); 3153 return 0; 3154 } 3155 #endif 3156 3157 3158 3159 #ifdef TEST6 3160 /* This example extracts a single glyph from a font */ 3161 int main(int ac, char **av) 3162 { 3163 TrueTypeFont *fnt; 3164 int r, i; 3165 3166 sal_uInt16 glyphs[256]; 3167 sal_uInt8 encoding[256]; 3168 3169 for (i=0; i<256; i++) { 3170 glyphs[i] = 512 + i; 3171 encoding[i] = i; 3172 } 3173 3174 #if 0 3175 i=0; 3176 glyphs[i++] = 2001; 3177 glyphs[i++] = 2002; 3178 glyphs[i++] = 2003; 3179 glyphs[i++] = 2004; 3180 glyphs[i++] = 2005; 3181 glyphs[i++] = 2006; 3182 glyphs[i++] = 2007; 3183 glyphs[i++] = 2008; 3184 glyphs[i++] = 2009; 3185 glyphs[i++] = 2010; 3186 glyphs[i++] = 2011; 3187 glyphs[i++] = 2012; 3188 glyphs[i++] = 2013; 3189 glyphs[i++] = 2014; 3190 glyphs[i++] = 2015; 3191 glyphs[i++] = 2016; 3192 glyphs[i++] = 2017; 3193 glyphs[i++] = 2018; 3194 glyphs[i++] = 2019; 3195 glyphs[i++] = 2020; 3196 3197 3198 r = 97; 3199 i = 0; 3200 encoding[i++] = r++; 3201 encoding[i++] = r++; 3202 encoding[i++] = r++; 3203 encoding[i++] = r++; 3204 encoding[i++] = r++; 3205 encoding[i++] = r++; 3206 encoding[i++] = r++; 3207 encoding[i++] = r++; 3208 encoding[i++] = r++; 3209 encoding[i++] = r++; 3210 encoding[i++] = r++; 3211 encoding[i++] = r++; 3212 encoding[i++] = r++; 3213 encoding[i++] = r++; 3214 encoding[i++] = r++; 3215 encoding[i++] = r++; 3216 encoding[i++] = r++; 3217 encoding[i++] = r++; 3218 encoding[i++] = r++; 3219 encoding[i++] = r++; 3220 #endif 3221 3222 if (ac < 2) return 0; 3223 3224 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3225 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3226 return 0; 3227 } 3228 3229 /* Generate a subset */ 3230 CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 256, 0); 3231 3232 fprintf(stderr, "UnitsPerEm: %d.\n", fnt->unitsPerEm); 3233 3234 /* Now call the dtor for the font */ 3235 CloseTTFont(fnt); 3236 return 0; 3237 } 3238 #endif 3239 3240 #ifdef TEST7 3241 /* NameRecord extraction example */ 3242 int main(int ac, char **av) 3243 { 3244 TrueTypeFont *fnt; 3245 int r, i, j, n; 3246 NameRecord *nr; 3247 3248 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3249 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3250 return 0; 3251 } 3252 3253 if ((n = GetTTNameRecords(fnt, &nr)) == 0) { 3254 fprintf(stderr, "No name records in the font.\n"); 3255 return 0; 3256 } 3257 3258 printf("Number of name records: %d.\n", n); 3259 for (i = 0; i < n; i++) { 3260 printf("%d %d %04X %d [", nr[i].platformID, nr[i].encodingID, nr[i].languageID, nr[i].nameID); 3261 for (j=0; j<nr[i].slen; j++) { 3262 printf("%c", isprint(nr[i].sptr[j]) ? nr[i].sptr[j] : '.'); 3263 } 3264 printf("]\n"); 3265 } 3266 3267 3268 DisposeNameRecords(nr, n); 3269 CloseTTFont(fnt); 3270 return 0; 3271 } 3272 #endif 3273 3274 #ifdef TEST8 3275 /* TrueType -> TrueType subsetting */ 3276 int main(int ac, char **av) 3277 { 3278 TrueTypeFont *fnt; 3279 sal_uInt16 glyphArray[] = { 0, 98, 99, 22, 24, 25, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; 3280 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; 3281 int r; 3282 3283 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3284 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3285 return 0; 3286 } 3287 3288 CreateTTFromTTGlyphs(fnt, "subfont.ttf", glyphArray, encoding, 15, 0, 0, TTCF_AutoName | TTCF_IncludeOS2); 3289 3290 3291 CloseTTFont(fnt); 3292 3293 return 0; 3294 } 3295 #endif 3296 3297 #ifdef TEST9 3298 /* TrueType -> Type42 subsetting */ 3299 int main(int ac, char **av) 3300 { 3301 TrueTypeFont *fnt; 3302 /* 3303 sal_uInt16 glyphArray[] = { 0, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}; 3304 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; 3305 */ 3306 sal_uInt16 glyphArray[] = { 0, 6711, 6724, 11133, 11144, 14360, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; 3307 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; 3308 int r; 3309 3310 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3311 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3312 return 0; 3313 } 3314 3315 CreateT42FromTTGlyphs(fnt, stdout, "testfont", glyphArray, encoding, 15); 3316 3317 CloseTTFont(fnt); 3318 3319 return 0; 3320 } 3321 #endif 3322 3323 #ifdef TEST10 3324 /* Component glyph test */ 3325 int main(int ac, char **av) 3326 { 3327 TrueTypeFont *fnt; 3328 int r, i; 3329 list glyphlist = listNewEmpty(); 3330 3331 3332 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3333 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3334 return 0; 3335 } 3336 3337 for (i = 0; i < fnt->nglyphs; i++) { 3338 r = GetTTGlyphComponents(fnt, i, glyphlist); 3339 if (r > 1) { 3340 printf("%d -> ", i); 3341 listToFirst(glyphlist); 3342 do { 3343 printf("%d ", (int) listCurrent(glyphlist)); 3344 } while (listNext(glyphlist)); 3345 printf("\n"); 3346 } else { 3347 printf("%d: single glyph.\n", i); 3348 } 3349 listClear(glyphlist); 3350 } 3351 3352 CloseTTFont(fnt); 3353 listDispose(glyphlist); 3354 3355 return 0; 3356 } 3357 #endif 3358 3359 3360