OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkData.h" | 8 #include "SkData.h" |
9 #include "SkGlyphCache.h" | 9 #include "SkGlyphCache.h" |
10 #include "SkPaint.h" | 10 #include "SkPaint.h" |
11 #include "SkPDFCanon.h" | 11 #include "SkPDFCanon.h" |
12 #include "SkPDFConvertType1FontStream.h" | 12 #include "SkPDFConvertType1FontStream.h" |
13 #include "SkPDFDevice.h" | 13 #include "SkPDFDevice.h" |
| 14 #include "SkPDFMakeCIDGlyphWidthsArray.h" |
14 #include "SkPDFMakeToUnicodeCmap.h" | 15 #include "SkPDFMakeToUnicodeCmap.h" |
15 #include "SkPDFFont.h" | 16 #include "SkPDFFont.h" |
16 #include "SkPDFUtils.h" | 17 #include "SkPDFUtils.h" |
17 #include "SkRefCnt.h" | 18 #include "SkRefCnt.h" |
18 #include "SkScalar.h" | 19 #include "SkScalar.h" |
19 #include "SkStream.h" | 20 #include "SkStream.h" |
20 #include "SkTypefacePriv.h" | 21 #include "SkTypefacePriv.h" |
21 #include "SkTypes.h" | 22 #include "SkTypes.h" |
22 #include "SkUtils.h" | 23 #include "SkUtils.h" |
23 | 24 |
24 #if defined (SK_SFNTLY_SUBSETTER) | 25 #if defined (SK_SFNTLY_SUBSETTER) |
25 #if defined (GOOGLE3) | 26 #if defined (GOOGLE3) |
26 // #including #defines doesn't work with this build system. | 27 // #including #defines doesn't work with this build system. |
27 #include "typography/font/sfntly/src/sample/chromium/font_subsetter.h" | 28 #include "typography/font/sfntly/src/sample/chromium/font_subsetter.h" |
28 #else | 29 #else |
29 #include SK_SFNTLY_SUBSETTER | 30 #include SK_SFNTLY_SUBSETTER |
30 #endif | 31 #endif |
31 #endif | 32 #endif |
32 | 33 |
33 namespace { | 34 namespace { |
34 | |
35 // PDF's notion of symbolic vs non-symbolic is related to the character set, not | 35 // PDF's notion of symbolic vs non-symbolic is related to the character set, not |
36 // symbols vs. characters. Rarely is a font the right character set to call it | 36 // symbols vs. characters. Rarely is a font the right character set to call it |
37 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) | 37 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) |
38 static const int kPdfSymbolic = 4; | 38 static const int kPdfSymbolic = 4; |
39 | 39 |
40 struct AdvanceMetric { | |
41 enum MetricType { | |
42 kDefault, // Default advance: fAdvance.count = 1 | |
43 kRange, // Advances for a range: fAdvance.count = fEndID-fStartID | |
44 kRun // fStartID-fEndID have same advance: fAdvance.count = 1 | |
45 }; | |
46 MetricType fType; | |
47 uint16_t fStartId; | |
48 uint16_t fEndId; | |
49 SkTDArray<int16_t> fAdvance; | |
50 AdvanceMetric(uint16_t startId) : fStartId(startId) {} | |
51 AdvanceMetric(AdvanceMetric&&) = default; | |
52 AdvanceMetric& operator=(AdvanceMetric&& other) = default; | |
53 AdvanceMetric(const AdvanceMetric&) = delete; | |
54 AdvanceMetric& operator=(const AdvanceMetric&) = delete; | |
55 }; | |
56 | |
57 class SkPDFType0Font final : public SkPDFFont { | 40 class SkPDFType0Font final : public SkPDFFont { |
58 public: | 41 public: |
59 SkPDFType0Font(sk_sp<const SkAdvancedTypefaceMetrics> info, | 42 SkPDFType0Font(sk_sp<const SkAdvancedTypefaceMetrics> info, |
60 sk_sp<SkTypeface> typeface, | 43 sk_sp<SkTypeface> typeface, |
61 SkAdvancedTypefaceMetrics::FontType type); | 44 SkAdvancedTypefaceMetrics::FontType type); |
62 virtual ~SkPDFType0Font(); | 45 virtual ~SkPDFType0Font(); |
63 sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; | 46 sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; |
64 #ifdef SK_DEBUG | 47 #ifdef SK_DEBUG |
65 void emitObject(SkWStream*, | 48 void emitObject(SkWStream*, |
66 const SkPDFObjNumMap&, | 49 const SkPDFObjNumMap&, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 const SkPDFSubstituteMap&) const override { | 83 const SkPDFSubstituteMap&) const override { |
101 SkDEBUGFAIL("should call getFontSubset!"); | 84 SkDEBUGFAIL("should call getFontSubset!"); |
102 } | 85 } |
103 sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; | 86 sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; |
104 }; | 87 }; |
105 | 88 |
106 /////////////////////////////////////////////////////////////////////////////// | 89 /////////////////////////////////////////////////////////////////////////////// |
107 // File-Local Functions | 90 // File-Local Functions |
108 /////////////////////////////////////////////////////////////////////////////// | 91 /////////////////////////////////////////////////////////////////////////////// |
109 | 92 |
110 const int16_t kInvalidAdvance = SK_MinS16; | 93 static SkAutoGlyphCache vector_cache(SkTypeface* face, SkScalar size = 0) { |
111 const int16_t kDontCareAdvance = SK_MinS16 + 1; | |
112 | |
113 static void stripUninterestingTrailingAdvancesFromRange( | |
114 AdvanceMetric* range) { | |
115 SkASSERT(range); | |
116 | |
117 int expectedAdvanceCount = range->fEndId - range->fStartId + 1; | |
118 if (range->fAdvance.count() < expectedAdvanceCount) { | |
119 return; | |
120 } | |
121 | |
122 for (int i = expectedAdvanceCount - 1; i >= 0; --i) { | |
123 if (range->fAdvance[i] != kDontCareAdvance && | |
124 range->fAdvance[i] != kInvalidAdvance && | |
125 range->fAdvance[i] != 0) { | |
126 range->fEndId = range->fStartId + i; | |
127 break; | |
128 } | |
129 } | |
130 } | |
131 | |
132 static void zeroWildcardsInRange(AdvanceMetric* range) { | |
133 SkASSERT(range); | |
134 if (range->fType != AdvanceMetric::kRange) { | |
135 return; | |
136 } | |
137 SkASSERT(range->fAdvance.count() == range->fEndId - range->fStartId + 1); | |
138 | |
139 // Zero out wildcards. | |
140 for (int i = 0; i < range->fAdvance.count(); ++i) { | |
141 if (range->fAdvance[i] == kDontCareAdvance) { | |
142 range->fAdvance[i] = 0; | |
143 } | |
144 } | |
145 } | |
146 | |
147 static void FinishRange( | |
148 AdvanceMetric* range, | |
149 int endId, | |
150 AdvanceMetric::MetricType type) { | |
151 range->fEndId = endId; | |
152 range->fType = type; | |
153 stripUninterestingTrailingAdvancesFromRange(range); | |
154 int newLength; | |
155 if (type == AdvanceMetric::kRange) { | |
156 newLength = range->fEndId - range->fStartId + 1; | |
157 } else { | |
158 if (range->fEndId == range->fStartId) { | |
159 range->fType = AdvanceMetric::kRange; | |
160 } | |
161 newLength = 1; | |
162 } | |
163 SkASSERT(range->fAdvance.count() >= newLength); | |
164 range->fAdvance.setCount(newLength); | |
165 zeroWildcardsInRange(range); | |
166 } | |
167 | |
168 /** Retrieve advance data for glyphs. Used by the PDF backend. */ | |
169 // TODO(halcanary): this function is complex enough to need its logic | |
170 // tested with unit tests. On the other hand, I want to do another | |
171 // round of re-factoring before figuring out how to mock this. | |
172 // TODO(halcanary): this function should be combined with | |
173 // composeAdvanceData() so that we don't need to produce a linked list | |
174 // of intermediate values. Or we could make the intermediate value | |
175 // something other than a linked list. | |
176 static void set_glyph_widths(SkTypeface* typeface, | |
177 const SkPDFGlyphSet* subset, | |
178 SkSinglyLinkedList<AdvanceMetric>* glyphWidths) { | |
179 SkPaint tmpPaint; | 94 SkPaint tmpPaint; |
180 tmpPaint.setHinting(SkPaint::kNo_Hinting); | 95 tmpPaint.setHinting(SkPaint::kNo_Hinting); |
181 tmpPaint.setTypeface(sk_ref_sp(typeface)); | 96 tmpPaint.setTypeface(sk_ref_sp(face)); |
182 tmpPaint.setTextSize((SkScalar)typeface->getUnitsPerEm()); | 97 if (0 == size) { |
| 98 SkASSERT(face); |
| 99 tmpPaint.setTextSize((SkScalar)face->getUnitsPerEm()); |
| 100 } else { |
| 101 tmpPaint.setTextSize(size); |
| 102 } |
183 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); | 103 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
184 SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); | 104 SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); |
185 SkASSERT(glyphCache.get()); | 105 SkASSERT(glyphCache.get()); |
186 | 106 return glyphCache; |
187 // Assuming that on average, the ASCII representation of an advance plus | |
188 // a space is 8 characters and the ASCII representation of a glyph id is 3 | |
189 // characters, then the following cut offs for using different range types | |
190 // apply: | |
191 // The cost of stopping and starting the range is 7 characers | |
192 // a. Removing 4 0's or don't care's is a win | |
193 // The cost of stopping and starting the range plus a run is 22 | |
194 // characters | |
195 // b. Removing 3 repeating advances is a win | |
196 // c. Removing 2 repeating advances and 3 don't cares is a win | |
197 // When not currently in a range the cost of a run over a range is 16 | |
198 // characaters, so: | |
199 // d. Removing a leading 0/don't cares is a win because it is omitted | |
200 // e. Removing 2 repeating advances is a win | |
201 | |
202 int num_glyphs = typeface->countGlyphs(); | |
203 | |
204 AdvanceMetric* prevRange = nullptr; | |
205 int16_t lastAdvance = kInvalidAdvance; | |
206 int repeatedAdvances = 0; | |
207 int wildCardsInRun = 0; | |
208 int trailingWildCards = 0; | |
209 | |
210 // Limit the loop count to glyph id ranges provided. | |
211 int lastIndex = num_glyphs; | |
212 if (subset) { | |
213 while (!subset->has(lastIndex - 1) && lastIndex > 0) { | |
214 --lastIndex; | |
215 } | |
216 } | |
217 AdvanceMetric curRange(0); | |
218 | |
219 for (int gId = 0; gId <= lastIndex; gId++) { | |
220 int16_t advance = kInvalidAdvance; | |
221 if (gId < lastIndex) { | |
222 if (!subset || 0 == gId || subset->has(gId)) { | |
223 advance = (int16_t)glyphCache->getGlyphIDAdvance(gId).fAdvanceX; | |
224 } else { | |
225 advance = kDontCareAdvance; | |
226 } | |
227 } | |
228 if (advance == lastAdvance) { | |
229 repeatedAdvances++; | |
230 trailingWildCards = 0; | |
231 } else if (advance == kDontCareAdvance) { | |
232 wildCardsInRun++; | |
233 trailingWildCards++; | |
234 } else if (curRange.fAdvance.count() == | |
235 repeatedAdvances + 1 + wildCardsInRun) { // All in run. | |
236 if (lastAdvance == 0) { | |
237 curRange.fStartId = gId; // reset | |
238 curRange.fAdvance.setCount(0); | |
239 trailingWildCards = 0; | |
240 } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) { | |
241 FinishRange(&curRange, gId - 1, AdvanceMetric::kRun); | |
242 prevRange = glyphWidths->emplace_back(std::move(curRange)); | |
243 curRange = AdvanceMetric(gId); | |
244 trailingWildCards = 0; | |
245 } | |
246 repeatedAdvances = 0; | |
247 wildCardsInRun = trailingWildCards; | |
248 trailingWildCards = 0; | |
249 } else { | |
250 if (lastAdvance == 0 && | |
251 repeatedAdvances + 1 + wildCardsInRun >= 4) { | |
252 FinishRange(&curRange, | |
253 gId - repeatedAdvances - wildCardsInRun - 2, | |
254 AdvanceMetric::kRange); | |
255 prevRange = glyphWidths->emplace_back(std::move(curRange)); | |
256 curRange = AdvanceMetric(gId); | |
257 trailingWildCards = 0; | |
258 } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) { | |
259 FinishRange(&curRange, gId - trailingWildCards - 1, | |
260 AdvanceMetric::kRange); | |
261 prevRange = glyphWidths->emplace_back(std::move(curRange)); | |
262 curRange = AdvanceMetric(gId); | |
263 trailingWildCards = 0; | |
264 } else if (lastAdvance != 0 && | |
265 (repeatedAdvances + 1 >= 3 || | |
266 (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) { | |
267 FinishRange(&curRange, | |
268 gId - repeatedAdvances - wildCardsInRun - 2, | |
269 AdvanceMetric::kRange); | |
270 (void)glyphWidths->emplace_back(std::move(curRange)); | |
271 curRange = | |
272 AdvanceMetric(gId - repeatedAdvances - wildCardsInRun -
1); | |
273 curRange.fAdvance.append(1, &lastAdvance); | |
274 FinishRange(&curRange, gId - 1, AdvanceMetric::kRun); | |
275 prevRange = glyphWidths->emplace_back(std::move(curRange)); | |
276 curRange = AdvanceMetric(gId); | |
277 trailingWildCards = 0; | |
278 } | |
279 repeatedAdvances = 0; | |
280 wildCardsInRun = trailingWildCards; | |
281 trailingWildCards = 0; | |
282 } | |
283 curRange.fAdvance.append(1, &advance); | |
284 if (advance != kDontCareAdvance) { | |
285 lastAdvance = advance; | |
286 } | |
287 } | |
288 if (curRange.fStartId == lastIndex) { | |
289 if (!prevRange) { | |
290 glyphWidths->reset(); | |
291 return; // https://crbug.com/567031 | |
292 } | |
293 } else { | |
294 FinishRange(&curRange, lastIndex - 1, AdvanceMetric::kRange); | |
295 glyphWidths->emplace_back(std::move(curRange)); | |
296 } | |
297 } | 107 } |
298 | 108 |
299 //////////////////////////////////////////////////////////////////////////////// | |
300 | |
301 // scale from em-units to base-1000, returning as a SkScalar | 109 // scale from em-units to base-1000, returning as a SkScalar |
302 SkScalar from_font_units(SkScalar scaled, uint16_t emSize) { | 110 SkScalar from_font_units(SkScalar scaled, uint16_t emSize) { |
303 if (emSize == 1000) { | 111 if (emSize == 1000) { |
304 return scaled; | 112 return scaled; |
305 } else { | 113 } else { |
306 return SkScalarMulDiv(scaled, 1000, emSize); | 114 return SkScalarMulDiv(scaled, 1000, emSize); |
307 } | 115 } |
308 } | 116 } |
309 | 117 |
310 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { | 118 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { |
(...skipping 18 matching lines...) Expand all Loading... |
329 | 137 |
330 static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { | 138 static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { |
331 auto bbox = sk_make_sp<SkPDFArray>(); | 139 auto bbox = sk_make_sp<SkPDFArray>(); |
332 bbox->reserve(4); | 140 bbox->reserve(4); |
333 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); | 141 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); |
334 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); | 142 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); |
335 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); | 143 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); |
336 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); | 144 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); |
337 return bbox; | 145 return bbox; |
338 } | 146 } |
339 | |
340 sk_sp<SkPDFArray> composeAdvanceData( | |
341 const SkSinglyLinkedList<AdvanceMetric>& advanceInfo, | |
342 uint16_t emSize, | |
343 int16_t* defaultAdvance) { | |
344 auto result = sk_make_sp<SkPDFArray>(); | |
345 for (const AdvanceMetric& range : advanceInfo) { | |
346 switch (range.fType) { | |
347 case AdvanceMetric::kDefault: { | |
348 SkASSERT(range.fAdvance.count() == 1); | |
349 *defaultAdvance = range.fAdvance[0]; | |
350 break; | |
351 } | |
352 case AdvanceMetric::kRange: { | |
353 auto advanceArray = sk_make_sp<SkPDFArray>(); | |
354 for (int j = 0; j < range.fAdvance.count(); j++) | |
355 advanceArray->appendScalar( | |
356 scaleFromFontUnits(range.fAdvance[j], emSize)); | |
357 result->appendInt(range.fStartId); | |
358 result->appendObject(std::move(advanceArray)); | |
359 break; | |
360 } | |
361 case AdvanceMetric::kRun: { | |
362 SkASSERT(range.fAdvance.count() == 1); | |
363 result->appendInt(range.fStartId); | |
364 result->appendInt(range.fEndId); | |
365 result->appendScalar( | |
366 scaleFromFontUnits(range.fAdvance[0], emSize)); | |
367 break; | |
368 } | |
369 } | |
370 } | |
371 return result; | |
372 } | |
373 | |
374 } // namespace | 147 } // namespace |
375 | 148 |
376 | 149 |
377 /////////////////////////////////////////////////////////////////////////////// | 150 /////////////////////////////////////////////////////////////////////////////// |
378 // class SkPDFGlyphSet | 151 // class SkPDFGlyphSet |
379 /////////////////////////////////////////////////////////////////////////////// | 152 /////////////////////////////////////////////////////////////////////////////// |
380 | 153 |
381 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { | 154 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { |
382 } | 155 } |
383 | 156 |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 } else { | 600 } else { |
828 SkASSERT(false); | 601 SkASSERT(false); |
829 } | 602 } |
830 | 603 |
831 auto sysInfo = sk_make_sp<SkPDFDict>(); | 604 auto sysInfo = sk_make_sp<SkPDFDict>(); |
832 sysInfo->insertString("Registry", "Adobe"); | 605 sysInfo->insertString("Registry", "Adobe"); |
833 sysInfo->insertString("Ordering", "Identity"); | 606 sysInfo->insertString("Ordering", "Identity"); |
834 sysInfo->insertInt("Supplement", 0); | 607 sysInfo->insertInt("Supplement", 0); |
835 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); | 608 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); |
836 | 609 |
837 SkSinglyLinkedList<AdvanceMetric> tmpMetrics; | 610 uint16_t emSize = this->getFontInfo()->fEmSize; |
838 set_glyph_widths(face, subset, &tmpMetrics); | |
839 int16_t defaultWidth = 0; | 611 int16_t defaultWidth = 0; |
840 uint16_t emSize = (uint16_t)this->getFontInfo()->fEmSize; | 612 const SkBitSet* bitSet = subset ? &subset->bitSet() : nullptr; |
841 sk_sp<SkPDFArray> widths = composeAdvanceData(tmpMetrics, emSize, &defaultWi
dth); | 613 { |
842 if (widths->size()) { | 614 SkAutoGlyphCache glyphCache = vector_cache(face); |
843 newCIDFont->insertObject("W", std::move(widths)); | 615 sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray( |
| 616 glyphCache.get(), bitSet, emSize, &defaultWidth); |
| 617 if (widths && widths->size() > 0) { |
| 618 newCIDFont->insertObject("W", std::move(widths)); |
| 619 } |
| 620 newCIDFont->insertScalar( |
| 621 "DW", scaleFromFontUnits(defaultWidth, emSize)); |
844 } | 622 } |
845 | 623 |
846 newCIDFont->insertScalar( | |
847 "DW", scaleFromFontUnits(defaultWidth, emSize)); | |
848 | |
849 | |
850 //////////////////////////////////////////////////////////////////////////// | 624 //////////////////////////////////////////////////////////////////////////// |
851 | 625 |
852 this->insertName("Subtype", "Type0"); | 626 this->insertName("Subtype", "Type0"); |
853 this->insertName("BaseFont", metrics.fFontName); | 627 this->insertName("BaseFont", metrics.fFontName); |
854 this->insertName("Encoding", "Identity-H"); | 628 this->insertName("Encoding", "Identity-H"); |
855 auto descendantFonts = sk_make_sp<SkPDFArray>(); | 629 auto descendantFonts = sk_make_sp<SkPDFArray>(); |
856 descendantFonts->appendObjRef(std::move(newCIDFont)); | 630 descendantFonts->appendObjRef(std::move(newCIDFont)); |
857 this->insertObject("DescendantFonts", std::move(descendantFonts)); | 631 this->insertObject("DescendantFonts", std::move(descendantFonts)); |
858 this->populateToUnicodeTable(subset); | 632 this->populateToUnicodeTable(subset); |
859 SkDEBUGCODE(fPopulated = true); | 633 SkDEBUGCODE(fPopulated = true); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 adjustGlyphRangeForSingleByteEncoding(glyphID); | 700 adjustGlyphRangeForSingleByteEncoding(glyphID); |
927 SkGlyphID firstGlyphID = this->firstGlyphID(); | 701 SkGlyphID firstGlyphID = this->firstGlyphID(); |
928 SkGlyphID lastGlyphID = this->lastGlyphID(); | 702 SkGlyphID lastGlyphID = this->lastGlyphID(); |
929 | 703 |
930 // glyphCount not including glyph 0 | 704 // glyphCount not including glyph 0 |
931 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID; | 705 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID; |
932 SkASSERT(glyphCount > 0 && glyphCount <= 255); | 706 SkASSERT(glyphCount > 0 && glyphCount <= 255); |
933 this->insertInt("FirstChar", (size_t)0); | 707 this->insertInt("FirstChar", (size_t)0); |
934 this->insertInt("LastChar", (size_t)glyphCount); | 708 this->insertInt("LastChar", (size_t)glyphCount); |
935 { | 709 { |
936 SkPaint tmpPaint; | 710 SkAutoGlyphCache glyphCache = vector_cache(this->typeface()); |
937 tmpPaint.setHinting(SkPaint::kNo_Hinting); | |
938 tmpPaint.setTypeface(sk_ref_sp(this->typeface())); | |
939 tmpPaint.setTextSize((SkScalar)this->typeface()->getUnitsPerEm()); | |
940 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); | |
941 SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); | |
942 auto widths = sk_make_sp<SkPDFArray>(); | 711 auto widths = sk_make_sp<SkPDFArray>(); |
943 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX; | 712 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX; |
944 const uint16_t emSize = this->getFontInfo()->fEmSize; | 713 const uint16_t emSize = this->getFontInfo()->fEmSize; |
945 widths->appendScalar(from_font_units(advance, emSize)); | 714 widths->appendScalar(from_font_units(advance, emSize)); |
946 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) { | 715 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) { |
947 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX; | 716 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX; |
948 widths->appendScalar(from_font_units(advance, emSize)); | 717 widths->appendScalar(from_font_units(advance, emSize)); |
949 } | 718 } |
950 this->insertObject("Widths", std::move(widths)); | 719 this->insertObject("Widths", std::move(widths)); |
951 } | 720 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1005 }; | 774 }; |
1006 } | 775 } |
1007 | 776 |
1008 static void add_type3_font_info(SkPDFDict* font, | 777 static void add_type3_font_info(SkPDFDict* font, |
1009 SkTypeface* typeface, | 778 SkTypeface* typeface, |
1010 SkScalar emSize, | 779 SkScalar emSize, |
1011 const SkPDFGlyphSet* subset, | 780 const SkPDFGlyphSet* subset, |
1012 SkGlyphID firstGlyphID, | 781 SkGlyphID firstGlyphID, |
1013 SkGlyphID lastGlyphID) { | 782 SkGlyphID lastGlyphID) { |
1014 SkASSERT(lastGlyphID >= firstGlyphID); | 783 SkASSERT(lastGlyphID >= firstGlyphID); |
1015 SkPaint paint; | 784 SkASSERT(emSize > 0.0f); |
1016 paint.setHinting(SkPaint::kNo_Hinting); | 785 SkAutoGlyphCache cache = vector_cache(typeface, emSize); |
1017 paint.setTypeface(sk_ref_sp(typeface)); | |
1018 paint.setTextSize(emSize); | |
1019 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); | |
1020 SkAutoGlyphCache cache(paint, &props, nullptr); | |
1021 | |
1022 font->insertName("Subtype", "Type3"); | 786 font->insertName("Subtype", "Type3"); |
1023 // Flip about the x-axis and scale by 1/emSize. | 787 // Flip about the x-axis and scale by 1/emSize. |
1024 SkMatrix fontMatrix; | 788 SkMatrix fontMatrix; |
1025 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize)); | 789 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize)); |
1026 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); | 790 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); |
1027 | 791 |
1028 auto charProcs = sk_make_sp<SkPDFDict>(); | 792 auto charProcs = sk_make_sp<SkPDFDict>(); |
1029 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); | 793 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); |
1030 | 794 |
1031 auto encDiffs = sk_make_sp<SkPDFArray>(); | 795 auto encDiffs = sk_make_sp<SkPDFArray>(); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 } | 953 } |
1190 return *canon->fCanEmbedTypeface.set(id, canEmbed); | 954 return *canon->fCanEmbedTypeface.set(id, canEmbed); |
1191 } | 955 } |
1192 | 956 |
1193 void SkPDFFont::drop() { | 957 void SkPDFFont::drop() { |
1194 fTypeface = nullptr; | 958 fTypeface = nullptr; |
1195 fFontInfo = nullptr; | 959 fFontInfo = nullptr; |
1196 fDescriptor = nullptr; | 960 fDescriptor = nullptr; |
1197 this->SkPDFDict::drop(); | 961 this->SkPDFDict::drop(); |
1198 } | 962 } |
OLD | NEW |