Index: src/pdf/SkPDFFont.cpp |
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp |
index 937360578c3021c0814f095a4bbf22c36dcb4f55..6d8f09c2471a10d3dd4bcdcc8ed5cba6079fb98a 100644 |
--- a/src/pdf/SkPDFFont.cpp |
+++ b/src/pdf/SkPDFFont.cpp |
@@ -75,20 +75,6 @@ private: |
typedef SkPDFDict INHERITED; |
}; |
-class SkPDFCIDFont final : public SkPDFFont { |
-public: |
- SkPDFCIDFont(sk_sp<const SkAdvancedTypefaceMetrics> info, |
- sk_sp<SkTypeface> typeface, |
- SkAdvancedTypefaceMetrics::FontType fontType, |
- const SkPDFGlyphSet* subset); |
- virtual ~SkPDFCIDFont(); |
- |
-private: |
- bool populate(const SkPDFGlyphSet* subset); |
- bool addFontDescriptor(int16_t defaultWidth, |
- const SkTDArray<uint32_t>* subset); |
-}; |
- |
class SkPDFType1Font final : public SkPDFFont { |
public: |
SkPDFType1Font(sk_sp<const SkAdvancedTypefaceMetrics> info, |
@@ -179,16 +165,7 @@ static void FinishRange( |
zeroWildcardsInRange(range); |
} |
- |
-/** Retrieve advance data for glyphs. Used by the PDF backend. |
- @param num_glyphs Total number of glyphs in the given font. |
- @param glyphIDs For per-glyph info, specify subset of the |
- font by giving glyph ids. Each integer |
- represents a glyph id. Passing nullptr |
- means all glyphs in the font. |
- @param glyphIDsCount Number of elements in subsetGlyphIds. |
- Ignored if glyphIDs is nullptr. |
-*/ |
+/** Retrieve advance data for glyphs. Used by the PDF backend. */ |
// TODO(halcanary): this function is complex enough to need its logic |
// tested with unit tests. On the other hand, I want to do another |
// round of re-factoring before figuring out how to mock this. |
@@ -196,11 +173,17 @@ static void FinishRange( |
// composeAdvanceData() so that we don't need to produce a linked list |
// of intermediate values. Or we could make the intermediate value |
// something other than a linked list. |
-static void get_glyph_widths(SkSinglyLinkedList<AdvanceMetric>* glyphWidths, |
- int num_glyphs, |
- const uint32_t* subsetGlyphIDs, |
- uint32_t subsetGlyphIDsLength, |
- SkGlyphCache* glyphCache) { |
+static void set_glyph_widths(SkTypeface* typeface, |
+ const SkPDFGlyphSet* subset, |
+ SkSinglyLinkedList<AdvanceMetric>* glyphWidths) { |
+ SkPaint tmpPaint; |
+ tmpPaint.setHinting(SkPaint::kNo_Hinting); |
+ tmpPaint.setTypeface(sk_ref_sp(typeface)); |
+ tmpPaint.setTextSize((SkScalar)typeface->getUnitsPerEm()); |
+ const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
+ SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); |
+ SkASSERT(glyphCache.get()); |
+ |
// Assuming that on average, the ASCII representation of an advance plus |
// a space is 8 characters and the ASCII representation of a glyph id is 3 |
// characters, then the following cut offs for using different range types |
@@ -216,34 +199,28 @@ static void get_glyph_widths(SkSinglyLinkedList<AdvanceMetric>* glyphWidths, |
// d. Removing a leading 0/don't cares is a win because it is omitted |
// e. Removing 2 repeating advances is a win |
+ int num_glyphs = typeface->countGlyphs(); |
+ |
AdvanceMetric* prevRange = nullptr; |
int16_t lastAdvance = kInvalidAdvance; |
int repeatedAdvances = 0; |
int wildCardsInRun = 0; |
int trailingWildCards = 0; |
- uint32_t subsetIndex = 0; |
// Limit the loop count to glyph id ranges provided. |
- int firstIndex = 0; |
int lastIndex = num_glyphs; |
- if (subsetGlyphIDs) { |
- firstIndex = static_cast<int>(subsetGlyphIDs[0]); |
- lastIndex = |
- static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1; |
+ if (subset) { |
+ while (!subset->has(lastIndex - 1) && lastIndex > 0) { |
+ --lastIndex; |
+ } |
} |
- AdvanceMetric curRange(firstIndex); |
+ AdvanceMetric curRange(0); |
- for (int gId = firstIndex; gId <= lastIndex; gId++) { |
+ for (int gId = 0; gId <= lastIndex; gId++) { |
int16_t advance = kInvalidAdvance; |
if (gId < lastIndex) { |
- // Get glyph id only when subset is nullptr, or the id is in subset. |
- SkASSERT(!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && |
- static_cast<uint32_t>(gId) <= subsetGlyphIDs[subsetIndex])); |
- if (!subsetGlyphIDs || |
- (subsetIndex < subsetGlyphIDsLength && |
- static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) { |
+ if (!subset || 0 == gId || subset->has(gId)) { |
advance = (int16_t)glyphCache->getGlyphIDAdvance(gId).fAdvanceX; |
- ++subsetIndex; |
} else { |
advance = kDontCareAdvance; |
} |
@@ -321,7 +298,6 @@ static void get_glyph_widths(SkSinglyLinkedList<AdvanceMetric>* glyphWidths, |
//////////////////////////////////////////////////////////////////////////////// |
- |
// scale from em-units to base-1000, returning as a SkScalar |
SkScalar from_font_units(SkScalar scaled, uint16_t emSize) { |
if (emSize == 1000) { |
@@ -643,33 +619,27 @@ void SkPDFFont::setFontDescriptor(sk_sp<SkPDFDict> descriptor) { |
fDescriptor = std::move(descriptor); |
} |
-bool SkPDFFont::addCommonFontDescriptorEntries(int16_t defaultWidth) { |
- if (fDescriptor.get() == nullptr) { |
- return false; |
- } |
- |
- const uint16_t emSize = fFontInfo->fEmSize; |
- |
- fDescriptor->insertName("FontName", fFontInfo->fFontName); |
- fDescriptor->insertInt("Flags", (size_t)(fFontInfo->fStyle | kPdfSymbolic)); |
- fDescriptor->insertScalar("Ascent", |
- scaleFromFontUnits(fFontInfo->fAscent, emSize)); |
- fDescriptor->insertScalar("Descent", |
- scaleFromFontUnits(fFontInfo->fDescent, emSize)); |
- fDescriptor->insertScalar("StemV", |
- scaleFromFontUnits(fFontInfo->fStemV, emSize)); |
- |
- fDescriptor->insertScalar("CapHeight", |
- scaleFromFontUnits(fFontInfo->fCapHeight, emSize)); |
- fDescriptor->insertInt("ItalicAngle", fFontInfo->fItalicAngle); |
- fDescriptor->insertObject( |
- "FontBBox", makeFontBBox(fFontInfo->fBBox, fFontInfo->fEmSize)); |
- |
+static void add_common_font_descriptor_entries(SkPDFDict* descriptor, |
+ const SkAdvancedTypefaceMetrics& metrics, |
+ int16_t defaultWidth) { |
+ const uint16_t emSize = metrics.fEmSize; |
+ descriptor->insertName("FontName", metrics.fFontName); |
+ descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic)); |
+ descriptor->insertScalar("Ascent", |
+ scaleFromFontUnits(metrics.fAscent, emSize)); |
+ descriptor->insertScalar("Descent", |
+ scaleFromFontUnits(metrics.fDescent, emSize)); |
+ descriptor->insertScalar("StemV", |
+ scaleFromFontUnits(metrics.fStemV, emSize)); |
+ descriptor->insertScalar("CapHeight", |
+ scaleFromFontUnits(metrics.fCapHeight, emSize)); |
+ descriptor->insertInt("ItalicAngle", metrics.fItalicAngle); |
+ descriptor->insertObject( |
+ "FontBBox", makeFontBBox(metrics.fBBox, metrics.fEmSize)); |
if (defaultWidth > 0) { |
- fDescriptor->insertScalar("MissingWidth", |
+ descriptor->insertScalar("MissingWidth", |
scaleFromFontUnits(defaultWidth, emSize)); |
} |
- return true; |
} |
void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(uint16_t glyphID) { |
@@ -726,41 +696,6 @@ void SkPDFType0Font::emitObject(SkWStream* stream, |
} |
#endif |
-bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) { |
- insertName("Subtype", "Type0"); |
- insertName("BaseFont", this->getFontInfo()->fFontName); |
- insertName("Encoding", "Identity-H"); |
- |
- sk_sp<SkPDFCIDFont> newCIDFont( |
- sk_make_sp<SkPDFCIDFont>(this->refFontInfo(), |
- this->refTypeface(), |
- this->getType(), |
- subset)); |
- auto descendantFonts = sk_make_sp<SkPDFArray>(); |
- descendantFonts->appendObjRef(std::move(newCIDFont)); |
- this->insertObject("DescendantFonts", std::move(descendantFonts)); |
- |
- this->populateToUnicodeTable(subset); |
- |
- SkDEBUGCODE(fPopulated = true); |
- return true; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// class SkPDFCIDFont |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-SkPDFCIDFont::SkPDFCIDFont(sk_sp<const SkAdvancedTypefaceMetrics> info, |
- sk_sp<SkTypeface> typeface, |
- SkAdvancedTypefaceMetrics::FontType fontType, |
- const SkPDFGlyphSet* subset) |
- : SkPDFFont(std::move(info), std::move(typeface), nullptr, |
- fontType , /* multiByteGlyphs = */ true) { |
- this->populate(subset); |
-} |
- |
-SkPDFCIDFont::~SkPDFCIDFont() {} |
- |
#ifdef SK_SFNTLY_SUBSETTER |
// if possible, make no copy. |
static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) { |
@@ -814,21 +749,21 @@ static sk_sp<SkPDFObject> get_subset_font_stream( |
} |
#endif // SK_SFNTLY_SUBSETTER |
-bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, |
- const SkTDArray<uint32_t>* subset) { |
- auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); |
- setFontDescriptor(descriptor); |
- if (!addCommonFontDescriptorEntries(defaultWidth)) { |
- this->insertObjRef("FontDescriptor", std::move(descriptor)); |
- return false; |
- } |
+bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) { |
SkASSERT(this->canEmbed()); |
+ SkASSERT(this->getFontInfo()); |
+ const SkAdvancedTypefaceMetrics& metrics = *(this->getFontInfo()); |
+ SkAdvancedTypefaceMetrics::FontType type = this->getType(); |
+ SkTypeface* face = this->typeface(); |
+ SkASSERT(face); |
+ const char* name = metrics.fFontName.c_str(); |
- switch (getType()) { |
+ auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); |
+ add_common_font_descriptor_entries(descriptor.get(), metrics, 0); |
+ switch (type) { |
case SkAdvancedTypefaceMetrics::kTrueType_Font: { |
int ttcIndex; |
- std::unique_ptr<SkStreamAsset> fontAsset( |
- this->typeface()->openStream(&ttcIndex)); |
+ std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex)); |
SkASSERT(fontAsset); |
if (!fontAsset) { |
return false; |
@@ -841,15 +776,22 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, |
#ifdef SK_SFNTLY_SUBSETTER |
if (this->canSubset() && subset) { |
- const char* name = this->getFontInfo()->fFontName.c_str(); |
+ // 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); |
+ } |
sk_sp<SkPDFObject> subsetStream = get_subset_font_stream( |
- std::move(fontAsset), *subset, name); |
+ std::move(fontAsset), glyphIDs, name); |
if (subsetStream) { |
descriptor->insertObjRef("FontFile2", std::move(subsetStream)); |
break; |
} |
// If subsetting fails, fall back to original font data. |
- fontAsset.reset(this->typeface()->openStream(&ttcIndex)); |
+ fontAsset.reset(face->openStream(&ttcIndex)); |
} |
#endif // SK_SFNTLY_SUBSETTER |
auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset)); |
@@ -857,91 +799,31 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, |
descriptor->insertObjRef("FontFile2", std::move(fontStream)); |
break; |
} |
- case SkAdvancedTypefaceMetrics::kCFF_Font: |
case SkAdvancedTypefaceMetrics::kType1CID_Font: { |
- std::unique_ptr<SkStreamAsset> fontData( |
- this->typeface()->openStream(nullptr)); |
+ std::unique_ptr<SkStreamAsset> fontData(face->openStream(nullptr)); |
SkASSERT(fontData); |
SkASSERT(fontData->getLength() > 0); |
if (!fontData || 0 == fontData->getLength()) { |
return false; |
} |
auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData)); |
- if (getType() == SkAdvancedTypefaceMetrics::kCFF_Font) { |
- fontStream->dict()->insertName("Subtype", "Type1C"); |
- } else { |
- fontStream->dict()->insertName("Subtype", "CIDFontType0c"); |
- } |
+ fontStream->dict()->insertName("Subtype", "CIDFontType0c"); |
descriptor->insertObjRef("FontFile3", std::move(fontStream)); |
break; |
} |
default: |
SkASSERT(false); |
} |
- this->insertObjRef("FontDescriptor", std::move(descriptor)); |
- return true; |
-} |
-void set_glyph_widths(SkTypeface* tf, |
- const SkTDArray<uint32_t>* glyphIDs, |
- SkSinglyLinkedList<AdvanceMetric>* dst) { |
- SkPaint tmpPaint; |
- 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); |
- if (!glyphIDs || glyphIDs->isEmpty()) { |
- get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get()); |
- } else { |
- get_glyph_widths(dst, tf->countGlyphs(), glyphIDs->begin(), |
- glyphIDs->count(), autoGlyphCache.get()); |
- } |
-} |
+ auto newCIDFont = sk_make_sp<SkPDFDict>("Font"); |
+ newCIDFont->insertObjRef("FontDescriptor", std::move(descriptor)); |
+ newCIDFont->insertName("BaseFont", name); |
-sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithGlyphNames( |
- SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) { |
- return sk_sp<const SkAdvancedTypefaceMetrics>( |
- typeface->getAdvancedTypefaceMetrics( |
- SkTypeface::kGlyphNames_PerGlyphInfo, glyphs, glyphsCount)); |
-} |
- |
-sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithToUnicode( |
- SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) { |
- return sk_sp<const SkAdvancedTypefaceMetrics>( |
- typeface->getAdvancedTypefaceMetrics( |
- SkTypeface::kToUnicode_PerGlyphInfo, glyphs, glyphsCount)); |
-} |
- |
-bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { |
- // Generate new font metrics with advance info for true type fonts. |
- // Generate glyph id array. |
- SkTDArray<uint32_t> glyphIDs; |
- if (subset) { |
- if (!subset->has(0)) { |
- glyphIDs.push(0); // Always include glyph 0. |
- } |
- subset->exportTo(&glyphIDs); |
- } |
- if (this->getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) { |
- uint32_t* glyphs = (glyphIDs.count() == 0) ? nullptr : glyphIDs.begin(); |
- uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0; |
- sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics = |
- SkPDFFont::GetFontMetricsWithGlyphNames(this->typeface(), glyphs, glyphsCount); |
- this->setFontInfo(std::move(fontMetrics)); |
- this->addFontDescriptor(0, &glyphIDs); |
- } else { |
- // Other CID fonts |
- addFontDescriptor(0, nullptr); |
- } |
- |
- insertName("BaseFont", this->getFontInfo()->fFontName); |
- |
- if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) { |
- insertName("Subtype", "CIDFontType0"); |
- } else if (getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) { |
- insertName("Subtype", "CIDFontType2"); |
- insertName("CIDToGIDMap", "Identity"); |
+ if (type == SkAdvancedTypefaceMetrics::kType1CID_Font) { |
+ newCIDFont->insertName("Subtype", "CIDFontType0"); |
+ } else if (type == SkAdvancedTypefaceMetrics::kTrueType_Font) { |
+ newCIDFont->insertName("Subtype", "CIDFontType2"); |
+ newCIDFont->insertName("CIDToGIDMap", "Identity"); |
} else { |
SkASSERT(false); |
} |
@@ -950,22 +832,42 @@ bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { |
sysInfo->insertString("Registry", "Adobe"); |
sysInfo->insertString("Ordering", "Identity"); |
sysInfo->insertInt("Supplement", 0); |
- this->insertObject("CIDSystemInfo", std::move(sysInfo)); |
+ newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); |
SkSinglyLinkedList<AdvanceMetric> tmpMetrics; |
- set_glyph_widths(this->typeface(), &glyphIDs, &tmpMetrics); |
+ set_glyph_widths(face, subset, &tmpMetrics); |
int16_t defaultWidth = 0; |
uint16_t emSize = (uint16_t)this->getFontInfo()->fEmSize; |
sk_sp<SkPDFArray> widths = composeAdvanceData(tmpMetrics, emSize, &defaultWidth); |
if (widths->size()) { |
- this->insertObject("W", std::move(widths)); |
+ newCIDFont->insertObject("W", std::move(widths)); |
} |
- this->insertScalar( |
+ newCIDFont->insertScalar( |
"DW", scaleFromFontUnits(defaultWidth, emSize)); |
+ |
+ |
+ //////////////////////////////////////////////////////////////////////////// |
+ |
+ this->insertName("Subtype", "Type0"); |
+ this->insertName("BaseFont", metrics.fFontName); |
+ this->insertName("Encoding", "Identity-H"); |
+ auto descendantFonts = sk_make_sp<SkPDFArray>(); |
+ descendantFonts->appendObjRef(std::move(newCIDFont)); |
+ this->insertObject("DescendantFonts", std::move(descendantFonts)); |
+ this->populateToUnicodeTable(subset); |
+ SkDEBUGCODE(fPopulated = true); |
return true; |
} |
+sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithToUnicode( |
+ SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) { |
+ return sk_sp<const SkAdvancedTypefaceMetrics>( |
+ typeface->getAdvancedTypefaceMetrics( |
+ SkTypeface::kToUnicode_PerGlyphInfo, glyphs, glyphsCount)); |
+} |
+ |
+ |
/////////////////////////////////////////////////////////////////////////////// |
// class SkPDFType1Font |
/////////////////////////////////////////////////////////////////////////////// |
@@ -1010,9 +912,12 @@ bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) { |
fontStream->dict()->insertInt("Length3", trailer); |
descriptor->insertObjRef("FontFile", std::move(fontStream)); |
+ SkASSERT(this->getFontInfo()); |
+ add_common_font_descriptor_entries(descriptor.get(), |
+ *this->getFontInfo(), |
+ defaultWidth); |
this->insertObjRef("FontDescriptor", std::move(descriptor)); |
- |
- return addCommonFontDescriptorEntries(defaultWidth); |
+ return true; |
} |
bool SkPDFType1Font::populate(int16_t glyphID) { |