| 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 |