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 16static 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 26static 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 39static 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 68static 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 94static 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 107DEF_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 116namespace { 117class 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 132size_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 149DEF_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 158DEF_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