| Index: src/pdf/SkPDFFont.cpp
|
| diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
|
| index 2836b31f7f3c99d6008f9baacd126ef1772ac2d6..53a0c02ed0c07fd986a59b1fda0427734b1197b7 100644
|
| --- a/src/pdf/SkPDFFont.cpp
|
| +++ b/src/pdf/SkPDFFont.cpp
|
| @@ -140,6 +140,12 @@
|
| static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
|
| return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
|
| }
|
| +
|
| +#ifdef SK_PDF_USE_SFNTLY
|
| +static bool can_subset(const SkAdvancedTypefaceMetrics& metrics) {
|
| + return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag);
|
| +}
|
| +#endif
|
|
|
| const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface,
|
| SkPDFCanon* canon) {
|
| @@ -300,34 +306,35 @@
|
| size_t size = stream->getLength();
|
| if (const void* base = stream->getMemoryBase()) {
|
| SkData::ReleaseProc proc =
|
| - [](const void*, void* ctx) { delete (SkStreamAsset*)ctx; };
|
| + [](const void*, void* ctx) { delete (SkStream*)ctx; };
|
| return SkData::MakeWithProc(base, size, proc, stream.release());
|
| }
|
| return SkData::MakeFromStream(stream.get(), size);
|
| }
|
|
|
| -static sk_sp<SkPDFStream> get_subset_font_stream(
|
| +static sk_sp<SkPDFObject> get_subset_font_stream(
|
| std::unique_ptr<SkStreamAsset> fontAsset,
|
| - const SkBitSet& glyphUsage,
|
| - int ttcIndex) {
|
| - // Generate glyph id array in format needed by sfntly.
|
| - // TODO(halcanary): sfntly should take a more compact format.
|
| - SkTDArray<unsigned> subset;
|
| - if (!glyphUsage.has(0)) {
|
| - subset.push(0); // Always include glyph 0.
|
| - }
|
| - glyphUsage.exportTo(&subset);
|
| + 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};
|
| - sk_sp<SkData> fontData(stream_to_data(std::move(fontAsset)));
|
| - int subsetFontSize = SfntlyWrapper::SubsetFont(ttcIndex,
|
| - fontData->bytes(),
|
| - fontData->size(),
|
| - subset.begin(),
|
| - subset.count(),
|
| - &subsetFont);
|
| - fontData.reset();
|
| - subset.reset();
|
| + 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;
|
| @@ -353,65 +360,76 @@
|
| SkAdvancedTypefaceMetrics::FontType type = this->getType();
|
| SkTypeface* face = this->typeface();
|
| SkASSERT(face);
|
| + const SkString& name = metrics.fFontName;
|
|
|
| auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
|
| add_common_font_descriptor_entries(descriptor.get(), metrics, 0);
|
| -
|
| - int ttcIndex;
|
| - std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex));
|
| - size_t fontSize = fontAsset ? fontAsset->getLength() : 0;
|
| - SkASSERT(fontAsset);
|
| - SkASSERT(fontSize > 0);
|
| - if (fontSize > 0) {
|
| - switch (type) {
|
| - case SkAdvancedTypefaceMetrics::kTrueType_Font: {
|
| - #ifdef SK_PDF_USE_SFNTLY
|
| - if (!SkToBool(metrics.fFlags &
|
| - SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag)) {
|
| - sk_sp<SkPDFStream> subsetStream = get_subset_font_stream(
|
| - std::move(fontAsset), this->glyphUsage(), ttcIndex);
|
| - if (subsetStream) {
|
| - descriptor->insertObjRef("FontFile2", std::move(subsetStream));
|
| - break;
|
| - }
|
| - // If subsetting fails, fall back to original font data.
|
| - fontAsset.reset(face->openStream(&ttcIndex));
|
| - SkASSERT(fontAsset);
|
| - SkASSERT(fontAsset->getLength() == fontSize);
|
| - if (!fontAsset || fontAsset->getLength() == 0) { break; }
|
| + switch (type) {
|
| + case SkAdvancedTypefaceMetrics::kTrueType_Font: {
|
| + int ttcIndex;
|
| + std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex));
|
| + SkASSERT(fontAsset);
|
| + if (!fontAsset) {
|
| + return;
|
| + }
|
| + size_t fontSize = fontAsset->getLength();
|
| + SkASSERT(fontSize > 0);
|
| + if (fontSize == 0) {
|
| + return;
|
| + }
|
| +
|
| + #ifdef SK_PDF_USE_SFNTLY
|
| + if (can_subset(metrics)) {
|
| + // Generate glyph id array. in format needed by sfntly
|
| + SkTDArray<uint32_t> glyphIDs;
|
| + if (!this->glyphUsage().has(0)) {
|
| + glyphIDs.push(0); // Always include glyph 0.
|
| }
|
| - #endif // SK_PDF_USE_SFNTLY
|
| - auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
|
| - fontStream->dict()->insertInt("Length1", fontSize);
|
| - descriptor->insertObjRef("FontFile2", std::move(fontStream));
|
| - break;
|
| + this->glyphUsage().exportTo(&glyphIDs);
|
| + sk_sp<SkPDFObject> subsetStream = get_subset_font_stream(
|
| + std::move(fontAsset), glyphIDs, name.c_str());
|
| + if (subsetStream) {
|
| + descriptor->insertObjRef("FontFile2", std::move(subsetStream));
|
| + break;
|
| + }
|
| + // If subsetting fails, fall back to original font data.
|
| + fontAsset.reset(face->openStream(&ttcIndex));
|
| }
|
| - case SkAdvancedTypefaceMetrics::kType1CID_Font: {
|
| - auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
|
| - fontStream->dict()->insertName("Subtype", "CIDFontType0C");
|
| - descriptor->insertObjRef("FontFile3", std::move(fontStream));
|
| - break;
|
| + #endif // SK_PDF_USE_SFNTLY
|
| + auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
|
| + fontStream->dict()->insertInt("Length1", fontSize);
|
| + descriptor->insertObjRef("FontFile2", std::move(fontStream));
|
| + break;
|
| + }
|
| + case SkAdvancedTypefaceMetrics::kType1CID_Font: {
|
| + std::unique_ptr<SkStreamAsset> fontData(face->openStream(nullptr));
|
| + SkASSERT(fontData);
|
| + SkASSERT(fontData->getLength() > 0);
|
| + if (!fontData || 0 == fontData->getLength()) {
|
| + return;
|
| }
|
| - default:
|
| - SkASSERT(false);
|
| + auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData));
|
| + fontStream->dict()->insertName("Subtype", "CIDFontType0c");
|
| + descriptor->insertObjRef("FontFile3", std::move(fontStream));
|
| + break;
|
| }
|
| + default:
|
| + SkASSERT(false);
|
| }
|
|
|
| auto newCIDFont = sk_make_sp<SkPDFDict>("Font");
|
| newCIDFont->insertObjRef("FontDescriptor", std::move(descriptor));
|
| - newCIDFont->insertName("BaseFont", metrics.fFontName);
|
| -
|
| - switch (type) {
|
| - case SkAdvancedTypefaceMetrics::kType1CID_Font:
|
| - newCIDFont->insertName("Subtype", "CIDFontType0");
|
| - break;
|
| - case SkAdvancedTypefaceMetrics::kTrueType_Font:
|
| - newCIDFont->insertName("Subtype", "CIDFontType2");
|
| - newCIDFont->insertName("CIDToGIDMap", "Identity");
|
| - break;
|
| - default:
|
| - SkASSERT(false);
|
| - }
|
| + newCIDFont->insertName("BaseFont", name);
|
| +
|
| + 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);
|
| + }
|
| +
|
| auto sysInfo = sk_make_sp<SkPDFDict>();
|
| sysInfo->insertString("Registry", "Adobe");
|
| sysInfo->insertString("Ordering", "Identity");
|
|
|