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

Unified Diff: src/pdf/SkPDFFont.cpp

Issue 2253283004: SkPDF: in-place font subsetting (Closed) Base URL: https://skia.googlesource.com/skia.git@SkPdfCacheMetrics
Patch Set: 2016-08-18 (Thursday) 16:02:16 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pdf/SkPDFFont.h ('k') | src/pdf/SkPDFGraphicState.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pdf/SkPDFFont.cpp
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index 290061a49171440960b59d4994614d61523e79a9..887f95001f406e88f6f4d4d2e3b942d51081f7bd 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -37,50 +37,27 @@ namespace {
// non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1)
static const int kPdfSymbolic = 4;
-class SkPDFType0Font final : public SkPDFFont {
-public:
- SkPDFType0Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType type);
+struct SkPDFType0Font final : public SkPDFFont {
+ SkPDFType0Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
virtual ~SkPDFType0Font();
- sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override;
-#ifdef SK_DEBUG
- void emitObject(SkWStream*,
- const SkPDFObjNumMap&,
- const SkPDFSubstituteMap&) const override;
-#endif
-
-private:
+ void getFontSubset(SkPDFCanon*) override;
#ifdef SK_DEBUG
+ void emitObject(SkWStream*, const SkPDFObjNumMap&) const override;
bool fPopulated;
#endif
- bool populate(const SkPDFGlyphSet* subset,
- const SkAdvancedTypefaceMetrics& metrics);
typedef SkPDFDict INHERITED;
};
-class SkPDFType1Font final : public SkPDFFont {
-public:
- SkPDFType1Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- uint16_t glyphID,
- SkPDFCanon* canon);
+struct SkPDFType1Font final : public SkPDFFont {
+ SkPDFType1Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&, SkPDFCanon*);
virtual ~SkPDFType1Font() {}
+ void getFontSubset(SkPDFCanon*) override {} // TODO(halcanary): implement
};
-class SkPDFType3Font final : public SkPDFFont {
-public:
- SkPDFType3Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType fontType,
- uint16_t glyphID);
+struct SkPDFType3Font final : public SkPDFFont {
+ SkPDFType3Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
virtual ~SkPDFType3Font() {}
- void emitObject(SkWStream*,
- const SkPDFObjNumMap&,
- const SkPDFSubstituteMap&) const override {
- SkDEBUGFAIL("should call getFontSubset!");
- }
- sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override;
+ void getFontSubset(SkPDFCanon*) override;
};
///////////////////////////////////////////////////////////////////////////////
@@ -143,58 +120,6 @@ static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) {
}
} // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// class SkPDFGlyphSet
-///////////////////////////////////////////////////////////////////////////////
-
-SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) {
-}
-
-void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) {
- for (int i = 0; i < numGlyphs; ++i) {
- fBitSet.setBit(glyphIDs[i], true);
- }
-}
-
-bool SkPDFGlyphSet::has(uint16_t glyphID) const {
- return fBitSet.isBitSet(glyphID);
-}
-
-void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const {
- fBitSet.exportTo(glyphIDs);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// class SkPDFGlyphSetMap
-///////////////////////////////////////////////////////////////////////////////
-
-SkPDFGlyphSetMap::SkPDFGlyphSetMap() {}
-
-SkPDFGlyphSetMap::~SkPDFGlyphSetMap() {
- fMap.reset();
-}
-
-void SkPDFGlyphSetMap::noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs,
- int numGlyphs) {
- SkPDFGlyphSet* subset = getGlyphSetForFont(font);
- if (subset) {
- subset->set(glyphIDs, numGlyphs);
- }
-}
-
-SkPDFGlyphSet* SkPDFGlyphSetMap::getGlyphSetForFont(SkPDFFont* font) {
- int index = fMap.count();
- for (int i = 0; i < index; ++i) {
- if (fMap[i].fFont == font) {
- return &fMap[i].fGlyphSet;
- }
- }
- FontGlyphSetPair& pair = fMap.push_back();
- pair.fFont = font;
- return &pair.fGlyphSet;
-}
-
///////////////////////////////////////////////////////////////////////////////
// class SkPDFFont
///////////////////////////////////////////////////////////////////////////////
@@ -322,47 +247,46 @@ SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon,
return nullptr;
}
+ SkGlyphID firstNonZeroGlyph;
+ SkGlyphID lastGlyph;
+ if (multibyte) {
+ firstNonZeroGlyph = 1;
+ lastGlyph = SkToU16(glyphCount - 1);
+ } else {
+ firstNonZeroGlyph = firstGlyph;
+ lastGlyph = SkToU16(SkTMin<int>(glyphCount - 1,
+ 254 + (int)firstGlyph));
+ }
+ SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, type};
sk_sp<SkPDFFont> font;
switch (type) {
case SkAdvancedTypefaceMetrics::kType1CID_Font:
case SkAdvancedTypefaceMetrics::kTrueType_Font:
SkASSERT(multibyte);
- font = sk_make_sp<SkPDFType0Font>(metrics,
- std::move(typeface),
- type);
+ font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics);
break;
case SkAdvancedTypefaceMetrics::kType1_Font:
SkASSERT(!multibyte);
- font = sk_make_sp<SkPDFType1Font>(metrics,
- std::move(typeface),
- glyphID,
- canon);
+ font = sk_make_sp<SkPDFType1Font>(std::move(info), metrics, canon);
break;
default:
SkASSERT(!multibyte);
// Type3 is our fallback font.
- font = sk_make_sp<SkPDFType3Font>(metrics,
- std::move(typeface),
- type,
- glyphID);
+ font = sk_make_sp<SkPDFType3Font>(std::move(info), metrics);
break;
}
canon->fFontMap.set(fontID, SkRef(font.get()));
return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>.
}
-sk_sp<SkPDFObject> SkPDFFont::getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) {
- return nullptr; // Default: no support.
-}
-
-SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType fontType)
+SkPDFFont::SkPDFFont(SkPDFFont::Info info)
: SkPDFDict("Font")
- , fTypeface(std::move(typeface))
- , fFirstGlyphID(1)
- , fFontType(fontType) {
+ , fTypeface(std::move(info.fTypeface))
+ , fGlyphUsage(info.fLastGlyphID + 1) // TODO(halcanary): Adjust mapping?
+ , fFirstGlyphID(info.fFirstGlyphID)
+ , fLastGlyphID(info.fLastGlyphID)
+ , fFontType(info.fFontType) {
SkASSERT(fTypeface);
- fLastGlyphID = SkToU16(fTypeface->countGlyphs() - 1);
}
static void add_common_font_descriptor_entries(SkPDFDict* descriptor,
@@ -388,50 +312,25 @@ static void add_common_font_descriptor_entries(SkPDFDict* descriptor,
}
}
-void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(SkGlyphID glyphID) {
- // Single byte glyph encoding supports a max of 255 glyphs.
- fFirstGlyphID = first_glyph_for_single_byte_encoding(glyphID);
- if (fLastGlyphID > fFirstGlyphID + 255 - 1) {
- fLastGlyphID = fFirstGlyphID + 255 - 1;
- }
-}
-
///////////////////////////////////////////////////////////////////////////////
// class SkPDFType0Font
///////////////////////////////////////////////////////////////////////////////
-SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType fontType)
- : SkPDFFont(std::move(typeface), fontType) {
+SkPDFType0Font::SkPDFType0Font(
+ SkPDFFont::Info info,
+ const SkAdvancedTypefaceMetrics& metrics)
+ : SkPDFFont(std::move(info)) {
SkDEBUGCODE(fPopulated = false);
- if (!can_subset(info)) {
- this->populate(nullptr, info);
- }
}
SkPDFType0Font::~SkPDFType0Font() {}
-sk_sp<SkPDFObject> SkPDFType0Font::getFontSubset(SkPDFCanon* canon,
- const SkPDFGlyphSet* subset) {
- const SkAdvancedTypefaceMetrics* metrics =
- SkPDFFont::GetMetrics(this->typeface(), canon);
- SkASSERT(metrics);
- if (!metrics || !can_subset(*metrics)) {
- return nullptr;
- }
- auto newSubset = sk_make_sp<SkPDFType0Font>(
- *metrics, this->refTypeface(), this->getType());
- newSubset->populate(subset, *metrics);
- return newSubset;
-}
#ifdef SK_DEBUG
void SkPDFType0Font::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
SkASSERT(fPopulated);
- return INHERITED::emitObject(stream, objNumMap, substitutes);
+ return INHERITED::emitObject(stream, objNumMap);
}
#endif
@@ -488,8 +387,12 @@ static sk_sp<SkPDFObject> get_subset_font_stream(
}
#endif // SK_SFNTLY_SUBSETTER
-bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
- const SkAdvancedTypefaceMetrics& metrics) {
+void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) {
+ const SkAdvancedTypefaceMetrics* metricsPtr =
+ SkPDFFont::GetMetrics(this->typeface(), canon);
+ SkASSERT(metricsPtr);
+ if (!metricsPtr) { return; }
+ const SkAdvancedTypefaceMetrics& metrics = *metricsPtr;
SkASSERT(can_embed(metrics));
SkAdvancedTypefaceMetrics::FontType type = this->getType();
SkTypeface* face = this->typeface();
@@ -504,24 +407,22 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex));
SkASSERT(fontAsset);
if (!fontAsset) {
- return false;
+ return;
}
size_t fontSize = fontAsset->getLength();
SkASSERT(fontSize > 0);
if (fontSize == 0) {
- return false;
+ return;
}
#ifdef SK_SFNTLY_SUBSETTER
- if (can_subset(metrics) && subset) {
+ if (can_subset(metrics)) {
// Generate glyph id array. in format needed by sfntly
SkTDArray<uint32_t> glyphIDs;
- if (subset) {
- if (!subset->has(0)) {
- glyphIDs.push(0); // Always include glyph 0.
- }
- subset->exportTo(&glyphIDs);
+ if (!this->glyphUsage().has(0)) {
+ glyphIDs.push(0); // Always include glyph 0.
}
+ this->glyphUsage().exportTo(&glyphIDs);
sk_sp<SkPDFObject> subsetStream = get_subset_font_stream(
std::move(fontAsset), glyphIDs, name.c_str());
if (subsetStream) {
@@ -542,7 +443,7 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
SkASSERT(fontData);
SkASSERT(fontData->getLength() > 0);
if (!fontData || 0 == fontData->getLength()) {
- return false;
+ return;
}
auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData));
fontStream->dict()->insertName("Subtype", "CIDFontType0c");
@@ -574,11 +475,10 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
uint16_t emSize = metrics.fEmSize;
int16_t defaultWidth = 0;
- const SkBitSet* bitSet = subset ? &subset->bitSet() : nullptr;
{
SkAutoGlyphCache glyphCache = vector_cache(face);
sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
- glyphCache.get(), bitSet, emSize, &defaultWidth);
+ glyphCache.get(), &this->glyphUsage(), emSize, &defaultWidth);
if (widths && widths->size() > 0) {
newCIDFont->insertObject("W", std::move(widths));
}
@@ -598,13 +498,13 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
if (metrics.fGlyphToUnicode.count() > 0) {
this->insertObjRef("ToUnicode",
SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode,
- subset,
+ &this->glyphUsage(),
multiByteGlyphs(),
firstGlyphID(),
lastGlyphID()));
}
SkDEBUGCODE(fPopulated = true);
- return true;
+ return;
}
///////////////////////////////////////////////////////////////////////////////
@@ -679,24 +579,22 @@ static void populate_type_1_font(SkPDFDict* font,
font->insertObject("Encoding", std::move(encoding));
}
-SkPDFType1Font::SkPDFType1Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- uint16_t glyphID,
+SkPDFType1Font::SkPDFType1Font(SkPDFFont::Info info,
+ const SkAdvancedTypefaceMetrics& metrics,
SkPDFCanon* canon)
- : SkPDFFont(std::move(typeface), SkAdvancedTypefaceMetrics::kType1_Font)
+ : SkPDFFont(std::move(info))
{
SkFontID fontID = this->typeface()->uniqueID();
sk_sp<SkPDFDict> fontDescriptor;
if (SkPDFDict** ptr = canon->fFontDescriptors.find(fontID)) {
fontDescriptor = sk_ref_sp(*ptr);
} else {
- fontDescriptor = make_type1_font_descriptor(this->typeface(), info);
+ fontDescriptor = make_type1_font_descriptor(this->typeface(), metrics);
canon->fFontDescriptors.set(fontID, SkRef(fontDescriptor.get()));
}
this->insertObjRef("FontDescriptor", std::move(fontDescriptor));
- this->adjustGlyphRangeForSingleByteEncoding(glyphID);
// TODO(halcanary): subset this (advances and names).
- populate_type_1_font(this, info, this->typeface(),
+ populate_type_1_font(this, metrics, this->typeface(),
this->firstGlyphID(), this->lastGlyphID());
}
@@ -738,7 +636,7 @@ static void add_type3_font_info(SkPDFCanon* canon,
SkPDFDict* font,
SkTypeface* typeface,
SkScalar emSize,
- const SkPDFGlyphSet* subset,
+ const SkBitSet& subset,
SkGlyphID firstGlyphID,
SkGlyphID lastGlyphID) {
SkASSERT(lastGlyphID >= firstGlyphID);
@@ -770,7 +668,7 @@ static void add_type3_font_info(SkPDFCanon* canon,
sk_sp<SkPDFStream> emptyStream;
for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
- bool skipGlyph = subset && gID != 0 && !subset->has(gID);
+ bool skipGlyph = gID != 0 && !subset.has(gID);
SkString characterName;
SkScalar advance = 0.0f;
SkIRect glyphBBox;
@@ -827,7 +725,7 @@ static void add_type3_font_info(SkPDFCanon* canon,
if (metrics /* && metrics->fGlyphToUnicode.count() > 0 */) {
font->insertObjRef("ToUnicode",
SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode,
- subset,
+ &subset,
false,
firstGlyphID,
lastGlyphID));
@@ -837,29 +735,20 @@ static void add_type3_font_info(SkPDFCanon* canon,
font->insertObject("CharProcs", std::move(charProcs));
}
-SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType fontType,
- uint16_t glyphID)
- : SkPDFFont(std::move(typeface), fontType) {
- this->adjustGlyphRangeForSingleByteEncoding(glyphID);
-}
+SkPDFType3Font::SkPDFType3Font(SkPDFFont::Info info,
+ const SkAdvancedTypefaceMetrics& metrics)
+ : SkPDFFont(std::move(info)) {}
-sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(SkPDFCanon* canon,
- const SkPDFGlyphSet* usage) {
- // All fonts are subset before serialization.
- // TODO(halcanary): all fonts should follow this pattern.
+void SkPDFType3Font::getFontSubset(SkPDFCanon* canon) {
const SkAdvancedTypefaceMetrics* info =
SkPDFFont::GetMetrics(this->typeface(), canon);
SkASSERT(info);
uint16_t emSize = info->fEmSize > 0 ? info->fEmSize : 1000;
- auto font = sk_make_sp<SkPDFDict>("Font");
- add_type3_font_info(canon, font.get(), this->typeface(), (SkScalar)emSize, usage,
+ add_type3_font_info(canon, this, this->typeface(), (SkScalar)emSize,
+ this->glyphUsage(),
this->firstGlyphID(), this->lastGlyphID());
- return font;
}
-
////////////////////////////////////////////////////////////////////////////////
bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) {
« no previous file with comments | « src/pdf/SkPDFFont.h ('k') | src/pdf/SkPDFGraphicState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698