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

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

Issue 1438503002: SkPDF: fix large-number bug (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-11-16 (Monday) 11:10:10 EST Created 5 years, 1 month 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
« gm/skbug_257.cpp ('K') | « gm/skbug_257.cpp ('k') | no next file » | 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 "SkAnnotation.h" 10 #include "SkAnnotation.h"
(...skipping 23 matching lines...) Expand all
34 #include "SkSurface.h" 34 #include "SkSurface.h"
35 #include "SkTextFormatParams.h" 35 #include "SkTextFormatParams.h"
36 #include "SkTemplates.h" 36 #include "SkTemplates.h"
37 #include "SkTypefacePriv.h" 37 #include "SkTypefacePriv.h"
38 #include "SkXfermodeInterpretation.h" 38 #include "SkXfermodeInterpretation.h"
39 39
40 #define DPI_FOR_RASTER_SCALE_ONE 72 40 #define DPI_FOR_RASTER_SCALE_ONE 72
41 41
42 // Utility functions 42 // Utility functions
43 43
44 static bool excessive_translation(const SkMatrix& m) {
45 const SkScalar kExcessiveTranslation = 8192.0f;
46 return SkScalarAbs(m.getTranslateX()) > kExcessiveTranslation
47 || SkScalarAbs(m.getTranslateY()) > kExcessiveTranslation;
48 }
49
50 static SkDraw untranslate(const SkDraw& d, SkVector* shiftVector) {
51 SkScalar translateX = d.fMatrix->getTranslateX() / d.fMatrix->getScaleX();
52 SkScalar translateY = d.fMatrix->getTranslateY() / d.fMatrix->getScaleY();
53 SkMatrix translate = *d.fMatrix;
54 translate.preTranslate(-translateX, -translateY);
55 SkASSERT(translate.getTranslateX() <= 1.0);
tomhudson 2015/11/16 16:35:30 Do we want an fabs() here for paranoia?
hal.canary 2015/11/16 16:50:17 done
56 SkDraw drawCopy(d);
57 drawCopy.fMatrix = &translate;
tomhudson 2015/11/16 16:35:30 Uh-oh; returning reference to a local static - thi
hal.canary 2015/11/16 16:50:18 Argh! This is what I get from copy-and-pasting in
58 if (shiftVector) {
59 shiftVector->set(translateX, translateY);
60 }
61 return drawCopy;
62 }
63
44 // If the paint will definitely draw opaquely, replace kSrc_Mode with 64 // If the paint will definitely draw opaquely, replace kSrc_Mode with
45 // kSrcOver_Mode. http://crbug.com/473572 65 // kSrcOver_Mode. http://crbug.com/473572
46 static void replace_srcmode_on_opaque_paint(SkPaint* paint) { 66 static void replace_srcmode_on_opaque_paint(SkPaint* paint) {
47 if (kSrcOver_SkXfermodeInterpretation 67 if (kSrcOver_SkXfermodeInterpretation
48 == SkInterpretXfermode(*paint, false)) { 68 == SkInterpretXfermode(*paint, false)) {
49 paint->setXfermode(nullptr); 69 paint->setXfermode(nullptr);
50 } 70 }
51 } 71 }
52 72
53 static void emit_pdf_color(SkColor color, SkWStream* result) { 73 static void emit_pdf_color(SkColor color, SkWStream* result) {
(...skipping 740 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 814
795 if (count == 0) { 815 if (count == 0) {
796 return; 816 return;
797 } 817 }
798 818
799 if (SkAnnotation* annotation = passedPaint.getAnnotation()) { 819 if (SkAnnotation* annotation = passedPaint.getAnnotation()) {
800 if (handlePointAnnotation(points, count, *d.fMatrix, annotation)) { 820 if (handlePointAnnotation(points, count, *d.fMatrix, annotation)) {
801 return; 821 return;
802 } 822 }
803 } 823 }
824 if (excessive_translation(*d.fMatrix)) {
825 // https://bug.skia.org/257 If the translation is too large,
826 // PDF can't exactly represent the float values as numbers.
tomhudson 2015/11/16 16:35:30 Nit: this comment is cut-and-pasted four times. Do
hal.canary 2015/11/16 16:50:18 done
827 SkVector translate;
828 SkDraw drawCopy = untranslate(d, &translate);
829 SkTArray<SkPoint> pointsCopy(points, count);
830 SkPoint::Offset(&pointsCopy[0], count, translate.x(), translate.y());
831 this->drawPoints(drawCopy, mode, count, &pointsCopy[0], srcPaint);
832 return; // NOTE: shader behavior will be off.
833 }
804 834
805 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath. 835 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
806 // We only use this when there's a path effect because of the overhead 836 // We only use this when there's a path effect because of the overhead
807 // of multiple calls to setUpContentEntry it causes. 837 // of multiple calls to setUpContentEntry it causes.
808 if (passedPaint.getPathEffect()) { 838 if (passedPaint.getPathEffect()) {
809 if (d.fClip->isEmpty()) { 839 if (d.fClip->isEmpty()) {
810 return; 840 return;
811 } 841 }
812 SkDraw pointDraw(d); 842 SkDraw pointDraw(d);
813 pointDraw.fDevice = this; 843 pointDraw.fDevice = this;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 } 952 }
923 953
924 void SkPDFDevice::drawRect(const SkDraw& d, 954 void SkPDFDevice::drawRect(const SkDraw& d,
925 const SkRect& rect, 955 const SkRect& rect,
926 const SkPaint& srcPaint) { 956 const SkPaint& srcPaint) {
927 SkPaint paint = srcPaint; 957 SkPaint paint = srcPaint;
928 replace_srcmode_on_opaque_paint(&paint); 958 replace_srcmode_on_opaque_paint(&paint);
929 SkRect r = rect; 959 SkRect r = rect;
930 r.sort(); 960 r.sort();
931 961
962 if (excessive_translation(*d.fMatrix)) {
963 // https://bug.skia.org/257 If the translation is too large,
964 // PDF can't exactly represent the float values as numbers.
965 SkVector translate;
966 SkDraw drawCopy = untranslate(d, &translate);
967 SkRect rectCopy = rect;
968 rectCopy.offset(translate.x(), translate.y());
969 this->drawRect(drawCopy, rectCopy, srcPaint);
970 return; // NOTE: shader behavior will be off.
971 }
972
932 if (paint.getPathEffect()) { 973 if (paint.getPathEffect()) {
933 if (d.fClip->isEmpty()) { 974 if (d.fClip->isEmpty()) {
934 return; 975 return;
935 } 976 }
936 SkPath path; 977 SkPath path;
937 path.addRect(r); 978 path.addRect(r);
938 drawPath(d, path, paint, nullptr, true); 979 drawPath(d, path, paint, nullptr, true);
939 return; 980 return;
940 } 981 }
941 982
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
974 SkPath path; 1015 SkPath path;
975 path.addOval(oval); 1016 path.addOval(oval);
976 this->drawPath(draw, path, paint, nullptr, true); 1017 this->drawPath(draw, path, paint, nullptr, true);
977 } 1018 }
978 1019
979 void SkPDFDevice::drawPath(const SkDraw& d, 1020 void SkPDFDevice::drawPath(const SkDraw& d,
980 const SkPath& origPath, 1021 const SkPath& origPath,
981 const SkPaint& srcPaint, 1022 const SkPaint& srcPaint,
982 const SkMatrix* prePathMatrix, 1023 const SkMatrix* prePathMatrix,
983 bool pathIsMutable) { 1024 bool pathIsMutable) {
1025 if (excessive_translation(*d.fMatrix)) {
1026 // https://bug.skia.org/257 If the translation is too large,
1027 // PDF can't exactly represent the float values as numbers.
1028 SkVector translate;
1029 SkDraw drawCopy = untranslate(d, &translate);
1030 SkPath pathCopy(origPath);
1031 pathCopy.offset(translate.x(), translate.y());
1032 this->drawPath(drawCopy, pathCopy, srcPaint, prePathMatrix, true);
1033 return; // NOTE: shader behavior will be off.
1034 }
1035
984 SkPaint paint = srcPaint; 1036 SkPaint paint = srcPaint;
985 replace_srcmode_on_opaque_paint(&paint); 1037 replace_srcmode_on_opaque_paint(&paint);
986 SkPath modifiedPath; 1038 SkPath modifiedPath;
987 SkPath* pathPtr = const_cast<SkPath*>(&origPath); 1039 SkPath* pathPtr = const_cast<SkPath*>(&origPath);
988 1040
989 SkMatrix matrix = *d.fMatrix; 1041 SkMatrix matrix = *d.fMatrix;
990 if (prePathMatrix) { 1042 if (prePathMatrix) {
991 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 1043 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
992 if (!pathIsMutable) { 1044 if (!pathIsMutable) {
993 pathPtr = &modifiedPath; 1045 pathPtr = &modifiedPath;
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 device->drawText(d, text, len, x, y, transparent); 1318 device->drawText(d, text, len, x, y, transparent);
1267 break; 1319 break;
1268 default: 1320 default:
1269 SkFAIL("unknown text encoding"); 1321 SkFAIL("unknown text encoding");
1270 } 1322 }
1271 } 1323 }
1272 1324
1273 1325
1274 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, 1326 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
1275 SkScalar x, SkScalar y, const SkPaint& srcPaint) { 1327 SkScalar x, SkScalar y, const SkPaint& srcPaint) {
1328 if (excessive_translation(*d.fMatrix)) {
1329 // https://bug.skia.org/257 If the translation is too large,
1330 // PDF can't exactly represent the float values as numbers.
1331 SkVector translate;
1332 SkDraw drawCopy = untranslate(d, &translate);
1333 this->drawText(drawCopy, text, len, x + translate.x(),
1334 y + translate.y(), srcPaint);
1335 return; // NOTE: shader behavior will be off.
1336 }
1337
1276 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) { 1338 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) {
1277 // https://bug.skia.org/3866 1339 // https://bug.skia.org/3866
1278 SkPath path; 1340 SkPath path;
1279 srcPaint.getTextPath(text, len, x, y, &path); 1341 srcPaint.getTextPath(text, len, x, y, &path);
1280 this->drawPath(d, path, srcPaint, &SkMatrix::I(), true); 1342 this->drawPath(d, path, srcPaint, &SkMatrix::I(), true);
1281 // Draw text transparently to make it copyable/searchable/accessable. 1343 // Draw text transparently to make it copyable/searchable/accessable.
1282 draw_transparent_text(this, d, text, len, x, y, srcPaint); 1344 draw_transparent_text(this, d, text, len, x, y, srcPaint);
1283 return; 1345 return;
1284 } 1346 }
1285 SkPaint paint = srcPaint; 1347 SkPaint paint = srcPaint;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 content.entry()->fContent.writeText(encodedString.c_str()); 1389 content.entry()->fContent.writeText(encodedString.c_str());
1328 consumedGlyphCount += availableGlyphs; 1390 consumedGlyphCount += availableGlyphs;
1329 content.entry()->fContent.writeText(" Tj\n"); 1391 content.entry()->fContent.writeText(" Tj\n");
1330 } 1392 }
1331 content.entry()->fContent.writeText("ET\n"); 1393 content.entry()->fContent.writeText("ET\n");
1332 } 1394 }
1333 1395
1334 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, 1396 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
1335 const SkScalar pos[], int scalarsPerPos, 1397 const SkScalar pos[], int scalarsPerPos,
1336 const SkPoint& offset, const SkPaint& srcPaint) { 1398 const SkPoint& offset, const SkPaint& srcPaint) {
1399 if (excessive_translation(*d.fMatrix)) {
1400 // https://bug.skia.org/257 If the translation is too large,
1401 // PDF can't exactly represent the float values as numbers.
1402 SkVector translate;
1403 SkDraw drawCopy = untranslate(d, &translate);
1404 SkPoint offsetCopy = offset;
1405 SkPoint::Offset(&offsetCopy, 1, translate.x(), translate.y());
1406 this->drawPosText(drawCopy, text, len, pos, scalarsPerPos, offsetCopy,
1407 srcPaint);
1408 return; // NOTE: shader behavior will be off.
tomhudson 2015/11/16 16:35:30 Can we quantify and document how much of a shader
hal.canary 2015/11/16 16:50:17 It's already off (comparing PDF to 8888 in that GM
1409 }
1410
1337 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) { 1411 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) {
1338 const SkPoint* positions = reinterpret_cast<const SkPoint*>(pos); 1412 const SkPoint* positions = reinterpret_cast<const SkPoint*>(pos);
1339 SkAutoTMalloc<SkPoint> positionsBuffer; 1413 SkAutoTMalloc<SkPoint> positionsBuffer;
1340 if (2 != scalarsPerPos) { 1414 if (2 != scalarsPerPos) {
1341 int glyphCount = srcPaint.textToGlyphs(text, len, NULL); 1415 int glyphCount = srcPaint.textToGlyphs(text, len, NULL);
1342 positionsBuffer.reset(glyphCount); 1416 positionsBuffer.reset(glyphCount);
1343 for (int i = 0; i < glyphCount; ++i) { 1417 for (int i = 0; i < glyphCount; ++i) {
1344 positionsBuffer[i].set(pos[i], 0.0f); 1418 positionsBuffer[i].set(pos[i], 0.0f);
1345 } 1419 }
1346 positions = &positionsBuffer[0]; 1420 positions = &positionsBuffer[0];
1347 } 1421 }
1348 SkPath path; 1422 SkPath path;
1349 srcPaint.getPosTextPath(text, len, positions, &path); 1423 srcPaint.getPosTextPath(text, len, positions, &path);
1350 SkMatrix matrix; 1424 SkMatrix matrix;
1351 matrix.setTranslate(offset); 1425 matrix.setTranslate(offset);
tomhudson 2015/11/16 16:35:30 This gets merged into d.fMatrix in drawPath(), *af
1352 this->drawPath(d, path, srcPaint, &matrix, true); 1426 this->drawPath(d, path, srcPaint, &matrix, true);
1353 // Draw text transparently to make it copyable/searchable/accessable. 1427 // Draw text transparently to make it copyable/searchable/accessable.
1354 draw_transparent_text( 1428 draw_transparent_text(
1355 this, d, text, len, offset.x() + positions[0].x(), 1429 this, d, text, len, offset.x() + positions[0].x(),
1356 offset.y() + positions[0].y(), srcPaint); 1430 offset.y() + positions[0].y(), srcPaint);
1357 return; 1431 return;
1358 } 1432 }
1359 1433
1360 SkPaint paint = srcPaint; 1434 SkPaint paint = srcPaint;
1361 replace_srcmode_on_opaque_paint(&paint); 1435 replace_srcmode_on_opaque_paint(&paint);
(...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 if (!pdfimage) { 2437 if (!pdfimage) {
2364 pdfimage.reset(SkPDFCreateBitmapObject(image)); 2438 pdfimage.reset(SkPDFCreateBitmapObject(image));
2365 if (!pdfimage) { 2439 if (!pdfimage) {
2366 return; 2440 return;
2367 } 2441 }
2368 fCanon->addPDFBitmap(image->uniqueID(), pdfimage); 2442 fCanon->addPDFBitmap(image->uniqueID(), pdfimage);
2369 } 2443 }
2370 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), 2444 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()),
2371 &content.entry()->fContent); 2445 &content.entry()->fContent);
2372 } 2446 }
OLDNEW
« gm/skbug_257.cpp ('K') | « gm/skbug_257.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698