1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 #include "Test.h" 8 9 #include "Resources.h" 10 #include "SkCanvas.h" 11 #include "SkDocument.h" 12 #include "SkOSFile.h" 13 #include "SkStream.h" 14 #include "SkPixelSerializer.h" 15 16 static void test_empty(skiatest::Reporter* reporter) { 17 SkDynamicMemoryWStream stream; 18 19 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&stream)); 20 21 doc->close(); 22 23 REPORTER_ASSERT(reporter, stream.bytesWritten() == 0); 24 } 25 26 static void test_abort(skiatest::Reporter* reporter) { 27 SkDynamicMemoryWStream stream; 28 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&stream)); 29 30 SkCanvas* canvas = doc->beginPage(100, 100); 31 canvas->drawColor(SK_ColorRED); 32 doc->endPage(); 33 34 doc->abort(); 35 36 REPORTER_ASSERT(reporter, stream.bytesWritten() == 0); 37 } 38 39 static void test_abortWithFile(skiatest::Reporter* reporter) { 40 SkString tmpDir = skiatest::GetTmpDir(); 41 42 if (tmpDir.isEmpty()) { 43 return; // TODO(edisonn): unfortunatelly this pattern is used in other 44 // tests, but if GetTmpDir() starts returning and empty dir 45 // allways, then all these tests will be disabled. 46 } 47 48 SkString path = SkOSPath::Join(tmpDir.c_str(), "aborted.pdf"); 49 50 // Make sure doc's destructor is called to flush. 51 { 52 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(path.c_str())); 53 54 SkCanvas* canvas = doc->beginPage(100, 100); 55 canvas->drawColor(SK_ColorRED); 56 doc->endPage(); 57 58 doc->abort(); 59 } 60 61 FILE* file = fopen(path.c_str(), "r"); 62 // The created file should be empty. 63 char buffer[100]; 64 REPORTER_ASSERT(reporter, fread(buffer, 1, 1, file) == 0); 65 fclose(file); 66 } 67 68 static void test_file(skiatest::Reporter* reporter) { 69 SkString tmpDir = skiatest::GetTmpDir(); 70 if (tmpDir.isEmpty()) { 71 return; // TODO(edisonn): unfortunatelly this pattern is used in other 72 // tests, but if GetTmpDir() starts returning and empty dir 73 // allways, then all these tests will be disabled. 74 } 75 76 SkString path = SkOSPath::Join(tmpDir.c_str(), "file.pdf"); 77 78 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(path.c_str())); 79 80 SkCanvas* canvas = doc->beginPage(100, 100); 81 82 canvas->drawColor(SK_ColorRED); 83 doc->endPage(); 84 doc->close(); 85 86 FILE* file = fopen(path.c_str(), "r"); 87 REPORTER_ASSERT(reporter, file != nullptr); 88 char header[100]; 89 REPORTER_ASSERT(reporter, fread(header, 4, 1, file) != 0); 90 REPORTER_ASSERT(reporter, strncmp(header, "%PDF", 4) == 0); 91 fclose(file); 92 } 93 94 static void test_close(skiatest::Reporter* reporter) { 95 SkDynamicMemoryWStream stream; 96 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&stream)); 97 98 SkCanvas* canvas = doc->beginPage(100, 100); 99 canvas->drawColor(SK_ColorRED); 100 doc->endPage(); 101 102 doc->close(); 103 104 REPORTER_ASSERT(reporter, stream.bytesWritten() != 0); 105 } 106 107 DEF_TEST(document_tests, reporter) { 108 REQUIRE_PDF_DOCUMENT(document_tests, reporter); 109 test_empty(reporter); 110 test_abort(reporter); 111 test_abortWithFile(reporter); 112 test_file(reporter); 113 test_close(reporter); 114 } 115 116 namespace { 117 class JPEGSerializer final : public SkPixelSerializer { 118 bool onUseEncodedData(const void*, size_t) override { return true; } 119 SkData* onEncode(const SkPixmap& pixmap) override { 120 SkBitmap bm; 121 return bm.installPixels(pixmap.info(), 122 pixmap.writable_addr(), 123 pixmap.rowBytes(), 124 pixmap.ctable(), 125 nullptr, nullptr) 126 ? SkImageEncoder::EncodeData(bm, SkImageEncoder::kJPEG_Type, 85) 127 : nullptr; 128 } 129 }; 130 } // namespace 131 132 size_t count_bytes(const SkBitmap& bm, bool useDCT) { 133 SkDynamicMemoryWStream stream; 134 SkAutoTUnref<SkDocument> doc; 135 if (useDCT) { 136 SkAutoTUnref<SkPixelSerializer> serializer(new JPEGSerializer); 137 doc.reset(SkDocument::CreatePDF( 138 &stream, SK_ScalarDefaultRasterDPI, serializer)); 139 } else { 140 doc.reset(SkDocument::CreatePDF(&stream)); 141 } 142 SkCanvas* canvas = doc->beginPage(64, 64); 143 canvas->drawBitmap(bm, 0, 0); 144 doc->endPage(); 145 doc->close(); 146 return stream.bytesWritten(); 147 } 148 149 DEF_TEST(document_dct_encoder, r) { 150 REQUIRE_PDF_DOCUMENT(document_dct_encoder, r); 151 SkBitmap bm; 152 if (GetResourceAsBitmap("mandrill_64.png", &bm)) { 153 // Lossy encoding works better on photographs. 154 REPORTER_ASSERT(r, count_bytes(bm, true) < count_bytes(bm, false)); 155 } 156 } 157 158 DEF_TEST(document_skbug_4734, r) { 159 REQUIRE_PDF_DOCUMENT(document_skbug_4734, r); 160 SkDynamicMemoryWStream stream; 161 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&stream)); 162 SkCanvas* canvas = doc->beginPage(64, 64); 163 canvas->scale(10000.0f, 10000.0f); 164 canvas->translate(20.0f, 10.0f); 165 canvas->rotate(30.0f); 166 const char text[] = "HELLO"; 167 canvas->drawText(text, strlen(text), 0, 0, SkPaint()); 168 } 169