1/* 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 17#include <string> 18 19#include "Test.h" 20#include "SkPDFCatalog.h" 21#include "SkPDFStream.h" 22#include "SkPDFTypes.h" 23#include "SkScalar.h" 24#include "SkStream.h" 25 26static void CheckObjectOutput(skiatest::Reporter* reporter, SkPDFObject* obj, 27 const std::string& representation, 28 bool indirect) { 29 size_t directSize = obj->getOutputSize(NULL, false); 30 REPORTER_ASSERT(reporter, directSize == representation.size()); 31 32 SkDynamicMemoryWStream buffer; 33 obj->emitObject(&buffer, NULL, false); 34 REPORTER_ASSERT(reporter, directSize == buffer.getOffset()); 35 REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), representation.c_str(), 36 directSize) == 0); 37 38 if (indirect) { 39 // Indirect output. 40 static char header[] = "1 0 obj\n"; 41 static size_t headerLen = strlen(header); 42 static char footer[] = "\nendobj\n"; 43 static size_t footerLen = strlen(footer); 44 45 SkPDFCatalog catalog; 46 catalog.addObject(obj, false); 47 48 size_t indirectSize = obj->getOutputSize(&catalog, true); 49 REPORTER_ASSERT(reporter, 50 indirectSize == directSize + headerLen + footerLen); 51 52 buffer.reset(); 53 obj->emitObject(&buffer, &catalog, true); 54 REPORTER_ASSERT(reporter, indirectSize == buffer.getOffset()); 55 REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), header, 56 headerLen) == 0); 57 REPORTER_ASSERT(reporter, 58 memcmp(buffer.getStream() + headerLen, 59 representation.c_str(), directSize) == 0); 60 REPORTER_ASSERT(reporter, 61 memcmp(buffer.getStream() + headerLen + directSize, 62 footer, footerLen) == 0); 63 } 64} 65 66static void TestCatalog(skiatest::Reporter* reporter) { 67 SkPDFCatalog catalog; 68 SkRefPtr<SkPDFInt> int1 = new SkPDFInt(1); 69 int1->unref(); // SkRefPtr and new both took a reference. 70 SkRefPtr<SkPDFInt> int2 = new SkPDFInt(2); 71 int2->unref(); // SkRefPtr and new both took a reference. 72 SkRefPtr<SkPDFInt> int3 = new SkPDFInt(3); 73 int3->unref(); // SkRefPtr and new both took a reference. 74 SkRefPtr<SkPDFInt> int1Again(int1.get()); 75 76 catalog.addObject(int1.get(), false); 77 catalog.addObject(int2.get(), false); 78 catalog.addObject(int3.get(), false); 79 80 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int1.get()) == 3); 81 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int2.get()) == 3); 82 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int3.get()) == 3); 83 84 SkDynamicMemoryWStream buffer; 85 catalog.emitObjectNumber(&buffer, int1.get()); 86 catalog.emitObjectNumber(&buffer, int2.get()); 87 catalog.emitObjectNumber(&buffer, int3.get()); 88 catalog.emitObjectNumber(&buffer, int1Again.get()); 89 char expectedResult[] = "1 02 03 01 0"; 90 REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), expectedResult, 91 strlen(expectedResult)) == 0); 92} 93 94static void TestObjectRef(skiatest::Reporter* reporter) { 95 SkRefPtr<SkPDFInt> int1 = new SkPDFInt(1); 96 int1->unref(); // SkRefPtr and new both took a reference. 97 SkRefPtr<SkPDFInt> int2 = new SkPDFInt(2); 98 int2->unref(); // SkRefPtr and new both took a reference. 99 SkRefPtr<SkPDFObjRef> int2ref = new SkPDFObjRef(int2.get()); 100 int2ref->unref(); // SkRefPtr and new both took a reference. 101 102 SkPDFCatalog catalog; 103 catalog.addObject(int1.get(), false); 104 catalog.addObject(int2.get(), false); 105 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int1.get()) == 3); 106 REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int2.get()) == 3); 107 108 char expectedResult[] = "2 0 R"; 109 SkDynamicMemoryWStream buffer; 110 int2ref->emitObject(&buffer, &catalog, false); 111 REPORTER_ASSERT(reporter, buffer.getOffset() == strlen(expectedResult)); 112 REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), expectedResult, 113 buffer.getOffset()) == 0); 114} 115 116static void TestPDFPrimitives(skiatest::Reporter* reporter) { 117 SkRefPtr<SkPDFInt> int42 = new SkPDFInt(42); 118 int42->unref(); // SkRefPtr and new both took a reference. 119 CheckObjectOutput(reporter, int42.get(), "42", true); 120 121 SkRefPtr<SkPDFScalar> realHalf = new SkPDFScalar(SK_ScalarHalf); 122 realHalf->unref(); // SkRefPtr and new both took a reference. 123 CheckObjectOutput(reporter, realHalf.get(), "0.5", true); 124 125#if defined(SK_SCALAR_IS_FLOAT) 126 SkRefPtr<SkPDFScalar> bigScalar = new SkPDFScalar(110999.75); 127 bigScalar->unref(); // SkRefPtr and new both took a reference. 128#if !defined(SK_ALLOW_LARGE_PDF_SCALARS) 129 CheckObjectOutput(reporter, bigScalar.get(), "111000", true); 130#else 131 CheckObjectOutput(reporter, bigScalar.get(), "110999.75", true); 132 133 SkRefPtr<SkPDFScalar> biggerScalar = new SkPDFScalar(50000000.1); 134 biggerScalar->unref(); // SkRefPtr and new both took a reference. 135 CheckObjectOutput(reporter, biggerScalar.get(), "50000000", true); 136 137 SkRefPtr<SkPDFScalar> smallestScalar = new SkPDFScalar(1.0/65536); 138 smallestScalar->unref(); // SkRefPtr and new both took a reference. 139 CheckObjectOutput(reporter, smallestScalar.get(), "0.00001526", true); 140#endif 141#endif 142 143 SkRefPtr<SkPDFString> stringSimple = new SkPDFString("test ) string ( foo"); 144 stringSimple->unref(); // SkRefPtr and new both took a reference. 145 CheckObjectOutput(reporter, stringSimple.get(), "(test \\) string \\( foo)", 146 true); 147 SkRefPtr<SkPDFString> stringComplex = 148 new SkPDFString("\ttest ) string ( foo"); 149 stringComplex->unref(); // SkRefPtr and new both took a reference. 150 CheckObjectOutput(reporter, stringComplex.get(), 151 "<0974657374202920737472696E67202820666F6F>", true); 152 153 SkRefPtr<SkPDFName> name = new SkPDFName("Test name\twith#tab"); 154 name->unref(); // SkRefPtr and new both took a reference. 155 CheckObjectOutput(reporter, name.get(), "/Test#20name#09with#23tab", false); 156 157 SkRefPtr<SkPDFArray> array = new SkPDFArray; 158 array->unref(); // SkRefPtr and new both took a reference. 159 CheckObjectOutput(reporter, array.get(), "[]", true); 160 array->append(int42.get()); 161 CheckObjectOutput(reporter, array.get(), "[42]", true); 162 array->append(realHalf.get()); 163 CheckObjectOutput(reporter, array.get(), "[42 0.5]", true); 164 SkRefPtr<SkPDFInt> int0 = new SkPDFInt(0); 165 int0->unref(); // SkRefPtr and new both took a reference. 166 array->append(int0.get()); 167 CheckObjectOutput(reporter, array.get(), "[42 0.5 0]", true); 168 SkRefPtr<SkPDFInt> int1 = new SkPDFInt(1); 169 int1->unref(); // SkRefPtr and new both took a reference. 170 array->setAt(0, int1.get()); 171 CheckObjectOutput(reporter, array.get(), "[1 0.5 0]", true); 172 173 SkRefPtr<SkPDFDict> dict = new SkPDFDict; 174 dict->unref(); // SkRefPtr and new both took a reference. 175 CheckObjectOutput(reporter, dict.get(), "<<>>", true); 176 SkRefPtr<SkPDFName> n1 = new SkPDFName("n1"); 177 n1->unref(); // SkRefPtr and new both took a reference. 178 dict->insert(n1.get(), int42.get()); 179 CheckObjectOutput(reporter, dict.get(), "<</n1 42\n>>", true); 180 SkRefPtr<SkPDFName> n2 = new SkPDFName("n2"); 181 n2->unref(); // SkRefPtr and new both took a reference. 182 SkRefPtr<SkPDFName> n3 = new SkPDFName("n3"); 183 n3->unref(); // SkRefPtr and new both took a reference. 184 dict->insert(n2.get(), realHalf.get()); 185 dict->insert(n3.get(), array.get()); 186 CheckObjectOutput(reporter, dict.get(), 187 "<</n1 42\n/n2 0.5\n/n3 [1 0.5 0]\n>>", true); 188 189 char streamBytes[] = "Test\nFoo\tBar"; 190 SkRefPtr<SkMemoryStream> streamData = new SkMemoryStream( 191 streamBytes, strlen(streamBytes), true); 192 streamData->unref(); // SkRefPtr and new both took a reference. 193 SkRefPtr<SkPDFStream> stream = new SkPDFStream(streamData.get()); 194 stream->unref(); // SkRefPtr and new both took a reference. 195 CheckObjectOutput(reporter, stream.get(), 196 "<</Length 12\n>> stream\nTest\nFoo\tBar\nendstream", 197 true); 198 stream->insert(n1.get(), int42.get()); 199 CheckObjectOutput(reporter, stream.get(), 200 "<</Length 12\n/n1 42\n>> stream\nTest\nFoo\tBar" 201 "\nendstream", 202 true); 203 204 TestCatalog(reporter); 205 206 TestObjectRef(reporter); 207} 208 209#include "TestClassDef.h" 210DEFINE_TESTCLASS("PDFPrimitives", PDFPrimitivesTestClass, TestPDFPrimitives) 211