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) { |