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 | |
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 | |
61 | |
62 | // scale from em-units to base-1000, returning as a SkScalar |
63 | inline SkScalar from_font_units(SkScalar scaled, uint16_t emSize) { |
64 | return emSize == 1000 ? scaled : scaled * 1000 / emSize; |
65 | } |
66 | |
67 | inline SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { |
68 | return from_font_units(SkIntToScalar(val), emSize); |
69 | } |
70 | |
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 | |
102 | static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) { |
103 | return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag); |
104 | } |
105 | |
106 | const 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 | |
156 | const 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 | |
169 | SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkAdvancedTypefaceMetrics& metrics) { |
170 | if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) || |
171 | SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag)) { |
172 | // force Type3 fallback. |
173 | return SkAdvancedTypefaceMetrics::kOther_Font; |
174 | } |
175 | return metrics.fType; |
176 | } |
177 | |
178 | static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) { |
179 | return gid != 0 ? gid - (gid - 1) % 255 : 1; |
180 | } |
181 | |
182 | SkPDFFont* 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 | |
225 | SkPDFFont::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 | |
239 | void 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. |
270 | static 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 | |
283 | static 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 | |
410 | namespace { |
411 | // returns [0, first, first+1, ... last-1, last] |
412 | struct 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); } |
434 | private: |
435 | const SkGlyphID fFirst; |
436 | const SkGlyphID fLast; |
437 | }; |
438 | } |
439 | |
440 | struct ImageAndOffset { |
441 | sk_sp<SkImage> fImage; |
442 | SkIPoint fOffset; |
443 | }; |
444 | static 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 {SkImage::MakeFromBitmap(bm), {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 | |
484 | static 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 |
513 | static constexpr float kBitmapFontSize = SK_PDF_BITMAP_GLYPH_RASTER_SIZE; |
514 | #else |
515 | static constexpr float kBitmapFontSize = 64; |
516 | #endif |
517 | |
518 | SkStrikeSpec 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 | |
529 | static 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 | |
669 | void SkPDFFont::emitSubset(SkPDFDocument* doc) const { |
670 | SkASSERT(fFontType != SkPDFFont().fFontType); // not default value |
671 | switch (fFontType) { |
672 | case SkAdvancedTypefaceMetrics::kType1CID_Font: |
673 | case SkAdvancedTypefaceMetrics::kTrueType_Font: |
674 | return emit_subset_type0(*this, doc); |
675 | #ifndef SK_PDF_DO_NOT_SUPPORT_TYPE_1_FONTS |
676 | case SkAdvancedTypefaceMetrics::kType1_Font: |
677 | return SkPDFEmitType1Font(*this, doc); |
678 | #endif |
679 | default: |
680 | return emit_subset_type3(*this, doc); |
681 | } |
682 | } |
683 | |
684 | //////////////////////////////////////////////////////////////////////////////// |
685 | |
686 | bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFDocument* doc) { |
687 | const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc); |
688 | return metrics && can_embed(*metrics); |
689 | } |
690 | |
691 | |