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