| 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" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include SK_SFNTLY_SUBSETTER | 30 #include SK_SFNTLY_SUBSETTER |
| 31 #endif | 31 #endif |
| 32 #endif | 32 #endif |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 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 class SkPDFType0Font final : public SkPDFFont { | 40 struct SkPDFType0Font final : public SkPDFFont { |
| 41 public: | 41 SkPDFType0Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&); |
| 42 SkPDFType0Font(const SkAdvancedTypefaceMetrics& info, | |
| 43 sk_sp<SkTypeface> typeface, | |
| 44 SkAdvancedTypefaceMetrics::FontType type); | |
| 45 virtual ~SkPDFType0Font(); | 42 virtual ~SkPDFType0Font(); |
| 46 sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override
; | 43 void getFontSubset(SkPDFCanon*) override; |
| 47 #ifdef SK_DEBUG | 44 #ifdef SK_DEBUG |
| 48 void emitObject(SkWStream*, | 45 void emitObject(SkWStream*, const SkPDFObjNumMap&) const override; |
| 49 const SkPDFObjNumMap&, | |
| 50 const SkPDFSubstituteMap&) const override; | |
| 51 #endif | |
| 52 | |
| 53 private: | |
| 54 #ifdef SK_DEBUG | |
| 55 bool fPopulated; | 46 bool fPopulated; |
| 56 #endif | 47 #endif |
| 57 bool populate(const SkPDFGlyphSet* subset, | |
| 58 const SkAdvancedTypefaceMetrics& metrics); | |
| 59 typedef SkPDFDict INHERITED; | 48 typedef SkPDFDict INHERITED; |
| 60 }; | 49 }; |
| 61 | 50 |
| 62 class SkPDFType1Font final : public SkPDFFont { | 51 struct SkPDFType1Font final : public SkPDFFont { |
| 63 public: | 52 SkPDFType1Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&, SkPDFCanon
*); |
| 64 SkPDFType1Font(const SkAdvancedTypefaceMetrics& info, | |
| 65 sk_sp<SkTypeface> typeface, | |
| 66 uint16_t glyphID, | |
| 67 SkPDFCanon* canon); | |
| 68 virtual ~SkPDFType1Font() {} | 53 virtual ~SkPDFType1Font() {} |
| 54 void getFontSubset(SkPDFCanon*) override {} // TODO(halcanary): implement |
| 69 }; | 55 }; |
| 70 | 56 |
| 71 class SkPDFType3Font final : public SkPDFFont { | 57 struct SkPDFType3Font final : public SkPDFFont { |
| 72 public: | 58 SkPDFType3Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&); |
| 73 SkPDFType3Font(const SkAdvancedTypefaceMetrics& info, | |
| 74 sk_sp<SkTypeface> typeface, | |
| 75 SkAdvancedTypefaceMetrics::FontType fontType, | |
| 76 uint16_t glyphID); | |
| 77 virtual ~SkPDFType3Font() {} | 59 virtual ~SkPDFType3Font() {} |
| 78 void emitObject(SkWStream*, | 60 void getFontSubset(SkPDFCanon*) override; |
| 79 const SkPDFObjNumMap&, | |
| 80 const SkPDFSubstituteMap&) const override { | |
| 81 SkDEBUGFAIL("should call getFontSubset!"); | |
| 82 } | |
| 83 sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override
; | |
| 84 }; | 61 }; |
| 85 | 62 |
| 86 /////////////////////////////////////////////////////////////////////////////// | 63 /////////////////////////////////////////////////////////////////////////////// |
| 87 // File-Local Functions | 64 // File-Local Functions |
| 88 /////////////////////////////////////////////////////////////////////////////// | 65 /////////////////////////////////////////////////////////////////////////////// |
| 89 | 66 |
| 90 static SkAutoGlyphCache vector_cache(SkTypeface* face, SkScalar size = 0) { | 67 static SkAutoGlyphCache vector_cache(SkTypeface* face, SkScalar size = 0) { |
| 91 SkPaint tmpPaint; | 68 SkPaint tmpPaint; |
| 92 tmpPaint.setHinting(SkPaint::kNo_Hinting); | 69 tmpPaint.setHinting(SkPaint::kNo_Hinting); |
| 93 tmpPaint.setTypeface(sk_ref_sp(face)); | 70 tmpPaint.setTypeface(sk_ref_sp(face)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 auto bbox = sk_make_sp<SkPDFArray>(); | 113 auto bbox = sk_make_sp<SkPDFArray>(); |
| 137 bbox->reserve(4); | 114 bbox->reserve(4); |
| 138 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); | 115 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); |
| 139 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); | 116 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); |
| 140 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); | 117 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); |
| 141 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); | 118 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); |
| 142 return bbox; | 119 return bbox; |
| 143 } | 120 } |
| 144 } // namespace | 121 } // namespace |
| 145 | 122 |
| 146 | |
| 147 /////////////////////////////////////////////////////////////////////////////// | |
| 148 // class SkPDFGlyphSet | |
| 149 /////////////////////////////////////////////////////////////////////////////// | |
| 150 | |
| 151 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { | |
| 152 } | |
| 153 | |
| 154 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { | |
| 155 for (int i = 0; i < numGlyphs; ++i) { | |
| 156 fBitSet.setBit(glyphIDs[i], true); | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 bool SkPDFGlyphSet::has(uint16_t glyphID) const { | |
| 161 return fBitSet.isBitSet(glyphID); | |
| 162 } | |
| 163 | |
| 164 void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const { | |
| 165 fBitSet.exportTo(glyphIDs); | |
| 166 } | |
| 167 | |
| 168 /////////////////////////////////////////////////////////////////////////////// | |
| 169 // class SkPDFGlyphSetMap | |
| 170 /////////////////////////////////////////////////////////////////////////////// | |
| 171 | |
| 172 SkPDFGlyphSetMap::SkPDFGlyphSetMap() {} | |
| 173 | |
| 174 SkPDFGlyphSetMap::~SkPDFGlyphSetMap() { | |
| 175 fMap.reset(); | |
| 176 } | |
| 177 | |
| 178 void SkPDFGlyphSetMap::noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs, | |
| 179 int numGlyphs) { | |
| 180 SkPDFGlyphSet* subset = getGlyphSetForFont(font); | |
| 181 if (subset) { | |
| 182 subset->set(glyphIDs, numGlyphs); | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 SkPDFGlyphSet* SkPDFGlyphSetMap::getGlyphSetForFont(SkPDFFont* font) { | |
| 187 int index = fMap.count(); | |
| 188 for (int i = 0; i < index; ++i) { | |
| 189 if (fMap[i].fFont == font) { | |
| 190 return &fMap[i].fGlyphSet; | |
| 191 } | |
| 192 } | |
| 193 FontGlyphSetPair& pair = fMap.push_back(); | |
| 194 pair.fFont = font; | |
| 195 return &pair.fGlyphSet; | |
| 196 } | |
| 197 | |
| 198 /////////////////////////////////////////////////////////////////////////////// | 123 /////////////////////////////////////////////////////////////////////////////// |
| 199 // class SkPDFFont | 124 // class SkPDFFont |
| 200 /////////////////////////////////////////////////////////////////////////////// | 125 /////////////////////////////////////////////////////////////////////////////// |
| 201 | 126 |
| 202 /* Font subset design: It would be nice to be able to subset fonts | 127 /* Font subset design: It would be nice to be able to subset fonts |
| 203 * (particularly type 3 fonts), but it's a lot of work and not a priority. | 128 * (particularly type 3 fonts), but it's a lot of work and not a priority. |
| 204 * | 129 * |
| 205 * Resources are canonicalized and uniqueified by pointer so there has to be | 130 * Resources are canonicalized and uniqueified by pointer so there has to be |
| 206 * some additional state indicating which subset of the font is used. It | 131 * some additional state indicating which subset of the font is used. It |
| 207 * must be maintained at the page granularity and then combined at the document | 132 * must be maintained at the page granularity and then combined at the document |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 sk_sp<SkTypeface> typeface(face ? sk_ref_sp(face) : SkTypeface::MakeDefault(
)); | 240 sk_sp<SkTypeface> typeface(face ? sk_ref_sp(face) : SkTypeface::MakeDefault(
)); |
| 316 SkASSERT(typeface); | 241 SkASSERT(typeface); |
| 317 int glyphCount = typeface->countGlyphs(); | 242 int glyphCount = typeface->countGlyphs(); |
| 318 // Validate typeface + glyph; | 243 // Validate typeface + glyph; |
| 319 if (glyphCount < 1 || // typeface lacks even a NOTDEF glyph. | 244 if (glyphCount < 1 || // typeface lacks even a NOTDEF glyph. |
| 320 glyphCount > 1 + SK_MaxU16 || // invalid glyphCount | 245 glyphCount > 1 + SK_MaxU16 || // invalid glyphCount |
| 321 glyphID >= glyphCount) { // invalid glyph | 246 glyphID >= glyphCount) { // invalid glyph |
| 322 return nullptr; | 247 return nullptr; |
| 323 } | 248 } |
| 324 | 249 |
| 250 SkGlyphID firstNonZeroGlyph; |
| 251 SkGlyphID lastGlyph; |
| 252 if (multibyte) { |
| 253 firstNonZeroGlyph = 1; |
| 254 lastGlyph = SkToU16(glyphCount - 1); |
| 255 } else { |
| 256 firstNonZeroGlyph = firstGlyph; |
| 257 lastGlyph = SkToU16(SkTMin<int>(glyphCount - 1, |
| 258 254 + (int)firstGlyph)); |
| 259 } |
| 260 SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, t
ype}; |
| 325 sk_sp<SkPDFFont> font; | 261 sk_sp<SkPDFFont> font; |
| 326 switch (type) { | 262 switch (type) { |
| 327 case SkAdvancedTypefaceMetrics::kType1CID_Font: | 263 case SkAdvancedTypefaceMetrics::kType1CID_Font: |
| 328 case SkAdvancedTypefaceMetrics::kTrueType_Font: | 264 case SkAdvancedTypefaceMetrics::kTrueType_Font: |
| 329 SkASSERT(multibyte); | 265 SkASSERT(multibyte); |
| 330 font = sk_make_sp<SkPDFType0Font>(metrics, | 266 font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics); |
| 331 std::move(typeface), | |
| 332 type); | |
| 333 break; | 267 break; |
| 334 case SkAdvancedTypefaceMetrics::kType1_Font: | 268 case SkAdvancedTypefaceMetrics::kType1_Font: |
| 335 SkASSERT(!multibyte); | 269 SkASSERT(!multibyte); |
| 336 font = sk_make_sp<SkPDFType1Font>(metrics, | 270 font = sk_make_sp<SkPDFType1Font>(std::move(info), metrics, canon); |
| 337 std::move(typeface), | |
| 338 glyphID, | |
| 339 canon); | |
| 340 break; | 271 break; |
| 341 default: | 272 default: |
| 342 SkASSERT(!multibyte); | 273 SkASSERT(!multibyte); |
| 343 // Type3 is our fallback font. | 274 // Type3 is our fallback font. |
| 344 font = sk_make_sp<SkPDFType3Font>(metrics, | 275 font = sk_make_sp<SkPDFType3Font>(std::move(info), metrics); |
| 345 std::move(typeface), | |
| 346 type, | |
| 347 glyphID); | |
| 348 break; | 276 break; |
| 349 } | 277 } |
| 350 canon->fFontMap.set(fontID, SkRef(font.get())); | 278 canon->fFontMap.set(fontID, SkRef(font.get())); |
| 351 return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>. | 279 return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>. |
| 352 } | 280 } |
| 353 | 281 |
| 354 sk_sp<SkPDFObject> SkPDFFont::getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) { | 282 SkPDFFont::SkPDFFont(SkPDFFont::Info info) |
| 355 return nullptr; // Default: no support. | |
| 356 } | |
| 357 | |
| 358 SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface, | |
| 359 SkAdvancedTypefaceMetrics::FontType fontType) | |
| 360 : SkPDFDict("Font") | 283 : SkPDFDict("Font") |
| 361 , fTypeface(std::move(typeface)) | 284 , fTypeface(std::move(info.fTypeface)) |
| 362 , fFirstGlyphID(1) | 285 , fGlyphUsage(info.fLastGlyphID + 1) // TODO(halcanary): Adjust mapping? |
| 363 , fFontType(fontType) { | 286 , fFirstGlyphID(info.fFirstGlyphID) |
| 287 , fLastGlyphID(info.fLastGlyphID) |
| 288 , fFontType(info.fFontType) { |
| 364 SkASSERT(fTypeface); | 289 SkASSERT(fTypeface); |
| 365 fLastGlyphID = SkToU16(fTypeface->countGlyphs() - 1); | |
| 366 } | 290 } |
| 367 | 291 |
| 368 static void add_common_font_descriptor_entries(SkPDFDict* descriptor, | 292 static void add_common_font_descriptor_entries(SkPDFDict* descriptor, |
| 369 const SkAdvancedTypefaceMetrics&
metrics, | 293 const SkAdvancedTypefaceMetrics&
metrics, |
| 370 int16_t defaultWidth) { | 294 int16_t defaultWidth) { |
| 371 const uint16_t emSize = metrics.fEmSize; | 295 const uint16_t emSize = metrics.fEmSize; |
| 372 descriptor->insertName("FontName", metrics.fFontName); | 296 descriptor->insertName("FontName", metrics.fFontName); |
| 373 descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic)); | 297 descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic)); |
| 374 descriptor->insertScalar("Ascent", | 298 descriptor->insertScalar("Ascent", |
| 375 scaleFromFontUnits(metrics.fAscent, emSize)); | 299 scaleFromFontUnits(metrics.fAscent, emSize)); |
| 376 descriptor->insertScalar("Descent", | 300 descriptor->insertScalar("Descent", |
| 377 scaleFromFontUnits(metrics.fDescent, emSize)); | 301 scaleFromFontUnits(metrics.fDescent, emSize)); |
| 378 descriptor->insertScalar("StemV", | 302 descriptor->insertScalar("StemV", |
| 379 scaleFromFontUnits(metrics.fStemV, emSize)); | 303 scaleFromFontUnits(metrics.fStemV, emSize)); |
| 380 descriptor->insertScalar("CapHeight", | 304 descriptor->insertScalar("CapHeight", |
| 381 scaleFromFontUnits(metrics.fCapHeight, emSize)); | 305 scaleFromFontUnits(metrics.fCapHeight, emSize)); |
| 382 descriptor->insertInt("ItalicAngle", metrics.fItalicAngle); | 306 descriptor->insertInt("ItalicAngle", metrics.fItalicAngle); |
| 383 descriptor->insertObject( | 307 descriptor->insertObject( |
| 384 "FontBBox", makeFontBBox(metrics.fBBox, metrics.fEmSize)); | 308 "FontBBox", makeFontBBox(metrics.fBBox, metrics.fEmSize)); |
| 385 if (defaultWidth > 0) { | 309 if (defaultWidth > 0) { |
| 386 descriptor->insertScalar("MissingWidth", | 310 descriptor->insertScalar("MissingWidth", |
| 387 scaleFromFontUnits(defaultWidth, emSize)); | 311 scaleFromFontUnits(defaultWidth, emSize)); |
| 388 } | 312 } |
| 389 } | 313 } |
| 390 | 314 |
| 391 void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(SkGlyphID glyphID) { | |
| 392 // Single byte glyph encoding supports a max of 255 glyphs. | |
| 393 fFirstGlyphID = first_glyph_for_single_byte_encoding(glyphID); | |
| 394 if (fLastGlyphID > fFirstGlyphID + 255 - 1) { | |
| 395 fLastGlyphID = fFirstGlyphID + 255 - 1; | |
| 396 } | |
| 397 } | |
| 398 | |
| 399 /////////////////////////////////////////////////////////////////////////////// | 315 /////////////////////////////////////////////////////////////////////////////// |
| 400 // class SkPDFType0Font | 316 // class SkPDFType0Font |
| 401 /////////////////////////////////////////////////////////////////////////////// | 317 /////////////////////////////////////////////////////////////////////////////// |
| 402 | 318 |
| 403 SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics& info, | 319 SkPDFType0Font::SkPDFType0Font( |
| 404 sk_sp<SkTypeface> typeface, | 320 SkPDFFont::Info info, |
| 405 SkAdvancedTypefaceMetrics::FontType fontType) | 321 const SkAdvancedTypefaceMetrics& metrics) |
| 406 : SkPDFFont(std::move(typeface), fontType) { | 322 : SkPDFFont(std::move(info)) { |
| 407 SkDEBUGCODE(fPopulated = false); | 323 SkDEBUGCODE(fPopulated = false); |
| 408 if (!can_subset(info)) { | |
| 409 this->populate(nullptr, info); | |
| 410 } | |
| 411 } | 324 } |
| 412 | 325 |
| 413 SkPDFType0Font::~SkPDFType0Font() {} | 326 SkPDFType0Font::~SkPDFType0Font() {} |
| 414 | 327 |
| 415 sk_sp<SkPDFObject> SkPDFType0Font::getFontSubset(SkPDFCanon* canon, | |
| 416 const SkPDFGlyphSet* subset) { | |
| 417 const SkAdvancedTypefaceMetrics* metrics = | |
| 418 SkPDFFont::GetMetrics(this->typeface(), canon); | |
| 419 SkASSERT(metrics); | |
| 420 if (!metrics || !can_subset(*metrics)) { | |
| 421 return nullptr; | |
| 422 } | |
| 423 auto newSubset = sk_make_sp<SkPDFType0Font>( | |
| 424 *metrics, this->refTypeface(), this->getType()); | |
| 425 newSubset->populate(subset, *metrics); | |
| 426 return newSubset; | |
| 427 } | |
| 428 | 328 |
| 429 #ifdef SK_DEBUG | 329 #ifdef SK_DEBUG |
| 430 void SkPDFType0Font::emitObject(SkWStream* stream, | 330 void SkPDFType0Font::emitObject(SkWStream* stream, |
| 431 const SkPDFObjNumMap& objNumMap, | 331 const SkPDFObjNumMap& objNumMap) const { |
| 432 const SkPDFSubstituteMap& substitutes) const { | |
| 433 SkASSERT(fPopulated); | 332 SkASSERT(fPopulated); |
| 434 return INHERITED::emitObject(stream, objNumMap, substitutes); | 333 return INHERITED::emitObject(stream, objNumMap); |
| 435 } | 334 } |
| 436 #endif | 335 #endif |
| 437 | 336 |
| 438 #ifdef SK_SFNTLY_SUBSETTER | 337 #ifdef SK_SFNTLY_SUBSETTER |
| 439 // if possible, make no copy. | 338 // if possible, make no copy. |
| 440 static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) { | 339 static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) { |
| 441 SkASSERT(stream); | 340 SkASSERT(stream); |
| 442 (void)stream->rewind(); | 341 (void)stream->rewind(); |
| 443 SkASSERT(stream->hasLength()); | 342 SkASSERT(stream->hasLength()); |
| 444 size_t size = stream->getLength(); | 343 size_t size = stream->getLength(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 auto subsetStream = sk_make_sp<SkPDFStream>( | 380 auto subsetStream = sk_make_sp<SkPDFStream>( |
| 482 SkData::MakeWithProc( | 381 SkData::MakeWithProc( |
| 483 subsetFont, subsetFontSize, | 382 subsetFont, subsetFontSize, |
| 484 [](const void* p, void*) { delete[] (unsigned char*)p; }, | 383 [](const void* p, void*) { delete[] (unsigned char*)p; }, |
| 485 nullptr)); | 384 nullptr)); |
| 486 subsetStream->dict()->insertInt("Length1", subsetFontSize); | 385 subsetStream->dict()->insertInt("Length1", subsetFontSize); |
| 487 return subsetStream; | 386 return subsetStream; |
| 488 } | 387 } |
| 489 #endif // SK_SFNTLY_SUBSETTER | 388 #endif // SK_SFNTLY_SUBSETTER |
| 490 | 389 |
| 491 bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset, | 390 void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) { |
| 492 const SkAdvancedTypefaceMetrics& metrics) { | 391 const SkAdvancedTypefaceMetrics* metricsPtr = |
| 392 SkPDFFont::GetMetrics(this->typeface(), canon); |
| 393 SkASSERT(metricsPtr); |
| 394 if (!metricsPtr) { return; } |
| 395 const SkAdvancedTypefaceMetrics& metrics = *metricsPtr; |
| 493 SkASSERT(can_embed(metrics)); | 396 SkASSERT(can_embed(metrics)); |
| 494 SkAdvancedTypefaceMetrics::FontType type = this->getType(); | 397 SkAdvancedTypefaceMetrics::FontType type = this->getType(); |
| 495 SkTypeface* face = this->typeface(); | 398 SkTypeface* face = this->typeface(); |
| 496 SkASSERT(face); | 399 SkASSERT(face); |
| 497 const SkString& name = metrics.fFontName; | 400 const SkString& name = metrics.fFontName; |
| 498 | 401 |
| 499 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); | 402 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); |
| 500 add_common_font_descriptor_entries(descriptor.get(), metrics, 0); | 403 add_common_font_descriptor_entries(descriptor.get(), metrics, 0); |
| 501 switch (type) { | 404 switch (type) { |
| 502 case SkAdvancedTypefaceMetrics::kTrueType_Font: { | 405 case SkAdvancedTypefaceMetrics::kTrueType_Font: { |
| 503 int ttcIndex; | 406 int ttcIndex; |
| 504 std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex)
); | 407 std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex)
); |
| 505 SkASSERT(fontAsset); | 408 SkASSERT(fontAsset); |
| 506 if (!fontAsset) { | 409 if (!fontAsset) { |
| 507 return false; | 410 return; |
| 508 } | 411 } |
| 509 size_t fontSize = fontAsset->getLength(); | 412 size_t fontSize = fontAsset->getLength(); |
| 510 SkASSERT(fontSize > 0); | 413 SkASSERT(fontSize > 0); |
| 511 if (fontSize == 0) { | 414 if (fontSize == 0) { |
| 512 return false; | 415 return; |
| 513 } | 416 } |
| 514 | 417 |
| 515 #ifdef SK_SFNTLY_SUBSETTER | 418 #ifdef SK_SFNTLY_SUBSETTER |
| 516 if (can_subset(metrics) && subset) { | 419 if (can_subset(metrics)) { |
| 517 // Generate glyph id array. in format needed by sfntly | 420 // Generate glyph id array. in format needed by sfntly |
| 518 SkTDArray<uint32_t> glyphIDs; | 421 SkTDArray<uint32_t> glyphIDs; |
| 519 if (subset) { | 422 if (!this->glyphUsage().has(0)) { |
| 520 if (!subset->has(0)) { | 423 glyphIDs.push(0); // Always include glyph 0. |
| 521 glyphIDs.push(0); // Always include glyph 0. | |
| 522 } | |
| 523 subset->exportTo(&glyphIDs); | |
| 524 } | 424 } |
| 425 this->glyphUsage().exportTo(&glyphIDs); |
| 525 sk_sp<SkPDFObject> subsetStream = get_subset_font_stream( | 426 sk_sp<SkPDFObject> subsetStream = get_subset_font_stream( |
| 526 std::move(fontAsset), glyphIDs, name.c_str()); | 427 std::move(fontAsset), glyphIDs, name.c_str()); |
| 527 if (subsetStream) { | 428 if (subsetStream) { |
| 528 descriptor->insertObjRef("FontFile2", std::move(subsetStream
)); | 429 descriptor->insertObjRef("FontFile2", std::move(subsetStream
)); |
| 529 break; | 430 break; |
| 530 } | 431 } |
| 531 // If subsetting fails, fall back to original font data. | 432 // If subsetting fails, fall back to original font data. |
| 532 fontAsset.reset(face->openStream(&ttcIndex)); | 433 fontAsset.reset(face->openStream(&ttcIndex)); |
| 533 } | 434 } |
| 534 #endif // SK_SFNTLY_SUBSETTER | 435 #endif // SK_SFNTLY_SUBSETTER |
| 535 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset)
); | 436 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset)
); |
| 536 fontStream->dict()->insertInt("Length1", fontSize); | 437 fontStream->dict()->insertInt("Length1", fontSize); |
| 537 descriptor->insertObjRef("FontFile2", std::move(fontStream)); | 438 descriptor->insertObjRef("FontFile2", std::move(fontStream)); |
| 538 break; | 439 break; |
| 539 } | 440 } |
| 540 case SkAdvancedTypefaceMetrics::kType1CID_Font: { | 441 case SkAdvancedTypefaceMetrics::kType1CID_Font: { |
| 541 std::unique_ptr<SkStreamAsset> fontData(face->openStream(nullptr)); | 442 std::unique_ptr<SkStreamAsset> fontData(face->openStream(nullptr)); |
| 542 SkASSERT(fontData); | 443 SkASSERT(fontData); |
| 543 SkASSERT(fontData->getLength() > 0); | 444 SkASSERT(fontData->getLength() > 0); |
| 544 if (!fontData || 0 == fontData->getLength()) { | 445 if (!fontData || 0 == fontData->getLength()) { |
| 545 return false; | 446 return; |
| 546 } | 447 } |
| 547 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData))
; | 448 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData))
; |
| 548 fontStream->dict()->insertName("Subtype", "CIDFontType0c"); | 449 fontStream->dict()->insertName("Subtype", "CIDFontType0c"); |
| 549 descriptor->insertObjRef("FontFile3", std::move(fontStream)); | 450 descriptor->insertObjRef("FontFile3", std::move(fontStream)); |
| 550 break; | 451 break; |
| 551 } | 452 } |
| 552 default: | 453 default: |
| 553 SkASSERT(false); | 454 SkASSERT(false); |
| 554 } | 455 } |
| 555 | 456 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 567 } | 468 } |
| 568 | 469 |
| 569 auto sysInfo = sk_make_sp<SkPDFDict>(); | 470 auto sysInfo = sk_make_sp<SkPDFDict>(); |
| 570 sysInfo->insertString("Registry", "Adobe"); | 471 sysInfo->insertString("Registry", "Adobe"); |
| 571 sysInfo->insertString("Ordering", "Identity"); | 472 sysInfo->insertString("Ordering", "Identity"); |
| 572 sysInfo->insertInt("Supplement", 0); | 473 sysInfo->insertInt("Supplement", 0); |
| 573 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); | 474 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); |
| 574 | 475 |
| 575 uint16_t emSize = metrics.fEmSize; | 476 uint16_t emSize = metrics.fEmSize; |
| 576 int16_t defaultWidth = 0; | 477 int16_t defaultWidth = 0; |
| 577 const SkBitSet* bitSet = subset ? &subset->bitSet() : nullptr; | |
| 578 { | 478 { |
| 579 SkAutoGlyphCache glyphCache = vector_cache(face); | 479 SkAutoGlyphCache glyphCache = vector_cache(face); |
| 580 sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray( | 480 sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray( |
| 581 glyphCache.get(), bitSet, emSize, &defaultWidth); | 481 glyphCache.get(), &this->glyphUsage(), emSize, &defaultWidth); |
| 582 if (widths && widths->size() > 0) { | 482 if (widths && widths->size() > 0) { |
| 583 newCIDFont->insertObject("W", std::move(widths)); | 483 newCIDFont->insertObject("W", std::move(widths)); |
| 584 } | 484 } |
| 585 newCIDFont->insertScalar( | 485 newCIDFont->insertScalar( |
| 586 "DW", scaleFromFontUnits(defaultWidth, emSize)); | 486 "DW", scaleFromFontUnits(defaultWidth, emSize)); |
| 587 } | 487 } |
| 588 | 488 |
| 589 //////////////////////////////////////////////////////////////////////////// | 489 //////////////////////////////////////////////////////////////////////////// |
| 590 | 490 |
| 591 this->insertName("Subtype", "Type0"); | 491 this->insertName("Subtype", "Type0"); |
| 592 this->insertName("BaseFont", metrics.fFontName); | 492 this->insertName("BaseFont", metrics.fFontName); |
| 593 this->insertName("Encoding", "Identity-H"); | 493 this->insertName("Encoding", "Identity-H"); |
| 594 auto descendantFonts = sk_make_sp<SkPDFArray>(); | 494 auto descendantFonts = sk_make_sp<SkPDFArray>(); |
| 595 descendantFonts->appendObjRef(std::move(newCIDFont)); | 495 descendantFonts->appendObjRef(std::move(newCIDFont)); |
| 596 this->insertObject("DescendantFonts", std::move(descendantFonts)); | 496 this->insertObject("DescendantFonts", std::move(descendantFonts)); |
| 597 | 497 |
| 598 if (metrics.fGlyphToUnicode.count() > 0) { | 498 if (metrics.fGlyphToUnicode.count() > 0) { |
| 599 this->insertObjRef("ToUnicode", | 499 this->insertObjRef("ToUnicode", |
| 600 SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode, | 500 SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode, |
| 601 subset, | 501 &this->glyphUsage(), |
| 602 multiByteGlyphs(), | 502 multiByteGlyphs(), |
| 603 firstGlyphID(), | 503 firstGlyphID(), |
| 604 lastGlyphID())); | 504 lastGlyphID())); |
| 605 } | 505 } |
| 606 SkDEBUGCODE(fPopulated = true); | 506 SkDEBUGCODE(fPopulated = true); |
| 607 return true; | 507 return; |
| 608 } | 508 } |
| 609 | 509 |
| 610 /////////////////////////////////////////////////////////////////////////////// | 510 /////////////////////////////////////////////////////////////////////////////// |
| 611 // class SkPDFType1Font | 511 // class SkPDFType1Font |
| 612 /////////////////////////////////////////////////////////////////////////////// | 512 /////////////////////////////////////////////////////////////////////////////// |
| 613 | 513 |
| 614 static sk_sp<SkPDFDict> make_type1_font_descriptor( | 514 static sk_sp<SkPDFDict> make_type1_font_descriptor( |
| 615 SkTypeface* typeface, | 515 SkTypeface* typeface, |
| 616 const SkAdvancedTypefaceMetrics& info) { | 516 const SkAdvancedTypefaceMetrics& info) { |
| 617 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); | 517 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 const bool valid = gID < glyphNames.count() && !glyphNames[gID].isEmpty(
); | 572 const bool valid = gID < glyphNames.count() && !glyphNames[gID].isEmpty(
); |
| 673 const SkString& name = valid ? glyphNames[gID] : unknown; | 573 const SkString& name = valid ? glyphNames[gID] : unknown; |
| 674 encDiffs->appendName(name); | 574 encDiffs->appendName(name); |
| 675 } | 575 } |
| 676 | 576 |
| 677 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); | 577 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); |
| 678 encoding->insertObject("Differences", std::move(encDiffs)); | 578 encoding->insertObject("Differences", std::move(encDiffs)); |
| 679 font->insertObject("Encoding", std::move(encoding)); | 579 font->insertObject("Encoding", std::move(encoding)); |
| 680 } | 580 } |
| 681 | 581 |
| 682 SkPDFType1Font::SkPDFType1Font(const SkAdvancedTypefaceMetrics& info, | 582 SkPDFType1Font::SkPDFType1Font(SkPDFFont::Info info, |
| 683 sk_sp<SkTypeface> typeface, | 583 const SkAdvancedTypefaceMetrics& metrics, |
| 684 uint16_t glyphID, | |
| 685 SkPDFCanon* canon) | 584 SkPDFCanon* canon) |
| 686 : SkPDFFont(std::move(typeface), SkAdvancedTypefaceMetrics::kType1_Font) | 585 : SkPDFFont(std::move(info)) |
| 687 { | 586 { |
| 688 SkFontID fontID = this->typeface()->uniqueID(); | 587 SkFontID fontID = this->typeface()->uniqueID(); |
| 689 sk_sp<SkPDFDict> fontDescriptor; | 588 sk_sp<SkPDFDict> fontDescriptor; |
| 690 if (SkPDFDict** ptr = canon->fFontDescriptors.find(fontID)) { | 589 if (SkPDFDict** ptr = canon->fFontDescriptors.find(fontID)) { |
| 691 fontDescriptor = sk_ref_sp(*ptr); | 590 fontDescriptor = sk_ref_sp(*ptr); |
| 692 } else { | 591 } else { |
| 693 fontDescriptor = make_type1_font_descriptor(this->typeface(), info); | 592 fontDescriptor = make_type1_font_descriptor(this->typeface(), metrics); |
| 694 canon->fFontDescriptors.set(fontID, SkRef(fontDescriptor.get())); | 593 canon->fFontDescriptors.set(fontID, SkRef(fontDescriptor.get())); |
| 695 } | 594 } |
| 696 this->insertObjRef("FontDescriptor", std::move(fontDescriptor)); | 595 this->insertObjRef("FontDescriptor", std::move(fontDescriptor)); |
| 697 this->adjustGlyphRangeForSingleByteEncoding(glyphID); | |
| 698 // TODO(halcanary): subset this (advances and names). | 596 // TODO(halcanary): subset this (advances and names). |
| 699 populate_type_1_font(this, info, this->typeface(), | 597 populate_type_1_font(this, metrics, this->typeface(), |
| 700 this->firstGlyphID(), this->lastGlyphID()); | 598 this->firstGlyphID(), this->lastGlyphID()); |
| 701 } | 599 } |
| 702 | 600 |
| 703 /////////////////////////////////////////////////////////////////////////////// | 601 /////////////////////////////////////////////////////////////////////////////// |
| 704 // class SkPDFType3Font | 602 // class SkPDFType3Font |
| 705 /////////////////////////////////////////////////////////////////////////////// | 603 /////////////////////////////////////////////////////////////////////////////// |
| 706 | 604 |
| 707 namespace { | 605 namespace { |
| 708 // returns [0, first, first+1, ... last-1, last] | 606 // returns [0, first, first+1, ... last-1, last] |
| 709 struct SingleByteGlyphIdIterator { | 607 struct SingleByteGlyphIdIterator { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 731 private: | 629 private: |
| 732 const SkGlyphID fFirst; | 630 const SkGlyphID fFirst; |
| 733 const SkGlyphID fLast; | 631 const SkGlyphID fLast; |
| 734 }; | 632 }; |
| 735 } | 633 } |
| 736 | 634 |
| 737 static void add_type3_font_info(SkPDFCanon* canon, | 635 static void add_type3_font_info(SkPDFCanon* canon, |
| 738 SkPDFDict* font, | 636 SkPDFDict* font, |
| 739 SkTypeface* typeface, | 637 SkTypeface* typeface, |
| 740 SkScalar emSize, | 638 SkScalar emSize, |
| 741 const SkPDFGlyphSet* subset, | 639 const SkBitSet& subset, |
| 742 SkGlyphID firstGlyphID, | 640 SkGlyphID firstGlyphID, |
| 743 SkGlyphID lastGlyphID) { | 641 SkGlyphID lastGlyphID) { |
| 744 SkASSERT(lastGlyphID >= firstGlyphID); | 642 SkASSERT(lastGlyphID >= firstGlyphID); |
| 745 SkASSERT(emSize > 0.0f); | 643 SkASSERT(emSize > 0.0f); |
| 746 SkAutoGlyphCache cache = vector_cache(typeface, emSize); | 644 SkAutoGlyphCache cache = vector_cache(typeface, emSize); |
| 747 font->insertName("Subtype", "Type3"); | 645 font->insertName("Subtype", "Type3"); |
| 748 // Flip about the x-axis and scale by 1/emSize. | 646 // Flip about the x-axis and scale by 1/emSize. |
| 749 SkMatrix fontMatrix; | 647 SkMatrix fontMatrix; |
| 750 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize)); | 648 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize)); |
| 751 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); | 649 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 763 encDiffs->reserve(glyphCount + 1); | 661 encDiffs->reserve(glyphCount + 1); |
| 764 encDiffs->appendInt(0); // index of first glyph | 662 encDiffs->appendInt(0); // index of first glyph |
| 765 | 663 |
| 766 auto widthArray = sk_make_sp<SkPDFArray>(); | 664 auto widthArray = sk_make_sp<SkPDFArray>(); |
| 767 widthArray->reserve(glyphCount); | 665 widthArray->reserve(glyphCount); |
| 768 | 666 |
| 769 SkIRect bbox = SkIRect::MakeEmpty(); | 667 SkIRect bbox = SkIRect::MakeEmpty(); |
| 770 | 668 |
| 771 sk_sp<SkPDFStream> emptyStream; | 669 sk_sp<SkPDFStream> emptyStream; |
| 772 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) { | 670 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) { |
| 773 bool skipGlyph = subset && gID != 0 && !subset->has(gID); | 671 bool skipGlyph = gID != 0 && !subset.has(gID); |
| 774 SkString characterName; | 672 SkString characterName; |
| 775 SkScalar advance = 0.0f; | 673 SkScalar advance = 0.0f; |
| 776 SkIRect glyphBBox; | 674 SkIRect glyphBBox; |
| 777 if (skipGlyph) { | 675 if (skipGlyph) { |
| 778 characterName.set("g0"); | 676 characterName.set("g0"); |
| 779 } else { | 677 } else { |
| 780 characterName.printf("g%X", gID); | 678 characterName.printf("g%X", gID); |
| 781 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); | 679 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); |
| 782 advance = SkFloatToScalar(glyph.fAdvanceX); | 680 advance = SkFloatToScalar(glyph.fAdvanceX); |
| 783 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, | 681 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 fontBBox->appendInt(bbox.left()); | 718 fontBBox->appendInt(bbox.left()); |
| 821 fontBBox->appendInt(bbox.bottom()); | 719 fontBBox->appendInt(bbox.bottom()); |
| 822 fontBBox->appendInt(bbox.right()); | 720 fontBBox->appendInt(bbox.right()); |
| 823 fontBBox->appendInt(bbox.top()); | 721 fontBBox->appendInt(bbox.top()); |
| 824 font->insertObject("FontBBox", std::move(fontBBox)); | 722 font->insertObject("FontBBox", std::move(fontBBox)); |
| 825 font->insertName("CIDToGIDMap", "Identity"); | 723 font->insertName("CIDToGIDMap", "Identity"); |
| 826 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c
anon); | 724 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c
anon); |
| 827 if (metrics /* && metrics->fGlyphToUnicode.count() > 0 */) { | 725 if (metrics /* && metrics->fGlyphToUnicode.count() > 0 */) { |
| 828 font->insertObjRef("ToUnicode", | 726 font->insertObjRef("ToUnicode", |
| 829 SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode, | 727 SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode, |
| 830 subset, | 728 &subset, |
| 831 false, | 729 false, |
| 832 firstGlyphID, | 730 firstGlyphID, |
| 833 lastGlyphID)); | 731 lastGlyphID)); |
| 834 } | 732 } |
| 835 font->insertObject("Widths", std::move(widthArray)); | 733 font->insertObject("Widths", std::move(widthArray)); |
| 836 font->insertObject("Encoding", std::move(encoding)); | 734 font->insertObject("Encoding", std::move(encoding)); |
| 837 font->insertObject("CharProcs", std::move(charProcs)); | 735 font->insertObject("CharProcs", std::move(charProcs)); |
| 838 } | 736 } |
| 839 | 737 |
| 840 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics& info, | 738 SkPDFType3Font::SkPDFType3Font(SkPDFFont::Info info, |
| 841 sk_sp<SkTypeface> typeface, | 739 const SkAdvancedTypefaceMetrics& metrics) |
| 842 SkAdvancedTypefaceMetrics::FontType fontType, | 740 : SkPDFFont(std::move(info)) {} |
| 843 uint16_t glyphID) | |
| 844 : SkPDFFont(std::move(typeface), fontType) { | |
| 845 this->adjustGlyphRangeForSingleByteEncoding(glyphID); | |
| 846 } | |
| 847 | 741 |
| 848 sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(SkPDFCanon* canon, | 742 void SkPDFType3Font::getFontSubset(SkPDFCanon* canon) { |
| 849 const SkPDFGlyphSet* usage) { | |
| 850 // All fonts are subset before serialization. | |
| 851 // TODO(halcanary): all fonts should follow this pattern. | |
| 852 const SkAdvancedTypefaceMetrics* info = | 743 const SkAdvancedTypefaceMetrics* info = |
| 853 SkPDFFont::GetMetrics(this->typeface(), canon); | 744 SkPDFFont::GetMetrics(this->typeface(), canon); |
| 854 SkASSERT(info); | 745 SkASSERT(info); |
| 855 uint16_t emSize = info->fEmSize > 0 ? info->fEmSize : 1000; | 746 uint16_t emSize = info->fEmSize > 0 ? info->fEmSize : 1000; |
| 856 auto font = sk_make_sp<SkPDFDict>("Font"); | 747 add_type3_font_info(canon, this, this->typeface(), (SkScalar)emSize, |
| 857 add_type3_font_info(canon, font.get(), this->typeface(), (SkScalar)emSize, u
sage, | 748 this->glyphUsage(), |
| 858 this->firstGlyphID(), this->lastGlyphID()); | 749 this->firstGlyphID(), this->lastGlyphID()); |
| 859 return font; | |
| 860 } | 750 } |
| 861 | 751 |
| 862 | |
| 863 //////////////////////////////////////////////////////////////////////////////// | 752 //////////////////////////////////////////////////////////////////////////////// |
| 864 | 753 |
| 865 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { | 754 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { |
| 866 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c
anon); | 755 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c
anon); |
| 867 return metrics && can_embed(*metrics); | 756 return metrics && can_embed(*metrics); |
| 868 } | 757 } |
| 869 | 758 |
| 870 void SkPDFFont::drop() { | 759 void SkPDFFont::drop() { |
| 871 fTypeface = nullptr; | 760 fTypeface = nullptr; |
| 872 this->SkPDFDict::drop(); | 761 this->SkPDFDict::drop(); |
| 873 } | 762 } |
| OLD | NEW |