diff options
author | 2016-08-11 13:59:18 -0700 | |
---|---|---|
committer | 2016-08-11 13:59:19 -0700 | |
commit | 5bf60adaaf76a102514b420a4acff6083902dabc (patch) | |
tree | 167023fceb92caf2c5d59cb4b5c4fac68ec52d05 /src/pdf | |
parent | 637b3bf2b9c10398d823bd015a722842d4f2f971 (diff) |
Revert of SkPDF: Subset Type3 (fallback) font (patchset #8 id:200001 of https://codereview.chromium.org/2231483002/ )
Reason for revert:
internal failing
Original issue's description:
> SkPDF: Subset Type3 (fallback) font
>
> Motivation: significant file-size reduction.
>
> Also: SkPDFFont::subsetFont() returns a sk_sp<SkPDFObject>
> rather than a SkPDFFont*.
>
> SkPDFType3Font constructor no longer populates font info;
> relies on subsetting.
>
> SkPDFFont::Create is easier to read
>
> Also: SkPDFType3Font are scaled by emSize rather than 1000.
>
> GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2231483002
>
> Committed: https://skia.googlesource.com/skia/+/88b138da99328b04cae9a8ee19c3882b8847a550
TBR=bungeman@google.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Review-Url: https://codereview.chromium.org/2232283003
Diffstat (limited to 'src/pdf')
-rw-r--r-- | src/pdf/SkPDFDocument.cpp | 4 | ||||
-rw-r--r-- | src/pdf/SkPDFFont.cpp | 273 | ||||
-rw-r--r-- | src/pdf/SkPDFFont.h | 2 | ||||
-rw-r--r-- | src/pdf/SkPDFTypes.cpp | 4 |
4 files changed, 89 insertions, 194 deletions
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp index 4a577fcff3..7723cafb12 100644 --- a/src/pdf/SkPDFDocument.cpp +++ b/src/pdf/SkPDFDocument.cpp @@ -483,8 +483,8 @@ bool SkPDFDocument::onClose(SkWStream* stream) { // Build font subsetting info before calling addObjectRecursively(). for (const auto& entry : fGlyphUsage) { - sk_sp<SkPDFObject> subsetFont = - entry.fFont->getFontSubset(&entry.fGlyphSet); + sk_sp<SkPDFFont> subsetFont( + entry.fFont->getFontSubset(&entry.fGlyphSet)); if (subsetFont) { fObjectSerializer.fSubstituteMap.setSubstitute( entry.fFont, subsetFont.get()); diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp index 5695274e83..ff1dd2d76d 100644 --- a/src/pdf/SkPDFFont.cpp +++ b/src/pdf/SkPDFFont.cpp @@ -60,7 +60,7 @@ public: SkTypeface* typeface); virtual ~SkPDFType0Font(); bool multiByteGlyphs() const override { return true; } - sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; + SkPDFFont* getFontSubset(const SkPDFGlyphSet* usage) override; #ifdef SK_DEBUG void emitObject(SkWStream*, const SkPDFObjNumMap&, @@ -108,14 +108,11 @@ public: SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, uint16_t glyphID); - virtual ~SkPDFType3Font() {} - void emitObject(SkWStream*, - const SkPDFObjNumMap&, - const SkPDFSubstituteMap&) const override { - SkDEBUGFAIL("should call getFontSubset!"); - } - sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; + virtual ~SkPDFType3Font(); bool multiByteGlyphs() const override { return false; } + +private: + bool populate(uint16_t glyphID); }; /////////////////////////////////////////////////////////////////////////////// @@ -338,7 +335,7 @@ SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, - SkDynamicMemoryWStream* content) { + SkWStream* content) { // Specify width and bounding box for the glyph. SkPDFUtils::AppendScalar(width, content); content->writeText(" 0 "); @@ -562,7 +559,7 @@ SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, return font; } -sk_sp<SkPDFObject> SkPDFFont::getFontSubset(const SkPDFGlyphSet*) { +SkPDFFont* SkPDFFont::getFontSubset(const SkPDFGlyphSet*) { return nullptr; // Default: no support. } @@ -574,13 +571,12 @@ SkPDFFont::SkPDFFont(const SkAdvancedTypefaceMetrics* info, , fFirstGlyphID(1) , fLastGlyphID(info ? info->fLastGlyphID : 0) , fFontInfo(SkSafeRef(info)) - , fDescriptor(SkSafeRef(relatedFontDescriptor)) - , fFontType((!info || info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) - ? SkAdvancedTypefaceMetrics::kOther_Font - : info->fType) { - if (0 == fLastGlyphID) { - SkAutoResolveDefaultTypeface face(typeface); - fLastGlyphID = SkToU16(face->countGlyphs() - 1); + , fDescriptor(SkSafeRef(relatedFontDescriptor)) { + if (info == nullptr || + info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) { + fFontType = SkAdvancedTypefaceMetrics::kOther_Font; + } else { + fFontType = info->fType; } } @@ -592,28 +588,23 @@ SkPDFFont* SkPDFFont::Create(SkPDFCanon* canon, SkPDFDict* relatedFontDescriptor) { SkAdvancedTypefaceMetrics::FontType type = info ? info->fType : SkAdvancedTypefaceMetrics::kOther_Font; - SkAdvancedTypefaceMetrics::FontFlags flags = - info ? info->fFlags : SkAdvancedTypefaceMetrics::kEmpty_FontFlag; - if (SkToBool(flags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) { + + if (info && (info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) { return new SkPDFType3Font(info, typeface, glyphID); } - switch (type) { - case SkAdvancedTypefaceMetrics::kType1CID_Font: - case SkAdvancedTypefaceMetrics::kTrueType_Font: - SkASSERT(relatedFontDescriptor == nullptr); - SkASSERT(info != nullptr); - return new SkPDFType0Font(info, typeface); - case SkAdvancedTypefaceMetrics::kType1_Font: - SkASSERT(info != nullptr); - return new SkPDFType1Font(info, typeface, glyphID, relatedFontDescriptor); - case SkAdvancedTypefaceMetrics::kCFF_Font: - SkASSERT(info != nullptr); - // fallthrough - case SkAdvancedTypefaceMetrics::kOther_Font: - return new SkPDFType3Font(info, typeface, glyphID); + if (type == SkAdvancedTypefaceMetrics::kType1CID_Font || + type == SkAdvancedTypefaceMetrics::kTrueType_Font) { + SkASSERT(relatedFontDescriptor == nullptr); + return new SkPDFType0Font(info, typeface); + } + if (type == SkAdvancedTypefaceMetrics::kType1_Font) { + return new SkPDFType1Font(info, typeface, glyphID, relatedFontDescriptor); } - SkDEBUGFAIL("invalid SkAdvancedTypefaceMetrics::FontType"); - return nullptr; + + SkASSERT(type == SkAdvancedTypefaceMetrics::kCFF_Font || + type == SkAdvancedTypefaceMetrics::kOther_Font); + + return new SkPDFType3Font(info, typeface, glyphID); } const SkAdvancedTypefaceMetrics* SkPDFFont::fontInfo() { @@ -712,11 +703,11 @@ SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, SkTypeface SkPDFType0Font::~SkPDFType0Font() {} -sk_sp<SkPDFObject> SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) { +SkPDFFont* SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) { if (!canSubset()) { return nullptr; } - auto newSubset = sk_make_sp<SkPDFType0Font>(fontInfo(), typeface()); + SkPDFType0Font* newSubset = new SkPDFType0Font(fontInfo(), typeface()); newSubset->populate(subset); return newSubset; } @@ -887,8 +878,7 @@ void set_glyph_widths(SkTypeface* tf, tmpPaint.setHinting(SkPaint::kNo_Hinting); tmpPaint.setTypeface(sk_ref_sp(tf)); tmpPaint.setTextSize((SkScalar)tf->getUnitsPerEm()); - const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); - SkAutoGlyphCache autoGlyphCache(tmpPaint, &props, nullptr); + SkAutoGlyphCache autoGlyphCache(tmpPaint, nullptr, nullptr); if (!glyphIDs || glyphIDs->isEmpty()) { get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get()); } else { @@ -1027,8 +1017,7 @@ bool SkPDFType1Font::populate(int16_t glyphID) { tmpPaint.setHinting(SkPaint::kNo_Hinting); tmpPaint.setTypeface(sk_ref_sp(this->typeface())); tmpPaint.setTextSize((SkScalar)this->typeface()->getUnitsPerEm()); - const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); - SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); + SkAutoGlyphCache glyphCache(tmpPaint, nullptr, nullptr); auto widths = sk_make_sp<SkPDFArray>(); SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX; const uint16_t emSize = this->fontInfo()->fEmSize; @@ -1065,176 +1054,84 @@ bool SkPDFType1Font::populate(int16_t glyphID) { // class SkPDFType3Font /////////////////////////////////////////////////////////////////////////////// -namespace { -// returns [0, first, first+1, ... last-1, last] -struct SingleByteGlyphIdIterator { - SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last) - : fFirst(first), fLast(last) { - SkASSERT(fFirst > 0); - SkASSERT(fLast >= first); - } - struct Iter { - void operator++() { - fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1; - } - // This is an input_iterator - SkGlyphID operator*() const { return (SkGlyphID)fCurrent; } - bool operator!=(const Iter& rhs) const { - return fCurrent != rhs.fCurrent; - } - Iter(SkGlyphID f, int c) : fFirst(f), fCurrent(c) {} - private: - const SkGlyphID fFirst; - int fCurrent; // must be int to make fLast+1 to fit - }; - Iter begin() const { return Iter(fFirst, 0); } - Iter end() const { return Iter(fFirst, (int)fLast + 1); } -private: - const SkGlyphID fFirst; - const SkGlyphID fLast; -}; +SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, + SkTypeface* typeface, + uint16_t glyphID) + : SkPDFFont(info, typeface, nullptr) { + this->populate(glyphID); } -static void add_type3_font_info(SkPDFDict* font, - SkTypeface* typeface, - SkScalar emSize, - const SkPDFGlyphSet* subset, - SkGlyphID firstGlyphID, - SkGlyphID lastGlyphID) { - SkASSERT(lastGlyphID >= firstGlyphID); +SkPDFType3Font::~SkPDFType3Font() {} + +bool SkPDFType3Font::populate(uint16_t glyphID) { SkPaint paint; - paint.setHinting(SkPaint::kNo_Hinting); - paint.setTypeface(sk_ref_sp(typeface)); - paint.setTextSize(emSize); + paint.setTypeface(sk_ref_sp(this->typeface())); + paint.setTextSize(1000); const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); - SkAutoGlyphCache cache(paint, &props, nullptr); + SkAutoGlyphCache autoCache(paint, &props, nullptr); + SkGlyphCache* cache = autoCache.getCache(); + // If fLastGlyphID isn't set (because there is not fFontInfo), look it up. + if (lastGlyphID() == 0) { + setLastGlyphID(cache->getGlyphCount() - 1); + } - font->insertName("Subtype", "Type3"); - // Flip about the x-axis and scale by 1/emSize. + adjustGlyphRangeForSingleByteEncoding(glyphID); + + insertName("Subtype", "Type3"); + // Flip about the x-axis and scale by 1/1000. SkMatrix fontMatrix; - fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize)); - font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); + fontMatrix.setScale(SkScalarInvert(1000), -SkScalarInvert(1000)); + this->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); auto charProcs = sk_make_sp<SkPDFDict>(); auto encoding = sk_make_sp<SkPDFDict>("Encoding"); auto encDiffs = sk_make_sp<SkPDFArray>(); - // length(firstGlyphID .. lastGlyphID) == lastGlyphID - firstGlyphID + 1 - // plus 1 for glyph 0; - SkASSERT(firstGlyphID > 0); - SkASSERT(lastGlyphID >= firstGlyphID); - int glyphCount = lastGlyphID - firstGlyphID + 2; - // one other entry for the index of first glyph. - encDiffs->reserve(glyphCount + 1); - encDiffs->appendInt(0); // index of first glyph + encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); + encDiffs->appendInt(1); auto widthArray = sk_make_sp<SkPDFArray>(); - widthArray->reserve(glyphCount); SkIRect bbox = SkIRect::MakeEmpty(); - - sk_sp<SkPDFStream> emptyStream; - for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) { - bool skipGlyph = subset && gID != 0 && !subset->has(gID); + for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { SkString characterName; - SkScalar advance = 0.0f; - SkIRect glyphBBox; - if (skipGlyph) { - characterName.set("g0"); - } else { - characterName.printf("g%X", gID); - const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); - advance = SkFloatToScalar(glyph.fAdvanceX); - glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, - glyph.fWidth, glyph.fHeight); - bbox.join(glyphBBox); - const SkPath* path = cache->findPath(glyph); - if (path && !path->isEmpty()) { - SkDynamicMemoryWStream content; - setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox, - &content); - SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content); - SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(), - &content); - charProcs->insertObjRef( - characterName, sk_make_sp<SkPDFStream>( - std::unique_ptr<SkStreamAsset>(content.detachAsStream()))); - } else { - if (!emptyStream) { - emptyStream = sk_make_sp<SkPDFStream>( - std::unique_ptr<SkStreamAsset>( - new SkMemoryStream((size_t)0))); - } - charProcs->insertObjRef(characterName, emptyStream); - } - } + characterName.printf("gid%d", gID); encDiffs->appendName(characterName.c_str()); - widthArray->appendScalar(advance); - } - encoding->insertObject("Differences", std::move(encDiffs)); - font->insertInt("FirstChar", 0); - font->insertInt("LastChar", lastGlyphID - firstGlyphID + 1); - /* FontBBox: "A rectangle expressed in the glyph coordinate - system, specifying the font bounding box. This is the smallest - rectangle enclosing the shape that would result if all of the - glyphs of the font were placed with their origins coincident and - then filled." */ - auto fontBBox = sk_make_sp<SkPDFArray>(); - fontBBox->reserve(4); - fontBBox->appendInt(bbox.left()); - fontBBox->appendInt(bbox.bottom()); - fontBBox->appendInt(bbox.right()); - fontBBox->appendInt(bbox.top()); - font->insertObject("FontBBox", std::move(fontBBox)); - font->insertName("CIDToGIDMap", "Identity"); - sk_sp<const SkAdvancedTypefaceMetrics> metrics; - if (subset) { - SkTDArray<uint32_t> subsetList; - for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) { - if (gID == 0 || subset->has(gID)) { // Always include glyph 0. - subsetList.push(0); - } + const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); + widthArray->appendScalar(SkFloatToScalar(glyph.fAdvanceX)); + SkIRect glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, + glyph.fWidth, glyph.fHeight); + bbox.join(glyphBBox); + + SkDynamicMemoryWStream content; + setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox, + &content); + const SkPath* path = cache->findPath(glyph); + if (path) { + SkPDFUtils::EmitPath(*path, paint.getStyle(), &content); + SkPDFUtils::PaintPath(paint.getStyle(), path->getFillType(), + &content); } - subset->exportTo(&subsetList); - metrics = SkPDFFont::GetFontMetricsWithToUnicode(typeface, subsetList.begin(), - subsetList.count()); - } else { - metrics = SkPDFFont::GetFontMetricsWithToUnicode(typeface, nullptr, 0); + charProcs->insertObjRef( + characterName, sk_make_sp<SkPDFStream>( + std::unique_ptr<SkStreamAsset>(content.detachAsStream()))); } - font->insertObjRef("ToUnicode", - SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode, - subset, - false, - firstGlyphID, - lastGlyphID)); - font->insertObject("Widths", std::move(widthArray)); - font->insertObject("Encoding", std::move(encoding)); - font->insertObject("CharProcs", std::move(charProcs)); -} -SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, - SkTypeface* typeface, - uint16_t glyphID) - : SkPDFFont(info, typeface, nullptr) { - // If fLastGlyphID isn't set (because there is not fFontInfo), look it up. - this->setLastGlyphID(SkToU16(typeface->countGlyphs() - 1)); - this->adjustGlyphRangeForSingleByteEncoding(glyphID); -} + encoding->insertObject("Differences", std::move(encDiffs)); -sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(const SkPDFGlyphSet* usage) { - // All fonts are subset before serialization. - // TODO(halcanary): all fonts should follow this pattern. - auto font = sk_make_sp<SkPDFDict>("Font"); - const SkAdvancedTypefaceMetrics* info = this->fontInfo(); - uint16_t emSize = info && info->fEmSize > 0 ? info->fEmSize : 1000; - add_type3_font_info(font.get(), this->typeface(), (SkScalar)emSize, usage, - this->firstGlyphID(), this->lastGlyphID()); - return font; -} + this->insertObject("CharProcs", std::move(charProcs)); + this->insertObject("Encoding", std::move(encoding)); + this->insertObject("FontBBox", makeFontBBox(bbox, 1000)); + this->insertInt("FirstChar", 1); + this->insertInt("LastChar", lastGlyphID() - firstGlyphID() + 1); + this->insertObject("Widths", std::move(widthArray)); + this->insertName("CIDToGIDMap", "Identity"); -//////////////////////////////////////////////////////////////////////////////// + this->populateToUnicodeTable(nullptr); + return true; +} SkPDFFont::Match SkPDFFont::IsMatch(SkPDFFont* existingFont, uint32_t existingFontID, diff --git a/src/pdf/SkPDFFont.h b/src/pdf/SkPDFFont.h index acf9bf87ee..c55f650769 100644 --- a/src/pdf/SkPDFFont.h +++ b/src/pdf/SkPDFFont.h @@ -132,7 +132,7 @@ public: * @return nullptr if font does not support subsetting, a new instance * of SkPDFFont otherwise. */ - virtual sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage); + virtual SkPDFFont* getFontSubset(const SkPDFGlyphSet* usage); enum Match { kExact_Match, diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp index 6bf6afc611..afb9b72c54 100644 --- a/src/pdf/SkPDFTypes.cpp +++ b/src/pdf/SkPDFTypes.cpp @@ -573,9 +573,7 @@ void SkPDFStream::setData(std::unique_ptr<SkStreamAsset> stream) { SkASSERT(stream->hasLength()); SkDynamicMemoryWStream compressedData; SkDeflateWStream deflateWStream(&compressedData); - if (stream->getLength() > 0) { - SkStreamCopy(&deflateWStream, stream.get()); - } + SkStreamCopy(&deflateWStream, stream.get()); deflateWStream.finalize(); size_t compressedLength = compressedData.bytesWritten(); size_t originalLength = stream->getLength(); |