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

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) 13:37:23 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
« no previous file with comments | « 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 <tuple>
8 #include "SkPDFDevice.h" 9 #include "SkPDFDevice.h"
9 10
10 #include "SkAnnotation.h" 11 #include "SkAnnotation.h"
11 #include "SkColor.h" 12 #include "SkColor.h"
12 #include "SkColorFilter.h" 13 #include "SkColorFilter.h"
13 #include "SkClipStack.h" 14 #include "SkClipStack.h"
14 #include "SkData.h" 15 #include "SkData.h"
15 #include "SkDraw.h" 16 #include "SkDraw.h"
16 #include "SkGlyphCache.h" 17 #include "SkGlyphCache.h"
17 #include "SkPaint.h" 18 #include "SkPaint.h"
(...skipping 16 matching lines...) Expand all
34 #include "SkSurface.h" 35 #include "SkSurface.h"
35 #include "SkTextFormatParams.h" 36 #include "SkTextFormatParams.h"
36 #include "SkTemplates.h" 37 #include "SkTemplates.h"
37 #include "SkTypefacePriv.h" 38 #include "SkTypefacePriv.h"
38 #include "SkXfermodeInterpretation.h" 39 #include "SkXfermodeInterpretation.h"
39 40
40 #define DPI_FOR_RASTER_SCALE_ONE 72 41 #define DPI_FOR_RASTER_SCALE_ONE 72
41 42
42 // Utility functions 43 // Utility functions
43 44
45 static bool excessive_translation(const SkMatrix& m) {
46 const SkScalar kExcessiveTranslation = 8192.0f;
47 return SkScalarAbs(m.getTranslateX()) > kExcessiveTranslation
48 || SkScalarAbs(m.getTranslateY()) > kExcessiveTranslation;
49 }
50
51 static std::tuple<SkMatrix, SkVector> untranslate(const SkDraw& d) {
52 // https://bug.skia.org/257 If the translation is too large,
53 // PDF can't exactly represent the float values as numbers.
54 SkScalar translateX = d.fMatrix->getTranslateX() / d.fMatrix->getScaleX();
55 SkScalar translateY = d.fMatrix->getTranslateY() / d.fMatrix->getScaleY();
56 SkMatrix mat = *d.fMatrix;
57 mat.preTranslate(-translateX, -translateY);
58 SkASSERT(SkScalarAbs(mat.getTranslateX()) <= 1.0);
59 return std::make_tuple(mat, SkVector::Make(translateX, translateY));
60 }
61
44 // If the paint will definitely draw opaquely, replace kSrc_Mode with 62 // If the paint will definitely draw opaquely, replace kSrc_Mode with
45 // kSrcOver_Mode. http://crbug.com/473572 63 // kSrcOver_Mode. http://crbug.com/473572
46 static void replace_srcmode_on_opaque_paint(SkPaint* paint) { 64 static void replace_srcmode_on_opaque_paint(SkPaint* paint) {
47 if (kSrcOver_SkXfermodeInterpretation 65 if (kSrcOver_SkXfermodeInterpretation
48 == SkInterpretXfermode(*paint, false)) { 66 == SkInterpretXfermode(*paint, false)) {
49 paint->setXfermode(nullptr); 67 paint->setXfermode(nullptr);
50 } 68 }
51 } 69 }
52 70
53 static void emit_pdf_color(SkColor color, SkWStream* result) { 71 static void emit_pdf_color(SkColor color, SkWStream* result) {
(...skipping 740 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 812
795 if (count == 0) { 813 if (count == 0) {
796 return; 814 return;
797 } 815 }
798 816
799 if (SkAnnotation* annotation = passedPaint.getAnnotation()) { 817 if (SkAnnotation* annotation = passedPaint.getAnnotation()) {
800 if (handlePointAnnotation(points, count, *d.fMatrix, annotation)) { 818 if (handlePointAnnotation(points, count, *d.fMatrix, annotation)) {
801 return; 819 return;
802 } 820 }
803 } 821 }
822 if (excessive_translation(*d.fMatrix)) {
823 SkVector translate; SkMatrix translateMatrix;
824 std::tie(translateMatrix, translate) = untranslate(d);
825 SkDraw drawCopy(d);
826 drawCopy.fMatrix = &translateMatrix;
827 SkTArray<SkPoint> pointsCopy(points, SkToInt(count));
828 SkPoint::Offset(&pointsCopy[0], SkToInt(count), translate);
829 this->drawPoints(drawCopy, mode, count, &pointsCopy[0], srcPaint);
830 return; // NOTE: shader behavior will be off.
831 }
804 832
805 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath. 833 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
806 // We only use this when there's a path effect because of the overhead 834 // We only use this when there's a path effect because of the overhead
807 // of multiple calls to setUpContentEntry it causes. 835 // of multiple calls to setUpContentEntry it causes.
808 if (passedPaint.getPathEffect()) { 836 if (passedPaint.getPathEffect()) {
809 if (d.fClip->isEmpty()) { 837 if (d.fClip->isEmpty()) {
810 return; 838 return;
811 } 839 }
812 SkDraw pointDraw(d); 840 SkDraw pointDraw(d);
813 pointDraw.fDevice = this; 841 pointDraw.fDevice = this;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 } 950 }
923 951
924 void SkPDFDevice::drawRect(const SkDraw& d, 952 void SkPDFDevice::drawRect(const SkDraw& d,
925 const SkRect& rect, 953 const SkRect& rect,
926 const SkPaint& srcPaint) { 954 const SkPaint& srcPaint) {
927 SkPaint paint = srcPaint; 955 SkPaint paint = srcPaint;
928 replace_srcmode_on_opaque_paint(&paint); 956 replace_srcmode_on_opaque_paint(&paint);
929 SkRect r = rect; 957 SkRect r = rect;
930 r.sort(); 958 r.sort();
931 959
960 if (excessive_translation(*d.fMatrix)) {
961 SkVector translate; SkMatrix translateMatrix;
962 std::tie(translateMatrix, translate) = untranslate(d);
963 SkDraw drawCopy(d);
964 drawCopy.fMatrix = &translateMatrix;
965 SkRect rectCopy = rect;
966 rectCopy.offset(translate.x(), translate.y());
967 this->drawRect(drawCopy, rectCopy, srcPaint);
968 return; // NOTE: shader behavior will be off.
969 }
970
932 if (paint.getPathEffect()) { 971 if (paint.getPathEffect()) {
933 if (d.fClip->isEmpty()) { 972 if (d.fClip->isEmpty()) {
934 return; 973 return;
935 } 974 }
936 SkPath path; 975 SkPath path;
937 path.addRect(r); 976 path.addRect(r);
938 drawPath(d, path, paint, nullptr, true); 977 drawPath(d, path, paint, nullptr, true);
939 return; 978 return;
940 } 979 }
941 980
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
974 SkPath path; 1013 SkPath path;
975 path.addOval(oval); 1014 path.addOval(oval);
976 this->drawPath(draw, path, paint, nullptr, true); 1015 this->drawPath(draw, path, paint, nullptr, true);
977 } 1016 }
978 1017
979 void SkPDFDevice::drawPath(const SkDraw& d, 1018 void SkPDFDevice::drawPath(const SkDraw& d,
980 const SkPath& origPath, 1019 const SkPath& origPath,
981 const SkPaint& srcPaint, 1020 const SkPaint& srcPaint,
982 const SkMatrix* prePathMatrix, 1021 const SkMatrix* prePathMatrix,
983 bool pathIsMutable) { 1022 bool pathIsMutable) {
1023 if (excessive_translation(*d.fMatrix)) {
1024 SkVector translate; SkMatrix translateMatrix;
1025 std::tie(translateMatrix, translate) = untranslate(d);
1026 SkDraw drawCopy(d);
1027 drawCopy.fMatrix = &translateMatrix;
1028 SkPath pathCopy(origPath);
1029 pathCopy.offset(translate.x(), translate.y());
1030 this->drawPath(drawCopy, pathCopy, srcPaint, prePathMatrix, true);
1031 return; // NOTE: shader behavior will be off.
1032 }
1033
984 SkPaint paint = srcPaint; 1034 SkPaint paint = srcPaint;
985 replace_srcmode_on_opaque_paint(&paint); 1035 replace_srcmode_on_opaque_paint(&paint);
986 SkPath modifiedPath; 1036 SkPath modifiedPath;
987 SkPath* pathPtr = const_cast<SkPath*>(&origPath); 1037 SkPath* pathPtr = const_cast<SkPath*>(&origPath);
988 1038
989 SkMatrix matrix = *d.fMatrix; 1039 SkMatrix matrix = *d.fMatrix;
990 if (prePathMatrix) { 1040 if (prePathMatrix) {
991 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 1041 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
992 if (!pathIsMutable) { 1042 if (!pathIsMutable) {
993 pathPtr = &modifiedPath; 1043 pathPtr = &modifiedPath;
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 device->drawText(d, text, len, x, y, transparent); 1316 device->drawText(d, text, len, x, y, transparent);
1267 break; 1317 break;
1268 default: 1318 default:
1269 SkFAIL("unknown text encoding"); 1319 SkFAIL("unknown text encoding");
1270 } 1320 }
1271 } 1321 }
1272 1322
1273 1323
1274 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, 1324 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
1275 SkScalar x, SkScalar y, const SkPaint& srcPaint) { 1325 SkScalar x, SkScalar y, const SkPaint& srcPaint) {
1326 if (excessive_translation(*d.fMatrix)) {
1327 SkVector translate; SkMatrix translateMatrix;
1328 std::tie(translateMatrix, translate) = untranslate(d);
1329 SkDraw drawCopy(d);
1330 drawCopy.fMatrix = &translateMatrix;
1331 this->drawText(drawCopy, text, len, x + translate.x(),
1332 y + translate.y(), srcPaint);
1333 return; // NOTE: shader behavior will be off.
1334 }
1335
1276 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) { 1336 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) {
1277 // https://bug.skia.org/3866 1337 // https://bug.skia.org/3866
1278 SkPath path; 1338 SkPath path;
1279 srcPaint.getTextPath(text, len, x, y, &path); 1339 srcPaint.getTextPath(text, len, x, y, &path);
1280 this->drawPath(d, path, srcPaint, &SkMatrix::I(), true); 1340 this->drawPath(d, path, srcPaint, &SkMatrix::I(), true);
1281 // Draw text transparently to make it copyable/searchable/accessable. 1341 // Draw text transparently to make it copyable/searchable/accessable.
1282 draw_transparent_text(this, d, text, len, x, y, srcPaint); 1342 draw_transparent_text(this, d, text, len, x, y, srcPaint);
1283 return; 1343 return;
1284 } 1344 }
1285 SkPaint paint = srcPaint; 1345 SkPaint paint = srcPaint;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 content.entry()->fContent.writeText(encodedString.c_str()); 1387 content.entry()->fContent.writeText(encodedString.c_str());
1328 consumedGlyphCount += availableGlyphs; 1388 consumedGlyphCount += availableGlyphs;
1329 content.entry()->fContent.writeText(" Tj\n"); 1389 content.entry()->fContent.writeText(" Tj\n");
1330 } 1390 }
1331 content.entry()->fContent.writeText("ET\n"); 1391 content.entry()->fContent.writeText("ET\n");
1332 } 1392 }
1333 1393
1334 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, 1394 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
1335 const SkScalar pos[], int scalarsPerPos, 1395 const SkScalar pos[], int scalarsPerPos,
1336 const SkPoint& offset, const SkPaint& srcPaint) { 1396 const SkPoint& offset, const SkPaint& srcPaint) {
1397 if (excessive_translation(*d.fMatrix)) {
1398 SkVector translate; SkMatrix translateMatrix;
1399 std::tie(translateMatrix, translate) = untranslate(d);
1400 SkDraw drawCopy(d);
1401 drawCopy.fMatrix = &translateMatrix;
1402 SkPoint offsetCopy = offset;
1403 SkPoint::Offset(&offsetCopy, 1, translate.x(), translate.y());
1404 this->drawPosText(drawCopy, text, len, pos, scalarsPerPos, offsetCopy,
1405 srcPaint);
1406 return; // NOTE: shader behavior will be off.
1407 }
1408
1337 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) { 1409 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) {
1338 const SkPoint* positions = reinterpret_cast<const SkPoint*>(pos); 1410 const SkPoint* positions = reinterpret_cast<const SkPoint*>(pos);
1339 SkAutoTMalloc<SkPoint> positionsBuffer; 1411 SkAutoTMalloc<SkPoint> positionsBuffer;
1340 if (2 != scalarsPerPos) { 1412 if (2 != scalarsPerPos) {
1341 int glyphCount = srcPaint.textToGlyphs(text, len, NULL); 1413 int glyphCount = srcPaint.textToGlyphs(text, len, NULL);
1342 positionsBuffer.reset(glyphCount); 1414 positionsBuffer.reset(glyphCount);
1343 for (int i = 0; i < glyphCount; ++i) { 1415 for (int i = 0; i < glyphCount; ++i) {
1344 positionsBuffer[i].set(pos[i], 0.0f); 1416 positionsBuffer[i].set(pos[i], 0.0f);
1345 } 1417 }
1346 positions = &positionsBuffer[0]; 1418 positions = &positionsBuffer[0];
(...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 if (!pdfimage) { 2435 if (!pdfimage) {
2364 pdfimage.reset(SkPDFCreateBitmapObject(image)); 2436 pdfimage.reset(SkPDFCreateBitmapObject(image));
2365 if (!pdfimage) { 2437 if (!pdfimage) {
2366 return; 2438 return;
2367 } 2439 }
2368 fCanon->addPDFBitmap(image->uniqueID(), pdfimage); 2440 fCanon->addPDFBitmap(image->uniqueID(), pdfimage);
2369 } 2441 }
2370 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), 2442 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()),
2371 &content.entry()->fContent); 2443 &content.entry()->fContent);
2372 } 2444 }
OLDNEW
« no previous file with comments | « gm/skbug_257.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698