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

Side by Side Diff: tests/PDFPrimitivesTest.cpp

Issue 1049753002: SkPDF: Factor SkPDFCatalog into SkPDFObjNumMap and SkPDFSubstituteMap (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: full Created 5 years, 8 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
« src/pdf/SkPDFStream.cpp ('K') | « src/pdf/SkPDFTypes.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 2010 The Android Open Source Project 2 * Copyright 2010 The Android Open Source Project
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 "SkBitmap.h" 8 #include "SkBitmap.h"
9 #include "SkCanvas.h" 9 #include "SkCanvas.h"
10 #include "SkData.h" 10 #include "SkData.h"
11 #include "SkDocument.h" 11 #include "SkDocument.h"
12 #include "SkFlate.h" 12 #include "SkFlate.h"
13 #include "SkImageEncoder.h" 13 #include "SkImageEncoder.h"
14 #include "SkMatrix.h" 14 #include "SkMatrix.h"
15 #include "SkPDFCanon.h" 15 #include "SkPDFCanon.h"
16 #include "SkPDFCatalog.h"
17 #include "SkPDFDevice.h" 16 #include "SkPDFDevice.h"
18 #include "SkPDFStream.h" 17 #include "SkPDFStream.h"
19 #include "SkPDFTypes.h" 18 #include "SkPDFTypes.h"
20 #include "SkReadBuffer.h" 19 #include "SkReadBuffer.h"
21 #include "SkScalar.h" 20 #include "SkScalar.h"
22 #include "SkStream.h" 21 #include "SkStream.h"
23 #include "SkTypes.h" 22 #include "SkTypes.h"
24 #include "Test.h" 23 #include "Test.h"
25 24
26 #define DUMMY_TEXT "DCT compessed stream." 25 #define DUMMY_TEXT "DCT compessed stream."
27 26
28 static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset, 27 static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
29 const void* buffer, size_t len) { 28 const void* buffer, size_t len) {
30 SkAutoDataUnref data(stream.copyToData()); 29 SkAutoDataUnref data(stream.copyToData());
31 if (offset + len > data->size()) { 30 if (offset + len > data->size()) {
32 return false; 31 return false;
33 } 32 }
34 return memcmp(data->bytes() + offset, buffer, len) == 0; 33 return memcmp(data->bytes() + offset, buffer, len) == 0;
35 } 34 }
36 35
37 static void emit_object(SkPDFObject* object, 36 static void emit_object(SkPDFObject* object,
38 SkWStream* stream, 37 SkWStream* stream,
39 SkPDFCatalog* catalog, 38 const SkPDFObjNumMap& objNumMap,
39 const SkPDFSubstituteMap& substitutes,
40 bool indirect) { 40 bool indirect) {
41 SkPDFObject* realObject = catalog->getSubstituteObject(object); 41 SkPDFObject* realObject = substitutes.getSubstitute(object);
42 if (indirect) { 42 if (indirect) {
43 stream->writeDecAsText(catalog->getObjectNumber(object)); 43 stream->writeDecAsText(objNumMap.getObjectNumber(realObject));
44 stream->writeText(" 0 obj\n"); // Generation number is always 0. 44 stream->writeText(" 0 obj\n"); // Generation number is always 0.
45 realObject->emitObject(stream, catalog); 45 realObject->emitObject(stream, objNumMap, substitutes);
46 stream->writeText("\nendobj\n"); 46 stream->writeText("\nendobj\n");
47 } else { 47 } else {
48 realObject->emitObject(stream, catalog); 48 realObject->emitObject(stream, objNumMap, substitutes);
49 } 49 }
50 } 50 }
51 51
52 static size_t get_output_size(SkPDFObject* object, 52 static size_t get_output_size(SkPDFObject* object,
53 SkPDFCatalog* catalog, 53 const SkPDFObjNumMap& objNumMap,
54 const SkPDFSubstituteMap& substitutes,
54 bool indirect) { 55 bool indirect) {
55 SkDynamicMemoryWStream buffer; 56 SkDynamicMemoryWStream buffer;
56 emit_object(object, &buffer, catalog, indirect); 57 emit_object(object, &buffer, objNumMap, substitutes, indirect);
57 return buffer.getOffset(); 58 return buffer.getOffset();
58 } 59 }
59 60
60 static void CheckObjectOutput(skiatest::Reporter* reporter, SkPDFObject* obj, 61 static void CheckObjectOutput(skiatest::Reporter* reporter, SkPDFObject* obj,
61 const char* expectedData, size_t expectedSize, 62 const char* expectedData, size_t expectedSize,
62 bool indirect) { 63 bool indirect) {
63 SkPDFCatalog catalog; 64 SkPDFSubstituteMap substituteMap;
64 size_t directSize = get_output_size(obj, &catalog, false); 65 SkPDFObjNumMap catalog;
66 size_t directSize = get_output_size(obj, catalog, substituteMap, false);
65 REPORTER_ASSERT(reporter, directSize == expectedSize); 67 REPORTER_ASSERT(reporter, directSize == expectedSize);
66 68
67 SkDynamicMemoryWStream buffer; 69 SkDynamicMemoryWStream buffer;
68 emit_object(obj, &buffer, &catalog, false); 70 emit_object(obj, &buffer, catalog, substituteMap, false);
69 REPORTER_ASSERT(reporter, directSize == buffer.getOffset()); 71 REPORTER_ASSERT(reporter, directSize == buffer.getOffset());
70 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedData, 72 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedData,
71 directSize)); 73 directSize));
72 74
73 if (indirect) { 75 if (indirect) {
74 // Indirect output. 76 // Indirect output.
75 static char header[] = "1 0 obj\n"; 77 static char header[] = "1 0 obj\n";
76 static size_t headerLen = strlen(header); 78 static size_t headerLen = strlen(header);
77 static char footer[] = "\nendobj\n"; 79 static char footer[] = "\nendobj\n";
78 static size_t footerLen = strlen(footer); 80 static size_t footerLen = strlen(footer);
79 81
80 catalog.addObject(obj); 82 catalog.addObject(obj);
81 83
82 size_t indirectSize = get_output_size(obj, &catalog, true); 84 size_t indirectSize =
85 get_output_size(obj, catalog, substituteMap, true);
83 REPORTER_ASSERT(reporter, 86 REPORTER_ASSERT(reporter,
84 indirectSize == directSize + headerLen + footerLen); 87 indirectSize == directSize + headerLen + footerLen);
85 88
86 buffer.reset(); 89 buffer.reset();
87 emit_object(obj, &buffer, &catalog, true); 90 emit_object(obj, &buffer, catalog, substituteMap, true);
88 REPORTER_ASSERT(reporter, indirectSize == buffer.getOffset()); 91 REPORTER_ASSERT(reporter, indirectSize == buffer.getOffset());
89 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, header, headerLen)); 92 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, header, headerLen));
90 REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen, expectedData, 93 REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen, expectedData,
91 directSize)); 94 directSize));
92 REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen + directSize, 95 REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen + directSize,
93 footer, footerLen)); 96 footer, footerLen));
94 } 97 }
95 } 98 }
96 99
97 static void SimpleCheckObjectOutput(skiatest::Reporter* reporter, 100 static void SimpleCheckObjectOutput(skiatest::Reporter* reporter,
98 SkPDFObject* obj, 101 SkPDFObject* obj,
99 const char* expectedResult) { 102 const char* expectedResult) {
100 CheckObjectOutput(reporter, obj, expectedResult, 103 CheckObjectOutput(reporter, obj, expectedResult,
101 strlen(expectedResult), true); 104 strlen(expectedResult), true);
102 } 105 }
103 106
104 static void TestPDFStream(skiatest::Reporter* reporter) { 107 static void TestPDFStream(skiatest::Reporter* reporter) {
105 char streamBytes[] = "Test\nFoo\tBar"; 108 char streamBytes[] = "Test\nFoo\tBar";
106 SkAutoTDelete<SkMemoryStream> streamData(new SkMemoryStream( 109 SkAutoTDelete<SkMemoryStream> streamData(new SkMemoryStream(
107 streamBytes, strlen(streamBytes), true)); 110 streamBytes, strlen(streamBytes), true));
108 SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData.get())); 111 SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData.get()));
109 SimpleCheckObjectOutput( 112 SimpleCheckObjectOutput(
110 reporter, stream.get(), 113 reporter, stream.get(),
111 "<</Length 12\n>> stream\nTest\nFoo\tBar\nendstream"); 114 "<</Length 12>> stream\nTest\nFoo\tBar\nendstream");
112 stream->insert("Attribute", new SkPDFInt(42))->unref(); 115 stream->insert("Attribute", new SkPDFInt(42))->unref();
113 SimpleCheckObjectOutput(reporter, stream.get(), 116 SimpleCheckObjectOutput(reporter, stream.get(),
114 "<</Length 12\n/Attribute 42\n>> stream\n" 117 "<</Length 12\n/Attribute 42>> stream\n"
115 "Test\nFoo\tBar\nendstream"); 118 "Test\nFoo\tBar\nendstream");
116 119
117 { 120 {
118 char streamBytes2[] = "This is a longer string, so that compression " 121 char streamBytes2[] = "This is a longer string, so that compression "
119 "can do something with it. With shorter strings, " 122 "can do something with it. With shorter strings, "
120 "the short circuit logic cuts in and we end up " 123 "the short circuit logic cuts in and we end up "
121 "with an uncompressed string."; 124 "with an uncompressed string.";
122 SkAutoDataUnref streamData2(SkData::NewWithCopy(streamBytes2, 125 SkAutoDataUnref streamData2(SkData::NewWithCopy(streamBytes2,
123 strlen(streamBytes2))); 126 strlen(streamBytes2)));
124 SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData2.get())); 127 SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData2.get()));
125 128
126 SkDynamicMemoryWStream compressedByteStream; 129 SkDynamicMemoryWStream compressedByteStream;
127 SkFlate::Deflate(streamData2.get(), &compressedByteStream); 130 SkFlate::Deflate(streamData2.get(), &compressedByteStream);
128 SkAutoDataUnref compressedData(compressedByteStream.copyToData()); 131 SkAutoDataUnref compressedData(compressedByteStream.copyToData());
129 132
130 SkDynamicMemoryWStream expected; 133 SkDynamicMemoryWStream expected;
131 expected.writeText("<</Filter /FlateDecode\n/Length 116\n" 134 expected.writeText("<</Filter /FlateDecode\n/Length 116>> stream\n");
132 ">> stream\n");
133 expected.write(compressedData->data(), compressedData->size()); 135 expected.write(compressedData->data(), compressedData->size());
134 expected.writeText("\nendstream"); 136 expected.writeText("\nendstream");
135 SkAutoDataUnref expectedResultData2(expected.copyToData()); 137 SkAutoDataUnref expectedResultData2(expected.copyToData());
136 CheckObjectOutput(reporter, stream.get(), 138 CheckObjectOutput(reporter, stream.get(),
137 (const char*) expectedResultData2->data(), 139 (const char*) expectedResultData2->data(),
138 expectedResultData2->size(), true); 140 expectedResultData2->size(), true);
139 } 141 }
140 } 142 }
141 143
142 static void TestCatalog(skiatest::Reporter* reporter) { 144 static void TestCatalog(skiatest::Reporter* reporter) {
143 SkPDFCatalog catalog; 145 SkPDFSubstituteMap substituteMap;
146 SkPDFObjNumMap catalog;
144 SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1)); 147 SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1));
145 SkAutoTUnref<SkPDFInt> int2(new SkPDFInt(2)); 148 SkAutoTUnref<SkPDFInt> int2(new SkPDFInt(2));
146 SkAutoTUnref<SkPDFInt> int3(new SkPDFInt(3)); 149 SkAutoTUnref<SkPDFInt> int3(new SkPDFInt(3));
147 int1.get()->ref(); 150 int1.get()->ref();
148 SkAutoTUnref<SkPDFInt> int1Again(int1.get()); 151 SkAutoTUnref<SkPDFInt> int1Again(int1.get());
149 152
150 catalog.addObject(int1.get()); 153 catalog.addObject(int1.get());
151 catalog.addObject(int2.get()); 154 catalog.addObject(int2.get());
152 catalog.addObject(int3.get()); 155 catalog.addObject(int3.get());
153 156
154 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1.get()) == 1); 157 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1.get()) == 1);
155 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int2.get()) == 2); 158 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int2.get()) == 2);
156 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int3.get()) == 3); 159 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int3.get()) == 3);
157 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1Again.get()) == 1); 160 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1Again.get()) == 1);
158 } 161 }
159 162
160 static void TestObjectRef(skiatest::Reporter* reporter) { 163 static void TestObjectRef(skiatest::Reporter* reporter) {
161 SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1)); 164 SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1));
162 SkAutoTUnref<SkPDFInt> int2(new SkPDFInt(2)); 165 SkAutoTUnref<SkPDFInt> int2(new SkPDFInt(2));
163 SkAutoTUnref<SkPDFObjRef> int2ref(new SkPDFObjRef(int2.get())); 166 SkAutoTUnref<SkPDFObjRef> int2ref(new SkPDFObjRef(int2.get()));
164 167
165 SkPDFCatalog catalog; 168 SkPDFSubstituteMap substituteMap;
169 SkPDFObjNumMap catalog;
166 catalog.addObject(int1.get()); 170 catalog.addObject(int1.get());
167 catalog.addObject(int2.get()); 171 catalog.addObject(int2.get());
168 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1.get()) == 1); 172 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1.get()) == 1);
169 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int2.get()) == 2); 173 REPORTER_ASSERT(reporter, catalog.getObjectNumber(int2.get()) == 2);
170 174
171 char expectedResult[] = "2 0 R"; 175 char expectedResult[] = "2 0 R";
172 SkDynamicMemoryWStream buffer; 176 SkDynamicMemoryWStream buffer;
173 int2ref->emitObject(&buffer, &catalog); 177 int2ref->emitObject(&buffer, catalog, substituteMap);
174 REPORTER_ASSERT(reporter, buffer.getOffset() == strlen(expectedResult)); 178 REPORTER_ASSERT(reporter, buffer.getOffset() == strlen(expectedResult));
175 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResult, 179 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResult,
176 buffer.getOffset())); 180 buffer.getOffset()));
177 } 181 }
178 182
179 static void TestSubstitute(skiatest::Reporter* reporter) { 183 static void TestSubstitute(skiatest::Reporter* reporter) {
180 SkAutoTUnref<SkPDFDict> proxy(new SkPDFDict()); 184 SkAutoTUnref<SkPDFDict> proxy(new SkPDFDict());
181 SkAutoTUnref<SkPDFDict> stub(new SkPDFDict()); 185 SkAutoTUnref<SkPDFDict> stub(new SkPDFDict());
182 186
183 proxy->insert("Value", new SkPDFInt(33))->unref(); 187 proxy->insert("Value", new SkPDFInt(33))->unref();
184 stub->insert("Value", new SkPDFInt(44))->unref(); 188 stub->insert("Value", new SkPDFInt(44))->unref();
185 189
186 SkPDFCatalog catalog; 190 SkPDFSubstituteMap substituteMap;
191 substituteMap.setSubstitute(proxy.get(), stub.get());
192 SkPDFObjNumMap catalog;
187 catalog.addObject(proxy.get()); 193 catalog.addObject(proxy.get());
188 catalog.setSubstitute(proxy.get(), stub.get());
189 194
190 REPORTER_ASSERT(reporter, stub.get() == catalog.getSubstituteObject(proxy)); 195 REPORTER_ASSERT(reporter, stub.get() == substituteMap.getSubstitute(proxy));
191 REPORTER_ASSERT(reporter, proxy.get() != catalog.getSubstituteObject(stub)); 196 REPORTER_ASSERT(reporter, proxy.get() != substituteMap.getSubstitute(stub));
192 } 197 }
193 198
194 // This test used to assert without the fix submitted for 199 // This test used to assert without the fix submitted for
195 // http://code.google.com/p/skia/issues/detail?id=1083. 200 // http://code.google.com/p/skia/issues/detail?id=1083.
196 // SKP files might have invalid glyph ids. This test ensures they are ignored, 201 // SKP files might have invalid glyph ids. This test ensures they are ignored,
197 // and there is no assert on input data in Debug mode. 202 // and there is no assert on input data in Debug mode.
198 static void test_issue1083() { 203 static void test_issue1083() {
199 SkDynamicMemoryWStream outStream; 204 SkDynamicMemoryWStream outStream;
200 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&outStream)); 205 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&outStream));
201 SkCanvas* canvas = doc->beginPage(100.0f, 100.0f); 206 SkCanvas* canvas = doc->beginPage(100.0f, 100.0f);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 array->append(int0.get()); 270 array->append(int0.get());
266 SimpleCheckObjectOutput(reporter, array.get(), "[42 0.5 0]"); 271 SimpleCheckObjectOutput(reporter, array.get(), "[42 0.5 0]");
267 SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1)); 272 SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1));
268 array->setAt(0, int1.get()); 273 array->setAt(0, int1.get());
269 SimpleCheckObjectOutput(reporter, array.get(), "[1 0.5 0]"); 274 SimpleCheckObjectOutput(reporter, array.get(), "[1 0.5 0]");
270 275
271 SkAutoTUnref<SkPDFDict> dict(new SkPDFDict); 276 SkAutoTUnref<SkPDFDict> dict(new SkPDFDict);
272 SimpleCheckObjectOutput(reporter, dict.get(), "<<>>"); 277 SimpleCheckObjectOutput(reporter, dict.get(), "<<>>");
273 SkAutoTUnref<SkPDFName> n1(new SkPDFName("n1")); 278 SkAutoTUnref<SkPDFName> n1(new SkPDFName("n1"));
274 dict->insert(n1.get(), int42.get()); 279 dict->insert(n1.get(), int42.get());
275 SimpleCheckObjectOutput(reporter, dict.get(), "<</n1 42\n>>"); 280 SimpleCheckObjectOutput(reporter, dict.get(), "<</n1 42>>");
276 SkAutoTUnref<SkPDFName> n2(new SkPDFName("n2")); 281 SkAutoTUnref<SkPDFName> n2(new SkPDFName("n2"));
277 SkAutoTUnref<SkPDFName> n3(new SkPDFName("n3")); 282 SkAutoTUnref<SkPDFName> n3(new SkPDFName("n3"));
278 dict->insert(n2.get(), realHalf.get()); 283 dict->insert(n2.get(), realHalf.get());
279 dict->insert(n3.get(), array.get()); 284 dict->insert(n3.get(), array.get());
280 SimpleCheckObjectOutput(reporter, dict.get(), 285 SimpleCheckObjectOutput(reporter, dict.get(),
281 "<</n1 42\n/n2 0.5\n/n3 [1 0.5 0]\n>>"); 286 "<</n1 42\n/n2 0.5\n/n3 [1 0.5 0]>>");
282 287
283 TestPDFStream(reporter); 288 TestPDFStream(reporter);
284 289
285 TestCatalog(reporter); 290 TestCatalog(reporter);
286 291
287 TestObjectRef(reporter); 292 TestObjectRef(reporter);
288 293
289 TestSubstitute(reporter); 294 TestSubstitute(reporter);
290 295
291 test_issue1083(); 296 test_issue1083();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 // Filter just created; should be unvisited. 344 // Filter just created; should be unvisited.
340 REPORTER_ASSERT(reporter, !filter->visited()); 345 REPORTER_ASSERT(reporter, !filter->visited());
341 SkPaint paint; 346 SkPaint paint;
342 paint.setImageFilter(filter.get()); 347 paint.setImageFilter(filter.get());
343 canvas->drawRect(SkRect::MakeWH(100, 100), paint); 348 canvas->drawRect(SkRect::MakeWH(100, 100), paint);
344 doc->close(); 349 doc->close();
345 350
346 // Filter was used in rendering; should be visited. 351 // Filter was used in rendering; should be visited.
347 REPORTER_ASSERT(reporter, filter->visited()); 352 REPORTER_ASSERT(reporter, filter->visited());
348 } 353 }
OLDNEW
« src/pdf/SkPDFStream.cpp ('K') | « src/pdf/SkPDFTypes.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698