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

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

Issue 1552263003: SkPDF: Change handling of large-numbers in matricies. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2016-01-05 (Tuesday) 13:11:15 EST Created 4 years, 11 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 | « no previous file | tests/PDFDocumentTest.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 <tuple>
9 #include "SkPDFDevice.h" 8 #include "SkPDFDevice.h"
10 9
11 #include "SkAnnotation.h" 10 #include "SkAnnotation.h"
12 #include "SkColor.h" 11 #include "SkColor.h"
13 #include "SkColorFilter.h" 12 #include "SkColorFilter.h"
14 #include "SkClipStack.h" 13 #include "SkClipStack.h"
15 #include "SkData.h" 14 #include "SkData.h"
16 #include "SkDraw.h" 15 #include "SkDraw.h"
17 #include "SkGlyphCache.h" 16 #include "SkGlyphCache.h"
18 #include "SkPaint.h" 17 #include "SkPaint.h"
(...skipping 22 matching lines...) Expand all
41 #define DPI_FOR_RASTER_SCALE_ONE 72 40 #define DPI_FOR_RASTER_SCALE_ONE 72
42 41
43 // Utility functions 42 // Utility functions
44 43
45 static bool excessive_translation(const SkMatrix& m) { 44 static bool excessive_translation(const SkMatrix& m) {
46 const SkScalar kExcessiveTranslation = 8192.0f; 45 const SkScalar kExcessiveTranslation = 8192.0f;
47 return SkScalarAbs(m.getTranslateX()) > kExcessiveTranslation 46 return SkScalarAbs(m.getTranslateX()) > kExcessiveTranslation
48 || SkScalarAbs(m.getTranslateY()) > kExcessiveTranslation; 47 || SkScalarAbs(m.getTranslateY()) > kExcessiveTranslation;
49 } 48 }
50 49
51 static std::tuple<SkMatrix, SkVector> untranslate(const SkDraw& d) { 50 static SkMatrix untranslate(const SkMatrix& matrix, SkScalar x, SkScalar y) {
52 // https://bug.skia.org/257 If the translation is too large, 51 // https://bug.skia.org/257 If the translation is too large,
53 // PDF can't exactly represent the float values as numbers. 52 // PDF can't exactly represent the float values as numbers.
54 SkScalar translateX = d.fMatrix->getTranslateX() / d.fMatrix->getScaleX(); 53 SkMatrix result(matrix);
55 SkScalar translateY = d.fMatrix->getTranslateY() / d.fMatrix->getScaleY(); 54 result.preTranslate(x, y);
56 SkMatrix mat = *d.fMatrix; 55 return result;
57 mat.preTranslate(-translateX, -translateY);
58 SkASSERT(SkScalarAbs(mat.getTranslateX()) <= 1.0);
59 return std::make_tuple(mat, SkVector::Make(translateX, translateY));
60 } 56 }
61 57
62 // If the paint will definitely draw opaquely, replace kSrc_Mode with 58 // If the paint will definitely draw opaquely, replace kSrc_Mode with
63 // kSrcOver_Mode. http://crbug.com/473572 59 // kSrcOver_Mode. http://crbug.com/473572
64 static void replace_srcmode_on_opaque_paint(SkPaint* paint) { 60 static void replace_srcmode_on_opaque_paint(SkPaint* paint) {
65 if (kSrcOver_SkXfermodeInterpretation 61 if (kSrcOver_SkXfermodeInterpretation
66 == SkInterpretXfermode(*paint, false)) { 62 == SkInterpretXfermode(*paint, false)) {
67 paint->setXfermode(nullptr); 63 paint->setXfermode(nullptr);
68 } 64 }
69 } 65 }
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 if (!contentEntry->fState.fMatrix.invert(&inverse)) { 791 if (!contentEntry->fState.fMatrix.invert(&inverse)) {
796 return; 792 return;
797 } 793 }
798 inverse.mapRect(&bbox); 794 inverse.mapRect(&bbox);
799 795
800 SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent); 796 SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent);
801 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, 797 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
802 &contentEntry->fContent); 798 &contentEntry->fContent);
803 } 799 }
804 800
805 void SkPDFDevice::drawPoints(const SkDraw& d, 801 void SkPDFDevice::drawPoints(const SkDraw& srcDraw,
806 SkCanvas::PointMode mode, 802 SkCanvas::PointMode mode,
807 size_t count, 803 size_t count,
808 const SkPoint* points, 804 const SkPoint* points,
809 const SkPaint& srcPaint) { 805 const SkPaint& srcPaint) {
810 SkPaint passedPaint = srcPaint; 806 SkPaint passedPaint = srcPaint;
811 replace_srcmode_on_opaque_paint(&passedPaint); 807 replace_srcmode_on_opaque_paint(&passedPaint);
812 808
813 if (count == 0) { 809 if (count == 0) {
814 return; 810 return;
815 } 811 }
816 812
817 if (SkAnnotation* annotation = passedPaint.getAnnotation()) { 813 if (SkAnnotation* annotation = passedPaint.getAnnotation()) {
818 if (handlePointAnnotation(points, count, *d.fMatrix, annotation)) { 814 if (handlePointAnnotation(points, count, *srcDraw.fMatrix, annotation)) {
819 return; 815 return;
820 } 816 }
821 } 817 }
818 SkMatrix newMatrix;
819 SkDraw d(srcDraw);
820 SkTArray<SkPoint> pointsCopy;
822 if (excessive_translation(*d.fMatrix)) { 821 if (excessive_translation(*d.fMatrix)) {
823 SkVector translate; SkMatrix translateMatrix; 822 newMatrix = untranslate(*d.fMatrix, points[0].x(), points[0].y());
824 std::tie(translateMatrix, translate) = untranslate(d); 823 d.fMatrix = &newMatrix;
825 SkDraw drawCopy(d); 824 pointsCopy.reset(points, SkToInt(count));
826 drawCopy.fMatrix = &translateMatrix; 825 SkPoint::Offset(&pointsCopy[0], SkToInt(count),
827 SkTArray<SkPoint> pointsCopy(points, SkToInt(count)); 826 -points[0].x(), -points[0].y());
828 SkPoint::Offset(&pointsCopy[0], SkToInt(count), translate); 827 points = &pointsCopy[0];
829 this->drawPoints(drawCopy, mode, count, &pointsCopy[0], srcPaint);
830 return; // NOTE: shader behavior will be off.
831 } 828 }
832 829
833 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath. 830 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
834 // We only use this when there's a path effect because of the overhead 831 // We only use this when there's a path effect because of the overhead
835 // of multiple calls to setUpContentEntry it causes. 832 // of multiple calls to setUpContentEntry it causes.
836 if (passedPaint.getPathEffect()) { 833 if (passedPaint.getPathEffect()) {
837 if (d.fClip->isEmpty()) { 834 if (d.fClip->isEmpty()) {
838 return; 835 return;
839 } 836 }
840 SkDraw pointDraw(d); 837 SkDraw pointDraw(d);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
942 939
943 static SkPDFDict* create_link_named_dest(const SkData* nameData, 940 static SkPDFDict* create_link_named_dest(const SkData* nameData,
944 const SkRect& r) { 941 const SkRect& r) {
945 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); 942 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r));
946 SkString name(static_cast<const char *>(nameData->data()), 943 SkString name(static_cast<const char *>(nameData->data()),
947 nameData->size() - 1); 944 nameData->size() - 1);
948 annotation->insertName("Dest", name); 945 annotation->insertName("Dest", name);
949 return annotation.detach(); 946 return annotation.detach();
950 } 947 }
951 948
952 void SkPDFDevice::drawRect(const SkDraw& d, 949 void SkPDFDevice::drawRect(const SkDraw& srcDraw,
953 const SkRect& rect, 950 const SkRect& rect,
954 const SkPaint& srcPaint) { 951 const SkPaint& srcPaint) {
955 SkPaint paint = srcPaint; 952 SkPaint paint = srcPaint;
956 replace_srcmode_on_opaque_paint(&paint); 953 replace_srcmode_on_opaque_paint(&paint);
957 SkRect r = rect; 954 SkRect r = rect;
958 r.sort(); 955 r.sort();
959 956
957 SkMatrix newMatrix;
958 SkDraw d(srcDraw);
960 if (excessive_translation(*d.fMatrix)) { 959 if (excessive_translation(*d.fMatrix)) {
961 SkVector translate; SkMatrix translateMatrix; 960 newMatrix = untranslate(*d.fMatrix, r.x(), r.y());
962 std::tie(translateMatrix, translate) = untranslate(d); 961 d.fMatrix = &newMatrix;
963 SkDraw drawCopy(d); 962 r.offsetTo(0, 0);
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 } 963 }
970 964
971 if (paint.getPathEffect()) { 965 if (paint.getPathEffect()) {
972 if (d.fClip->isEmpty()) { 966 if (d.fClip->isEmpty()) {
973 return; 967 return;
974 } 968 }
975 SkPath path; 969 SkPath path;
976 path.addRect(r); 970 path.addRect(r);
977 drawPath(d, path, paint, nullptr, true); 971 drawPath(d, path, paint, nullptr, true);
978 return; 972 return;
(...skipping 29 matching lines...) Expand all
1008 void SkPDFDevice::drawOval(const SkDraw& draw, 1002 void SkPDFDevice::drawOval(const SkDraw& draw,
1009 const SkRect& oval, 1003 const SkRect& oval,
1010 const SkPaint& srcPaint) { 1004 const SkPaint& srcPaint) {
1011 SkPaint paint = srcPaint; 1005 SkPaint paint = srcPaint;
1012 replace_srcmode_on_opaque_paint(&paint); 1006 replace_srcmode_on_opaque_paint(&paint);
1013 SkPath path; 1007 SkPath path;
1014 path.addOval(oval); 1008 path.addOval(oval);
1015 this->drawPath(draw, path, paint, nullptr, true); 1009 this->drawPath(draw, path, paint, nullptr, true);
1016 } 1010 }
1017 1011
1018 void SkPDFDevice::drawPath(const SkDraw& d, 1012 void SkPDFDevice::drawPath(const SkDraw& srcDraw,
1019 const SkPath& origPath, 1013 const SkPath& origPath,
1020 const SkPaint& srcPaint, 1014 const SkPaint& srcPaint,
1021 const SkMatrix* prePathMatrix, 1015 const SkMatrix* prePathMatrix,
1022 bool pathIsMutable) { 1016 bool pathIsMutable) {
1017 SkMatrix newMatrix;
1018 SkDraw d(srcDraw);
1019 SkPath modifiedPath;
1020 SkPath* pathPtr = const_cast<SkPath*>(&origPath);
1023 if (excessive_translation(*d.fMatrix)) { 1021 if (excessive_translation(*d.fMatrix)) {
1024 SkVector translate; SkMatrix translateMatrix; 1022 SkPoint firstPt;
1025 std::tie(translateMatrix, translate) = untranslate(d); 1023 if (origPath.getPoints(&firstPt, 1) > 0) {
1026 SkDraw drawCopy(d); 1024 newMatrix = untranslate(*d.fMatrix, firstPt.x(), firstPt.y());
1027 drawCopy.fMatrix = &translateMatrix; 1025 d.fMatrix = &newMatrix;
1028 SkPath pathCopy(origPath); 1026 modifiedPath = origPath;
1029 pathCopy.offset(translate.x(), translate.y()); 1027 modifiedPath.offset(-firstPt.x(), -firstPt.y());
1030 this->drawPath(drawCopy, pathCopy, srcPaint, prePathMatrix, true); 1028 pathPtr = &modifiedPath; // NOTE: shader behavior will be off.
1031 return; // NOTE: shader behavior will be off. 1029 pathIsMutable = true;
1030 }
1032 } 1031 }
1033 1032
1034 SkPaint paint = srcPaint; 1033 SkPaint paint = srcPaint;
1035 replace_srcmode_on_opaque_paint(&paint); 1034 replace_srcmode_on_opaque_paint(&paint);
1036 SkPath modifiedPath;
1037 SkPath* pathPtr = const_cast<SkPath*>(&origPath);
1038 1035
1039 SkMatrix matrix = *d.fMatrix; 1036 SkMatrix matrix = *d.fMatrix;
1040 if (prePathMatrix) { 1037 if (prePathMatrix) {
1041 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 1038 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
1042 if (!pathIsMutable) { 1039 if (pathIsMutable) {
1040 pathPtr->transform(*prePathMatrix);
1041 } else {
1042 pathPtr->transform(*prePathMatrix, &modifiedPath);
1043 pathPtr = &modifiedPath; 1043 pathPtr = &modifiedPath;
1044 pathIsMutable = true; 1044 pathIsMutable = true;
1045 } 1045 }
1046 origPath.transform(*prePathMatrix, pathPtr);
1047 } else { 1046 } else {
1048 matrix.preConcat(*prePathMatrix); 1047 matrix.preConcat(*prePathMatrix);
1049 } 1048 }
1050 } 1049 }
1051 1050
1052 if (paint.getPathEffect()) { 1051 if (paint.getPathEffect()) {
1053 if (d.fClip->isEmpty()) { 1052 if (d.fClip->isEmpty()) {
1054 return; 1053 return;
1055 } 1054 }
1056 if (!pathIsMutable) { 1055 bool fill;
1056 if (pathIsMutable) {
1057 fill = paint.getFillPath(*pathPtr, pathPtr);
1058 } else {
1059 fill = paint.getFillPath(*pathPtr, &modifiedPath);
1057 pathPtr = &modifiedPath; 1060 pathPtr = &modifiedPath;
1058 pathIsMutable = true; 1061 pathIsMutable = true;
1059 } 1062 }
1060 bool fill = paint.getFillPath(origPath, pathPtr);
1061 1063
1062 SkPaint noEffectPaint(paint); 1064 SkPaint noEffectPaint(paint);
1063 noEffectPaint.setPathEffect(nullptr); 1065 noEffectPaint.setPathEffect(nullptr);
1064 if (fill) { 1066 if (fill) {
1065 noEffectPaint.setStyle(SkPaint::kFill_Style); 1067 noEffectPaint.setStyle(SkPaint::kFill_Style);
1066 } else { 1068 } else {
1067 noEffectPaint.setStyle(SkPaint::kStroke_Style); 1069 noEffectPaint.setStyle(SkPaint::kStroke_Style);
1068 noEffectPaint.setStrokeWidth(0); 1070 noEffectPaint.setStrokeWidth(0);
1069 } 1071 }
1070 drawPath(d, *pathPtr, noEffectPaint, nullptr, true); 1072 drawPath(d, *pathPtr, noEffectPaint, nullptr, true);
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 case SkPaint::kUTF32_TextEncoding: 1316 case SkPaint::kUTF32_TextEncoding:
1315 transparent.setTextEncoding(srcPaint.getTextEncoding()); 1317 transparent.setTextEncoding(srcPaint.getTextEncoding());
1316 device->drawText(d, text, len, x, y, transparent); 1318 device->drawText(d, text, len, x, y, transparent);
1317 break; 1319 break;
1318 default: 1320 default:
1319 SkFAIL("unknown text encoding"); 1321 SkFAIL("unknown text encoding");
1320 } 1322 }
1321 } 1323 }
1322 1324
1323 1325
1324 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, 1326 void SkPDFDevice::drawText(const SkDraw& srcDraw, const void* text, size_t len,
1325 SkScalar x, SkScalar y, const SkPaint& srcPaint) { 1327 SkScalar x, SkScalar y, const SkPaint& srcPaint) {
1328 SkMatrix newMatrix;
1329 SkDraw d(srcDraw);
1326 if (excessive_translation(*d.fMatrix)) { 1330 if (excessive_translation(*d.fMatrix)) {
1327 SkVector translate; SkMatrix translateMatrix; 1331 newMatrix = untranslate(*d.fMatrix, x, y);
1328 std::tie(translateMatrix, translate) = untranslate(d); 1332 d.fMatrix = &newMatrix;
1329 SkDraw drawCopy(d); 1333 x = 0;
1330 drawCopy.fMatrix = &translateMatrix; 1334 y = 0;
1331 this->drawText(drawCopy, text, len, x + translate.x(),
1332 y + translate.y(), srcPaint);
1333 return; // NOTE: shader behavior will be off.
1334 } 1335 }
1335 1336
1336 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) { 1337 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) {
1337 // https://bug.skia.org/3866 1338 // https://bug.skia.org/3866
1338 SkPath path; 1339 SkPath path;
1339 srcPaint.getTextPath(text, len, x, y, &path); 1340 srcPaint.getTextPath(text, len, x, y, &path);
1340 this->drawPath(d, path, srcPaint, &SkMatrix::I(), true); 1341 this->drawPath(d, path, srcPaint, &SkMatrix::I(), true);
1341 // Draw text transparently to make it copyable/searchable/accessable. 1342 // Draw text transparently to make it copyable/searchable/accessable.
1342 draw_transparent_text(this, d, text, len, x, y, srcPaint); 1343 draw_transparent_text(this, d, text, len, x, y, srcPaint);
1343 return; 1344 return;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1384 SkString encodedString = 1385 SkString encodedString =
1385 format_wide_string(glyphIDsCopy.begin() + consumedGlyphCount, 1386 format_wide_string(glyphIDsCopy.begin() + consumedGlyphCount,
1386 availableGlyphs, font->multiByteGlyphs()); 1387 availableGlyphs, font->multiByteGlyphs());
1387 content.entry()->fContent.writeText(encodedString.c_str()); 1388 content.entry()->fContent.writeText(encodedString.c_str());
1388 consumedGlyphCount += availableGlyphs; 1389 consumedGlyphCount += availableGlyphs;
1389 content.entry()->fContent.writeText(" Tj\n"); 1390 content.entry()->fContent.writeText(" Tj\n");
1390 } 1391 }
1391 content.entry()->fContent.writeText("ET\n"); 1392 content.entry()->fContent.writeText("ET\n");
1392 } 1393 }
1393 1394
1394 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, 1395 void SkPDFDevice::drawPosText(const SkDraw& srcDraw, const void* text, size_t le n,
1395 const SkScalar pos[], int scalarsPerPos, 1396 const SkScalar pos[], int scalarsPerPos,
1396 const SkPoint& offset, const SkPaint& srcPaint) { 1397 const SkPoint& srcOffset, const SkPaint& srcPaint) {
1398 if (len == 0) {
1399 return;
1400 }
1401 SkMatrix newMatrix;
1402 SkDraw d(srcDraw);
1403 SkPoint offset(srcOffset);
1404 SkAutoTMalloc<SkScalar> scalarsBuffer;
1397 if (excessive_translation(*d.fMatrix)) { 1405 if (excessive_translation(*d.fMatrix)) {
1398 SkVector translate; SkMatrix translateMatrix; 1406 SkPoint first;
1399 std::tie(translateMatrix, translate) = untranslate(d); 1407 if (scalarsPerPos != 2) {
1400 SkDraw drawCopy(d); 1408 first.set(pos[0], 0);
1401 drawCopy.fMatrix = &translateMatrix; 1409 } else {
1402 SkPoint offsetCopy = offset; 1410 first.set(pos[0], pos[1]);
1403 SkPoint::Offset(&offsetCopy, 1, translate.x(), translate.y()); 1411 }
1404 this->drawPosText(drawCopy, text, len, pos, scalarsPerPos, offsetCopy, 1412 newMatrix = untranslate(*d.fMatrix,
1405 srcPaint); 1413 first.x() + offset.x(),
1406 return; // NOTE: shader behavior will be off. 1414 first.y() + offset.y());
1415 d.fMatrix = &newMatrix;
1416 offset.set(0, 0); // offset -= offset;
1417 if (first.x() != 0 || first.y() != 0) {
1418 int glyphCount = srcPaint.textToGlyphs(text, len, NULL);
1419 if (scalarsPerPos != 2) {
1420 scalarsBuffer.reset(glyphCount);
1421 for (int i = 0; i < glyphCount; ++i) {
1422 scalarsBuffer[i] = pos[i] - first.x();
1423 }
1424 } else {
1425 scalarsBuffer.reset(2 * glyphCount);
1426 for (int i = 0; i < glyphCount; ++i) {
1427 scalarsBuffer[2 * i] = pos[2 * i] - first.x();
1428 scalarsBuffer[2 * i + 1] = pos[2 * i + 1] - first.y();
1429 }
1430 }
1431 pos = &scalarsBuffer[0];
1432 }
1407 } 1433 }
1408 1434
1409 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) { 1435 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) {
1410 const SkPoint* positions = reinterpret_cast<const SkPoint*>(pos); 1436 const SkPoint* positions = reinterpret_cast<const SkPoint*>(pos);
1411 SkAutoTMalloc<SkPoint> positionsBuffer; 1437 SkAutoTMalloc<SkPoint> positionsBuffer;
1412 if (2 != scalarsPerPos) { 1438 if (2 != scalarsPerPos) {
1413 int glyphCount = srcPaint.textToGlyphs(text, len, NULL); 1439 int glyphCount = srcPaint.textToGlyphs(text, len, NULL);
1414 positionsBuffer.reset(glyphCount); 1440 positionsBuffer.reset(glyphCount);
1415 for (int i = 0; i < glyphCount; ++i) { 1441 for (int i = 0; i < glyphCount; ++i) {
1416 positionsBuffer[i].set(pos[i], 0.0f); 1442 positionsBuffer[i].set(pos[i], 0.0f);
(...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after
2436 pdfimage.reset(SkPDFCreateBitmapObject( 2462 pdfimage.reset(SkPDFCreateBitmapObject(
2437 image, fCanon->fPixelSerializer)); 2463 image, fCanon->fPixelSerializer));
2438 if (!pdfimage) { 2464 if (!pdfimage) {
2439 return; 2465 return;
2440 } 2466 }
2441 fCanon->addPDFBitmap(image->uniqueID(), pdfimage); 2467 fCanon->addPDFBitmap(image->uniqueID(), pdfimage);
2442 } 2468 }
2443 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), 2469 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()),
2444 &content.entry()->fContent); 2470 &content.entry()->fContent);
2445 } 2471 }
OLDNEW
« no previous file with comments | « no previous file | tests/PDFDocumentTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698