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 { | 150 // returns null only when typeface is bad |
bungeman-skia
2016/08/25 19:28:44
/** Returns .... */
hal.canary
2016/08/26 15:27:04
Done.
| |
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, | 151 const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface, |
186 SkPDFCanon* canon) { | 152 SkPDFCanon* canon) { |
187 SkFontID id = SkTypeface::UniqueID(typeface); | 153 SkFontID id = SkTypeface::UniqueID(typeface); |
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 sk_sp<SkTypeface> defaultFace; |
bungeman-skia
2016/08/25 19:28:43
not used anymore?
hal.canary
2016/08/26 15:27:04
Done.
| |
192 if (!typeface) { | 158 SkASSERT(typeface); |
193 defaultFace = SkTypeface::MakeDefault(); | 159 sk_sp<SkAdvancedTypefaceMetrics> metrics; |
194 typeface = defaultFace.get(); | 160 SkPDFFont::TypefaceInfo faceInfo = SkPDFFont::GetTypefaceInfo(typeface); |
195 } | 161 if (faceInfo.fGood) { |
196 sk_sp<SkAdvancedTypefaceMetrics> metrics( | 162 metrics.reset( |
197 typeface->getAdvancedTypefaceMetrics( | 163 typeface->getAdvancedTypefaceMetrics( |
198 SkTypeface::kGlyphNames_PerGlyphInfo | SkTypeface::kToUnicod e_PerGlyphInfo, | 164 SkTypeface::kGlyphNames_PerGlyphInfo | SkTypeface::kToUn icode_PerGlyphInfo, |
199 nullptr, 0)); | 165 nullptr, 0)); |
200 if (!metrics) { | 166 if (!metrics) { |
201 if (typeface->countGlyphs() > 0) { | |
202 metrics = sk_make_sp<SkAdvancedTypefaceMetrics>(); | 167 metrics = sk_make_sp<SkAdvancedTypefaceMetrics>(); |
168 metrics->fLastGlyphID = faceInfo.fMaxGlyphID; | |
203 } else { | 169 } else { |
204 SkDEBUGF(("SkPDF: SkTypeface:getAdvancedTypefaceMetrics() returned n ull.\n")); | 170 SkASSERT(metrics->fLastGlyphID == faceInfo.fMaxGlyphID); |
205 } | 171 } |
172 } else { | |
173 SkDEBUGF(("SkPDF: SkTypeface:countGlyphs() bad value.\n")); | |
206 } | 174 } |
207 // May cache null to skip this check. use SkSafeUnref. | 175 // May cache null to skip this check. use SkSafeUnref. |
208 return *canon->fTypefaceMetrics.set(id, metrics.release()); | 176 return *canon->fTypefaceMetrics.set(id, metrics.release()); |
209 } | 177 } |
210 | 178 |
211 SkAdvancedTypefaceMetrics::FontType font_type(const SkAdvancedTypefaceMetrics& m etrics) { | 179 SkAdvancedTypefaceMetrics::FontType font_type(const SkAdvancedTypefaceMetrics& m etrics) { |
212 if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFl ag)) { | 180 if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFl ag)) { |
213 // force Type3 fallback. | 181 // force Type3 fallback. |
214 return SkAdvancedTypefaceMetrics::kOther_Font; | 182 return SkAdvancedTypefaceMetrics::kOther_Font; |
215 } | 183 } |
216 return metrics.fType; | 184 return metrics.fType; |
217 } | 185 } |
218 | 186 |
219 static SkGlyphID first_glyph_for_single_byte_encoding(SkGlyphID gid) { | 187 static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) { |
220 return gid != 0 ? gid - (gid - 1) % 255 : 1; | 188 return gid != 0 ? gid - (gid - 1) % 255 : 1; |
221 } | 189 } |
222 | 190 |
223 SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, | 191 SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, |
224 SkTypeface* face, | 192 SkTypeface* face, |
225 SkGlyphID glyphID) { | 193 SkGlyphID glyphID) { |
226 SkASSERT(canon); | 194 SkASSERT(canon); |
195 SkASSERT(face); // All SkPDFDevice::internalDrawText ensures this. | |
227 const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, c anon); | 196 const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, c anon); |
228 if (!fontMetrics) { | 197 SkASSERT(fontMetrics); // SkPDFDevice::internalDrawText ensures the typefac e is good. |
229 return nullptr; // bad font, return early. | 198 // GetMetrics only returns null to signify a bad typ eface. |
230 } | |
231 const SkAdvancedTypefaceMetrics& metrics = *fontMetrics; | 199 const SkAdvancedTypefaceMetrics& metrics = *fontMetrics; |
232 SkAdvancedTypefaceMetrics::FontType type = font_type(metrics); | 200 SkAdvancedTypefaceMetrics::FontType type = font_type(metrics); |
233 bool multibyte = SkPDFFont::IsMultiByte(type); | 201 bool multibyte = SkPDFFont::IsMultiByte(type); |
234 SkGlyphID firstGlyph = multibyte ? 0 : first_glyph_for_single_byte_encoding( glyphID); | 202 SkGlyphID subsetCode = multibyte ? 0 : first_nonzero_glyph_for_single_byte_e ncoding(glyphID); |
235 uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | firstGlyph; | 203 uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | subsetCode; |
236 | 204 |
237 if (SkPDFFont** found = canon->fFontMap.find(fontID)) { | 205 if (SkPDFFont** found = canon->fFontMap.find(fontID)) { |
238 SkASSERT(multibyte == (*found)->multiByteGlyphs()); | 206 SkPDFFont* foundFont = *found; |
239 return SkRef(*found); | 207 SkASSERT(foundFont && multibyte == foundFont->multiByteGlyphs()); |
208 return SkRef(foundFont); | |
240 } | 209 } |
241 | 210 |
242 sk_sp<SkTypeface> typeface(face ? sk_ref_sp(face) : SkTypeface::MakeDefault( )); | 211 sk_sp<SkTypeface> typeface(sk_ref_sp(face)); |
243 SkASSERT(typeface); | 212 SkASSERT(typeface); |
244 int glyphCount = typeface->countGlyphs(); | 213 |
245 // Validate typeface + glyph; | 214 SkGlyphID lastGlyph = metrics.fLastGlyphID; |
246 if (glyphCount < 1 || // typeface lacks even a NOTDEF glyph. | 215 SkASSERT(typeface->countGlyphs() == SkToInt(1 + metrics.fLastGlyphID)); |
247 glyphCount > 1 + SK_MaxU16 || // invalid glyphCount | 216 |
248 glyphID >= glyphCount) { // invalid glyph | 217 // should be caught by SkPDFDevice::internalDrawText |
249 return nullptr; | 218 SkASSERT(glyphID <= lastGlyph); |
250 } | |
251 | 219 |
252 SkGlyphID firstNonZeroGlyph; | 220 SkGlyphID firstNonZeroGlyph; |
253 SkGlyphID lastGlyph; | |
254 if (multibyte) { | 221 if (multibyte) { |
255 firstNonZeroGlyph = 1; | 222 firstNonZeroGlyph = 1; |
256 lastGlyph = SkToU16(glyphCount - 1); | |
257 } else { | 223 } else { |
258 firstNonZeroGlyph = firstGlyph; | 224 firstNonZeroGlyph = subsetCode; |
259 lastGlyph = SkToU16(SkTMin<int>(glyphCount - 1, | 225 lastGlyph = SkToU16(SkTMin<int>((int)lastGlyph, |
260 254 + (int)firstGlyph)); | 226 254 + (int)subsetCode)); |
bungeman-skia
2016/08/25 19:28:43
maybe fits on one line now?
hal.canary
2016/08/26 15:27:03
Done.
| |
261 } | 227 } |
262 SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, t ype}; | 228 SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, t ype}; |
263 sk_sp<SkPDFFont> font; | 229 sk_sp<SkPDFFont> font; |
264 switch (type) { | 230 switch (type) { |
265 case SkAdvancedTypefaceMetrics::kType1CID_Font: | 231 case SkAdvancedTypefaceMetrics::kType1CID_Font: |
266 case SkAdvancedTypefaceMetrics::kTrueType_Font: | 232 case SkAdvancedTypefaceMetrics::kTrueType_Font: |
267 SkASSERT(multibyte); | 233 SkASSERT(multibyte); |
268 font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics); | 234 font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics); |
269 break; | 235 break; |
270 case SkAdvancedTypefaceMetrics::kType1_Font: | 236 case SkAdvancedTypefaceMetrics::kType1_Font: |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
755 | 721 |
756 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { | 722 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { |
757 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c anon); | 723 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c anon); |
758 return metrics && can_embed(*metrics); | 724 return metrics && can_embed(*metrics); |
759 } | 725 } |
760 | 726 |
761 void SkPDFFont::drop() { | 727 void SkPDFFont::drop() { |
762 fTypeface = nullptr; | 728 fTypeface = nullptr; |
763 this->SkPDFDict::drop(); | 729 this->SkPDFDict::drop(); |
764 } | 730 } |
OLD | NEW |