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