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

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) 10:28:24 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 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); 1057 auto encoding = sk_make_sp<SkPDFDict>("Encoding");
1048 encoding->insertObject("Differences", std::move(encDiffs)); 1058 encoding->insertObject("Differences", std::move(encDiffs));
1049 this->insertObject("Encoding", std::move(encoding)); 1059 this->insertObject("Encoding", std::move(encoding));
1050 return true; 1060 return true;
1051 } 1061 }
1052 1062
1053 /////////////////////////////////////////////////////////////////////////////// 1063 ///////////////////////////////////////////////////////////////////////////////
1054 // class SkPDFType3Font 1064 // class SkPDFType3Font
1055 /////////////////////////////////////////////////////////////////////////////// 1065 ///////////////////////////////////////////////////////////////////////////////
1056 1066
1067 namespace {
1068 // returns [0, first, first+1, ... last-1, last]
1069 struct SingleByteGlyphIdIterator {
1070 SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last)
1071 : fFirst(first), fLast(last) {
1072 SkASSERT(fFirst > 0);
1073 SkASSERT(fLast >= first);
1074 }
1075 struct Iter {
1076 void operator++() {
1077 fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1;
1078 }
1079 SkGlyphID operator*() const { return SkToU16(fCurrent); }
bungeman-skia 2016/08/10 15:32:56 Doesn't this operator normally return a reference?
hal.canary 2016/08/10 18:59:52 It doesn't have to, but okay. Done.
1080 bool operator!=(const Iter& rhs) const {
1081 return fCurrent != rhs.fCurrent;
1082 }
1083 const SkGlyphID& fFirst;
bungeman-skia 2016/08/10 15:32:56 It seems odd that this is a reference. If the comp
hal.canary 2016/08/10 18:59:53 Done.
1084 int fCurrent;
1085 };
1086 Iter begin() const { return Iter{fFirst, 0}; }
1087 Iter end() const { return{fFirst, (int)(fLast)+1}; }
1088 SkGlyphID fFirst;
1089 SkGlyphID fLast;
bungeman-skia 2016/08/10 15:32:56 This is all in a limited scope, but it seems bette
hal.canary 2016/08/10 18:59:53 Done.
1090 };
1091 }
1092
1093 static void add_type3_font_info(SkPDFDict* font,
1094 SkTypeface* typeface,
1095 SkScalar emSize,
1096 const SkPDFGlyphSet* subset,
1097 SkGlyphID firstGlyphID,
1098 SkGlyphID lastGlyphID) {
1099 SkASSERT(lastGlyphID >= firstGlyphID);
1100 SkPaint paint;
1101 paint.setTypeface(sk_ref_sp(typeface));
1102 paint.setTextSize(emSize);
bungeman-skia 2016/08/10 15:32:56 Set hinting to none?
hal.canary 2016/08/10 18:59:52 Done.
1103 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
1104 SkAutoGlyphCache cache(paint, &props, nullptr);
1105
1106 font->insertName("Subtype", "Type3");
1107 // Flip about the x-axis and scale by 1/1000.
bungeman-skia 2016/08/10 15:32:56 comment: scale by em
hal.canary 2016/08/10 18:59:52 Done.
1108 SkMatrix fontMatrix;
1109 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize));
1110 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix));
1111
1112 auto charProcs = sk_make_sp<SkPDFDict>();
1113 auto encoding = sk_make_sp<SkPDFDict>("Encoding");
1114
1115 auto encDiffs = sk_make_sp<SkPDFArray>();
1116 encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
1117 encDiffs->appendInt(0);
1118
1119 auto widthArray = sk_make_sp<SkPDFArray>();
1120 widthArray->reserve(lastGlyphID - firstGlyphID + 2);
bungeman-skia 2016/08/10 15:32:56 a short comment about these magic '2' and '3' woul
hal.canary 2016/08/10 18:59:52 Done.
1121
1122 SkIRect bbox = SkIRect::MakeEmpty();
1123
1124 sk_sp<SkPDFStream> emptyStream;
1125 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
1126 bool skipGlyph = subset && gID != 0 && !subset->has(gID);
1127 SkString characterName;
1128 SkScalar advance = 0.0f;
1129 SkIRect glyphBBox;
1130 if (skipGlyph) {
1131 characterName.set("g0");
1132 } else {
1133 characterName.printf("g%X", gID);
1134 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID);
1135 advance = SkFloatToScalar(glyph.fAdvanceX);
1136 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop,
1137 glyph.fWidth, glyph.fHeight);
1138 bbox.join(glyphBBox);
1139 const SkPath* path = cache->findPath(glyph);
1140 if (path && !path->isEmpty()) {
1141 SkDynamicMemoryWStream content;
1142 setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), gl yphBBox,
1143 &content);
1144 SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content);
1145 content.writeText("f"); // ::kFill_Style, ::kWinding_FillType
1146 charProcs->insertObjRef(
1147 characterName, sk_make_sp<SkPDFStream>(
1148 std::unique_ptr<SkStreamAsset>(content.detachAsStrea m())));
1149 } else {
1150 if (!emptyStream) {
1151 emptyStream = sk_make_sp<SkPDFStream>(
1152 std::unique_ptr<SkStreamAsset>(
1153 new SkMemoryStream((size_t)0)));
1154 }
1155 charProcs->insertObjRef(characterName, emptyStream);
1156 }
1157 }
1158 encDiffs->appendName(characterName.c_str());
1159 widthArray->appendScalar(advance);
1160 }
1161
1162 encoding->insertObject("Differences", std::move(encDiffs));
1163 font->insertInt("FirstChar", 0);
1164 font->insertInt("LastChar", lastGlyphID - firstGlyphID + 1);
1165 font->insertObject("FontBBox", makeFontBBox(bbox, 1000));
bungeman-skia 2016/08/10 15:32:56 Is this 1000 right? Should it be em?
hal.canary 2016/08/10 18:59:52 actually no. they want the glyph coordinate syste
1166 font->insertName("CIDToGIDMap", "Identity");
1167 sk_sp<const SkAdvancedTypefaceMetrics> metrics;
1168 if (subset) {
1169 SkTDArray<uint32_t> subsetList;
1170 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID )) {
1171 if (gID == 0 || subset->has(gID)) { // Always include glyph 0.
1172 subsetList.push(0);
1173 }
1174 }
1175 subset->exportTo(&subsetList);
1176 metrics = SkPDFFont::GetFontMetricsWithToUnicode(typeface, subsetList.be gin(),
1177 subsetList.count());
1178 } else {
1179 metrics = SkPDFFont::GetFontMetricsWithToUnicode(typeface, nullptr, 0);
1180 }
1181 font->insertObjRef("ToUnicode",
1182 SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode,
1183 subset,
1184 false,
1185 firstGlyphID,
1186 lastGlyphID));
1187 font->insertObject("Widths", std::move(widthArray));
1188 font->insertObject("Encoding", std::move(encoding));
1189 font->insertObject("CharProcs", std::move(charProcs));
1190 }
1191
1057 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, 1192 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info,
1058 SkTypeface* typeface, 1193 SkTypeface* typeface,
1059 uint16_t glyphID) 1194 uint16_t glyphID)
1060 : SkPDFFont(info, typeface, nullptr) { 1195 : SkPDFFont(info, typeface, nullptr) {
1061 this->populate(glyphID); 1196 // If fLastGlyphID isn't set (because there is not fFontInfo), look it up.
1197 this->setLastGlyphID(SkToU16(typeface->countGlyphs() - 1));
1198 this->adjustGlyphRangeForSingleByteEncoding(glyphID);
1062 } 1199 }
1063 1200
1064 SkPDFType3Font::~SkPDFType3Font() {} 1201 sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(const SkPDFGlyphSet* usage) {
1202 // All fonts are subset before serialization.
1203 // TODO(halcanary): all fonts should follow this pattern.
1204 auto font = sk_make_sp<SkPDFDict>("Font");
1205 const SkAdvancedTypefaceMetrics* info = this->fontInfo();
1206 uint16_t emSize = info && info->fEmSize > 0 ? info->fEmSize : 1000;
bungeman-skia 2016/08/10 15:32:56 Do you sometimes get a bogus em size or no info? S
hal.canary 2016/08/10 18:59:52 I do not assume SkAdvancedTypefaceMetrics* is non-
1207 add_type3_font_info(font.get(), this->typeface(), (SkScalar)emSize, usage,
1208 this->firstGlyphID(), this->lastGlyphID());
1209 return font;
1210 }
1065 1211
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 1212
1078 adjustGlyphRangeForSingleByteEncoding(glyphID); 1213 ////////////////////////////////////////////////////////////////////////////////
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 1214
1136 SkPDFFont::Match SkPDFFont::IsMatch(SkPDFFont* existingFont, 1215 SkPDFFont::Match SkPDFFont::IsMatch(SkPDFFont* existingFont,
1137 uint32_t existingFontID, 1216 uint32_t existingFontID,
1138 uint16_t existingGlyphID, 1217 uint16_t existingGlyphID,
1139 uint32_t searchFontID, 1218 uint32_t searchFontID,
1140 uint16_t searchGlyphID) { 1219 uint16_t searchGlyphID) {
1141 if (existingFontID != searchFontID) { 1220 if (existingFontID != searchFontID) {
1142 return SkPDFFont::kNot_Match; 1221 return SkPDFFont::kNot_Match;
1143 } 1222 }
1144 if (existingGlyphID == 0 || searchGlyphID == 0) { 1223 if (existingGlyphID == 0 || searchGlyphID == 0) {
(...skipping 27 matching lines...) Expand all
1172 } 1251 }
1173 return *canon->fCanEmbedTypeface.set(id, canEmbed); 1252 return *canon->fCanEmbedTypeface.set(id, canEmbed);
1174 } 1253 }
1175 1254
1176 void SkPDFFont::drop() { 1255 void SkPDFFont::drop() {
1177 fTypeface = nullptr; 1256 fTypeface = nullptr;
1178 fFontInfo = nullptr; 1257 fFontInfo = nullptr;
1179 fDescriptor = nullptr; 1258 fDescriptor = nullptr;
1180 this->SkPDFDict::drop(); 1259 this->SkPDFDict::drop();
1181 } 1260 }
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