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