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 "SkPDFMakeCIDGlyphWidthsArray.h" |
15 #include "SkPDFMakeToUnicodeCmap.h" | 15 #include "SkPDFMakeToUnicodeCmap.h" |
16 #include "SkPDFFont.h" | 16 #include "SkPDFFont.h" |
17 #include "SkPDFUtils.h" | 17 #include "SkPDFUtils.h" |
18 #include "SkRefCnt.h" | 18 #include "SkRefCnt.h" |
19 #include "SkScalar.h" | 19 #include "SkScalar.h" |
20 #include "SkStream.h" | 20 #include "SkStream.h" |
21 #include "SkTypefacePriv.h" | |
22 #include "SkTypes.h" | 21 #include "SkTypes.h" |
23 #include "SkUtils.h" | 22 #include "SkUtils.h" |
24 | 23 |
25 // TODO(halcanary): Switch Chrome from SK_SFNTLY_SUBSETTER to SK_PDF_USE_SFNTLY. | 24 // TODO(halcanary): Switch Chrome from SK_SFNTLY_SUBSETTER to SK_PDF_USE_SFNTLY. |
26 #if defined(SK_SFNTLY_SUBSETTER) && !defined(SK_PDF_USE_SFNTLY) | 25 #if defined(SK_SFNTLY_SUBSETTER) && !defined(SK_PDF_USE_SFNTLY) |
27 #define SK_PDF_USE_SFNTLY | 26 #define SK_PDF_USE_SFNTLY |
28 #endif | 27 #endif |
29 | 28 |
30 #ifdef SK_PDF_USE_SFNTLY | 29 #ifdef SK_PDF_USE_SFNTLY |
31 #include "sample/chromium/font_subsetter.h" | 30 #include "sample/chromium/font_subsetter.h" |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) { | 140 static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) { |
142 return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_
FontFlag); | 141 return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_
FontFlag); |
143 } | 142 } |
144 | 143 |
145 #ifdef SK_PDF_USE_SFNTLY | 144 #ifdef SK_PDF_USE_SFNTLY |
146 static bool can_subset(const SkAdvancedTypefaceMetrics& metrics) { | 145 static bool can_subset(const SkAdvancedTypefaceMetrics& metrics) { |
147 return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotSubsettable
_FontFlag); | 146 return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotSubsettable
_FontFlag); |
148 } | 147 } |
149 #endif | 148 #endif |
150 | 149 |
151 int SkPDFFont::glyphsToPDFFontEncoding(SkGlyphID* glyphIDs, int numGlyphs) const
{ | |
152 // A font with multibyte glyphs will support all glyph IDs in a single font. | |
153 if (this->multiByteGlyphs()) { | |
154 return numGlyphs; | |
155 } | |
156 | |
157 for (int i = 0; i < numGlyphs; i++) { | |
158 if (glyphIDs[i] == 0) { | |
159 continue; | |
160 } | |
161 if (glyphIDs[i] < fFirstGlyphID || glyphIDs[i] > fLastGlyphID) { | |
162 return i; | |
163 } | |
164 glyphIDs[i] -= (fFirstGlyphID - 1); | |
165 } | |
166 | |
167 return numGlyphs; | |
168 } | |
169 | |
170 int SkPDFFont::glyphsToPDFFontEncodingCount(const SkGlyphID* glyphIDs, | |
171 int numGlyphs) const { | |
172 if (this->multiByteGlyphs()) { // A font with multibyte glyphs will | |
173 return numGlyphs; // support all glyph IDs in a single font. | |
174 } | |
175 for (int i = 0; i < numGlyphs; i++) { | |
176 if (glyphIDs[i] != 0 && | |
177 (glyphIDs[i] < fFirstGlyphID || glyphIDs[i] > fLastGlyphID)) { | |
178 return i; | |
179 } | |
180 } | |
181 return numGlyphs; | |
182 } | |
183 | |
184 | |
185 const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface, | 150 const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface, |
186 SkPDFCanon* canon) { | 151 SkPDFCanon* canon) { |
187 SkFontID id = SkTypeface::UniqueID(typeface); | 152 SkASSERT(typeface); |
| 153 SkFontID id = typeface->uniqueID(); |
188 if (SkAdvancedTypefaceMetrics** ptr = canon->fTypefaceMetrics.find(id)) { | 154 if (SkAdvancedTypefaceMetrics** ptr = canon->fTypefaceMetrics.find(id)) { |
189 return *ptr; | 155 return *ptr; |
190 } | 156 } |
191 sk_sp<SkTypeface> defaultFace; | 157 int count = typeface->countGlyphs(); |
192 if (!typeface) { | 158 if (count <= 0 || count > 1 + SK_MaxU16) { |
193 defaultFace = SkTypeface::MakeDefault(); | 159 // Cache nullptr to skip this check. Use SkSafeUnref(). |
194 typeface = defaultFace.get(); | 160 canon->fTypefaceMetrics.set(id, nullptr); |
| 161 return nullptr; |
195 } | 162 } |
196 sk_sp<SkAdvancedTypefaceMetrics> metrics( | 163 sk_sp<SkAdvancedTypefaceMetrics> metrics( |
197 typeface->getAdvancedTypefaceMetrics( | 164 typeface->getAdvancedTypefaceMetrics( |
198 SkTypeface::kGlyphNames_PerGlyphInfo | SkTypeface::kToUnicod
e_PerGlyphInfo, | 165 SkTypeface::kGlyphNames_PerGlyphInfo | SkTypeface::kToUnicod
e_PerGlyphInfo, |
199 nullptr, 0)); | 166 nullptr, 0)); |
200 if (!metrics) { | 167 if (!metrics) { |
201 if (typeface->countGlyphs() > 0) { | 168 metrics = sk_make_sp<SkAdvancedTypefaceMetrics>(); |
202 metrics = sk_make_sp<SkAdvancedTypefaceMetrics>(); | 169 metrics->fLastGlyphID = SkToU16(count - 1); |
203 } else { | 170 } |
204 SkDEBUGF(("SkPDF: SkTypeface:getAdvancedTypefaceMetrics() returned n
ull.\n")); | 171 SkASSERT(metrics->fLastGlyphID == SkToU16(count - 1)); |
205 } | |
206 } | |
207 // May cache null to skip this check. use SkSafeUnref. | |
208 return *canon->fTypefaceMetrics.set(id, metrics.release()); | 172 return *canon->fTypefaceMetrics.set(id, metrics.release()); |
209 } | 173 } |
210 | 174 |
211 SkAdvancedTypefaceMetrics::FontType font_type(const SkAdvancedTypefaceMetrics& m
etrics) { | 175 SkAdvancedTypefaceMetrics::FontType font_type(const SkAdvancedTypefaceMetrics& m
etrics) { |
212 if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFl
ag)) { | 176 if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFl
ag)) { |
213 // force Type3 fallback. | 177 // force Type3 fallback. |
214 return SkAdvancedTypefaceMetrics::kOther_Font; | 178 return SkAdvancedTypefaceMetrics::kOther_Font; |
215 } | 179 } |
216 return metrics.fType; | 180 return metrics.fType; |
217 } | 181 } |
218 | 182 |
219 static SkGlyphID first_glyph_for_single_byte_encoding(SkGlyphID gid) { | 183 static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) { |
220 return gid != 0 ? gid - (gid - 1) % 255 : 1; | 184 return gid != 0 ? gid - (gid - 1) % 255 : 1; |
221 } | 185 } |
222 | 186 |
223 SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, | 187 SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, |
224 SkTypeface* face, | 188 SkTypeface* face, |
225 SkGlyphID glyphID) { | 189 SkGlyphID glyphID) { |
226 SkASSERT(canon); | 190 SkASSERT(canon); |
| 191 SkASSERT(face); // All SkPDFDevice::internalDrawText ensures this. |
227 const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, c
anon); | 192 const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, c
anon); |
228 if (!fontMetrics) { | 193 SkASSERT(fontMetrics); // SkPDFDevice::internalDrawText ensures the typefac
e is good. |
229 return nullptr; // bad font, return early. | 194 // GetMetrics only returns null to signify a bad typ
eface. |
230 } | |
231 const SkAdvancedTypefaceMetrics& metrics = *fontMetrics; | 195 const SkAdvancedTypefaceMetrics& metrics = *fontMetrics; |
232 SkAdvancedTypefaceMetrics::FontType type = font_type(metrics); | 196 SkAdvancedTypefaceMetrics::FontType type = font_type(metrics); |
233 bool multibyte = SkPDFFont::IsMultiByte(type); | 197 bool multibyte = SkPDFFont::IsMultiByte(type); |
234 SkGlyphID firstGlyph = multibyte ? 0 : first_glyph_for_single_byte_encoding(
glyphID); | 198 SkGlyphID subsetCode = multibyte ? 0 : first_nonzero_glyph_for_single_byte_e
ncoding(glyphID); |
235 uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | firstGlyph; | 199 uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | subsetCode; |
236 | 200 |
237 if (SkPDFFont** found = canon->fFontMap.find(fontID)) { | 201 if (SkPDFFont** found = canon->fFontMap.find(fontID)) { |
238 SkASSERT(multibyte == (*found)->multiByteGlyphs()); | 202 SkPDFFont* foundFont = *found; |
239 return SkRef(*found); | 203 SkASSERT(foundFont && multibyte == foundFont->multiByteGlyphs()); |
| 204 return SkRef(foundFont); |
240 } | 205 } |
241 | 206 |
242 sk_sp<SkTypeface> typeface(face ? sk_ref_sp(face) : SkTypeface::MakeDefault(
)); | 207 sk_sp<SkTypeface> typeface(sk_ref_sp(face)); |
243 SkASSERT(typeface); | 208 SkASSERT(typeface); |
244 int glyphCount = typeface->countGlyphs(); | 209 |
245 // Validate typeface + glyph; | 210 SkGlyphID lastGlyph = metrics.fLastGlyphID; |
246 if (glyphCount < 1 || // typeface lacks even a NOTDEF glyph. | 211 SkASSERT(typeface->countGlyphs() == SkToInt(1 + metrics.fLastGlyphID)); |
247 glyphCount > 1 + SK_MaxU16 || // invalid glyphCount | 212 |
248 glyphID >= glyphCount) { // invalid glyph | 213 // should be caught by SkPDFDevice::internalDrawText |
249 return nullptr; | 214 SkASSERT(glyphID <= lastGlyph); |
250 } | |
251 | 215 |
252 SkGlyphID firstNonZeroGlyph; | 216 SkGlyphID firstNonZeroGlyph; |
253 SkGlyphID lastGlyph; | |
254 if (multibyte) { | 217 if (multibyte) { |
255 firstNonZeroGlyph = 1; | 218 firstNonZeroGlyph = 1; |
256 lastGlyph = SkToU16(glyphCount - 1); | |
257 } else { | 219 } else { |
258 firstNonZeroGlyph = firstGlyph; | 220 firstNonZeroGlyph = subsetCode; |
259 lastGlyph = SkToU16(SkTMin<int>(glyphCount - 1, | 221 lastGlyph = SkToU16(SkTMin<int>((int)lastGlyph, 254 + (int)subsetCode)); |
260 254 + (int)firstGlyph)); | |
261 } | 222 } |
262 SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, t
ype}; | 223 SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, t
ype}; |
263 sk_sp<SkPDFFont> font; | 224 sk_sp<SkPDFFont> font; |
264 switch (type) { | 225 switch (type) { |
265 case SkAdvancedTypefaceMetrics::kType1CID_Font: | 226 case SkAdvancedTypefaceMetrics::kType1CID_Font: |
266 case SkAdvancedTypefaceMetrics::kTrueType_Font: | 227 case SkAdvancedTypefaceMetrics::kTrueType_Font: |
267 SkASSERT(multibyte); | 228 SkASSERT(multibyte); |
268 font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics); | 229 font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics); |
269 break; | 230 break; |
270 case SkAdvancedTypefaceMetrics::kType1_Font: | 231 case SkAdvancedTypefaceMetrics::kType1_Font: |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 | 716 |
756 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { | 717 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { |
757 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c
anon); | 718 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c
anon); |
758 return metrics && can_embed(*metrics); | 719 return metrics && can_embed(*metrics); |
759 } | 720 } |
760 | 721 |
761 void SkPDFFont::drop() { | 722 void SkPDFFont::drop() { |
762 fTypeface = nullptr; | 723 fTypeface = nullptr; |
763 this->SkPDFDict::drop(); | 724 this->SkPDFDict::drop(); |
764 } | 725 } |
OLD | NEW |