| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include <ctype.h> | 8 #include <ctype.h> |
| 9 | 9 |
| 10 #include "SkData.h" | 10 #include "SkData.h" |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 uint16_t lastGlyphID) { | 577 uint16_t lastGlyphID) { |
| 578 SkDynamicMemoryWStream cmap; | 578 SkDynamicMemoryWStream cmap; |
| 579 if (multiByteGlyphs) { | 579 if (multiByteGlyphs) { |
| 580 append_tounicode_header(&cmap, firstGlyphID, lastGlyphID); | 580 append_tounicode_header(&cmap, firstGlyphID, lastGlyphID); |
| 581 } else { | 581 } else { |
| 582 append_tounicode_header(&cmap, 1, lastGlyphID - firstGlyphID + 1); | 582 append_tounicode_header(&cmap, 1, lastGlyphID - firstGlyphID + 1); |
| 583 } | 583 } |
| 584 append_cmap_sections(glyphToUnicode, subset, &cmap, multiByteGlyphs, | 584 append_cmap_sections(glyphToUnicode, subset, &cmap, multiByteGlyphs, |
| 585 firstGlyphID, lastGlyphID); | 585 firstGlyphID, lastGlyphID); |
| 586 append_cmap_footer(&cmap); | 586 append_cmap_footer(&cmap); |
| 587 sk_sp<SkData> cmapData(cmap.copyToData()); | 587 return sk_make_sp<SkPDFStream>( |
| 588 return sk_make_sp<SkPDFStream>(cmapData.get()); | 588 std::unique_ptr<SkStreamAsset>(cmap.detachAsStream())); |
| 589 } | 589 } |
| 590 | 590 |
| 591 #if defined (SK_SFNTLY_SUBSETTER) | |
| 592 static void sk_delete_array(const void* ptr, void*) { | |
| 593 // Use C-style cast to cast away const and cast type simultaneously. | |
| 594 delete[] (unsigned char*)ptr; | |
| 595 } | |
| 596 #endif | |
| 597 | |
| 598 #if defined(SK_SFNTLY_SUBSETTER) | |
| 599 static size_t get_subset_font_stream(const char* fontName, | |
| 600 const SkTypeface* typeface, | |
| 601 const SkTDArray<uint32_t>& subset, | |
| 602 SkPDFStream** fontStream) { | |
| 603 int ttcIndex; | |
| 604 std::unique_ptr<SkStreamAsset> fontData(typeface->openStream(&ttcIndex)); | |
| 605 SkASSERT(fontData); | |
| 606 if (!fontData) { | |
| 607 return 0; | |
| 608 } | |
| 609 | |
| 610 size_t fontSize = fontData->getLength(); | |
| 611 | |
| 612 // Read font into buffer. | |
| 613 SkPDFStream* subsetFontStream = nullptr; | |
| 614 SkTDArray<unsigned char> originalFont; | |
| 615 originalFont.setCount(SkToInt(fontSize)); | |
| 616 if (fontData->read(originalFont.begin(), fontSize) == fontSize) { | |
| 617 unsigned char* subsetFont = nullptr; | |
| 618 // sfntly requires unsigned int* to be passed in, as far as we know, | |
| 619 // unsigned int is equivalent to uint32_t on all platforms. | |
| 620 static_assert(sizeof(unsigned int) == sizeof(uint32_t), "unsigned_int_no
t_32_bits"); | |
| 621 int subsetFontSize = SfntlyWrapper::SubsetFont(fontName, | |
| 622 originalFont.begin(), | |
| 623 fontSize, | |
| 624 subset.begin(), | |
| 625 subset.count(), | |
| 626 &subsetFont); | |
| 627 if (subsetFontSize > 0 && subsetFont != nullptr) { | |
| 628 SkAutoDataUnref data(SkData::NewWithProc(subsetFont, | |
| 629 subsetFontSize, | |
| 630 sk_delete_array, | |
| 631 nullptr)); | |
| 632 subsetFontStream = new SkPDFStream(data.get()); | |
| 633 fontSize = subsetFontSize; | |
| 634 } | |
| 635 } | |
| 636 if (subsetFontStream) { | |
| 637 *fontStream = subsetFontStream; | |
| 638 return fontSize; | |
| 639 } | |
| 640 fontData->rewind(); | |
| 641 | |
| 642 // Fail over: just embed the whole font. | |
| 643 *fontStream = new SkPDFStream(std::move(fontData)); | |
| 644 return fontSize; | |
| 645 } | |
| 646 #endif | |
| 647 | |
| 648 /////////////////////////////////////////////////////////////////////////////// | 591 /////////////////////////////////////////////////////////////////////////////// |
| 649 // class SkPDFGlyphSet | 592 // class SkPDFGlyphSet |
| 650 /////////////////////////////////////////////////////////////////////////////// | 593 /////////////////////////////////////////////////////////////////////////////// |
| 651 | 594 |
| 652 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { | 595 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { |
| 653 } | 596 } |
| 654 | 597 |
| 655 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { | 598 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { |
| 656 for (int i = 0; i < numGlyphs; ++i) { | 599 for (int i = 0; i < numGlyphs; ++i) { |
| 657 fBitSet.setBit(glyphIDs[i], true); | 600 fBitSet.setBit(glyphIDs[i], true); |
| 658 } | 601 } |
| 659 } | 602 } |
| 660 | 603 |
| 661 bool SkPDFGlyphSet::has(uint16_t glyphID) const { | 604 bool SkPDFGlyphSet::has(uint16_t glyphID) const { |
| 662 return fBitSet.isBitSet(glyphID); | 605 return fBitSet.isBitSet(glyphID); |
| 663 } | 606 } |
| 664 | 607 |
| 665 void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const { | 608 void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const { |
| 666 fBitSet.exportTo(glyphIDs); | 609 fBitSet.exportTo(glyphIDs); |
| 667 } | 610 } |
| 668 | 611 |
| 669 /////////////////////////////////////////////////////////////////////////////// | 612 /////////////////////////////////////////////////////////////////////////////// |
| 670 // class SkPDFGlyphSetMap | 613 // class SkPDFGlyphSetMap |
| 671 /////////////////////////////////////////////////////////////////////////////// | 614 /////////////////////////////////////////////////////////////////////////////// |
| 672 | 615 |
| 673 SkPDFGlyphSetMap::SkPDFGlyphSetMap() {} | 616 SkPDFGlyphSetMap::SkPDFGlyphSetMap() {} |
| 674 | 617 |
| 675 SkPDFGlyphSetMap::~SkPDFGlyphSetMap() { | 618 SkPDFGlyphSetMap::~SkPDFGlyphSetMap() { |
| 676 fMap.reset(); | 619 fMap.reset(); |
| 677 } | 620 } |
| 678 | 621 |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 | 951 |
| 1009 SkPDFCIDFont::SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info, | 952 SkPDFCIDFont::SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info, |
| 1010 SkTypeface* typeface, | 953 SkTypeface* typeface, |
| 1011 const SkPDFGlyphSet* subset) | 954 const SkPDFGlyphSet* subset) |
| 1012 : SkPDFFont(info, typeface, nullptr) { | 955 : SkPDFFont(info, typeface, nullptr) { |
| 1013 this->populate(subset); | 956 this->populate(subset); |
| 1014 } | 957 } |
| 1015 | 958 |
| 1016 SkPDFCIDFont::~SkPDFCIDFont() {} | 959 SkPDFCIDFont::~SkPDFCIDFont() {} |
| 1017 | 960 |
| 961 #ifdef SK_SFNTLY_SUBSETTER |
| 962 // if possible, make no copy. |
| 963 static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) { |
| 964 SkASSERT(stream); |
| 965 (void)stream->rewind(); |
| 966 SkASSERT(stream->hasLength()); |
| 967 size_t size = stream->getLength(); |
| 968 if (const void* base = stream->getMemoryBase()) { |
| 969 SkData::ReleaseProc proc = |
| 970 [](const void*, void* ctx) { delete (SkStream*)ctx; }; |
| 971 return SkData::MakeWithProc(base, size, proc, stream.release()); |
| 972 } |
| 973 return SkData::MakeFromStream(stream.get(), size); |
| 974 } |
| 975 |
| 976 static sk_sp<SkPDFObject> get_subset_font_stream( |
| 977 std::unique_ptr<SkStreamAsset> fontAsset, |
| 978 const SkTDArray<uint32_t>& subset, |
| 979 const char* fontName) { |
| 980 // sfntly requires unsigned int* to be passed in, |
| 981 // as far as we know, unsigned int is equivalent |
| 982 // to uint32_t on all platforms. |
| 983 static_assert(sizeof(unsigned) == sizeof(uint32_t), ""); |
| 984 |
| 985 // TODO(halcanary): Use ttcIndex, not fontName. |
| 986 |
| 987 unsigned char* subsetFont{nullptr}; |
| 988 int subsetFontSize{0}; |
| 989 { |
| 990 sk_sp<SkData> fontData(stream_to_data(std::move(fontAsset))); |
| 991 subsetFontSize = |
| 992 SfntlyWrapper::SubsetFont(fontName, |
| 993 fontData->bytes(), |
| 994 fontData->size(), |
| 995 subset.begin(), |
| 996 subset.count(), |
| 997 &subsetFont); |
| 998 } |
| 999 SkASSERT(subsetFontSize > 0 || subsetFont == nullptr); |
| 1000 if (subsetFontSize < 1) { |
| 1001 return nullptr; |
| 1002 } |
| 1003 SkASSERT(subsetFont != nullptr); |
| 1004 auto subsetStream = sk_make_sp<SkPDFStream>( |
| 1005 SkData::MakeWithProc( |
| 1006 subsetFont, subsetFontSize, |
| 1007 [](const void* p, void*) { delete[] (unsigned char*)p; }, |
| 1008 nullptr)); |
| 1009 subsetStream->insertInt("Length1", subsetFontSize); |
| 1010 return subsetStream; |
| 1011 } |
| 1012 #endif // SK_SFNTLY_SUBSETTER |
| 1013 |
| 1018 bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, | 1014 bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, |
| 1019 const SkTDArray<uint32_t>* subset) { | 1015 const SkTDArray<uint32_t>* subset) { |
| 1020 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); | 1016 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); |
| 1021 setFontDescriptor(descriptor.get()); | 1017 setFontDescriptor(descriptor.get()); |
| 1022 if (!addCommonFontDescriptorEntries(defaultWidth)) { | 1018 if (!addCommonFontDescriptorEntries(defaultWidth)) { |
| 1023 this->insertObjRef("FontDescriptor", std::move(descriptor)); | 1019 this->insertObjRef("FontDescriptor", std::move(descriptor)); |
| 1024 return false; | 1020 return false; |
| 1025 } | 1021 } |
| 1026 SkASSERT(this->canEmbed()); | 1022 SkASSERT(this->canEmbed()); |
| 1027 | 1023 |
| 1028 switch (getType()) { | 1024 switch (getType()) { |
| 1029 case SkAdvancedTypefaceMetrics::kTrueType_Font: { | 1025 case SkAdvancedTypefaceMetrics::kTrueType_Font: { |
| 1030 size_t fontSize = 0; | 1026 int ttcIndex; |
| 1031 #if defined(SK_SFNTLY_SUBSETTER) | 1027 std::unique_ptr<SkStreamAsset> fontAsset( |
| 1032 if (this->canSubset()) { | 1028 this->typeface()->openStream(&ttcIndex)); |
| 1033 sk_sp<SkPDFStream> fontStream; | 1029 SkASSERT(fontAsset); |
| 1034 SkPDFStream* rawStream = nullptr; | 1030 if (!fontAsset) { |
| 1035 fontSize = get_subset_font_stream(fontInfo()->fFontName.c_str(), | 1031 return false; |
| 1036 typeface(), | 1032 } |
| 1037 *subset, | 1033 size_t fontSize = fontAsset->getLength(); |
| 1038 &rawStream); | 1034 SkASSERT(fontSize > 0); |
| 1039 if (0 == fontSize) { | 1035 if (fontSize == 0) { |
| 1040 return false; | 1036 return false; |
| 1041 } | 1037 } |
| 1042 if (rawStream) { | 1038 |
| 1043 fontStream.reset(rawStream); | 1039 #ifdef SK_SFNTLY_SUBSETTER |
| 1044 fontStream->insertInt("Length1", fontSize); | 1040 if (this->canSubset() && subset) { |
| 1045 descriptor->insertObjRef("FontFile2", std::move(fontStream))
; | 1041 sk_sp<SkPDFObject> subsetStream = get_subset_font_stream( |
| 1042 std::move(fontAsset), *subset, fontInfo()->fFontName.c_s
tr()); |
| 1043 if (subsetStream) { |
| 1044 descriptor->insertObjRef("FontFile2", std::move(subsetStream
)); |
| 1046 break; | 1045 break; |
| 1047 } | 1046 } |
| 1047 // If subsetting fails, fall back to original font data. |
| 1048 fontAsset.reset(this->typeface()->openStream(&ttcIndex)); |
| 1048 } | 1049 } |
| 1049 #endif | 1050 #endif // SK_SFNTLY_SUBSETTER |
| 1050 sk_sp<SkPDFSharedStream> fontStream; | 1051 auto fontStream = sk_make_sp<SkPDFSharedStream>(fontAsset.release())
; |
| 1051 std::unique_ptr<SkStreamAsset> fontData( | |
| 1052 this->typeface()->openStream(nullptr)); | |
| 1053 SkASSERT(fontData); | |
| 1054 if (!fontData || 0 == fontData->getLength()) { | |
| 1055 return false; | |
| 1056 } | |
| 1057 fontSize = fontData->getLength(); | |
| 1058 SkASSERT(fontSize > 0); | |
| 1059 fontStream.reset(new SkPDFSharedStream(fontData.release())); | |
| 1060 fontStream->dict()->insertInt("Length1", fontSize); | 1052 fontStream->dict()->insertInt("Length1", fontSize); |
| 1061 descriptor->insertObjRef("FontFile2", std::move(fontStream)); | 1053 descriptor->insertObjRef("FontFile2", std::move(fontStream)); |
| 1062 break; | 1054 break; |
| 1063 } | 1055 } |
| 1064 case SkAdvancedTypefaceMetrics::kCFF_Font: | 1056 case SkAdvancedTypefaceMetrics::kCFF_Font: |
| 1065 case SkAdvancedTypefaceMetrics::kType1CID_Font: { | 1057 case SkAdvancedTypefaceMetrics::kType1CID_Font: { |
| 1066 std::unique_ptr<SkStreamAsset> fontData( | 1058 std::unique_ptr<SkStreamAsset> fontData( |
| 1067 this->typeface()->openStream(nullptr)); | 1059 this->typeface()->openStream(nullptr)); |
| 1068 SkASSERT(fontData); | 1060 SkASSERT(fontData); |
| 1069 SkASSERT(fontData->getLength() > 0); | 1061 SkASSERT(fontData->getLength() > 0); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 SkASSERT(rawFontData->getLength() > 0); | 1192 SkASSERT(rawFontData->getLength() > 0); |
| 1201 if (!rawFontData || 0 == rawFontData->getLength()) { | 1193 if (!rawFontData || 0 == rawFontData->getLength()) { |
| 1202 return false; | 1194 return false; |
| 1203 } | 1195 } |
| 1204 sk_sp<SkData> fontData(handle_type1_stream(rawFontData.get(), &header, | 1196 sk_sp<SkData> fontData(handle_type1_stream(rawFontData.get(), &header, |
| 1205 &data, &trailer)); | 1197 &data, &trailer)); |
| 1206 if (fontData.get() == nullptr) { | 1198 if (fontData.get() == nullptr) { |
| 1207 return false; | 1199 return false; |
| 1208 } | 1200 } |
| 1209 SkASSERT(this->canEmbed()); | 1201 SkASSERT(this->canEmbed()); |
| 1210 auto fontStream = sk_make_sp<SkPDFStream>(fontData.get()); | 1202 auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData)); |
| 1211 fontStream->insertInt("Length1", header); | 1203 fontStream->insertInt("Length1", header); |
| 1212 fontStream->insertInt("Length2", data); | 1204 fontStream->insertInt("Length2", data); |
| 1213 fontStream->insertInt("Length3", trailer); | 1205 fontStream->insertInt("Length3", trailer); |
| 1214 descriptor->insertObjRef("FontFile", std::move(fontStream)); | 1206 descriptor->insertObjRef("FontFile", std::move(fontStream)); |
| 1215 | 1207 |
| 1216 this->insertObjRef("FontDescriptor", std::move(descriptor)); | 1208 this->insertObjRef("FontDescriptor", std::move(descriptor)); |
| 1217 | 1209 |
| 1218 return addCommonFontDescriptorEntries(defaultWidth); | 1210 return addCommonFontDescriptorEntries(defaultWidth); |
| 1219 } | 1211 } |
| 1220 | 1212 |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 } | 1407 } |
| 1416 return *canon->fCanEmbedTypeface.set(id, canEmbed); | 1408 return *canon->fCanEmbedTypeface.set(id, canEmbed); |
| 1417 } | 1409 } |
| 1418 | 1410 |
| 1419 void SkPDFFont::drop() { | 1411 void SkPDFFont::drop() { |
| 1420 fTypeface = nullptr; | 1412 fTypeface = nullptr; |
| 1421 fFontInfo = nullptr; | 1413 fFontInfo = nullptr; |
| 1422 fDescriptor = nullptr; | 1414 fDescriptor = nullptr; |
| 1423 this->SkPDFDict::drop(); | 1415 this->SkPDFDict::drop(); |
| 1424 } | 1416 } |
| OLD | NEW |