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

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

Issue 2248923002: Revert of SkPDF: unify drawText and drawPosText (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 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/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 #include "SkAnnotationKeys.h" 9 #include "SkAnnotationKeys.h"
10 #include "SkBitmapDevice.h" 10 #include "SkBitmapDevice.h"
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 if (result.getStyle() == SkPaint::kFill_Style) { 69 if (result.getStyle() == SkPaint::kFill_Style) {
70 result.setStyle(SkPaint::kStrokeAndFill_Style); 70 result.setStyle(SkPaint::kStrokeAndFill_Style);
71 } else { 71 } else {
72 width += result.getStrokeWidth(); 72 width += result.getStrokeWidth();
73 } 73 }
74 result.setStrokeWidth(width); 74 result.setStrokeWidth(width);
75 } 75 }
76 return result; 76 return result;
77 } 77 }
78 78
79 // Stolen from measure_text in SkDraw.cpp and then tweaked.
80 static void align_text(const SkPaint& paint,
81 const uint16_t* glyphs, size_t len,
82 SkScalar* x, SkScalar* y) {
83 if (paint.getTextAlign() == SkPaint::kLeft_Align) {
84 return;
85 }
86 SkScalar advance = paint.measureText(glyphs, len * sizeof(uint16_t));
87 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
88 advance *= 0.5f;
89 }
90 if (paint.isVerticalText()) {
91 *y -= advance;
92 } else {
93 *x -= advance;
94 }
95 }
96
97 static int max_glyphid_for_typeface(SkTypeface* typeface) {
98 SkAutoResolveDefaultTypeface autoResolve(typeface);
99 typeface = autoResolve.get();
100 return typeface->countGlyphs() - 1;
101 }
102
103 typedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage;
104
105 static int force_glyph_encoding(const SkPaint& paint, const void* text,
106 size_t len, SkGlyphStorage* storage,
107 const uint16_t** glyphIDs) {
108 // Make sure we have a glyph id encoding.
109 if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
110 int numGlyphs = paint.textToGlyphs(text, len, nullptr);
111 storage->reset(numGlyphs);
112 paint.textToGlyphs(text, len, storage->get());
113 *glyphIDs = storage->get();
114 return numGlyphs;
115 }
116
117 // For user supplied glyph ids we need to validate them.
118 SkASSERT((len & 1) == 0);
119 int numGlyphs = SkToInt(len / 2);
120 const uint16_t* input = static_cast<const uint16_t*>(text);
121
122 int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface());
123 int validated;
124 for (validated = 0; validated < numGlyphs; ++validated) {
125 if (input[validated] > maxGlyphID) {
126 break;
127 }
128 }
129 if (validated >= numGlyphs) {
130 *glyphIDs = static_cast<const uint16_t*>(text);
131 return numGlyphs;
132 }
133
134 // Silently drop anything out of range.
135 storage->reset(numGlyphs);
136 if (validated > 0) {
137 memcpy(storage->get(), input, validated * sizeof(uint16_t));
138 }
139
140 for (int i = validated; i < numGlyphs; ++i) {
141 storage->get()[i] = input[i];
142 if (input[i] > maxGlyphID) {
143 storage->get()[i] = 0;
144 }
145 }
146 *glyphIDs = storage->get();
147 return numGlyphs;
148 }
149
79 static void set_text_transform(SkScalar x, SkScalar y, SkScalar textSkewX, 150 static void set_text_transform(SkScalar x, SkScalar y, SkScalar textSkewX,
80 SkWStream* content) { 151 SkWStream* content) {
81 // Flip the text about the x-axis to account for origin swap and include 152 // Flip the text about the x-axis to account for origin swap and include
82 // the passed parameters. 153 // the passed parameters.
83 content->writeText("1 0 "); 154 content->writeText("1 0 ");
84 SkPDFUtils::AppendScalar(0 - textSkewX, content); 155 SkPDFUtils::AppendScalar(0 - textSkewX, content);
85 content->writeText(" -1 "); 156 content->writeText(" -1 ");
86 SkPDFUtils::AppendScalar(x, content); 157 SkPDFUtils::AppendScalar(x, content);
87 content->writeText(" "); 158 content->writeText(" ");
88 SkPDFUtils::AppendScalar(y, content); 159 SkPDFUtils::AppendScalar(y, content);
(...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 1020
950 void SkPDFDevice::drawImageRect(const SkDraw& draw, 1021 void SkPDFDevice::drawImageRect(const SkDraw& draw,
951 const SkImage* image, 1022 const SkImage* image,
952 const SkRect* src, 1023 const SkRect* src,
953 const SkRect& dst, 1024 const SkRect& dst,
954 const SkPaint& srcPaint, 1025 const SkPaint& srcPaint,
955 SkCanvas::SrcRectConstraint constraint) { 1026 SkCanvas::SrcRectConstraint constraint) {
956 SkASSERT(false); 1027 SkASSERT(false);
957 } 1028 }
958 1029
1030 // Create a PDF string. Maximum length (in bytes) is 65,535.
1031 // @param input A string value.
1032 // @param len The length of the input array.
1033 // @param wideChars True iff the upper byte in each uint16_t is
1034 // significant and should be encoded and not
1035 // discarded. If true, the upper byte is encoded
1036 // first. Otherwise, we assert the upper byte is
1037 // zero.
1038 static void write_wide_string(SkDynamicMemoryWStream* wStream,
1039 const uint16_t* input,
1040 size_t len,
1041 bool wideChars) {
1042 if (wideChars) {
1043 SkASSERT(2 * len < 65535);
1044 wStream->writeText("<");
1045 for (size_t i = 0; i < len; i++) {
1046 SkPDFUtils::WriteUInt16BE(wStream, input[i]);
1047 }
1048 wStream->writeText(">");
1049 } else {
1050 SkASSERT(len <= 65535);
1051 SkAutoMalloc buffer(len); // Remove every other byte.
1052 uint8_t* ptr = (uint8_t*)buffer.get();
1053 for (size_t i = 0; i < len; i++) {
1054 SkASSERT(0 == input[i] >> 8);
1055 ptr[i] = static_cast<uint8_t>(input[i]);
1056 }
1057 SkPDFUtils::WriteString(wStream, (char*)buffer.get(), len);
1058 }
1059 }
1060
959 namespace { 1061 namespace {
960 class GlyphPositioner { 1062 class GlyphPositioner {
961 public: 1063 public:
962 GlyphPositioner(SkDynamicMemoryWStream* content, 1064 GlyphPositioner(SkDynamicMemoryWStream* content,
963 SkScalar textSkewX, 1065 SkScalar textSkewX,
964 bool wideChars, 1066 bool wideChars)
965 bool defaultPositioning,
966 SkPoint origin)
967 : fContent(content) 1067 : fContent(content)
968 , fCurrentMatrixX(0.0f) 1068 , fCurrentMatrixX(0.0f)
969 , fCurrentMatrixY(0.0f) 1069 , fCurrentMatrixY(0.0f)
970 , fXAdvance(0.0f) 1070 , fXAdvance(0.0f)
971 , fWideChars(wideChars) 1071 , fWideChars(wideChars)
972 , fInText(false) 1072 , fInText(false) {
973 , fDefaultPositioning(defaultPositioning) { 1073 set_text_transform(0.0f, 0.0f, textSkewX, fContent);
974 set_text_transform(origin.x(), origin.y(), textSkewX, fContent);
975 } 1074 }
976 ~GlyphPositioner() { SkASSERT(!fInText); /* flush first */ } 1075 ~GlyphPositioner() { SkASSERT(!fInText); /* flush first */ }
977 void flush() { 1076 void flush() {
978 if (fInText) { 1077 if (fInText) {
979 fContent->writeText("> Tj\n"); 1078 fContent->writeText("> Tj\n");
980 fInText = false; 1079 fInText = false;
981 } 1080 }
982 } 1081 }
983 void setWideChars(bool wideChars) { 1082 void setWideChars(bool wideChars) {
984 if (fWideChars != wideChars) { 1083 if (fWideChars != wideChars) {
985 SkASSERT(!fInText); 1084 SkASSERT(!fInText);
986 SkASSERT(fWideChars == wideChars);
987 fWideChars = wideChars; 1085 fWideChars = wideChars;
988 } 1086 }
989 } 1087 }
990 void writeGlyph(SkScalar x, 1088 void writeGlyph(SkScalar x,
991 SkScalar y, 1089 SkScalar y,
992 SkScalar advanceWidth, 1090 SkScalar advanceWidth,
993 uint16_t glyph) { 1091 uint16_t glyph) {
994 if (!fDefaultPositioning) { 1092 SkScalar xPosition = x - fCurrentMatrixX;
995 SkScalar xPosition = x - fCurrentMatrixX; 1093 SkScalar yPosition = y - fCurrentMatrixY;
996 SkScalar yPosition = y - fCurrentMatrixY; 1094 if (xPosition != fXAdvance || yPosition != 0) {
997 if (xPosition != fXAdvance || yPosition != 0) { 1095 this->flush();
998 this->flush(); 1096 SkPDFUtils::AppendScalar(xPosition, fContent);
999 SkPDFUtils::AppendScalar(xPosition, fContent); 1097 fContent->writeText(" ");
1000 fContent->writeText(" "); 1098 SkPDFUtils::AppendScalar(-yPosition, fContent);
1001 SkPDFUtils::AppendScalar(-yPosition, fContent); 1099 fContent->writeText(" Td ");
1002 fContent->writeText(" Td "); 1100 fCurrentMatrixX = x;
1003 fCurrentMatrixX = x; 1101 fCurrentMatrixY = y;
1004 fCurrentMatrixY = y; 1102 fXAdvance = 0;
1005 fXAdvance = 0;
1006 }
1007 fXAdvance += advanceWidth;
1008 } 1103 }
1009 if (!fInText) { 1104 if (!fInText) {
1010 fContent->writeText("<"); 1105 fContent->writeText("<");
1011 fInText = true; 1106 fInText = true;
1012 } 1107 }
1013 if (fWideChars) { 1108 if (fWideChars) {
1014 SkPDFUtils::WriteUInt16BE(fContent, glyph); 1109 SkPDFUtils::WriteUInt16BE(fContent, glyph);
1015 } else { 1110 } else {
1016 SkASSERT(0 == glyph >> 8); 1111 SkASSERT(0 == glyph >> 8);
1017 SkPDFUtils::WriteUInt8(fContent, static_cast<uint8_t>(glyph)); 1112 SkPDFUtils::WriteUInt8(fContent, static_cast<uint8_t>(glyph));
1018 } 1113 }
1114 fXAdvance += advanceWidth;
1019 } 1115 }
1020 1116
1021 private: 1117 private:
1022 SkDynamicMemoryWStream* fContent; 1118 SkDynamicMemoryWStream* fContent;
1023 SkScalar fCurrentMatrixX; 1119 SkScalar fCurrentMatrixX;
1024 SkScalar fCurrentMatrixY; 1120 SkScalar fCurrentMatrixY;
1025 SkScalar fXAdvance; 1121 SkScalar fXAdvance;
1026 bool fWideChars; 1122 bool fWideChars;
1027 bool fInText; 1123 bool fInText;
1028 const bool fDefaultPositioning;
1029 }; 1124 };
1030 } // namespace 1125 } // namespace
1031 1126
1032 static void draw_transparent_text(SkPDFDevice* device, 1127 static void draw_transparent_text(SkPDFDevice* device,
1033 const SkDraw& d, 1128 const SkDraw& d,
1034 const void* text, size_t len, 1129 const void* text, size_t len,
1035 SkScalar x, SkScalar y, 1130 SkScalar x, SkScalar y,
1036 const SkPaint& srcPaint) { 1131 const SkPaint& srcPaint) {
1037 1132
1038 SkPaint transparent; 1133 SkPaint transparent;
1039 if (!SkPDFFont::CanEmbedTypeface(transparent.getTypeface(), 1134 if (!SkPDFFont::CanEmbedTypeface(transparent.getTypeface(),
1040 device->getCanon())) { 1135 device->getCanon())) {
1041 SkDEBUGFAIL("default typeface should be embeddable"); 1136 SkDEBUGFAIL("default typeface should be embeddable");
1042 return; // Avoid infinite loop in release. 1137 return; // Avoid infinite loop in release.
1043 } 1138 }
1044 transparent.setTextSize(srcPaint.getTextSize()); 1139 transparent.setTextSize(srcPaint.getTextSize());
1045 transparent.setColor(SK_ColorTRANSPARENT); 1140 transparent.setColor(SK_ColorTRANSPARENT);
1046 switch (srcPaint.getTextEncoding()) { 1141 switch (srcPaint.getTextEncoding()) {
1047 case SkPaint::kGlyphID_TextEncoding: { 1142 case SkPaint::kGlyphID_TextEncoding: {
1048 // Since a glyphId<->Unicode mapping is typeface-specific, 1143 // Since a glyphId<->Unicode mapping is typeface-specific,
1049 // map back to Unicode first. 1144 // map back to Unicode first.
1050 size_t glyphCount = len / 2; 1145 size_t glyphCount = len / 2;
1051 SkAutoTMalloc<SkUnichar> unichars(glyphCount); 1146 SkAutoTMalloc<SkUnichar> unichars(glyphCount);
1052 srcPaint.glyphsToUnichars( 1147 srcPaint.glyphsToUnichars(
1053 (const uint16_t*)text, SkToInt(glyphCount), &unichars[0]); 1148 (const uint16_t*)text, SkToInt(glyphCount), &unichars[0]);
1054 transparent.setTextEncoding(SkPaint::kUTF32_TextEncoding); 1149 transparent.setTextEncoding(SkPaint::kUTF32_TextEncoding);
1055 // TODO(halcanary): deal with case where default typeface
1056 // does not have glyphs for these unicode code points.
1057 device->drawText(d, &unichars[0], 1150 device->drawText(d, &unichars[0],
1058 glyphCount * sizeof(SkUnichar), 1151 glyphCount * sizeof(SkUnichar),
1059 x, y, transparent); 1152 x, y, transparent);
1060 break; 1153 break;
1061 } 1154 }
1062 case SkPaint::kUTF8_TextEncoding: 1155 case SkPaint::kUTF8_TextEncoding:
1063 case SkPaint::kUTF16_TextEncoding: 1156 case SkPaint::kUTF16_TextEncoding:
1064 case SkPaint::kUTF32_TextEncoding: 1157 case SkPaint::kUTF32_TextEncoding:
1065 transparent.setTextEncoding(srcPaint.getTextEncoding()); 1158 transparent.setTextEncoding(srcPaint.getTextEncoding());
1066 device->drawText(d, text, len, x, y, transparent); 1159 device->drawText(d, text, len, x, y, transparent);
1067 break; 1160 break;
1068 default: 1161 default:
1069 SkFAIL("unknown text encoding"); 1162 SkFAIL("unknown text encoding");
1070 } 1163 }
1071 } 1164 }
1072 1165
1073 void SkPDFDevice::internalDrawText( 1166
1074 const SkDraw& d, const void* sourceText, size_t sourceByteCount, 1167 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
1075 const SkScalar pos[], SkTextBlob::GlyphPositioning positioning, 1168 SkScalar x, SkScalar y, const SkPaint& srcPaint) {
1076 SkPoint offset, const SkPaint& srcPaint) { 1169 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fDocument->canon()) ) {
1077 NOT_IMPLEMENTED(srcPaint.getMaskFilter() != nullptr, false); 1170 // https://bug.skia.org/3866
1078 if (srcPaint.getMaskFilter() != nullptr) { 1171 SkPath path;
1172 srcPaint.getTextPath(text, len, x, y, &path);
1173 this->drawPath(d, path, srcPaint, &SkMatrix::I(), true);
1174 // Draw text transparently to make it copyable/searchable/accessable.
1175 draw_transparent_text(this, d, text, len, x, y, srcPaint);
1176 return;
1177 }
1178 SkPaint paint = srcPaint;
1179 replace_srcmode_on_opaque_paint(&paint);
1180
1181 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false);
1182 if (paint.getMaskFilter() != nullptr) {
1079 // Don't pretend we support drawing MaskFilters, it makes for artifacts 1183 // Don't pretend we support drawing MaskFilters, it makes for artifacts
1080 // making text unreadable (e.g. same text twice when using CSS shadows). 1184 // making text unreadable (e.g. same text twice when using CSS shadows).
1081 return; 1185 return;
1082 } 1186 }
1083 SkPaint paint = calculate_text_paint(srcPaint); 1187 SkPaint textPaint = calculate_text_paint(paint);
1084 replace_srcmode_on_opaque_paint(&paint); 1188 ScopedContentEntry content(this, d, textPaint, true);
1085 if (!paint.getTypeface()) {
1086 paint.setTypeface(SkTypeface::MakeDefault());
1087 }
1088 SkTypeface* typeface = paint.getTypeface();
1089 SkASSERT(typeface);
1090 if (!SkPDFFont::CanEmbedTypeface(typeface, fDocument->canon())) {
1091 SkPath path; // https://bug.skia.org/3866
1092 paint.getTextPath(sourceText, sourceByteCount,
1093 offset.x(), offset.y(), &path);
1094 this->drawPath(d, path, srcPaint, &SkMatrix::I(), true);
1095 // Draw text transparently to make it copyable/searchable/accessable.
1096 draw_transparent_text(this, d, sourceText, sourceByteCount,
1097 offset.x(), offset.y(), paint);
1098 return;
1099 }
1100 // Always make a copy (1) to validate user-input glyphs and
1101 // (2) because we may modify the glyphs in place (for
1102 // single-byte-glyph-id PDF fonts).
1103 int glyphCount = paint.textToGlyphs(sourceText, sourceByteCount, nullptr);
1104 if (glyphCount <= 0) { return; }
1105 SkAutoSTMalloc<128, SkGlyphID> glyphStorage(SkToSizeT(glyphCount));
1106 SkGlyphID* glyphs = glyphStorage.get();
1107 (void)paint.textToGlyphs(sourceText, sourceByteCount, glyphs);
1108 if (paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding) {
1109 // Validate user-input glyphs.
1110 SkGlyphID maxGlyphID = SkToU16(typeface->countGlyphs() - 1);
1111 for (int i = 0; i < glyphCount; ++i) {
1112 glyphs[i] = SkTMin(maxGlyphID, glyphs[i]);
1113 }
1114 } else {
1115 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1116 }
1117
1118 bool defaultPositioning = (positioning == SkTextBlob::kDefault_Positioning);
1119 SkAutoGlyphCache glyphCache(paint, nullptr, nullptr);
1120
1121 SkPaint::Align alignment = paint.getTextAlign();
1122 bool verticalText = paint.isVerticalText();
1123 if (defaultPositioning && alignment != SkPaint::kLeft_Align) {
1124 SkScalar advance{0};
1125 for (int i = 0; i < glyphCount; ++i) {
1126 advance += glyphCache->getGlyphIDAdvance(glyphs[i]).fAdvanceX;
1127 }
1128 SkScalar m = alignment == SkPaint::kCenter_Align
1129 ? 0.5f * advance : advance;
1130 offset -= verticalText ? SkPoint{0, m} : SkPoint{m, 0};
1131 }
1132 ScopedContentEntry content(this, d, paint, true);
1133 if (!content.entry()) { 1189 if (!content.entry()) {
1134 return; 1190 return;
1135 } 1191 }
1136 SkDynamicMemoryWStream* out = &content.entry()->fContent; 1192
1137 out->writeText("BT\n"); 1193 SkGlyphStorage storage(0);
1138 if (!this->updateFont(paint, glyphs[0], content.entry())) { 1194 const uint16_t* glyphIDs = nullptr;
1139 SkDebugf("SkPDF: Font error."); 1195 int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs);
1140 out->writeText("ET\n%SkPDF: Font error.\n"); 1196 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1197
1198 align_text(textPaint, glyphIDs, numGlyphs, &x, &y);
1199 content.entry()->fContent.writeText("BT\n");
1200 set_text_transform(x, y, textPaint.getTextSkewX(),
1201 &content.entry()->fContent);
1202 int consumedGlyphCount = 0;
1203
1204 SkTDArray<uint16_t> glyphIDsCopy(glyphIDs, numGlyphs);
1205
1206 SkPDFGlyphSetMap* fontGlyphUsage = fDocument->getGlyphUsage();
1207
1208 while (numGlyphs > consumedGlyphCount) {
1209 if (!this->updateFont(textPaint, glyphIDs[consumedGlyphCount], content.e ntry())) {
1210 SkDebugf("SkPDF: Font error.");
1211 content.entry()->fContent.writeText("ET\n%SkPDF: Font error.\n");
1212 return;
1213 }
1214 SkPDFFont* font = content.entry()->fState.fFont;
1215
1216 int availableGlyphs = font->glyphsToPDFFontEncoding(
1217 glyphIDsCopy.begin() + consumedGlyphCount,
1218 numGlyphs - consumedGlyphCount);
1219 fontGlyphUsage->noteGlyphUsage(
1220 font, glyphIDsCopy.begin() + consumedGlyphCount,
1221 availableGlyphs);
1222 write_wide_string(&content.entry()->fContent,
1223 glyphIDsCopy.begin() + consumedGlyphCount,
1224 availableGlyphs, font->multiByteGlyphs());
1225 consumedGlyphCount += availableGlyphs;
1226 content.entry()->fContent.writeText(" Tj\n");
1227 }
1228 content.entry()->fContent.writeText("ET\n");
1229 }
1230
1231 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
1232 const SkScalar pos[], int scalarsPerPos,
1233 const SkPoint& offset, const SkPaint& srcPaint) {
1234 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fDocument->canon()) ) {
1235 const SkPoint* positions = reinterpret_cast<const SkPoint*>(pos);
1236 SkAutoTMalloc<SkPoint> positionsBuffer;
1237 if (2 != scalarsPerPos) {
1238 int glyphCount = srcPaint.textToGlyphs(text, len, NULL);
1239 positionsBuffer.reset(glyphCount);
1240 for (int i = 0; i < glyphCount; ++i) {
1241 positionsBuffer[i].set(pos[i], 0.0f);
1242 }
1243 positions = &positionsBuffer[0];
1244 }
1245 SkPath path;
1246 srcPaint.getPosTextPath(text, len, positions, &path);
1247 SkMatrix matrix;
1248 matrix.setTranslate(offset);
1249 this->drawPath(d, path, srcPaint, &matrix, true);
1250 // Draw text transparently to make it copyable/searchable/accessable.
1251 draw_transparent_text(
1252 this, d, text, len, offset.x() + positions[0].x(),
1253 offset.y() + positions[0].y(), srcPaint);
1141 return; 1254 return;
1142 } 1255 }
1143 SkPDFFont* font = content.entry()->fState.fFont; 1256
1144 GlyphPositioner glyphPositioner(out, 1257 SkPaint paint = srcPaint;
1145 paint.getTextSkewX(), 1258 replace_srcmode_on_opaque_paint(&paint);
1146 font->multiByteGlyphs(), 1259
1147 defaultPositioning, 1260 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false);
1148 offset); 1261 if (paint.getMaskFilter() != nullptr) {
1262 // Don't pretend we support drawing MaskFilters, it makes for artifacts
1263 // making text unreadable (e.g. same text twice when using CSS shadows).
1264 return;
1265 }
1266 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
1267 SkPaint textPaint = calculate_text_paint(paint);
1268 ScopedContentEntry content(this, d, textPaint, true);
1269 if (!content.entry()) {
1270 return;
1271 }
1272
1273 SkGlyphStorage storage(0);
1274 const uint16_t* glyphIDs = nullptr;
1275 size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphID s);
1276 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1277 SkAutoGlyphCache autoGlyphCache(textPaint, nullptr, nullptr);
1278
1279 content.entry()->fContent.writeText("BT\n");
1280 if (!this->updateFont(textPaint, glyphIDs[0], content.entry())) {
1281 SkDebugf("SkPDF: Font error.");
1282 content.entry()->fContent.writeText("ET\n%SkPDF: Font error.\n");
1283 return;
1284 }
1285 GlyphPositioner glyphPositioner(&content.entry()->fContent,
1286 textPaint.getTextSkewX(),
1287 content.entry()->fState.fFont->multiByteGlyp hs());
1149 SkPDFGlyphSetMap* fontGlyphUsage = fDocument->getGlyphUsage(); 1288 SkPDFGlyphSetMap* fontGlyphUsage = fDocument->getGlyphUsage();
1150 const SkGlyphID* const glyphsEnd = glyphs + glyphCount; 1289 for (size_t i = 0; i < numGlyphs; i++) {
1151 1290 SkPDFFont* font = content.entry()->fState.fFont;
1152 while (glyphs < glyphsEnd) { 1291 uint16_t encodedValue = glyphIDs[i];
1153 font = content.entry()->fState.fFont; 1292 SkScalar advanceWidth = autoGlyphCache->getGlyphIDAdvance(encodedValue). fAdvanceX;
1154 int stretch = font->multiByteGlyphs() 1293 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
1155 ? SkToInt(glyphsEnd - glyphs) 1294 // The current pdf font cannot encode the current glyph.
1156 : font->glyphsToPDFFontEncodingCount(glyphs, SkToInt(glyphsEnd - gly phs)); 1295 // Try to get a pdf font which can encode the current glyph.
1157 SkASSERT(glyphs + stretch <= glyphsEnd);
1158 if (stretch < 1) {
1159 SkASSERT(!font->multiByteGlyphs());
1160 // The current pdf font cannot encode the next glyph.
1161 // Try to get a pdf font which can encode the next glyph.
1162 glyphPositioner.flush(); 1296 glyphPositioner.flush();
1163 if (!this->updateFont(paint, *glyphs, content.entry())) { 1297 if (!this->updateFont(textPaint, glyphIDs[i], content.entry())) {
1164 SkDebugf("SkPDF: Font error."); 1298 SkDebugf("SkPDF: Font error.");
1165 out->writeText("ET\n%SkPDF: Font error.\n"); 1299 content.entry()->fContent.writeText("ET\n%SkPDF: Font error.\n") ;
1166 return; 1300 return;
1167 } 1301 }
1168 font = content.entry()->fState.fFont; 1302 font = content.entry()->fState.fFont;
1169 glyphPositioner.setWideChars(font->multiByteGlyphs()); 1303 glyphPositioner.setWideChars(font->multiByteGlyphs());
1170 // try again 1304 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
1171 stretch = font->glyphsToPDFFontEncodingCount(glyphs,
1172 SkToInt(glyphsEnd - gly phs));
1173 if (stretch < 1) {
1174 SkDEBUGFAIL("PDF could not encode glyph."); 1305 SkDEBUGFAIL("PDF could not encode glyph.");
1175 glyphPositioner.flush(); 1306 continue;
1176 out->writeText("ET\n%SkPDF: Font encoding error.\n");
1177 return;
1178 } 1307 }
1179 } 1308 }
1180 fontGlyphUsage->noteGlyphUsage(font, glyphs, stretch); 1309 fontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1);
1181 if (defaultPositioning) { 1310 SkScalar x = offset.x() + pos[i * scalarsPerPos];
1182 (void)font->glyphsToPDFFontEncoding(glyphs, SkToInt(glyphsEnd - glyp hs)); 1311 SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * scalarsPerPos + 1] : 0);
1183 while (stretch-- > 0) { 1312 align_text(textPaint, glyphIDs + i, 1, &x, &y);
1184 glyphPositioner.writeGlyph(0, 0, 0, *glyphs); 1313
1185 ++glyphs; 1314 glyphPositioner.writeGlyph(x, y, advanceWidth, encodedValue);
1186 }
1187 } else {
1188 while (stretch-- > 0) {
1189 SkScalar advance = glyphCache->getGlyphIDAdvance(*glyphs).fAdvan ceX;
1190 SkScalar x = *pos++;
1191 // evaluate x and y in order!
1192 SkScalar y = SkTextBlob::kFull_Positioning == positioning ? *pos ++ : 0;
1193 SkPoint xy{x, y};
1194 if (alignment != SkPaint::kLeft_Align) {
1195 SkScalar m = alignment == SkPaint::kCenter_Align
1196 ? 0.5f * advance : advance;
1197 xy -= verticalText ? SkPoint{0, m} : SkPoint{m, 0};
1198 }
1199 (void)font->glyphsToPDFFontEncoding(glyphs, 1);
1200 glyphPositioner.writeGlyph(xy.x(), xy.y(), advance, *glyphs);
1201 ++glyphs;
1202 }
1203 }
1204 } 1315 }
1205 glyphPositioner.flush(); 1316 glyphPositioner.flush(); // Must flush before ending text object.
1206 out->writeText("ET\n"); 1317 content.entry()->fContent.writeText("ET\n");
1207 }
1208
1209 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
1210 SkScalar x, SkScalar y, const SkPaint& paint) {
1211 this->internalDrawText(d, text, len, nullptr, SkTextBlob::kDefault_Positioni ng,
1212 SkPoint{x, y}, paint);
1213 }
1214
1215 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
1216 const SkScalar pos[], int scalarsPerPos,
1217 const SkPoint& offset, const SkPaint& paint) {
1218 this->internalDrawText(d, text, len, pos, (SkTextBlob::GlyphPositioning)scal arsPerPos,
1219 offset, paint);
1220 } 1318 }
1221 1319
1222 void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode, 1320 void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
1223 int vertexCount, const SkPoint verts[], 1321 int vertexCount, const SkPoint verts[],
1224 const SkPoint texs[], const SkColor colors[], 1322 const SkPoint texs[], const SkColor colors[],
1225 SkXfermode* xmode, const uint16_t indices[], 1323 SkXfermode* xmode, const uint16_t indices[],
1226 int indexCount, const SkPaint& paint) { 1324 int indexCount, const SkPaint& paint) {
1227 if (d.fRC->isEmpty()) { 1325 if (d.fRC->isEmpty()) {
1228 return; 1326 return;
1229 } 1327 }
(...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after
2153 } 2251 }
2154 2252
2155 sk_sp<SkSpecialImage> SkPDFDevice::makeSpecial(const SkImage* image) { 2253 sk_sp<SkSpecialImage> SkPDFDevice::makeSpecial(const SkImage* image) {
2156 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(image->width(), image-> height()), 2254 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(image->width(), image-> height()),
2157 image->makeNonTextureImage()); 2255 image->makeNonTextureImage());
2158 } 2256 }
2159 2257
2160 sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() { 2258 sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() {
2161 return nullptr; 2259 return nullptr;
2162 } 2260 }
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