Chromium Code Reviews| Index: src/pdf/SkPDFFont.cpp |
| diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp |
| index 2f7137fd99cefae9e51c36e1b4f66a3b71aa7c39..fe3ae4698bcd798e9c366edc767bb94658b108bc 100644 |
| --- a/src/pdf/SkPDFFont.cpp |
| +++ b/src/pdf/SkPDFFont.cpp |
| @@ -584,64 +584,23 @@ 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; |
| +#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); |
| } |
| #endif |
| @@ -665,7 +624,7 @@ bool SkPDFGlyphSet::has(uint16_t glyphID) const { |
| void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const { |
| fBitSet.exportTo(glyphIDs); |
| } |
| - |
| + |
| /////////////////////////////////////////////////////////////////////////////// |
| // class SkPDFGlyphSetMap |
| /////////////////////////////////////////////////////////////////////////////// |
| @@ -1027,36 +986,54 @@ 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<SkData> fontData(stream_to_data(std::move(fontAsset))); |
| + 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) == sizeof(uint32_t), ""); |
| + const char* fontName = fontInfo()->fFontName.c_str(); |
| + // TODO(halcanary): Use ttcIndex, not fontName. |
| + int subsetFontSize = |
| + SfntlyWrapper::SubsetFont(fontName, |
| + fontData->bytes(), |
| + fontSize, |
| + subset->begin(), |
| + subset->count(), |
| + &subsetFont); |
| + SkASSERT(subsetFontSize > 0 || subsetFont == nullptr); |
| + if (subsetFontSize > 0) { |
| + SkASSERT(subsetFont != nullptr); |
| + auto subset = sk_make_sp<SkPDFStream>( |
| + SkData::MakeWithProc( |
| + subsetFont, subsetFontSize, |
| + [](const void* p, void*) { |
| + delete[] (unsigned char*)p; |
| + }, nullptr)); |
| + subset->insertInt("Length1", subsetFontSize); |
| + descriptor->insertObjRef("FontFile2", std::move(subset)); |
| + break; |
| + } |
| + // If subsetting fails, fall back to original font data. |
| + fontAsset.reset(this->typeface()->openStream(&ttcIndex)); |
|
bungeman-skia
2016/07/27 19:26:44
Hopefully it doesn't matter too much, but note tha
hal.canary
2016/07/27 19:54:26
Fixed. now fontData is out of scope (in another f
|
| + } |
| + #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 +1184,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); |