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

Side by Side Diff: src/pdf/SkPDFDevice.cpp

Issue 2327953002: SkPDF: refactor & code cleanup ahead of https://crrev.com/2322403002 (Closed)
Patch Set: comments Created 4 years, 3 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/SkPDFDevice.h ('k') | src/pdf/SkPDFFont.h » ('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 "SkPDFDevice.h" 8 #include "SkPDFDevice.h"
9 9
10 #include "SkAnnotationKeys.h" 10 #include "SkAnnotationKeys.h"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 result.setStrokeWidth(width); 78 result.setStrokeWidth(width);
79 } 79 }
80 return result; 80 return result;
81 } 81 }
82 82
83 SkPDFDevice::GraphicStateEntry::GraphicStateEntry() 83 SkPDFDevice::GraphicStateEntry::GraphicStateEntry()
84 : fColor(SK_ColorBLACK) 84 : fColor(SK_ColorBLACK)
85 , fTextScaleX(SK_Scalar1) 85 , fTextScaleX(SK_Scalar1)
86 , fTextFill(SkPaint::kFill_Style) 86 , fTextFill(SkPaint::kFill_Style)
87 , fShaderIndex(-1) 87 , fShaderIndex(-1)
88 , fGraphicStateIndex(-1) 88 , fGraphicStateIndex(-1) {
89 , fFont(nullptr)
90 , fTextSize(SK_ScalarNaN) {
91 fMatrix.reset(); 89 fMatrix.reset();
92 } 90 }
93 91
94 bool SkPDFDevice::GraphicStateEntry::compareInitialState( 92 bool SkPDFDevice::GraphicStateEntry::compareInitialState(
95 const GraphicStateEntry& cur) { 93 const GraphicStateEntry& cur) {
96 return fColor == cur.fColor && 94 return fColor == cur.fColor &&
97 fShaderIndex == cur.fShaderIndex && 95 fShaderIndex == cur.fShaderIndex &&
98 fGraphicStateIndex == cur.fGraphicStateIndex && 96 fGraphicStateIndex == cur.fGraphicStateIndex &&
99 fMatrix == cur.fMatrix && 97 fMatrix == cur.fMatrix &&
100 fClipStack == cur.fClipStack && 98 fClipStack == cur.fClipStack &&
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 852
855 namespace { 853 namespace {
856 class GlyphPositioner { 854 class GlyphPositioner {
857 public: 855 public:
858 GlyphPositioner(SkDynamicMemoryWStream* content, 856 GlyphPositioner(SkDynamicMemoryWStream* content,
859 SkScalar textSkewX, 857 SkScalar textSkewX,
860 bool wideChars, 858 bool wideChars,
861 bool defaultPositioning, 859 bool defaultPositioning,
862 SkPoint origin) 860 SkPoint origin)
863 : fContent(content) 861 : fContent(content)
864 , fCurrentMatrixOrigin{0.0f, 0.0f} 862 , fCurrentMatrixOrigin(origin)
865 , fXAdvance(0.0f) 863 , fTextSkewX(textSkewX)
866 , fWideChars(wideChars) 864 , fWideChars(wideChars)
867 , fInText(false)
868 , fDefaultPositioning(defaultPositioning) { 865 , fDefaultPositioning(defaultPositioning) {
869 // Flip the text about the x-axis to account for origin swap and include
870 // the passed parameters.
871 fContent->writeText("1 0 ");
872 SkPDFUtils::AppendScalar(0 - textSkewX, fContent);
873 fContent->writeText(" -1 ");
874 SkPDFUtils::AppendScalar(origin.x(), fContent);
875 fContent->writeText(" ");
876 SkPDFUtils::AppendScalar(origin.y(), fContent);
877 fContent->writeText(" Tm\n");
878 } 866 }
879 ~GlyphPositioner() { this->flush(); } 867 ~GlyphPositioner() { this->flush(); }
880 void flush() { 868 void flush() {
881 if (fInText) { 869 if (fInText) {
882 fContent->writeText("> Tj\n"); 870 fContent->writeText("> Tj\n");
883 fInText = false; 871 fInText = false;
884 } 872 }
885 } 873 }
886 void setWideChars(bool wideChars) {
887 if (fWideChars != wideChars) {
888 SkASSERT(!fInText);
889 SkASSERT(fWideChars == wideChars);
890 fWideChars = wideChars;
891 }
892 }
893 void writeGlyph(SkPoint xy, 874 void writeGlyph(SkPoint xy,
894 SkScalar advanceWidth, 875 SkScalar advanceWidth,
895 uint16_t glyph) { 876 uint16_t glyph) {
877 if (!fInitialized) {
878 // Flip the text about the x-axis to account for origin swap and inc lude
879 // the passed parameters.
880 fContent->writeText("1 0 ");
881 SkPDFUtils::AppendScalar(-fTextSkewX, fContent);
882 fContent->writeText(" -1 ");
883 SkPDFUtils::AppendScalar(fCurrentMatrixOrigin.x(), fContent);
884 fContent->writeText(" ");
885 SkPDFUtils::AppendScalar(fCurrentMatrixOrigin.y(), fContent);
886 fContent->writeText(" Tm\n");
887 fCurrentMatrixOrigin.set(0.0f, 0.0f);
888 fInitialized = true;
889 }
896 if (!fDefaultPositioning) { 890 if (!fDefaultPositioning) {
897 SkPoint position = xy - fCurrentMatrixOrigin; 891 SkPoint position = xy - fCurrentMatrixOrigin;
898 if (position != SkPoint{fXAdvance, 0}) { 892 if (position != SkPoint{fXAdvance, 0}) {
899 this->flush(); 893 this->flush();
900 SkPDFUtils::AppendScalar(position.x(), fContent); 894 SkPDFUtils::AppendScalar(position.x(), fContent);
901 fContent->writeText(" "); 895 fContent->writeText(" ");
902 SkPDFUtils::AppendScalar(-position.y(), fContent); 896 SkPDFUtils::AppendScalar(-position.y(), fContent);
903 fContent->writeText(" Td "); 897 fContent->writeText(" Td ");
904 fCurrentMatrixOrigin = xy; 898 fCurrentMatrixOrigin = xy;
905 fXAdvance = 0; 899 fXAdvance = 0;
906 } 900 }
907 fXAdvance += advanceWidth; 901 fXAdvance += advanceWidth;
908 } 902 }
909 if (!fInText) { 903 if (!fInText) {
910 fContent->writeText("<"); 904 fContent->writeText("<");
911 fInText = true; 905 fInText = true;
912 } 906 }
913 if (fWideChars) { 907 if (fWideChars) {
914 SkPDFUtils::WriteUInt16BE(fContent, glyph); 908 SkPDFUtils::WriteUInt16BE(fContent, glyph);
915 } else { 909 } else {
916 SkASSERT(0 == glyph >> 8); 910 SkASSERT(0 == glyph >> 8);
917 SkPDFUtils::WriteUInt8(fContent, static_cast<uint8_t>(glyph)); 911 SkPDFUtils::WriteUInt8(fContent, static_cast<uint8_t>(glyph));
918 } 912 }
919 } 913 }
920 914
921 private: 915 private:
922 SkDynamicMemoryWStream* fContent; 916 SkDynamicMemoryWStream* fContent;
923 SkPoint fCurrentMatrixOrigin; 917 SkPoint fCurrentMatrixOrigin;
924 SkScalar fXAdvance; 918 SkScalar fXAdvance = 0.0f;
919 SkScalar fTextSkewX;
925 bool fWideChars; 920 bool fWideChars;
926 bool fInText; 921 bool fInText = false;
922 bool fInitialized = false;
927 const bool fDefaultPositioning; 923 const bool fDefaultPositioning;
928 }; 924 };
929 } // namespace 925 } // namespace
930 926
931 static void draw_transparent_text(SkPDFDevice* device, 927 static void draw_transparent_text(SkPDFDevice* device,
932 const SkDraw& d, 928 const SkDraw& d,
933 const void* text, size_t len, 929 const void* text, size_t len,
934 SkScalar x, SkScalar y, 930 SkScalar x, SkScalar y,
935 const SkPaint& srcPaint) { 931 const SkPaint& srcPaint) {
936 sk_sp<SkTypeface> defaultFace = SkTypeface::MakeDefault(); 932 sk_sp<SkTypeface> defaultFace = SkTypeface::MakeDefault();
(...skipping 25 matching lines...) Expand all
962 case SkPaint::kUTF16_TextEncoding: 958 case SkPaint::kUTF16_TextEncoding:
963 case SkPaint::kUTF32_TextEncoding: 959 case SkPaint::kUTF32_TextEncoding:
964 transparent.setTextEncoding(srcPaint.getTextEncoding()); 960 transparent.setTextEncoding(srcPaint.getTextEncoding());
965 device->drawText(d, text, len, x, y, transparent); 961 device->drawText(d, text, len, x, y, transparent);
966 break; 962 break;
967 default: 963 default:
968 SkFAIL("unknown text encoding"); 964 SkFAIL("unknown text encoding");
969 } 965 }
970 } 966 }
971 967
968 static void update_font(SkWStream* wStream, int fontIndex, SkScalar textSize) {
969 wStream->writeText("/");
970 char prefix = SkPDFResourceDict::GetResourceTypePrefix(SkPDFResourceDict::kF ont_ResourceType);
971 wStream->write(&prefix, 1);
972 wStream->writeDecAsText(fontIndex);
973 wStream->writeText(" ");
974 SkPDFUtils::AppendScalar(textSize, wStream);
975 wStream->writeText(" Tf\n");
976 }
977
972 void SkPDFDevice::internalDrawText( 978 void SkPDFDevice::internalDrawText(
973 const SkDraw& d, const void* sourceText, size_t sourceByteCount, 979 const SkDraw& d, const void* sourceText, size_t sourceByteCount,
974 const SkScalar pos[], SkTextBlob::GlyphPositioning positioning, 980 const SkScalar pos[], SkTextBlob::GlyphPositioning positioning,
975 SkPoint offset, const SkPaint& srcPaint, const uint32_t* clusters, 981 SkPoint offset, const SkPaint& srcPaint, const uint32_t* clusters,
976 uint32_t textByteLength, const char* utf8Text) { 982 uint32_t textByteLength, const char* utf8Text) {
977 NOT_IMPLEMENTED(srcPaint.getMaskFilter() != nullptr, false); 983 NOT_IMPLEMENTED(srcPaint.getMaskFilter() != nullptr, false);
978 if (srcPaint.getMaskFilter() != nullptr) { 984 if (srcPaint.getMaskFilter() != nullptr) {
979 // Don't pretend we support drawing MaskFilters, it makes for artifacts 985 // Don't pretend we support drawing MaskFilters, it makes for artifacts
980 // making text unreadable (e.g. same text twice when using CSS shadows). 986 // making text unreadable (e.g. same text twice when using CSS shadows).
981 return; 987 return;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 } 1066 }
1061 offset.offset(alignmentFactor * advance, 0); 1067 offset.offset(alignmentFactor * advance, 0);
1062 } 1068 }
1063 ScopedContentEntry content(this, d, paint, true); 1069 ScopedContentEntry content(this, d, paint, true);
1064 if (!content.entry()) { 1070 if (!content.entry()) {
1065 return; 1071 return;
1066 } 1072 }
1067 SkDynamicMemoryWStream* out = &content.entry()->fContent; 1073 SkDynamicMemoryWStream* out = &content.entry()->fContent;
1068 SkScalar textSize = paint.getTextSize(); 1074 SkScalar textSize = paint.getTextSize();
1069 1075
1070 int index = 0;
1071 while (glyphs[index] > maxGlyphID) { // Invalid glyphID for this font.
1072 ++index; // Skip this glyphID
1073 if (index == glyphCount) {
1074 return; // all glyphIDs were bad.
1075 }
1076 }
1077
1078 out->writeText("BT\n"); 1076 out->writeText("BT\n");
1079 SK_AT_SCOPE_EXIT(out->writeText("ET\n")); 1077 SK_AT_SCOPE_EXIT(out->writeText("ET\n"));
1080 1078
1081 SkPDFFont* font = this->updateFont( 1079 bool multiByteGlyphs = SkPDFFont::IsMultiByte(SkPDFFont::FontType(*metrics)) ;
1082 typeface, textSize, glyphs[index], content.entry());
1083 SkASSERT(font); // All preconditions for SkPDFFont::GetFontResource are met .
1084 if (!font) { return; }
1085
1086 GlyphPositioner glyphPositioner(out, 1080 GlyphPositioner glyphPositioner(out,
1087 paint.getTextSkewX(), 1081 paint.getTextSkewX(),
1088 font->multiByteGlyphs(), 1082 multiByteGlyphs,
1089 defaultPositioning, 1083 defaultPositioning,
1090 offset); 1084 offset);
1091 1085 SkPDFFont* font = nullptr;
1092 while (index < glyphCount) { 1086 for (int index = 0; index < glyphCount; ++index) {
1093 int stretch = font->countStretch(&glyphs[index], glyphCount - index, max GlyphID); 1087 SkGlyphID gid = glyphs[index];
1094 SkASSERT(index + stretch <= glyphCount); 1088 if (gid > maxGlyphID) {
1095 if (stretch < 1) { 1089 continue; // Skip this invalid glyphID.
1096 // The current pdf font cannot encode the next glyph. 1090 }
1097 // Try to get a pdf font which can encode the next glyph. 1091 if (!font || !font->hasGlyph(gid)) {
1092 // Either this is the first loop iteration or the current
1093 // PDFFont cannot encode this glyph.
1098 glyphPositioner.flush(); 1094 glyphPositioner.flush();
1099 // first, validate the next glyph 1095 // Try to get a font which can encode the glyph.
1100 while (glyphs[index] > maxGlyphID) { 1096 int fontIndex = this->getFontResourceIndex(typeface, gid);
1101 ++index; // Skip this glyphID 1097 SkASSERT(fontIndex >= 0);
1102 if (index == glyphCount) { 1098 if (fontIndex < 0) { return; }
1103 return; // all remainng glyphIDs were bad. 1099 update_font(out, fontIndex, textSize);
1104 } 1100 font = fFontResources[fontIndex];
1105 } 1101 SkASSERT(font); // All preconditions for SkPDFFont::GetFontResource are met.
1106 SkASSERT(index < glyphCount);
1107 font = this->updateFont(typeface, textSize, glyphs[index], content.e ntry());
1108 SkASSERT(font); // preconditions for SkPDFFont::GetFontResource met .
1109 if (!font) { return; } 1102 if (!font) { return; }
1110 glyphPositioner.setWideChars(font->multiByteGlyphs()); 1103 SkASSERT(font->multiByteGlyphs() == multiByteGlyphs);
1111 // Get stretch for this new font. 1104 }
1112 stretch = font->countStretch(&glyphs[index], glyphCount - index, max GlyphID); 1105 font->noteGlyphUsage(gid);
1113 if (stretch < 1) { 1106 SkScalar advance{0.0f};
1114 SkDEBUGFAIL("PDF could not encode glyph."); 1107 SkPoint xy{0.0f, 0.0f};
1115 return; 1108 if (!defaultPositioning) {
1109 advance = glyphCache->getGlyphIDAdvance(gid).fAdvanceX;
1110 xy = SkTextBlob::kFull_Positioning == positioning
1111 ? SkPoint{pos[2 * index], pos[2 * index + 1]}
1112 : SkPoint{pos[index], 0};
1113 if (alignment != SkPaint::kLeft_Align) {
1114 xy.offset(alignmentFactor * advance, 0);
1116 } 1115 }
1117 } 1116 }
1118 while (stretch-- > 0) { 1117 SkGlyphID encodedGlyph =
1119 SkGlyphID gid = glyphs[index]; 1118 multiByteGlyphs ? gid : font->glyphToPDFFontEncoding(gid);
1120 if (gid <= maxGlyphID) { 1119 glyphPositioner.writeGlyph(xy, advance, encodedGlyph);
1121 font->noteGlyphUsage(gid);
1122 SkGlyphID encodedGlyph = font->glyphToPDFFontEncoding(gid);
1123 if (defaultPositioning) {
1124 glyphPositioner.writeGlyph(SkPoint{0, 0}, 0, encodedGlyph);
1125 } else {
1126 SkScalar advance = glyphCache->getGlyphIDAdvance(gid).fAdvan ceX;
1127 SkPoint xy = SkTextBlob::kFull_Positioning == positioning
1128 ? SkPoint{pos[2 * index], pos[2 * index + 1]}
1129 : SkPoint{pos[index], 0};
1130 if (alignment != SkPaint::kLeft_Align) {
1131 xy.offset(alignmentFactor * advance, 0);
1132 }
1133 glyphPositioner.writeGlyph(xy, advance, encodedGlyph);
1134 }
1135 }
1136 ++index;
1137 }
1138 } 1120 }
1139 } 1121 }
1140 1122
1141 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, 1123 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
1142 SkScalar x, SkScalar y, const SkPaint& paint) { 1124 SkScalar x, SkScalar y, const SkPaint& paint) {
1143 this->internalDrawText(d, text, len, nullptr, SkTextBlob::kDefault_Positioni ng, 1125 this->internalDrawText(d, text, len, nullptr, SkTextBlob::kDefault_Positioni ng,
1144 SkPoint{x, y}, paint, nullptr, 0, nullptr); 1126 SkPoint{x, y}, paint, nullptr, 0, nullptr);
1145 } 1127 }
1146 1128
1147 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, 1129 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
1830 // Assumes that xobject has been canonicalized (so we can directly compare 1812 // Assumes that xobject has been canonicalized (so we can directly compare
1831 // pointers). 1813 // pointers).
1832 int result = fXObjectResources.find(xObject); 1814 int result = fXObjectResources.find(xObject);
1833 if (result < 0) { 1815 if (result < 0) {
1834 result = fXObjectResources.count(); 1816 result = fXObjectResources.count();
1835 fXObjectResources.push(SkRef(xObject)); 1817 fXObjectResources.push(SkRef(xObject));
1836 } 1818 }
1837 return result; 1819 return result;
1838 } 1820 }
1839 1821
1840 SkPDFFont* SkPDFDevice::updateFont(SkTypeface* typeface,
1841 SkScalar textSize,
1842 uint16_t glyphID,
1843 SkPDFDevice::ContentEntry* contentEntry) {
1844 if (contentEntry->fState.fFont == nullptr ||
1845 contentEntry->fState.fTextSize != textSize ||
1846 !contentEntry->fState.fFont->hasGlyph(glyphID)) {
1847 int fontIndex = getFontResourceIndex(typeface, glyphID);
1848 if (fontIndex < 0) {
1849 SkDebugf("SkPDF: Font error.");
1850 return nullptr;
1851 }
1852 contentEntry->fContent.writeText("/");
1853 contentEntry->fContent.writeText(SkPDFResourceDict::getResourceName(
1854 SkPDFResourceDict::kFont_ResourceType,
1855 fontIndex).c_str());
1856 contentEntry->fContent.writeText(" ");
1857 SkPDFUtils::AppendScalar(textSize, &contentEntry->fContent);
1858 contentEntry->fContent.writeText(" Tf\n");
1859 contentEntry->fState.fFont = fFontResources[fontIndex];
1860 }
1861 return contentEntry->fState.fFont;
1862 }
1863
1864 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) { 1822 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
1865 sk_sp<SkPDFFont> newFont( 1823 sk_sp<SkPDFFont> newFont(
1866 SkPDFFont::GetFontResource(fDocument->canon(), typeface, glyphID)); 1824 SkPDFFont::GetFontResource(fDocument->canon(), typeface, glyphID));
1867 if (!newFont) { 1825 if (!newFont) {
1868 return -1; 1826 return -1;
1869 } 1827 }
1870 int resourceIndex = fFontResources.find(newFont.get()); 1828 int resourceIndex = fFontResources.find(newFont.get());
1871 if (resourceIndex < 0) { 1829 if (resourceIndex < 0) {
1872 fDocument->registerFont(newFont.get()); 1830 fDocument->registerFont(newFont.get());
1873 resourceIndex = fFontResources.count(); 1831 resourceIndex = fFontResources.count();
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
2081 } 2039 }
2082 2040
2083 sk_sp<SkSpecialImage> SkPDFDevice::makeSpecial(const SkImage* image) { 2041 sk_sp<SkSpecialImage> SkPDFDevice::makeSpecial(const SkImage* image) {
2084 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(image->width(), image-> height()), 2042 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(image->width(), image-> height()),
2085 image->makeNonTextureImage()); 2043 image->makeNonTextureImage());
2086 } 2044 }
2087 2045
2088 sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() { 2046 sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() {
2089 return nullptr; 2047 return nullptr;
2090 } 2048 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFDevice.h ('k') | src/pdf/SkPDFFont.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698