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