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

Unified Diff: src/pdf/SkPDFFont.cpp

Issue 2190643002: SkPDF: refactor font subset: fewer copies (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2016-07-27 (Wednesday) 16:22:36 EDT Created 4 years, 5 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/SkPDFDocument.cpp ('k') | src/pdf/SkPDFGraphicState.cpp » ('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 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);
« no previous file with comments | « src/pdf/SkPDFDocument.cpp ('k') | src/pdf/SkPDFGraphicState.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698