SkPDFFont.cpp revision ee5ee582430196ee3a9b9473bf865e060515996c
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 "SkFontHost.h" 20#include "SkGlyphCache.h" 21#include "SkPaint.h" 22#include "SkPDFDevice.h" 23#include "SkPDFFont.h" 24#include "SkPDFStream.h" 25#include "SkPDFTypes.h" 26#include "SkPDFUtils.h" 27#include "SkRefCnt.h" 28#include "SkScalar.h" 29#include "SkStream.h" 30#include "SkTypeface.h" 31#include "SkTypes.h" 32#include "SkUtils.h" 33 34namespace { 35 36bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType, 37 size_t* size) { 38 // PFB sections have a two or six bytes header. 0x80 and a one byte 39 // section type followed by a four byte section length. Type one is 40 // an ASCII section (includes a length), type two is a binary section 41 // (includes a length) and type three is an EOF marker with no length. 42 const uint8_t* buf = *src; 43 if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) 44 return false; 45 if (buf[1] == 3) 46 return true; 47 if (*len < 6) 48 return false; 49 50 *size = buf[2] | (buf[3] << 8) | (buf[4] << 16) | (buf[5] << 24); 51 size_t consumed = *size + 6; 52 if (consumed > *len) 53 return false; 54 *src = *src + consumed; 55 *len = *len - consumed; 56 return true; 57} 58 59bool parsePFB(const uint8_t* src, size_t size, size_t* headerLen, 60 size_t* dataLen, size_t* trailerLen) { 61 const uint8_t* srcPtr = src; 62 size_t remaining = size; 63 64 return parsePFBSection(&srcPtr, &remaining, 1, headerLen) && 65 parsePFBSection(&srcPtr, &remaining, 2, dataLen) && 66 parsePFBSection(&srcPtr, &remaining, 1, trailerLen) && 67 parsePFBSection(&srcPtr, &remaining, 3, NULL); 68} 69 70/* The sections of a PFA file are implicitly defined. The body starts 71 * after the line containing "eexec," and the trailer starts with 512 72 * literal 0's followed by "cleartomark" (plus arbitrary white space). 73 * 74 * This function assumes that src is NUL terminated, but the NUL 75 * termination is not included in size. 76 * 77 */ 78bool parsePFA(const char* src, size_t size, size_t* headerLen, 79 size_t* hexDataLen, size_t* dataLen, size_t* trailerLen) { 80 const char* end = src + size; 81 82 const char* dataPos = strstr(src, "eexec"); 83 if (!dataPos) 84 return false; 85 dataPos += strlen("eexec"); 86 while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') && 87 dataPos < end) 88 dataPos++; 89 *headerLen = dataPos - src; 90 91 const char* trailerPos = strstr(dataPos, "cleartomark"); 92 if (!trailerPos) 93 return false; 94 int zeroCount = 0; 95 for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) { 96 if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') { 97 continue; 98 } else if (*trailerPos == '0') { 99 zeroCount++; 100 } else { 101 return false; 102 } 103 } 104 if (zeroCount != 512) 105 return false; 106 107 *hexDataLen = trailerPos - src - *headerLen; 108 *trailerLen = size - *headerLen - *hexDataLen; 109 110 // Verify that the data section is hex encoded and count the bytes. 111 int nibbles = 0; 112 for (; dataPos < trailerPos; dataPos++) { 113 if (isspace(*dataPos)) 114 continue; 115 if (!isxdigit(*dataPos)) 116 return false; 117 nibbles++; 118 } 119 *dataLen = (nibbles + 1) / 2; 120 121 return true; 122} 123 124int8_t hexToBin(uint8_t c) { 125 if (!isxdigit(c)) 126 return -1; 127 if (c <= '9') return c - '0'; 128 if (c <= 'F') return c - 'A' + 10; 129 if (c <= 'f') return c - 'a' + 10; 130 return -1; 131} 132 133SkStream* handleType1Stream(SkStream* srcStream, size_t* headerLen, 134 size_t* dataLen, size_t* trailerLen) { 135 // srcStream may be backed by a file or a unseekable fd, so we may not be 136 // able to use skip(), rewind(), or getMemoryBase(). read()ing through 137 // the input only once is doable, but very ugly. Furthermore, it'd be nice 138 // if the data was NUL terminated so that we can use strstr() to search it. 139 // Make as few copies as possible given these constraints. 140 SkDynamicMemoryWStream dynamicStream; 141 SkRefPtr<SkMemoryStream> staticStream; 142 const uint8_t* src; 143 size_t srcLen; 144 if ((srcLen = srcStream->getLength()) > 0) { 145 staticStream = new SkMemoryStream(srcLen + 1); 146 staticStream->unref(); // new and SkRefPtr both took a ref. 147 src = (const uint8_t*)staticStream->getMemoryBase(); 148 if (srcStream->getMemoryBase() != NULL) { 149 memcpy((void *)src, srcStream->getMemoryBase(), srcLen); 150 } else { 151 size_t read = 0; 152 while (read < srcLen) { 153 size_t got = srcStream->read((void *)staticStream->getAtPos(), 154 srcLen - read); 155 if (got == 0) 156 return NULL; 157 read += got; 158 staticStream->seek(read); 159 } 160 } 161 ((uint8_t *)src)[srcLen] = 0; 162 } else { 163 static const size_t bufSize = 4096; 164 uint8_t buf[bufSize]; 165 size_t amount; 166 while ((amount = srcStream->read(buf, bufSize)) > 0) 167 dynamicStream.write(buf, amount); 168 amount = 0; 169 dynamicStream.write(&amount, 1); // NULL terminator. 170 // getStream makes another copy, but we couldn't do any better. 171 src = (const uint8_t*)dynamicStream.getStream(); 172 srcLen = dynamicStream.getOffset() - 1; 173 } 174 175 if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) { 176 SkMemoryStream* result = 177 new SkMemoryStream(*headerLen + *dataLen + *trailerLen); 178 memcpy((char*)result->getAtPos(), src + 6, *headerLen); 179 result->seek(*headerLen); 180 memcpy((char*)result->getAtPos(), src + 6 + *headerLen + 6, *dataLen); 181 result->seek(*headerLen + *dataLen); 182 memcpy((char*)result->getAtPos(), src + 6 + *headerLen + 6 + *dataLen, 183 *trailerLen); 184 result->rewind(); 185 return result; 186 } 187 188 // A PFA has to be converted for PDF. 189 size_t hexDataLen; 190 if (parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen, 191 trailerLen)) { 192 SkMemoryStream* result = 193 new SkMemoryStream(*headerLen + *dataLen + *trailerLen); 194 memcpy((char*)result->getAtPos(), src, *headerLen); 195 result->seek(*headerLen); 196 197 const uint8_t* hexData = src + *headerLen; 198 const uint8_t* trailer = hexData + hexDataLen; 199 size_t outputOffset = 0; 200 uint8_t dataByte = 0; // To hush compiler. 201 bool highNibble = true; 202 for (; hexData < trailer; hexData++) { 203 char curNibble = hexToBin(*hexData); 204 if (curNibble < 0) 205 continue; 206 if (highNibble) { 207 dataByte = curNibble << 4; 208 highNibble = false; 209 } else { 210 dataByte |= curNibble; 211 highNibble = true; 212 ((char *)result->getAtPos())[outputOffset++] = dataByte; 213 } 214 } 215 if (!highNibble) 216 ((char *)result->getAtPos())[outputOffset++] = dataByte; 217 SkASSERT(outputOffset == *dataLen); 218 result->seek(*headerLen + outputOffset); 219 220 memcpy((char *)result->getAtPos(), src + *headerLen + hexDataLen, 221 *trailerLen); 222 result->rewind(); 223 return result; 224 } 225 226 return NULL; 227} 228 229// scale from em-units to base-1000, returning as a SkScalar 230SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { 231 SkScalar scaled = SkIntToScalar(val); 232 if (emSize == 1000) { 233 return scaled; 234 } else { 235 return SkScalarMulDiv(scaled, 1000, emSize); 236 } 237} 238 239void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, 240 SkWStream* content) { 241 // Specify width and bounding box for the glyph. 242 SkPDFScalar::Append(width, content); 243 content->writeText(" 0 "); 244 content->writeDecAsText(box.fLeft); 245 content->writeText(" "); 246 content->writeDecAsText(box.fTop); 247 content->writeText(" "); 248 content->writeDecAsText(box.fRight); 249 content->writeText(" "); 250 content->writeDecAsText(box.fBottom); 251 content->writeText(" d1\n"); 252} 253 254SkPDFArray* makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { 255 SkPDFArray* bbox = new SkPDFArray; 256 bbox->reserve(4); 257 bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fLeft, 258 emSize)))->unref(); 259 bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fBottom, 260 emSize)))->unref(); 261 bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fRight, 262 emSize)))->unref(); 263 bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fTop, 264 emSize)))->unref(); 265 return bbox; 266} 267 268SkPDFArray* appendWidth(const int16_t& width, uint16_t emSize, 269 SkPDFArray* array) { 270 array->append(new SkPDFScalar(scaleFromFontUnits(width, emSize)))->unref(); 271 return array; 272} 273 274SkPDFArray* appendVerticalAdvance( 275 const SkAdvancedTypefaceMetrics::VerticalMetric& advance, 276 uint16_t emSize, SkPDFArray* array) { 277 appendWidth(advance.fVerticalAdvance, emSize, array); 278 appendWidth(advance.fOriginXDisp, emSize, array); 279 appendWidth(advance.fOriginYDisp, emSize, array); 280 return array; 281} 282 283template <typename Data> 284SkPDFArray* composeAdvanceData( 285 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* advanceInfo, 286 uint16_t emSize, 287 SkPDFArray* (*appendAdvance)(const Data& advance, uint16_t emSize, 288 SkPDFArray* array), 289 Data* defaultAdvance) { 290 SkPDFArray* result = new SkPDFArray(); 291 for (; advanceInfo != NULL; advanceInfo = advanceInfo->fNext.get()) { 292 switch (advanceInfo->fType) { 293 case SkAdvancedTypefaceMetrics::WidthRange::kDefault: { 294 SkASSERT(advanceInfo->fAdvance.count() == 1); 295 *defaultAdvance = advanceInfo->fAdvance[0]; 296 break; 297 } 298 case SkAdvancedTypefaceMetrics::WidthRange::kRange: { 299 SkRefPtr<SkPDFArray> advanceArray = new SkPDFArray(); 300 advanceArray->unref(); // SkRefPtr and new both took a ref. 301 for (int j = 0; j < advanceInfo->fAdvance.count(); j++) 302 appendAdvance(advanceInfo->fAdvance[j], emSize, 303 advanceArray.get()); 304 result->append(new SkPDFInt(advanceInfo->fStartId))->unref(); 305 result->append(advanceArray.get()); 306 break; 307 } 308 case SkAdvancedTypefaceMetrics::WidthRange::kRun: { 309 SkASSERT(advanceInfo->fAdvance.count() == 1); 310 result->append(new SkPDFInt(advanceInfo->fStartId))->unref(); 311 result->append(new SkPDFInt(advanceInfo->fEndId))->unref(); 312 appendAdvance(advanceInfo->fAdvance[0], emSize, result); 313 break; 314 } 315 } 316 } 317 return result; 318} 319 320} // namespace 321 322/* Font subset design: It would be nice to be able to subset fonts 323 * (particularly type 3 fonts), but it's a lot of work and not a priority. 324 * 325 * Resources are canonicalized and uniqueified by pointer so there has to be 326 * some additional state indicating which subset of the font is used. It 327 * must be maintained at the page granularity and then combined at the document 328 * granularity. a) change SkPDFFont to fill in its state on demand, kind of 329 * like SkPDFGraphicState. b) maintain a per font glyph usage class in each 330 * page/pdf device. c) in the document, retrieve the per font glyph usage 331 * from each page and combine it and ask for a resource with that subset. 332 */ 333 334SkPDFFont::~SkPDFFont() { 335 SkAutoMutexAcquire lock(canonicalFontsMutex()); 336 int index; 337 if (find(SkTypeface::UniqueID(fTypeface.get()), fFirstGlyphID, &index)) { 338 canonicalFonts().removeShuffle(index); 339#ifdef SK_DEBUG 340 SkASSERT(!fDescendant); 341 } else { 342 SkASSERT(fDescendant); 343#endif 344 } 345 fResources.unrefAll(); 346} 347 348void SkPDFFont::getResources(SkTDArray<SkPDFObject*>* resourceList) { 349 resourceList->setReserve(resourceList->count() + fResources.count()); 350 for (int i = 0; i < fResources.count(); i++) { 351 resourceList->push(fResources[i]); 352 fResources[i]->ref(); 353 fResources[i]->getResources(resourceList); 354 } 355} 356 357SkTypeface* SkPDFFont::typeface() { 358 return fTypeface.get(); 359} 360 361bool SkPDFFont::hasGlyph(uint16_t id) { 362 return (id >= fFirstGlyphID && id <= fLastGlyphID) || id == 0; 363} 364 365bool SkPDFFont::multiByteGlyphs() { 366 return fMultiByteGlyphs; 367} 368 369size_t SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs, 370 size_t numGlyphs) { 371 // A font with multibyte glyphs will support all glyph IDs in a single font. 372 if (fMultiByteGlyphs) { 373 return numGlyphs; 374 } 375 376 for (size_t i = 0; i < numGlyphs; i++) { 377 if (glyphIDs[i] == 0) { 378 continue; 379 } 380 if (glyphIDs[i] < fFirstGlyphID || glyphIDs[i] > fLastGlyphID) { 381 return i; 382 } 383 glyphIDs[i] -= (fFirstGlyphID - 1); 384 } 385 386 return numGlyphs; 387} 388 389// static 390SkPDFFont* SkPDFFont::getFontResource(SkTypeface* typeface, uint16_t glyphID) { 391 SkAutoMutexAcquire lock(canonicalFontsMutex()); 392 const uint32_t fontID = SkTypeface::UniqueID(typeface); 393 int index; 394 if (find(fontID, glyphID, &index)) { 395 canonicalFonts()[index].fFont->ref(); 396 return canonicalFonts()[index].fFont; 397 } 398 399 SkRefPtr<SkAdvancedTypefaceMetrics> fontInfo; 400 SkPDFDict* fontDescriptor = NULL; 401 if (index >= 0) { 402 SkPDFFont* relatedFont = canonicalFonts()[index].fFont; 403 SkASSERT(relatedFont->fFontInfo.get()); 404 fontInfo = relatedFont->fFontInfo; 405 fontDescriptor = relatedFont->fDescriptor.get(); 406 } else { 407 fontInfo = SkFontHost::GetAdvancedTypefaceMetrics(fontID, SkTBitOr( 408 SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo, 409 SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo)); 410 SkSafeUnref(fontInfo.get()); // SkRefPtr and Get both took a reference. 411 } 412 413 SkPDFFont* font = new SkPDFFont(fontInfo.get(), typeface, glyphID, false, 414 fontDescriptor); 415 FontRec newEntry(font, fontID, font->fFirstGlyphID); 416 index = canonicalFonts().count(); 417 canonicalFonts().push(newEntry); 418 return font; // Return the reference new SkPDFFont() created. 419} 420 421// static 422SkTDArray<SkPDFFont::FontRec>& SkPDFFont::canonicalFonts() { 423 // This initialization is only thread safe with gcc. 424 static SkTDArray<FontRec> gCanonicalFonts; 425 return gCanonicalFonts; 426} 427 428// static 429SkMutex& SkPDFFont::canonicalFontsMutex() { 430 // This initialization is only thread safe with gcc. 431 static SkMutex gCanonicalFontsMutex; 432 return gCanonicalFontsMutex; 433} 434 435// static 436bool SkPDFFont::find(uint32_t fontID, uint16_t glyphID, int* index) { 437 // TODO(vandebo) optimize this, do only one search? 438 FontRec search(NULL, fontID, glyphID); 439 *index = canonicalFonts().find(search); 440 if (*index >= 0) 441 return true; 442 search.fGlyphID = 0; 443 *index = canonicalFonts().find(search); 444 return false; 445} 446 447SkPDFFont::SkPDFFont(class SkAdvancedTypefaceMetrics* fontInfo, 448 SkTypeface* typeface, 449 uint16_t glyphID, 450 bool descendantFont, 451 SkPDFDict* fontDescriptor) 452 : SkPDFDict("Font"), 453 fTypeface(typeface), 454#ifdef SK_DEBUG 455 fDescendant(descendantFont), 456#endif 457 fMultiByteGlyphs(false), 458 fFirstGlyphID(1), 459 fLastGlyphID(fontInfo ? fontInfo->fLastGlyphID : 0), 460 fFontInfo(fontInfo), 461 fDescriptor(fontDescriptor) { 462 463 SkAdvancedTypefaceMetrics::FontType type; 464 if (fontInfo) { 465 type = fontInfo->fType; 466 } else { 467 type = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 468 } 469 470 if (fontInfo && fontInfo->fMultiMaster) { 471 SkASSERT(false); // Not supported yet. 472 fontInfo->fType = SkAdvancedTypefaceMetrics::kOther_Font; 473 } 474 if (type == SkAdvancedTypefaceMetrics::kType1CID_Font || 475 type == SkAdvancedTypefaceMetrics::kTrueType_Font) { 476 if (descendantFont) { 477 populateCIDFont(); 478 } else { 479 populateType0Font(); 480 } 481 // No need to hold onto the font info for fonts types that 482 // support multibyte glyphs. 483 fFontInfo = NULL; 484 return; 485 } 486 487 if (type == SkAdvancedTypefaceMetrics::kType1_Font && 488 populateType1Font(glyphID)) { 489 return; 490 } 491 492 SkASSERT(type == SkAdvancedTypefaceMetrics::kType1_Font || 493 type == SkAdvancedTypefaceMetrics::kCFF_Font || 494 type == SkAdvancedTypefaceMetrics::kOther_Font || 495 type == SkAdvancedTypefaceMetrics::kNotEmbeddable_Font); 496 populateType3Font(glyphID); 497} 498 499void SkPDFFont::populateType0Font() { 500 // TODO(vandebo) add a ToUnicode mapping. 501 fMultiByteGlyphs = true; 502 503 insert("Subtype", new SkPDFName("Type0"))->unref(); 504 insert("BaseFont", new SkPDFName(fFontInfo->fFontName))->unref(); 505 insert("Encoding", new SkPDFName("Identity-H"))->unref(); 506 507 SkRefPtr<SkPDFArray> descendantFonts = new SkPDFArray(); 508 descendantFonts->unref(); // SkRefPtr and new took a reference. 509 510 // Pass ref new created to fResources. 511 fResources.push( 512 new SkPDFFont(fFontInfo.get(), fTypeface.get(), 1, true, NULL)); 513 descendantFonts->append(new SkPDFObjRef(fResources.top()))->unref(); 514 insert("DescendantFonts", descendantFonts.get()); 515} 516 517void SkPDFFont::populateCIDFont() { 518 fMultiByteGlyphs = true; 519 insert("BaseFont", new SkPDFName(fFontInfo->fFontName))->unref(); 520 521 if (fFontInfo->fType == SkAdvancedTypefaceMetrics::kType1CID_Font) { 522 insert("Subtype", new SkPDFName("CIDFontType0"))->unref(); 523 } else if (fFontInfo->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) { 524 insert("Subtype", new SkPDFName("CIDFontType2"))->unref(); 525 } else { 526 SkASSERT(false); 527 } 528 529 SkRefPtr<SkPDFDict> sysInfo = new SkPDFDict; 530 sysInfo->unref(); // SkRefPtr and new both took a reference. 531 sysInfo->insert("Registry", new SkPDFString("Adobe"))->unref(); 532 sysInfo->insert("Ordering", new SkPDFString("Identity"))->unref(); 533 sysInfo->insert("Supplement", new SkPDFInt(0))->unref(); 534 insert("CIDSystemInfo", sysInfo.get()); 535 536 addFontDescriptor(0); 537 538 if (fFontInfo->fGlyphWidths.get()) { 539 int16_t defaultWidth = 0; 540 SkRefPtr<SkPDFArray> widths = 541 composeAdvanceData(fFontInfo->fGlyphWidths.get(), 542 fFontInfo->fEmSize, &appendWidth, &defaultWidth); 543 widths->unref(); // SkRefPtr and compose both took a reference. 544 if (widths->size()) 545 insert("W", widths.get()); 546 if (defaultWidth != 0) { 547 insert("DW", new SkPDFScalar(scaleFromFontUnits( 548 defaultWidth, fFontInfo->fEmSize)))->unref(); 549 } 550 } 551 if (fFontInfo->fVerticalMetrics.get()) { 552 struct SkAdvancedTypefaceMetrics::VerticalMetric defaultAdvance; 553 defaultAdvance.fVerticalAdvance = 0; 554 defaultAdvance.fOriginXDisp = 0; 555 defaultAdvance.fOriginYDisp = 0; 556 SkRefPtr<SkPDFArray> advances = 557 composeAdvanceData(fFontInfo->fVerticalMetrics.get(), 558 fFontInfo->fEmSize, &appendVerticalAdvance, 559 &defaultAdvance); 560 advances->unref(); // SkRefPtr and compose both took a ref. 561 if (advances->size()) 562 insert("W2", advances.get()); 563 if (defaultAdvance.fVerticalAdvance || 564 defaultAdvance.fOriginXDisp || 565 defaultAdvance.fOriginYDisp) { 566 insert("DW2", appendVerticalAdvance(defaultAdvance, 567 fFontInfo->fEmSize, 568 new SkPDFArray))->unref(); 569 } 570 } 571} 572 573bool SkPDFFont::populateType1Font(int16_t glyphID) { 574 SkASSERT(!fFontInfo->fVerticalMetrics.get()); 575 SkASSERT(fFontInfo->fGlyphWidths.get()); 576 577 adjustGlyphRangeForSingleByteEncoding(glyphID); 578 579 int16_t defaultWidth = 0; 580 const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry = NULL; 581 const SkAdvancedTypefaceMetrics::WidthRange* widthEntry; 582 for (widthEntry = fFontInfo.get()->fGlyphWidths.get(); 583 widthEntry != NULL; 584 widthEntry = widthEntry->fNext.get()) { 585 switch (widthEntry->fType) { 586 case SkAdvancedTypefaceMetrics::WidthRange::kDefault: 587 defaultWidth = widthEntry->fAdvance[0]; 588 break; 589 case SkAdvancedTypefaceMetrics::WidthRange::kRun: 590 SkASSERT(false); 591 break; 592 case SkAdvancedTypefaceMetrics::WidthRange::kRange: 593 SkASSERT(widthRangeEntry == NULL); 594 widthRangeEntry = widthEntry; 595 break; 596 } 597 } 598 599 if (!addFontDescriptor(defaultWidth)) 600 return false; 601 602 insert("Subtype", new SkPDFName("Type1"))->unref(); 603 insert("BaseFont", new SkPDFName(fFontInfo->fFontName))->unref(); 604 605 addWidthInfoFromRange(defaultWidth, widthRangeEntry); 606 607 SkRefPtr<SkPDFDict> encoding = new SkPDFDict("Encoding"); 608 encoding->unref(); // SkRefPtr and new both took a reference. 609 insert("Encoding", encoding.get()); 610 611 SkRefPtr<SkPDFArray> encDiffs = new SkPDFArray; 612 encDiffs->unref(); // SkRefPtr and new both took a reference. 613 encoding->insert("Differences", encDiffs.get()); 614 615 encDiffs->reserve(fLastGlyphID - fFirstGlyphID + 2); 616 encDiffs->append(new SkPDFInt(1))->unref(); 617 for (int gID = fFirstGlyphID; gID <= fLastGlyphID; gID++) { 618 encDiffs->append( 619 new SkPDFName(fFontInfo->fGlyphNames->get()[gID]))->unref(); 620 } 621 622 if (fFontInfo->fLastGlyphID <= 255) 623 fFontInfo = NULL; 624 return true; 625} 626 627void SkPDFFont::populateType3Font(int16_t glyphID) { 628 SkPaint paint; 629 paint.setTypeface(fTypeface.get()); 630 paint.setTextSize(1000); 631 SkAutoGlyphCache autoCache(paint, NULL); 632 SkGlyphCache* cache = autoCache.getCache(); 633 // If fLastGlyphID isn't set (because there is not fFontInfo), look it up. 634 if (fLastGlyphID == 0) { 635 fLastGlyphID = cache->getGlyphCount() - 1; 636 } 637 638 adjustGlyphRangeForSingleByteEncoding(glyphID); 639 640 insert("Subtype", new SkPDFName("Type3"))->unref(); 641 // Flip about the x-axis and scale by 1/1000. 642 SkMatrix fontMatrix; 643 fontMatrix.setScale(SkScalarInvert(1000), -SkScalarInvert(1000)); 644 insert("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix))->unref(); 645 646 SkRefPtr<SkPDFDict> charProcs = new SkPDFDict; 647 charProcs->unref(); // SkRefPtr and new both took a reference. 648 insert("CharProcs", charProcs.get()); 649 650 SkRefPtr<SkPDFDict> encoding = new SkPDFDict("Encoding"); 651 encoding->unref(); // SkRefPtr and new both took a reference. 652 insert("Encoding", encoding.get()); 653 654 SkRefPtr<SkPDFArray> encDiffs = new SkPDFArray; 655 encDiffs->unref(); // SkRefPtr and new both took a reference. 656 encoding->insert("Differences", encDiffs.get()); 657 encDiffs->reserve(fLastGlyphID - fFirstGlyphID + 2); 658 encDiffs->append(new SkPDFInt(1))->unref(); 659 660 SkRefPtr<SkPDFArray> widthArray = new SkPDFArray(); 661 widthArray->unref(); // SkRefPtr and new both took a ref. 662 663 SkIRect bbox = SkIRect::MakeEmpty(); 664 for (int gID = fFirstGlyphID; gID <= fLastGlyphID; gID++) { 665 SkString characterName; 666 characterName.printf("gid%d", gID); 667 encDiffs->append(new SkPDFName(characterName))->unref(); 668 669 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); 670 widthArray->append(new SkPDFScalar(SkFixedToScalar(glyph.fAdvanceX)))->unref(); 671 SkIRect glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, 672 glyph.fWidth, glyph.fHeight); 673 bbox.join(glyphBBox); 674 675 SkDynamicMemoryWStream content; 676 setGlyphWidthAndBoundingBox(SkFixedToScalar(glyph.fAdvanceX), glyphBBox, 677 &content); 678 const SkPath* path = cache->findPath(glyph); 679 if (path) { 680 SkPDFUtils::EmitPath(*path, &content); 681 SkPDFUtils::PaintPath(paint.getStyle(), path->getFillType(), 682 &content); 683 } 684 SkRefPtr<SkMemoryStream> glyphStream = new SkMemoryStream(); 685 glyphStream->unref(); // SkRefPtr and new both took a ref. 686 glyphStream->setMemoryOwned(content.detach(), content.getOffset()); 687 688 SkRefPtr<SkPDFStream> glyphDescription = 689 new SkPDFStream(glyphStream.get()); 690 // SkRefPtr and new both ref()'d charProcs, pass one. 691 fResources.push(glyphDescription.get()); 692 charProcs->insert(characterName.c_str(), 693 new SkPDFObjRef(glyphDescription.get()))->unref(); 694 } 695 696 insert("FontBBox", makeFontBBox(bbox, 1000))->unref(); 697 insert("FirstChar", new SkPDFInt(fFirstGlyphID))->unref(); 698 insert("LastChar", new SkPDFInt(fLastGlyphID))->unref(); 699 insert("Widths", widthArray.get()); 700 701 if (fFontInfo && fFontInfo->fLastGlyphID <= 255) 702 fFontInfo = NULL; 703} 704 705bool SkPDFFont::addFontDescriptor(int16_t defaultWidth) { 706 if (fDescriptor.get() != NULL) { 707 fResources.push(fDescriptor.get()); 708 fDescriptor->ref(); 709 insert("FontDescriptor", new SkPDFObjRef(fDescriptor.get()))->unref(); 710 return true; 711 } 712 713 fDescriptor = new SkPDFDict("FontDescriptor"); 714 fDescriptor->unref(); // SkRefPtr and new both took a ref. 715 716 switch (fFontInfo->fType) { 717 case SkAdvancedTypefaceMetrics::kType1_Font: { 718 size_t header SK_INIT_TO_AVOID_WARNING; 719 size_t data SK_INIT_TO_AVOID_WARNING; 720 size_t trailer SK_INIT_TO_AVOID_WARNING; 721 SkRefPtr<SkStream> rawFontData = 722 SkFontHost::OpenStream(SkTypeface::UniqueID(fTypeface.get())); 723 rawFontData->unref(); // SkRefPtr and OpenStream both took a ref. 724 SkStream* fontData = handleType1Stream(rawFontData.get(), &header, 725 &data, &trailer); 726 if (fontData == NULL) 727 return false; 728 SkRefPtr<SkPDFStream> fontStream = new SkPDFStream(fontData); 729 // SkRefPtr and new both ref()'d fontStream, pass one. 730 fResources.push(fontStream.get()); 731 fontStream->insert("Length1", new SkPDFInt(header))->unref(); 732 fontStream->insert("Length2", new SkPDFInt(data))->unref(); 733 fontStream->insert("Length3", new SkPDFInt(trailer))->unref(); 734 fDescriptor->insert("FontFile", 735 new SkPDFObjRef(fontStream.get()))->unref(); 736 break; 737 } 738 case SkAdvancedTypefaceMetrics::kTrueType_Font: { 739 SkRefPtr<SkStream> fontData = 740 SkFontHost::OpenStream(SkTypeface::UniqueID(fTypeface.get())); 741 fontData->unref(); // SkRefPtr and OpenStream both took a ref. 742 SkRefPtr<SkPDFStream> fontStream = new SkPDFStream(fontData.get()); 743 // SkRefPtr and new both ref()'d fontStream, pass one. 744 fResources.push(fontStream.get()); 745 746 fontStream->insert("Length1", 747 new SkPDFInt(fontData->getLength()))->unref(); 748 fDescriptor->insert("FontFile2", 749 new SkPDFObjRef(fontStream.get()))->unref(); 750 break; 751 } 752 case SkAdvancedTypefaceMetrics::kCFF_Font: 753 case SkAdvancedTypefaceMetrics::kType1CID_Font: { 754 SkRefPtr<SkStream> fontData = 755 SkFontHost::OpenStream(SkTypeface::UniqueID(fTypeface.get())); 756 fontData->unref(); // SkRefPtr and OpenStream both took a ref. 757 SkRefPtr<SkPDFStream> fontStream = new SkPDFStream(fontData.get()); 758 // SkRefPtr and new both ref()'d fontStream, pass one. 759 fResources.push(fontStream.get()); 760 761 if (fFontInfo->fType == SkAdvancedTypefaceMetrics::kCFF_Font) { 762 fontStream->insert("Subtype", new SkPDFName("Type1C"))->unref(); 763 } else { 764 fontStream->insert("Subtype", 765 new SkPDFName("CIDFontType0c"))->unref(); 766 } 767 fDescriptor->insert("FontFile3", 768 new SkPDFObjRef(fontStream.get()))->unref(); 769 break; 770 } 771 default: 772 SkASSERT(false); 773 } 774 775 const uint16_t emSize = fFontInfo->fEmSize; 776 fResources.push(fDescriptor.get()); 777 fDescriptor->ref(); 778 insert("FontDescriptor", new SkPDFObjRef(fDescriptor.get()))->unref(); 779 780 fDescriptor->insert("FontName", new SkPDFName( 781 fFontInfo->fFontName))->unref(); 782 fDescriptor->insert("Flags", new SkPDFInt(fFontInfo->fStyle))->unref(); 783 fDescriptor->insert("Ascent", new SkPDFScalar( 784 scaleFromFontUnits(fFontInfo->fAscent, emSize)))->unref(); 785 fDescriptor->insert("Descent", new SkPDFScalar( 786 scaleFromFontUnits(fFontInfo->fDescent, emSize)))->unref(); 787 fDescriptor->insert("StemV", new SkPDFScalar( 788 scaleFromFontUnits(fFontInfo->fStemV, emSize)))->unref(); 789 fDescriptor->insert("CapHeight", new SkPDFScalar( 790 scaleFromFontUnits(fFontInfo->fCapHeight, emSize)))->unref(); 791 fDescriptor->insert("ItalicAngle", new SkPDFInt( 792 fFontInfo->fItalicAngle))->unref(); 793 fDescriptor->insert("FontBBox", makeFontBBox(fFontInfo->fBBox, 794 fFontInfo->fEmSize))->unref(); 795 796 if (defaultWidth > 0) { 797 fDescriptor->insert("MissingWidth", new SkPDFScalar( 798 scaleFromFontUnits(defaultWidth, emSize)))->unref(); 799 } 800 return true; 801} 802void SkPDFFont::addWidthInfoFromRange( 803 int16_t defaultWidth, 804 const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry) { 805 SkRefPtr<SkPDFArray> widthArray = new SkPDFArray(); 806 widthArray->unref(); // SkRefPtr and new both took a ref. 807 int firstChar = 0; 808 if (widthRangeEntry) { 809 const uint16_t emSize = fFontInfo->fEmSize; 810 int startIndex = fFirstGlyphID - widthRangeEntry->fStartId; 811 int endIndex = startIndex + fLastGlyphID - fFirstGlyphID + 1; 812 if (startIndex < 0) 813 startIndex = 0; 814 if (endIndex > widthRangeEntry->fAdvance.count()) 815 endIndex = widthRangeEntry->fAdvance.count(); 816 if (widthRangeEntry->fStartId == 0) { 817 appendWidth(widthRangeEntry->fAdvance[0], emSize, widthArray.get()); 818 } else { 819 firstChar = startIndex + widthRangeEntry->fStartId; 820 } 821 for (int i = startIndex; i < endIndex; i++) 822 appendWidth(widthRangeEntry->fAdvance[i], emSize, widthArray.get()); 823 } else { 824 appendWidth(defaultWidth, 1000, widthArray.get()); 825 } 826 insert("FirstChar", new SkPDFInt(firstChar))->unref(); 827 insert("LastChar", 828 new SkPDFInt(firstChar + widthArray->size() - 1))->unref(); 829 insert("Widths", widthArray.get()); 830} 831 832void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(int16_t glyphID) { 833 // Single byte glyph encoding supports a max of 255 glyphs. 834 fFirstGlyphID = glyphID - (glyphID - 1) % 255; 835 if (fLastGlyphID > fFirstGlyphID + 255 - 1) { 836 fLastGlyphID = fFirstGlyphID + 255 - 1; 837 } 838} 839 840 841bool SkPDFFont::FontRec::operator==(const SkPDFFont::FontRec& b) const { 842 if (fFontID != b.fFontID) 843 return false; 844 if (fFont != NULL && b.fFont != NULL) { 845 return fFont->fFirstGlyphID == b.fFont->fFirstGlyphID && 846 fFont->fLastGlyphID == b.fFont->fLastGlyphID; 847 } 848 if (fGlyphID == 0 || b.fGlyphID == 0) 849 return true; 850 851 if (fFont != NULL) { 852 return fFont->fFirstGlyphID <= b.fGlyphID && 853 b.fGlyphID <= fFont->fLastGlyphID; 854 } else if (b.fFont != NULL) { 855 return b.fFont->fFirstGlyphID <= fGlyphID && 856 fGlyphID <= b.fFont->fLastGlyphID; 857 } 858 return fGlyphID == b.fGlyphID; 859} 860 861SkPDFFont::FontRec::FontRec(SkPDFFont* font, uint32_t fontID, uint16_t glyphID) 862 : fFont(font), 863 fFontID(fontID), 864 fGlyphID(glyphID) { 865} 866