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; | |
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; | |
180 tmpPaint.setHinting(SkPaint::kNo_Hinting); | |
181 tmpPaint.setTypeface(sk_ref_sp(typeface)); | |
182 tmpPaint.setTextSize((SkScalar)typeface->getUnitsPerEm()); | |
183 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); | |
184 SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); | |
185 SkASSERT(glyphCache.get()); | |
186 | |
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 } | |
298 | |
299 //////////////////////////////////////////////////////////////////////////////// | |
300 | |
301 // scale from em-units to base-1000, returning as a SkScalar | 93 // scale from em-units to base-1000, returning as a SkScalar |
302 SkScalar from_font_units(SkScalar scaled, uint16_t emSize) { | 94 SkScalar from_font_units(SkScalar scaled, uint16_t emSize) { |
303 if (emSize == 1000) { | 95 if (emSize == 1000) { |
304 return scaled; | 96 return scaled; |
305 } else { | 97 } else { |
306 return SkScalarMulDiv(scaled, 1000, emSize); | 98 return SkScalarMulDiv(scaled, 1000, emSize); |
307 } | 99 } |
308 } | 100 } |
309 | 101 |
310 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { | 102 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { |
(...skipping 18 matching lines...) Expand all Loading... | |
329 | 121 |
330 static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { | 122 static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { |
331 auto bbox = sk_make_sp<SkPDFArray>(); | 123 auto bbox = sk_make_sp<SkPDFArray>(); |
332 bbox->reserve(4); | 124 bbox->reserve(4); |
333 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); | 125 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); |
334 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); | 126 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); |
335 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); | 127 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); |
336 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); | 128 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); |
337 return bbox; | 129 return bbox; |
338 } | 130 } |
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 | 131 } // namespace |
375 | 132 |
376 | 133 |
377 /////////////////////////////////////////////////////////////////////////////// | 134 /////////////////////////////////////////////////////////////////////////////// |
378 // class SkPDFGlyphSet | 135 // class SkPDFGlyphSet |
379 /////////////////////////////////////////////////////////////////////////////// | 136 /////////////////////////////////////////////////////////////////////////////// |
380 | 137 |
381 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { | 138 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { |
382 } | 139 } |
383 | 140 |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
827 } else { | 584 } else { |
828 SkASSERT(false); | 585 SkASSERT(false); |
829 } | 586 } |
830 | 587 |
831 auto sysInfo = sk_make_sp<SkPDFDict>(); | 588 auto sysInfo = sk_make_sp<SkPDFDict>(); |
832 sysInfo->insertString("Registry", "Adobe"); | 589 sysInfo->insertString("Registry", "Adobe"); |
833 sysInfo->insertString("Ordering", "Identity"); | 590 sysInfo->insertString("Ordering", "Identity"); |
834 sysInfo->insertInt("Supplement", 0); | 591 sysInfo->insertInt("Supplement", 0); |
835 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); | 592 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); |
836 | 593 |
837 SkSinglyLinkedList<AdvanceMetric> tmpMetrics; | 594 uint16_t emSize = this->getFontInfo()->fEmSize; |
838 set_glyph_widths(face, subset, &tmpMetrics); | |
839 int16_t defaultWidth = 0; | 595 int16_t defaultWidth = 0; |
840 uint16_t emSize = (uint16_t)this->getFontInfo()->fEmSize; | 596 const SkBitSet* bitSet = subset ? &subset->bitSet() : nullptr; |
841 sk_sp<SkPDFArray> widths = composeAdvanceData(tmpMetrics, emSize, &defaultWi dth); | 597 { |
842 if (widths->size()) { | 598 SkPaint tmpPaint; |
843 newCIDFont->insertObject("W", std::move(widths)); | 599 tmpPaint.setHinting(SkPaint::kNo_Hinting); |
600 tmpPaint.setTypeface(sk_ref_sp(face)); | |
601 tmpPaint.setTextSize((SkScalar)face->getUnitsPerEm()); | |
602 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); | |
603 SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); | |
604 SkASSERT(glyphCache.get()); | |
bungeman-skia
2016/08/16 19:16:25
The above seems to be done in at least three other
hal.canary
2016/08/16 20:42:09
Done.
| |
605 sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray( | |
606 glyphCache.get(), bitSet, emSize, &defaultWidth); | |
607 if (widths && widths->size() > 0) { | |
608 newCIDFont->insertObject("W", std::move(widths)); | |
609 } | |
610 newCIDFont->insertScalar( | |
611 "DW", scaleFromFontUnits(defaultWidth, emSize)); | |
844 } | 612 } |
845 | 613 |
846 newCIDFont->insertScalar( | |
847 "DW", scaleFromFontUnits(defaultWidth, emSize)); | |
848 | |
849 | |
850 //////////////////////////////////////////////////////////////////////////// | 614 //////////////////////////////////////////////////////////////////////////// |
851 | 615 |
852 this->insertName("Subtype", "Type0"); | 616 this->insertName("Subtype", "Type0"); |
853 this->insertName("BaseFont", metrics.fFontName); | 617 this->insertName("BaseFont", metrics.fFontName); |
854 this->insertName("Encoding", "Identity-H"); | 618 this->insertName("Encoding", "Identity-H"); |
855 auto descendantFonts = sk_make_sp<SkPDFArray>(); | 619 auto descendantFonts = sk_make_sp<SkPDFArray>(); |
856 descendantFonts->appendObjRef(std::move(newCIDFont)); | 620 descendantFonts->appendObjRef(std::move(newCIDFont)); |
857 this->insertObject("DescendantFonts", std::move(descendantFonts)); | 621 this->insertObject("DescendantFonts", std::move(descendantFonts)); |
858 this->populateToUnicodeTable(subset); | 622 this->populateToUnicodeTable(subset); |
859 SkDEBUGCODE(fPopulated = true); | 623 SkDEBUGCODE(fPopulated = true); |
(...skipping 329 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 |