Home | History | Annotate | Download | only in tests
      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