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