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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 AdvanceMetric(const AdvanceMetric&) = delete; | 53 AdvanceMetric(const AdvanceMetric&) = delete; |
54 AdvanceMetric& operator=(const AdvanceMetric&) = delete; | 54 AdvanceMetric& operator=(const AdvanceMetric&) = delete; |
55 }; | 55 }; |
56 | 56 |
57 class SkPDFType0Font final : public SkPDFFont { | 57 class SkPDFType0Font final : public SkPDFFont { |
58 public: | 58 public: |
59 SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, | 59 SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, |
60 SkTypeface* typeface); | 60 SkTypeface* typeface); |
61 virtual ~SkPDFType0Font(); | 61 virtual ~SkPDFType0Font(); |
62 bool multiByteGlyphs() const override { return true; } | 62 bool multiByteGlyphs() const override { return true; } |
63 SkPDFFont* getFontSubset(const SkPDFGlyphSet* usage) override; | 63 sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; |
64 #ifdef SK_DEBUG | 64 #ifdef SK_DEBUG |
65 void emitObject(SkWStream*, | 65 void emitObject(SkWStream*, |
66 const SkPDFObjNumMap&, | 66 const SkPDFObjNumMap&, |
67 const SkPDFSubstituteMap&) const override; | 67 const SkPDFSubstituteMap&) const override; |
68 #endif | 68 #endif |
69 | 69 |
70 private: | 70 private: |
71 #ifdef SK_DEBUG | 71 #ifdef SK_DEBUG |
72 bool fPopulated; | 72 bool fPopulated; |
73 #endif | 73 #endif |
(...skipping 27 matching lines...) Expand all Loading... |
101 private: | 101 private: |
102 bool populate(int16_t glyphID); | 102 bool populate(int16_t glyphID); |
103 bool addFontDescriptor(int16_t defaultWidth); | 103 bool addFontDescriptor(int16_t defaultWidth); |
104 }; | 104 }; |
105 | 105 |
106 class SkPDFType3Font final : public SkPDFFont { | 106 class SkPDFType3Font final : public SkPDFFont { |
107 public: | 107 public: |
108 SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, | 108 SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, |
109 SkTypeface* typeface, | 109 SkTypeface* typeface, |
110 uint16_t glyphID); | 110 uint16_t glyphID); |
111 virtual ~SkPDFType3Font(); | 111 virtual ~SkPDFType3Font() {} |
| 112 void emitObject(SkWStream*, |
| 113 const SkPDFObjNumMap&, |
| 114 const SkPDFSubstituteMap&) const override { |
| 115 SkDEBUGFAIL("should call getFontSubset!"); |
| 116 } |
| 117 sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; |
112 bool multiByteGlyphs() const override { return false; } | 118 bool multiByteGlyphs() const override { return false; } |
113 | |
114 private: | |
115 bool populate(uint16_t glyphID); | |
116 }; | 119 }; |
117 | 120 |
118 /////////////////////////////////////////////////////////////////////////////// | 121 /////////////////////////////////////////////////////////////////////////////// |
119 // File-Local Functions | 122 // File-Local Functions |
120 /////////////////////////////////////////////////////////////////////////////// | 123 /////////////////////////////////////////////////////////////////////////////// |
121 | 124 |
122 const int16_t kInvalidAdvance = SK_MinS16; | 125 const int16_t kInvalidAdvance = SK_MinS16; |
123 const int16_t kDontCareAdvance = SK_MinS16 + 1; | 126 const int16_t kDontCareAdvance = SK_MinS16 + 1; |
124 | 127 |
125 static void stripUninterestingTrailingAdvancesFromRange( | 128 static void stripUninterestingTrailingAdvancesFromRange( |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 return SkScalarMulDiv(scaled, 1000, emSize); | 331 return SkScalarMulDiv(scaled, 1000, emSize); |
329 } | 332 } |
330 } | 333 } |
331 | 334 |
332 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { | 335 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { |
333 return from_font_units(SkIntToScalar(val), emSize); | 336 return from_font_units(SkIntToScalar(val), emSize); |
334 } | 337 } |
335 | 338 |
336 | 339 |
337 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, | 340 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, |
338 SkWStream* content) { | 341 SkDynamicMemoryWStream* content) { |
339 // Specify width and bounding box for the glyph. | 342 // Specify width and bounding box for the glyph. |
340 SkPDFUtils::AppendScalar(width, content); | 343 SkPDFUtils::AppendScalar(width, content); |
341 content->writeText(" 0 "); | 344 content->writeText(" 0 "); |
342 content->writeDecAsText(box.fLeft); | 345 content->writeDecAsText(box.fLeft); |
343 content->writeText(" "); | 346 content->writeText(" "); |
344 content->writeDecAsText(box.fTop); | 347 content->writeDecAsText(box.fTop); |
345 content->writeText(" "); | 348 content->writeText(" "); |
346 content->writeDecAsText(box.fRight); | 349 content->writeDecAsText(box.fRight); |
347 content->writeText(" "); | 350 content->writeText(" "); |
348 content->writeDecAsText(box.fBottom); | 351 content->writeDecAsText(box.fBottom); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 } | 515 } |
513 | 516 |
514 return numGlyphs; | 517 return numGlyphs; |
515 } | 518 } |
516 | 519 |
517 // static | 520 // static |
518 SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, | 521 SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, |
519 SkTypeface* typeface, | 522 SkTypeface* typeface, |
520 uint16_t glyphID) { | 523 uint16_t glyphID) { |
521 SkASSERT(canon); | 524 SkASSERT(canon); |
522 SkAutoResolveDefaultTypeface autoResolve(typeface); | 525 const uint32_t fontID = SkTypeface::UniqueID(typeface); |
523 typeface = autoResolve.get(); | |
524 const uint32_t fontID = typeface->uniqueID(); | |
525 | |
526 SkPDFFont* relatedFont; | 526 SkPDFFont* relatedFont; |
527 if (SkPDFFont* pdfFont = canon->findFont(fontID, glyphID, &relatedFont)) { | 527 if (SkPDFFont* pdfFont = canon->findFont(fontID, glyphID, &relatedFont)) { |
528 return SkRef(pdfFont); | 528 return SkRef(pdfFont); |
529 } | 529 } |
530 | 530 SkAutoResolveDefaultTypeface autoResolve(typeface); |
| 531 typeface = autoResolve.get(); |
| 532 SkASSERT(typeface); |
| 533 int glyphCount = typeface->countGlyphs(); |
| 534 if (glyphCount < 1 || // typeface lacks even a NOTDEF glyph. |
| 535 glyphCount > 1 + SK_MaxU16 || // invalid glyphCount |
| 536 glyphID >= glyphCount) { // invalid glyph |
| 537 return nullptr; |
| 538 } |
531 sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics; | 539 sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics; |
532 SkPDFDict* relatedFontDescriptor = nullptr; | 540 SkPDFDict* relatedFontDescriptor = nullptr; |
533 if (relatedFont) { | 541 if (relatedFont) { |
534 fontMetrics.reset(SkSafeRef(relatedFont->fontInfo())); | 542 fontMetrics.reset(SkSafeRef(relatedFont->fontInfo())); |
535 relatedFontDescriptor = relatedFont->getFontDescriptor(); | 543 relatedFontDescriptor = relatedFont->getFontDescriptor(); |
536 | 544 |
537 // This only is to catch callers who pass invalid glyph ids. | 545 // This only is to catch callers who pass invalid glyph ids. |
538 // If glyph id is invalid, then we will create duplicate entries | 546 // If glyph id is invalid, then we will create duplicate entries |
539 // for TrueType fonts. | 547 // for TrueType fonts. |
540 SkAdvancedTypefaceMetrics::FontType fontType = | 548 SkAdvancedTypefaceMetrics::FontType fontType = |
(...skipping 11 matching lines...) Expand all Loading... |
552 fontMetrics.reset( | 560 fontMetrics.reset( |
553 typeface->getAdvancedTypefaceMetrics(info, nullptr, 0)); | 561 typeface->getAdvancedTypefaceMetrics(info, nullptr, 0)); |
554 } | 562 } |
555 | 563 |
556 SkPDFFont* font = SkPDFFont::Create(canon, fontMetrics.get(), typeface, | 564 SkPDFFont* font = SkPDFFont::Create(canon, fontMetrics.get(), typeface, |
557 glyphID, relatedFontDescriptor); | 565 glyphID, relatedFontDescriptor); |
558 canon->addFont(font, fontID, font->fFirstGlyphID); | 566 canon->addFont(font, fontID, font->fFirstGlyphID); |
559 return font; | 567 return font; |
560 } | 568 } |
561 | 569 |
562 SkPDFFont* SkPDFFont::getFontSubset(const SkPDFGlyphSet*) { | 570 sk_sp<SkPDFObject> SkPDFFont::getFontSubset(const SkPDFGlyphSet*) { |
563 return nullptr; // Default: no support. | 571 return nullptr; // Default: no support. |
564 } | 572 } |
565 | 573 |
| 574 // TODO: take a sk_sp<SkAdvancedTypefaceMetrics> and sk_sp<SkTypeface> |
566 SkPDFFont::SkPDFFont(const SkAdvancedTypefaceMetrics* info, | 575 SkPDFFont::SkPDFFont(const SkAdvancedTypefaceMetrics* info, |
567 SkTypeface* typeface, | 576 SkTypeface* typeface, |
568 SkPDFDict* relatedFontDescriptor) | 577 SkPDFDict* relatedFontDescriptor) |
569 : SkPDFDict("Font") | 578 : SkPDFDict("Font") |
570 , fTypeface(ref_or_default(typeface)) | 579 , fTypeface(ref_or_default(typeface)) |
571 , fFirstGlyphID(1) | 580 , fFirstGlyphID(1) |
572 , fLastGlyphID(info ? info->fLastGlyphID : 0) | 581 , fLastGlyphID(info ? info->fLastGlyphID : 0) |
573 , fFontInfo(SkSafeRef(info)) | 582 , fFontInfo(SkSafeRef(info)) |
574 , fDescriptor(SkSafeRef(relatedFontDescriptor)) { | 583 , fDescriptor(SkSafeRef(relatedFontDescriptor)) |
575 if (info == nullptr || | 584 , fFontType((!info || info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster
_FontFlag) |
576 info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) { | 585 ? SkAdvancedTypefaceMetrics::kOther_Font |
577 fFontType = SkAdvancedTypefaceMetrics::kOther_Font; | 586 : info->fType) { |
578 } else { | 587 SkASSERT(fTypeface); |
579 fFontType = info->fType; | 588 if (0 == fLastGlyphID) { |
| 589 fLastGlyphID = SkToU16(fTypeface->countGlyphs() - 1); |
580 } | 590 } |
581 } | 591 } |
582 | 592 |
583 // static | 593 // static |
584 SkPDFFont* SkPDFFont::Create(SkPDFCanon* canon, | 594 SkPDFFont* SkPDFFont::Create(SkPDFCanon* canon, |
585 const SkAdvancedTypefaceMetrics* info, | 595 const SkAdvancedTypefaceMetrics* info, |
586 SkTypeface* typeface, | 596 SkTypeface* typeface, |
587 uint16_t glyphID, | 597 uint16_t glyphID, |
588 SkPDFDict* relatedFontDescriptor) { | 598 SkPDFDict* relatedFontDescriptor) { |
589 SkAdvancedTypefaceMetrics::FontType type = | 599 SkAdvancedTypefaceMetrics::FontType type = |
590 info ? info->fType : SkAdvancedTypefaceMetrics::kOther_Font; | 600 info ? info->fType : SkAdvancedTypefaceMetrics::kOther_Font; |
591 | 601 SkAdvancedTypefaceMetrics::FontFlags flags = |
592 if (info && (info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag
)) { | 602 info ? info->fFlags : SkAdvancedTypefaceMetrics::kEmpty_FontFlag; |
| 603 if (SkToBool(flags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) { |
593 return new SkPDFType3Font(info, typeface, glyphID); | 604 return new SkPDFType3Font(info, typeface, glyphID); |
594 } | 605 } |
595 if (type == SkAdvancedTypefaceMetrics::kType1CID_Font || | 606 switch (type) { |
596 type == SkAdvancedTypefaceMetrics::kTrueType_Font) { | 607 case SkAdvancedTypefaceMetrics::kType1CID_Font: |
597 SkASSERT(relatedFontDescriptor == nullptr); | 608 case SkAdvancedTypefaceMetrics::kTrueType_Font: |
598 return new SkPDFType0Font(info, typeface); | 609 SkASSERT(relatedFontDescriptor == nullptr); |
| 610 SkASSERT(info != nullptr); |
| 611 return new SkPDFType0Font(info, typeface); |
| 612 case SkAdvancedTypefaceMetrics::kType1_Font: |
| 613 SkASSERT(info != nullptr); |
| 614 return new SkPDFType1Font(info, typeface, glyphID, relatedFontDescri
ptor); |
| 615 case SkAdvancedTypefaceMetrics::kCFF_Font: |
| 616 SkASSERT(info != nullptr); |
| 617 // fallthrough |
| 618 case SkAdvancedTypefaceMetrics::kOther_Font: |
| 619 return new SkPDFType3Font(info, typeface, glyphID); |
599 } | 620 } |
600 if (type == SkAdvancedTypefaceMetrics::kType1_Font) { | 621 SkDEBUGFAIL("invalid SkAdvancedTypefaceMetrics::FontType"); |
601 return new SkPDFType1Font(info, typeface, glyphID, relatedFontDescriptor
); | 622 return nullptr; |
602 } | |
603 | |
604 SkASSERT(type == SkAdvancedTypefaceMetrics::kCFF_Font || | |
605 type == SkAdvancedTypefaceMetrics::kOther_Font); | |
606 | |
607 return new SkPDFType3Font(info, typeface, glyphID); | |
608 } | 623 } |
609 | 624 |
610 const SkAdvancedTypefaceMetrics* SkPDFFont::fontInfo() { | 625 const SkAdvancedTypefaceMetrics* SkPDFFont::fontInfo() { |
611 return fFontInfo.get(); | 626 return fFontInfo.get(); |
612 } | 627 } |
613 | 628 |
614 void SkPDFFont::setFontInfo(const SkAdvancedTypefaceMetrics* info) { | 629 void SkPDFFont::setFontInfo(const SkAdvancedTypefaceMetrics* info) { |
615 if (info == nullptr || info == fFontInfo.get()) { | 630 if (info == nullptr || info == fFontInfo.get()) { |
616 return; | 631 return; |
617 } | 632 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, SkTypeface
* typeface) | 711 SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, SkTypeface
* typeface) |
697 : SkPDFFont(info, typeface, nullptr) { | 712 : SkPDFFont(info, typeface, nullptr) { |
698 SkDEBUGCODE(fPopulated = false); | 713 SkDEBUGCODE(fPopulated = false); |
699 if (!canSubset()) { | 714 if (!canSubset()) { |
700 this->populate(nullptr); | 715 this->populate(nullptr); |
701 } | 716 } |
702 } | 717 } |
703 | 718 |
704 SkPDFType0Font::~SkPDFType0Font() {} | 719 SkPDFType0Font::~SkPDFType0Font() {} |
705 | 720 |
706 SkPDFFont* SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) { | 721 sk_sp<SkPDFObject> SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) { |
707 if (!canSubset()) { | 722 if (!canSubset()) { |
708 return nullptr; | 723 return nullptr; |
709 } | 724 } |
710 SkPDFType0Font* newSubset = new SkPDFType0Font(fontInfo(), typeface()); | 725 auto newSubset = sk_make_sp<SkPDFType0Font>(fontInfo(), typeface()); |
711 newSubset->populate(subset); | 726 newSubset->populate(subset); |
712 return newSubset; | 727 return newSubset; |
713 } | 728 } |
714 | 729 |
715 #ifdef SK_DEBUG | 730 #ifdef SK_DEBUG |
716 void SkPDFType0Font::emitObject(SkWStream* stream, | 731 void SkPDFType0Font::emitObject(SkWStream* stream, |
717 const SkPDFObjNumMap& objNumMap, | 732 const SkPDFObjNumMap& objNumMap, |
718 const SkPDFSubstituteMap& substitutes) const { | 733 const SkPDFSubstituteMap& substitutes) const { |
719 SkASSERT(fPopulated); | 734 SkASSERT(fPopulated); |
720 return INHERITED::emitObject(stream, objNumMap, substitutes); | 735 return INHERITED::emitObject(stream, objNumMap, substitutes); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 return true; | 886 return true; |
872 } | 887 } |
873 | 888 |
874 void set_glyph_widths(SkTypeface* tf, | 889 void set_glyph_widths(SkTypeface* tf, |
875 const SkTDArray<uint32_t>* glyphIDs, | 890 const SkTDArray<uint32_t>* glyphIDs, |
876 SkSinglyLinkedList<AdvanceMetric>* dst) { | 891 SkSinglyLinkedList<AdvanceMetric>* dst) { |
877 SkPaint tmpPaint; | 892 SkPaint tmpPaint; |
878 tmpPaint.setHinting(SkPaint::kNo_Hinting); | 893 tmpPaint.setHinting(SkPaint::kNo_Hinting); |
879 tmpPaint.setTypeface(sk_ref_sp(tf)); | 894 tmpPaint.setTypeface(sk_ref_sp(tf)); |
880 tmpPaint.setTextSize((SkScalar)tf->getUnitsPerEm()); | 895 tmpPaint.setTextSize((SkScalar)tf->getUnitsPerEm()); |
881 SkAutoGlyphCache autoGlyphCache(tmpPaint, nullptr, nullptr); | 896 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
| 897 SkAutoGlyphCache autoGlyphCache(tmpPaint, &props, nullptr); |
882 if (!glyphIDs || glyphIDs->isEmpty()) { | 898 if (!glyphIDs || glyphIDs->isEmpty()) { |
883 get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get(
)); | 899 get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get(
)); |
884 } else { | 900 } else { |
885 get_glyph_widths(dst, tf->countGlyphs(), glyphIDs->begin(), | 901 get_glyph_widths(dst, tf->countGlyphs(), glyphIDs->begin(), |
886 glyphIDs->count(), autoGlyphCache.get()); | 902 glyphIDs->count(), autoGlyphCache.get()); |
887 } | 903 } |
888 } | 904 } |
889 | 905 |
890 sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithGlyphNames( | 906 sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithGlyphNames( |
891 SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) { | 907 SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1010 // glyphCount not including glyph 0 | 1026 // glyphCount not including glyph 0 |
1011 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID; | 1027 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID; |
1012 SkASSERT(glyphCount > 0 && glyphCount <= 255); | 1028 SkASSERT(glyphCount > 0 && glyphCount <= 255); |
1013 this->insertInt("FirstChar", (size_t)0); | 1029 this->insertInt("FirstChar", (size_t)0); |
1014 this->insertInt("LastChar", (size_t)glyphCount); | 1030 this->insertInt("LastChar", (size_t)glyphCount); |
1015 { | 1031 { |
1016 SkPaint tmpPaint; | 1032 SkPaint tmpPaint; |
1017 tmpPaint.setHinting(SkPaint::kNo_Hinting); | 1033 tmpPaint.setHinting(SkPaint::kNo_Hinting); |
1018 tmpPaint.setTypeface(sk_ref_sp(this->typeface())); | 1034 tmpPaint.setTypeface(sk_ref_sp(this->typeface())); |
1019 tmpPaint.setTextSize((SkScalar)this->typeface()->getUnitsPerEm()); | 1035 tmpPaint.setTextSize((SkScalar)this->typeface()->getUnitsPerEm()); |
1020 SkAutoGlyphCache glyphCache(tmpPaint, nullptr, nullptr); | 1036 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
| 1037 SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); |
1021 auto widths = sk_make_sp<SkPDFArray>(); | 1038 auto widths = sk_make_sp<SkPDFArray>(); |
1022 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX; | 1039 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX; |
1023 const uint16_t emSize = this->fontInfo()->fEmSize; | 1040 const uint16_t emSize = this->fontInfo()->fEmSize; |
1024 widths->appendScalar(from_font_units(advance, emSize)); | 1041 widths->appendScalar(from_font_units(advance, emSize)); |
1025 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) { | 1042 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) { |
1026 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX; | 1043 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX; |
1027 widths->appendScalar(from_font_units(advance, emSize)); | 1044 widths->appendScalar(from_font_units(advance, emSize)); |
1028 } | 1045 } |
1029 this->insertObject("Widths", std::move(widths)); | 1046 this->insertObject("Widths", std::move(widths)); |
1030 } | 1047 } |
(...skipping 16 matching lines...) Expand all Loading... |
1047 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); | 1064 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); |
1048 encoding->insertObject("Differences", std::move(encDiffs)); | 1065 encoding->insertObject("Differences", std::move(encDiffs)); |
1049 this->insertObject("Encoding", std::move(encoding)); | 1066 this->insertObject("Encoding", std::move(encoding)); |
1050 return true; | 1067 return true; |
1051 } | 1068 } |
1052 | 1069 |
1053 /////////////////////////////////////////////////////////////////////////////// | 1070 /////////////////////////////////////////////////////////////////////////////// |
1054 // class SkPDFType3Font | 1071 // class SkPDFType3Font |
1055 /////////////////////////////////////////////////////////////////////////////// | 1072 /////////////////////////////////////////////////////////////////////////////// |
1056 | 1073 |
| 1074 namespace { |
| 1075 // returns [0, first, first+1, ... last-1, last] |
| 1076 struct SingleByteGlyphIdIterator { |
| 1077 SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last) |
| 1078 : fFirst(first), fLast(last) { |
| 1079 SkASSERT(fFirst > 0); |
| 1080 SkASSERT(fLast >= first); |
| 1081 } |
| 1082 struct Iter { |
| 1083 void operator++() { |
| 1084 fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1; |
| 1085 } |
| 1086 // This is an input_iterator |
| 1087 SkGlyphID operator*() const { return (SkGlyphID)fCurrent; } |
| 1088 bool operator!=(const Iter& rhs) const { |
| 1089 return fCurrent != rhs.fCurrent; |
| 1090 } |
| 1091 Iter(SkGlyphID f, int c) : fFirst(f), fCurrent(c) {} |
| 1092 private: |
| 1093 const SkGlyphID fFirst; |
| 1094 int fCurrent; // must be int to make fLast+1 to fit |
| 1095 }; |
| 1096 Iter begin() const { return Iter(fFirst, 0); } |
| 1097 Iter end() const { return Iter(fFirst, (int)fLast + 1); } |
| 1098 private: |
| 1099 const SkGlyphID fFirst; |
| 1100 const SkGlyphID fLast; |
| 1101 }; |
| 1102 } |
| 1103 |
| 1104 static void add_type3_font_info(SkPDFDict* font, |
| 1105 SkTypeface* typeface, |
| 1106 SkScalar emSize, |
| 1107 const SkPDFGlyphSet* subset, |
| 1108 SkGlyphID firstGlyphID, |
| 1109 SkGlyphID lastGlyphID) { |
| 1110 SkASSERT(lastGlyphID >= firstGlyphID); |
| 1111 SkPaint paint; |
| 1112 paint.setHinting(SkPaint::kNo_Hinting); |
| 1113 paint.setTypeface(sk_ref_sp(typeface)); |
| 1114 paint.setTextSize(emSize); |
| 1115 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
| 1116 SkAutoGlyphCache cache(paint, &props, nullptr); |
| 1117 |
| 1118 font->insertName("Subtype", "Type3"); |
| 1119 // Flip about the x-axis and scale by 1/emSize. |
| 1120 SkMatrix fontMatrix; |
| 1121 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize)); |
| 1122 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); |
| 1123 |
| 1124 auto charProcs = sk_make_sp<SkPDFDict>(); |
| 1125 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); |
| 1126 |
| 1127 auto encDiffs = sk_make_sp<SkPDFArray>(); |
| 1128 // length(firstGlyphID .. lastGlyphID) == lastGlyphID - firstGlyphID + 1 |
| 1129 // plus 1 for glyph 0; |
| 1130 SkASSERT(firstGlyphID > 0); |
| 1131 SkASSERT(lastGlyphID >= firstGlyphID); |
| 1132 int glyphCount = lastGlyphID - firstGlyphID + 2; |
| 1133 // one other entry for the index of first glyph. |
| 1134 encDiffs->reserve(glyphCount + 1); |
| 1135 encDiffs->appendInt(0); // index of first glyph |
| 1136 |
| 1137 auto widthArray = sk_make_sp<SkPDFArray>(); |
| 1138 widthArray->reserve(glyphCount); |
| 1139 |
| 1140 SkIRect bbox = SkIRect::MakeEmpty(); |
| 1141 |
| 1142 sk_sp<SkPDFStream> emptyStream; |
| 1143 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) { |
| 1144 bool skipGlyph = subset && gID != 0 && !subset->has(gID); |
| 1145 SkString characterName; |
| 1146 SkScalar advance = 0.0f; |
| 1147 SkIRect glyphBBox; |
| 1148 if (skipGlyph) { |
| 1149 characterName.set("g0"); |
| 1150 } else { |
| 1151 characterName.printf("g%X", gID); |
| 1152 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); |
| 1153 advance = SkFloatToScalar(glyph.fAdvanceX); |
| 1154 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, |
| 1155 glyph.fWidth, glyph.fHeight); |
| 1156 bbox.join(glyphBBox); |
| 1157 const SkPath* path = cache->findPath(glyph); |
| 1158 if (path && !path->isEmpty()) { |
| 1159 SkDynamicMemoryWStream content; |
| 1160 setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), gl
yphBBox, |
| 1161 &content); |
| 1162 SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content); |
| 1163 SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(), |
| 1164 &content); |
| 1165 charProcs->insertObjRef( |
| 1166 characterName, sk_make_sp<SkPDFStream>( |
| 1167 std::unique_ptr<SkStreamAsset>(content.detachAsStrea
m()))); |
| 1168 } else { |
| 1169 if (!emptyStream) { |
| 1170 emptyStream = sk_make_sp<SkPDFStream>( |
| 1171 std::unique_ptr<SkStreamAsset>( |
| 1172 new SkMemoryStream((size_t)0))); |
| 1173 } |
| 1174 charProcs->insertObjRef(characterName, emptyStream); |
| 1175 } |
| 1176 } |
| 1177 encDiffs->appendName(characterName.c_str()); |
| 1178 widthArray->appendScalar(advance); |
| 1179 } |
| 1180 |
| 1181 encoding->insertObject("Differences", std::move(encDiffs)); |
| 1182 font->insertInt("FirstChar", 0); |
| 1183 font->insertInt("LastChar", lastGlyphID - firstGlyphID + 1); |
| 1184 /* FontBBox: "A rectangle expressed in the glyph coordinate |
| 1185 system, specifying the font bounding box. This is the smallest |
| 1186 rectangle enclosing the shape that would result if all of the |
| 1187 glyphs of the font were placed with their origins coincident and |
| 1188 then filled." */ |
| 1189 auto fontBBox = sk_make_sp<SkPDFArray>(); |
| 1190 fontBBox->reserve(4); |
| 1191 fontBBox->appendInt(bbox.left()); |
| 1192 fontBBox->appendInt(bbox.bottom()); |
| 1193 fontBBox->appendInt(bbox.right()); |
| 1194 fontBBox->appendInt(bbox.top()); |
| 1195 font->insertObject("FontBBox", std::move(fontBBox)); |
| 1196 font->insertName("CIDToGIDMap", "Identity"); |
| 1197 sk_sp<const SkAdvancedTypefaceMetrics> metrics; |
| 1198 if (subset) { |
| 1199 SkTDArray<uint32_t> subsetList; |
| 1200 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID
)) { |
| 1201 if (gID == 0 || subset->has(gID)) { // Always include glyph 0. |
| 1202 subsetList.push(0); |
| 1203 } |
| 1204 } |
| 1205 subset->exportTo(&subsetList); |
| 1206 metrics = SkPDFFont::GetFontMetricsWithToUnicode(typeface, subsetList.be
gin(), |
| 1207 subsetList.count()); |
| 1208 } else { |
| 1209 metrics = SkPDFFont::GetFontMetricsWithToUnicode(typeface, nullptr, 0); |
| 1210 } |
| 1211 if (metrics) { |
| 1212 font->insertObjRef("ToUnicode", |
| 1213 SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode, |
| 1214 subset, |
| 1215 false, |
| 1216 firstGlyphID, |
| 1217 lastGlyphID)); |
| 1218 } |
| 1219 font->insertObject("Widths", std::move(widthArray)); |
| 1220 font->insertObject("Encoding", std::move(encoding)); |
| 1221 font->insertObject("CharProcs", std::move(charProcs)); |
| 1222 } |
| 1223 |
1057 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, | 1224 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, |
1058 SkTypeface* typeface, | 1225 SkTypeface* typeface, |
1059 uint16_t glyphID) | 1226 uint16_t glyphID) |
1060 : SkPDFFont(info, typeface, nullptr) { | 1227 : SkPDFFont(info, typeface, nullptr) { |
1061 this->populate(glyphID); | 1228 // If fLastGlyphID isn't set (because there is not fFontInfo), look it up. |
| 1229 this->setLastGlyphID(SkToU16(typeface->countGlyphs() - 1)); |
| 1230 this->adjustGlyphRangeForSingleByteEncoding(glyphID); |
1062 } | 1231 } |
1063 | 1232 |
1064 SkPDFType3Font::~SkPDFType3Font() {} | 1233 sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(const SkPDFGlyphSet* usage) { |
| 1234 // All fonts are subset before serialization. |
| 1235 // TODO(halcanary): all fonts should follow this pattern. |
| 1236 auto font = sk_make_sp<SkPDFDict>("Font"); |
| 1237 const SkAdvancedTypefaceMetrics* info = this->fontInfo(); |
| 1238 uint16_t emSize = info && info->fEmSize > 0 ? info->fEmSize : 1000; |
| 1239 add_type3_font_info(font.get(), this->typeface(), (SkScalar)emSize, usage, |
| 1240 this->firstGlyphID(), this->lastGlyphID()); |
| 1241 return font; |
| 1242 } |
1065 | 1243 |
1066 bool SkPDFType3Font::populate(uint16_t glyphID) { | |
1067 SkPaint paint; | |
1068 paint.setTypeface(sk_ref_sp(this->typeface())); | |
1069 paint.setTextSize(1000); | |
1070 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); | |
1071 SkAutoGlyphCache autoCache(paint, &props, nullptr); | |
1072 SkGlyphCache* cache = autoCache.getCache(); | |
1073 // If fLastGlyphID isn't set (because there is not fFontInfo), look it up. | |
1074 if (lastGlyphID() == 0) { | |
1075 setLastGlyphID(cache->getGlyphCount() - 1); | |
1076 } | |
1077 | 1244 |
1078 adjustGlyphRangeForSingleByteEncoding(glyphID); | 1245 //////////////////////////////////////////////////////////////////////////////// |
1079 | |
1080 insertName("Subtype", "Type3"); | |
1081 // Flip about the x-axis and scale by 1/1000. | |
1082 SkMatrix fontMatrix; | |
1083 fontMatrix.setScale(SkScalarInvert(1000), -SkScalarInvert(1000)); | |
1084 this->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); | |
1085 | |
1086 auto charProcs = sk_make_sp<SkPDFDict>(); | |
1087 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); | |
1088 | |
1089 auto encDiffs = sk_make_sp<SkPDFArray>(); | |
1090 encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); | |
1091 encDiffs->appendInt(1); | |
1092 | |
1093 auto widthArray = sk_make_sp<SkPDFArray>(); | |
1094 | |
1095 SkIRect bbox = SkIRect::MakeEmpty(); | |
1096 for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { | |
1097 SkString characterName; | |
1098 characterName.printf("gid%d", gID); | |
1099 encDiffs->appendName(characterName.c_str()); | |
1100 | |
1101 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); | |
1102 widthArray->appendScalar(SkFloatToScalar(glyph.fAdvanceX)); | |
1103 SkIRect glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, | |
1104 glyph.fWidth, glyph.fHeight); | |
1105 bbox.join(glyphBBox); | |
1106 | |
1107 SkDynamicMemoryWStream content; | |
1108 setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox, | |
1109 &content); | |
1110 const SkPath* path = cache->findPath(glyph); | |
1111 if (path) { | |
1112 SkPDFUtils::EmitPath(*path, paint.getStyle(), &content); | |
1113 SkPDFUtils::PaintPath(paint.getStyle(), path->getFillType(), | |
1114 &content); | |
1115 } | |
1116 charProcs->insertObjRef( | |
1117 characterName, sk_make_sp<SkPDFStream>( | |
1118 std::unique_ptr<SkStreamAsset>(content.detachAsStream())
)); | |
1119 } | |
1120 | |
1121 encoding->insertObject("Differences", std::move(encDiffs)); | |
1122 | |
1123 this->insertObject("CharProcs", std::move(charProcs)); | |
1124 this->insertObject("Encoding", std::move(encoding)); | |
1125 | |
1126 this->insertObject("FontBBox", makeFontBBox(bbox, 1000)); | |
1127 this->insertInt("FirstChar", 1); | |
1128 this->insertInt("LastChar", lastGlyphID() - firstGlyphID() + 1); | |
1129 this->insertObject("Widths", std::move(widthArray)); | |
1130 this->insertName("CIDToGIDMap", "Identity"); | |
1131 | |
1132 this->populateToUnicodeTable(nullptr); | |
1133 return true; | |
1134 } | |
1135 | 1246 |
1136 SkPDFFont::Match SkPDFFont::IsMatch(SkPDFFont* existingFont, | 1247 SkPDFFont::Match SkPDFFont::IsMatch(SkPDFFont* existingFont, |
1137 uint32_t existingFontID, | 1248 uint32_t existingFontID, |
1138 uint16_t existingGlyphID, | 1249 uint16_t existingGlyphID, |
1139 uint32_t searchFontID, | 1250 uint32_t searchFontID, |
1140 uint16_t searchGlyphID) { | 1251 uint16_t searchGlyphID) { |
1141 if (existingFontID != searchFontID) { | 1252 if (existingFontID != searchFontID) { |
1142 return SkPDFFont::kNot_Match; | 1253 return SkPDFFont::kNot_Match; |
1143 } | 1254 } |
1144 if (existingGlyphID == 0 || searchGlyphID == 0) { | 1255 if (existingGlyphID == 0 || searchGlyphID == 0) { |
(...skipping 27 matching lines...) Expand all Loading... |
1172 } | 1283 } |
1173 return *canon->fCanEmbedTypeface.set(id, canEmbed); | 1284 return *canon->fCanEmbedTypeface.set(id, canEmbed); |
1174 } | 1285 } |
1175 | 1286 |
1176 void SkPDFFont::drop() { | 1287 void SkPDFFont::drop() { |
1177 fTypeface = nullptr; | 1288 fTypeface = nullptr; |
1178 fFontInfo = nullptr; | 1289 fFontInfo = nullptr; |
1179 fDescriptor = nullptr; | 1290 fDescriptor = nullptr; |
1180 this->SkPDFDict::drop(); | 1291 this->SkPDFDict::drop(); |
1181 } | 1292 } |
OLD | NEW |