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