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 803 804 np = myPoints.size(); 805 806 pa = (ControlPoint*)calloc(np, sizeof(ControlPoint)); 807 assert(pa != 0); 808 809 memcpy( pa, &myPoints[0], np*sizeof(ControlPoint) ); 810 811 *pointArray = pa; 812 return np; 813 } 814 815 /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect, 816 * but Get{Simple|Compound}GlyphOutline returns 0 in such a case. 817 * 818 * NOTE: glyphlist is the stack of glyphs traversed while constructing 819 * a composite glyph. This is a safequard against endless recursion 820 * in corrupted fonts. 821 */ 822 static int GetTTGlyphOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >* glyphlist) 823 { 824 const sal_uInt8 *table = getTable( ttf, O_glyf ); 825 sal_Int16 numberOfContours; 826 int res; 827 *pointArray = 0; 828 829 if (metrics) { 830 memset(metrics, 0, sizeof(TTGlyphMetrics)); /*- metrics is initialized to all zeroes */ 831 } 832 833 if (glyphID >= ttf->nglyphs) return -1; /**/ 834 835 const sal_uInt8* ptr = table + ttf->goffsets[glyphID]; 836 int length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; 837 838 if (length == 0) { /*- empty glyphs still have hmtx and vmtx metrics values */ 839 if (metrics) GetMetrics(ttf, glyphID, metrics); 840 return 0; 841 } 842 843 numberOfContours = GetInt16(ptr, 0, 1); 844 845 if (numberOfContours >= 0) 846 { 847 res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics); 848 } 849 else 850 { 851 std::vector< sal_uInt32 > aPrivList; 852 aPrivList.push_back( glyphID ); 853 res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist ? *glyphlist : aPrivList ); 854 } 855 856 #ifdef DEBUG3 857 { 858 int i; 859 FILE *out = fopen("points.dat", "a"); 860 assert(out != 0); 861 fprintf(out, "Glyph: %d\nPoints: %d\n", glyphID, res); 862 for (i=0; i<res; i++) { 863 fprintf(out, "%c ", ((*pointArray)[i].flags & 0x8000) ? 'X' : '.'); 864 fprintf(out, "%c ", ((*pointArray)[i].flags & 1) ? '+' : '-'); 865 fprintf(out, "%d %d\n", (*pointArray)[i].x, (*pointArray)[i].y); 866 } 867 fclose(out); 868 } 869 #endif 870 871 return res; 872 } 873 874 #ifndef NO_TYPE3 875 876 /*- returns the number of items in the path -*/ 877 878 static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path) 879 { 880 std::vector< PSPathElement > aPathList; 881 int nPathCount = 0; 882 PSPathElement p( PS_NOOP ); 883 884 int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury; 885 int lastOff = 0; /*- last point was off-contour */ 886 int scflag = 1; /*- start contour flag */ 887 int ecflag = 0; /*- end contour flag */ 888 int cp = 0; /*- current point */ 889 int StartContour = 0, EndContour = 1; 890 891 *path = 0; 892 893 /* if (srcCount > 0) for(;;) */ 894 while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */ 895 if (scflag) { 896 int l = cp; 897 StartContour = cp; 898 while (!(srcA[l].flags & 0x8000)) l++; 899 EndContour = l; 900 if (StartContour == EndContour) { 901 if (cp + 1 < srcCount) { 902 cp++; 903 continue; 904 } else { 905 break; 906 } 907 } 908 p = PSPathElement(PS_MOVETO); 909 if (!(srcA[cp].flags & 1)) { 910 if (!(srcA[EndContour].flags & 1)) { 911 p.x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2; 912 p.y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2; 913 } else { 914 p.x1 = x0 = srcA[EndContour].x; 915 p.y1 = y0 = srcA[EndContour].y; 916 } 917 } else { 918 p.x1 = x0 = srcA[cp].x; 919 p.y1 = y0 = srcA[cp].y; 920 cp++; 921 } 922 aPathList.push_back( p ); 923 lastOff = 0; 924 scflag = 0; 925 } 926 927 curx = srcA[cp].x; 928 cury = srcA[cp].y; 929 930 if (srcA[cp].flags & 1) 931 { 932 if (lastOff) 933 { 934 p = PSPathElement(PS_CURVETO); 935 p.x1 = x0 + (2 * (x1 - x0) + 1) / 3; 936 p.y1 = y0 + (2 * (y1 - y0) + 1) / 3; 937 p.x2 = x1 + (curx - x1 + 1) / 3; 938 p.y2 = y1 + (cury - y1 + 1) / 3; 939 p.x3 = curx; 940 p.y3 = cury; 941 aPathList.push_back( p ); 942 } 943 else 944 { 945 if (!(x0 == curx && y0 == cury)) 946 { /* eliminate empty lines */ 947 p = PSPathElement(PS_LINETO); 948 p.x1 = curx; 949 p.y1 = cury; 950 aPathList.push_back( p ); 951 } 952 } 953 x0 = curx; y0 = cury; lastOff = 0; 954 } 955 else 956 { 957 if (lastOff) 958 { 959 x2 = (x1 + curx + 1) / 2; 960 y2 = (y1 + cury + 1) / 2; 961 p = PSPathElement(PS_CURVETO); 962 p.x1 = x0 + (2 * (x1 - x0) + 1) / 3; 963 p.y1 = y0 + (2 * (y1 - y0) + 1) / 3; 964 p.x2 = x1 + (x2 - x1 + 1) / 3; 965 p.y2 = y1 + (y2 - y1 + 1) / 3; 966 p.x3 = x2; 967 p.y3 = y2; 968 aPathList.push_back( p ); 969 x0 = x2; y0 = y2; 970 x1 = curx; y1 = cury; 971 } else { 972 x1 = curx; y1 = cury; 973 } 974 lastOff = true; 975 } 976 977 if (ecflag) { 978 aPathList.push_back( PSPathElement(PS_CLOSEPATH) ); 979 scflag = 1; 980 ecflag = 0; 981 cp = EndContour + 1; 982 if (cp >= srcCount) break; 983 continue; 984 } 985 986 987 if (cp == EndContour) { 988 cp = StartContour; 989 ecflag = true; 990 } else { 991 cp++; 992 } 993 } 994 995 if( (nPathCount = (int)aPathList.size()) > 0) 996 { 997 *path = (PSPathElement*)calloc(nPathCount, sizeof(PSPathElement)); 998 assert(*path != 0); 999 memcpy( *path, &aPathList[0], nPathCount * sizeof(PSPathElement) ); 1000 } 1001 1002 return nPathCount; 1003 } 1004 1005 #endif 1006 1007 /*- Extracts a string from the name table and allocates memory for it -*/ 1008 1009 static char *nameExtract( const sal_uInt8* name, int nTableSize, int n, int dbFlag, sal_uInt16** ucs2result ) 1010 { 1011 int i; 1012 char *res; 1013 const sal_uInt8* ptr = name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1); 1014 int len = GetUInt16(name+6, 12 * n + 8, 1); 1015 1016 // sanity check 1017 if( (len <= 0) || ((ptr+len) > (name+nTableSize)) ) 1018 { 1019 if( ucs2result ) 1020 *ucs2result = NULL; 1021 return NULL; 1022 } 1023 1024 if( ucs2result ) 1025 *ucs2result = NULL; 1026 if (dbFlag) { 1027 res = (char*)malloc(1 + len/2); 1028 assert(res != 0); 1029 for (i = 0; i < len/2; i++) res[i] = *(ptr + i * 2 + 1); 1030 res[len/2] = 0; 1031 if( ucs2result ) 1032 { 1033 *ucs2result = (sal_uInt16*)malloc( len+2 ); 1034 for (i = 0; i < len/2; i++ ) (*ucs2result)[i] = GetUInt16( ptr, 2*i, 1 ); 1035 (*ucs2result)[len/2] = 0; 1036 } 1037 } else { 1038 res = (char*)malloc(1 + len); 1039 assert(res != 0); 1040 memcpy(res, ptr, len); 1041 res[len] = 0; 1042 } 1043 1044 return res; 1045 } 1046 1047 static int findname( const sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID, 1048 sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID ) 1049 { 1050 int l = 0, r = n-1, i; 1051 sal_uInt32 t1, t2; 1052 sal_uInt32 m1, m2; 1053 1054 if (n == 0) return -1; 1055 1056 m1 = (platformID << 16) | encodingID; 1057 m2 = (languageID << 16) | nameID; 1058 1059 do { 1060 i = (l + r) >> 1; 1061 t1 = GetUInt32(name + 6, i * 12 + 0, 1); 1062 t2 = GetUInt32(name + 6, i * 12 + 4, 1); 1063 1064 if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1; 1065 if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1; 1066 } while (l <= r); 1067 1068 if (l - r == 2) { 1069 return l - 1; 1070 } 1071 1072 return -1; 1073 } 1074 1075 /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables. 1076 * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033) 1077 * 1078 * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0) 1079 * and does not have (3, 1, 1033) 1080 * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will 1081 * require a change in algorithm 1082 * 1083 * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID, 1084 * but (1, 0, 1042) strings usable 1085 * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found 1086 */ 1087 1088 static void GetNames(TrueTypeFont *t) 1089 { 1090 const sal_uInt8* table = getTable( t, O_name ); 1091 int nTableSize = getTableSize(t, O_name); 1092 1093 if (nTableSize < 4) 1094 { 1095 #if OSL_DEBUG_LEVEL > 1 1096 fprintf(stderr, "O_name table too small\n"); 1097 #endif 1098 return; 1099 } 1100 1101 sal_uInt16 n = GetUInt16(table, 2, 1); 1102 int i, r; 1103 sal_Bool bPSNameOK = sal_True; 1104 1105 /* #129743# simple sanity check for name table entry count */ 1106 if( nTableSize <= n * 12 + 6 ) 1107 n = 0; 1108 1109 /* PostScript name: preferred Microsoft */ 1110 t->psname = NULL; 1111 if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1) 1112 t->psname = nameExtract(table, nTableSize, r, 1, NULL); 1113 if ( ! t->psname && (r = findname(table, n, 1, 0, 0, 6)) != -1) 1114 t->psname = nameExtract(table, nTableSize, r, 0, NULL); 1115 if ( ! t->psname && (r = findname(table, n, 3, 0, 0x0409, 6)) != -1) 1116 { 1117 // some symbol fonts like Marlett have a 3,0 name! 1118 t->psname = nameExtract(table, nTableSize, r, 1, NULL); 1119 } 1120 // for embedded font in Ghostscript PDFs 1121 if ( ! t->psname && (r = findname(table, n, 2, 2, 0, 6)) != -1) 1122 { 1123 t->psname = nameExtract(table, nTableSize, r, 0, NULL); 1124 } 1125 if ( ! t->psname ) 1126 { 1127 if ( t->fname ) 1128 { 1129 char* pReverse = t->fname + strlen(t->fname); 1130 /* take only last token of filename */ 1131 while(pReverse != t->fname && *pReverse != '/') pReverse--; 1132 if(*pReverse == '/') pReverse++; 1133 t->psname = strdup(pReverse); 1134 assert(t->psname != 0); 1135 for (i=strlen(t->psname) - 1; i > 0; i--) 1136 { 1137 /*- Remove the suffix -*/ 1138 if (t->psname[i] == '.' ) { 1139 t->psname[i] = 0; 1140 break; 1141 } 1142 } 1143 } 1144 else 1145 t->psname = strdup( "Unknown" ); 1146 } 1147 1148 /* Font family and subfamily names: preferred Apple */ 1149 t->family = NULL; 1150 if ((r = findname(table, n, 0, 0, 0, 1)) != -1) 1151 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1152 if ( ! t->family && (r = findname(table, n, 3, 1, 0x0409, 1)) != -1) 1153 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1154 if ( ! t->family && (r = findname(table, n, 1, 0, 0, 1)) != -1) 1155 t->family = nameExtract(table, nTableSize, r, 0, NULL); 1156 if ( ! t->family && (r = findname(table, n, 3, 1, 0x0411, 1)) != -1) 1157 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1158 if ( ! t->family && (r = findname(table, n, 3, 0, 0x0409, 1)) != -1) 1159 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1160 if ( ! t->family ) 1161 { 1162 t->family = strdup(t->psname); 1163 assert(t->family != 0); 1164 } 1165 1166 t->subfamily = NULL; 1167 t->usubfamily = NULL; 1168 if ((r = findname(table, n, 1, 0, 0, 2)) != -1) 1169 t->subfamily = nameExtract(table, nTableSize, r, 0, &t->usubfamily); 1170 if ( ! t->subfamily && (r = findname(table, n, 3, 1, 0x0409, 2)) != -1) 1171 t->subfamily = nameExtract(table, nTableSize, r, 1, &t->usubfamily); 1172 if ( ! t->subfamily ) 1173 { 1174 t->subfamily = strdup(""); 1175 } 1176 1177 /* #i60349# sanity check psname 1178 * psname parctically has to be 7bit ascii and should not contains spaces 1179 * there is a class of broken fonts which do not fullfill that at all, so let's try 1180 * if the family name is 7bit ascii and take it instead if so 1181 */ 1182 /* check psname */ 1183 for( i = 0; t->psname[i] != 0 && bPSNameOK; i++ ) 1184 if( t->psname[ i ] < 33 || (t->psname[ i ] & 0x80) ) 1185 bPSNameOK = sal_False; 1186 if( bPSNameOK == sal_False ) 1187 { 1188 sal_Bool bReplace = sal_True; 1189 /* check if family is a suitable replacement */ 1190 if( t->ufamily && t->family ) 1191 { 1192 for( i = 0; t->ufamily[ i ] != 0 && bReplace; i++ ) 1193 if( t->ufamily[ i ] < 33 || t->ufamily[ i ] > 127 ) 1194 bReplace = sal_False; 1195 if( bReplace ) 1196 { 1197 free( t->psname ); 1198 t->psname = strdup( t->family ); 1199 } 1200 } 1201 } 1202 } 1203 1204 enum cmapType { 1205 CMAP_NOT_USABLE = -1, 1206 CMAP_MS_Symbol = 10, 1207 CMAP_MS_Unicode = 11, 1208 CMAP_MS_ShiftJIS = 12, 1209 CMAP_MS_Big5 = 13, 1210 CMAP_MS_PRC = 14, 1211 CMAP_MS_Wansung = 15, 1212 CMAP_MS_Johab = 16 1213 }; 1214 1215 #define MISSING_GLYPH_INDEX 0 1216 1217 /* 1218 * getGlyph[0246]() functions and freinds are implemented by: 1219 * @author Manpreet Singh 1220 * getGlyph12() function and friends by: 1221 * @author HDU 1222 */ 1223 static sal_uInt32 getGlyph0(const sal_uInt8* cmap, sal_uInt32 c) { 1224 if (c <= 255) { 1225 return *(cmap + 6 + c); 1226 } else { 1227 return MISSING_GLYPH_INDEX; 1228 } 1229 } 1230 1231 typedef struct _subHeader2 { 1232 sal_uInt16 firstCode; 1233 sal_uInt16 entryCount; 1234 sal_uInt16 idDelta; 1235 sal_uInt16 idRangeOffset; 1236 } subHeader2; 1237 1238 static sal_uInt32 getGlyph2(const sal_uInt8 *cmap, sal_uInt32 c) { 1239 sal_uInt16 *CMAP2 = (sal_uInt16 *) cmap; 1240 sal_uInt8 theHighByte; 1241 1242 sal_uInt8 theLowByte; 1243 subHeader2* subHeader2s; 1244 sal_uInt16* subHeader2Keys; 1245 sal_uInt16 firstCode; 1246 int k; 1247 sal_uInt32 ToReturn; 1248 1249 theHighByte = (sal_uInt8)((c >> 8) & 0x00ff); 1250 theLowByte = (sal_uInt8)(c & 0x00ff); 1251 subHeader2Keys = CMAP2 + 3; 1252 subHeader2s = (subHeader2 *)(subHeader2Keys + 256); 1253 k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8; 1254 1255 if(k == 0) { 1256 firstCode = Int16FromMOTA(subHeader2s[k].firstCode); 1257 if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { 1258 return *((&(subHeader2s[0].idRangeOffset)) 1259 + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) /* + offset */ 1260 + theLowByte /* + to_look */ 1261 - Int16FromMOTA(subHeader2s[0].firstCode) 1262 ); 1263 } else { 1264 return MISSING_GLYPH_INDEX; 1265 } 1266 } else if (k > 0) { 1267 firstCode = Int16FromMOTA(subHeader2s[k].firstCode); 1268 if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { 1269 ToReturn = *((&(subHeader2s[k].idRangeOffset)) 1270 + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2) 1271 + theLowByte - firstCode); 1272 if(ToReturn == 0) { 1273 return MISSING_GLYPH_INDEX; 1274 } else { 1275 ToReturn += Int16FromMOTA(subHeader2s[k].idDelta); 1276 return (ToReturn & 0xFFFF); 1277 } 1278 } else { 1279 return MISSING_GLYPH_INDEX; 1280 } 1281 } else { 1282 return MISSING_GLYPH_INDEX; 1283 } 1284 } 1285 1286 static sal_uInt32 getGlyph6(const sal_uInt8 *cmap, sal_uInt32 c) { 1287 sal_uInt16 firstCode, lastCode, count; 1288 sal_uInt16 *CMAP6 = (sal_uInt16 *) cmap; 1289 1290 firstCode = Int16FromMOTA(*(CMAP6 + 3)); 1291 count = Int16FromMOTA(*(CMAP6 + 4)); 1292 lastCode = firstCode + count - 1; 1293 if (c < firstCode || c > lastCode) { 1294 return MISSING_GLYPH_INDEX; 1295 } else { 1296 return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode)); 1297 } 1298 } 1299 1300 static sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch) { 1301 signed int low, mid, high, lastfound = 0xffff; 1302 sal_uInt16 res; 1303 if(length == (sal_uInt16)0 || length == (sal_uInt16)0xFFFF) { 1304 return (sal_uInt16)0xFFFF; 1305 } 1306 low = 0; 1307 high = length - 1; 1308 while(high >= low) { 1309 mid = (high + low)/2; 1310 res = Int16FromMOTA(*(ar+mid)); 1311 if(res >= toSearch) { 1312 lastfound = mid; 1313 high = --mid; 1314 } else { 1315 low = ++mid; 1316 } 1317 } 1318 return (sal_uInt16)lastfound; 1319 } 1320 1321 1322 static sal_uInt32 getGlyph4(const sal_uInt8 *cmap, sal_uInt32 c) { 1323 sal_uInt16 i; 1324 int ToReturn; 1325 sal_uInt16 segCount; 1326 sal_uInt16 * startCode; 1327 sal_uInt16 * endCode; 1328 sal_uInt16 * idDelta; 1329 /* sal_uInt16 * glyphIdArray; */ 1330 sal_uInt16 * idRangeOffset; 1331 sal_uInt16 * glyphIndexArray; 1332 sal_uInt16 *CMAP4 = (sal_uInt16 *) cmap; 1333 /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */ 1334 1335 segCount = Int16FromMOTA(*(CMAP4 + 3))/2; 1336 endCode = CMAP4 + 7; 1337 i = GEbinsearch(endCode, segCount, (sal_uInt16)c); 1338 1339 if (i == (sal_uInt16) 0xFFFF) { 1340 return MISSING_GLYPH_INDEX; 1341 } 1342 startCode = endCode + segCount + 1; 1343 1344 if(Int16FromMOTA(startCode[i]) > c) { 1345 return MISSING_GLYPH_INDEX; 1346 } 1347 idDelta = startCode + segCount; 1348 idRangeOffset = idDelta + segCount; 1349 glyphIndexArray = idRangeOffset + segCount; 1350 1351 if(Int16FromMOTA(idRangeOffset[i]) != 0) { 1352 c = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i]))))); 1353 } 1354 1355 ToReturn = (Int16FromMOTA(idDelta[i]) + c) & 0xFFFF; 1356 return ToReturn; 1357 } 1358 1359 static sal_uInt32 getGlyph12(const sal_uInt8 *pCmap, sal_uInt32 cChar) { 1360 const sal_uInt32* pCMAP12 = (const sal_uInt32*)pCmap; 1361 int nLength = Int32FromMOTA( pCMAP12[1] ); 1362 int nGroups = Int32FromMOTA( pCMAP12[3] ); 1363 int nLower = 0; 1364 int nUpper = nGroups; 1365 1366 if( nUpper > (nLength-16)/12 ) 1367 nUpper = (nLength-16)/12; 1368 1369 /* binary search in "segmented coverage" subtable */ 1370 while( nLower < nUpper ) { 1371 int nIndex = (nLower + nUpper) / 2; 1372 const sal_uInt32* pEntry = &pCMAP12[ 4 + 3*nIndex ]; 1373 sal_uInt32 cStart = Int32FromMOTA( pEntry[0] ); 1374 sal_uInt32 cLast = Int32FromMOTA( pEntry[1] ); 1375 if( cChar < cStart ) 1376 nUpper = nIndex; 1377 else if( cChar > cLast ) 1378 nLower = nIndex + 1; 1379 else { /* found matching entry! */ 1380 sal_uInt32 nGlyph = Int32FromMOTA( pEntry[2] ); 1381 nGlyph += cChar - cStart; 1382 return nGlyph; 1383 } 1384 } 1385 1386 return MISSING_GLYPH_INDEX; 1387 } 1388 1389 1390 static void FindCmap(TrueTypeFont *ttf) 1391 { 1392 const sal_uInt8* table = getTable(ttf, O_cmap); 1393 sal_uInt32 table_size = getTableSize(ttf, O_cmap); 1394 sal_uInt16 ncmaps = GetUInt16(table, 2, 1); 1395 unsigned int i; 1396 sal_uInt32 AppleUni = 0; // Apple Unicode 1397 sal_uInt32 ThreeZero = 0; /* MS Symbol */ 1398 sal_uInt32 ThreeOne = 0; /* MS UCS-2 */ 1399 sal_uInt32 ThreeTwo = 0; /* MS ShiftJIS */ 1400 sal_uInt32 ThreeThree = 0; /* MS Big5 */ 1401 sal_uInt32 ThreeFour = 0; /* MS PRC */ 1402 sal_uInt32 ThreeFive = 0; /* MS Wansung */ 1403 sal_uInt32 ThreeSix = 0; /* MS Johab */ 1404 1405 for (i = 0; i < ncmaps; i++) { 1406 sal_uInt32 offset; 1407 sal_uInt16 pID, eID; 1408 1409 /* sanity check, cmap entry must lie within table */ 1410 if( i*8+4 > table_size ) 1411 break; 1412 1413 pID = GetUInt16(table, 4 + i * 8, 1); 1414 eID = GetUInt16(table, 6 + i * 8, 1); 1415 offset = GetUInt32(table, 8 + i * 8, 1); 1416 1417 /* sanity check, cmap must lie within file */ 1418 if( (table - ttf->ptr) + offset > (sal_uInt32)ttf->fsize ) 1419 continue; 1420 1421 /* Unicode tables in Apple fonts */ 1422 if (pID == 0) { 1423 AppleUni = offset; 1424 } 1425 1426 if (pID == 3) { 1427 switch (eID) { 1428 case 0: ThreeZero = offset; break; 1429 case 10: // UCS-4 1430 case 1: ThreeOne = offset; break; 1431 case 2: ThreeTwo = offset; break; 1432 case 3: ThreeThree = offset; break; 1433 case 4: ThreeFour = offset; break; 1434 case 5: ThreeFive = offset; break; 1435 case 6: ThreeSix = offset; break; 1436 } 1437 } 1438 } 1439 1440 // fall back to AppleUnicode if there are no ThreeOne/Threezero tables 1441 if( AppleUni && !ThreeZero && !ThreeOne) 1442 ThreeOne = AppleUni; 1443 1444 if (ThreeOne) { 1445 ttf->cmapType = CMAP_MS_Unicode; 1446 ttf->cmap = table + ThreeOne; 1447 } else if (ThreeTwo) { 1448 ttf->cmapType = CMAP_MS_ShiftJIS; 1449 ttf->cmap = table + ThreeTwo; 1450 } else if (ThreeThree) { 1451 ttf->cmapType = CMAP_MS_Big5; 1452 ttf->cmap = table + ThreeThree; 1453 } else if (ThreeFour) { 1454 ttf->cmapType = CMAP_MS_PRC; 1455 ttf->cmap = table + ThreeFour; 1456 } else if (ThreeFive) { 1457 ttf->cmapType = CMAP_MS_Wansung; 1458 ttf->cmap = table + ThreeFive; 1459 } else if (ThreeSix) { 1460 ttf->cmapType = CMAP_MS_Johab; 1461 ttf->cmap = table + ThreeSix; 1462 } else if (ThreeZero) { 1463 ttf->cmapType = CMAP_MS_Symbol; 1464 ttf->cmap = table + ThreeZero; 1465 } else { 1466 ttf->cmapType = CMAP_NOT_USABLE; 1467 ttf->cmap = 0; 1468 } 1469 1470 if (ttf->cmapType != CMAP_NOT_USABLE) { 1471 switch (GetUInt16(ttf->cmap, 0, 1)) { 1472 case 0: ttf->mapper = getGlyph0; break; 1473 case 2: ttf->mapper = getGlyph2; break; 1474 case 4: ttf->mapper = getGlyph4; break; 1475 case 6: ttf->mapper = getGlyph6; break; 1476 case 12: ttf->mapper= getGlyph12; break; 1477 default: 1478 #if OSL_DEBUG_LEVEL > 1 1479 /*- if the cmap table is really broken */ 1480 printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1)); 1481 #endif 1482 ttf->cmapType = CMAP_NOT_USABLE; 1483 ttf->cmap = 0; 1484 ttf->mapper = 0; 1485 } 1486 } 1487 } 1488 1489 static void GetKern(TrueTypeFont *ttf) 1490 { 1491 const sal_uInt8* table = getTable(ttf, O_kern); 1492 const sal_uInt8 *ptr; 1493 1494 if( !table ) 1495 goto badtable; 1496 1497 if (GetUInt16(table, 0, 1) == 0) { /* Traditional Microsoft style table with sal_uInt16 version and nTables fields */ 1498 ttf->nkern = GetUInt16(table, 2, 1); 1499 ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8 *)); 1500 assert(ttf->kerntables != 0); 1501 memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); 1502 ttf->kerntype = KT_MICROSOFT; 1503 ptr = table + 4; 1504 for( unsigned i = 0; i < ttf->nkern; ++i) { 1505 ttf->kerntables[i] = ptr; 1506 ptr += GetUInt16(ptr, 2, 1); 1507 /* sanity check */ 1508 if( ptr > ttf->ptr+ttf->fsize ) 1509 { 1510 free( ttf->kerntables ); 1511 goto badtable; 1512 } 1513 } 1514 return; 1515 } 1516 1517 if (GetUInt32(table, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */ 1518 ttf->nkern = GetUInt32(table, 4, 1); 1519 ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8*)); 1520 assert(ttf->kerntables != 0); 1521 memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); 1522 ttf->kerntype = KT_APPLE_NEW; 1523 ptr = table + 8; 1524 for( unsigned i = 0; i < ttf->nkern; ++i) { 1525 ttf->kerntables[i] = ptr; 1526 ptr += GetUInt32(ptr, 0, 1); 1527 /* sanity check; there are some fonts that are broken in this regard */ 1528 if( ptr > ttf->ptr+ttf->fsize ) 1529 { 1530 free( ttf->kerntables ); 1531 goto badtable; 1532 } 1533 } 1534 return; 1535 } 1536 1537 badtable: 1538 ttf->kerntype = KT_NONE; 1539 ttf->kerntables = 0; 1540 1541 return; 1542 } 1543 1544 #ifdef TEST5 1545 /* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and 1546 * that x and y elements of the kern array are initialized to zeroes 1547 */ 1548 static void KernGlyphsPrim1(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) 1549 { 1550 (void)ttf; /* avoid warning */ 1551 (void)glyphs; /* avoid warning */ 1552 (void)nglyphs; /* avoid warning */ 1553 (void)wmode; /* avoid warning */ 1554 (void)nglyphs; /* avoid warning */ 1555 (void)kern; /* avoid warning */ 1556 fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n"); 1557 } 1558 1559 static void KernGlyphsPrim2(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) 1560 { 1561 sal_uInt32 i, j; 1562 sal_uInt32 gpair; 1563 1564 if( ! nglyphs ) 1565 return; 1566 1567 for (i = 0; i < (sal_uInt32)nglyphs - 1; i++) { 1568 gpair = (glyphs[i] << 16) | glyphs[i+1]; 1569 #ifdef DEBUG2 1570 /* All fonts with MS kern table that I've seen so far contain just one kern subtable. 1571 * MS kern documentation is very poor and I doubt that font developers will be using 1572 * several subtables. I expect them to be using OpenType tables instead. 1573 * According to MS documention, format 2 subtables are not supported by Windows and OS/2. 1574 */ 1575 if (ttf->nkern > 1) { 1576 fprintf(stderr, "KernGlyphsPrim2: %d kern tables found.\n", ttf->nkern); 1577 } 1578 #endif 1579 for (j = 0; j < ttf->nkern; j++) { 1580 sal_uInt16 coverage = GetUInt16(ttf->kerntables[j], 4, 1); 1581 sal_uInt8 *ptr; 1582 int npairs; 1583 sal_uInt32 t; 1584 int l, r, k; 1585 1586 if (! ((coverage & 1) ^ wmode)) continue; 1587 if ((coverage & 0xFFFE) != 0) { 1588 #ifdef DEBUG2 1589 fprintf(stderr, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage); 1590 #endif 1591 continue; 1592 } 1593 ptr = ttf->kerntables[j]; 1594 npairs = GetUInt16(ptr, 6, 1); 1595 ptr += 14; 1596 l = 0; 1597 r = npairs; 1598 do { 1599 k = (l + r) >> 1; 1600 t = GetUInt32(ptr, k * 6, 1); 1601 if (gpair >= t) l = k + 1; 1602 if (gpair <= t) r = k - 1; 1603 } while (l <= r); 1604 if (l - r == 2) { 1605 if (!wmode) { 1606 kern[i].x = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); 1607 } else { 1608 kern[i].y = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); 1609 } 1610 /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */ 1611 } 1612 } 1613 } 1614 } 1615 #endif 1616 1617 /*- Public functions */ /*FOLD00*/ 1618 1619 int CountTTCFonts(const char* fname) 1620 { 1621 int nFonts = 0; 1622 sal_uInt8 buffer[12]; 1623 FILE* fd = fopen(fname, "rb"); 1624 if( fd ) { 1625 if (fread(buffer, 1, 12, fd) == 12) { 1626 if(GetUInt32(buffer, 0, 1) == T_ttcf ) 1627 nFonts = GetUInt32(buffer, 8, 1); 1628 } 1629 fclose(fd); 1630 } 1631 return nFonts; 1632 } 1633 1634 static void allocTrueTypeFont( TrueTypeFont** ttf ) 1635 { 1636 *ttf = (TrueTypeFont*)calloc(1,sizeof(TrueTypeFont)); 1637 if( *ttf != NULL ) 1638 { 1639 (*ttf)->tag = 0; 1640 (*ttf)->fname = 0; 1641 (*ttf)->fsize = -1; 1642 (*ttf)->ptr = 0; 1643 (*ttf)->nglyphs = 0xFFFFFFFF; 1644 (*ttf)->pGSubstitution = 0; 1645 } 1646 } 1647 1648 /* forward declariotn for the two entry points to use*/ 1649 static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ); 1650 1651 #if !defined(WIN32) && !defined(OS2) 1652 int OpenTTFontFile( const char* fname, sal_uInt32 facenum, TrueTypeFont** ttf ) 1653 { 1654 int ret, fd = -1; 1655 struct stat st; 1656 1657 if (!fname || !*fname) return SF_BADFILE; 1658 1659 allocTrueTypeFont( ttf ); 1660 if( ! *ttf ) 1661 return SF_MEMORY; 1662 1663 (*ttf)->fname = strdup(fname); 1664 if( ! (*ttf)->fname ) 1665 { 1666 ret = SF_MEMORY; 1667 goto cleanup; 1668 } 1669 1670 fd = open(fname, O_RDONLY); 1671 1672 if (fd == -1) { 1673 ret = SF_BADFILE; 1674 goto cleanup; 1675 } 1676 1677 if (fstat(fd, &st) == -1) { 1678 ret = SF_FILEIO; 1679 goto cleanup; 1680 } 1681 1682 (*ttf)->fsize = st.st_size; 1683 1684 /* On Mac OS, most likely will happen if a Mac user renames a font file 1685 * to be .ttf when its really a Mac resource-based font. 1686 * Size will be 0, but fonts smaller than 4 bytes would be broken anyway. 1687 */ 1688 if ((*ttf)->fsize == 0) { 1689 ret = SF_BADFILE; 1690 goto cleanup; 1691 } 1692 1693 if (((*ttf)->ptr = (sal_uInt8 *) mmap(0, (*ttf)->fsize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 1694 ret = SF_MEMORY; 1695 goto cleanup; 1696 } 1697 close(fd); 1698 1699 return doOpenTTFont( facenum, *ttf ); 1700 1701 cleanup: 1702 if (fd != -1) close(fd); 1703 /*- t and t->fname have been allocated! */ 1704 free((*ttf)->fname); 1705 free(*ttf); 1706 *ttf = NULL; 1707 return ret; 1708 } 1709 #endif 1710 1711 int OpenTTFontBuffer(void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf) 1712 { 1713 allocTrueTypeFont( ttf ); 1714 if( *ttf == NULL ) 1715 return SF_MEMORY; 1716 1717 (*ttf)->fname = NULL; 1718 (*ttf)->fsize = nLen; 1719 (*ttf)->ptr = (sal_uInt8*)pBuffer; 1720 1721 return doOpenTTFont( facenum, *ttf ); 1722 } 1723 1724 static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) 1725 { 1726 int i; 1727 sal_uInt32 length, tag; 1728 sal_uInt32 tdoffset = 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */ 1729 int indexfmt, k; 1730 1731 sal_uInt32 version = GetInt32(t->ptr, 0, 1); 1732 1733 if ((version == 0x00010000) || (version == T_true)) { 1734 tdoffset = 0; 1735 } else if (version == T_otto) { /* PS-OpenType font */ 1736 tdoffset = 0; 1737 } else if (version == T_ttcf) { /* TrueType collection */ 1738 if (GetUInt32(t->ptr, 4, 1) != 0x00010000) { 1739 CloseTTFont(t); 1740 return SF_TTFORMAT; 1741 } 1742 if (facenum >= GetUInt32(t->ptr, 8, 1)) { 1743 CloseTTFont(t); 1744 return SF_FONTNO; 1745 } 1746 tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1); 1747 } else { 1748 CloseTTFont(t); 1749 return SF_TTFORMAT; 1750 } 1751 1752 #ifdef DEBUG2 1753 fprintf(stderr, "tdoffset: %d\n", tdoffset); 1754 #endif 1755 1756 /* magic number */ 1757 t->tag = TTFontClassTag; 1758 1759 t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1); 1760 if( t->ntables >= 128 ) 1761 return SF_TTFORMAT; 1762 1763 t->tables = (const sal_uInt8**)calloc(NUM_TAGS, sizeof(sal_uInt8*)); 1764 assert(t->tables != 0); 1765 t->tlens = (sal_uInt32*)calloc(NUM_TAGS, sizeof(sal_uInt32)); 1766 assert(t->tlens != 0); 1767 1768 memset(t->tables, 0, NUM_TAGS * sizeof(void *)); 1769 memset(t->tlens, 0, NUM_TAGS * sizeof(sal_uInt32)); 1770 1771 /* parse the tables */ 1772 for (i=0; i<(int)t->ntables; i++) { 1773 int nIndex; 1774 tag = GetUInt32(t->ptr + tdoffset + 12, 16 * i, 1); 1775 switch( tag ) { 1776 case T_maxp: nIndex = O_maxp; break; 1777 case T_glyf: nIndex = O_glyf; break; 1778 case T_head: nIndex = O_head; break; 1779 case T_loca: nIndex = O_loca; break; 1780 case T_name: nIndex = O_name; break; 1781 case T_hhea: nIndex = O_hhea; break; 1782 case T_hmtx: nIndex = O_hmtx; break; 1783 case T_cmap: nIndex = O_cmap; break; 1784 case T_vhea: nIndex = O_vhea; break; 1785 case T_vmtx: nIndex = O_vmtx; break; 1786 case T_OS2 : nIndex = O_OS2; break; 1787 case T_post: nIndex = O_post; break; 1788 case T_kern: nIndex = O_kern; break; 1789 case T_cvt : nIndex = O_cvt; break; 1790 case T_prep: nIndex = O_prep; break; 1791 case T_fpgm: nIndex = O_fpgm; break; 1792 case T_gsub: nIndex = O_gsub; break; 1793 case T_CFF: nIndex = O_CFF; break; 1794 default: nIndex = -1; break; 1795 } 1796 if( nIndex >= 0 ) { 1797 sal_uInt32 nTableOffset = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8, 1); 1798 length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12, 1); 1799 t->tables[nIndex] = t->ptr + nTableOffset; 1800 t->tlens[nIndex] = length; 1801 } 1802 } 1803 1804 /* Fixup offsets when only a TTC extract was provided */ 1805 if( facenum == (sal_uInt32)~0 ) { 1806 sal_uInt8* pHead = (sal_uInt8*)t->tables[O_head]; 1807 if( !pHead ) 1808 return SF_TTFORMAT; 1809 /* limit Head candidate to TTC extract's limits */ 1810 if( pHead > t->ptr + (t->fsize - 54) ) 1811 pHead = t->ptr + (t->fsize - 54); 1812 /* TODO: find better method than searching head table's magic */ 1813 sal_uInt8* p = NULL; 1814 for( p = pHead + 12; p > t->ptr; --p ) { 1815 if( p[0]==0x5F && p[1]==0x0F && p[2]==0x3C && p[3]==0xF5 ) { 1816 int nDelta = (pHead + 12) - p, j; 1817 if( nDelta ) 1818 for( j=0; j<NUM_TAGS; ++j ) 1819 if( t->tables[j] ) 1820 *(char**)&t->tables[j] -= nDelta; 1821 break; 1822 } 1823 } 1824 if( p <= t->ptr ) 1825 return SF_TTFORMAT; 1826 } 1827 1828 /* Check the table offsets after TTC correction */ 1829 for (i=0; i<NUM_TAGS; i++) { 1830 /* sanity check: table must lay completely within the file 1831 * at this point one could check the checksum of all contained 1832 * tables, but this would be quite time intensive. 1833 * Try to fix tables, so we can cope with minor problems. 1834 */ 1835 1836 if( (sal_uInt8*)t->tables[i] < t->ptr ) 1837 { 1838 #if OSL_DEBUG_LEVEL > 1 1839 if( t->tables[i] ) 1840 fprintf( stderr, "font file %s has bad table offset %d (tagnum=%d)\n", t->fname, (sal_uInt8*)t->tables[i]-t->ptr, i ); 1841 #endif 1842 t->tlens[i] = 0; 1843 t->tables[i] = NULL; 1844 } 1845 else if( (sal_uInt8*)t->tables[i] + t->tlens[i] > t->ptr + t->fsize ) 1846 { 1847 int nMaxLen = (t->ptr + t->fsize) - (sal_uInt8*)t->tables[i]; 1848 if( nMaxLen < 0 ) 1849 nMaxLen = 0; 1850 t->tlens[i] = nMaxLen; 1851 #if OSL_DEBUG_LEVEL > 1 1852 fprintf( stderr, "font file %s has too big table (tagnum=%d)\n", t->fname, i ); 1853 #endif 1854 } 1855 } 1856 1857 /* At this point TrueTypeFont is constructed, now need to verify the font format 1858 and read the basic font properties */ 1859 1860 /* The following tables are absolutely required: 1861 * maxp, head, name, cmap 1862 */ 1863 1864 if( !(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_name) && getTable(t, O_cmap)) ) { 1865 CloseTTFont(t); 1866 return SF_TTFORMAT; 1867 } 1868 1869 const sal_uInt8* table = getTable(t, O_maxp); 1870 t->nglyphs = GetUInt16(table, 4, 1); 1871 1872 table = getTable(t, O_head); 1873 t->unitsPerEm = GetUInt16(table, 18, 1); 1874 indexfmt = GetInt16(table, 50, 1); 1875 1876 if( ((indexfmt != 0) && (indexfmt != 1)) || (t->unitsPerEm <= 0) ) { 1877 CloseTTFont(t); 1878 return SF_TTFORMAT; 1879 } 1880 1881 if( getTable(t, O_glyf) && getTable(t, O_loca) ) { /* TTF or TTF-OpenType */ 1882 k = (getTableSize(t, O_loca) / (indexfmt ? 4 : 2)) - 1; 1883 if( k < (int)t->nglyphs ) /* Hack for broken Chinese fonts */ 1884 t->nglyphs = k; 1885 1886 table = getTable(t, O_loca); 1887 t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32)); 1888 assert(t->goffsets != 0); 1889 1890 for( i = 0; i <= (int)t->nglyphs; ++i ) 1891 t->goffsets[i] = indexfmt ? GetUInt32(table, i << 2, 1) : (sal_uInt32)GetUInt16(table, i << 1, 1) << 1; 1892 } else if( getTable(t, O_CFF) ) { /* PS-OpenType */ 1893 t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32)); 1894 /* TODO: implement to get subsetting */ 1895 assert(t->goffsets != 0); 1896 } else { 1897 CloseTTFont(t); 1898 return SF_TTFORMAT; 1899 } 1900 1901 table = getTable(t, O_hhea); 1902 t->numberOfHMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; 1903 1904 table = getTable(t, O_vhea); 1905 t->numOfLongVerMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; 1906 1907 GetNames(t); 1908 FindCmap(t); 1909 GetKern(t); 1910 ReadGSUB( t, 0, 0 ); 1911 1912 return SF_OK; 1913 } 1914 1915 void CloseTTFont(TrueTypeFont *ttf) /*FOLD01*/ 1916 { 1917 if (ttf->tag != TTFontClassTag) return; 1918 1919 #if !defined(WIN32) && !defined(OS2) 1920 if( ttf->fname ) 1921 munmap((char *) ttf->ptr, ttf->fsize); 1922 #endif 1923 free(ttf->fname); 1924 free(ttf->goffsets); 1925 free(ttf->psname); 1926 free(ttf->family); 1927 if( ttf->ufamily ) 1928 free( ttf->ufamily ); 1929 free(ttf->subfamily); 1930 if( ttf->usubfamily ) 1931 free( ttf->usubfamily ); 1932 free(ttf->tables); 1933 free(ttf->tlens); 1934 free(ttf->kerntables); 1935 1936 ReleaseGSUB(ttf); 1937 1938 free(ttf); 1939 return; 1940 } 1941 1942 int GetTTGlyphPoints(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray) 1943 { 1944 return GetTTGlyphOutline(ttf, glyphID, pointArray, 0, 0); 1945 } 1946 1947 int GetTTGlyphComponents(TrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal_uInt32 >& glyphlist) 1948 { 1949 int n = 1; 1950 1951 if( glyphID >= ttf->nglyphs ) 1952 return 0; 1953 1954 const sal_uInt8* glyf = getTable(ttf, O_glyf); 1955 const sal_uInt8* ptr = glyf + ttf->goffsets[glyphID]; 1956 1957 glyphlist.push_back( glyphID ); 1958 1959 if (GetInt16(ptr, 0, 1) == -1) { 1960 sal_uInt16 flags, index; 1961 ptr += 10; 1962 do { 1963 flags = GetUInt16(ptr, 0, 1); 1964 index = GetUInt16(ptr, 2, 1); 1965 1966 ptr += 4; 1967 n += GetTTGlyphComponents(ttf, index, glyphlist); 1968 1969 if (flags & ARG_1_AND_2_ARE_WORDS) { 1970 ptr += 4; 1971 } else { 1972 ptr += 2; 1973 } 1974 1975 if (flags & WE_HAVE_A_SCALE) { 1976 ptr += 2; 1977 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { 1978 ptr += 4; 1979 } else if (flags & WE_HAVE_A_TWO_BY_TWO) { 1980 ptr += 8; 1981 } 1982 } while (flags & MORE_COMPONENTS); 1983 } 1984 1985 return n; 1986 } 1987 1988 #ifndef NO_TYPE3 1989 int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, /*FOLD00*/ 1990 sal_uInt16 *glyphArray, sal_uInt8 *encoding, int nGlyphs, 1991 int wmode) 1992 { 1993 ControlPoint *pa; 1994 PSPathElement *path; 1995 int i, j, r, n; 1996 const sal_uInt8* table = getTable(ttf, O_head); 1997 TTGlyphMetrics metrics; 1998 int UPEm = ttf->unitsPerEm; 1999 2000 const char *h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n"; 2001 const char *h02 = "%% Creator: %s %s %s\n"; 2002 const char *h09 = "%% Original font name: %s\n"; 2003 2004 const char *h10 = 2005 "30 dict begin\n" 2006 "/PaintType 0 def\n" 2007 "/FontType 3 def\n" 2008 "/StrokeWidth 0 def\n"; 2009 2010 const char *h11 = "/FontName (%s) cvn def\n"; 2011 2012 /* 2013 const char *h12 = "%/UniqueID %d def\n"; 2014 */ 2015 const char *h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n"; 2016 const char *h14 = "/FontBBox [%d %d %d %d] def\n"; 2017 2018 const char *h15= 2019 "/Encoding 256 array def\n" 2020 " 0 1 255 {Encoding exch /.notdef put} for\n"; 2021 2022 const char *h16 = " Encoding %d /glyph%d put\n"; 2023 const char *h17 = "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n"; 2024 2025 const char *h30 = "/CharProcs %d dict def\n"; 2026 const char *h31 = " CharProcs begin\n"; 2027 const char *h32 = " /.notdef {} def\n"; 2028 const char *h33 = " /glyph%d {\n"; 2029 const char *h34 = " } bind def\n"; 2030 const char *h35 = " end\n"; 2031 2032 const char *h40 = 2033 "/BuildGlyph {\n" 2034 " exch /CharProcs get exch\n" 2035 " 2 copy known not\n" 2036 " {pop /.notdef} if\n" 2037 " get exec\n" 2038 "} bind def\n" 2039 "/BuildChar {\n" 2040 " 1 index /Encoding get exch get\n" 2041 " 1 index /BuildGlyph get exec\n" 2042 "} bind def\n" 2043 "currentdict end\n"; 2044 2045 const char *h41 = "(%s) cvn exch definefont pop\n"; 2046 2047 2048 if (!((nGlyphs > 0) && (nGlyphs <= 256))) return SF_GLYPHNUM; 2049 if (!glyphArray) return SF_BADARG; 2050 if (!fname) fname = ttf->psname; 2051 2052 fprintf(outf, h01, GetInt16(table, 0, 1), GetUInt16(table, 2, 1), GetInt16(table, 4, 1), GetUInt16(table, 6, 1)); 2053 fprintf(outf, h02, modname, modver, modextra); 2054 fprintf(outf, h09, ttf->psname); 2055 2056 fprintf(outf, h10); 2057 fprintf(outf, h11, fname); 2058 /* fprintf(outf, h12, 4000000); */ 2059 2060 /* XUID generation: 2061 * 103 0 0 C1 C2 C3 C4 2062 * C1 - CRC-32 of the entire source TrueType font 2063 * C2 - number of glyphs in the subset 2064 * C3 - CRC-32 of the glyph array 2065 * C4 - CRC-32 of the encoding array 2066 * 2067 * All CRC-32 numbers are presented as hexadecimal numbers 2068 */ 2069 2070 fprintf(outf, h17, rtl_crc32(0, ttf->ptr, ttf->fsize), nGlyphs, rtl_crc32(0, glyphArray, nGlyphs * 2), rtl_crc32(0, encoding, nGlyphs)); 2071 fprintf(outf, h13); 2072 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))); 2073 fprintf(outf, h15); 2074 2075 for (i = 0; i < nGlyphs; i++) { 2076 fprintf(outf, h16, encoding[i], i); 2077 } 2078 2079 fprintf(outf, h30, nGlyphs+1); 2080 fprintf(outf, h31); 2081 fprintf(outf, h32); 2082 2083 for (i = 0; i < nGlyphs; i++) { 2084 fprintf(outf, h33, i); 2085 r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->nglyphs ? glyphArray[i] : 0, &pa, &metrics, 0); 2086 2087 if (r > 0) { 2088 n = BSplineToPSPath(pa, r, &path); 2089 } else { 2090 n = 0; /* glyph might have zero contours but valid metrics ??? */ 2091 path = 0; 2092 if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */ 2093 continue; 2094 } 2095 } 2096 fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n", 2097 wmode == 0 ? XUnits(UPEm, metrics.aw) : 0, 2098 wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah), 2099 XUnits(UPEm, metrics.xMin), 2100 XUnits(UPEm, metrics.yMin), 2101 XUnits(UPEm, metrics.xMax), 2102 XUnits(UPEm, metrics.yMax)); 2103 2104 for (j = 0; j < n; j++) 2105 { 2106 switch (path[j].type) 2107 { 2108 case PS_MOVETO: 2109 fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); 2110 break; 2111 2112 case PS_LINETO: 2113 fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); 2114 break; 2115 2116 case PS_CURVETO: 2117 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)); 2118 break; 2119 2120 case PS_CLOSEPATH: 2121 fprintf(outf, "\tclosepath\n"); 2122 break; 2123 case PS_NOOP: 2124 break; 2125 } 2126 } 2127 if (n > 0) fprintf(outf, "\tfill\n"); /* if glyph is not a whitespace character */ 2128 2129 fprintf(outf, h34); 2130 2131 free(pa); 2132 free(path); 2133 } 2134 fprintf(outf, h35); 2135 2136 fprintf(outf, h40); 2137 fprintf(outf, h41, fname); 2138 2139 return SF_OK; 2140 } 2141 #endif 2142 2143 #ifndef NO_TTCR 2144 int CreateTTFromTTGlyphs(TrueTypeFont *ttf, 2145 const char *fname, 2146 sal_uInt16 *glyphArray, 2147 sal_uInt8 *encoding, 2148 int nGlyphs, 2149 int nNameRecs, 2150 NameRecord *nr, 2151 sal_uInt32 flags) 2152 { 2153 TrueTypeCreator *ttcr; 2154 TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0, *cmap=0, *name=0, *post = 0, *os2 = 0; 2155 int i; 2156 int res; 2157 2158 TrueTypeCreatorNewEmpty(T_true, &ttcr); 2159 2160 /** name **/ 2161 2162 if (flags & TTCF_AutoName) { 2163 /* not implemented yet 2164 NameRecord *names; 2165 NameRecord newname; 2166 int n = GetTTNameRecords(ttf, &names); 2167 int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0; 2168 sal_uInt8 *cp1; 2169 sal_uInt8 suffix[32]; 2170 sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2); 2171 sal_uInt32 c2 = crc32(encoding, nGlyphs); 2172 int len; 2173 snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs); 2174 2175 name = TrueTypeTableNew_name(0, 0); 2176 for (i = 0; i < n; i++) { 2177 if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) { 2178 2179 memcpy(newname, names+i, sizeof(NameRecord)); 2180 newname.slen = name[i].slen + strlen(suffix); 2181 */ 2182 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'}; 2183 NameRecord n1 = {1, 0, 0, 6, 14, (sal_uInt8*)"TrueTypeSubset"}; 2184 NameRecord n2 = {3, 1, 1033, 6, 28, 0}; 2185 n2.sptr = (sal_uInt8 *) ptr; 2186 name = TrueTypeTableNew_name(0, 0); 2187 nameAdd(name, &n1); 2188 nameAdd(name, &n2); 2189 } else { 2190 if (nNameRecs == 0) { 2191 NameRecord *names; 2192 int n = GetTTNameRecords(ttf, &names); 2193 name = TrueTypeTableNew_name(n, names); 2194 DisposeNameRecords(names, n); 2195 } else { 2196 name = TrueTypeTableNew_name(nNameRecs, nr); 2197 } 2198 } 2199 2200 /** maxp **/ 2201 maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); 2202 2203 /** hhea **/ 2204 const sal_uInt8* p = getTable(ttf, O_hhea); 2205 if (p) { 2206 hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); 2207 } else { 2208 hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); 2209 } 2210 2211 /** head **/ 2212 2213 p = getTable(ttf, O_head); 2214 assert(p != 0); 2215 head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), 2216 GetUInt16(p, 16, 1), 2217 GetUInt16(p, 18, 1), 2218 p+20, 2219 GetUInt16(p, 44, 1), 2220 GetUInt16(p, 46, 1), 2221 GetInt16(p, 48, 1)); 2222 2223 2224 /** glyf **/ 2225 2226 glyf = TrueTypeTableNew_glyf(); 2227 sal_uInt32* gID = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32)); 2228 2229 for (i = 0; i < nGlyphs; i++) { 2230 gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); 2231 } 2232 2233 /** cmap **/ 2234 cmap = TrueTypeTableNew_cmap(); 2235 2236 for (i=0; i < nGlyphs; i++) { 2237 cmapAdd(cmap, 0x010000, encoding[i], gID[i]); 2238 } 2239 2240 /** cvt **/ 2241 if ((p = getTable(ttf, O_cvt)) != 0) { 2242 cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); 2243 } 2244 2245 /** prep **/ 2246 if ((p = getTable(ttf, O_prep)) != 0) { 2247 prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); 2248 } 2249 2250 /** fpgm **/ 2251 if ((p = getTable(ttf, O_fpgm)) != 0) { 2252 fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); 2253 } 2254 2255 /** post **/ 2256 if ((p = getTable(ttf, O_post)) != 0) { 2257 post = TrueTypeTableNew_post(0x00030000, 2258 GetUInt32(p, 4, 1), 2259 GetUInt16(p, 8, 1), 2260 GetUInt16(p, 10, 1), 2261 GetUInt16(p, 12, 1)); 2262 } else { 2263 post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0); 2264 } 2265 2266 if (flags & TTCF_IncludeOS2) { 2267 if ((p = getTable(ttf, O_OS2)) != 0) { 2268 os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p); 2269 } 2270 } 2271 2272 AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea); 2273 AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap); 2274 AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm); 2275 AddTable(ttcr, post); AddTable(ttcr, os2); 2276 2277 if ((res = StreamToFile(ttcr, fname)) != SF_OK) { 2278 #if OSL_DEBUG_LEVEL > 1 2279 fprintf(stderr, "StreamToFile: error code: %d.\n", res); 2280 #endif 2281 } 2282 2283 TrueTypeCreatorDispose(ttcr); 2284 free(gID); 2285 2286 return res; 2287 } 2288 #endif 2289 2290 2291 #ifndef NO_TYPE42 2292 static GlyphOffsets *GlyphOffsetsNew(sal_uInt8 *sfntP) 2293 { 2294 GlyphOffsets* res = (GlyphOffsets*)smalloc(sizeof(GlyphOffsets)); 2295 sal_uInt8 *loca = NULL; 2296 sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); 2297 sal_uInt32 locaLen = 0; 2298 sal_Int16 indexToLocFormat = 0; 2299 2300 for (i = 0; i < numTables; i++) { 2301 sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); 2302 sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); 2303 sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); 2304 2305 if (tag == T_loca) { 2306 loca = sfntP + off; 2307 locaLen = len; 2308 } else if (tag == T_head) { 2309 indexToLocFormat = GetInt16(sfntP + off, 50, 1); 2310 } 2311 } 2312 2313 res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2); 2314 assert(res->nGlyphs != 0); 2315 res->offs = (sal_uInt32*)scalloc(res->nGlyphs, sizeof(sal_uInt32)); 2316 2317 for (i = 0; i < res->nGlyphs; i++) { 2318 if (indexToLocFormat == 1) { 2319 res->offs[i] = GetUInt32(loca, i * 4, 1); 2320 } else { 2321 res->offs[i] = GetUInt16(loca, i * 2, 1) << 1; 2322 } 2323 } 2324 return res; 2325 } 2326 2327 static void GlyphOffsetsDispose(GlyphOffsets *_this) 2328 { 2329 if (_this) { 2330 free(_this->offs); 2331 free(_this); 2332 } 2333 } 2334 2335 static void DumpSfnts(FILE *outf, sal_uInt8 *sfntP) 2336 { 2337 HexFmt *h = HexFmtNew(outf); 2338 sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); 2339 GlyphOffsets *go = GlyphOffsetsNew(sfntP); 2340 sal_uInt8 pad[] = {0,0,0,0}; /* zeroes */ 2341 2342 assert(numTables <= 9); /* Type42 has 9 required tables */ 2343 2344 sal_uInt32* offs = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32)); 2345 // sal_uInt32* lens = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32)); 2346 2347 fputs("/sfnts [", outf); 2348 HexFmtOpenString(h); 2349 HexFmtBlockWrite(h, sfntP, 12); /* stream out the Offset Table */ 2350 HexFmtBlockWrite(h, sfntP+12, 16 * numTables); /* stream out the Table Directory */ 2351 2352 for (i=0; i<numTables; i++) { 2353 sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); 2354 sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); 2355 sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); 2356 2357 if (tag != T_glyf) { 2358 HexFmtBlockWrite(h, sfntP + off, len); 2359 } else { 2360 sal_uInt8 *glyf = sfntP + off; 2361 sal_uInt32 o, l, j; 2362 for (j = 0; j < go->nGlyphs - 1; j++) { 2363 o = go->offs[j]; 2364 l = go->offs[j + 1] - o; 2365 HexFmtBlockWrite(h, glyf + o, l); 2366 } 2367 } 2368 HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3); 2369 } 2370 HexFmtCloseString(h); 2371 fputs("] def\n", outf); 2372 GlyphOffsetsDispose(go); 2373 HexFmtDispose(h); 2374 free(offs); 2375 // free(lens); 2376 } 2377 2378 int CreateT42FromTTGlyphs(TrueTypeFont *ttf, 2379 FILE *outf, 2380 const char *psname, 2381 sal_uInt16 *glyphArray, 2382 sal_uInt8 *encoding, 2383 int nGlyphs) 2384 { 2385 TrueTypeCreator *ttcr; 2386 TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0; 2387 int i; 2388 int res; 2389 2390 sal_uInt32 ver, rev; 2391 2392 sal_uInt8 *sfntP; 2393 sal_uInt32 sfntLen; 2394 int UPEm = ttf->unitsPerEm; 2395 2396 if (nGlyphs >= 256) return SF_GLYPHNUM; 2397 2398 assert(psname != 0); 2399 2400 TrueTypeCreatorNewEmpty(T_true, &ttcr); 2401 2402 /* head */ 2403 const sal_uInt8* p = getTable(ttf, O_head); 2404 const sal_uInt8* headP = p; 2405 assert(p != 0); 2406 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)); 2407 ver = GetUInt32(p, 0, 1); 2408 rev = GetUInt32(p, 4, 1); 2409 2410 /** hhea **/ 2411 p = getTable(ttf, O_hhea); 2412 if (p) { 2413 hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); 2414 } else { 2415 hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); 2416 } 2417 2418 /** maxp **/ 2419 maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); 2420 2421 /** cvt **/ 2422 if ((p = getTable(ttf, O_cvt)) != 0) { 2423 cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); 2424 } 2425 2426 /** prep **/ 2427 if ((p = getTable(ttf, O_prep)) != 0) { 2428 prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); 2429 } 2430 2431 /** fpgm **/ 2432 if ((p = getTable(ttf, O_fpgm)) != 0) { 2433 fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); 2434 } 2435 2436 /** glyf **/ 2437 glyf = TrueTypeTableNew_glyf(); 2438 sal_uInt16* gID = (sal_uInt16*)scalloc(nGlyphs, sizeof(sal_uInt32)); 2439 2440 for (i = 0; i < nGlyphs; i++) { 2441 gID[i] = (sal_uInt16)glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); 2442 } 2443 2444 AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt); 2445 AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm); 2446 2447 if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SF_OK) { 2448 TrueTypeCreatorDispose(ttcr); 2449 free(gID); 2450 return res; 2451 } 2452 2453 fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver>>16), (int)(ver & 0xFFFF), (int)(rev>>16), (int)(rev & 0xFFFF)); 2454 fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra); 2455 fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fname); 2456 fprintf(outf, "%%- Original font name: %s\n", ttf->psname); 2457 fprintf(outf, "%%- Original font family: %s\n", ttf->family); 2458 fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily); 2459 fprintf(outf, "11 dict begin\n"); 2460 fprintf(outf, "/FontName (%s) cvn def\n", psname); 2461 fprintf(outf, "/PaintType 0 def\n"); 2462 fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n"); 2463 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))); 2464 fprintf(outf, "/FontType 42 def\n"); 2465 fprintf(outf, "/Encoding 256 array def\n"); 2466 fprintf(outf, " 0 1 255 {Encoding exch /.notdef put} for\n"); 2467 2468 for (i = 1; i<nGlyphs; i++) { 2469 fprintf(outf, "Encoding %d /glyph%d put\n", encoding[i], gID[i]); 2470 } 2471 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)); 2472 2473 DumpSfnts(outf, sfntP); 2474 2475 /* dump charstrings */ 2476 fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs); 2477 fprintf(outf, "/.notdef 0 def\n"); 2478 for (i = 1; i < (int)glyfCount(glyf); i++) { 2479 fprintf(outf,"/glyph%d %d def\n", i, i); 2480 } 2481 fprintf(outf, "end readonly def\n"); 2482 2483 fprintf(outf, "FontName currentdict end definefont pop\n"); 2484 TrueTypeCreatorDispose(ttcr); 2485 free(gID); 2486 free(sfntP); 2487 return SF_OK; 2488 } 2489 #endif 2490 2491 2492 #ifndef NO_MAPPERS 2493 int MapString(TrueTypeFont *ttf, sal_uInt16 *str, int nchars, sal_uInt16 *glyphArray, int bvertical) 2494 { 2495 int i; 2496 sal_uInt16 *cp; 2497 2498 if (ttf->cmapType == CMAP_NOT_USABLE ) return -1; 2499 if (!nchars) return 0; 2500 2501 if (glyphArray == 0) { 2502 cp = str; 2503 } else { 2504 cp = glyphArray; 2505 } 2506 2507 switch (ttf->cmapType) { 2508 case CMAP_MS_Symbol: 2509 if( ttf->mapper == getGlyph0 ) { 2510 sal_uInt16 aChar; 2511 for( i = 0; i < nchars; i++ ) { 2512 aChar = str[i]; 2513 if( ( aChar & 0xf000 ) == 0xf000 ) 2514 aChar &= 0x00ff; 2515 cp[i] = aChar; 2516 } 2517 } 2518 else if( glyphArray ) 2519 memcpy(glyphArray, str, nchars * 2); 2520 break; 2521 2522 case CMAP_MS_Unicode: 2523 if (glyphArray != 0) { 2524 memcpy(glyphArray, str, nchars * 2); 2525 } 2526 break; 2527 2528 case CMAP_MS_ShiftJIS: TranslateString12(str, cp, nchars); break; 2529 case CMAP_MS_Big5: TranslateString13(str, cp, nchars); break; 2530 case CMAP_MS_PRC: TranslateString14(str, cp, nchars); break; 2531 case CMAP_MS_Wansung: TranslateString15(str, cp, nchars); break; 2532 case CMAP_MS_Johab: TranslateString16(str, cp, nchars); break; 2533 } 2534 2535 for (i = 0; i < nchars; i++) { 2536 cp[i] = (sal_uInt16)ttf->mapper(ttf->cmap, cp[i]); 2537 if (cp[i]!=0 && bvertical!=0) 2538 cp[i] = (sal_uInt16)UseGSUB(ttf,cp[i],bvertical); 2539 } 2540 return nchars; 2541 } 2542 2543 sal_uInt16 MapChar(TrueTypeFont *ttf, sal_uInt16 ch, int bvertical) 2544 { 2545 switch (ttf->cmapType) { 2546 case CMAP_MS_Symbol: 2547 2548 if( ttf->mapper == getGlyph0 && ( ch & 0xf000 ) == 0xf000 ) 2549 ch &= 0x00ff; 2550 return (sal_uInt16)ttf->mapper(ttf->cmap, ch ); 2551 2552 case CMAP_MS_Unicode: break; 2553 case CMAP_MS_ShiftJIS: ch = TranslateChar12(ch); break; 2554 case CMAP_MS_Big5: ch = TranslateChar13(ch); break; 2555 case CMAP_MS_PRC: ch = TranslateChar14(ch); break; 2556 case CMAP_MS_Wansung: ch = TranslateChar15(ch); break; 2557 case CMAP_MS_Johab: ch = TranslateChar16(ch); break; 2558 default: return 0; 2559 } 2560 ch = (sal_uInt16)ttf->mapper(ttf->cmap, ch); 2561 if (ch!=0 && bvertical!=0) 2562 ch = (sal_uInt16)UseGSUB(ttf,ch,bvertical); 2563 return ch; 2564 } 2565 2566 int DoesVerticalSubstitution( TrueTypeFont *ttf, int bvertical) 2567 { 2568 int nRet = 0; 2569 if( bvertical) 2570 nRet = HasVerticalGSUB( ttf); 2571 return nRet; 2572 } 2573 2574 #endif 2575 2576 int GetTTGlyphCount( TrueTypeFont* ttf ) 2577 { 2578 return ttf->nglyphs; 2579 } 2580 2581 bool GetSfntTable( TrueTypeFont* ttf, int nSubtableIndex, 2582 const sal_uInt8** ppRawBytes, int* pRawLength ) 2583 { 2584 if( (nSubtableIndex < 0) || (nSubtableIndex >= NUM_TAGS) ) 2585 return false; 2586 *pRawLength = ttf->tlens[ nSubtableIndex ]; 2587 *ppRawBytes = ttf->tables[ nSubtableIndex ]; 2588 bool bOk = (*pRawLength > 0) && (ppRawBytes != NULL); 2589 return bOk; 2590 } 2591 2592 TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, sal_uInt16 *glyphArray, int nGlyphs, int mode) 2593 { 2594 const sal_uInt8* pTable; 2595 sal_uInt32 n; 2596 int nTableSize; 2597 2598 if (mode == 0) { 2599 n = ttf->numberOfHMetrics; 2600 pTable = getTable( ttf, O_hmtx ); 2601 nTableSize = getTableSize( ttf, O_hmtx ); 2602 } else { 2603 n = ttf->numOfLongVerMetrics; 2604 pTable = getTable( ttf, O_vmtx ); 2605 nTableSize = getTableSize( ttf, O_vmtx ); 2606 } 2607 2608 if (!nGlyphs || !glyphArray) return 0; /* invalid parameters */ 2609 if (!n || !pTable) return 0; /* the font does not contain the requested metrics */ 2610 2611 TTSimpleGlyphMetrics* res = (TTSimpleGlyphMetrics*)calloc(nGlyphs, sizeof(TTSimpleGlyphMetrics)); 2612 assert(res != 0); 2613 2614 const int UPEm = ttf->unitsPerEm; 2615 for( int i = 0; i < nGlyphs; ++i) { 2616 int nAdvOffset, nLsbOffset; 2617 sal_uInt16 glyphID = glyphArray[i]; 2618 2619 if (glyphID < n) { 2620 nAdvOffset = 4 * glyphID; 2621 nLsbOffset = nAdvOffset + 2; 2622 } else { 2623 nAdvOffset = 4 * (n - 1); 2624 if( glyphID < ttf->nglyphs ) 2625 nLsbOffset = 4 * n + 2 * (glyphID - n); 2626 else /* font is broken -> use lsb of last hmetrics */ 2627 nLsbOffset = nAdvOffset + 2; 2628 } 2629 2630 if( nAdvOffset >= nTableSize) 2631 res[i].adv = 0; /* better than a crash for buggy fonts */ 2632 else 2633 res[i].adv = static_cast<sal_uInt16>( 2634 XUnits( UPEm, GetUInt16( pTable, nAdvOffset, 1) ) ); 2635 2636 if( nLsbOffset >= nTableSize) 2637 res[i].sb = 0; /* better than a crash for buggy fonts */ 2638 else 2639 res[i].sb = static_cast<sal_Int16>( 2640 XUnits( UPEm, GetInt16( pTable, nLsbOffset, 1) ) ); 2641 } 2642 2643 return res; 2644 } 2645 2646 #ifndef NO_MAPPERS 2647 TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, sal_uInt16 firstChar, int nChars, int mode) 2648 { 2649 TTSimpleGlyphMetrics *res = 0; 2650 int i, n; 2651 2652 sal_uInt16* str = (sal_uInt16*)malloc(nChars * 2); 2653 assert(str != 0); 2654 2655 for (i=0; i<nChars; i++) str[i] = (sal_uInt16)(firstChar + i); 2656 if ((n = MapString(ttf, str, nChars, 0, mode)) != -1) { 2657 res = GetTTSimpleGlyphMetrics(ttf, str, n, mode); 2658 } 2659 2660 free(str); 2661 2662 return res; 2663 } 2664 #endif 2665 2666 void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info) 2667 { 2668 int UPEm = ttf->unitsPerEm; 2669 2670 memset(info, 0, sizeof(TTGlobalFontInfo)); 2671 2672 info->family = ttf->family; 2673 info->ufamily = ttf->ufamily; 2674 info->subfamily = ttf->subfamily; 2675 info->usubfamily = ttf->usubfamily; 2676 info->psname = ttf->psname; 2677 info->symbolEncoded = (ttf->cmapType == CMAP_MS_Symbol); 2678 2679 const sal_uInt8* table = getTable(ttf, O_OS2); 2680 if (table) { 2681 info->weight = GetUInt16(table, 4, 1); 2682 info->width = GetUInt16(table, 6, 1); 2683 2684 /* There are 3 different versions of OS/2 table: original (68 bytes long), 2685 * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,) 2686 * Apple's documentation recommends looking at the table length. 2687 */ 2688 if (getTableSize(ttf, O_OS2) > 68) { 2689 info->typoAscender = XUnits(UPEm,GetInt16(table, 68, 1)); 2690 info->typoDescender = XUnits(UPEm, GetInt16(table, 70, 1)); 2691 info->typoLineGap = XUnits(UPEm, GetInt16(table, 72, 1)); 2692 info->winAscent = XUnits(UPEm, GetUInt16(table, 74, 1)); 2693 info->winDescent = XUnits(UPEm, GetUInt16(table, 76, 1)); 2694 /* sanity check; some fonts treat winDescent as signed 2695 * violating the standard */ 2696 if( info->winDescent > 5*UPEm ) 2697 info->winDescent = XUnits(UPEm, GetInt16(table, 76,1)); 2698 } 2699 if (ttf->cmapType == CMAP_MS_Unicode) { 2700 info->rangeFlag = 1; 2701 info->ur1 = GetUInt32(table, 42, 1); 2702 info->ur2 = GetUInt32(table, 46, 1); 2703 info->ur3 = GetUInt32(table, 50, 1); 2704 info->ur4 = GetUInt32(table, 54, 1); 2705 } 2706 memcpy(info->panose, table + 32, 10); 2707 info->typeFlags = GetUInt16( table, 8, 1 ); 2708 if( getTable(ttf, O_CFF) ) 2709 info->typeFlags |= TYPEFLAG_PS_OPENTYPE; 2710 } 2711 2712 table = getTable(ttf, O_post); 2713 if (table && getTableSize(ttf, O_post) >= 12+sizeof(sal_uInt32)) { 2714 info->pitch = GetUInt32(table, 12, 1); 2715 info->italicAngle = GetInt32(table, 4, 1); 2716 } 2717 2718 table = getTable(ttf, O_head); /* 'head' tables is always there */ 2719 info->xMin = XUnits(UPEm, GetInt16(table, 36, 1)); 2720 info->yMin = XUnits(UPEm, GetInt16(table, 38, 1)); 2721 info->xMax = XUnits(UPEm, GetInt16(table, 40, 1)); 2722 info->yMax = XUnits(UPEm, GetInt16(table, 42, 1)); 2723 info->macStyle = GetInt16(table, 44, 1); 2724 2725 table = getTable(ttf, O_hhea); 2726 if (table) { 2727 info->ascender = XUnits(UPEm, GetInt16(table, 4, 1)); 2728 info->descender = XUnits(UPEm, GetInt16(table, 6, 1)); 2729 info->linegap = XUnits(UPEm, GetInt16(table, 8, 1)); 2730 } 2731 2732 table = getTable(ttf, O_vhea); 2733 if (table) { 2734 info->vascent = XUnits(UPEm, GetInt16(table, 4, 1)); 2735 info->vdescent = XUnits(UPEm, GetInt16(table, 6, 1)); 2736 } 2737 } 2738 2739 #ifdef TEST5 2740 void KernGlyphs(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) 2741 { 2742 int i; 2743 2744 if (!nglyphs || !glyphs || !kern) return; 2745 2746 for (i = 0; i < nglyphs-1; i++) kern[i].x = kern[i].y = 0; 2747 2748 switch (ttf->kerntype) { 2749 case KT_APPLE_NEW: KernGlyphsPrim1(ttf, glyphs, nglyphs, wmode, kern); return; 2750 case KT_MICROSOFT: KernGlyphsPrim2(ttf, glyphs, nglyphs, wmode, kern); return; 2751 default: return; 2752 } 2753 } 2754 #endif 2755 2756 GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, sal_uInt32 glyphID) 2757 { 2758 const sal_uInt8* glyf = getTable(ttf, O_glyf); 2759 const sal_uInt8* hmtx = getTable(ttf, O_hmtx); 2760 int i, n, m; 2761 2762 if( glyphID >= ttf->nglyphs ) 2763 return 0; 2764 2765 /* #127161# check the glyph offsets */ 2766 sal_uInt32 length = getTableSize( ttf, O_glyf ); 2767 if( length < ttf->goffsets[ glyphID+1 ] ) 2768 return 0; 2769 2770 length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; 2771 2772 GlyphData* d = (GlyphData*)malloc(sizeof(GlyphData)); assert(d != 0); 2773 2774 if (length > 0) { 2775 const sal_uInt8* srcptr = glyf + ttf->goffsets[glyphID]; 2776 d->ptr = (sal_uInt8*)malloc((length + 1) & ~1); assert(d->ptr != 0); 2777 memcpy( d->ptr, srcptr, length ); 2778 d->compflag = (GetInt16( srcptr, 0, 1 ) < 0); 2779 } else { 2780 d->ptr = 0; 2781 d->compflag = 0; 2782 } 2783 2784 d->glyphID = glyphID; 2785 d->nbytes = (sal_uInt16)((length + 1) & ~1); 2786 2787 /* now calculate npoints and ncontours */ 2788 ControlPoint *cp; 2789 n = GetTTGlyphPoints(ttf, glyphID, &cp); 2790 if (n != -1) { 2791 m = 0; 2792 for (i = 0; i < n; i++) { 2793 if (cp[i].flags & 0x8000) m++; 2794 } 2795 d->npoints = (sal_uInt16)n; 2796 d->ncontours = (sal_uInt16)m; 2797 free(cp); 2798 } else { 2799 d->npoints = 0; 2800 d->ncontours = 0; 2801 } 2802 2803 /* get advance width and left sidebearing */ 2804 if (glyphID < ttf->numberOfHMetrics) { 2805 d->aw = GetUInt16(hmtx, 4 * glyphID, 1); 2806 d->lsb = GetInt16(hmtx, 4 * glyphID + 2, 1); 2807 } else { 2808 d->aw = GetUInt16(hmtx, 4 * (ttf->numberOfHMetrics - 1), 1); 2809 d->lsb = GetInt16(hmtx + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1); 2810 } 2811 2812 return d; 2813 } 2814 2815 int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr) 2816 { 2817 const sal_uInt8* table = getTable(ttf, O_name); 2818 int nTableSize = getTableSize(ttf, O_name ); 2819 2820 if (nTableSize < 6) 2821 { 2822 #if OSL_DEBUG_LEVEL > 1 2823 fprintf(stderr, "O_name table too small\n"); 2824 #endif 2825 return 0; 2826 } 2827 2828 sal_uInt16 n = GetUInt16(table, 2, 1); 2829 int nStrBase = GetUInt16(table, 4, 1); 2830 int i; 2831 2832 *nr = 0; 2833 if (n == 0) return 0; 2834 2835 NameRecord* rec = (NameRecord*)calloc(n, sizeof(NameRecord)); 2836 2837 for (i = 0; i < n; i++) { 2838 int nStrOffset = GetUInt16(table + 6, 10 + 12 * i, 1); 2839 rec[i].platformID = GetUInt16(table + 6, 12 * i, 1); 2840 rec[i].encodingID = GetUInt16(table + 6, 2 + 12 * i, 1); 2841 rec[i].languageID = GetUInt16(table + 6, 4 + 12 * i, 1); 2842 rec[i].nameID = GetUInt16(table + 6, 6 + 12 * i, 1); 2843 rec[i].slen = GetUInt16(table + 6, 8 + 12 * i, 1); 2844 if (rec[i].slen) { 2845 if( nStrBase+nStrOffset+rec[i].slen >= nTableSize ) { 2846 rec[i].sptr = 0; 2847 rec[i].slen = 0; 2848 continue; 2849 } 2850 2851 const sal_uInt8* rec_string = table + nStrBase + nStrOffset; 2852 // sanity check 2853 if( rec_string > (sal_uInt8*)ttf->ptr && rec_string < ((sal_uInt8*)ttf->ptr + ttf->fsize - rec[i].slen ) ) 2854 { 2855 rec[i].sptr = (sal_uInt8 *) malloc(rec[i].slen); assert(rec[i].sptr != 0); 2856 memcpy(rec[i].sptr, rec_string, rec[i].slen); 2857 } 2858 else 2859 { 2860 #ifdef DEBUG 2861 fprintf( stderr, "found invalid name record %d with name id %d for file %s\n", 2862 i, rec[i].nameID, ttf->fname ); 2863 #endif 2864 rec[i].sptr = 0; 2865 rec[i].slen = 0; 2866 } 2867 } else { 2868 rec[i].sptr = 0; 2869 } 2870 // some fonts have 3.0 names => fix them to 3.1 2871 if( (rec[i].platformID == 3) && (rec[i].encodingID == 0) ) 2872 rec[i].encodingID = 1; 2873 } 2874 2875 *nr = rec; 2876 return n; 2877 } 2878 2879 void DisposeNameRecords(NameRecord* nr, int n) 2880 { 2881 int i; 2882 for (i = 0; i < n; i++) { 2883 if (nr[i].sptr) free(nr[i].sptr); 2884 } 2885 free(nr); 2886 } 2887 2888 } // namespace vcl 2889 2890 2891 #ifdef TEST1 2892 /* This example creates a subset of a TrueType font with two encoded characters */ 2893 int main(int ac, char **av) 2894 { 2895 TrueTypeFont *fnt; 2896 int r; 2897 2898 /* Array of Unicode source characters */ 2899 sal_uInt16 chars[2]; 2900 2901 /* Encoding vector maps character encoding to the ordinal number 2902 * of the glyph in the output file */ 2903 sal_uInt8 encoding[2]; 2904 2905 /* This array is for glyph IDs that source characters map to */ 2906 sal_uInt16 g[2]; 2907 2908 2909 if (ac < 2) return 0; 2910 2911 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 2912 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 2913 return 0; 2914 } 2915 2916 2917 /* We want to create the output file that only contains two Unicode characters: 2918 * L'a' and L'A' */ 2919 2920 chars[0] = L'a'; 2921 chars[1] = L'A'; 2922 2923 /* Figure out what glyphs do these characters map in our font */ 2924 MapString(fnt, chars, 2, g); 2925 2926 /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the 2927 * newly generated font */ 2928 encoding[0] = chars[0]; 2929 encoding[1] = chars[1]; 2930 2931 2932 /* Generate a subset */ 2933 CreateT3FromTTGlyphs(fnt, stdout, 0, g, encoding, 2, 0); 2934 2935 /* Now call the dtor for the font */ 2936 CloseTTFont(fnt); 2937 return 0; 2938 } 2939 #endif 2940 2941 #ifdef TEST2 2942 /* This example extracts first 224 glyphs from a TT fonts and encodes them starting at 32 */ 2943 int main(int ac, char **av) 2944 { 2945 TrueTypeFont *fnt; 2946 int i, r; 2947 2948 /* Array of Unicode source characters */ 2949 sal_uInt16 glyphs[224]; 2950 2951 /* Encoding vector maps character encoding to the ordinal number 2952 * of the glyph in the output file */ 2953 sal_uInt8 encoding[224]; 2954 2955 2956 2957 for (i=0; i<224; i++) { 2958 glyphs[i] = i; 2959 encoding[i] = 32 + i; 2960 } 2961 2962 if (ac < 2) return 0; 2963 2964 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 2965 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 2966 return 0; 2967 } 2968 2969 2970 /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the 2971 * newly generated font */ 2972 2973 /* Generate a subset */ 2974 CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 224, 0); 2975 2976 /* Now call the dtor for the font */ 2977 CloseTTFont(fnt); 2978 return 0; 2979 } 2980 #endif 2981 2982 #ifdef TEST3 2983 /* Glyph metrics example */ 2984 int main(int ac, char **av) 2985 { 2986 TrueTypeFont *fnt; 2987 int i, r; 2988 sal_uInt16 glyphs[224]; 2989 TTSimpleGlyphMetrics *m; 2990 2991 for (i=0; i<224; i++) { 2992 glyphs[i] = i; 2993 } 2994 2995 if (ac < 2) return 0; 2996 2997 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 2998 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 2999 return 0; 3000 } 3001 3002 if ((m = GetTTSimpleGlyphMetrics(fnt, glyphs, 224, 0)) == 0) { 3003 printf("Requested metrics is not available\n"); 3004 } else { 3005 for (i=0; i<224; i++) { 3006 printf("%d. advWid: %5d, LSBear: %5d\n", i, m[i].adv, m[i].sb); 3007 } 3008 } 3009 3010 /* Now call the dtor for the font */ 3011 free(m); 3012 CloseTTFont(fnt); 3013 return 0; 3014 } 3015 #endif 3016 3017 #ifdef TEST4 3018 int main(int ac, char **av) 3019 { 3020 TrueTypeFont *fnt; 3021 TTGlobalFontInfo info; 3022 int i, r; 3023 3024 3025 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3026 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3027 return 0; 3028 } 3029 3030 printf("Font file: %s\n", av[1]); 3031 3032 #ifdef PRINT_KERN 3033 switch (fnt->kerntype) { 3034 case KT_MICROSOFT: 3035 printf("\tkern: MICROSOFT, ntables: %d.", fnt->nkern); 3036 if (fnt->nkern) { 3037 printf(" ["); 3038 for (i=0; i<fnt->nkern; i++) { 3039 printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); 3040 } 3041 printf("]"); 3042 } 3043 printf("\n"); 3044 break; 3045 3046 case KT_APPLE_NEW: 3047 printf("\tkern: APPLE_NEW, ntables: %d.", fnt->nkern); 3048 if (fnt->nkern) { 3049 printf(" ["); 3050 for (i=0; i<fnt->nkern; i++) { 3051 printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); 3052 } 3053 printf("]"); 3054 } 3055 printf("\n"); 3056 break; 3057 3058 case KT_NONE: 3059 printf("\tkern: none.\n"); 3060 break; 3061 3062 default: 3063 printf("\tkern: unrecoginzed.\n"); 3064 break; 3065 } 3066 printf("\n"); 3067 #endif 3068 3069 GetTTGlobalFontInfo(fnt, &info); 3070 printf("\tfamily name: `%s`\n", info.family); 3071 printf("\tsubfamily name: `%s`\n", info.subfamily); 3072 printf("\tpostscript name: `%s`\n", info.psname); 3073 printf("\tweight: %d\n", info.weight); 3074 printf("\twidth: %d\n", info.width); 3075 printf("\tpitch: %d\n", info.pitch); 3076 printf("\titalic angle: %d\n", info.italicAngle); 3077 printf("\tbouding box: [%d %d %d %d]\n", info.xMin, info.yMin, info.xMax, info.yMax); 3078 printf("\tascender: %d\n", info.ascender); 3079 printf("\tdescender: %d\n", info.descender); 3080 printf("\tlinegap: %d\n", info.linegap); 3081 printf("\tvascent: %d\n", info.vascent); 3082 printf("\tvdescent: %d\n", info.vdescent); 3083 printf("\ttypoAscender: %d\n", info.typoAscender); 3084 printf("\ttypoDescender: %d\n", info.typoDescender); 3085 printf("\ttypoLineGap: %d\n", info.typoLineGap); 3086 printf("\twinAscent: %d\n", info.winAscent); 3087 printf("\twinDescent: %d\n", info.winDescent); 3088 printf("\tUnicode ranges:\n"); 3089 for (i = 0; i < 32; i++) { 3090 if ((info.ur1 >> i) & 1) { 3091 printf("\t\t\t%s\n", UnicodeRangeName(i)); 3092 } 3093 } 3094 for (i = 0; i < 32; i++) { 3095 if ((info.ur2 >> i) & 1) { 3096 printf("\t\t\t%s\n", UnicodeRangeName(i+32)); 3097 } 3098 } 3099 for (i = 0; i < 32; i++) { 3100 if ((info.ur3 >> i) & 1) { 3101 printf("\t\t\t%s\n", UnicodeRangeName(i+64)); 3102 } 3103 } 3104 for (i = 0; i < 32; i++) { 3105 if ((info.ur4 >> i) & 1) { 3106 printf("\t\t\t%s\n", UnicodeRangeName(i+96)); 3107 } 3108 } 3109 3110 CloseTTFont(fnt); 3111 return 0; 3112 } 3113 #endif 3114 3115 #ifdef TEST5 3116 /* Kerning example */ 3117 int main(int ac, char **av) 3118 { 3119 TrueTypeFont *fnt; 3120 sal_uInt16 g[224]; 3121 KernData d[223]; 3122 int r, i, k = 0; 3123 3124 g[k++] = 11; 3125 g[k++] = 36; 3126 g[k++] = 11; 3127 g[k++] = 98; 3128 g[k++] = 11; 3129 g[k++] = 144; 3130 g[k++] = 41; 3131 g[k++] = 171; 3132 g[k++] = 51; 3133 g[k++] = 15; 3134 3135 if (ac < 2) return 0; 3136 3137 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3138 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3139 return 0; 3140 } 3141 3142 KernGlyphs(fnt, g, k, 0, d); 3143 3144 for (i = 0; i < k-1; i++) { 3145 printf("%3d %3d: [%3d %3d]\n", g[i], g[i+1], d[i].x, d[i].y); 3146 } 3147 3148 CloseTTFont(fnt); 3149 return 0; 3150 } 3151 #endif 3152 3153 3154 3155 #ifdef TEST6 3156 /* This example extracts a single glyph from a font */ 3157 int main(int ac, char **av) 3158 { 3159 TrueTypeFont *fnt; 3160 int r, i; 3161 3162 sal_uInt16 glyphs[256]; 3163 sal_uInt8 encoding[256]; 3164 3165 for (i=0; i<256; i++) { 3166 glyphs[i] = 512 + i; 3167 encoding[i] = i; 3168 } 3169 3170 #if 0 3171 i=0; 3172 glyphs[i++] = 2001; 3173 glyphs[i++] = 2002; 3174 glyphs[i++] = 2003; 3175 glyphs[i++] = 2004; 3176 glyphs[i++] = 2005; 3177 glyphs[i++] = 2006; 3178 glyphs[i++] = 2007; 3179 glyphs[i++] = 2008; 3180 glyphs[i++] = 2009; 3181 glyphs[i++] = 2010; 3182 glyphs[i++] = 2011; 3183 glyphs[i++] = 2012; 3184 glyphs[i++] = 2013; 3185 glyphs[i++] = 2014; 3186 glyphs[i++] = 2015; 3187 glyphs[i++] = 2016; 3188 glyphs[i++] = 2017; 3189 glyphs[i++] = 2018; 3190 glyphs[i++] = 2019; 3191 glyphs[i++] = 2020; 3192 3193 3194 r = 97; 3195 i = 0; 3196 encoding[i++] = r++; 3197 encoding[i++] = r++; 3198 encoding[i++] = r++; 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 #endif 3217 3218 if (ac < 2) return 0; 3219 3220 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3221 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3222 return 0; 3223 } 3224 3225 /* Generate a subset */ 3226 CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 256, 0); 3227 3228 fprintf(stderr, "UnitsPerEm: %d.\n", fnt->unitsPerEm); 3229 3230 /* Now call the dtor for the font */ 3231 CloseTTFont(fnt); 3232 return 0; 3233 } 3234 #endif 3235 3236 #ifdef TEST7 3237 /* NameRecord extraction example */ 3238 int main(int ac, char **av) 3239 { 3240 TrueTypeFont *fnt; 3241 int r, i, j, n; 3242 NameRecord *nr; 3243 3244 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3245 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3246 return 0; 3247 } 3248 3249 if ((n = GetTTNameRecords(fnt, &nr)) == 0) { 3250 fprintf(stderr, "No name records in the font.\n"); 3251 return 0; 3252 } 3253 3254 printf("Number of name records: %d.\n", n); 3255 for (i = 0; i < n; i++) { 3256 printf("%d %d %04X %d [", nr[i].platformID, nr[i].encodingID, nr[i].languageID, nr[i].nameID); 3257 for (j=0; j<nr[i].slen; j++) { 3258 printf("%c", isprint(nr[i].sptr[j]) ? nr[i].sptr[j] : '.'); 3259 } 3260 printf("]\n"); 3261 } 3262 3263 3264 DisposeNameRecords(nr, n); 3265 CloseTTFont(fnt); 3266 return 0; 3267 } 3268 #endif 3269 3270 #ifdef TEST8 3271 /* TrueType -> TrueType subsetting */ 3272 int main(int ac, char **av) 3273 { 3274 TrueTypeFont *fnt; 3275 sal_uInt16 glyphArray[] = { 0, 98, 99, 22, 24, 25, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; 3276 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; 3277 int r; 3278 3279 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3280 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3281 return 0; 3282 } 3283 3284 CreateTTFromTTGlyphs(fnt, "subfont.ttf", glyphArray, encoding, 15, 0, 0, TTCF_AutoName | TTCF_IncludeOS2); 3285 3286 3287 CloseTTFont(fnt); 3288 3289 return 0; 3290 } 3291 #endif 3292 3293 #ifdef TEST9 3294 /* TrueType -> Type42 subsetting */ 3295 int main(int ac, char **av) 3296 { 3297 TrueTypeFont *fnt; 3298 /* 3299 sal_uInt16 glyphArray[] = { 0, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}; 3300 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; 3301 */ 3302 sal_uInt16 glyphArray[] = { 0, 6711, 6724, 11133, 11144, 14360, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; 3303 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; 3304 int r; 3305 3306 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3307 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3308 return 0; 3309 } 3310 3311 CreateT42FromTTGlyphs(fnt, stdout, "testfont", glyphArray, encoding, 15); 3312 3313 CloseTTFont(fnt); 3314 3315 return 0; 3316 } 3317 #endif 3318 3319 #ifdef TEST10 3320 /* Component glyph test */ 3321 int main(int ac, char **av) 3322 { 3323 TrueTypeFont *fnt; 3324 int r, i; 3325 list glyphlist = listNewEmpty(); 3326 3327 3328 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3329 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3330 return 0; 3331 } 3332 3333 for (i = 0; i < fnt->nglyphs; i++) { 3334 r = GetTTGlyphComponents(fnt, i, glyphlist); 3335 if (r > 1) { 3336 printf("%d -> ", i); 3337 listToFirst(glyphlist); 3338 do { 3339 printf("%d ", (int) listCurrent(glyphlist)); 3340 } while (listNext(glyphlist)); 3341 printf("\n"); 3342 } else { 3343 printf("%d: single glyph.\n", i); 3344 } 3345 listClear(glyphlist); 3346 } 3347 3348 CloseTTFont(fnt); 3349 listDispose(glyphlist); 3350 3351 return 0; 3352 } 3353 #endif 3354 3355 3356