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 "SkData.h" 9 #include "SkGlyphCache.h" 10 #include "SkPaint.h" 11 #include "SkPDFCanon.h" 12 #include "SkPDFConvertType1FontStream.h" 13 #include "SkPDFDevice.h" 14 #include "SkPDFMakeCIDGlyphWidthsArray.h" 15 #include "SkPDFMakeToUnicodeCmap.h" 16 #include "SkPDFFont.h" 17 #include "SkPDFUtils.h" 18 #include "SkRefCnt.h" 19 #include "SkScalar.h" 20 #include "SkStream.h" 21 #include "SkTypes.h" 22 #include "SkUtils.h" 23 24 #ifdef SK_PDF_USE_SFNTLY 25 #include "sample/chromium/font_subsetter.h" 26 #endif 27 28 SkAutoGlyphCache SkPDFFont::MakeVectorCache(SkTypeface* face, int* size) { 29 SkPaint tmpPaint; 30 tmpPaint.setHinting(SkPaint::kNo_Hinting); 31 tmpPaint.setTypeface(sk_ref_sp(face)); 32 int unitsPerEm = face->getUnitsPerEm(); 33 if (unitsPerEm <= 0) { 34 unitsPerEm = 1024; 35 } 36 if (size) { 37 *size = unitsPerEm; 38 } 39 tmpPaint.setTextSize((SkScalar)unitsPerEm); 40 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); 41 SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); 42 SkASSERT(glyphCache.get()); 43 return glyphCache; 44 } 45 46 namespace { 47 // PDF's notion of symbolic vs non-symbolic is related to the character set, not 48 // symbols vs. characters. Rarely is a font the right character set to call it 49 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) 50 static const int32_t kPdfSymbolic = 4; 51 52 struct SkPDFType0Font final : public SkPDFFont { 53 SkPDFType0Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&); 54 ~SkPDFType0Font() override; 55 void getFontSubset(SkPDFCanon*) override; 56 #ifdef SK_DEBUG 57 void emitObject(SkWStream*, const SkPDFObjNumMap&) const override; 58 bool fPopulated; 59 #endif 60 typedef SkPDFDict INHERITED; 61 }; 62 63 struct SkPDFType1Font final : public SkPDFFont { 64 SkPDFType1Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&, SkPDFCanon*); 65 ~SkPDFType1Font() override {} 66 void getFontSubset(SkPDFCanon*) override {} // TODO(halcanary): implement 67 }; 68 69 struct SkPDFType3Font final : public SkPDFFont { 70 SkPDFType3Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&); 71 ~SkPDFType3Font() override {} 72 void getFontSubset(SkPDFCanon*) override; 73 }; 74 75 /////////////////////////////////////////////////////////////////////////////// 76 // File-Local Functions 77 /////////////////////////////////////////////////////////////////////////////// 78 79 // scale from em-units to base-1000, returning as a SkScalar 80 SkScalar from_font_units(SkScalar scaled, uint16_t emSize) { 81 if (emSize == 1000) { 82 return scaled; 83 } else { 84 return scaled * 1000 / emSize; 85 } 86 } 87 88 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { 89 return from_font_units(SkIntToScalar(val), emSize); 90 } 91 92 93 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, 94 SkDynamicMemoryWStream* content) { 95 // Specify width and bounding box for the glyph. 96 SkPDFUtils::AppendScalar(width, content); 97 content->writeText(" 0 "); 98 content->writeDecAsText(box.fLeft); 99 content->writeText(" "); 100 content->writeDecAsText(box.fTop); 101 content->writeText(" "); 102 content->writeDecAsText(box.fRight); 103 content->writeText(" "); 104 content->writeDecAsText(box.fBottom); 105 content->writeText(" d1\n"); 106 } 107 108 static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { 109 auto bbox = sk_make_sp<SkPDFArray>(); 110 bbox->reserve(4); 111 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); 112 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); 113 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); 114 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); 115 return bbox; 116 } 117 } // namespace 118 119 /////////////////////////////////////////////////////////////////////////////// 120 // class SkPDFFont 121 /////////////////////////////////////////////////////////////////////////////// 122 123 /* Font subset design: It would be nice to be able to subset fonts 124 * (particularly type 3 fonts), but it's a lot of work and not a priority. 125 * 126 * Resources are canonicalized and uniqueified by pointer so there has to be 127 * some additional state indicating which subset of the font is used. It 128 * must be maintained at the page granularity and then combined at the document 129 * granularity. a) change SkPDFFont to fill in its state on demand, kind of 130 * like SkPDFGraphicState. b) maintain a per font glyph usage class in each 131 * page/pdf device. c) in the document, retrieve the per font glyph usage 132 * from each page and combine it and ask for a resource with that subset. 133 */ 134 135 SkPDFFont::~SkPDFFont() {} 136 137 static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) { 138 return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag); 139 } 140 141 const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface, 142 SkPDFCanon* canon) { 143 SkASSERT(typeface); 144 SkFontID id = typeface->uniqueID(); 145 if (SkAdvancedTypefaceMetrics** ptr = canon->fTypefaceMetrics.find(id)) { 146 return *ptr; 147 } 148 int count = typeface->countGlyphs(); 149 if (count <= 0 || count > 1 + SK_MaxU16) { 150 // Cache nullptr to skip this check. Use SkSafeUnref(). 151 canon->fTypefaceMetrics.set(id, nullptr); 152 return nullptr; 153 } 154 sk_sp<SkAdvancedTypefaceMetrics> metrics( 155 typeface->getAdvancedTypefaceMetrics( 156 SkTypeface::kGlyphNames_PerGlyphInfo | SkTypeface::kToUnicode_PerGlyphInfo, 157 nullptr, 0)); 158 if (!metrics) { 159 metrics = sk_make_sp<SkAdvancedTypefaceMetrics>(); 160 } 161 return *canon->fTypefaceMetrics.set(id, metrics.release()); 162 } 163 164 SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkAdvancedTypefaceMetrics& metrics) { 165 if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) || 166 SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag)) { 167 // force Type3 fallback. 168 return SkAdvancedTypefaceMetrics::kOther_Font; 169 } 170 return metrics.fType; 171 } 172 173 static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) { 174 return gid != 0 ? gid - (gid - 1) % 255 : 1; 175 } 176 177 SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, 178 SkTypeface* face, 179 SkGlyphID glyphID) { 180 SkASSERT(canon); 181 SkASSERT(face); // All SkPDFDevice::internalDrawText ensures this. 182 const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, canon); 183 SkASSERT(fontMetrics); // SkPDFDevice::internalDrawText ensures the typeface is good. 184 // GetMetrics only returns null to signify a bad typeface. 185 const SkAdvancedTypefaceMetrics& metrics = *fontMetrics; 186 SkAdvancedTypefaceMetrics::FontType type = SkPDFFont::FontType(metrics); 187 bool multibyte = SkPDFFont::IsMultiByte(type); 188 SkGlyphID subsetCode = multibyte ? 0 : first_nonzero_glyph_for_single_byte_encoding(glyphID); 189 uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | subsetCode; 190 191 if (SkPDFFont** found = canon->fFontMap.find(fontID)) { 192 SkPDFFont* foundFont = *found; 193 SkASSERT(foundFont && multibyte == foundFont->multiByteGlyphs()); 194 return SkRef(foundFont); 195 } 196 197 sk_sp<SkTypeface> typeface(sk_ref_sp(face)); 198 SkASSERT(typeface); 199 200 SkGlyphID lastGlyph = SkToU16(typeface->countGlyphs() - 1); 201 202 // should be caught by SkPDFDevice::internalDrawText 203 SkASSERT(glyphID <= lastGlyph); 204 205 SkGlyphID firstNonZeroGlyph; 206 if (multibyte) { 207 firstNonZeroGlyph = 1; 208 } else { 209 firstNonZeroGlyph = subsetCode; 210 lastGlyph = SkToU16(SkTMin<int>((int)lastGlyph, 254 + (int)subsetCode)); 211 } 212 SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, type}; 213 sk_sp<SkPDFFont> font; 214 switch (type) { 215 case SkAdvancedTypefaceMetrics::kType1CID_Font: 216 case SkAdvancedTypefaceMetrics::kTrueType_Font: 217 SkASSERT(multibyte); 218 font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics); 219 break; 220 case SkAdvancedTypefaceMetrics::kType1_Font: 221 SkASSERT(!multibyte); 222 font = sk_make_sp<SkPDFType1Font>(std::move(info), metrics, canon); 223 break; 224 default: 225 SkASSERT(!multibyte); 226 // Type3 is our fallback font. 227 font = sk_make_sp<SkPDFType3Font>(std::move(info), metrics); 228 break; 229 } 230 canon->fFontMap.set(fontID, SkRef(font.get())); 231 return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>. 232 } 233 234 SkPDFFont::SkPDFFont(SkPDFFont::Info info) 235 : SkPDFDict("Font") 236 , fTypeface(std::move(info.fTypeface)) 237 , fGlyphUsage(info.fLastGlyphID + 1) // TODO(halcanary): Adjust mapping? 238 , fFirstGlyphID(info.fFirstGlyphID) 239 , fLastGlyphID(info.fLastGlyphID) 240 , fFontType(info.fFontType) { 241 SkASSERT(fTypeface); 242 } 243 244 static void add_common_font_descriptor_entries(SkPDFDict* descriptor, 245 const SkAdvancedTypefaceMetrics& metrics, 246 uint16_t emSize, 247 int16_t defaultWidth) { 248 descriptor->insertName("FontName", metrics.fFontName); 249 descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic)); 250 descriptor->insertScalar("Ascent", 251 scaleFromFontUnits(metrics.fAscent, emSize)); 252 descriptor->insertScalar("Descent", 253 scaleFromFontUnits(metrics.fDescent, emSize)); 254 descriptor->insertScalar("StemV", 255 scaleFromFontUnits(metrics.fStemV, emSize)); 256 descriptor->insertScalar("CapHeight", 257 scaleFromFontUnits(metrics.fCapHeight, emSize)); 258 descriptor->insertInt("ItalicAngle", metrics.fItalicAngle); 259 descriptor->insertObject( 260 "FontBBox", makeFontBBox(metrics.fBBox, emSize)); 261 if (defaultWidth > 0) { 262 descriptor->insertScalar("MissingWidth", 263 scaleFromFontUnits(defaultWidth, emSize)); 264 } 265 } 266 267 /////////////////////////////////////////////////////////////////////////////// 268 // class SkPDFType0Font 269 /////////////////////////////////////////////////////////////////////////////// 270 271 SkPDFType0Font::SkPDFType0Font( 272 SkPDFFont::Info info, 273 const SkAdvancedTypefaceMetrics& metrics) 274 : SkPDFFont(std::move(info)) { 275 SkDEBUGCODE(fPopulated = false); 276 } 277 278 SkPDFType0Font::~SkPDFType0Font() {} 279 280 281 #ifdef SK_DEBUG 282 void SkPDFType0Font::emitObject(SkWStream* stream, 283 const SkPDFObjNumMap& objNumMap) const { 284 SkASSERT(fPopulated); 285 return INHERITED::emitObject(stream, objNumMap); 286 } 287 #endif 288 289 #ifdef SK_PDF_USE_SFNTLY 290 // if possible, make no copy. 291 static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) { 292 SkASSERT(stream); 293 (void)stream->rewind(); 294 SkASSERT(stream->hasLength()); 295 size_t size = stream->getLength(); 296 if (const void* base = stream->getMemoryBase()) { 297 SkData::ReleaseProc proc = 298 [](const void*, void* ctx) { delete (SkStreamAsset*)ctx; }; 299 return SkData::MakeWithProc(base, size, proc, stream.release()); 300 } 301 return SkData::MakeFromStream(stream.get(), size); 302 } 303 304 static sk_sp<SkPDFStream> get_subset_font_stream( 305 std::unique_ptr<SkStreamAsset> fontAsset, 306 const SkBitSet& glyphUsage, 307 const char* fontName, 308 int ttcIndex) { 309 // Generate glyph id array in format needed by sfntly. 310 // TODO(halcanary): sfntly should take a more compact format. 311 SkTDArray<unsigned> subset; 312 if (!glyphUsage.has(0)) { 313 subset.push(0); // Always include glyph 0. 314 } 315 glyphUsage.exportTo(&subset); 316 317 unsigned char* subsetFont{nullptr}; 318 sk_sp<SkData> fontData(stream_to_data(std::move(fontAsset))); 319 #if defined(GOOGLE3) 320 // TODO(halcanary): update GOOGLE3 to newest version of Sfntly. 321 (void)ttcIndex; 322 int subsetFontSize = SfntlyWrapper::SubsetFont(fontName, 323 fontData->bytes(), 324 fontData->size(), 325 subset.begin(), 326 subset.count(), 327 &subsetFont); 328 #else 329 (void)fontName; 330 int subsetFontSize = SfntlyWrapper::SubsetFont(ttcIndex, 331 fontData->bytes(), 332 fontData->size(), 333 subset.begin(), 334 subset.count(), 335 &subsetFont); 336 #endif 337 fontData.reset(); 338 subset.reset(); 339 SkASSERT(subsetFontSize > 0 || subsetFont == nullptr); 340 if (subsetFontSize < 1) { 341 return nullptr; 342 } 343 SkASSERT(subsetFont != nullptr); 344 auto subsetStream = sk_make_sp<SkPDFStream>( 345 SkData::MakeWithProc( 346 subsetFont, subsetFontSize, 347 [](const void* p, void*) { delete[] (unsigned char*)p; }, 348 nullptr)); 349 subsetStream->dict()->insertInt("Length1", subsetFontSize); 350 return subsetStream; 351 } 352 #endif // SK_PDF_USE_SFNTLY 353 354 void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) { 355 const SkAdvancedTypefaceMetrics* metricsPtr = 356 SkPDFFont::GetMetrics(this->typeface(), canon); 357 SkASSERT(metricsPtr); 358 if (!metricsPtr) { return; } 359 const SkAdvancedTypefaceMetrics& metrics = *metricsPtr; 360 SkASSERT(can_embed(metrics)); 361 SkAdvancedTypefaceMetrics::FontType type = this->getType(); 362 SkTypeface* face = this->typeface(); 363 SkASSERT(face); 364 365 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); 366 uint16_t emSize = SkToU16(this->typeface()->getUnitsPerEm()); 367 add_common_font_descriptor_entries(descriptor.get(), metrics, emSize , 0); 368 369 int ttcIndex; 370 std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex)); 371 size_t fontSize = fontAsset ? fontAsset->getLength() : 0; 372 if (0 == fontSize) { 373 SkDebugf("Error: (SkTypeface)(%p)::openStream() returned " 374 "empty stream (%p) when identified as kType1CID_Font " 375 "or kTrueType_Font.\n", face, fontAsset.get()); 376 } else { 377 switch (type) { 378 case SkAdvancedTypefaceMetrics::kTrueType_Font: { 379 #ifdef SK_PDF_USE_SFNTLY 380 if (!SkToBool(metrics.fFlags & 381 SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag)) { 382 sk_sp<SkPDFStream> subsetStream = get_subset_font_stream( 383 std::move(fontAsset), this->glyphUsage(), 384 metrics.fFontName.c_str(), ttcIndex); 385 if (subsetStream) { 386 descriptor->insertObjRef("FontFile2", std::move(subsetStream)); 387 break; 388 } 389 // If subsetting fails, fall back to original font data. 390 fontAsset.reset(face->openStream(&ttcIndex)); 391 SkASSERT(fontAsset); 392 SkASSERT(fontAsset->getLength() == fontSize); 393 if (!fontAsset || fontAsset->getLength() == 0) { break; } 394 } 395 #endif // SK_PDF_USE_SFNTLY 396 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset)); 397 fontStream->dict()->insertInt("Length1", fontSize); 398 descriptor->insertObjRef("FontFile2", std::move(fontStream)); 399 break; 400 } 401 case SkAdvancedTypefaceMetrics::kType1CID_Font: { 402 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset)); 403 fontStream->dict()->insertName("Subtype", "CIDFontType0C"); 404 descriptor->insertObjRef("FontFile3", std::move(fontStream)); 405 break; 406 } 407 default: 408 SkASSERT(false); 409 } 410 } 411 412 auto newCIDFont = sk_make_sp<SkPDFDict>("Font"); 413 newCIDFont->insertObjRef("FontDescriptor", std::move(descriptor)); 414 newCIDFont->insertName("BaseFont", metrics.fFontName); 415 416 switch (type) { 417 case SkAdvancedTypefaceMetrics::kType1CID_Font: 418 newCIDFont->insertName("Subtype", "CIDFontType0"); 419 break; 420 case SkAdvancedTypefaceMetrics::kTrueType_Font: 421 newCIDFont->insertName("Subtype", "CIDFontType2"); 422 newCIDFont->insertName("CIDToGIDMap", "Identity"); 423 break; 424 default: 425 SkASSERT(false); 426 } 427 auto sysInfo = sk_make_sp<SkPDFDict>(); 428 sysInfo->insertString("Registry", "Adobe"); 429 sysInfo->insertString("Ordering", "Identity"); 430 sysInfo->insertInt("Supplement", 0); 431 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); 432 433 int16_t defaultWidth = 0; 434 { 435 int emSize; 436 SkAutoGlyphCache glyphCache = SkPDFFont::MakeVectorCache(face, &emSize); 437 sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray( 438 glyphCache.get(), &this->glyphUsage(), SkToS16(emSize), &defaultWidth); 439 if (widths && widths->size() > 0) { 440 newCIDFont->insertObject("W", std::move(widths)); 441 } 442 newCIDFont->insertScalar( 443 "DW", scaleFromFontUnits(defaultWidth, SkToS16(emSize))); 444 } 445 446 //////////////////////////////////////////////////////////////////////////// 447 448 this->insertName("Subtype", "Type0"); 449 this->insertName("BaseFont", metrics.fFontName); 450 this->insertName("Encoding", "Identity-H"); 451 auto descendantFonts = sk_make_sp<SkPDFArray>(); 452 descendantFonts->appendObjRef(std::move(newCIDFont)); 453 this->insertObject("DescendantFonts", std::move(descendantFonts)); 454 455 if (metrics.fGlyphToUnicode.count() > 0) { 456 this->insertObjRef("ToUnicode", 457 SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode, 458 &this->glyphUsage(), 459 multiByteGlyphs(), 460 firstGlyphID(), 461 lastGlyphID())); 462 } 463 SkDEBUGCODE(fPopulated = true); 464 return; 465 } 466 467 /////////////////////////////////////////////////////////////////////////////// 468 // class SkPDFType1Font 469 /////////////////////////////////////////////////////////////////////////////// 470 471 static sk_sp<SkPDFDict> make_type1_font_descriptor( 472 SkTypeface* typeface, 473 const SkAdvancedTypefaceMetrics& info) { 474 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); 475 uint16_t emSize = SkToU16(typeface->getUnitsPerEm()); 476 add_common_font_descriptor_entries(descriptor.get(), info, emSize, 0); 477 if (!can_embed(info)) { 478 return descriptor; 479 } 480 int ttcIndex; 481 size_t header SK_INIT_TO_AVOID_WARNING; 482 size_t data SK_INIT_TO_AVOID_WARNING; 483 size_t trailer SK_INIT_TO_AVOID_WARNING; 484 std::unique_ptr<SkStreamAsset> rawFontData(typeface->openStream(&ttcIndex)); 485 sk_sp<SkData> fontData = SkPDFConvertType1FontStream(std::move(rawFontData), 486 &header, &data, &trailer); 487 if (fontData) { 488 auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData)); 489 fontStream->dict()->insertInt("Length1", header); 490 fontStream->dict()->insertInt("Length2", data); 491 fontStream->dict()->insertInt("Length3", trailer); 492 descriptor->insertObjRef("FontFile", std::move(fontStream)); 493 } 494 return descriptor; 495 } 496 497 static void populate_type_1_font(SkPDFDict* font, 498 const SkAdvancedTypefaceMetrics& info, 499 SkTypeface* typeface, 500 SkGlyphID firstGlyphID, 501 SkGlyphID lastGlyphID) { 502 font->insertName("Subtype", "Type1"); 503 font->insertName("BaseFont", info.fFontName); 504 505 // glyphCount not including glyph 0 506 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID; 507 SkASSERT(glyphCount > 0 && glyphCount <= 255); 508 font->insertInt("FirstChar", (size_t)0); 509 font->insertInt("LastChar", (size_t)glyphCount); 510 { 511 int emSize; 512 SkAutoGlyphCache glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize); 513 auto widths = sk_make_sp<SkPDFArray>(); 514 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX; 515 widths->appendScalar(from_font_units(advance, SkToU16(emSize))); 516 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) { 517 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX; 518 widths->appendScalar(from_font_units(advance, SkToU16(emSize))); 519 } 520 font->insertObject("Widths", std::move(widths)); 521 } 522 auto encDiffs = sk_make_sp<SkPDFArray>(); 523 encDiffs->reserve(lastGlyphID - firstGlyphID + 3); 524 encDiffs->appendInt(0); 525 const SkTArray<SkString>& glyphNames = info.fGlyphNames; 526 SkASSERT(glyphNames.count() > lastGlyphID); 527 encDiffs->appendName(glyphNames[0].c_str()); 528 const SkString unknown("UNKNOWN"); 529 for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) { 530 const bool valid = gID < glyphNames.count() && !glyphNames[gID].isEmpty(); 531 const SkString& name = valid ? glyphNames[gID] : unknown; 532 encDiffs->appendName(name); 533 } 534 535 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); 536 encoding->insertObject("Differences", std::move(encDiffs)); 537 font->insertObject("Encoding", std::move(encoding)); 538 } 539 540 SkPDFType1Font::SkPDFType1Font(SkPDFFont::Info info, 541 const SkAdvancedTypefaceMetrics& metrics, 542 SkPDFCanon* canon) 543 : SkPDFFont(std::move(info)) 544 { 545 SkFontID fontID = this->typeface()->uniqueID(); 546 sk_sp<SkPDFDict> fontDescriptor; 547 if (SkPDFDict** ptr = canon->fFontDescriptors.find(fontID)) { 548 fontDescriptor = sk_ref_sp(*ptr); 549 } else { 550 fontDescriptor = make_type1_font_descriptor(this->typeface(), metrics); 551 canon->fFontDescriptors.set(fontID, SkRef(fontDescriptor.get())); 552 } 553 this->insertObjRef("FontDescriptor", std::move(fontDescriptor)); 554 // TODO(halcanary): subset this (advances and names). 555 populate_type_1_font(this, metrics, this->typeface(), 556 this->firstGlyphID(), this->lastGlyphID()); 557 } 558 559 /////////////////////////////////////////////////////////////////////////////// 560 // class SkPDFType3Font 561 /////////////////////////////////////////////////////////////////////////////// 562 563 namespace { 564 // returns [0, first, first+1, ... last-1, last] 565 struct SingleByteGlyphIdIterator { 566 SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last) 567 : fFirst(first), fLast(last) { 568 SkASSERT(fFirst > 0); 569 SkASSERT(fLast >= first); 570 } 571 struct Iter { 572 void operator++() { 573 fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1; 574 } 575 // This is an input_iterator 576 SkGlyphID operator*() const { return (SkGlyphID)fCurrent; } 577 bool operator!=(const Iter& rhs) const { 578 return fCurrent != rhs.fCurrent; 579 } 580 Iter(SkGlyphID f, int c) : fFirst(f), fCurrent(c) {} 581 private: 582 const SkGlyphID fFirst; 583 int fCurrent; // must be int to make fLast+1 to fit 584 }; 585 Iter begin() const { return Iter(fFirst, 0); } 586 Iter end() const { return Iter(fFirst, (int)fLast + 1); } 587 private: 588 const SkGlyphID fFirst; 589 const SkGlyphID fLast; 590 }; 591 } 592 593 static void add_type3_font_info(SkPDFCanon* canon, 594 SkPDFDict* font, 595 SkTypeface* typeface, 596 const SkBitSet& subset, 597 SkGlyphID firstGlyphID, 598 SkGlyphID lastGlyphID) { 599 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon); 600 SkASSERT(lastGlyphID >= firstGlyphID); 601 // Remove unused glyphs at the end of the range. 602 // Keep the lastGlyphID >= firstGlyphID invariant true. 603 while (lastGlyphID > firstGlyphID && !subset.has(lastGlyphID)) { 604 --lastGlyphID; 605 } 606 int unitsPerEm; 607 SkAutoGlyphCache cache = SkPDFFont::MakeVectorCache(typeface, &unitsPerEm); 608 SkScalar emSize = (SkScalar)unitsPerEm; 609 font->insertName("Subtype", "Type3"); 610 // Flip about the x-axis and scale by 1/emSize. 611 SkMatrix fontMatrix; 612 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize)); 613 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); 614 615 auto charProcs = sk_make_sp<SkPDFDict>(); 616 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); 617 618 auto encDiffs = sk_make_sp<SkPDFArray>(); 619 // length(firstGlyphID .. lastGlyphID) == lastGlyphID - firstGlyphID + 1 620 // plus 1 for glyph 0; 621 SkASSERT(firstGlyphID > 0); 622 SkASSERT(lastGlyphID >= firstGlyphID); 623 int glyphCount = lastGlyphID - firstGlyphID + 2; 624 // one other entry for the index of first glyph. 625 encDiffs->reserve(glyphCount + 1); 626 encDiffs->appendInt(0); // index of first glyph 627 628 auto widthArray = sk_make_sp<SkPDFArray>(); 629 widthArray->reserve(glyphCount); 630 631 SkIRect bbox = SkIRect::MakeEmpty(); 632 633 sk_sp<SkPDFStream> emptyStream; 634 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) { 635 bool skipGlyph = gID != 0 && !subset.has(gID); 636 SkString characterName; 637 SkScalar advance = 0.0f; 638 SkIRect glyphBBox; 639 if (skipGlyph) { 640 characterName.set("g0"); 641 } else { 642 characterName.printf("g%X", gID); 643 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); 644 advance = SkFloatToScalar(glyph.fAdvanceX); 645 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, 646 glyph.fWidth, glyph.fHeight); 647 bbox.join(glyphBBox); 648 const SkPath* path = cache->findPath(glyph); 649 if (path && !path->isEmpty()) { 650 SkDynamicMemoryWStream content; 651 setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox, 652 &content); 653 SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content); 654 SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(), 655 &content); 656 charProcs->insertObjRef( 657 characterName, sk_make_sp<SkPDFStream>( 658 std::unique_ptr<SkStreamAsset>(content.detachAsStream()))); 659 } else { 660 if (!emptyStream) { 661 emptyStream = sk_make_sp<SkPDFStream>( 662 std::unique_ptr<SkStreamAsset>( 663 new SkMemoryStream((size_t)0))); 664 } 665 charProcs->insertObjRef(characterName, emptyStream); 666 } 667 } 668 encDiffs->appendName(characterName.c_str()); 669 widthArray->appendScalar(advance); 670 } 671 672 encoding->insertObject("Differences", std::move(encDiffs)); 673 font->insertInt("FirstChar", 0); 674 font->insertInt("LastChar", lastGlyphID - firstGlyphID + 1); 675 /* FontBBox: "A rectangle expressed in the glyph coordinate 676 system, specifying the font bounding box. This is the smallest 677 rectangle enclosing the shape that would result if all of the 678 glyphs of the font were placed with their origins coincident and 679 then filled." */ 680 auto fontBBox = sk_make_sp<SkPDFArray>(); 681 fontBBox->reserve(4); 682 fontBBox->appendInt(bbox.left()); 683 fontBBox->appendInt(bbox.bottom()); 684 fontBBox->appendInt(bbox.right()); 685 fontBBox->appendInt(bbox.top()); 686 font->insertObject("FontBBox", std::move(fontBBox)); 687 font->insertName("CIDToGIDMap", "Identity"); 688 if (metrics && metrics->fGlyphToUnicode.count() > 0) { 689 font->insertObjRef("ToUnicode", 690 SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode, 691 &subset, 692 false, 693 firstGlyphID, 694 lastGlyphID)); 695 } 696 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); 697 int32_t fontDescriptorFlags = kPdfSymbolic; 698 if (metrics) { 699 // Type3 FontDescriptor does not require all the same fields. 700 descriptor->insertName("FontName", metrics->fFontName); 701 descriptor->insertInt("ItalicAngle", metrics->fItalicAngle); 702 fontDescriptorFlags |= (int32_t)metrics->fStyle; 703 } 704 descriptor->insertInt("Flags", fontDescriptorFlags); 705 font->insertObjRef("FontDescriptor", std::move(descriptor)); 706 font->insertObject("Widths", std::move(widthArray)); 707 font->insertObject("Encoding", std::move(encoding)); 708 font->insertObject("CharProcs", std::move(charProcs)); 709 } 710 711 SkPDFType3Font::SkPDFType3Font(SkPDFFont::Info info, 712 const SkAdvancedTypefaceMetrics& metrics) 713 : SkPDFFont(std::move(info)) {} 714 715 void SkPDFType3Font::getFontSubset(SkPDFCanon* canon) { 716 add_type3_font_info(canon, this, this->typeface(), this->glyphUsage(), 717 this->firstGlyphID(), this->lastGlyphID()); 718 } 719 720 //////////////////////////////////////////////////////////////////////////////// 721 722 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { 723 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon); 724 return metrics && can_embed(*metrics); 725 } 726 727 void SkPDFFont::drop() { 728 fTypeface = nullptr; 729 fGlyphUsage.~SkBitSet(); 730 new (&fGlyphUsage) SkBitSet(0); 731 this->SkPDFDict::drop(); 732 } 733