blob: a5feba842531f716bbbb2e3a85b18bd458e5785f [file] [log] [blame]
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +00001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000017#include <string>
18
19#include "Test.h"
reed@google.com8a85d0c2011-06-24 19:12:12 +000020#include "SkData.h"
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000021#include "SkPDFCatalog.h"
22#include "SkPDFStream.h"
23#include "SkPDFTypes.h"
24#include "SkScalar.h"
25#include "SkStream.h"
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());
30 if (offset + len > data.size()) {
31 return false;
32 }
33 return memcmp(data.bytes() + offset, buffer, len) == 0;
34}
35
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000036static void CheckObjectOutput(skiatest::Reporter* reporter, SkPDFObject* obj,
37 const std::string& representation,
38 bool indirect) {
39 size_t directSize = obj->getOutputSize(NULL, false);
40 REPORTER_ASSERT(reporter, directSize == representation.size());
41
42 SkDynamicMemoryWStream buffer;
43 obj->emitObject(&buffer, NULL, false);
44 REPORTER_ASSERT(reporter, directSize == buffer.getOffset());
reed@google.com8a85d0c2011-06-24 19:12:12 +000045 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, representation.c_str(),
46 directSize));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000047
48 if (indirect) {
49 // Indirect output.
50 static char header[] = "1 0 obj\n";
51 static size_t headerLen = strlen(header);
52 static char footer[] = "\nendobj\n";
53 static size_t footerLen = strlen(footer);
54
55 SkPDFCatalog catalog;
56 catalog.addObject(obj, false);
57
58 size_t indirectSize = obj->getOutputSize(&catalog, true);
59 REPORTER_ASSERT(reporter,
60 indirectSize == directSize + headerLen + footerLen);
61
62 buffer.reset();
63 obj->emitObject(&buffer, &catalog, true);
64 REPORTER_ASSERT(reporter, indirectSize == buffer.getOffset());
reed@google.com8a85d0c2011-06-24 19:12:12 +000065 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, header, headerLen));
66 REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen,
67 representation.c_str(),
68 directSize));
69 REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen + directSize,
70 footer, footerLen));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000071 }
72}
73
74static void TestCatalog(skiatest::Reporter* reporter) {
75 SkPDFCatalog catalog;
76 SkRefPtr<SkPDFInt> int1 = new SkPDFInt(1);
77 int1->unref(); // SkRefPtr and new both took a reference.
78 SkRefPtr<SkPDFInt> int2 = new SkPDFInt(2);
79 int2->unref(); // SkRefPtr and new both took a reference.
80 SkRefPtr<SkPDFInt> int3 = new SkPDFInt(3);
81 int3->unref(); // SkRefPtr and new both took a reference.
82 SkRefPtr<SkPDFInt> int1Again(int1.get());
83
84 catalog.addObject(int1.get(), false);
85 catalog.addObject(int2.get(), false);
86 catalog.addObject(int3.get(), false);
87
88 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int1.get()) == 3);
89 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int2.get()) == 3);
90 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int3.get()) == 3);
91
92 SkDynamicMemoryWStream buffer;
93 catalog.emitObjectNumber(&buffer, int1.get());
94 catalog.emitObjectNumber(&buffer, int2.get());
95 catalog.emitObjectNumber(&buffer, int3.get());
96 catalog.emitObjectNumber(&buffer, int1Again.get());
97 char expectedResult[] = "1 02 03 01 0";
reed@google.com8a85d0c2011-06-24 19:12:12 +000098 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResult,
99 strlen(expectedResult)));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000100}
101
102static void TestObjectRef(skiatest::Reporter* reporter) {
103 SkRefPtr<SkPDFInt> int1 = new SkPDFInt(1);
104 int1->unref(); // SkRefPtr and new both took a reference.
105 SkRefPtr<SkPDFInt> int2 = new SkPDFInt(2);
106 int2->unref(); // SkRefPtr and new both took a reference.
107 SkRefPtr<SkPDFObjRef> int2ref = new SkPDFObjRef(int2.get());
108 int2ref->unref(); // SkRefPtr and new both took a reference.
109
110 SkPDFCatalog catalog;
111 catalog.addObject(int1.get(), false);
112 catalog.addObject(int2.get(), false);
113 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int1.get()) == 3);
114 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int2.get()) == 3);
115
116 char expectedResult[] = "2 0 R";
117 SkDynamicMemoryWStream buffer;
118 int2ref->emitObject(&buffer, &catalog, false);
119 REPORTER_ASSERT(reporter, buffer.getOffset() == strlen(expectedResult));
reed@google.com8a85d0c2011-06-24 19:12:12 +0000120 REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResult,
121 buffer.getOffset()));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000122}
123
124static void TestPDFPrimitives(skiatest::Reporter* reporter) {
125 SkRefPtr<SkPDFInt> int42 = new SkPDFInt(42);
126 int42->unref(); // SkRefPtr and new both took a reference.
127 CheckObjectOutput(reporter, int42.get(), "42", true);
128
129 SkRefPtr<SkPDFScalar> realHalf = new SkPDFScalar(SK_ScalarHalf);
130 realHalf->unref(); // SkRefPtr and new both took a reference.
131 CheckObjectOutput(reporter, realHalf.get(), "0.5", true);
132
vandebo@chromium.org6cc26da2011-05-18 17:08:05 +0000133#if defined(SK_SCALAR_IS_FLOAT)
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000134 SkRefPtr<SkPDFScalar> bigScalar = new SkPDFScalar(110999.75);
135 bigScalar->unref(); // SkRefPtr and new both took a reference.
vandebo@chromium.org6cc26da2011-05-18 17:08:05 +0000136#if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000137 CheckObjectOutput(reporter, bigScalar.get(), "111000", true);
138#else
139 CheckObjectOutput(reporter, bigScalar.get(), "110999.75", true);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000140
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000141 SkRefPtr<SkPDFScalar> biggerScalar = new SkPDFScalar(50000000.1);
142 biggerScalar->unref(); // SkRefPtr and new both took a reference.
143 CheckObjectOutput(reporter, biggerScalar.get(), "50000000", true);
144
145 SkRefPtr<SkPDFScalar> smallestScalar = new SkPDFScalar(1.0/65536);
146 smallestScalar->unref(); // SkRefPtr and new both took a reference.
147 CheckObjectOutput(reporter, smallestScalar.get(), "0.00001526", true);
148#endif
vandebo@chromium.org6cc26da2011-05-18 17:08:05 +0000149#endif
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000150
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000151 SkRefPtr<SkPDFString> stringSimple = new SkPDFString("test ) string ( foo");
152 stringSimple->unref(); // SkRefPtr and new both took a reference.
153 CheckObjectOutput(reporter, stringSimple.get(), "(test \\) string \\( foo)",
154 true);
155 SkRefPtr<SkPDFString> stringComplex =
156 new SkPDFString("\ttest ) string ( foo");
157 stringComplex->unref(); // SkRefPtr and new both took a reference.
158 CheckObjectOutput(reporter, stringComplex.get(),
159 "<0974657374202920737472696E67202820666F6F>", true);
160
161 SkRefPtr<SkPDFName> name = new SkPDFName("Test name\twith#tab");
162 name->unref(); // SkRefPtr and new both took a reference.
163 CheckObjectOutput(reporter, name.get(), "/Test#20name#09with#23tab", false);
164
165 SkRefPtr<SkPDFArray> array = new SkPDFArray;
166 array->unref(); // SkRefPtr and new both took a reference.
167 CheckObjectOutput(reporter, array.get(), "[]", true);
168 array->append(int42.get());
169 CheckObjectOutput(reporter, array.get(), "[42]", true);
170 array->append(realHalf.get());
171 CheckObjectOutput(reporter, array.get(), "[42 0.5]", true);
172 SkRefPtr<SkPDFInt> int0 = new SkPDFInt(0);
173 int0->unref(); // SkRefPtr and new both took a reference.
174 array->append(int0.get());
175 CheckObjectOutput(reporter, array.get(), "[42 0.5 0]", true);
176 SkRefPtr<SkPDFInt> int1 = new SkPDFInt(1);
177 int1->unref(); // SkRefPtr and new both took a reference.
178 array->setAt(0, int1.get());
179 CheckObjectOutput(reporter, array.get(), "[1 0.5 0]", true);
180
181 SkRefPtr<SkPDFDict> dict = new SkPDFDict;
182 dict->unref(); // SkRefPtr and new both took a reference.
183 CheckObjectOutput(reporter, dict.get(), "<<>>", true);
184 SkRefPtr<SkPDFName> n1 = new SkPDFName("n1");
185 n1->unref(); // SkRefPtr and new both took a reference.
186 dict->insert(n1.get(), int42.get());
187 CheckObjectOutput(reporter, dict.get(), "<</n1 42\n>>", true);
188 SkRefPtr<SkPDFName> n2 = new SkPDFName("n2");
189 n2->unref(); // SkRefPtr and new both took a reference.
190 SkRefPtr<SkPDFName> n3 = new SkPDFName("n3");
191 n3->unref(); // SkRefPtr and new both took a reference.
192 dict->insert(n2.get(), realHalf.get());
193 dict->insert(n3.get(), array.get());
194 CheckObjectOutput(reporter, dict.get(),
195 "<</n1 42\n/n2 0.5\n/n3 [1 0.5 0]\n>>", true);
196
197 char streamBytes[] = "Test\nFoo\tBar";
198 SkRefPtr<SkMemoryStream> streamData = new SkMemoryStream(
199 streamBytes, strlen(streamBytes), true);
200 streamData->unref(); // SkRefPtr and new both took a reference.
201 SkRefPtr<SkPDFStream> stream = new SkPDFStream(streamData.get());
202 stream->unref(); // SkRefPtr and new both took a reference.
203 CheckObjectOutput(reporter, stream.get(),
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000204 "<</Length 12\n>> stream\nTest\nFoo\tBar\nendstream",
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000205 true);
206 stream->insert(n1.get(), int42.get());
207 CheckObjectOutput(reporter, stream.get(),
208 "<</Length 12\n/n1 42\n>> stream\nTest\nFoo\tBar"
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000209 "\nendstream",
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000210 true);
211
212 TestCatalog(reporter);
213
214 TestObjectRef(reporter);
215}
216
217#include "TestClassDef.h"
218DEFINE_TESTCLASS("PDFPrimitives", PDFPrimitivesTestClass, TestPDFPrimitives)