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