Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Side by Side Diff: src/pdf/SkPDFFont.cpp

Issue 2231483002: SkPDF: Subset Type3 (fallback) font (Closed) Base URL: https://skia.googlesource.com/skia.git@SkPDF_next3
Patch Set: 2016-08-10 (Wednesday) 14:58:04 EDT Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pdf/SkPDFFont.h ('k') | src/pdf/SkPDFTypes.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFFont.h ('k') | src/pdf/SkPDFTypes.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698