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