Index: src/pdf/SkPDFFont.cpp |
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp |
index 2f7137fd99cefae9e51c36e1b4f66a3b71aa7c39..6e04c23e25790e673e050ffedfec554b2365c177 100644 |
--- a/src/pdf/SkPDFFont.cpp |
+++ b/src/pdf/SkPDFFont.cpp |
@@ -584,67 +584,10 @@ static sk_sp<SkPDFStream> generate_tounicode_cmap( |
append_cmap_sections(glyphToUnicode, subset, &cmap, multiByteGlyphs, |
firstGlyphID, lastGlyphID); |
append_cmap_footer(&cmap); |
- sk_sp<SkData> cmapData(cmap.copyToData()); |
- return sk_make_sp<SkPDFStream>(cmapData.get()); |
+ return sk_make_sp<SkPDFStream>( |
+ std::unique_ptr<SkStreamAsset>(cmap.detachAsStream())); |
} |
-#if defined (SK_SFNTLY_SUBSETTER) |
-static void sk_delete_array(const void* ptr, void*) { |
- // Use C-style cast to cast away const and cast type simultaneously. |
- delete[] (unsigned char*)ptr; |
-} |
-#endif |
- |
-#if defined(SK_SFNTLY_SUBSETTER) |
-static size_t get_subset_font_stream(const char* fontName, |
- const SkTypeface* typeface, |
- const SkTDArray<uint32_t>& subset, |
- SkPDFStream** fontStream) { |
- int ttcIndex; |
- std::unique_ptr<SkStreamAsset> fontData(typeface->openStream(&ttcIndex)); |
- SkASSERT(fontData); |
- if (!fontData) { |
- return 0; |
- } |
- |
- size_t fontSize = fontData->getLength(); |
- |
- // Read font into buffer. |
- SkPDFStream* subsetFontStream = nullptr; |
- SkTDArray<unsigned char> originalFont; |
- originalFont.setCount(SkToInt(fontSize)); |
- if (fontData->read(originalFont.begin(), fontSize) == fontSize) { |
- unsigned char* subsetFont = nullptr; |
- // sfntly requires unsigned int* to be passed in, as far as we know, |
- // unsigned int is equivalent to uint32_t on all platforms. |
- static_assert(sizeof(unsigned int) == sizeof(uint32_t), "unsigned_int_not_32_bits"); |
- int subsetFontSize = SfntlyWrapper::SubsetFont(fontName, |
- originalFont.begin(), |
- fontSize, |
- subset.begin(), |
- subset.count(), |
- &subsetFont); |
- if (subsetFontSize > 0 && subsetFont != nullptr) { |
- SkAutoDataUnref data(SkData::NewWithProc(subsetFont, |
- subsetFontSize, |
- sk_delete_array, |
- nullptr)); |
- subsetFontStream = new SkPDFStream(data.get()); |
- fontSize = subsetFontSize; |
- } |
- } |
- if (subsetFontStream) { |
- *fontStream = subsetFontStream; |
- return fontSize; |
- } |
- fontData->rewind(); |
- |
- // Fail over: just embed the whole font. |
- *fontStream = new SkPDFStream(std::move(fontData)); |
- return fontSize; |
-} |
-#endif |
- |
/////////////////////////////////////////////////////////////////////////////// |
// class SkPDFGlyphSet |
/////////////////////////////////////////////////////////////////////////////// |
@@ -665,7 +608,7 @@ bool SkPDFGlyphSet::has(uint16_t glyphID) const { |
void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const { |
fBitSet.exportTo(glyphIDs); |
} |
- |
+ |
/////////////////////////////////////////////////////////////////////////////// |
// class SkPDFGlyphSetMap |
/////////////////////////////////////////////////////////////////////////////// |
@@ -1015,6 +958,59 @@ SkPDFCIDFont::SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info, |
SkPDFCIDFont::~SkPDFCIDFont() {} |
+#ifdef SK_SFNTLY_SUBSETTER |
+// if possible, make no copy. |
+static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) { |
+ SkASSERT(stream); |
+ (void)stream->rewind(); |
+ SkASSERT(stream->hasLength()); |
+ size_t size = stream->getLength(); |
+ if (const void* base = stream->getMemoryBase()) { |
+ SkData::ReleaseProc proc = |
+ [](const void*, void* ctx) { delete (SkStream*)ctx; }; |
+ return SkData::MakeWithProc(base, size, proc, stream.release()); |
+ } |
+ return SkData::MakeFromStream(stream.get(), size); |
+} |
+ |
+static sk_sp<SkPDFObject> get_subset_font_stream( |
+ std::unique_ptr<SkStreamAsset> fontAsset, |
+ const SkTDArray<uint32_t>& subset, |
+ const char* fontName) { |
+ // sfntly requires unsigned int* to be passed in, |
+ // as far as we know, unsigned int is equivalent |
+ // to uint32_t on all platforms. |
+ static_assert(sizeof(unsigned) == sizeof(uint32_t), ""); |
+ |
+ // TODO(halcanary): Use ttcIndex, not fontName. |
+ |
+ unsigned char* subsetFont{nullptr}; |
+ int subsetFontSize{0}; |
+ { |
+ sk_sp<SkData> fontData(stream_to_data(std::move(fontAsset))); |
+ subsetFontSize = |
+ SfntlyWrapper::SubsetFont(fontName, |
+ fontData->bytes(), |
+ fontData->size(), |
+ subset.begin(), |
+ subset.count(), |
+ &subsetFont); |
+ } |
+ SkASSERT(subsetFontSize > 0 || subsetFont == nullptr); |
+ if (subsetFontSize < 1) { |
+ return nullptr; |
+ } |
+ SkASSERT(subsetFont != nullptr); |
+ auto subsetStream = sk_make_sp<SkPDFStream>( |
+ SkData::MakeWithProc( |
+ subsetFont, subsetFontSize, |
+ [](const void* p, void*) { delete[] (unsigned char*)p; }, |
+ nullptr)); |
+ subsetStream->insertInt("Length1", subsetFontSize); |
+ return subsetStream; |
+} |
+#endif // SK_SFNTLY_SUBSETTER |
+ |
bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, |
const SkTDArray<uint32_t>* subset) { |
auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); |
@@ -1027,36 +1023,32 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, |
switch (getType()) { |
case SkAdvancedTypefaceMetrics::kTrueType_Font: { |
- size_t fontSize = 0; |
-#if defined(SK_SFNTLY_SUBSETTER) |
- if (this->canSubset()) { |
- sk_sp<SkPDFStream> fontStream; |
- SkPDFStream* rawStream = nullptr; |
- fontSize = get_subset_font_stream(fontInfo()->fFontName.c_str(), |
- typeface(), |
- *subset, |
- &rawStream); |
- if (0 == fontSize) { |
- return false; |
- } |
- if (rawStream) { |
- fontStream.reset(rawStream); |
- fontStream->insertInt("Length1", fontSize); |
- descriptor->insertObjRef("FontFile2", std::move(fontStream)); |
- break; |
- } |
- } |
-#endif |
- sk_sp<SkPDFSharedStream> fontStream; |
- std::unique_ptr<SkStreamAsset> fontData( |
- this->typeface()->openStream(nullptr)); |
- SkASSERT(fontData); |
- if (!fontData || 0 == fontData->getLength()) { |
+ int ttcIndex; |
+ std::unique_ptr<SkStreamAsset> fontAsset( |
+ this->typeface()->openStream(&ttcIndex)); |
+ SkASSERT(fontAsset); |
+ if (!fontAsset) { |
return false; |
} |
- fontSize = fontData->getLength(); |
+ size_t fontSize = fontAsset->getLength(); |
SkASSERT(fontSize > 0); |
- fontStream.reset(new SkPDFSharedStream(fontData.release())); |
+ if (fontSize == 0) { |
+ return false; |
+ } |
+ |
+ #ifdef SK_SFNTLY_SUBSETTER |
+ if (this->canSubset() && subset) { |
+ sk_sp<SkPDFObject> subsetStream = get_subset_font_stream( |
+ std::move(fontAsset), *subset, fontInfo()->fFontName.c_str()); |
+ if (subsetStream) { |
+ descriptor->insertObjRef("FontFile2", std::move(subsetStream)); |
+ break; |
+ } |
+ // If subsetting fails, fall back to original font data. |
+ fontAsset.reset(this->typeface()->openStream(&ttcIndex)); |
+ } |
+ #endif // SK_SFNTLY_SUBSETTER |
+ auto fontStream = sk_make_sp<SkPDFSharedStream>(fontAsset.release()); |
fontStream->dict()->insertInt("Length1", fontSize); |
descriptor->insertObjRef("FontFile2", std::move(fontStream)); |
break; |
@@ -1207,7 +1199,7 @@ bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) { |
return false; |
} |
SkASSERT(this->canEmbed()); |
- auto fontStream = sk_make_sp<SkPDFStream>(fontData.get()); |
+ auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData)); |
fontStream->insertInt("Length1", header); |
fontStream->insertInt("Length2", data); |
fontStream->insertInt("Length3", trailer); |