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 "SkPDFFont.h" 9 10 #include "SkData.h" 11 #include "SkFont.h" 12 #include "SkImagePriv.h" 13 #include "SkMacros.h" 14 #include "SkMakeUnique.h" 15 #include "SkPDFBitmap.h" 16 #include "SkPDFDocument.h" 17 #include "SkPDFConvertType1FontStream.h" 18 #include "SkPDFDevice.h" 19 #include "SkPDFDocumentPriv.h" 20 #include "SkPDFMakeCIDGlyphWidthsArray.h" 21 #include "SkPDFMakeToUnicodeCmap.h" 22 #include "SkPDFResourceDict.h" 23 #include "SkPDFSubsetFont.h" 24 #include "SkPDFUtils.h" 25 #include "SkPaint.h" 26 #include "SkRefCnt.h" 27 #include "SkScalar.h" 28 #include "SkStream.h" 29 #include "SkStrike.h" 30 #include "SkTo.h" 31 #include "SkTypes.h" 32 #include "SkUTF.h" 33 34 SkExclusiveStrikePtr SkPDFFont::MakeVectorCache(SkTypeface* face, int* size) { 35 SkFont font; 36 font.setHinting(kNo_SkFontHinting); 37 font.setTypeface(sk_ref_sp(face)); 38 int unitsPerEm = face->getUnitsPerEm(); 39 if (unitsPerEm <= 0) { 40 unitsPerEm = 1024; 41 } 42 if (size) { 43 *size = unitsPerEm; 44 } 45 font.setSize((SkScalar)unitsPerEm); 46 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); 47 return SkStrikeCache::FindOrCreateStrikeExclusive( 48 font, SkPaint(), props, SkScalerContextFlags::kFakeGammaAndBoostContrast, SkMatrix::I()); 49 } 50 51 namespace { 52 // PDF's notion of symbolic vs non-symbolic is related to the character set, not 53 // symbols vs. characters. Rarely is a font the right character set to call it 54 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) 55 static const int32_t kPdfSymbolic = 4; 56 57 58 // scale from em-units to base-1000, returning as a SkScalar 59 SkScalar from_font_units(SkScalar scaled, uint16_t emSize) { 60 if (emSize == 1000) { 61 return scaled; 62 } else { 63 return scaled * 1000 / emSize; 64 } 65 } 66 67 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { 68 return from_font_units(SkIntToScalar(val), emSize); 69 } 70 71 72 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, 73 SkDynamicMemoryWStream* content) { 74 // Specify width and bounding box for the glyph. 75 SkPDFUtils::AppendScalar(width, content); 76 content->writeText(" 0 "); 77 content->writeDecAsText(box.fLeft); 78 content->writeText(" "); 79 content->writeDecAsText(box.fTop); 80 content->writeText(" "); 81 content->writeDecAsText(box.fRight); 82 content->writeText(" "); 83 content->writeDecAsText(box.fBottom); 84 content->writeText(" d1\n"); 85 } 86 } // namespace 87 88 /////////////////////////////////////////////////////////////////////////////// 89 // class SkPDFFont 90 /////////////////////////////////////////////////////////////////////////////// 91 92 /* Resources are canonicalized and uniqueified by pointer so there has to be 93 * some additional state indicating which subset of the font is used. It 94 * must be maintained at the document granularity. 95 */ 96 97 SkPDFFont::~SkPDFFont() = default; 98 99 SkPDFFont::SkPDFFont(SkPDFFont&&) = default; 100 101 SkPDFFont& SkPDFFont::operator=(SkPDFFont&&) = default; 102 103 static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) { 104 return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag); 105 } 106 107 const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(const SkTypeface* typeface, 108 SkPDFDocument* canon) { 109 SkASSERT(typeface); 110 SkFontID id = typeface->uniqueID(); 111 if (std::unique_ptr<SkAdvancedTypefaceMetrics>* ptr = canon->fTypefaceMetrics.find(id)) { 112 return ptr->get(); // canon retains ownership. 113 } 114 int count = typeface->countGlyphs(); 115 if (count <= 0 || count > 1 + SkTo<int>(UINT16_MAX)) { 116 // Cache nullptr to skip this check. Use SkSafeUnref(). 117 canon->fTypefaceMetrics.set(id, nullptr); 118 return nullptr; 119 } 120 std::unique_ptr<SkAdvancedTypefaceMetrics> metrics = typeface->getAdvancedMetrics(); 121 if (!metrics) { 122 metrics = skstd::make_unique<SkAdvancedTypefaceMetrics>(); 123 } 124 125 if (0 == metrics->fStemV || 0 == metrics->fCapHeight) { 126 SkFont font; 127 font.setHinting(kNo_SkFontHinting); 128 font.setTypeface(sk_ref_sp(typeface)); 129 font.setSize(1000); // glyph coordinate system 130 if (0 == metrics->fStemV) { 131 // Figure out a good guess for StemV - Min width of i, I, !, 1. 132 // This probably isn't very good with an italic font. 133 int16_t stemV = SHRT_MAX; 134 for (char c : {'i', 'I', '!', '1'}) { 135 uint16_t g = font.unicharToGlyph(c); 136 SkRect bounds; 137 font.getBounds(&g, 1, &bounds, nullptr); 138 stemV = SkTMin(stemV, SkToS16(SkScalarRoundToInt(bounds.width()))); 139 } 140 metrics->fStemV = stemV; 141 } 142 if (0 == metrics->fCapHeight) { 143 // Figure out a good guess for CapHeight: average the height of M and X. 144 SkScalar capHeight = 0; 145 for (char c : {'M', 'X'}) { 146 uint16_t g = font.unicharToGlyph(c); 147 SkRect bounds; 148 font.getBounds(&g, 1, &bounds, nullptr); 149 capHeight += bounds.height(); 150 } 151 metrics->fCapHeight = SkToS16(SkScalarRoundToInt(capHeight / 2)); 152 } 153 } 154 return canon->fTypefaceMetrics.set(id, std::move(metrics))->get(); 155 } 156 157 const std::vector<SkUnichar>& SkPDFFont::GetUnicodeMap(const SkTypeface* typeface, 158 SkPDFDocument* canon) { 159 SkASSERT(typeface); 160 SkASSERT(canon); 161 SkFontID id = typeface->uniqueID(); 162 if (std::vector<SkUnichar>* ptr = canon->fToUnicodeMap.find(id)) { 163 return *ptr; 164 } 165 std::vector<SkUnichar> buffer(typeface->countGlyphs()); 166 typeface->getGlyphToUnicodeMap(buffer.data()); 167 return *canon->fToUnicodeMap.set(id, std::move(buffer)); 168 } 169 170 SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkAdvancedTypefaceMetrics& metrics) { 171 if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) || 172 SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag)) { 173 // force Type3 fallback. 174 return SkAdvancedTypefaceMetrics::kOther_Font; 175 } 176 return metrics.fType; 177 } 178 179 static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) { 180 return gid != 0 ? gid - (gid - 1) % 255 : 1; 181 } 182 183 static bool has_outline_glyph(SkGlyphID gid, SkStrike* cache) { 184 const SkGlyph& glyph = cache->getGlyphIDMetrics(gid); 185 return glyph.isEmpty() || cache->findPath(glyph); 186 } 187 188 SkPDFFont* SkPDFFont::GetFontResource(SkPDFDocument* doc, 189 SkStrike* cache, 190 SkTypeface* face, 191 SkGlyphID glyphID) { 192 SkASSERT(doc); 193 SkASSERT(face); // All SkPDFDevice::internalDrawText ensures this. 194 const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, doc); 195 SkASSERT(fontMetrics); // SkPDFDevice::internalDrawText ensures the typeface is good. 196 // GetMetrics only returns null to signify a bad typeface. 197 const SkAdvancedTypefaceMetrics& metrics = *fontMetrics; 198 SkAdvancedTypefaceMetrics::FontType type = SkPDFFont::FontType(metrics); 199 if (!has_outline_glyph(glyphID, cache)) { 200 type = SkAdvancedTypefaceMetrics::kOther_Font; 201 } 202 bool multibyte = SkPDFFont::IsMultiByte(type); 203 SkGlyphID subsetCode = multibyte ? 0 : first_nonzero_glyph_for_single_byte_encoding(glyphID); 204 uint64_t fontID = (static_cast<uint64_t>(SkTypeface::UniqueID(face)) << 16) | subsetCode; 205 206 if (SkPDFFont* found = doc->fFontMap.find(fontID)) { 207 SkASSERT(multibyte == found->multiByteGlyphs()); 208 return found; 209 } 210 211 sk_sp<SkTypeface> typeface(sk_ref_sp(face)); 212 SkASSERT(typeface); 213 214 SkGlyphID lastGlyph = SkToU16(typeface->countGlyphs() - 1); 215 216 // should be caught by SkPDFDevice::internalDrawText 217 SkASSERT(glyphID <= lastGlyph); 218 219 SkGlyphID firstNonZeroGlyph; 220 if (multibyte) { 221 firstNonZeroGlyph = 1; 222 } else { 223 firstNonZeroGlyph = subsetCode; 224 lastGlyph = SkToU16(SkTMin<int>((int)lastGlyph, 254 + (int)subsetCode)); 225 } 226 auto ref = doc->reserveRef(); 227 return doc->fFontMap.set( 228 fontID, SkPDFFont(std::move(typeface), firstNonZeroGlyph, lastGlyph, type, ref)); 229 } 230 231 SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface, 232 SkGlyphID firstGlyphID, 233 SkGlyphID lastGlyphID, 234 SkAdvancedTypefaceMetrics::FontType fontType, 235 SkPDFIndirectReference indirectReference) 236 : fTypeface(std::move(typeface)) 237 , fGlyphUsage(firstGlyphID, lastGlyphID) 238 , fIndirectReference(indirectReference) 239 , fFontType(fontType) {} 240 241 static void add_common_font_descriptor_entries(SkPDFDict* descriptor, 242 const SkAdvancedTypefaceMetrics& metrics, 243 uint16_t emSize, 244 int16_t defaultWidth) { 245 descriptor->insertName("FontName", metrics.fPostScriptName); 246 descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic)); 247 descriptor->insertScalar("Ascent", 248 scaleFromFontUnits(metrics.fAscent, emSize)); 249 descriptor->insertScalar("Descent", 250 scaleFromFontUnits(metrics.fDescent, emSize)); 251 descriptor->insertScalar("StemV", 252 scaleFromFontUnits(metrics.fStemV, emSize)); 253 descriptor->insertScalar("CapHeight", 254 scaleFromFontUnits(metrics.fCapHeight, emSize)); 255 descriptor->insertInt("ItalicAngle", metrics.fItalicAngle); 256 descriptor->insertObject("FontBBox", 257 SkPDFMakeArray(scaleFromFontUnits(metrics.fBBox.left(), emSize), 258 scaleFromFontUnits(metrics.fBBox.bottom(), emSize), 259 scaleFromFontUnits(metrics.fBBox.right(), emSize), 260 scaleFromFontUnits(metrics.fBBox.top(), emSize))); 261 if (defaultWidth > 0) { 262 descriptor->insertScalar("MissingWidth", 263 scaleFromFontUnits(defaultWidth, emSize)); 264 } 265 } 266 267 /////////////////////////////////////////////////////////////////////////////// 268 // Type0Font 269 /////////////////////////////////////////////////////////////////////////////// 270 271 #ifdef SK_PDF_SUBSET_SUPPORTED 272 273 // if possible, make no copy. 274 static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) { 275 SkASSERT(stream); 276 (void)stream->rewind(); 277 SkASSERT(stream->hasLength()); 278 size_t size = stream->getLength(); 279 if (const void* base = stream->getMemoryBase()) { 280 SkData::ReleaseProc proc = 281 [](const void*, void* ctx) { delete (SkStreamAsset*)ctx; }; 282 return SkData::MakeWithProc(base, size, proc, stream.release()); 283 } 284 return SkData::MakeFromStream(stream.get(), size); 285 } 286 #endif // SK_PDF_SUBSET_SUPPORTED 287 288 static void emit_subset_type0(const SkPDFFont& font, SkPDFDocument* doc) { 289 const SkAdvancedTypefaceMetrics* metricsPtr = 290 SkPDFFont::GetMetrics(font.typeface(), doc); 291 SkASSERT(metricsPtr); 292 if (!metricsPtr) { return; } 293 const SkAdvancedTypefaceMetrics& metrics = *metricsPtr; 294 SkASSERT(can_embed(metrics)); 295 SkAdvancedTypefaceMetrics::FontType type = font.getType(); 296 SkTypeface* face = font.typeface(); 297 SkASSERT(face); 298 299 auto descriptor = SkPDFMakeDict("FontDescriptor"); 300 uint16_t emSize = SkToU16(font.typeface()->getUnitsPerEm()); 301 add_common_font_descriptor_entries(descriptor.get(), metrics, emSize , 0); 302 303 int ttcIndex; 304 std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex)); 305 size_t fontSize = fontAsset ? fontAsset->getLength() : 0; 306 if (0 == fontSize) { 307 SkDebugf("Error: (SkTypeface)(%p)::openStream() returned " 308 "empty stream (%p) when identified as kType1CID_Font " 309 "or kTrueType_Font.\n", face, fontAsset.get()); 310 } else { 311 switch (type) { 312 case SkAdvancedTypefaceMetrics::kTrueType_Font: { 313 #ifdef SK_PDF_SUBSET_SUPPORTED 314 if (!SkToBool(metrics.fFlags & 315 SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag)) { 316 SkASSERT(font.firstGlyphID() == 1); 317 sk_sp<SkData> subsetFontData = SkPDFSubsetFont( 318 stream_to_data(std::move(fontAsset)), font.glyphUsage(), 319 metrics.fFontName.c_str(), ttcIndex); 320 if (subsetFontData) { 321 std::unique_ptr<SkPDFDict> tmp = SkPDFMakeDict(); 322 tmp->insertInt("Length1", SkToInt(subsetFontData->size())); 323 descriptor->insertRef( 324 "FontFile2", 325 SkPDFStreamOut(std::move(tmp), 326 SkMemoryStream::Make(std::move(subsetFontData)), 327 doc, true)); 328 break; 329 } 330 // If subsetting fails, fall back to original font data. 331 fontAsset.reset(face->openStream(&ttcIndex)); 332 SkASSERT(fontAsset); 333 SkASSERT(fontAsset->getLength() == fontSize); 334 if (!fontAsset || fontAsset->getLength() == 0) { break; } 335 } 336 #endif // SK_PDF_SUBSET_SUPPORTED 337 std::unique_ptr<SkPDFDict> tmp = SkPDFMakeDict(); 338 tmp->insertInt("Length1", fontSize); 339 descriptor->insertRef("FontFile2", 340 SkPDFStreamOut(std::move(tmp), std::move(fontAsset), 341 doc, true)); 342 break; 343 } 344 case SkAdvancedTypefaceMetrics::kType1CID_Font: { 345 std::unique_ptr<SkPDFDict> tmp = SkPDFMakeDict(); 346 tmp->insertName("Subtype", "CIDFontType0C"); 347 descriptor->insertRef("FontFile3", 348 SkPDFStreamOut(std::move(tmp), std::move(fontAsset), 349 doc, true)); 350 break; 351 } 352 default: 353 SkASSERT(false); 354 } 355 } 356 357 auto newCIDFont = SkPDFMakeDict("Font"); 358 newCIDFont->insertRef("FontDescriptor", doc->emit(*descriptor)); 359 newCIDFont->insertName("BaseFont", metrics.fPostScriptName); 360 361 switch (type) { 362 case SkAdvancedTypefaceMetrics::kType1CID_Font: 363 newCIDFont->insertName("Subtype", "CIDFontType0"); 364 break; 365 case SkAdvancedTypefaceMetrics::kTrueType_Font: 366 newCIDFont->insertName("Subtype", "CIDFontType2"); 367 newCIDFont->insertName("CIDToGIDMap", "Identity"); 368 break; 369 default: 370 SkASSERT(false); 371 } 372 auto sysInfo = SkPDFMakeDict(); 373 sysInfo->insertString("Registry", "Adobe"); 374 sysInfo->insertString("Ordering", "Identity"); 375 sysInfo->insertInt("Supplement", 0); 376 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); 377 378 int16_t defaultWidth = 0; 379 { 380 int emSize; 381 auto glyphCache = SkPDFFont::MakeVectorCache(face, &emSize); 382 std::unique_ptr<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray( 383 glyphCache.get(), &font.glyphUsage(), SkToS16(emSize), &defaultWidth); 384 if (widths && widths->size() > 0) { 385 newCIDFont->insertObject("W", std::move(widths)); 386 } 387 newCIDFont->insertScalar( 388 "DW", scaleFromFontUnits(defaultWidth, SkToS16(emSize))); 389 } 390 391 //////////////////////////////////////////////////////////////////////////// 392 393 SkPDFDict fontDict("Font"); 394 fontDict.insertName("Subtype", "Type0"); 395 fontDict.insertName("BaseFont", metrics.fPostScriptName); 396 fontDict.insertName("Encoding", "Identity-H"); 397 auto descendantFonts = SkPDFMakeArray(); 398 descendantFonts->appendRef(doc->emit(*newCIDFont)); 399 fontDict.insertObject("DescendantFonts", std::move(descendantFonts)); 400 401 const std::vector<SkUnichar>& glyphToUnicode = 402 SkPDFFont::GetUnicodeMap(font.typeface(), doc); 403 SkASSERT(SkToSizeT(font.typeface()->countGlyphs()) == glyphToUnicode.size()); 404 std::unique_ptr<SkStreamAsset> toUnicode = 405 SkPDFMakeToUnicodeCmap(glyphToUnicode.data(), 406 &font.glyphUsage(), 407 font.multiByteGlyphs(), 408 font.firstGlyphID(), 409 font.lastGlyphID()); 410 fontDict.insertRef("ToUnicode", SkPDFStreamOut(nullptr, std::move(toUnicode), doc)); 411 412 doc->emit(fontDict, font.indirectReference()); 413 } 414 415 /////////////////////////////////////////////////////////////////////////////// 416 // Type1Font 417 /////////////////////////////////////////////////////////////////////////////// 418 419 static SkPDFIndirectReference make_type1_font_descriptor(SkPDFDocument* doc, 420 const SkTypeface* typeface, 421 const SkAdvancedTypefaceMetrics* info) { 422 SkPDFDict descriptor("FontDescriptor"); 423 uint16_t emSize = SkToU16(typeface->getUnitsPerEm()); 424 if (info) { 425 add_common_font_descriptor_entries(&descriptor, *info, emSize, 0); 426 if (can_embed(*info)) { 427 int ttcIndex; 428 size_t header SK_INIT_TO_AVOID_WARNING; 429 size_t data SK_INIT_TO_AVOID_WARNING; 430 size_t trailer SK_INIT_TO_AVOID_WARNING; 431 std::unique_ptr<SkStreamAsset> rawFontData(typeface->openStream(&ttcIndex)); 432 sk_sp<SkData> fontData = SkPDFConvertType1FontStream(std::move(rawFontData), 433 &header, &data, &trailer); 434 if (fontData) { 435 std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict(); 436 dict->insertInt("Length1", header); 437 dict->insertInt("Length2", data); 438 dict->insertInt("Length3", trailer); 439 auto fontStream = SkMemoryStream::Make(std::move(fontData)); 440 descriptor.insertRef("FontFile", SkPDFStreamOut(std::move(dict), 441 std::move(fontStream), doc, true)); 442 } 443 } 444 } 445 return doc->emit(descriptor); 446 } 447 448 449 static const std::vector<SkString>& type_1_glyphnames(SkPDFDocument* canon, 450 const SkTypeface* typeface) { 451 SkFontID fontID = typeface->uniqueID(); 452 const std::vector<SkString>* glyphNames = canon->fType1GlyphNames.find(fontID); 453 if (!glyphNames) { 454 std::vector<SkString> names(typeface->countGlyphs()); 455 SkPDFFont::GetType1GlyphNames(*typeface, names.data()); 456 glyphNames = canon->fType1GlyphNames.set(fontID, std::move(names)); 457 } 458 SkASSERT(glyphNames); 459 return *glyphNames; 460 } 461 462 static SkPDFIndirectReference type1_font_descriptor(SkPDFDocument* doc, 463 const SkTypeface* typeface) { 464 SkFontID fontID = typeface->uniqueID(); 465 if (SkPDFIndirectReference* ptr = doc->fFontDescriptors.find(fontID)) { 466 return *ptr; 467 } 468 const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc); 469 auto fontDescriptor = make_type1_font_descriptor(doc, typeface, info); 470 doc->fFontDescriptors.set(fontID, fontDescriptor); 471 return fontDescriptor; 472 } 473 474 static void emit_subset_type1(const SkPDFFont& pdfFont, SkPDFDocument* doc) { 475 SkTypeface* typeface = pdfFont.typeface(); 476 const std::vector<SkString> glyphNames = type_1_glyphnames(doc, typeface); 477 SkGlyphID firstGlyphID = pdfFont.firstGlyphID(); 478 SkGlyphID lastGlyphID = pdfFont.lastGlyphID(); 479 480 SkPDFDict font("Font"); 481 font.insertRef("FontDescriptor", type1_font_descriptor(doc, typeface)); 482 font.insertName("Subtype", "Type1"); 483 if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc)) { 484 font.insertName("BaseFont", info->fPostScriptName); 485 } 486 487 // glyphCount not including glyph 0 488 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID; 489 SkASSERT(glyphCount > 0 && glyphCount <= 255); 490 font.insertInt("FirstChar", (size_t)0); 491 font.insertInt("LastChar", (size_t)glyphCount); 492 { 493 int emSize; 494 auto glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize); 495 auto widths = SkPDFMakeArray(); 496 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX; 497 widths->appendScalar(from_font_units(advance, SkToU16(emSize))); 498 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) { 499 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX; 500 widths->appendScalar(from_font_units(advance, SkToU16(emSize))); 501 } 502 font.insertObject("Widths", std::move(widths)); 503 } 504 auto encDiffs = SkPDFMakeArray(); 505 encDiffs->reserve(lastGlyphID - firstGlyphID + 3); 506 encDiffs->appendInt(0); 507 508 SkASSERT(glyphNames.size() > lastGlyphID); 509 const SkString unknown("UNKNOWN"); 510 encDiffs->appendName(glyphNames[0].isEmpty() ? unknown : glyphNames[0]); 511 for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) { 512 encDiffs->appendName(glyphNames[gID].isEmpty() ? unknown : glyphNames[gID]); 513 } 514 515 auto encoding = SkPDFMakeDict("Encoding"); 516 encoding->insertObject("Differences", std::move(encDiffs)); 517 font.insertObject("Encoding", std::move(encoding)); 518 519 doc->emit(font, pdfFont.indirectReference()); 520 } 521 522 void SkPDFFont::GetType1GlyphNames(const SkTypeface& face, SkString* dst) { 523 face.getPostScriptGlyphNames(dst); 524 } 525 526 /////////////////////////////////////////////////////////////////////////////// 527 // PDFType3Font 528 /////////////////////////////////////////////////////////////////////////////// 529 530 namespace { 531 // returns [0, first, first+1, ... last-1, last] 532 struct SingleByteGlyphIdIterator { 533 SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last) 534 : fFirst(first), fLast(last) { 535 SkASSERT(fFirst > 0); 536 SkASSERT(fLast >= first); 537 } 538 struct Iter { 539 void operator++() { 540 fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1; 541 } 542 // This is an input_iterator 543 SkGlyphID operator*() const { return (SkGlyphID)fCurrent; } 544 bool operator!=(const Iter& rhs) const { 545 return fCurrent != rhs.fCurrent; 546 } 547 Iter(SkGlyphID f, int c) : fFirst(f), fCurrent(c) {} 548 private: 549 const SkGlyphID fFirst; 550 int fCurrent; // must be int to make fLast+1 to fit 551 }; 552 Iter begin() const { return Iter(fFirst, 0); } 553 Iter end() const { return Iter(fFirst, (int)fLast + 1); } 554 private: 555 const SkGlyphID fFirst; 556 const SkGlyphID fLast; 557 }; 558 } 559 560 struct ImageAndOffset { 561 sk_sp<SkImage> fImage; 562 SkIPoint fOffset; 563 }; 564 static ImageAndOffset to_image(SkGlyphID gid, SkStrike* cache) { 565 (void)cache->findImage(cache->getGlyphIDMetrics(gid)); 566 SkMask mask; 567 cache->getGlyphIDMetrics(gid).toMask(&mask); 568 if (!mask.fImage) { 569 return {nullptr, {0, 0}}; 570 } 571 SkIRect bounds = mask.fBounds; 572 SkBitmap bm; 573 switch (mask.fFormat) { 574 case SkMask::kBW_Format: 575 bm.allocPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height())); 576 for (int y = 0; y < bm.height(); ++y) { 577 for (int x8 = 0; x8 < bm.width(); x8 += 8) { 578 uint8_t v = *mask.getAddr1(x8 + bounds.x(), y + bounds.y()); 579 int e = SkTMin(x8 + 8, bm.width()); 580 for (int x = x8; x < e; ++x) { 581 *bm.getAddr8(x, y) = (v >> (x & 0x7)) & 0x1 ? 0xFF : 0x00; 582 } 583 } 584 } 585 bm.setImmutable(); 586 return {SkImage::MakeFromBitmap(bm), {bounds.x(), bounds.y()}}; 587 case SkMask::kA8_Format: 588 bm.installPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height()), 589 mask.fImage, mask.fRowBytes); 590 return {SkMakeImageFromRasterBitmap(bm, kAlways_SkCopyPixelsMode), 591 {bounds.x(), bounds.y()}}; 592 case SkMask::kARGB32_Format: 593 bm.installPixels(SkImageInfo::MakeN32Premul(bounds.width(), bounds.height()), 594 mask.fImage, mask.fRowBytes); 595 return {SkMakeImageFromRasterBitmap(bm, kAlways_SkCopyPixelsMode), 596 {bounds.x(), bounds.y()}}; 597 case SkMask::k3D_Format: 598 case SkMask::kLCD16_Format: 599 default: 600 SkASSERT(false); 601 return {nullptr, {0, 0}}; 602 } 603 } 604 605 static SkPDFIndirectReference type3_descriptor(SkPDFDocument* doc, 606 const SkTypeface* typeface, 607 SkStrike* cache) { 608 if (SkPDFIndirectReference* ptr = doc->fType3FontDescriptors.find(typeface->uniqueID())) { 609 return *ptr; 610 } 611 612 SkPDFDict descriptor("FontDescriptor"); 613 int32_t fontDescriptorFlags = kPdfSymbolic; 614 if (const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc)) { 615 // Type3 FontDescriptor does not require all the same fields. 616 descriptor.insertName("FontName", metrics->fPostScriptName); 617 descriptor.insertInt("ItalicAngle", metrics->fItalicAngle); 618 fontDescriptorFlags |= (int32_t)metrics->fStyle; 619 // Adobe requests CapHeight, XHeight, and StemV be added 620 // to "greatly help our workflow downstream". 621 if (metrics->fCapHeight != 0) { descriptor.insertInt("CapHeight", metrics->fCapHeight); } 622 if (metrics->fStemV != 0) { descriptor.insertInt("StemV", metrics->fStemV); } 623 SkScalar xHeight = cache->getFontMetrics().fXHeight; 624 if (xHeight != 0) { 625 descriptor.insertScalar("XHeight", xHeight); 626 } 627 } 628 descriptor.insertInt("Flags", fontDescriptorFlags); 629 SkPDFIndirectReference ref = doc->emit(descriptor); 630 doc->fType3FontDescriptors.set(typeface->uniqueID(), ref); 631 return ref; 632 } 633 634 635 static void emit_subset_type3(const SkPDFFont& pdfFont, SkPDFDocument* doc) { 636 SkTypeface* typeface = pdfFont.typeface(); 637 SkGlyphID firstGlyphID = pdfFont.firstGlyphID(); 638 SkGlyphID lastGlyphID = pdfFont.lastGlyphID(); 639 const SkPDFGlyphUse& subset = pdfFont.glyphUsage(); 640 SkASSERT(lastGlyphID >= firstGlyphID); 641 // Remove unused glyphs at the end of the range. 642 // Keep the lastGlyphID >= firstGlyphID invariant true. 643 while (lastGlyphID > firstGlyphID && !subset.has(lastGlyphID)) { 644 --lastGlyphID; 645 } 646 int unitsPerEm; 647 auto cache = SkPDFFont::MakeVectorCache(typeface, &unitsPerEm); 648 SkASSERT(cache); 649 SkScalar emSize = (SkScalar)unitsPerEm; 650 651 SkPDFDict font("Font"); 652 font.insertName("Subtype", "Type3"); 653 // Flip about the x-axis and scale by 1/emSize. 654 SkMatrix fontMatrix; 655 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize)); 656 font.insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); 657 658 auto charProcs = SkPDFMakeDict(); 659 auto encoding = SkPDFMakeDict("Encoding"); 660 661 auto encDiffs = SkPDFMakeArray(); 662 // length(firstGlyphID .. lastGlyphID) == lastGlyphID - firstGlyphID + 1 663 // plus 1 for glyph 0; 664 SkASSERT(firstGlyphID > 0); 665 SkASSERT(lastGlyphID >= firstGlyphID); 666 int glyphCount = lastGlyphID - firstGlyphID + 2; 667 // one other entry for the index of first glyph. 668 encDiffs->reserve(glyphCount + 1); 669 encDiffs->appendInt(0); // index of first glyph 670 671 auto widthArray = SkPDFMakeArray(); 672 widthArray->reserve(glyphCount); 673 674 SkIRect bbox = SkIRect::MakeEmpty(); 675 676 std::vector<std::pair<SkGlyphID, SkPDFIndirectReference>> imageGlyphs; 677 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) { 678 bool skipGlyph = gID != 0 && !subset.has(gID); 679 SkString characterName; 680 SkScalar advance = 0.0f; 681 SkIRect glyphBBox; 682 if (skipGlyph) { 683 characterName.set("g0"); 684 } else { 685 characterName.printf("g%X", gID); 686 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); 687 advance = SkFloatToScalar(glyph.fAdvanceX); 688 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, 689 glyph.fWidth, glyph.fHeight); 690 bbox.join(glyphBBox); 691 const SkPath* path = cache->findPath(glyph); 692 SkDynamicMemoryWStream content; 693 if (path && !path->isEmpty()) { 694 setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox, &content); 695 SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content); 696 SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(), &content); 697 } else { 698 auto pimg = to_image(gID, cache.get()); 699 if (!pimg.fImage) { 700 setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox, 701 &content); 702 } else { 703 imageGlyphs.emplace_back(gID, SkPDFSerializeImage(pimg.fImage.get(), doc)); 704 SkPDFUtils::AppendScalar(SkFloatToScalar(glyph.fAdvanceX), &content); 705 content.writeText(" 0 d0\n"); 706 content.writeDecAsText(pimg.fImage->width()); 707 content.writeText(" 0 0 "); 708 content.writeDecAsText(-pimg.fImage->height()); 709 content.writeText(" "); 710 content.writeDecAsText(pimg.fOffset.x()); 711 content.writeText(" "); 712 content.writeDecAsText(pimg.fImage->height() + pimg.fOffset.y()); 713 content.writeText(" cm\n/X"); 714 content.write(characterName.c_str(), characterName.size()); 715 content.writeText(" Do\n"); 716 } 717 } 718 charProcs->insertRef(characterName, SkPDFStreamOut(nullptr, 719 content.detachAsStream(), doc)); 720 } 721 encDiffs->appendName(std::move(characterName)); 722 widthArray->appendScalar(advance); 723 } 724 725 if (!imageGlyphs.empty()) { 726 auto d0 = SkPDFMakeDict(); 727 for (const auto& pair : imageGlyphs) { 728 d0->insertRef(SkStringPrintf("Xg%X", pair.first), pair.second); 729 } 730 auto d1 = SkPDFMakeDict(); 731 d1->insertObject("XObject", std::move(d0)); 732 font.insertObject("Resources", std::move(d1)); 733 } 734 735 encoding->insertObject("Differences", std::move(encDiffs)); 736 font.insertInt("FirstChar", 0); 737 font.insertInt("LastChar", lastGlyphID - firstGlyphID + 1); 738 /* FontBBox: "A rectangle expressed in the glyph coordinate 739 system, specifying the font bounding box. This is the smallest 740 rectangle enclosing the shape that would result if all of the 741 glyphs of the font were placed with their origins coincident and 742 then filled." */ 743 font.insertObject("FontBBox", SkPDFMakeArray(bbox.left(), 744 bbox.bottom(), 745 bbox.right(), 746 bbox.top())); 747 748 font.insertName("CIDToGIDMap", "Identity"); 749 750 const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(typeface, doc); 751 SkASSERT(glyphToUnicode.size() == SkToSizeT(typeface->countGlyphs())); 752 auto toUnicodeCmap = SkPDFMakeToUnicodeCmap(glyphToUnicode.data(), 753 &subset, 754 false, 755 firstGlyphID, 756 lastGlyphID); 757 font.insertRef("ToUnicode", SkPDFStreamOut(nullptr, std::move(toUnicodeCmap), doc)); 758 font.insertRef("FontDescriptor", type3_descriptor(doc, typeface, cache.get())); 759 font.insertObject("Widths", std::move(widthArray)); 760 font.insertObject("Encoding", std::move(encoding)); 761 font.insertObject("CharProcs", std::move(charProcs)); 762 763 doc->emit(font, pdfFont.indirectReference()); 764 } 765 766 767 void SkPDFFont::emitSubset(SkPDFDocument* doc) const { 768 SkASSERT(fFontType != SkPDFFont().fFontType); // not default value 769 switch (fFontType) { 770 case SkAdvancedTypefaceMetrics::kType1CID_Font: 771 case SkAdvancedTypefaceMetrics::kTrueType_Font: 772 return emit_subset_type0(*this, doc); 773 case SkAdvancedTypefaceMetrics::kType1_Font: 774 return emit_subset_type1(*this, doc); 775 default: 776 return emit_subset_type3(*this, doc); 777 } 778 } 779 780 //////////////////////////////////////////////////////////////////////////////// 781 782 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFDocument* doc) { 783 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc); 784 return metrics && can_embed(*metrics); 785 } 786 787