blob: a98aacbb8f2b47fcae5713b2b71a057d89002a4d [file] [log] [blame]
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2010 The Android Open Source Project
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +00006 */
7
edisonn@google.comd9dfa182013-04-24 13:01:01 +00008#include "SkBitmap.h"
vandebo@chromium.org4e1cc6a2013-01-25 19:27:23 +00009#include "SkCanvas.h"
reed@google.com8a85d0c2011-06-24 19:12:12 +000010#include "SkData.h"
halcanary3d32d502015-03-01 06:55:20 -080011#include "SkDocument.h"
vandebo@chromium.org421d6442011-07-20 17:39:01 +000012#include "SkFlate.h"
edisonn@google.comd9dfa182013-04-24 13:01:01 +000013#include "SkImageEncoder.h"
14#include "SkMatrix.h"
halcanarya1f1ee92015-02-20 06:17:26 -080015#include "SkPDFCanon.h"
vandebo@chromium.org4e1cc6a2013-01-25 19:27:23 +000016#include "SkPDFDevice.h"
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000017#include "SkPDFStream.h"
18#include "SkPDFTypes.h"
senorblancob0e89dc2014-10-20 14:03:12 -070019#include "SkReadBuffer.h"
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000020#include "SkScalar.h"
21#include "SkStream.h"
vandebo@chromium.org421d6442011-07-20 17:39:01 +000022#include "SkTypes.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000023#include "Test.h"
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000024
commit-bot@chromium.org608ea652013-10-03 19:29:21 +000025#define DUMMY_TEXT "DCT compessed stream."
26
reed@google.com8a85d0c2011-06-24 19:12:12 +000027static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
28 const void* buffer, size_t len) {
29 SkAutoDataUnref data(stream.copyToData());
robertphillips@google.com59f46b82012-07-10 17:30:58 +000030 if (offset + len > data->size()) {
reed@google.com8a85d0c2011-06-24 19:12:12 +000031 return false;
32 }
robertphillips@google.com59f46b82012-07-10 17:30:58 +000033 return memcmp(data->bytes() + offset, buffer, len) == 0;
reed@google.com8a85d0c2011-06-24 19:12:12 +000034}
35
halcanary6a144342015-01-23 11:45:10 -080036static void emit_object(SkPDFObject* object,
37 SkWStream* stream,
halcanary37c46ca2015-03-31 12:30:20 -070038 const SkPDFObjNumMap& objNumMap,
39 const SkPDFSubstituteMap& substitutes,
halcanary6a144342015-01-23 11:45:10 -080040 bool indirect) {
halcanary37c46ca2015-03-31 12:30:20 -070041 SkPDFObject* realObject = substitutes.getSubstitute(object);
halcanary6a144342015-01-23 11:45:10 -080042 if (indirect) {
halcanary37c46ca2015-03-31 12:30:20 -070043 stream->writeDecAsText(objNumMap.getObjectNumber(realObject));
halcanarybf799cd2015-02-10 13:32:09 -080044 stream->writeText(" 0 obj\n"); // Generation number is always 0.
halcanary37c46ca2015-03-31 12:30:20 -070045 realObject->emitObject(stream, objNumMap, substitutes);
halcanary6a144342015-01-23 11:45:10 -080046 stream->writeText("\nendobj\n");
47 } else {
halcanary37c46ca2015-03-31 12:30:20 -070048 realObject->emitObject(stream, objNumMap, substitutes);
halcanary6a144342015-01-23 11:45:10 -080049 }
50}
51
52static size_t get_output_size(SkPDFObject* object,
halcanary37c46ca2015-03-31 12:30:20 -070053 const SkPDFObjNumMap& objNumMap,
54 const SkPDFSubstituteMap& substitutes,
halcanary6a144342015-01-23 11:45:10 -080055 bool indirect) {
56 SkDynamicMemoryWStream buffer;
halcanary37c46ca2015-03-31 12:30:20 -070057 emit_object(object, &buffer, objNumMap, substitutes, indirect);
halcanary6a144342015-01-23 11:45:10 -080058 return buffer.getOffset();
59}
60
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000061static void CheckObjectOutput(skiatest::Reporter* reporter, SkPDFObject* obj,
vandebo@chromium.org421d6442011-07-20 17:39:01 +000062 const char* expectedData, size_t expectedSize,
mtkleincabc08c2015-02-19 08:29:24 -080063 bool indirect) {
halcanary37c46ca2015-03-31 12:30:20 -070064 SkPDFSubstituteMap substituteMap;
65 SkPDFObjNumMap catalog;
66 size_t directSize = get_output_size(obj, catalog, substituteMap, false);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000067 REPORTER_ASSERT(reporter, directSize == expectedSize);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000068
69 SkDynamicMemoryWStream buffer;
halcanary37c46ca2015-03-31 12:30:20 -070070 emit_object(obj, &buffer, catalog, substituteMap, false);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000071 REPORTER_ASSERT(reporter, directSize == buffer.getOffset());
vandebo@chromium.org421d6442011-07-20 17:39:01 +000072 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedData,
reed@google.com8a85d0c2011-06-24 19:12:12 +000073 directSize));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000074
75 if (indirect) {
76 // Indirect output.
77 static char header[] = "1 0 obj\n";
78 static size_t headerLen = strlen(header);
79 static char footer[] = "\nendobj\n";
80 static size_t footerLen = strlen(footer);
81
halcanaryf41061c2015-03-25 11:29:18 -070082 catalog.addObject(obj);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000083
halcanary37c46ca2015-03-31 12:30:20 -070084 size_t indirectSize =
85 get_output_size(obj, catalog, substituteMap, true);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000086 REPORTER_ASSERT(reporter,
87 indirectSize == directSize + headerLen + footerLen);
88
89 buffer.reset();
halcanary37c46ca2015-03-31 12:30:20 -070090 emit_object(obj, &buffer, catalog, substituteMap, true);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000091 REPORTER_ASSERT(reporter, indirectSize == buffer.getOffset());
reed@google.com8a85d0c2011-06-24 19:12:12 +000092 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, header, headerLen));
vandebo@chromium.org421d6442011-07-20 17:39:01 +000093 REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen, expectedData,
reed@google.com8a85d0c2011-06-24 19:12:12 +000094 directSize));
95 REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen + directSize,
96 footer, footerLen));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000097 }
98}
99
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000100static void SimpleCheckObjectOutput(skiatest::Reporter* reporter,
101 SkPDFObject* obj,
robertphillips@google.com4debcac2012-05-14 16:33:36 +0000102 const char* expectedResult) {
103 CheckObjectOutput(reporter, obj, expectedResult,
mtkleincabc08c2015-02-19 08:29:24 -0800104 strlen(expectedResult), true);
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000105}
106
107static void TestPDFStream(skiatest::Reporter* reporter) {
108 char streamBytes[] = "Test\nFoo\tBar";
scroggoa1193e42015-01-21 12:09:53 -0800109 SkAutoTDelete<SkMemoryStream> streamData(new SkMemoryStream(
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000110 streamBytes, strlen(streamBytes), true));
111 SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData.get()));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000112 SimpleCheckObjectOutput(
113 reporter, stream.get(),
halcanary37c46ca2015-03-31 12:30:20 -0700114 "<</Length 12>> stream\nTest\nFoo\tBar\nendstream");
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000115 stream->insert("Attribute", new SkPDFInt(42))->unref();
116 SimpleCheckObjectOutput(reporter, stream.get(),
halcanary37c46ca2015-03-31 12:30:20 -0700117 "<</Length 12\n/Attribute 42>> stream\n"
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000118 "Test\nFoo\tBar\nendstream");
119
halcanary91d1d622015-02-17 14:43:06 -0800120 {
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000121 char streamBytes2[] = "This is a longer string, so that compression "
122 "can do something with it. With shorter strings, "
123 "the short circuit logic cuts in and we end up "
124 "with an uncompressed string.";
125 SkAutoDataUnref streamData2(SkData::NewWithCopy(streamBytes2,
126 strlen(streamBytes2)));
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000127 SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData2.get()));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000128
129 SkDynamicMemoryWStream compressedByteStream;
130 SkFlate::Deflate(streamData2.get(), &compressedByteStream);
131 SkAutoDataUnref compressedData(compressedByteStream.copyToData());
132
mtkleincabc08c2015-02-19 08:29:24 -0800133 SkDynamicMemoryWStream expected;
halcanary37c46ca2015-03-31 12:30:20 -0700134 expected.writeText("<</Filter /FlateDecode\n/Length 116>> stream\n");
mtkleincabc08c2015-02-19 08:29:24 -0800135 expected.write(compressedData->data(), compressedData->size());
136 expected.writeText("\nendstream");
137 SkAutoDataUnref expectedResultData2(expected.copyToData());
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000138 CheckObjectOutput(reporter, stream.get(),
robertphillips@google.com59f46b82012-07-10 17:30:58 +0000139 (const char*) expectedResultData2->data(),
mtkleincabc08c2015-02-19 08:29:24 -0800140 expectedResultData2->size(), true);
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000141 }
142}
143
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000144static void TestCatalog(skiatest::Reporter* reporter) {
halcanary37c46ca2015-03-31 12:30:20 -0700145 SkPDFSubstituteMap substituteMap;
146 SkPDFObjNumMap catalog;
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000147 SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1));
148 SkAutoTUnref<SkPDFInt> int2(new SkPDFInt(2));
149 SkAutoTUnref<SkPDFInt> int3(new SkPDFInt(3));
150 int1.get()->ref();
151 SkAutoTUnref<SkPDFInt> int1Again(int1.get());
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000152
halcanaryf41061c2015-03-25 11:29:18 -0700153 catalog.addObject(int1.get());
154 catalog.addObject(int2.get());
155 catalog.addObject(int3.get());
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000156
halcanarybf799cd2015-02-10 13:32:09 -0800157 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1.get()) == 1);
158 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int2.get()) == 2);
159 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int3.get()) == 3);
160 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1Again.get()) == 1);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000161}
162
163static void TestObjectRef(skiatest::Reporter* reporter) {
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000164 SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1));
165 SkAutoTUnref<SkPDFInt> int2(new SkPDFInt(2));
166 SkAutoTUnref<SkPDFObjRef> int2ref(new SkPDFObjRef(int2.get()));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000167
halcanary37c46ca2015-03-31 12:30:20 -0700168 SkPDFSubstituteMap substituteMap;
169 SkPDFObjNumMap catalog;
halcanaryf41061c2015-03-25 11:29:18 -0700170 catalog.addObject(int1.get());
171 catalog.addObject(int2.get());
halcanarybf799cd2015-02-10 13:32:09 -0800172 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1.get()) == 1);
173 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int2.get()) == 2);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000174
175 char expectedResult[] = "2 0 R";
176 SkDynamicMemoryWStream buffer;
halcanary37c46ca2015-03-31 12:30:20 -0700177 int2ref->emitObject(&buffer, catalog, substituteMap);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000178 REPORTER_ASSERT(reporter, buffer.getOffset() == strlen(expectedResult));
reed@google.com8a85d0c2011-06-24 19:12:12 +0000179 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResult,
180 buffer.getOffset()));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000181}
182
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +0000183static void TestSubstitute(skiatest::Reporter* reporter) {
halcanaryf3d53a02015-03-24 15:29:39 -0700184 SkAutoTUnref<SkPDFDict> proxy(new SkPDFDict());
185 SkAutoTUnref<SkPDFDict> stub(new SkPDFDict());
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +0000186
halcanarybf799cd2015-02-10 13:32:09 -0800187 proxy->insert("Value", new SkPDFInt(33))->unref();
188 stub->insert("Value", new SkPDFInt(44))->unref();
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +0000189
halcanary37c46ca2015-03-31 12:30:20 -0700190 SkPDFSubstituteMap substituteMap;
191 substituteMap.setSubstitute(proxy.get(), stub.get());
192 SkPDFObjNumMap catalog;
halcanaryf41061c2015-03-25 11:29:18 -0700193 catalog.addObject(proxy.get());
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +0000194
halcanary37c46ca2015-03-31 12:30:20 -0700195 REPORTER_ASSERT(reporter, stub.get() == substituteMap.getSubstitute(proxy));
196 REPORTER_ASSERT(reporter, proxy.get() != substituteMap.getSubstitute(stub));
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +0000197}
198
vandebo@chromium.org4e1cc6a2013-01-25 19:27:23 +0000199// This test used to assert without the fix submitted for
200// http://code.google.com/p/skia/issues/detail?id=1083.
201// SKP files might have invalid glyph ids. This test ensures they are ignored,
202// and there is no assert on input data in Debug mode.
sugoi@google.com54f0d1b2013-02-27 19:17:41 +0000203static void test_issue1083() {
halcanary3d32d502015-03-01 06:55:20 -0800204 SkDynamicMemoryWStream outStream;
205 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&outStream));
206 SkCanvas* canvas = doc->beginPage(100.0f, 100.0f);
vandebo@chromium.org4e1cc6a2013-01-25 19:27:23 +0000207 SkPaint paint;
208 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
209
210 uint16_t glyphID = 65000;
halcanary3d32d502015-03-01 06:55:20 -0800211 canvas->drawText(&glyphID, 2, 0, 0, paint);
vandebo@chromium.org4e1cc6a2013-01-25 19:27:23 +0000212
halcanary3d32d502015-03-01 06:55:20 -0800213 doc->close();
vandebo@chromium.org4e1cc6a2013-01-25 19:27:23 +0000214}
215
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000216DEF_TEST(PDFPrimitives, reporter) {
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000217 SkAutoTUnref<SkPDFInt> int42(new SkPDFInt(42));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000218 SimpleCheckObjectOutput(reporter, int42.get(), "42");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000219
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000220 SkAutoTUnref<SkPDFScalar> realHalf(new SkPDFScalar(SK_ScalarHalf));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000221 SimpleCheckObjectOutput(reporter, realHalf.get(), "0.5");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000222
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000223 SkAutoTUnref<SkPDFScalar> bigScalar(new SkPDFScalar(110999.75f));
vandebo@chromium.org6cc26da2011-05-18 17:08:05 +0000224#if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000225 SimpleCheckObjectOutput(reporter, bigScalar.get(), "111000");
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000226#else
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000227 SimpleCheckObjectOutput(reporter, bigScalar.get(), "110999.75");
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000228
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000229 SkAutoTUnref<SkPDFScalar> biggerScalar(new SkPDFScalar(50000000.1));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000230 SimpleCheckObjectOutput(reporter, biggerScalar.get(), "50000000");
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000231
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000232 SkAutoTUnref<SkPDFScalar> smallestScalar(new SkPDFScalar(1.0/65536));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000233 SimpleCheckObjectOutput(reporter, smallestScalar.get(), "0.00001526");
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000234#endif
235
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000236 SkAutoTUnref<SkPDFString> stringSimple(
237 new SkPDFString("test ) string ( foo"));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000238 SimpleCheckObjectOutput(reporter, stringSimple.get(),
239 "(test \\) string \\( foo)");
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000240 SkAutoTUnref<SkPDFString> stringComplex(
241 new SkPDFString("\ttest ) string ( foo"));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000242 SimpleCheckObjectOutput(reporter, stringComplex.get(),
243 "<0974657374202920737472696E67202820666F6F>");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000244
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000245 SkAutoTUnref<SkPDFName> name(new SkPDFName("Test name\twith#tab"));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000246 const char expectedResult[] = "/Test#20name#09with#23tab";
247 CheckObjectOutput(reporter, name.get(), expectedResult,
mtkleincabc08c2015-02-19 08:29:24 -0800248 strlen(expectedResult), false);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000249
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000250 SkAutoTUnref<SkPDFName> escapedName(new SkPDFName("A#/%()<>[]{}B"));
vandebo@chromium.org251a7662012-09-21 17:50:50 +0000251 const char escapedNameExpected[] = "/A#23#2F#25#28#29#3C#3E#5B#5D#7B#7DB";
252 CheckObjectOutput(reporter, escapedName.get(), escapedNameExpected,
mtkleincabc08c2015-02-19 08:29:24 -0800253 strlen(escapedNameExpected), false);
vandebo@chromium.org251a7662012-09-21 17:50:50 +0000254
vandebo@chromium.orgc0376fe2012-03-05 18:44:33 +0000255 // Test that we correctly handle characters with the high-bit set.
bungeman@google.comf8aa18c2012-03-19 21:04:52 +0000256 const unsigned char highBitCString[] = {0xDE, 0xAD, 'b', 'e', 0xEF, 0};
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000257 SkAutoTUnref<SkPDFName> highBitName(
258 new SkPDFName((const char*)highBitCString));
vandebo@chromium.orgc0376fe2012-03-05 18:44:33 +0000259 const char highBitExpectedResult[] = "/#DE#ADbe#EF";
260 CheckObjectOutput(reporter, highBitName.get(), highBitExpectedResult,
mtkleincabc08c2015-02-19 08:29:24 -0800261 strlen(highBitExpectedResult), false);
vandebo@chromium.orgc0376fe2012-03-05 18:44:33 +0000262
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000263 SkAutoTUnref<SkPDFArray> array(new SkPDFArray);
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000264 SimpleCheckObjectOutput(reporter, array.get(), "[]");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000265 array->append(int42.get());
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000266 SimpleCheckObjectOutput(reporter, array.get(), "[42]");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000267 array->append(realHalf.get());
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000268 SimpleCheckObjectOutput(reporter, array.get(), "[42 0.5]");
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000269 SkAutoTUnref<SkPDFInt> int0(new SkPDFInt(0));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000270 array->append(int0.get());
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000271 SimpleCheckObjectOutput(reporter, array.get(), "[42 0.5 0]");
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000272 SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000273 array->setAt(0, int1.get());
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000274 SimpleCheckObjectOutput(reporter, array.get(), "[1 0.5 0]");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000275
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000276 SkAutoTUnref<SkPDFDict> dict(new SkPDFDict);
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000277 SimpleCheckObjectOutput(reporter, dict.get(), "<<>>");
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000278 SkAutoTUnref<SkPDFName> n1(new SkPDFName("n1"));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000279 dict->insert(n1.get(), int42.get());
halcanary37c46ca2015-03-31 12:30:20 -0700280 SimpleCheckObjectOutput(reporter, dict.get(), "<</n1 42>>");
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000281 SkAutoTUnref<SkPDFName> n2(new SkPDFName("n2"));
282 SkAutoTUnref<SkPDFName> n3(new SkPDFName("n3"));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000283 dict->insert(n2.get(), realHalf.get());
284 dict->insert(n3.get(), array.get());
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000285 SimpleCheckObjectOutput(reporter, dict.get(),
halcanary37c46ca2015-03-31 12:30:20 -0700286 "<</n1 42\n/n2 0.5\n/n3 [1 0.5 0]>>");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000287
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000288 TestPDFStream(reporter);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000289
290 TestCatalog(reporter);
291
292 TestObjectRef(reporter);
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +0000293
294 TestSubstitute(reporter);
vandebo@chromium.org4e1cc6a2013-01-25 19:27:23 +0000295
sugoi@google.com54f0d1b2013-02-27 19:17:41 +0000296 test_issue1083();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000297}
senorblancob0e89dc2014-10-20 14:03:12 -0700298
299namespace {
300
301class DummyImageFilter : public SkImageFilter {
302public:
303 DummyImageFilter(bool visited = false) : SkImageFilter(0, NULL), fVisited(visited) {}
mtklein36352bf2015-03-25 18:17:31 -0700304 ~DummyImageFilter() override {}
senorblancob0e89dc2014-10-20 14:03:12 -0700305 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
mtklein36352bf2015-03-25 18:17:31 -0700306 SkBitmap* result, SkIPoint* offset) const override {
senorblancob0e89dc2014-10-20 14:03:12 -0700307 fVisited = true;
308 offset->fX = offset->fY = 0;
309 *result = src;
310 return true;
311 }
robertphillipsf3f5bad2014-12-19 13:49:15 -0800312 SK_TO_STRING_OVERRIDE()
senorblancob0e89dc2014-10-20 14:03:12 -0700313 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DummyImageFilter)
senorblancob0e89dc2014-10-20 14:03:12 -0700314 bool visited() const { return fVisited; }
315
316private:
317 mutable bool fVisited;
318};
319
320SkFlattenable* DummyImageFilter::CreateProc(SkReadBuffer& buffer) {
321 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
322 bool visited = buffer.readBool();
323 return SkNEW_ARGS(DummyImageFilter, (visited));
324}
325
robertphillipsf3f5bad2014-12-19 13:49:15 -0800326#ifndef SK_IGNORE_TO_STRING
327void DummyImageFilter::toString(SkString* str) const {
328 str->appendf("DummyImageFilter: (");
329 str->append(")");
330}
331#endif
332
senorblancob0e89dc2014-10-20 14:03:12 -0700333};
334
335// Check that PDF rendering of image filters successfully falls back to
336// CPU rasterization.
337DEF_TEST(PDFImageFilter, reporter) {
halcanary3d32d502015-03-01 06:55:20 -0800338 SkDynamicMemoryWStream stream;
339 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&stream));
340 SkCanvas* canvas = doc->beginPage(100.0f, 100.0f);
341
senorblancob0e89dc2014-10-20 14:03:12 -0700342 SkAutoTUnref<DummyImageFilter> filter(new DummyImageFilter());
343
344 // Filter just created; should be unvisited.
345 REPORTER_ASSERT(reporter, !filter->visited());
346 SkPaint paint;
347 paint.setImageFilter(filter.get());
halcanary3d32d502015-03-01 06:55:20 -0800348 canvas->drawRect(SkRect::MakeWH(100, 100), paint);
349 doc->close();
senorblancob0e89dc2014-10-20 14:03:12 -0700350
351 // Filter was used in rendering; should be visited.
352 REPORTER_ASSERT(reporter, filter->visited());
353}