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

Side by Side 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, 4 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 unified diff | Download patch
« no previous file with comments | « src/pdf/SkPDFDocument.cpp ('k') | src/pdf/SkPDFGraphicState.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« 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