Index: src/pdf/SkPDFFont.cpp |
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp |
index 7afdff6aa842c8e6dbba513a66c4ba5934687333..4d114f0e1a91b72c6e5ee28269f8c9a5dd341059 100644 |
--- a/src/pdf/SkPDFFont.cpp |
+++ b/src/pdf/SkPDFFont.cpp |
@@ -39,11 +39,11 @@ |
class SkPDFType0Font final : public SkPDFFont { |
public: |
- SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, |
+ SkPDFType0Font(sk_sp<const SkAdvancedTypefaceMetrics> info, |
sk_sp<SkTypeface> typeface, |
SkAdvancedTypefaceMetrics::FontType type); |
virtual ~SkPDFType0Font(); |
- sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override; |
+ sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; |
#ifdef SK_DEBUG |
void emitObject(SkWStream*, |
const SkPDFObjNumMap&, |
@@ -54,23 +54,26 @@ |
#ifdef SK_DEBUG |
bool fPopulated; |
#endif |
- bool populate(const SkPDFGlyphSet* subset, |
- const SkAdvancedTypefaceMetrics& metrics); |
+ bool populate(const SkPDFGlyphSet* subset); |
typedef SkPDFDict INHERITED; |
}; |
class SkPDFType1Font final : public SkPDFFont { |
public: |
- SkPDFType1Font(const SkAdvancedTypefaceMetrics* info, |
+ SkPDFType1Font(sk_sp<const SkAdvancedTypefaceMetrics> info, |
sk_sp<SkTypeface> typeface, |
uint16_t glyphID, |
- SkPDFCanon* canon); |
- virtual ~SkPDFType1Font() {} |
+ sk_sp<SkPDFDict> relatedFontDescriptor); |
+ virtual ~SkPDFType1Font(); |
+ |
+private: |
+ bool populate(int16_t glyphID); |
+ bool addFontDescriptor(int16_t defaultWidth); |
}; |
class SkPDFType3Font final : public SkPDFFont { |
public: |
- SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, |
+ SkPDFType3Font(sk_sp<const SkAdvancedTypefaceMetrics> info, |
sk_sp<SkTypeface> typeface, |
SkAdvancedTypefaceMetrics::FontType fontType, |
uint16_t glyphID); |
@@ -80,7 +83,7 @@ |
const SkPDFSubstituteMap&) const override { |
SkDEBUGFAIL("should call getFontSubset!"); |
} |
- sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override; |
+ sk_sp<SkPDFObject> getFontSubset(const SkPDFGlyphSet* usage) override; |
}; |
/////////////////////////////////////////////////////////////////////////////// |
@@ -213,14 +216,26 @@ |
SkPDFFont::~SkPDFFont() {} |
-static bool can_embed(const SkAdvancedTypefaceMetrics* metrics) { |
- return !metrics || |
- !SkToBool(metrics->fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag); |
-} |
- |
-static bool can_subset(const SkAdvancedTypefaceMetrics* metrics) { |
- return !metrics || |
- !SkToBool(metrics->fFlags & SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag); |
+bool SkPDFFont::canEmbed() const { |
+ if (!fFontInfo.get()) { |
+ SkASSERT(fFontType == SkAdvancedTypefaceMetrics::kOther_Font); |
+ return true; |
+ } |
+ return (fFontInfo->fFlags & |
+ SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag) == 0; |
+} |
+ |
+bool SkPDFFont::canSubset() const { |
+ if (!fFontInfo.get()) { |
+ SkASSERT(fFontType == SkAdvancedTypefaceMetrics::kOther_Font); |
+ return true; |
+ } |
+ return (fFontInfo->fFlags & |
+ SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag) == 0; |
+} |
+ |
+bool SkPDFFont::hasGlyph(uint16_t id) { |
+ return (id >= fFirstGlyphID && id <= fLastGlyphID) || id == 0; |
} |
int SkPDFFont::glyphsToPDFFontEncoding(SkGlyphID* glyphIDs, int numGlyphs) const { |
@@ -256,105 +271,125 @@ |
return numGlyphs; |
} |
- |
-const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface, |
- SkPDFCanon* canon) { |
- SkFontID id = SkTypeface::UniqueID(typeface); |
- if (SkAdvancedTypefaceMetrics** ptr = canon->fTypefaceMetrics.find(id)) { |
- return *ptr; |
- } |
- sk_sp<SkTypeface> defaultFace; |
- if (!typeface) { |
- defaultFace = SkTypeface::MakeDefault(); |
- typeface = defaultFace.get(); |
- } |
- sk_sp<SkAdvancedTypefaceMetrics> metrics( |
- typeface->getAdvancedTypefaceMetrics( |
- SkTypeface::kGlyphNames_PerGlyphInfo | SkTypeface::kToUnicode_PerGlyphInfo, |
- nullptr, 0)); |
- return *canon->fTypefaceMetrics.set(id, metrics.release()); |
-} |
- |
-SkAdvancedTypefaceMetrics::FontType font_type(const SkAdvancedTypefaceMetrics* metrics) { |
- if (!metrics || SkToBool(metrics->fFlags & |
- SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) { |
- // force Type3 fallback. |
- return SkAdvancedTypefaceMetrics::kOther_Font; |
- } |
- return metrics->fType; |
-} |
- |
-static SkGlyphID first_glyph_for_single_byte_encoding(SkGlyphID gid) { |
- return gid != 0 ? gid - (gid - 1) % 255 : 1; |
-} |
- |
+// static |
SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, |
SkTypeface* face, |
- SkGlyphID glyphID) { |
+ uint16_t glyphID) { |
SkASSERT(canon); |
- const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, canon); |
- SkAdvancedTypefaceMetrics::FontType type = font_type(fontMetrics); |
- bool multibyte = SkPDFFont::IsMultiByte(type); |
- SkGlyphID firstGlyph = multibyte ? 0 : first_glyph_for_single_byte_encoding(glyphID); |
- uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | firstGlyph; |
- |
- if (SkPDFFont** found = canon->fFontMap.find(fontID)) { |
- SkASSERT(multibyte == (*found)->multiByteGlyphs()); |
- return SkRef(*found); |
- } |
- |
+ const uint32_t fontID = SkTypeface::UniqueID(face); |
+ SkPDFFont* relatedFont; |
+ if (SkPDFFont* pdfFont = canon->findFont(fontID, glyphID, &relatedFont)) { |
+ return SkRef(pdfFont); |
+ } |
sk_sp<SkTypeface> typeface(face ? sk_ref_sp(face) : SkTypeface::MakeDefault()); |
SkASSERT(typeface); |
int glyphCount = typeface->countGlyphs(); |
- // Validate typeface + glyph; |
if (glyphCount < 1 || // typeface lacks even a NOTDEF glyph. |
glyphCount > 1 + SK_MaxU16 || // invalid glyphCount |
glyphID >= glyphCount) { // invalid glyph |
return nullptr; |
} |
+ sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics; |
+ sk_sp<SkPDFDict> relatedFontDescriptor; |
+ if (relatedFont) { |
+ fontMetrics = relatedFont->refFontInfo(); |
+ relatedFontDescriptor = relatedFont->refFontDescriptor(); |
+ |
+ // This only is to catch callers who pass invalid glyph ids. |
+ // If glyph id is invalid, then we will create duplicate entries |
+ // for TrueType fonts. |
+ SkDEBUGCODE(SkAdvancedTypefaceMetrics::FontType fontType = relatedFont->getType()); |
+ SkASSERT(fontType != SkAdvancedTypefaceMetrics::kType1CID_Font); |
+ SkASSERT(fontType != SkAdvancedTypefaceMetrics::kTrueType_Font); |
+ } else { |
+ SkTypeface::PerGlyphInfo info = SkTypeface::kGlyphNames_PerGlyphInfo | |
+ SkTypeface::kToUnicode_PerGlyphInfo; |
+ fontMetrics.reset( |
+ typeface->getAdvancedTypefaceMetrics(info, nullptr, 0)); |
+ } |
+ |
+ SkAdvancedTypefaceMetrics::FontType type = |
+ fontMetrics ? fontMetrics->fType : SkAdvancedTypefaceMetrics::kOther_Font; |
+ if (fontMetrics && |
+ SkToBool(fontMetrics->fFlags & |
+ SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) { |
+ // force Type3 fallback. |
+ type = SkAdvancedTypefaceMetrics::kOther_Font; |
+ } |
sk_sp<SkPDFFont> font; |
switch (type) { |
case SkAdvancedTypefaceMetrics::kType1CID_Font: |
case SkAdvancedTypefaceMetrics::kTrueType_Font: |
- SkASSERT(multibyte); |
+ SkASSERT(relatedFontDescriptor == nullptr); |
SkASSERT(fontMetrics != nullptr); |
- font = sk_make_sp<SkPDFType0Font>(fontMetrics, |
+ font = sk_make_sp<SkPDFType0Font>(std::move(fontMetrics), |
std::move(typeface), |
type); |
break; |
case SkAdvancedTypefaceMetrics::kType1_Font: |
- SkASSERT(!multibyte); |
SkASSERT(fontMetrics != nullptr); |
- font = sk_make_sp<SkPDFType1Font>(fontMetrics, |
+ font = sk_make_sp<SkPDFType1Font>(std::move(fontMetrics), |
std::move(typeface), |
glyphID, |
- canon); |
+ std::move(relatedFontDescriptor)); |
break; |
- default: |
- SkASSERT(!multibyte); |
- font = sk_make_sp<SkPDFType3Font>(fontMetrics, |
+ case SkAdvancedTypefaceMetrics::kCFF_Font: |
+ SkASSERT(fontMetrics != nullptr); |
+ // fallthrough |
+ case SkAdvancedTypefaceMetrics::kOther_Font: |
+ font = sk_make_sp<SkPDFType3Font>(std::move(fontMetrics), |
std::move(typeface), |
type, |
glyphID); |
break; |
- } |
- canon->fFontMap.set(fontID, SkRef(font.get())); |
+ default: |
+ SkDEBUGFAIL("invalid SkAdvancedTypefaceMetrics::FontType"); |
+ return nullptr; |
+ } |
+ // When firstGlyphID==0, SkFont::IsMatch() matches all glyphs in font. |
+ SkGlyphID firstGlyphID = font->multiByteGlyphs() ? 0 : font->fFirstGlyphID; |
+ // TODO(halcanary) Make SkCanon::addFont take sk_sp<SkPDFFont>. |
+ canon->addFont(font.get(), fontID, firstGlyphID); |
return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>. |
} |
-sk_sp<SkPDFObject> SkPDFFont::getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) { |
+sk_sp<SkPDFObject> SkPDFFont::getFontSubset(const SkPDFGlyphSet*) { |
return nullptr; // Default: no support. |
} |
-SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface, |
- SkAdvancedTypefaceMetrics::FontType fontType) |
+// TODO: take a sk_sp<SkAdvancedTypefaceMetrics> and sk_sp<SkTypeface> |
+SkPDFFont::SkPDFFont(sk_sp<const SkAdvancedTypefaceMetrics> info, |
+ sk_sp<SkTypeface> typeface, |
+ sk_sp<SkPDFDict> relatedFontDescriptor, |
+ SkAdvancedTypefaceMetrics::FontType fontType, |
+ bool multiByteGlyphs) |
: SkPDFDict("Font") |
, fTypeface(std::move(typeface)) |
+ , fFontInfo(std::move(info)) |
+ , fDescriptor(std::move(relatedFontDescriptor)) |
, fFirstGlyphID(1) |
- , fFontType(fontType) { |
+ , fFontType(fontType) |
+ , fMultiByteGlyphs(multiByteGlyphs) { |
SkASSERT(fTypeface); |
- fLastGlyphID = SkToU16(fTypeface->countGlyphs() - 1); |
+ fLastGlyphID = fFontInfo ? fFontInfo->fLastGlyphID : 0; |
+ if (0 == fLastGlyphID) { |
+ fLastGlyphID = SkToU16(fTypeface->countGlyphs() - 1); |
+ } |
+} |
+ |
+void SkPDFFont::setFontInfo(sk_sp<const SkAdvancedTypefaceMetrics> info) { |
+ if (info) { |
+ fFontInfo = std::move(info); |
+ } |
+} |
+ |
+void SkPDFFont::setLastGlyphID(uint16_t glyphID) { |
+ fLastGlyphID = glyphID; |
+} |
+ |
+void SkPDFFont::setFontDescriptor(sk_sp<SkPDFDict> descriptor) { |
+ fDescriptor = std::move(descriptor); |
} |
static void add_common_font_descriptor_entries(SkPDFDict* descriptor, |
@@ -380,41 +415,48 @@ |
} |
} |
-void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(SkGlyphID glyphID) { |
+void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(uint16_t glyphID) { |
// Single byte glyph encoding supports a max of 255 glyphs. |
- fFirstGlyphID = first_glyph_for_single_byte_encoding(glyphID); |
+ fFirstGlyphID = glyphID - (glyphID - 1) % 255; |
if (fLastGlyphID > fFirstGlyphID + 255 - 1) { |
fLastGlyphID = fFirstGlyphID + 255 - 1; |
} |
} |
+void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { |
+ if (fFontInfo == nullptr || fFontInfo->fGlyphToUnicode.begin() == nullptr) { |
+ return; |
+ } |
+ this->insertObjRef("ToUnicode", |
+ SkPDFMakeToUnicodeCmap(fFontInfo->fGlyphToUnicode, |
+ subset, |
+ multiByteGlyphs(), |
+ firstGlyphID(), |
+ lastGlyphID())); |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
// class SkPDFType0Font |
/////////////////////////////////////////////////////////////////////////////// |
-SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, |
+SkPDFType0Font::SkPDFType0Font(sk_sp<const SkAdvancedTypefaceMetrics> info, |
sk_sp<SkTypeface> typeface, |
SkAdvancedTypefaceMetrics::FontType fontType) |
- : SkPDFFont(std::move(typeface), fontType) { |
+ : SkPDFFont(std::move(info), std::move(typeface), nullptr, fontType, true) { |
SkDEBUGCODE(fPopulated = false); |
- if (!can_subset(info)) { |
- this->populate(nullptr, *info); |
+ if (!canSubset()) { |
+ this->populate(nullptr); |
} |
} |
SkPDFType0Font::~SkPDFType0Font() {} |
-sk_sp<SkPDFObject> SkPDFType0Font::getFontSubset(SkPDFCanon* canon, |
- const SkPDFGlyphSet* subset) { |
- const SkAdvancedTypefaceMetrics* metrics = |
- SkPDFFont::GetMetrics(this->typeface(), canon); |
- SkASSERT(metrics); |
- if (!can_subset(metrics)) { |
+sk_sp<SkPDFObject> SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) { |
+ if (!canSubset()) { |
return nullptr; |
} |
- auto newSubset = sk_make_sp<SkPDFType0Font>( |
- metrics, this->refTypeface(), this->getType()); |
- newSubset->populate(subset, *metrics); |
+ auto newSubset = sk_make_sp<SkPDFType0Font>(refFontInfo(), refTypeface(), getType()); |
+ newSubset->populate(subset); |
return newSubset; |
} |
@@ -480,9 +522,10 @@ |
} |
#endif // SK_SFNTLY_SUBSETTER |
-bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset, |
- const SkAdvancedTypefaceMetrics& metrics) { |
- SkASSERT(can_embed(&metrics)); |
+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); |
@@ -505,7 +548,7 @@ |
} |
#ifdef SK_SFNTLY_SUBSETTER |
- if (can_subset(&metrics) && subset) { |
+ if (this->canSubset() && subset) { |
// Generate glyph id array. in format needed by sfntly |
SkTDArray<uint32_t> glyphIDs; |
if (subset) { |
@@ -564,7 +607,7 @@ |
sysInfo->insertInt("Supplement", 0); |
newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); |
- uint16_t emSize = metrics.fEmSize; |
+ uint16_t emSize = this->getFontInfo()->fEmSize; |
int16_t defaultWidth = 0; |
const SkBitSet* bitSet = subset ? &subset->bitSet() : nullptr; |
{ |
@@ -586,77 +629,102 @@ |
auto descendantFonts = sk_make_sp<SkPDFArray>(); |
descendantFonts->appendObjRef(std::move(newCIDFont)); |
this->insertObject("DescendantFonts", std::move(descendantFonts)); |
- |
- if (metrics.fGlyphToUnicode.count() > 0) { |
- this->insertObjRef("ToUnicode", |
- SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode, |
- subset, |
- multiByteGlyphs(), |
- firstGlyphID(), |
- lastGlyphID())); |
- } |
+ 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 |
/////////////////////////////////////////////////////////////////////////////// |
-static sk_sp<SkPDFDict> make_type1_font_descriptor( |
- SkTypeface* typeface, |
- const SkAdvancedTypefaceMetrics* info) { |
+SkPDFType1Font::SkPDFType1Font(sk_sp<const SkAdvancedTypefaceMetrics> info, |
+ sk_sp<SkTypeface> typeface, |
+ uint16_t glyphID, |
+ sk_sp<SkPDFDict> relatedFontDescriptor) |
+ : SkPDFFont(std::move(info), |
+ std::move(typeface), |
+ std::move(relatedFontDescriptor), |
+ SkAdvancedTypefaceMetrics::kType1_Font, |
+ /* multiByteGlyphs = */ false) { |
+ this->populate(glyphID); // TODO(halcanary): subset this. |
+} |
+ |
+SkPDFType1Font::~SkPDFType1Font() {} |
+ |
+bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) { |
+ if (sk_sp<SkPDFDict> descriptor = this->refFontDescriptor()) { |
+ this->insertObjRef("FontDescriptor", std::move(descriptor)); |
+ return true; |
+ } |
+ |
auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); |
- SkASSERT(info); |
- add_common_font_descriptor_entries(descriptor.get(), *info, 0); |
+ setFontDescriptor(descriptor); |
int ttcIndex; |
size_t header SK_INIT_TO_AVOID_WARNING; |
size_t data SK_INIT_TO_AVOID_WARNING; |
size_t trailer SK_INIT_TO_AVOID_WARNING; |
- std::unique_ptr<SkStreamAsset> rawFontData(typeface->openStream(&ttcIndex)); |
+ std::unique_ptr<SkStreamAsset> rawFontData(typeface()->openStream(&ttcIndex)); |
sk_sp<SkData> fontData = SkPDFConvertType1FontStream(std::move(rawFontData), |
&header, &data, &trailer); |
- if (fontData && can_embed(info)) { |
- auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData)); |
- fontStream->dict()->insertInt("Length1", header); |
- fontStream->dict()->insertInt("Length2", data); |
- fontStream->dict()->insertInt("Length3", trailer); |
- descriptor->insertObjRef("FontFile", std::move(fontStream)); |
- } |
- return descriptor; |
-} |
- |
-static void populate_type_1_font(SkPDFDict* font, |
- const SkAdvancedTypefaceMetrics* info, |
- SkTypeface* typeface, |
- SkGlyphID firstGlyphID, |
- SkGlyphID lastGlyphID) { |
- SkASSERT(info); |
- font->insertName("Subtype", "Type1"); |
- font->insertName("BaseFont", info->fFontName); |
+ if (!fontData) { |
+ return false; |
+ } |
+ SkASSERT(this->canEmbed()); |
+ auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData)); |
+ fontStream->dict()->insertInt("Length1", header); |
+ fontStream->dict()->insertInt("Length2", data); |
+ 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 true; |
+} |
+ |
+bool SkPDFType1Font::populate(int16_t glyphID) { |
+ this->insertName("Subtype", "Type1"); |
+ this->insertName("BaseFont", this->getFontInfo()->fFontName); |
+ adjustGlyphRangeForSingleByteEncoding(glyphID); |
+ SkGlyphID firstGlyphID = this->firstGlyphID(); |
+ SkGlyphID lastGlyphID = this->lastGlyphID(); |
// glyphCount not including glyph 0 |
unsigned glyphCount = 1 + lastGlyphID - firstGlyphID; |
SkASSERT(glyphCount > 0 && glyphCount <= 255); |
- font->insertInt("FirstChar", (size_t)0); |
- font->insertInt("LastChar", (size_t)glyphCount); |
+ this->insertInt("FirstChar", (size_t)0); |
+ this->insertInt("LastChar", (size_t)glyphCount); |
{ |
- SkAutoGlyphCache glyphCache = vector_cache(typeface); |
+ SkAutoGlyphCache glyphCache = vector_cache(this->typeface()); |
auto widths = sk_make_sp<SkPDFArray>(); |
SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX; |
- const uint16_t emSize = info->fEmSize; |
+ const uint16_t emSize = this->getFontInfo()->fEmSize; |
widths->appendScalar(from_font_units(advance, emSize)); |
for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) { |
advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX; |
widths->appendScalar(from_font_units(advance, emSize)); |
} |
- font->insertObject("Widths", std::move(widths)); |
+ this->insertObject("Widths", std::move(widths)); |
+ } |
+ if (!addFontDescriptor(0)) { |
+ return false; |
} |
auto encDiffs = sk_make_sp<SkPDFArray>(); |
encDiffs->reserve(lastGlyphID - firstGlyphID + 3); |
encDiffs->appendInt(0); |
- const SkTArray<SkString>& glyphNames = info->fGlyphNames; |
+ const SkTArray<SkString>& glyphNames = this->getFontInfo()->fGlyphNames; |
SkASSERT(glyphNames.count() > lastGlyphID); |
encDiffs->appendName(glyphNames[0].c_str()); |
const SkString unknown("UNKNOWN"); |
@@ -668,28 +736,8 @@ |
auto encoding = sk_make_sp<SkPDFDict>("Encoding"); |
encoding->insertObject("Differences", std::move(encDiffs)); |
- font->insertObject("Encoding", std::move(encoding)); |
-} |
- |
-SkPDFType1Font::SkPDFType1Font(const SkAdvancedTypefaceMetrics* info, |
- sk_sp<SkTypeface> typeface, |
- uint16_t glyphID, |
- SkPDFCanon* canon) |
- : SkPDFFont(std::move(typeface), SkAdvancedTypefaceMetrics::kType1_Font) |
-{ |
- 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); |
- 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(), |
- this->firstGlyphID(), this->lastGlyphID()); |
+ this->insertObject("Encoding", std::move(encoding)); |
+ return true; |
} |
/////////////////////////////////////////////////////////////////////////////// |
@@ -726,8 +774,7 @@ |
}; |
} |
-static void add_type3_font_info(SkPDFCanon* canon, |
- SkPDFDict* font, |
+static void add_type3_font_info(SkPDFDict* font, |
SkTypeface* typeface, |
SkScalar emSize, |
const SkPDFGlyphSet* subset, |
@@ -815,8 +862,21 @@ |
fontBBox->appendInt(bbox.top()); |
font->insertObject("FontBBox", std::move(fontBBox)); |
font->insertName("CIDToGIDMap", "Identity"); |
- const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon); |
- if (metrics /* && metrics->fGlyphToUnicode.count() > 0 */) { |
+ 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); |
+ } |
+ } |
+ subset->exportTo(&subsetList); |
+ metrics = SkPDFFont::GetFontMetricsWithToUnicode(typeface, subsetList.begin(), |
+ subsetList.count()); |
+ } else { |
+ metrics = SkPDFFont::GetFontMetricsWithToUnicode(typeface, nullptr, 0); |
+ } |
+ if (metrics) { |
font->insertObjRef("ToUnicode", |
SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode, |
subset, |
@@ -829,23 +889,24 @@ |
font->insertObject("CharProcs", std::move(charProcs)); |
} |
-SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, |
+SkPDFType3Font::SkPDFType3Font(sk_sp<const SkAdvancedTypefaceMetrics> info, |
sk_sp<SkTypeface> typeface, |
SkAdvancedTypefaceMetrics::FontType fontType, |
uint16_t glyphID) |
- : SkPDFFont(std::move(typeface), fontType) { |
+ : SkPDFFont(std::move(info), std::move(typeface), nullptr, |
+ fontType, /* multiByteGlyphs = */ false) { |
+ // If fLastGlyphID isn't set (because there is not fFontInfo), look it up. |
+ this->setLastGlyphID(SkToU16(this->typeface()->countGlyphs() - 1)); |
this->adjustGlyphRangeForSingleByteEncoding(glyphID); |
} |
-sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(SkPDFCanon* canon, |
- const SkPDFGlyphSet* usage) { |
+sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(const SkPDFGlyphSet* usage) { |
// All fonts are subset before serialization. |
// TODO(halcanary): all fonts should follow this pattern. |
- const SkAdvancedTypefaceMetrics* info = |
- SkPDFFont::GetMetrics(this->typeface(), canon); |
+ auto font = sk_make_sp<SkPDFDict>("Font"); |
+ const SkAdvancedTypefaceMetrics* info = this->getFontInfo(); |
uint16_t emSize = info && 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(font.get(), this->typeface(), (SkScalar)emSize, usage, |
this->firstGlyphID(), this->lastGlyphID()); |
return font; |
} |
@@ -853,11 +914,49 @@ |
//////////////////////////////////////////////////////////////////////////////// |
+SkPDFFont::Match SkPDFFont::IsMatch(SkPDFFont* existingFont, |
+ uint32_t existingFontID, |
+ uint16_t existingGlyphID, |
+ uint32_t searchFontID, |
+ uint16_t searchGlyphID) { |
+ if (existingFontID != searchFontID) { |
+ return SkPDFFont::kNot_Match; |
+ } |
+ if (existingGlyphID == 0 || searchGlyphID == 0) { |
+ return SkPDFFont::kExact_Match; |
+ } |
+ if (existingFont != nullptr) { |
+ return (existingFont->fFirstGlyphID <= searchGlyphID && |
+ searchGlyphID <= existingFont->fLastGlyphID) |
+ ? SkPDFFont::kExact_Match |
+ : SkPDFFont::kRelated_Match; |
+ } |
+ return (existingGlyphID == searchGlyphID) ? SkPDFFont::kExact_Match |
+ : SkPDFFont::kRelated_Match; |
+} |
+ |
+// Since getAdvancedTypefaceMetrics is expensive, cache the result. |
bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { |
- return can_embed(SkPDFFont::GetMetrics(typeface, canon)); |
+ SkFontID id = SkTypeface::UniqueID(typeface); |
+ if (bool* value = canon->fCanEmbedTypeface.find(id)) { |
+ return *value; |
+ } |
+ SkAutoResolveDefaultTypeface face(typeface); |
+ bool canEmbed = true; |
+ sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics( |
+ face->getAdvancedTypefaceMetrics( |
+ SkTypeface::kNo_PerGlyphInfo, nullptr, 0)); |
+ if (fontMetrics) { |
+ canEmbed = !SkToBool( |
+ fontMetrics->fFlags & |
+ SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag); |
+ } |
+ return *canon->fCanEmbedTypeface.set(id, canEmbed); |
} |
void SkPDFFont::drop() { |
fTypeface = nullptr; |
+ fFontInfo = nullptr; |
+ fDescriptor = nullptr; |
this->SkPDFDict::drop(); |
} |