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

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) 14:24:06 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) 591 #ifdef SK_SFNTLY_SUBSETTER
592 static void sk_delete_array(const void* ptr, void*) { 592 // if possible, make no copy.
593 // Use C-style cast to cast away const and cast type simultaneously. 593 static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) {
594 delete[] (unsigned char*)ptr; 594 SkASSERT(stream);
595 (void)stream->rewind();
596 SkASSERT(stream->hasLength());
597 size_t size = stream->getLength();
598 if (const void* base = stream->getMemoryBase()) {
599 SkData::ReleaseProc proc =
600 [](const void*, void* ctx) { delete (SkStream*)ctx; };
601 return SkData::MakeWithProc(base, size, proc, stream.release());
602 }
603 return SkData::MakeFromStream(stream.get(), size);
595 } 604 }
596 #endif 605 #endif
597 606
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 /////////////////////////////////////////////////////////////////////////////// 607 ///////////////////////////////////////////////////////////////////////////////
649 // class SkPDFGlyphSet 608 // class SkPDFGlyphSet
650 /////////////////////////////////////////////////////////////////////////////// 609 ///////////////////////////////////////////////////////////////////////////////
651 610
652 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { 611 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) {
653 } 612 }
654 613
655 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { 614 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) {
656 for (int i = 0; i < numGlyphs; ++i) { 615 for (int i = 0; i < numGlyphs; ++i) {
657 fBitSet.setBit(glyphIDs[i], true); 616 fBitSet.setBit(glyphIDs[i], true);
658 } 617 }
659 } 618 }
660 619
661 bool SkPDFGlyphSet::has(uint16_t glyphID) const { 620 bool SkPDFGlyphSet::has(uint16_t glyphID) const {
662 return fBitSet.isBitSet(glyphID); 621 return fBitSet.isBitSet(glyphID);
663 } 622 }
664 623
665 void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const { 624 void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const {
666 fBitSet.exportTo(glyphIDs); 625 fBitSet.exportTo(glyphIDs);
667 } 626 }
668 627
669 /////////////////////////////////////////////////////////////////////////////// 628 ///////////////////////////////////////////////////////////////////////////////
670 // class SkPDFGlyphSetMap 629 // class SkPDFGlyphSetMap
671 /////////////////////////////////////////////////////////////////////////////// 630 ///////////////////////////////////////////////////////////////////////////////
672 631
673 SkPDFGlyphSetMap::SkPDFGlyphSetMap() {} 632 SkPDFGlyphSetMap::SkPDFGlyphSetMap() {}
674 633
675 SkPDFGlyphSetMap::~SkPDFGlyphSetMap() { 634 SkPDFGlyphSetMap::~SkPDFGlyphSetMap() {
676 fMap.reset(); 635 fMap.reset();
677 } 636 }
678 637
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); 979 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
1021 setFontDescriptor(descriptor.get()); 980 setFontDescriptor(descriptor.get());
1022 if (!addCommonFontDescriptorEntries(defaultWidth)) { 981 if (!addCommonFontDescriptorEntries(defaultWidth)) {
1023 this->insertObjRef("FontDescriptor", std::move(descriptor)); 982 this->insertObjRef("FontDescriptor", std::move(descriptor));
1024 return false; 983 return false;
1025 } 984 }
1026 SkASSERT(this->canEmbed()); 985 SkASSERT(this->canEmbed());
1027 986
1028 switch (getType()) { 987 switch (getType()) {
1029 case SkAdvancedTypefaceMetrics::kTrueType_Font: { 988 case SkAdvancedTypefaceMetrics::kTrueType_Font: {
1030 size_t fontSize = 0; 989 int ttcIndex;
1031 #if defined(SK_SFNTLY_SUBSETTER) 990 std::unique_ptr<SkStreamAsset> fontAsset(
1032 if (this->canSubset()) { 991 this->typeface()->openStream(&ttcIndex));
1033 sk_sp<SkPDFStream> fontStream; 992 SkASSERT(fontAsset);
1034 SkPDFStream* rawStream = nullptr; 993 if (!fontAsset) {
1035 fontSize = get_subset_font_stream(fontInfo()->fFontName.c_str(), 994 return false;
1036 typeface(), 995 }
1037 *subset, 996 size_t fontSize = fontAsset->getLength();
1038 &rawStream); 997 SkASSERT(fontSize > 0);
1039 if (0 == fontSize) { 998 if (fontSize == 0) {
1040 return false; 999 return false;
1041 } 1000 }
1042 if (rawStream) { 1001
1043 fontStream.reset(rawStream); 1002 #ifdef SK_SFNTLY_SUBSETTER
1044 fontStream->insertInt("Length1", fontSize); 1003 if (this->canSubset() && subset) {
1045 descriptor->insertObjRef("FontFile2", std::move(fontStream)) ; 1004 sk_sp<SkData> fontData(stream_to_data(std::move(fontAsset)));
1005 unsigned char* subsetFont = nullptr;
1006 // sfntly requires unsigned int* to be passed in,
1007 // as far as we know, unsigned int is equivalent
1008 // to uint32_t on all platforms.
1009 static_assert(sizeof(unsigned) == sizeof(uint32_t), "");
1010 const char* fontName = fontInfo()->fFontName.c_str();
1011 // TODO(halcanary): Use ttcIndex, not fontName.
1012 int subsetFontSize =
1013 SfntlyWrapper::SubsetFont(fontName,
1014 fontData->bytes(),
1015 fontSize,
1016 subset->begin(),
1017 subset->count(),
1018 &subsetFont);
1019 SkASSERT(subsetFontSize > 0 || subsetFont == nullptr);
1020 if (subsetFontSize > 0) {
1021 SkASSERT(subsetFont != nullptr);
1022 auto subset = sk_make_sp<SkPDFStream>(
1023 SkData::MakeWithProc(
1024 subsetFont, subsetFontSize,
1025 [](const void* p, void*) {
1026 delete[] (unsigned char*)p;
1027 }, nullptr));
1028 subset->insertInt("Length1", subsetFontSize);
1029 descriptor->insertObjRef("FontFile2", std::move(subset));
1046 break; 1030 break;
1047 } 1031 }
1032 // If subsetting fails, fall back to original font data.
1033 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
1048 } 1034 }
1049 #endif 1035 #endif // SK_SFNTLY_SUBSETTER
1050 sk_sp<SkPDFSharedStream> fontStream; 1036 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); 1037 fontStream->dict()->insertInt("Length1", fontSize);
1061 descriptor->insertObjRef("FontFile2", std::move(fontStream)); 1038 descriptor->insertObjRef("FontFile2", std::move(fontStream));
1062 break; 1039 break;
1063 } 1040 }
1064 case SkAdvancedTypefaceMetrics::kCFF_Font: 1041 case SkAdvancedTypefaceMetrics::kCFF_Font:
1065 case SkAdvancedTypefaceMetrics::kType1CID_Font: { 1042 case SkAdvancedTypefaceMetrics::kType1CID_Font: {
1066 std::unique_ptr<SkStreamAsset> fontData( 1043 std::unique_ptr<SkStreamAsset> fontData(
1067 this->typeface()->openStream(nullptr)); 1044 this->typeface()->openStream(nullptr));
1068 SkASSERT(fontData); 1045 SkASSERT(fontData);
1069 SkASSERT(fontData->getLength() > 0); 1046 SkASSERT(fontData->getLength() > 0);
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1200 SkASSERT(rawFontData->getLength() > 0); 1177 SkASSERT(rawFontData->getLength() > 0);
1201 if (!rawFontData || 0 == rawFontData->getLength()) { 1178 if (!rawFontData || 0 == rawFontData->getLength()) {
1202 return false; 1179 return false;
1203 } 1180 }
1204 sk_sp<SkData> fontData(handle_type1_stream(rawFontData.get(), &header, 1181 sk_sp<SkData> fontData(handle_type1_stream(rawFontData.get(), &header,
1205 &data, &trailer)); 1182 &data, &trailer));
1206 if (fontData.get() == nullptr) { 1183 if (fontData.get() == nullptr) {
1207 return false; 1184 return false;
1208 } 1185 }
1209 SkASSERT(this->canEmbed()); 1186 SkASSERT(this->canEmbed());
1210 auto fontStream = sk_make_sp<SkPDFStream>(fontData.get()); 1187 auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData));
1211 fontStream->insertInt("Length1", header); 1188 fontStream->insertInt("Length1", header);
1212 fontStream->insertInt("Length2", data); 1189 fontStream->insertInt("Length2", data);
1213 fontStream->insertInt("Length3", trailer); 1190 fontStream->insertInt("Length3", trailer);
1214 descriptor->insertObjRef("FontFile", std::move(fontStream)); 1191 descriptor->insertObjRef("FontFile", std::move(fontStream));
1215 1192
1216 this->insertObjRef("FontDescriptor", std::move(descriptor)); 1193 this->insertObjRef("FontDescriptor", std::move(descriptor));
1217 1194
1218 return addCommonFontDescriptorEntries(defaultWidth); 1195 return addCommonFontDescriptorEntries(defaultWidth);
1219 } 1196 }
1220 1197
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 } 1392 }
1416 return *canon->fCanEmbedTypeface.set(id, canEmbed); 1393 return *canon->fCanEmbedTypeface.set(id, canEmbed);
1417 } 1394 }
1418 1395
1419 void SkPDFFont::drop() { 1396 void SkPDFFont::drop() {
1420 fTypeface = nullptr; 1397 fTypeface = nullptr;
1421 fFontInfo = nullptr; 1398 fFontInfo = nullptr;
1422 fDescriptor = nullptr; 1399 fDescriptor = nullptr;
1423 this->SkPDFDict::drop(); 1400 this->SkPDFDict::drop();
1424 } 1401 }
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