blob: 41b0d4da723824e3c56ef060eb50b2dcd099b9b8 [file] [log] [blame]
vandebo@chromium.org28be72b2010-11-11 21:37:00 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 Google Inc.
vandebo@chromium.org28be72b2010-11-11 21:37:00 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
vandebo@chromium.org28be72b2010-11-11 21:37:00 +00006 */
7
reed@google.com8a85d0c2011-06-24 19:12:12 +00008#include "SkData.h"
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +00009#include "SkGlyphCache.h"
vandebo@chromium.org28be72b2010-11-11 21:37:00 +000010#include "SkPaint.h"
halcanaryfb62b3d2015-01-21 09:59:14 -080011#include "SkPDFCanon.h"
halcanary8eccc302016-08-09 13:04:34 -070012#include "SkPDFConvertType1FontStream.h"
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +000013#include "SkPDFDevice.h"
halcanary86b6eab2016-08-17 07:57:27 -070014#include "SkPDFMakeCIDGlyphWidthsArray.h"
halcanary8eccc302016-08-09 13:04:34 -070015#include "SkPDFMakeToUnicodeCmap.h"
vandebo@chromium.org28be72b2010-11-11 21:37:00 +000016#include "SkPDFFont.h"
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +000017#include "SkPDFUtils.h"
vandebo@chromium.orgf77e27d2011-03-10 22:50:28 +000018#include "SkRefCnt.h"
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +000019#include "SkScalar.h"
vandebo@chromium.org2a22e102011-01-25 21:01:34 +000020#include "SkStream.h"
vandebo@chromium.org325cb9a2011-03-30 18:36:29 +000021#include "SkTypes.h"
vandebo@chromium.org28be72b2010-11-11 21:37:00 +000022#include "SkUtils.h"
23
halcanary650e20d2016-08-25 09:07:02 -070024#ifdef SK_PDF_USE_SFNTLY
25 #include "sample/chromium/font_subsetter.h"
vandebo@chromium.org1f165892011-07-26 02:11:41 +000026#endif
27
Hal Canaryaa3af7b2017-03-06 16:18:49 -050028SkAutoGlyphCache SkPDFFont::MakeVectorCache(SkTypeface* face, int* size) {
29 SkPaint tmpPaint;
30 tmpPaint.setHinting(SkPaint::kNo_Hinting);
31 tmpPaint.setTypeface(sk_ref_sp(face));
32 int unitsPerEm = face->getUnitsPerEm();
33 if (unitsPerEm <= 0) {
34 unitsPerEm = 1024;
35 }
36 if (size) {
37 *size = unitsPerEm;
38 }
39 tmpPaint.setTextSize((SkScalar)unitsPerEm);
40 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
41 SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr);
42 SkASSERT(glyphCache.get());
43 return glyphCache;
44}
45
halcanary8eccc302016-08-09 13:04:34 -070046namespace {
vandebo@chromium.orgdcf9c192013-03-13 20:01:51 +000047// PDF's notion of symbolic vs non-symbolic is related to the character set, not
48// symbols vs. characters. Rarely is a font the right character set to call it
49// non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1)
halcanary3d01c622016-08-31 12:52:35 -070050static const int32_t kPdfSymbolic = 4;
vandebo@chromium.orgdcf9c192013-03-13 20:01:51 +000051
halcanary530032a2016-08-18 14:22:52 -070052struct SkPDFType0Font final : public SkPDFFont {
53 SkPDFType0Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
halcanary8eccc302016-08-09 13:04:34 -070054 virtual ~SkPDFType0Font();
halcanary530032a2016-08-18 14:22:52 -070055 void getFontSubset(SkPDFCanon*) override;
halcanary8eccc302016-08-09 13:04:34 -070056#ifdef SK_DEBUG
halcanary530032a2016-08-18 14:22:52 -070057 void emitObject(SkWStream*, const SkPDFObjNumMap&) const override;
halcanary8eccc302016-08-09 13:04:34 -070058 bool fPopulated;
59#endif
halcanary8eccc302016-08-09 13:04:34 -070060 typedef SkPDFDict INHERITED;
61};
62
halcanary530032a2016-08-18 14:22:52 -070063struct SkPDFType1Font final : public SkPDFFont {
64 SkPDFType1Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&, SkPDFCanon*);
halcanarycee13422016-08-18 09:52:48 -070065 virtual ~SkPDFType1Font() {}
halcanary530032a2016-08-18 14:22:52 -070066 void getFontSubset(SkPDFCanon*) override {} // TODO(halcanary): implement
halcanary8eccc302016-08-09 13:04:34 -070067};
68
halcanary530032a2016-08-18 14:22:52 -070069struct SkPDFType3Font final : public SkPDFFont {
70 SkPDFType3Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
halcanary7e8d5d32016-08-12 07:59:38 -070071 virtual ~SkPDFType3Font() {}
halcanary530032a2016-08-18 14:22:52 -070072 void getFontSubset(SkPDFCanon*) override;
halcanary8eccc302016-08-09 13:04:34 -070073};
vandebo@chromium.org28be72b2010-11-11 21:37:00 +000074
vandebo@chromium.org98594282011-07-25 22:34:12 +000075///////////////////////////////////////////////////////////////////////////////
76// File-Local Functions
77///////////////////////////////////////////////////////////////////////////////
78
reed@google.com3f0dcf92011-03-18 21:23:45 +000079// scale from em-units to base-1000, returning as a SkScalar
halcanary8eccc302016-08-09 13:04:34 -070080SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
reed@google.com3f0dcf92011-03-18 21:23:45 +000081 if (emSize == 1000) {
82 return scaled;
83 } else {
Mike Reed8be952a2017-02-13 20:44:33 -050084 return scaled * 1000 / emSize;
reed@google.com3f0dcf92011-03-18 21:23:45 +000085 }
vandebo@chromium.orgc48b2b32011-02-02 02:11:22 +000086}
87
halcanary8eccc302016-08-09 13:04:34 -070088SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
89 return from_font_units(SkIntToScalar(val), emSize);
90}
91
92
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +000093void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box,
halcanary7e8d5d32016-08-12 07:59:38 -070094 SkDynamicMemoryWStream* content) {
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +000095 // Specify width and bounding box for the glyph.
halcanarybc4696b2015-05-06 10:56:04 -070096 SkPDFUtils::AppendScalar(width, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000097 content->writeText(" 0 ");
98 content->writeDecAsText(box.fLeft);
99 content->writeText(" ");
100 content->writeDecAsText(box.fTop);
101 content->writeText(" ");
102 content->writeDecAsText(box.fRight);
103 content->writeText(" ");
104 content->writeDecAsText(box.fBottom);
105 content->writeText(" d1\n");
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000106}
107
halcanary8103a342016-03-08 15:10:16 -0800108static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) {
109 auto bbox = sk_make_sp<SkPDFArray>();
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000110 bbox->reserve(4);
reed@google.comc789cf12011-07-20 12:14:33 +0000111 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize));
112 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize));
113 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize));
114 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize));
halcanary51d04d32016-03-08 13:03:55 -0800115 return bbox;
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000116}
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000117} // namespace
118
vandebo@chromium.org98594282011-07-25 22:34:12 +0000119///////////////////////////////////////////////////////////////////////////////
120// class SkPDFFont
121///////////////////////////////////////////////////////////////////////////////
122
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000123/* Font subset design: It would be nice to be able to subset fonts
124 * (particularly type 3 fonts), but it's a lot of work and not a priority.
125 *
126 * Resources are canonicalized and uniqueified by pointer so there has to be
127 * some additional state indicating which subset of the font is used. It
128 * must be maintained at the page granularity and then combined at the document
129 * granularity. a) change SkPDFFont to fill in its state on demand, kind of
130 * like SkPDFGraphicState. b) maintain a per font glyph usage class in each
131 * page/pdf device. c) in the document, retrieve the per font glyph usage
132 * from each page and combine it and ask for a resource with that subset.
133 */
134
halcanary2e3f9d82015-02-27 12:41:03 -0800135SkPDFFont::~SkPDFFont() {}
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000136
halcanarycee13422016-08-18 09:52:48 -0700137static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
138 return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
vandebo0f9bad02014-06-19 11:05:39 -0700139}
140
halcanarycee13422016-08-18 09:52:48 -0700141const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface,
142 SkPDFCanon* canon) {
halcanary4871f222016-08-26 13:17:44 -0700143 SkASSERT(typeface);
144 SkFontID id = typeface->uniqueID();
halcanarycee13422016-08-18 09:52:48 -0700145 if (SkAdvancedTypefaceMetrics** ptr = canon->fTypefaceMetrics.find(id)) {
146 return *ptr;
147 }
halcanary4871f222016-08-26 13:17:44 -0700148 int count = typeface->countGlyphs();
149 if (count <= 0 || count > 1 + SK_MaxU16) {
150 // Cache nullptr to skip this check. Use SkSafeUnref().
151 canon->fTypefaceMetrics.set(id, nullptr);
152 return nullptr;
halcanarycee13422016-08-18 09:52:48 -0700153 }
154 sk_sp<SkAdvancedTypefaceMetrics> metrics(
155 typeface->getAdvancedTypefaceMetrics(
156 SkTypeface::kGlyphNames_PerGlyphInfo | SkTypeface::kToUnicode_PerGlyphInfo,
157 nullptr, 0));
158 if (!metrics) {
halcanary4871f222016-08-26 13:17:44 -0700159 metrics = sk_make_sp<SkAdvancedTypefaceMetrics>();
halcanary17484322016-08-29 09:47:48 -0700160 }
halcanarycee13422016-08-18 09:52:48 -0700161 return *canon->fTypefaceMetrics.set(id, metrics.release());
162}
163
halcanaryc2f9ec12016-09-12 08:55:29 -0700164SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkAdvancedTypefaceMetrics& metrics) {
Hal Canaryb3480e12016-09-30 14:53:15 -0400165 if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) ||
166 SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag)) {
halcanarycee13422016-08-18 09:52:48 -0700167 // force Type3 fallback.
168 return SkAdvancedTypefaceMetrics::kOther_Font;
169 }
170 return metrics.fType;
171}
172
halcanary4871f222016-08-26 13:17:44 -0700173static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) {
halcanarycee13422016-08-18 09:52:48 -0700174 return gid != 0 ? gid - (gid - 1) % 255 : 1;
175}
176
halcanary792c80f2015-02-20 07:21:05 -0800177SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon,
halcanary32875882016-08-16 09:36:23 -0700178 SkTypeface* face,
halcanarycee13422016-08-18 09:52:48 -0700179 SkGlyphID glyphID) {
halcanary792c80f2015-02-20 07:21:05 -0800180 SkASSERT(canon);
halcanary4871f222016-08-26 13:17:44 -0700181 SkASSERT(face); // All SkPDFDevice::internalDrawText ensures this.
halcanarycee13422016-08-18 09:52:48 -0700182 const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, canon);
halcanary4871f222016-08-26 13:17:44 -0700183 SkASSERT(fontMetrics); // SkPDFDevice::internalDrawText ensures the typeface is good.
184 // GetMetrics only returns null to signify a bad typeface.
halcanarycee13422016-08-18 09:52:48 -0700185 const SkAdvancedTypefaceMetrics& metrics = *fontMetrics;
halcanaryc2f9ec12016-09-12 08:55:29 -0700186 SkAdvancedTypefaceMetrics::FontType type = SkPDFFont::FontType(metrics);
halcanarycee13422016-08-18 09:52:48 -0700187 bool multibyte = SkPDFFont::IsMultiByte(type);
halcanary4871f222016-08-26 13:17:44 -0700188 SkGlyphID subsetCode = multibyte ? 0 : first_nonzero_glyph_for_single_byte_encoding(glyphID);
189 uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | subsetCode;
halcanarycee13422016-08-18 09:52:48 -0700190
191 if (SkPDFFont** found = canon->fFontMap.find(fontID)) {
halcanary4871f222016-08-26 13:17:44 -0700192 SkPDFFont* foundFont = *found;
193 SkASSERT(foundFont && multibyte == foundFont->multiByteGlyphs());
194 return SkRef(foundFont);
halcanarycee13422016-08-18 09:52:48 -0700195 }
196
halcanary4871f222016-08-26 13:17:44 -0700197 sk_sp<SkTypeface> typeface(sk_ref_sp(face));
halcanary7e8d5d32016-08-12 07:59:38 -0700198 SkASSERT(typeface);
halcanary4871f222016-08-26 13:17:44 -0700199
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500200 SkGlyphID lastGlyph = SkToU16(typeface->countGlyphs() - 1);
halcanary4871f222016-08-26 13:17:44 -0700201
202 // should be caught by SkPDFDevice::internalDrawText
203 SkASSERT(glyphID <= lastGlyph);
halcanary32875882016-08-16 09:36:23 -0700204
halcanary530032a2016-08-18 14:22:52 -0700205 SkGlyphID firstNonZeroGlyph;
halcanary530032a2016-08-18 14:22:52 -0700206 if (multibyte) {
207 firstNonZeroGlyph = 1;
halcanary530032a2016-08-18 14:22:52 -0700208 } else {
halcanary4871f222016-08-26 13:17:44 -0700209 firstNonZeroGlyph = subsetCode;
210 lastGlyph = SkToU16(SkTMin<int>((int)lastGlyph, 254 + (int)subsetCode));
halcanary530032a2016-08-18 14:22:52 -0700211 }
212 SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, type};
halcanary32875882016-08-16 09:36:23 -0700213 sk_sp<SkPDFFont> font;
214 switch (type) {
215 case SkAdvancedTypefaceMetrics::kType1CID_Font:
216 case SkAdvancedTypefaceMetrics::kTrueType_Font:
halcanarycee13422016-08-18 09:52:48 -0700217 SkASSERT(multibyte);
halcanary530032a2016-08-18 14:22:52 -0700218 font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics);
halcanary32875882016-08-16 09:36:23 -0700219 break;
220 case SkAdvancedTypefaceMetrics::kType1_Font:
halcanarycee13422016-08-18 09:52:48 -0700221 SkASSERT(!multibyte);
halcanary530032a2016-08-18 14:22:52 -0700222 font = sk_make_sp<SkPDFType1Font>(std::move(info), metrics, canon);
halcanary32875882016-08-16 09:36:23 -0700223 break;
halcanarycee13422016-08-18 09:52:48 -0700224 default:
225 SkASSERT(!multibyte);
226 // Type3 is our fallback font.
halcanary530032a2016-08-18 14:22:52 -0700227 font = sk_make_sp<SkPDFType3Font>(std::move(info), metrics);
halcanary32875882016-08-16 09:36:23 -0700228 break;
halcanary32875882016-08-16 09:36:23 -0700229 }
halcanarycee13422016-08-18 09:52:48 -0700230 canon->fFontMap.set(fontID, SkRef(font.get()));
halcanary32875882016-08-16 09:36:23 -0700231 return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>.
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000232}
233
halcanary530032a2016-08-18 14:22:52 -0700234SkPDFFont::SkPDFFont(SkPDFFont::Info info)
halcanary792c80f2015-02-20 07:21:05 -0800235 : SkPDFDict("Font")
halcanary530032a2016-08-18 14:22:52 -0700236 , fTypeface(std::move(info.fTypeface))
237 , fGlyphUsage(info.fLastGlyphID + 1) // TODO(halcanary): Adjust mapping?
238 , fFirstGlyphID(info.fFirstGlyphID)
239 , fLastGlyphID(info.fLastGlyphID)
240 , fFontType(info.fFontType) {
halcanary7e8d5d32016-08-12 07:59:38 -0700241 SkASSERT(fTypeface);
vandebo@chromium.org98594282011-07-25 22:34:12 +0000242}
243
halcanary28c6d832016-08-16 10:29:38 -0700244static void add_common_font_descriptor_entries(SkPDFDict* descriptor,
245 const SkAdvancedTypefaceMetrics& metrics,
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500246 uint16_t emSize,
halcanary28c6d832016-08-16 10:29:38 -0700247 int16_t defaultWidth) {
halcanary28c6d832016-08-16 10:29:38 -0700248 descriptor->insertName("FontName", metrics.fFontName);
249 descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic));
250 descriptor->insertScalar("Ascent",
251 scaleFromFontUnits(metrics.fAscent, emSize));
252 descriptor->insertScalar("Descent",
253 scaleFromFontUnits(metrics.fDescent, emSize));
254 descriptor->insertScalar("StemV",
255 scaleFromFontUnits(metrics.fStemV, emSize));
256 descriptor->insertScalar("CapHeight",
257 scaleFromFontUnits(metrics.fCapHeight, emSize));
258 descriptor->insertInt("ItalicAngle", metrics.fItalicAngle);
259 descriptor->insertObject(
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500260 "FontBBox", makeFontBBox(metrics.fBBox, emSize));
vandebo@chromium.org98594282011-07-25 22:34:12 +0000261 if (defaultWidth > 0) {
halcanary28c6d832016-08-16 10:29:38 -0700262 descriptor->insertScalar("MissingWidth",
vandebo@chromium.org98594282011-07-25 22:34:12 +0000263 scaleFromFontUnits(defaultWidth, emSize));
264 }
vandebo@chromium.org98594282011-07-25 22:34:12 +0000265}
266
vandebo@chromium.org98594282011-07-25 22:34:12 +0000267///////////////////////////////////////////////////////////////////////////////
268// class SkPDFType0Font
269///////////////////////////////////////////////////////////////////////////////
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000270
halcanary530032a2016-08-18 14:22:52 -0700271SkPDFType0Font::SkPDFType0Font(
272 SkPDFFont::Info info,
273 const SkAdvancedTypefaceMetrics& metrics)
274 : SkPDFFont(std::move(info)) {
vandebo@chromium.org98594282011-07-25 22:34:12 +0000275 SkDEBUGCODE(fPopulated = false);
276}
277
278SkPDFType0Font::~SkPDFType0Font() {}
279
vandebo@chromium.org98594282011-07-25 22:34:12 +0000280
281#ifdef SK_DEBUG
halcanary37c46ca2015-03-31 12:30:20 -0700282void SkPDFType0Font::emitObject(SkWStream* stream,
halcanary530032a2016-08-18 14:22:52 -0700283 const SkPDFObjNumMap& objNumMap) const {
vandebo@chromium.org98594282011-07-25 22:34:12 +0000284 SkASSERT(fPopulated);
halcanary530032a2016-08-18 14:22:52 -0700285 return INHERITED::emitObject(stream, objNumMap);
vandebo@chromium.org98594282011-07-25 22:34:12 +0000286}
287#endif
288
halcanary650e20d2016-08-25 09:07:02 -0700289#ifdef SK_PDF_USE_SFNTLY
halcanaryfe8f0e02016-07-27 14:14:04 -0700290// if possible, make no copy.
291static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) {
292 SkASSERT(stream);
293 (void)stream->rewind();
294 SkASSERT(stream->hasLength());
295 size_t size = stream->getLength();
296 if (const void* base = stream->getMemoryBase()) {
297 SkData::ReleaseProc proc =
halcanary426a2452016-09-08 15:04:38 -0700298 [](const void*, void* ctx) { delete (SkStreamAsset*)ctx; };
halcanaryfe8f0e02016-07-27 14:14:04 -0700299 return SkData::MakeWithProc(base, size, proc, stream.release());
300 }
301 return SkData::MakeFromStream(stream.get(), size);
302}
303
halcanary426a2452016-09-08 15:04:38 -0700304static sk_sp<SkPDFStream> get_subset_font_stream(
halcanaryfe8f0e02016-07-27 14:14:04 -0700305 std::unique_ptr<SkStreamAsset> fontAsset,
halcanary426a2452016-09-08 15:04:38 -0700306 const SkBitSet& glyphUsage,
307 const char* fontName,
308 int ttcIndex) {
309 // Generate glyph id array in format needed by sfntly.
310 // TODO(halcanary): sfntly should take a more compact format.
311 SkTDArray<unsigned> subset;
312 if (!glyphUsage.has(0)) {
313 subset.push(0); // Always include glyph 0.
314 }
315 glyphUsage.exportTo(&subset);
halcanaryfe8f0e02016-07-27 14:14:04 -0700316
317 unsigned char* subsetFont{nullptr};
halcanary426a2452016-09-08 15:04:38 -0700318 sk_sp<SkData> fontData(stream_to_data(std::move(fontAsset)));
Hal Canary7ad87932017-02-16 10:33:49 -0500319#if defined(GOOGLE3)
320 // TODO(halcanary): update GOOGLE3 to newest version of Sfntly.
halcanary426a2452016-09-08 15:04:38 -0700321 (void)ttcIndex;
322 int subsetFontSize = SfntlyWrapper::SubsetFont(fontName,
323 fontData->bytes(),
324 fontData->size(),
325 subset.begin(),
326 subset.count(),
327 &subsetFont);
328#else
329 (void)fontName;
330 int subsetFontSize = SfntlyWrapper::SubsetFont(ttcIndex,
331 fontData->bytes(),
332 fontData->size(),
333 subset.begin(),
334 subset.count(),
335 &subsetFont);
336#endif
337 fontData.reset();
338 subset.reset();
halcanaryfe8f0e02016-07-27 14:14:04 -0700339 SkASSERT(subsetFontSize > 0 || subsetFont == nullptr);
340 if (subsetFontSize < 1) {
341 return nullptr;
342 }
343 SkASSERT(subsetFont != nullptr);
344 auto subsetStream = sk_make_sp<SkPDFStream>(
345 SkData::MakeWithProc(
346 subsetFont, subsetFontSize,
347 [](const void* p, void*) { delete[] (unsigned char*)p; },
348 nullptr));
halcanaryfa251062016-07-29 10:13:18 -0700349 subsetStream->dict()->insertInt("Length1", subsetFontSize);
halcanaryfe8f0e02016-07-27 14:14:04 -0700350 return subsetStream;
351}
halcanary650e20d2016-08-25 09:07:02 -0700352#endif // SK_PDF_USE_SFNTLY
halcanaryfe8f0e02016-07-27 14:14:04 -0700353
halcanary530032a2016-08-18 14:22:52 -0700354void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) {
355 const SkAdvancedTypefaceMetrics* metricsPtr =
356 SkPDFFont::GetMetrics(this->typeface(), canon);
357 SkASSERT(metricsPtr);
358 if (!metricsPtr) { return; }
359 const SkAdvancedTypefaceMetrics& metrics = *metricsPtr;
halcanarycee13422016-08-18 09:52:48 -0700360 SkASSERT(can_embed(metrics));
halcanary28c6d832016-08-16 10:29:38 -0700361 SkAdvancedTypefaceMetrics::FontType type = this->getType();
362 SkTypeface* face = this->typeface();
363 SkASSERT(face);
vandebo@chromium.org98594282011-07-25 22:34:12 +0000364
halcanary28c6d832016-08-16 10:29:38 -0700365 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500366 uint16_t emSize = SkToU16(this->typeface()->getUnitsPerEm());
367 add_common_font_descriptor_entries(descriptor.get(), metrics, emSize , 0);
halcanaryfe8f0e02016-07-27 14:14:04 -0700368
halcanary426a2452016-09-08 15:04:38 -0700369 int ttcIndex;
370 std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex));
371 size_t fontSize = fontAsset ? fontAsset->getLength() : 0;
halcanary2a4d1e12016-09-22 14:13:16 -0700372 if (0 == fontSize) {
373 SkDebugf("Error: (SkTypeface)(%p)::openStream() returned "
374 "empty stream (%p) when identified as kType1CID_Font "
375 "or kTrueType_Font.\n", face, fontAsset.get());
376 } else {
halcanary426a2452016-09-08 15:04:38 -0700377 switch (type) {
378 case SkAdvancedTypefaceMetrics::kTrueType_Font: {
379 #ifdef SK_PDF_USE_SFNTLY
380 if (!SkToBool(metrics.fFlags &
381 SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag)) {
382 sk_sp<SkPDFStream> subsetStream = get_subset_font_stream(
383 std::move(fontAsset), this->glyphUsage(),
384 metrics.fFontName.c_str(), ttcIndex);
385 if (subsetStream) {
386 descriptor->insertObjRef("FontFile2", std::move(subsetStream));
387 break;
388 }
389 // If subsetting fails, fall back to original font data.
390 fontAsset.reset(face->openStream(&ttcIndex));
391 SkASSERT(fontAsset);
392 SkASSERT(fontAsset->getLength() == fontSize);
393 if (!fontAsset || fontAsset->getLength() == 0) { break; }
halcanary28c6d832016-08-16 10:29:38 -0700394 }
halcanary426a2452016-09-08 15:04:38 -0700395 #endif // SK_PDF_USE_SFNTLY
396 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
397 fontStream->dict()->insertInt("Length1", fontSize);
398 descriptor->insertObjRef("FontFile2", std::move(fontStream));
399 break;
halcanaryfe8f0e02016-07-27 14:14:04 -0700400 }
halcanary426a2452016-09-08 15:04:38 -0700401 case SkAdvancedTypefaceMetrics::kType1CID_Font: {
402 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
403 fontStream->dict()->insertName("Subtype", "CIDFontType0C");
404 descriptor->insertObjRef("FontFile3", std::move(fontStream));
405 break;
halcanary8e3f54d2016-08-30 11:58:52 -0700406 }
halcanary426a2452016-09-08 15:04:38 -0700407 default:
408 SkASSERT(false);
halcanary8e3f54d2016-08-30 11:58:52 -0700409 }
vandebo@chromium.org98594282011-07-25 22:34:12 +0000410 }
vandebo@chromium.org98594282011-07-25 22:34:12 +0000411
halcanary28c6d832016-08-16 10:29:38 -0700412 auto newCIDFont = sk_make_sp<SkPDFDict>("Font");
413 newCIDFont->insertObjRef("FontDescriptor", std::move(descriptor));
halcanary426a2452016-09-08 15:04:38 -0700414 newCIDFont->insertName("BaseFont", metrics.fFontName);
halcanary28c6d832016-08-16 10:29:38 -0700415
halcanary426a2452016-09-08 15:04:38 -0700416 switch (type) {
417 case SkAdvancedTypefaceMetrics::kType1CID_Font:
418 newCIDFont->insertName("Subtype", "CIDFontType0");
419 break;
420 case SkAdvancedTypefaceMetrics::kTrueType_Font:
421 newCIDFont->insertName("Subtype", "CIDFontType2");
422 newCIDFont->insertName("CIDToGIDMap", "Identity");
423 break;
424 default:
425 SkASSERT(false);
halcanary462d0142016-08-05 13:51:46 -0700426 }
halcanary28c6d832016-08-16 10:29:38 -0700427 auto sysInfo = sk_make_sp<SkPDFDict>();
halcanary59be20c2016-09-01 14:10:00 -0700428 sysInfo->insertString("Registry", "Adobe");
429 sysInfo->insertString("Ordering", "Identity");
halcanary28c6d832016-08-16 10:29:38 -0700430 sysInfo->insertInt("Supplement", 0);
431 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo));
432
halcanary28c6d832016-08-16 10:29:38 -0700433 int16_t defaultWidth = 0;
halcanary86b6eab2016-08-17 07:57:27 -0700434 {
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500435 int emSize;
436 SkAutoGlyphCache glyphCache = SkPDFFont::MakeVectorCache(face, &emSize);
halcanary86b6eab2016-08-17 07:57:27 -0700437 sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500438 glyphCache.get(), &this->glyphUsage(), SkToS16(emSize), &defaultWidth);
halcanary86b6eab2016-08-17 07:57:27 -0700439 if (widths && widths->size() > 0) {
440 newCIDFont->insertObject("W", std::move(widths));
441 }
442 newCIDFont->insertScalar(
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500443 "DW", scaleFromFontUnits(defaultWidth, SkToS16(emSize)));
halcanary28c6d832016-08-16 10:29:38 -0700444 }
445
halcanary28c6d832016-08-16 10:29:38 -0700446 ////////////////////////////////////////////////////////////////////////////
447
448 this->insertName("Subtype", "Type0");
449 this->insertName("BaseFont", metrics.fFontName);
450 this->insertName("Encoding", "Identity-H");
451 auto descendantFonts = sk_make_sp<SkPDFArray>();
452 descendantFonts->appendObjRef(std::move(newCIDFont));
453 this->insertObject("DescendantFonts", std::move(descendantFonts));
halcanarycee13422016-08-18 09:52:48 -0700454
455 if (metrics.fGlyphToUnicode.count() > 0) {
456 this->insertObjRef("ToUnicode",
457 SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode,
halcanary530032a2016-08-18 14:22:52 -0700458 &this->glyphUsage(),
halcanarycee13422016-08-18 09:52:48 -0700459 multiByteGlyphs(),
460 firstGlyphID(),
461 lastGlyphID()));
462 }
halcanary28c6d832016-08-16 10:29:38 -0700463 SkDEBUGCODE(fPopulated = true);
halcanary530032a2016-08-18 14:22:52 -0700464 return;
halcanary8eccc302016-08-09 13:04:34 -0700465}
466
vandebo@chromium.org98594282011-07-25 22:34:12 +0000467///////////////////////////////////////////////////////////////////////////////
468// class SkPDFType1Font
469///////////////////////////////////////////////////////////////////////////////
470
halcanarycee13422016-08-18 09:52:48 -0700471static sk_sp<SkPDFDict> make_type1_font_descriptor(
472 SkTypeface* typeface,
473 const SkAdvancedTypefaceMetrics& info) {
halcanaryece83922016-03-08 08:32:12 -0800474 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500475 uint16_t emSize = SkToU16(typeface->getUnitsPerEm());
476 add_common_font_descriptor_entries(descriptor.get(), info, emSize, 0);
halcanarycee13422016-08-18 09:52:48 -0700477 if (!can_embed(info)) {
478 return descriptor;
479 }
reed@google.comfed86bd2013-03-14 15:04:57 +0000480 int ttcIndex;
vandebo@chromium.org98594282011-07-25 22:34:12 +0000481 size_t header SK_INIT_TO_AVOID_WARNING;
482 size_t data SK_INIT_TO_AVOID_WARNING;
483 size_t trailer SK_INIT_TO_AVOID_WARNING;
halcanarycee13422016-08-18 09:52:48 -0700484 std::unique_ptr<SkStreamAsset> rawFontData(typeface->openStream(&ttcIndex));
halcanary8eccc302016-08-09 13:04:34 -0700485 sk_sp<SkData> fontData = SkPDFConvertType1FontStream(std::move(rawFontData),
486 &header, &data, &trailer);
halcanarycee13422016-08-18 09:52:48 -0700487 if (fontData) {
488 auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData));
489 fontStream->dict()->insertInt("Length1", header);
490 fontStream->dict()->insertInt("Length2", data);
491 fontStream->dict()->insertInt("Length3", trailer);
492 descriptor->insertObjRef("FontFile", std::move(fontStream));
vandebo@chromium.org98594282011-07-25 22:34:12 +0000493 }
halcanarycee13422016-08-18 09:52:48 -0700494 return descriptor;
vandebo@chromium.org98594282011-07-25 22:34:12 +0000495}
496
halcanarycee13422016-08-18 09:52:48 -0700497static void populate_type_1_font(SkPDFDict* font,
498 const SkAdvancedTypefaceMetrics& info,
499 SkTypeface* typeface,
500 SkGlyphID firstGlyphID,
501 SkGlyphID lastGlyphID) {
502 font->insertName("Subtype", "Type1");
503 font->insertName("BaseFont", info.fFontName);
vandebo@chromium.orgf77e27d2011-03-10 22:50:28 +0000504
halcanary8eccc302016-08-09 13:04:34 -0700505 // glyphCount not including glyph 0
506 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
507 SkASSERT(glyphCount > 0 && glyphCount <= 255);
halcanarycee13422016-08-18 09:52:48 -0700508 font->insertInt("FirstChar", (size_t)0);
509 font->insertInt("LastChar", (size_t)glyphCount);
halcanary462d0142016-08-05 13:51:46 -0700510 {
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500511 int emSize;
512 SkAutoGlyphCache glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize);
halcanary8eccc302016-08-09 13:04:34 -0700513 auto widths = sk_make_sp<SkPDFArray>();
514 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500515 widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
halcanary8eccc302016-08-09 13:04:34 -0700516 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
517 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500518 widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000519 }
halcanarycee13422016-08-18 09:52:48 -0700520 font->insertObject("Widths", std::move(widths));
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000521 }
halcanaryece83922016-03-08 08:32:12 -0800522 auto encDiffs = sk_make_sp<SkPDFArray>();
halcanary8eccc302016-08-09 13:04:34 -0700523 encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
524 encDiffs->appendInt(0);
halcanarycee13422016-08-18 09:52:48 -0700525 const SkTArray<SkString>& glyphNames = info.fGlyphNames;
halcanary8eccc302016-08-09 13:04:34 -0700526 SkASSERT(glyphNames.count() > lastGlyphID);
527 encDiffs->appendName(glyphNames[0].c_str());
528 const SkString unknown("UNKNOWN");
529 for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
530 const bool valid = gID < glyphNames.count() && !glyphNames[gID].isEmpty();
531 const SkString& name = valid ? glyphNames[gID] : unknown;
532 encDiffs->appendName(name);
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000533 }
534
halcanaryece83922016-03-08 08:32:12 -0800535 auto encoding = sk_make_sp<SkPDFDict>("Encoding");
halcanary8103a342016-03-08 15:10:16 -0800536 encoding->insertObject("Differences", std::move(encDiffs));
halcanarycee13422016-08-18 09:52:48 -0700537 font->insertObject("Encoding", std::move(encoding));
538}
539
halcanary530032a2016-08-18 14:22:52 -0700540SkPDFType1Font::SkPDFType1Font(SkPDFFont::Info info,
541 const SkAdvancedTypefaceMetrics& metrics,
halcanarycee13422016-08-18 09:52:48 -0700542 SkPDFCanon* canon)
halcanary530032a2016-08-18 14:22:52 -0700543 : SkPDFFont(std::move(info))
halcanarycee13422016-08-18 09:52:48 -0700544{
545 SkFontID fontID = this->typeface()->uniqueID();
546 sk_sp<SkPDFDict> fontDescriptor;
547 if (SkPDFDict** ptr = canon->fFontDescriptors.find(fontID)) {
548 fontDescriptor = sk_ref_sp(*ptr);
549 } else {
halcanary530032a2016-08-18 14:22:52 -0700550 fontDescriptor = make_type1_font_descriptor(this->typeface(), metrics);
halcanarycee13422016-08-18 09:52:48 -0700551 canon->fFontDescriptors.set(fontID, SkRef(fontDescriptor.get()));
552 }
553 this->insertObjRef("FontDescriptor", std::move(fontDescriptor));
halcanarycee13422016-08-18 09:52:48 -0700554 // TODO(halcanary): subset this (advances and names).
halcanary530032a2016-08-18 14:22:52 -0700555 populate_type_1_font(this, metrics, this->typeface(),
halcanarycee13422016-08-18 09:52:48 -0700556 this->firstGlyphID(), this->lastGlyphID());
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000557}
558
vandebo@chromium.org98594282011-07-25 22:34:12 +0000559///////////////////////////////////////////////////////////////////////////////
560// class SkPDFType3Font
561///////////////////////////////////////////////////////////////////////////////
562
halcanary7e8d5d32016-08-12 07:59:38 -0700563namespace {
564// returns [0, first, first+1, ... last-1, last]
565struct SingleByteGlyphIdIterator {
566 SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last)
567 : fFirst(first), fLast(last) {
568 SkASSERT(fFirst > 0);
569 SkASSERT(fLast >= first);
570 }
571 struct Iter {
572 void operator++() {
573 fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1;
574 }
575 // This is an input_iterator
576 SkGlyphID operator*() const { return (SkGlyphID)fCurrent; }
577 bool operator!=(const Iter& rhs) const {
578 return fCurrent != rhs.fCurrent;
579 }
580 Iter(SkGlyphID f, int c) : fFirst(f), fCurrent(c) {}
581 private:
582 const SkGlyphID fFirst;
583 int fCurrent; // must be int to make fLast+1 to fit
584 };
585 Iter begin() const { return Iter(fFirst, 0); }
586 Iter end() const { return Iter(fFirst, (int)fLast + 1); }
587private:
588 const SkGlyphID fFirst;
589 const SkGlyphID fLast;
590};
vandebo@chromium.org98594282011-07-25 22:34:12 +0000591}
592
halcanarycee13422016-08-18 09:52:48 -0700593static void add_type3_font_info(SkPDFCanon* canon,
594 SkPDFDict* font,
halcanary7e8d5d32016-08-12 07:59:38 -0700595 SkTypeface* typeface,
halcanary530032a2016-08-18 14:22:52 -0700596 const SkBitSet& subset,
halcanary7e8d5d32016-08-12 07:59:38 -0700597 SkGlyphID firstGlyphID,
598 SkGlyphID lastGlyphID) {
halcanary3d01c622016-08-31 12:52:35 -0700599 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon);
halcanary7e8d5d32016-08-12 07:59:38 -0700600 SkASSERT(lastGlyphID >= firstGlyphID);
halcanary17484322016-08-29 09:47:48 -0700601 // Remove unused glyphs at the end of the range.
602 // Keep the lastGlyphID >= firstGlyphID invariant true.
603 while (lastGlyphID > firstGlyphID && !subset.has(lastGlyphID)) {
604 --lastGlyphID;
605 }
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500606 int unitsPerEm;
607 SkAutoGlyphCache cache = SkPDFFont::MakeVectorCache(typeface, &unitsPerEm);
608 SkScalar emSize = (SkScalar)unitsPerEm;
halcanary7e8d5d32016-08-12 07:59:38 -0700609 font->insertName("Subtype", "Type3");
610 // Flip about the x-axis and scale by 1/emSize.
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000611 SkMatrix fontMatrix;
halcanary7e8d5d32016-08-12 07:59:38 -0700612 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize));
613 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix));
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000614
halcanaryece83922016-03-08 08:32:12 -0800615 auto charProcs = sk_make_sp<SkPDFDict>();
616 auto encoding = sk_make_sp<SkPDFDict>("Encoding");
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000617
halcanaryece83922016-03-08 08:32:12 -0800618 auto encDiffs = sk_make_sp<SkPDFArray>();
halcanary7e8d5d32016-08-12 07:59:38 -0700619 // length(firstGlyphID .. lastGlyphID) == lastGlyphID - firstGlyphID + 1
620 // plus 1 for glyph 0;
621 SkASSERT(firstGlyphID > 0);
622 SkASSERT(lastGlyphID >= firstGlyphID);
623 int glyphCount = lastGlyphID - firstGlyphID + 2;
624 // one other entry for the index of first glyph.
625 encDiffs->reserve(glyphCount + 1);
626 encDiffs->appendInt(0); // index of first glyph
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000627
halcanaryece83922016-03-08 08:32:12 -0800628 auto widthArray = sk_make_sp<SkPDFArray>();
halcanary7e8d5d32016-08-12 07:59:38 -0700629 widthArray->reserve(glyphCount);
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000630
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000631 SkIRect bbox = SkIRect::MakeEmpty();
halcanary7e8d5d32016-08-12 07:59:38 -0700632
633 sk_sp<SkPDFStream> emptyStream;
634 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
halcanary530032a2016-08-18 14:22:52 -0700635 bool skipGlyph = gID != 0 && !subset.has(gID);
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000636 SkString characterName;
halcanary7e8d5d32016-08-12 07:59:38 -0700637 SkScalar advance = 0.0f;
638 SkIRect glyphBBox;
639 if (skipGlyph) {
640 characterName.set("g0");
641 } else {
642 characterName.printf("g%X", gID);
643 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID);
644 advance = SkFloatToScalar(glyph.fAdvanceX);
645 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop,
646 glyph.fWidth, glyph.fHeight);
647 bbox.join(glyphBBox);
648 const SkPath* path = cache->findPath(glyph);
649 if (path && !path->isEmpty()) {
650 SkDynamicMemoryWStream content;
651 setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox,
652 &content);
653 SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content);
654 SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(),
655 &content);
656 charProcs->insertObjRef(
657 characterName, sk_make_sp<SkPDFStream>(
658 std::unique_ptr<SkStreamAsset>(content.detachAsStream())));
659 } else {
660 if (!emptyStream) {
661 emptyStream = sk_make_sp<SkPDFStream>(
662 std::unique_ptr<SkStreamAsset>(
663 new SkMemoryStream((size_t)0)));
664 }
665 charProcs->insertObjRef(characterName, emptyStream);
666 }
halcanary5bf60ad2016-08-11 13:59:18 -0700667 }
halcanary7e8d5d32016-08-12 07:59:38 -0700668 encDiffs->appendName(characterName.c_str());
669 widthArray->appendScalar(advance);
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000670 }
671
halcanary8103a342016-03-08 15:10:16 -0800672 encoding->insertObject("Differences", std::move(encDiffs));
halcanary7e8d5d32016-08-12 07:59:38 -0700673 font->insertInt("FirstChar", 0);
674 font->insertInt("LastChar", lastGlyphID - firstGlyphID + 1);
675 /* FontBBox: "A rectangle expressed in the glyph coordinate
676 system, specifying the font bounding box. This is the smallest
677 rectangle enclosing the shape that would result if all of the
678 glyphs of the font were placed with their origins coincident and
679 then filled." */
680 auto fontBBox = sk_make_sp<SkPDFArray>();
681 fontBBox->reserve(4);
682 fontBBox->appendInt(bbox.left());
683 fontBBox->appendInt(bbox.bottom());
684 fontBBox->appendInt(bbox.right());
685 fontBBox->appendInt(bbox.top());
686 font->insertObject("FontBBox", std::move(fontBBox));
687 font->insertName("CIDToGIDMap", "Identity");
halcanary3d01c622016-08-31 12:52:35 -0700688 if (metrics && metrics->fGlyphToUnicode.count() > 0) {
halcanary7e8d5d32016-08-12 07:59:38 -0700689 font->insertObjRef("ToUnicode",
690 SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode,
halcanary530032a2016-08-18 14:22:52 -0700691 &subset,
halcanary7e8d5d32016-08-12 07:59:38 -0700692 false,
693 firstGlyphID,
694 lastGlyphID));
695 }
halcanary3d01c622016-08-31 12:52:35 -0700696 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
697 int32_t fontDescriptorFlags = kPdfSymbolic;
698 if (metrics) {
699 // Type3 FontDescriptor does not require all the same fields.
700 descriptor->insertName("FontName", metrics->fFontName);
701 descriptor->insertInt("ItalicAngle", metrics->fItalicAngle);
702 fontDescriptorFlags |= (int32_t)metrics->fStyle;
703 }
704 descriptor->insertInt("Flags", fontDescriptorFlags);
705 font->insertObjRef("FontDescriptor", std::move(descriptor));
halcanary7e8d5d32016-08-12 07:59:38 -0700706 font->insertObject("Widths", std::move(widthArray));
707 font->insertObject("Encoding", std::move(encoding));
708 font->insertObject("CharProcs", std::move(charProcs));
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000709}
halcanaryfb62b3d2015-01-21 09:59:14 -0800710
halcanary530032a2016-08-18 14:22:52 -0700711SkPDFType3Font::SkPDFType3Font(SkPDFFont::Info info,
712 const SkAdvancedTypefaceMetrics& metrics)
713 : SkPDFFont(std::move(info)) {}
halcanary7e8d5d32016-08-12 07:59:38 -0700714
halcanary530032a2016-08-18 14:22:52 -0700715void SkPDFType3Font::getFontSubset(SkPDFCanon* canon) {
Hal Canaryaa3af7b2017-03-06 16:18:49 -0500716 add_type3_font_info(canon, this, this->typeface(), this->glyphUsage(),
halcanary7e8d5d32016-08-12 07:59:38 -0700717 this->firstGlyphID(), this->lastGlyphID());
halcanary7e8d5d32016-08-12 07:59:38 -0700718}
719
halcanary7e8d5d32016-08-12 07:59:38 -0700720////////////////////////////////////////////////////////////////////////////////
721
halcanary66a82f32015-10-12 13:05:04 -0700722bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) {
halcanarycee13422016-08-18 09:52:48 -0700723 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon);
724 return metrics && can_embed(*metrics);
halcanary66a82f32015-10-12 13:05:04 -0700725}
halcanarybae235e2016-03-21 10:05:23 -0700726
727void SkPDFFont::drop() {
728 fTypeface = nullptr;
halcanarye202bd82016-09-19 10:27:03 -0700729 fGlyphUsage.~SkBitSet();
730 new (&fGlyphUsage) SkBitSet(0);
halcanarybae235e2016-03-21 10:05:23 -0700731 this->SkPDFDict::drop();
732}