1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include <ctype.h> 11 12 #include "SkData.h" 13 #include "SkFontHost.h" 14 #include "SkGlyphCache.h" 15 #include "SkPaint.h" 16 #include "SkPDFCatalog.h" 17 #include "SkPDFDevice.h" 18 #include "SkPDFFont.h" 19 #include "SkPDFFontImpl.h" 20 #include "SkPDFStream.h" 21 #include "SkPDFTypes.h" 22 #include "SkPDFUtils.h" 23 #include "SkRefCnt.h" 24 #include "SkScalar.h" 25 #include "SkStream.h" 26 #include "SkTypeface.h" 27 #include "SkTypes.h" 28 #include "SkUtils.h" 29 30 #if defined (SK_SFNTLY_SUBSETTER) 31 #include SK_SFNTLY_SUBSETTER 32 #endif 33 34 namespace { 35 36 /////////////////////////////////////////////////////////////////////////////// 37 // File-Local Functions 38 /////////////////////////////////////////////////////////////////////////////// 39 40 bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType, 41 size_t* size) { 42 // PFB sections have a two or six bytes header. 0x80 and a one byte 43 // section type followed by a four byte section length. Type one is 44 // an ASCII section (includes a length), type two is a binary section 45 // (includes a length) and type three is an EOF marker with no length. 46 const uint8_t* buf = *src; 47 if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) { 48 return false; 49 } else if (buf[1] == 3) { 50 return true; 51 } else if (*len < 6) { 52 return false; 53 } 54 55 *size = (size_t)buf[2] | ((size_t)buf[3] << 8) | ((size_t)buf[4] << 16) | 56 ((size_t)buf[5] << 24); 57 size_t consumed = *size + 6; 58 if (consumed > *len) { 59 return false; 60 } 61 *src = *src + consumed; 62 *len = *len - consumed; 63 return true; 64 } 65 66 bool parsePFB(const uint8_t* src, size_t size, size_t* headerLen, 67 size_t* dataLen, size_t* trailerLen) { 68 const uint8_t* srcPtr = src; 69 size_t remaining = size; 70 71 return parsePFBSection(&srcPtr, &remaining, 1, headerLen) && 72 parsePFBSection(&srcPtr, &remaining, 2, dataLen) && 73 parsePFBSection(&srcPtr, &remaining, 1, trailerLen) && 74 parsePFBSection(&srcPtr, &remaining, 3, NULL); 75 } 76 77 /* The sections of a PFA file are implicitly defined. The body starts 78 * after the line containing "eexec," and the trailer starts with 512 79 * literal 0's followed by "cleartomark" (plus arbitrary white space). 80 * 81 * This function assumes that src is NUL terminated, but the NUL 82 * termination is not included in size. 83 * 84 */ 85 bool parsePFA(const char* src, size_t size, size_t* headerLen, 86 size_t* hexDataLen, size_t* dataLen, size_t* trailerLen) { 87 const char* end = src + size; 88 89 const char* dataPos = strstr(src, "eexec"); 90 if (!dataPos) { 91 return false; 92 } 93 dataPos += strlen("eexec"); 94 while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') && 95 dataPos < end) { 96 dataPos++; 97 } 98 *headerLen = dataPos - src; 99 100 const char* trailerPos = strstr(dataPos, "cleartomark"); 101 if (!trailerPos) { 102 return false; 103 } 104 int zeroCount = 0; 105 for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) { 106 if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') { 107 continue; 108 } else if (*trailerPos == '0') { 109 zeroCount++; 110 } else { 111 return false; 112 } 113 } 114 if (zeroCount != 512) { 115 return false; 116 } 117 118 *hexDataLen = trailerPos - src - *headerLen; 119 *trailerLen = size - *headerLen - *hexDataLen; 120 121 // Verify that the data section is hex encoded and count the bytes. 122 int nibbles = 0; 123 for (; dataPos < trailerPos; dataPos++) { 124 if (isspace(*dataPos)) { 125 continue; 126 } 127 if (!isxdigit(*dataPos)) { 128 return false; 129 } 130 nibbles++; 131 } 132 *dataLen = (nibbles + 1) / 2; 133 134 return true; 135 } 136 137 int8_t hexToBin(uint8_t c) { 138 if (!isxdigit(c)) { 139 return -1; 140 } else if (c <= '9') { 141 return c - '0'; 142 } else if (c <= 'F') { 143 return c - 'A' + 10; 144 } else if (c <= 'f') { 145 return c - 'a' + 10; 146 } 147 return -1; 148 } 149 150 SkStream* handleType1Stream(SkStream* srcStream, size_t* headerLen, 151 size_t* dataLen, size_t* trailerLen) { 152 // srcStream may be backed by a file or a unseekable fd, so we may not be 153 // able to use skip(), rewind(), or getMemoryBase(). read()ing through 154 // the input only once is doable, but very ugly. Furthermore, it'd be nice 155 // if the data was NUL terminated so that we can use strstr() to search it. 156 // Make as few copies as possible given these constraints. 157 SkDynamicMemoryWStream dynamicStream; 158 SkAutoTUnref<SkMemoryStream> staticStream; 159 SkData* data = NULL; 160 const uint8_t* src; 161 size_t srcLen; 162 if ((srcLen = srcStream->getLength()) > 0) { 163 staticStream.reset(new SkMemoryStream(srcLen + 1)); 164 src = (const uint8_t*)staticStream->getMemoryBase(); 165 if (srcStream->getMemoryBase() != NULL) { 166 memcpy((void *)src, srcStream->getMemoryBase(), srcLen); 167 } else { 168 size_t read = 0; 169 while (read < srcLen) { 170 size_t got = srcStream->read((void *)staticStream->getAtPos(), 171 srcLen - read); 172 if (got == 0) { 173 return NULL; 174 } 175 read += got; 176 staticStream->seek(read); 177 } 178 } 179 ((uint8_t *)src)[srcLen] = 0; 180 } else { 181 static const size_t kBufSize = 4096; 182 uint8_t buf[kBufSize]; 183 size_t amount; 184 while ((amount = srcStream->read(buf, kBufSize)) > 0) { 185 dynamicStream.write(buf, amount); 186 } 187 amount = 0; 188 dynamicStream.write(&amount, 1); // NULL terminator. 189 data = dynamicStream.copyToData(); 190 src = data->bytes(); 191 srcLen = data->size() - 1; 192 } 193 194 // this handles releasing the data we may have gotten from dynamicStream. 195 // if data is null, it is a no-op 196 SkAutoDataUnref aud(data); 197 198 if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) { 199 SkMemoryStream* result = 200 new SkMemoryStream(*headerLen + *dataLen + *trailerLen); 201 memcpy((char*)result->getAtPos(), src + 6, *headerLen); 202 result->seek(*headerLen); 203 memcpy((char*)result->getAtPos(), src + 6 + *headerLen + 6, *dataLen); 204 result->seek(*headerLen + *dataLen); 205 memcpy((char*)result->getAtPos(), src + 6 + *headerLen + 6 + *dataLen, 206 *trailerLen); 207 result->rewind(); 208 return result; 209 } 210 211 // A PFA has to be converted for PDF. 212 size_t hexDataLen; 213 if (parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen, 214 trailerLen)) { 215 SkMemoryStream* result = 216 new SkMemoryStream(*headerLen + *dataLen + *trailerLen); 217 memcpy((char*)result->getAtPos(), src, *headerLen); 218 result->seek(*headerLen); 219 220 const uint8_t* hexData = src + *headerLen; 221 const uint8_t* trailer = hexData + hexDataLen; 222 size_t outputOffset = 0; 223 uint8_t dataByte = 0; // To hush compiler. 224 bool highNibble = true; 225 for (; hexData < trailer; hexData++) { 226 char curNibble = hexToBin(*hexData); 227 if (curNibble < 0) { 228 continue; 229 } 230 if (highNibble) { 231 dataByte = curNibble << 4; 232 highNibble = false; 233 } else { 234 dataByte |= curNibble; 235 highNibble = true; 236 ((char *)result->getAtPos())[outputOffset++] = dataByte; 237 } 238 } 239 if (!highNibble) { 240 ((char *)result->getAtPos())[outputOffset++] = dataByte; 241 } 242 SkASSERT(outputOffset == *dataLen); 243 result->seek(*headerLen + outputOffset); 244 245 memcpy((char *)result->getAtPos(), src + *headerLen + hexDataLen, 246 *trailerLen); 247 result->rewind(); 248 return result; 249 } 250 251 return NULL; 252 } 253 254 // scale from em-units to base-1000, returning as a SkScalar 255 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { 256 SkScalar scaled = SkIntToScalar(val); 257 if (emSize == 1000) { 258 return scaled; 259 } else { 260 return SkScalarMulDiv(scaled, 1000, emSize); 261 } 262 } 263 264 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, 265 SkWStream* content) { 266 // Specify width and bounding box for the glyph. 267 SkPDFScalar::Append(width, content); 268 content->writeText(" 0 "); 269 content->writeDecAsText(box.fLeft); 270 content->writeText(" "); 271 content->writeDecAsText(box.fTop); 272 content->writeText(" "); 273 content->writeDecAsText(box.fRight); 274 content->writeText(" "); 275 content->writeDecAsText(box.fBottom); 276 content->writeText(" d1\n"); 277 } 278 279 SkPDFArray* makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { 280 SkPDFArray* bbox = new SkPDFArray; 281 bbox->reserve(4); 282 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); 283 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); 284 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); 285 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); 286 return bbox; 287 } 288 289 SkPDFArray* appendWidth(const int16_t& width, uint16_t emSize, 290 SkPDFArray* array) { 291 array->appendScalar(scaleFromFontUnits(width, emSize)); 292 return array; 293 } 294 295 SkPDFArray* appendVerticalAdvance( 296 const SkAdvancedTypefaceMetrics::VerticalMetric& advance, 297 uint16_t emSize, SkPDFArray* array) { 298 appendWidth(advance.fVerticalAdvance, emSize, array); 299 appendWidth(advance.fOriginXDisp, emSize, array); 300 appendWidth(advance.fOriginYDisp, emSize, array); 301 return array; 302 } 303 304 template <typename Data> 305 SkPDFArray* composeAdvanceData( 306 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* advanceInfo, 307 uint16_t emSize, 308 SkPDFArray* (*appendAdvance)(const Data& advance, uint16_t emSize, 309 SkPDFArray* array), 310 Data* defaultAdvance) { 311 SkPDFArray* result = new SkPDFArray(); 312 for (; advanceInfo != NULL; advanceInfo = advanceInfo->fNext.get()) { 313 switch (advanceInfo->fType) { 314 case SkAdvancedTypefaceMetrics::WidthRange::kDefault: { 315 SkASSERT(advanceInfo->fAdvance.count() == 1); 316 *defaultAdvance = advanceInfo->fAdvance[0]; 317 break; 318 } 319 case SkAdvancedTypefaceMetrics::WidthRange::kRange: { 320 SkAutoTUnref<SkPDFArray> advanceArray(new SkPDFArray()); 321 for (int j = 0; j < advanceInfo->fAdvance.count(); j++) 322 appendAdvance(advanceInfo->fAdvance[j], emSize, 323 advanceArray.get()); 324 result->appendInt(advanceInfo->fStartId); 325 result->append(advanceArray.get()); 326 break; 327 } 328 case SkAdvancedTypefaceMetrics::WidthRange::kRun: { 329 SkASSERT(advanceInfo->fAdvance.count() == 1); 330 result->appendInt(advanceInfo->fStartId); 331 result->appendInt(advanceInfo->fEndId); 332 appendAdvance(advanceInfo->fAdvance[0], emSize, result); 333 break; 334 } 335 } 336 } 337 return result; 338 } 339 340 } // namespace 341 342 static void append_tounicode_header(SkDynamicMemoryWStream* cmap) { 343 // 12 dict begin: 12 is an Adobe-suggested value. Shall not change. 344 // It's there to prevent old version Adobe Readers from malfunctioning. 345 const char* kHeader = 346 "/CIDInit /ProcSet findresource begin\n" 347 "12 dict begin\n" 348 "begincmap\n"; 349 cmap->writeText(kHeader); 350 351 // The /CIDSystemInfo must be consistent to the one in 352 // SkPDFFont::populateCIDFont(). 353 // We can not pass over the system info object here because the format is 354 // different. This is not a reference object. 355 const char* kSysInfo = 356 "/CIDSystemInfo\n" 357 "<< /Registry (Adobe)\n" 358 "/Ordering (UCS)\n" 359 "/Supplement 0\n" 360 ">> def\n"; 361 cmap->writeText(kSysInfo); 362 363 // The CMapName must be consistent to /CIDSystemInfo above. 364 // /CMapType 2 means ToUnicode. 365 // We specify codespacerange from 0x0000 to 0xFFFF because we convert our 366 // code table from unsigned short (16-bits). Codespace range just tells the 367 // PDF processor the valid range. It does not matter whether a complete 368 // mapping is provided or not. 369 const char* kTypeInfo = 370 "/CMapName /Adobe-Identity-UCS def\n" 371 "/CMapType 2 def\n" 372 "1 begincodespacerange\n" 373 "<0000> <FFFF>\n" 374 "endcodespacerange\n"; 375 cmap->writeText(kTypeInfo); 376 } 377 378 static void append_cmap_footer(SkDynamicMemoryWStream* cmap) { 379 const char* kFooter = 380 "endcmap\n" 381 "CMapName currentdict /CMap defineresource pop\n" 382 "end\n" 383 "end"; 384 cmap->writeText(kFooter); 385 } 386 387 struct BFChar { 388 uint16_t fGlyphId; 389 SkUnichar fUnicode; 390 }; 391 392 struct BFRange { 393 uint16_t fStart; 394 uint16_t fEnd; 395 SkUnichar fUnicode; 396 }; 397 398 static void append_bfchar_section(const SkTDArray<BFChar>& bfchar, 399 SkDynamicMemoryWStream* cmap) { 400 // PDF spec defines that every bf* list can have at most 100 entries. 401 for (int i = 0; i < bfchar.count(); i += 100) { 402 int count = bfchar.count() - i; 403 count = SkMin32(count, 100); 404 cmap->writeDecAsText(count); 405 cmap->writeText(" beginbfchar\n"); 406 for (int j = 0; j < count; ++j) { 407 cmap->writeText("<"); 408 cmap->writeHexAsText(bfchar[i + j].fGlyphId, 4); 409 cmap->writeText("> <"); 410 cmap->writeHexAsText(bfchar[i + j].fUnicode, 4); 411 cmap->writeText(">\n"); 412 } 413 cmap->writeText("endbfchar\n"); 414 } 415 } 416 417 static void append_bfrange_section(const SkTDArray<BFRange>& bfrange, 418 SkDynamicMemoryWStream* cmap) { 419 // PDF spec defines that every bf* list can have at most 100 entries. 420 for (int i = 0; i < bfrange.count(); i += 100) { 421 int count = bfrange.count() - i; 422 count = SkMin32(count, 100); 423 cmap->writeDecAsText(count); 424 cmap->writeText(" beginbfrange\n"); 425 for (int j = 0; j < count; ++j) { 426 cmap->writeText("<"); 427 cmap->writeHexAsText(bfrange[i + j].fStart, 4); 428 cmap->writeText("> <"); 429 cmap->writeHexAsText(bfrange[i + j].fEnd, 4); 430 cmap->writeText("> <"); 431 cmap->writeHexAsText(bfrange[i + j].fUnicode, 4); 432 cmap->writeText(">\n"); 433 } 434 cmap->writeText("endbfrange\n"); 435 } 436 } 437 438 // Generate <bfchar> and <bfrange> table according to PDF spec 1.4 and Adobe 439 // Technote 5014. 440 // The function is not static so we can test it in unit tests. 441 // 442 // Current implementation guarantees bfchar and bfrange entries do not overlap. 443 // 444 // Current implementation does not attempt aggresive optimizations against 445 // following case because the specification is not clear. 446 // 447 // 4 beginbfchar 1 beginbfchar 448 // <0003> <0013> <0020> <0014> 449 // <0005> <0015> to endbfchar 450 // <0007> <0017> 1 beginbfrange 451 // <0020> <0014> <0003> <0007> <0013> 452 // endbfchar endbfrange 453 // 454 // Adobe Technote 5014 said: "Code mappings (unlike codespace ranges) may 455 // overlap, but succeeding maps superceded preceding maps." 456 // 457 // In case of searching text in PDF, bfrange will have higher precedence so 458 // typing char id 0x0014 in search box will get glyph id 0x0004 first. However, 459 // the spec does not mention how will this kind of conflict being resolved. 460 // 461 // For the worst case (having 65536 continuous unicode and we use every other 462 // one of them), the possible savings by aggressive optimization is 416KB 463 // pre-compressed and does not provide enough motivation for implementation. 464 465 // FIXME: this should be in a header so that it is separately testable 466 // ( see caller in tests/ToUnicode.cpp ) 467 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 468 const SkPDFGlyphSet* subset, 469 SkDynamicMemoryWStream* cmap); 470 471 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 472 const SkPDFGlyphSet* subset, 473 SkDynamicMemoryWStream* cmap) { 474 if (glyphToUnicode.isEmpty()) { 475 return; 476 } 477 478 SkTDArray<BFChar> bfcharEntries; 479 SkTDArray<BFRange> bfrangeEntries; 480 481 BFRange currentRangeEntry = {0, 0, 0}; 482 bool rangeEmpty = true; 483 const int count = glyphToUnicode.count(); 484 485 for (int i = 0; i < count + 1; ++i) { 486 bool inSubset = i < count && (subset == NULL || subset->has(i)); 487 if (!rangeEmpty) { 488 // PDF spec requires bfrange not changing the higher byte, 489 // e.g. <1035> <10FF> <2222> is ok, but 490 // <1035> <1100> <2222> is no good 491 bool inRange = 492 i == currentRangeEntry.fEnd + 1 && 493 i >> 8 == currentRangeEntry.fStart >> 8 && 494 i < count && 495 glyphToUnicode[i] == currentRangeEntry.fUnicode + i - 496 currentRangeEntry.fStart; 497 if (!inSubset || !inRange) { 498 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) { 499 bfrangeEntries.push(currentRangeEntry); 500 } else { 501 BFChar* entry = bfcharEntries.append(); 502 entry->fGlyphId = currentRangeEntry.fStart; 503 entry->fUnicode = currentRangeEntry.fUnicode; 504 } 505 rangeEmpty = true; 506 } 507 } 508 if (inSubset) { 509 currentRangeEntry.fEnd = i; 510 if (rangeEmpty) { 511 currentRangeEntry.fStart = i; 512 currentRangeEntry.fUnicode = glyphToUnicode[i]; 513 rangeEmpty = false; 514 } 515 } 516 } 517 518 // The spec requires all bfchar entries for a font must come before bfrange 519 // entries. 520 append_bfchar_section(bfcharEntries, cmap); 521 append_bfrange_section(bfrangeEntries, cmap); 522 } 523 524 static SkPDFStream* generate_tounicode_cmap( 525 const SkTDArray<SkUnichar>& glyphToUnicode, 526 const SkPDFGlyphSet* subset) { 527 SkDynamicMemoryWStream cmap; 528 append_tounicode_header(&cmap); 529 append_cmap_sections(glyphToUnicode, subset, &cmap); 530 append_cmap_footer(&cmap); 531 SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream()); 532 cmapStream->setData(cmap.copyToData())->unref(); 533 return new SkPDFStream(cmapStream.get()); 534 } 535 536 #if defined (SK_SFNTLY_SUBSETTER) 537 static void sk_delete_array(const void* ptr, size_t, void*) { 538 // Use C-style cast to cast away const and cast type simultaneously. 539 delete[] (unsigned char*)ptr; 540 } 541 #endif 542 543 static int get_subset_font_stream(const char* fontName, 544 const SkTypeface* typeface, 545 const SkTDArray<uint32_t>& subset, 546 SkPDFStream** fontStream) { 547 SkAutoTUnref<SkStream> fontData( 548 SkFontHost::OpenStream(SkTypeface::UniqueID(typeface))); 549 550 int fontSize = fontData->getLength(); 551 552 #if defined (SK_SFNTLY_SUBSETTER) 553 // Read font into buffer. 554 SkPDFStream* subsetFontStream = NULL; 555 SkTDArray<unsigned char> originalFont; 556 originalFont.setCount(fontSize); 557 if (fontData->read(originalFont.begin(), fontSize) == (size_t)fontSize) { 558 unsigned char* subsetFont = NULL; 559 // sfntly requires unsigned int* to be passed in, as far as we know, 560 // unsigned int is equivalent to uint32_t on all platforms. 561 SK_COMPILE_ASSERT(sizeof(unsigned int) == sizeof(uint32_t), 562 unsigned_int_not_32_bits); 563 int subsetFontSize = SfntlyWrapper::SubsetFont(fontName, 564 originalFont.begin(), 565 fontSize, 566 subset.begin(), 567 subset.count(), 568 &subsetFont); 569 if (subsetFontSize > 0 && subsetFont != NULL) { 570 SkAutoDataUnref data(SkData::NewWithProc(subsetFont, 571 subsetFontSize, 572 sk_delete_array, 573 NULL)); 574 subsetFontStream = new SkPDFStream(data.get()); 575 fontSize = subsetFontSize; 576 } 577 } 578 if (subsetFontStream) { 579 *fontStream = subsetFontStream; 580 return fontSize; 581 } 582 #endif 583 584 // Fail over: just embed the whole font. 585 *fontStream = new SkPDFStream(fontData.get()); 586 return fontSize; 587 } 588 589 /////////////////////////////////////////////////////////////////////////////// 590 // class SkPDFGlyphSet 591 /////////////////////////////////////////////////////////////////////////////// 592 593 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { 594 } 595 596 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { 597 for (int i = 0; i < numGlyphs; ++i) { 598 fBitSet.setBit(glyphIDs[i], true); 599 } 600 } 601 602 bool SkPDFGlyphSet::has(uint16_t glyphID) const { 603 return fBitSet.isBitSet(glyphID); 604 } 605 606 void SkPDFGlyphSet::merge(const SkPDFGlyphSet& usage) { 607 fBitSet.orBits(usage.fBitSet); 608 } 609 610 void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const { 611 fBitSet.exportTo(glyphIDs); 612 } 613 614 /////////////////////////////////////////////////////////////////////////////// 615 // class SkPDFGlyphSetMap 616 /////////////////////////////////////////////////////////////////////////////// 617 SkPDFGlyphSetMap::FontGlyphSetPair::FontGlyphSetPair(SkPDFFont* font, 618 SkPDFGlyphSet* glyphSet) 619 : fFont(font), 620 fGlyphSet(glyphSet) { 621 } 622 623 SkPDFGlyphSetMap::F2BIter::F2BIter(const SkPDFGlyphSetMap& map) { 624 reset(map); 625 } 626 627 SkPDFGlyphSetMap::FontGlyphSetPair* SkPDFGlyphSetMap::F2BIter::next() const { 628 if (fIndex >= fMap->count()) { 629 return NULL; 630 } 631 return &((*fMap)[fIndex++]); 632 } 633 634 void SkPDFGlyphSetMap::F2BIter::reset(const SkPDFGlyphSetMap& map) { 635 fMap = &(map.fMap); 636 fIndex = 0; 637 } 638 639 SkPDFGlyphSetMap::SkPDFGlyphSetMap() { 640 } 641 642 SkPDFGlyphSetMap::~SkPDFGlyphSetMap() { 643 reset(); 644 } 645 646 void SkPDFGlyphSetMap::merge(const SkPDFGlyphSetMap& usage) { 647 for (int i = 0; i < usage.fMap.count(); ++i) { 648 SkPDFGlyphSet* myUsage = getGlyphSetForFont(usage.fMap[i].fFont); 649 myUsage->merge(*(usage.fMap[i].fGlyphSet)); 650 } 651 } 652 653 void SkPDFGlyphSetMap::reset() { 654 for (int i = 0; i < fMap.count(); ++i) { 655 delete fMap[i].fGlyphSet; // Should not be NULL. 656 } 657 fMap.reset(); 658 } 659 660 void SkPDFGlyphSetMap::noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs, 661 int numGlyphs) { 662 SkPDFGlyphSet* subset = getGlyphSetForFont(font); 663 if (subset) { 664 subset->set(glyphIDs, numGlyphs); 665 } 666 } 667 668 SkPDFGlyphSet* SkPDFGlyphSetMap::getGlyphSetForFont(SkPDFFont* font) { 669 int index = fMap.count(); 670 for (int i = 0; i < index; ++i) { 671 if (fMap[i].fFont == font) { 672 return fMap[i].fGlyphSet; 673 } 674 } 675 fMap.append(); 676 index = fMap.count() - 1; 677 fMap[index].fFont = font; 678 fMap[index].fGlyphSet = new SkPDFGlyphSet(); 679 return fMap[index].fGlyphSet; 680 } 681 682 /////////////////////////////////////////////////////////////////////////////// 683 // class SkPDFFont 684 /////////////////////////////////////////////////////////////////////////////// 685 686 /* Font subset design: It would be nice to be able to subset fonts 687 * (particularly type 3 fonts), but it's a lot of work and not a priority. 688 * 689 * Resources are canonicalized and uniqueified by pointer so there has to be 690 * some additional state indicating which subset of the font is used. It 691 * must be maintained at the page granularity and then combined at the document 692 * granularity. a) change SkPDFFont to fill in its state on demand, kind of 693 * like SkPDFGraphicState. b) maintain a per font glyph usage class in each 694 * page/pdf device. c) in the document, retrieve the per font glyph usage 695 * from each page and combine it and ask for a resource with that subset. 696 */ 697 698 SkPDFFont::~SkPDFFont() { 699 SkAutoMutexAcquire lock(CanonicalFontsMutex()); 700 int index = -1; 701 for (int i = 0 ; i < CanonicalFonts().count() ; i++) { 702 if (CanonicalFonts()[i].fFont == this) { 703 index = i; 704 } 705 } 706 707 SkDEBUGCODE(int indexFound;) 708 SkASSERT(index == -1 || 709 (Find(SkTypeface::UniqueID(fTypeface.get()), 710 fFirstGlyphID, 711 &indexFound) && 712 index == indexFound)); 713 if (index >= 0) { 714 CanonicalFonts().removeShuffle(index); 715 } 716 fResources.unrefAll(); 717 } 718 719 void SkPDFFont::getResources(SkTDArray<SkPDFObject*>* resourceList) { 720 GetResourcesHelper(&fResources, resourceList); 721 } 722 723 SkTypeface* SkPDFFont::typeface() { 724 return fTypeface.get(); 725 } 726 727 SkAdvancedTypefaceMetrics::FontType SkPDFFont::getType() { 728 return fFontType; 729 } 730 731 bool SkPDFFont::hasGlyph(uint16_t id) { 732 return (id >= fFirstGlyphID && id <= fLastGlyphID) || id == 0; 733 } 734 735 size_t SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs, 736 size_t numGlyphs) { 737 // A font with multibyte glyphs will support all glyph IDs in a single font. 738 if (this->multiByteGlyphs()) { 739 return numGlyphs; 740 } 741 742 for (size_t i = 0; i < numGlyphs; i++) { 743 if (glyphIDs[i] == 0) { 744 continue; 745 } 746 if (glyphIDs[i] < fFirstGlyphID || glyphIDs[i] > fLastGlyphID) { 747 return i; 748 } 749 glyphIDs[i] -= (fFirstGlyphID - 1); 750 } 751 752 return numGlyphs; 753 } 754 755 // static 756 SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) { 757 SkAutoMutexAcquire lock(CanonicalFontsMutex()); 758 const uint32_t fontID = SkTypeface::UniqueID(typeface); 759 int relatedFontIndex; 760 if (Find(fontID, glyphID, &relatedFontIndex)) { 761 CanonicalFonts()[relatedFontIndex].fFont->ref(); 762 return CanonicalFonts()[relatedFontIndex].fFont; 763 } 764 765 SkAutoTUnref<SkAdvancedTypefaceMetrics> fontMetrics; 766 SkPDFDict* relatedFontDescriptor = NULL; 767 if (relatedFontIndex >= 0) { 768 SkPDFFont* relatedFont = CanonicalFonts()[relatedFontIndex].fFont; 769 fontMetrics.reset(relatedFont->fontInfo()); 770 SkSafeRef(fontMetrics.get()); 771 relatedFontDescriptor = relatedFont->getFontDescriptor(); 772 773 // This only is to catch callers who pass invalid glyph ids. 774 // If glyph id is invalid, then we will create duplicate entries 775 // for True Type fonts. 776 SkAdvancedTypefaceMetrics::FontType fontType = 777 fontMetrics.get() ? fontMetrics.get()->fType : 778 SkAdvancedTypefaceMetrics::kOther_Font; 779 780 if (fontType == SkAdvancedTypefaceMetrics::kType1CID_Font || 781 fontType == SkAdvancedTypefaceMetrics::kTrueType_Font) { 782 CanonicalFonts()[relatedFontIndex].fFont->ref(); 783 return CanonicalFonts()[relatedFontIndex].fFont; 784 } 785 } else { 786 SkAdvancedTypefaceMetrics::PerGlyphInfo info; 787 info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo; 788 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( 789 info, SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo); 790 #if !defined (SK_SFNTLY_SUBSETTER) 791 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( 792 info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); 793 #endif 794 fontMetrics.reset( 795 SkFontHost::GetAdvancedTypefaceMetrics(fontID, info, NULL, 0)); 796 #if defined (SK_SFNTLY_SUBSETTER) 797 if (fontMetrics.get() && 798 fontMetrics->fType != SkAdvancedTypefaceMetrics::kTrueType_Font) { 799 // Font does not support subsetting, get new info with advance. 800 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( 801 info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); 802 fontMetrics.reset( 803 SkFontHost::GetAdvancedTypefaceMetrics(fontID, info, NULL, 0)); 804 } 805 #endif 806 } 807 808 SkPDFFont* font = Create(fontMetrics.get(), typeface, glyphID, 809 relatedFontDescriptor); 810 FontRec newEntry(font, fontID, font->fFirstGlyphID); 811 CanonicalFonts().push(newEntry); 812 return font; // Return the reference new SkPDFFont() created. 813 } 814 815 SkPDFFont* SkPDFFont::getFontSubset(const SkPDFGlyphSet* usage) { 816 return NULL; // Default: no support. 817 } 818 819 // static 820 SkTDArray<SkPDFFont::FontRec>& SkPDFFont::CanonicalFonts() { 821 // This initialization is only thread safe with gcc. 822 static SkTDArray<FontRec> gCanonicalFonts; 823 return gCanonicalFonts; 824 } 825 826 // static 827 SkBaseMutex& SkPDFFont::CanonicalFontsMutex() { 828 // This initialization is only thread safe with gcc, or when 829 // POD-style mutex initialization is used. 830 SK_DECLARE_STATIC_MUTEX(gCanonicalFontsMutex); 831 return gCanonicalFontsMutex; 832 } 833 834 // static 835 bool SkPDFFont::Find(uint32_t fontID, uint16_t glyphID, int* index) { 836 // TODO(vandebo): Optimize this, do only one search? 837 FontRec search(NULL, fontID, glyphID); 838 *index = CanonicalFonts().find(search); 839 if (*index >= 0) { 840 return true; 841 } 842 search.fGlyphID = 0; 843 *index = CanonicalFonts().find(search); 844 return false; 845 } 846 847 SkPDFFont::SkPDFFont(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, 848 uint16_t glyphID, bool descendantFont) 849 : SkPDFDict("Font"), 850 fTypeface(typeface), 851 fFirstGlyphID(1), 852 fLastGlyphID(info ? info->fLastGlyphID : 0), 853 fFontInfo(info) { 854 SkSafeRef(typeface); 855 SkSafeRef(info); 856 if (info == NULL) { 857 fFontType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 858 } else if (info->fMultiMaster) { 859 fFontType = SkAdvancedTypefaceMetrics::kOther_Font; 860 } else { 861 fFontType = info->fType; 862 } 863 } 864 865 // static 866 SkPDFFont* SkPDFFont::Create(SkAdvancedTypefaceMetrics* info, 867 SkTypeface* typeface, uint16_t glyphID, 868 SkPDFDict* relatedFontDescriptor) { 869 SkAdvancedTypefaceMetrics::FontType type = 870 info ? info->fType : SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 871 872 if (info && info->fMultiMaster) { 873 NOT_IMPLEMENTED(true, true); 874 return new SkPDFType3Font(info, 875 typeface, 876 glyphID, 877 relatedFontDescriptor); 878 } 879 if (type == SkAdvancedTypefaceMetrics::kType1CID_Font || 880 type == SkAdvancedTypefaceMetrics::kTrueType_Font) { 881 SkASSERT(relatedFontDescriptor == NULL); 882 return new SkPDFType0Font(info, typeface); 883 } 884 if (type == SkAdvancedTypefaceMetrics::kType1_Font) { 885 return new SkPDFType1Font(info, 886 typeface, 887 glyphID, 888 relatedFontDescriptor); 889 } 890 891 SkASSERT(type == SkAdvancedTypefaceMetrics::kCFF_Font || 892 type == SkAdvancedTypefaceMetrics::kOther_Font || 893 type == SkAdvancedTypefaceMetrics::kNotEmbeddable_Font); 894 895 return new SkPDFType3Font(info, typeface, glyphID, relatedFontDescriptor); 896 } 897 898 SkAdvancedTypefaceMetrics* SkPDFFont::fontInfo() { 899 return fFontInfo.get(); 900 } 901 902 void SkPDFFont::setFontInfo(SkAdvancedTypefaceMetrics* info) { 903 if (info == NULL || info == fFontInfo.get()) { 904 return; 905 } 906 fFontInfo.reset(info); 907 SkSafeRef(info); 908 } 909 910 uint16_t SkPDFFont::firstGlyphID() const { 911 return fFirstGlyphID; 912 } 913 914 uint16_t SkPDFFont::lastGlyphID() const { 915 return fLastGlyphID; 916 } 917 918 void SkPDFFont::setLastGlyphID(uint16_t glyphID) { 919 fLastGlyphID = glyphID; 920 } 921 922 void SkPDFFont::addResource(SkPDFObject* object) { 923 SkASSERT(object != NULL); 924 fResources.push(object); 925 object->ref(); 926 } 927 928 SkPDFDict* SkPDFFont::getFontDescriptor() { 929 return fDescriptor.get(); 930 } 931 932 void SkPDFFont::setFontDescriptor(SkPDFDict* descriptor) { 933 fDescriptor.reset(descriptor); 934 SkSafeRef(descriptor); 935 } 936 937 bool SkPDFFont::addCommonFontDescriptorEntries(int16_t defaultWidth) { 938 if (fDescriptor.get() == NULL) { 939 return false; 940 } 941 942 const uint16_t emSize = fFontInfo->fEmSize; 943 944 fDescriptor->insertName("FontName", fFontInfo->fFontName); 945 fDescriptor->insertInt("Flags", fFontInfo->fStyle); 946 fDescriptor->insertScalar("Ascent", 947 scaleFromFontUnits(fFontInfo->fAscent, emSize)); 948 fDescriptor->insertScalar("Descent", 949 scaleFromFontUnits(fFontInfo->fDescent, emSize)); 950 fDescriptor->insertScalar("StemV", 951 scaleFromFontUnits(fFontInfo->fStemV, emSize)); 952 fDescriptor->insertScalar("CapHeight", 953 scaleFromFontUnits(fFontInfo->fCapHeight, emSize)); 954 fDescriptor->insertInt("ItalicAngle", fFontInfo->fItalicAngle); 955 fDescriptor->insert("FontBBox", makeFontBBox(fFontInfo->fBBox, 956 fFontInfo->fEmSize))->unref(); 957 958 if (defaultWidth > 0) { 959 fDescriptor->insertScalar("MissingWidth", 960 scaleFromFontUnits(defaultWidth, emSize)); 961 } 962 return true; 963 } 964 965 void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(int16_t glyphID) { 966 // Single byte glyph encoding supports a max of 255 glyphs. 967 fFirstGlyphID = glyphID - (glyphID - 1) % 255; 968 if (fLastGlyphID > fFirstGlyphID + 255 - 1) { 969 fLastGlyphID = fFirstGlyphID + 255 - 1; 970 } 971 } 972 973 bool SkPDFFont::FontRec::operator==(const SkPDFFont::FontRec& b) const { 974 if (fFontID != b.fFontID) { 975 return false; 976 } 977 if (fFont != NULL && b.fFont != NULL) { 978 return fFont->fFirstGlyphID == b.fFont->fFirstGlyphID && 979 fFont->fLastGlyphID == b.fFont->fLastGlyphID; 980 } 981 if (fGlyphID == 0 || b.fGlyphID == 0) { 982 return true; 983 } 984 985 if (fFont != NULL) { 986 return fFont->fFirstGlyphID <= b.fGlyphID && 987 b.fGlyphID <= fFont->fLastGlyphID; 988 } else if (b.fFont != NULL) { 989 return b.fFont->fFirstGlyphID <= fGlyphID && 990 fGlyphID <= b.fFont->fLastGlyphID; 991 } 992 return fGlyphID == b.fGlyphID; 993 } 994 995 SkPDFFont::FontRec::FontRec(SkPDFFont* font, uint32_t fontID, uint16_t glyphID) 996 : fFont(font), 997 fFontID(fontID), 998 fGlyphID(glyphID) { 999 } 1000 1001 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { 1002 if (fFontInfo == NULL || fFontInfo->fGlyphToUnicode.begin() == NULL) { 1003 return; 1004 } 1005 SkAutoTUnref<SkPDFStream> pdfCmap( 1006 generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset)); 1007 addResource(pdfCmap.get()); 1008 insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref(); 1009 } 1010 1011 /////////////////////////////////////////////////////////////////////////////// 1012 // class SkPDFType0Font 1013 /////////////////////////////////////////////////////////////////////////////// 1014 1015 SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info, 1016 SkTypeface* typeface) 1017 : SkPDFFont(info, typeface, 0, false) { 1018 SkDEBUGCODE(fPopulated = false); 1019 } 1020 1021 SkPDFType0Font::~SkPDFType0Font() {} 1022 1023 SkPDFFont* SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) { 1024 SkPDFType0Font* newSubset = new SkPDFType0Font(fontInfo(), typeface()); 1025 newSubset->populate(subset); 1026 return newSubset; 1027 } 1028 1029 #ifdef SK_DEBUG 1030 void SkPDFType0Font::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 1031 bool indirect) { 1032 SkASSERT(fPopulated); 1033 return INHERITED::emitObject(stream, catalog, indirect); 1034 } 1035 #endif 1036 1037 bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) { 1038 insertName("Subtype", "Type0"); 1039 insertName("BaseFont", fontInfo()->fFontName); 1040 insertName("Encoding", "Identity-H"); 1041 1042 SkAutoTUnref<SkPDFCIDFont> newCIDFont( 1043 new SkPDFCIDFont(fontInfo(), typeface(), subset)); 1044 addResource(newCIDFont.get()); 1045 SkAutoTUnref<SkPDFArray> descendantFonts(new SkPDFArray()); 1046 descendantFonts->append(new SkPDFObjRef(newCIDFont.get()))->unref(); 1047 insert("DescendantFonts", descendantFonts.get()); 1048 1049 populateToUnicodeTable(subset); 1050 1051 SkDEBUGCODE(fPopulated = true); 1052 return true; 1053 } 1054 1055 /////////////////////////////////////////////////////////////////////////////// 1056 // class SkPDFCIDFont 1057 /////////////////////////////////////////////////////////////////////////////// 1058 1059 SkPDFCIDFont::SkPDFCIDFont(SkAdvancedTypefaceMetrics* info, 1060 SkTypeface* typeface, const SkPDFGlyphSet* subset) 1061 : SkPDFFont(info, typeface, 0, true) { 1062 populate(subset); 1063 } 1064 1065 SkPDFCIDFont::~SkPDFCIDFont() {} 1066 1067 bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, 1068 const SkTDArray<uint32_t>* subset) { 1069 SkAutoTUnref<SkPDFDict> descriptor(new SkPDFDict("FontDescriptor")); 1070 setFontDescriptor(descriptor.get()); 1071 addResource(descriptor.get()); 1072 1073 switch (getType()) { 1074 case SkAdvancedTypefaceMetrics::kTrueType_Font: { 1075 SkASSERT(subset); 1076 // Font subsetting 1077 SkPDFStream* rawStream = NULL; 1078 int fontSize = get_subset_font_stream(fontInfo()->fFontName.c_str(), 1079 typeface(), 1080 *subset, 1081 &rawStream); 1082 SkASSERT(fontSize); 1083 SkASSERT(rawStream); 1084 SkAutoTUnref<SkPDFStream> fontStream(rawStream); 1085 addResource(fontStream.get()); 1086 1087 fontStream->insertInt("Length1", fontSize); 1088 descriptor->insert("FontFile2", 1089 new SkPDFObjRef(fontStream.get()))->unref(); 1090 break; 1091 } 1092 case SkAdvancedTypefaceMetrics::kCFF_Font: 1093 case SkAdvancedTypefaceMetrics::kType1CID_Font: { 1094 SkAutoTUnref<SkStream> fontData( 1095 SkFontHost::OpenStream(SkTypeface::UniqueID(typeface()))); 1096 SkAutoTUnref<SkPDFStream> fontStream( 1097 new SkPDFStream(fontData.get())); 1098 addResource(fontStream.get()); 1099 1100 if (getType() == SkAdvancedTypefaceMetrics::kCFF_Font) { 1101 fontStream->insertName("Subtype", "Type1C"); 1102 } else { 1103 fontStream->insertName("Subtype", "CIDFontType0c"); 1104 } 1105 descriptor->insert("FontFile3", 1106 new SkPDFObjRef(fontStream.get()))->unref(); 1107 break; 1108 } 1109 default: 1110 SkASSERT(false); 1111 } 1112 1113 insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref(); 1114 return addCommonFontDescriptorEntries(defaultWidth); 1115 } 1116 1117 bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { 1118 // Generate new font metrics with advance info for true type fonts. 1119 if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) { 1120 // Generate glyph id array. 1121 SkTDArray<uint32_t> glyphIDs; 1122 glyphIDs.push(0); // Always include glyph 0. 1123 if (subset) { 1124 subset->exportTo(&glyphIDs); 1125 } 1126 1127 SkAdvancedTypefaceMetrics::PerGlyphInfo info; 1128 info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo; 1129 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( 1130 info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); 1131 uint32_t* glyphs = (glyphIDs.count() == 1) ? NULL : glyphIDs.begin(); 1132 uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0; 1133 SkAutoTUnref<SkAdvancedTypefaceMetrics> fontMetrics( 1134 SkFontHost::GetAdvancedTypefaceMetrics( 1135 SkTypeface::UniqueID(typeface()), 1136 info, 1137 glyphs, 1138 glyphsCount)); 1139 setFontInfo(fontMetrics.get()); 1140 addFontDescriptor(0, &glyphIDs); 1141 } else { 1142 // Other CID fonts 1143 addFontDescriptor(0, NULL); 1144 } 1145 1146 insertName("BaseFont", fontInfo()->fFontName); 1147 1148 if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) { 1149 insertName("Subtype", "CIDFontType0"); 1150 } else if (getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) { 1151 insertName("Subtype", "CIDFontType2"); 1152 insertName("CIDToGIDMap", "Identity"); 1153 } else { 1154 SkASSERT(false); 1155 } 1156 1157 SkAutoTUnref<SkPDFDict> sysInfo(new SkPDFDict); 1158 sysInfo->insert("Registry", new SkPDFString("Adobe"))->unref(); 1159 sysInfo->insert("Ordering", new SkPDFString("Identity"))->unref(); 1160 sysInfo->insertInt("Supplement", 0); 1161 insert("CIDSystemInfo", sysInfo.get()); 1162 1163 if (fontInfo()->fGlyphWidths.get()) { 1164 int16_t defaultWidth = 0; 1165 SkAutoTUnref<SkPDFArray> widths( 1166 composeAdvanceData(fontInfo()->fGlyphWidths.get(), 1167 fontInfo()->fEmSize, &appendWidth, 1168 &defaultWidth)); 1169 if (widths->size()) 1170 insert("W", widths.get()); 1171 if (defaultWidth != 0) { 1172 insertScalar("DW", scaleFromFontUnits(defaultWidth, 1173 fontInfo()->fEmSize)); 1174 } 1175 } 1176 if (fontInfo()->fVerticalMetrics.get()) { 1177 struct SkAdvancedTypefaceMetrics::VerticalMetric defaultAdvance; 1178 defaultAdvance.fVerticalAdvance = 0; 1179 defaultAdvance.fOriginXDisp = 0; 1180 defaultAdvance.fOriginYDisp = 0; 1181 SkAutoTUnref<SkPDFArray> advances( 1182 composeAdvanceData(fontInfo()->fVerticalMetrics.get(), 1183 fontInfo()->fEmSize, &appendVerticalAdvance, 1184 &defaultAdvance)); 1185 if (advances->size()) 1186 insert("W2", advances.get()); 1187 if (defaultAdvance.fVerticalAdvance || 1188 defaultAdvance.fOriginXDisp || 1189 defaultAdvance.fOriginYDisp) { 1190 insert("DW2", appendVerticalAdvance(defaultAdvance, 1191 fontInfo()->fEmSize, 1192 new SkPDFArray))->unref(); 1193 } 1194 } 1195 1196 return true; 1197 } 1198 1199 /////////////////////////////////////////////////////////////////////////////// 1200 // class SkPDFType1Font 1201 /////////////////////////////////////////////////////////////////////////////// 1202 1203 SkPDFType1Font::SkPDFType1Font(SkAdvancedTypefaceMetrics* info, 1204 SkTypeface* typeface, 1205 uint16_t glyphID, 1206 SkPDFDict* relatedFontDescriptor) 1207 : SkPDFFont(info, typeface, glyphID, false) { 1208 populate(glyphID); 1209 } 1210 1211 SkPDFType1Font::~SkPDFType1Font() {} 1212 1213 bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) { 1214 if (getFontDescriptor() != NULL) { 1215 SkPDFDict* descriptor = getFontDescriptor(); 1216 addResource(descriptor); 1217 insert("FontDescriptor", new SkPDFObjRef(descriptor))->unref(); 1218 return true; 1219 } 1220 1221 SkAutoTUnref<SkPDFDict> descriptor(new SkPDFDict("FontDescriptor")); 1222 setFontDescriptor(descriptor.get()); 1223 1224 size_t header SK_INIT_TO_AVOID_WARNING; 1225 size_t data SK_INIT_TO_AVOID_WARNING; 1226 size_t trailer SK_INIT_TO_AVOID_WARNING; 1227 SkAutoTUnref<SkStream> rawFontData( 1228 SkFontHost::OpenStream(SkTypeface::UniqueID(typeface()))); 1229 SkStream* fontData = handleType1Stream(rawFontData.get(), &header, &data, 1230 &trailer); 1231 if (fontData == NULL) { 1232 return false; 1233 } 1234 SkAutoTUnref<SkPDFStream> fontStream(new SkPDFStream(fontData)); 1235 addResource(fontStream.get()); 1236 fontStream->insertInt("Length1", header); 1237 fontStream->insertInt("Length2", data); 1238 fontStream->insertInt("Length3", trailer); 1239 descriptor->insert("FontFile", new SkPDFObjRef(fontStream.get()))->unref(); 1240 1241 addResource(descriptor.get()); 1242 insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref(); 1243 1244 return addCommonFontDescriptorEntries(defaultWidth); 1245 } 1246 1247 bool SkPDFType1Font::populate(int16_t glyphID) { 1248 SkASSERT(!fontInfo()->fVerticalMetrics.get()); 1249 SkASSERT(fontInfo()->fGlyphWidths.get()); 1250 1251 adjustGlyphRangeForSingleByteEncoding(glyphID); 1252 1253 int16_t defaultWidth = 0; 1254 const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry = NULL; 1255 const SkAdvancedTypefaceMetrics::WidthRange* widthEntry; 1256 for (widthEntry = fontInfo()->fGlyphWidths.get(); 1257 widthEntry != NULL; 1258 widthEntry = widthEntry->fNext.get()) { 1259 switch (widthEntry->fType) { 1260 case SkAdvancedTypefaceMetrics::WidthRange::kDefault: 1261 defaultWidth = widthEntry->fAdvance[0]; 1262 break; 1263 case SkAdvancedTypefaceMetrics::WidthRange::kRun: 1264 SkASSERT(false); 1265 break; 1266 case SkAdvancedTypefaceMetrics::WidthRange::kRange: 1267 SkASSERT(widthRangeEntry == NULL); 1268 widthRangeEntry = widthEntry; 1269 break; 1270 } 1271 } 1272 1273 if (!addFontDescriptor(defaultWidth)) { 1274 return false; 1275 } 1276 1277 insertName("Subtype", "Type1"); 1278 insertName("BaseFont", fontInfo()->fFontName); 1279 1280 addWidthInfoFromRange(defaultWidth, widthRangeEntry); 1281 1282 SkAutoTUnref<SkPDFDict> encoding(new SkPDFDict("Encoding")); 1283 insert("Encoding", encoding.get()); 1284 1285 SkAutoTUnref<SkPDFArray> encDiffs(new SkPDFArray); 1286 encoding->insert("Differences", encDiffs.get()); 1287 1288 encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); 1289 encDiffs->appendInt(1); 1290 for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { 1291 encDiffs->appendName(fontInfo()->fGlyphNames->get()[gID].c_str()); 1292 } 1293 1294 return true; 1295 } 1296 1297 void SkPDFType1Font::addWidthInfoFromRange( 1298 int16_t defaultWidth, 1299 const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry) { 1300 SkAutoTUnref<SkPDFArray> widthArray(new SkPDFArray()); 1301 int firstChar = 0; 1302 if (widthRangeEntry) { 1303 const uint16_t emSize = fontInfo()->fEmSize; 1304 int startIndex = firstGlyphID() - widthRangeEntry->fStartId; 1305 int endIndex = startIndex + lastGlyphID() - firstGlyphID() + 1; 1306 if (startIndex < 0) 1307 startIndex = 0; 1308 if (endIndex > widthRangeEntry->fAdvance.count()) 1309 endIndex = widthRangeEntry->fAdvance.count(); 1310 if (widthRangeEntry->fStartId == 0) { 1311 appendWidth(widthRangeEntry->fAdvance[0], emSize, widthArray.get()); 1312 } else { 1313 firstChar = startIndex + widthRangeEntry->fStartId; 1314 } 1315 for (int i = startIndex; i < endIndex; i++) { 1316 appendWidth(widthRangeEntry->fAdvance[i], emSize, widthArray.get()); 1317 } 1318 } else { 1319 appendWidth(defaultWidth, 1000, widthArray.get()); 1320 } 1321 insertInt("FirstChar", firstChar); 1322 insertInt("LastChar", firstChar + widthArray->size() - 1); 1323 insert("Widths", widthArray.get()); 1324 } 1325 1326 /////////////////////////////////////////////////////////////////////////////// 1327 // class SkPDFType3Font 1328 /////////////////////////////////////////////////////////////////////////////// 1329 1330 SkPDFType3Font::SkPDFType3Font(SkAdvancedTypefaceMetrics* info, 1331 SkTypeface* typeface, 1332 uint16_t glyphID, 1333 SkPDFDict* relatedFontDescriptor) 1334 : SkPDFFont(info, typeface, glyphID, false) { 1335 populate(glyphID); 1336 } 1337 1338 SkPDFType3Font::~SkPDFType3Font() {} 1339 1340 bool SkPDFType3Font::populate(int16_t glyphID) { 1341 SkPaint paint; 1342 paint.setTypeface(typeface()); 1343 paint.setTextSize(1000); 1344 SkAutoGlyphCache autoCache(paint, NULL, NULL); 1345 SkGlyphCache* cache = autoCache.getCache(); 1346 // If fLastGlyphID isn't set (because there is not fFontInfo), look it up. 1347 if (lastGlyphID() == 0) { 1348 setLastGlyphID(cache->getGlyphCount() - 1); 1349 } 1350 1351 adjustGlyphRangeForSingleByteEncoding(glyphID); 1352 1353 insertName("Subtype", "Type3"); 1354 // Flip about the x-axis and scale by 1/1000. 1355 SkMatrix fontMatrix; 1356 fontMatrix.setScale(SkScalarInvert(1000), -SkScalarInvert(1000)); 1357 insert("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix))->unref(); 1358 1359 SkAutoTUnref<SkPDFDict> charProcs(new SkPDFDict); 1360 insert("CharProcs", charProcs.get()); 1361 1362 SkAutoTUnref<SkPDFDict> encoding(new SkPDFDict("Encoding")); 1363 insert("Encoding", encoding.get()); 1364 1365 SkAutoTUnref<SkPDFArray> encDiffs(new SkPDFArray); 1366 encoding->insert("Differences", encDiffs.get()); 1367 encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); 1368 encDiffs->appendInt(1); 1369 1370 SkAutoTUnref<SkPDFArray> widthArray(new SkPDFArray()); 1371 1372 SkIRect bbox = SkIRect::MakeEmpty(); 1373 for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { 1374 SkString characterName; 1375 characterName.printf("gid%d", gID); 1376 encDiffs->appendName(characterName.c_str()); 1377 1378 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); 1379 widthArray->appendScalar(SkFixedToScalar(glyph.fAdvanceX)); 1380 SkIRect glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, 1381 glyph.fWidth, glyph.fHeight); 1382 bbox.join(glyphBBox); 1383 1384 SkDynamicMemoryWStream content; 1385 setGlyphWidthAndBoundingBox(SkFixedToScalar(glyph.fAdvanceX), glyphBBox, 1386 &content); 1387 const SkPath* path = cache->findPath(glyph); 1388 if (path) { 1389 SkPDFUtils::EmitPath(*path, paint.getStyle(), &content); 1390 SkPDFUtils::PaintPath(paint.getStyle(), path->getFillType(), 1391 &content); 1392 } 1393 SkAutoTUnref<SkMemoryStream> glyphStream(new SkMemoryStream()); 1394 glyphStream->setData(content.copyToData())->unref(); 1395 1396 SkAutoTUnref<SkPDFStream> glyphDescription( 1397 new SkPDFStream(glyphStream.get())); 1398 addResource(glyphDescription.get()); 1399 charProcs->insert(characterName.c_str(), 1400 new SkPDFObjRef(glyphDescription.get()))->unref(); 1401 } 1402 1403 insert("FontBBox", makeFontBBox(bbox, 1000))->unref(); 1404 insertInt("FirstChar", firstGlyphID()); 1405 insertInt("LastChar", lastGlyphID()); 1406 insert("Widths", widthArray.get()); 1407 insertName("CIDToGIDMap", "Identity"); 1408 1409 populateToUnicodeTable(NULL); 1410 return true; 1411 } 1412