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