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 "SkOSPath.h"
     14 #include "SkStream.h"
     15 
     16 #include "sk_tool_utils.h"
     17 
     18 static void test_empty(skiatest::Reporter* reporter) {
     19     SkDynamicMemoryWStream stream;
     20 
     21     sk_sp<SkDocument> doc(SkDocument::MakePDF(&stream));
     22 
     23     doc->close();
     24 
     25     REPORTER_ASSERT(reporter, stream.bytesWritten() == 0);
     26 }
     27 
     28 static void test_abort(skiatest::Reporter* reporter) {
     29     SkDynamicMemoryWStream stream;
     30     sk_sp<SkDocument> doc(SkDocument::MakePDF(&stream));
     31 
     32     SkCanvas* canvas = doc->beginPage(100, 100);
     33     canvas->drawColor(SK_ColorRED);
     34     doc->endPage();
     35 
     36     doc->abort();
     37 
     38     // Test that only the header is written, not the full document.
     39     REPORTER_ASSERT(reporter, stream.bytesWritten() < 256);
     40 }
     41 
     42 static void test_abortWithFile(skiatest::Reporter* reporter) {
     43     SkString tmpDir = skiatest::GetTmpDir();
     44 
     45     if (tmpDir.isEmpty()) {
     46         ERRORF(reporter, "missing tmpDir.");
     47         return;
     48     }
     49 
     50     SkString path = SkOSPath::Join(tmpDir.c_str(), "aborted.pdf");
     51     if (!SkFILEWStream(path.c_str()).isValid()) {
     52         ERRORF(reporter, "unable to write to: %s", path.c_str());
     53         return;
     54     }
     55 
     56     // Make sure doc's destructor is called to flush.
     57     {
     58         SkFILEWStream stream(path.c_str());
     59         sk_sp<SkDocument> doc = SkDocument::MakePDF(&stream);
     60 
     61         SkCanvas* canvas = doc->beginPage(100, 100);
     62         canvas->drawColor(SK_ColorRED);
     63         doc->endPage();
     64 
     65         doc->abort();
     66     }
     67 
     68     FILE* file = fopen(path.c_str(), "r");
     69     // Test that only the header is written, not the full document.
     70     char buffer[256];
     71     REPORTER_ASSERT(reporter, fread(buffer, 1, sizeof(buffer), file) < sizeof(buffer));
     72     fclose(file);
     73 }
     74 
     75 static void test_file(skiatest::Reporter* reporter) {
     76     SkString tmpDir = skiatest::GetTmpDir();
     77     if (tmpDir.isEmpty()) {
     78         ERRORF(reporter, "missing tmpDir.");
     79         return;
     80     }
     81 
     82     SkString path = SkOSPath::Join(tmpDir.c_str(), "file.pdf");
     83     if (!SkFILEWStream(path.c_str()).isValid()) {
     84         ERRORF(reporter, "unable to write to: %s", path.c_str());
     85         return;
     86     }
     87 
     88     {
     89         SkFILEWStream stream(path.c_str());
     90         sk_sp<SkDocument> doc = SkDocument::MakePDF(&stream);
     91         SkCanvas* canvas = doc->beginPage(100, 100);
     92 
     93         canvas->drawColor(SK_ColorRED);
     94         doc->endPage();
     95         doc->close();
     96     }
     97 
     98     FILE* file = fopen(path.c_str(), "r");
     99     REPORTER_ASSERT(reporter, file != nullptr);
    100     char header[100];
    101     REPORTER_ASSERT(reporter, fread(header, 4, 1, file) != 0);
    102     REPORTER_ASSERT(reporter, strncmp(header, "%PDF", 4) == 0);
    103     fclose(file);
    104 }
    105 
    106 static void test_close(skiatest::Reporter* reporter) {
    107     SkDynamicMemoryWStream stream;
    108     sk_sp<SkDocument> doc(SkDocument::MakePDF(&stream));
    109 
    110     SkCanvas* canvas = doc->beginPage(100, 100);
    111     canvas->drawColor(SK_ColorRED);
    112     doc->endPage();
    113 
    114     doc->close();
    115 
    116     REPORTER_ASSERT(reporter, stream.bytesWritten() != 0);
    117 }
    118 
    119 DEF_TEST(SkPDF_document_tests, reporter) {
    120     REQUIRE_PDF_DOCUMENT(document_tests, reporter);
    121     test_empty(reporter);
    122     test_abort(reporter);
    123     test_abortWithFile(reporter);
    124     test_file(reporter);
    125     test_close(reporter);
    126 }
    127 
    128 DEF_TEST(SkPDF_document_skbug_4734, r) {
    129     REQUIRE_PDF_DOCUMENT(SkPDF_document_skbug_4734, r);
    130     SkDynamicMemoryWStream stream;
    131     sk_sp<SkDocument> doc(SkDocument::MakePDF(&stream));
    132     SkCanvas* canvas = doc->beginPage(64, 64);
    133     canvas->scale(10000.0f, 10000.0f);
    134     canvas->translate(20.0f, 10.0f);
    135     canvas->rotate(30.0f);
    136     const char text[] = "HELLO";
    137     canvas->drawString(text, 0, 0, SkPaint());
    138 }
    139 
    140 static bool contains(const uint8_t* result, size_t size, const char expectation[]) {
    141     size_t len = strlen(expectation);
    142     size_t N = 1 + size - len;
    143     for (size_t i = 0; i < N; ++i) {
    144         if (0 == memcmp(result + i, expectation, len)) {
    145             return true;
    146         }
    147     }
    148     return false;
    149 }
    150 
    151 // verify that the PDFA flag does something.
    152 DEF_TEST(SkPDF_pdfa_document, r) {
    153     REQUIRE_PDF_DOCUMENT(SkPDF_pdfa_document, r);
    154 
    155     SkDocument::PDFMetadata pdfMetadata;
    156     pdfMetadata.fTitle = "test document";
    157     pdfMetadata.fCreation.fEnabled = true;
    158     pdfMetadata.fCreation.fDateTime = {0, 1999, 12, 5, 31, 23, 59, 59};
    159     pdfMetadata.fPDFA = true;
    160 
    161     SkDynamicMemoryWStream buffer;
    162     auto doc = SkDocument::MakePDF(&buffer, pdfMetadata);
    163     doc->beginPage(64, 64)->drawColor(SK_ColorRED);
    164     doc->close();
    165     sk_sp<SkData> data(buffer.detachAsData());
    166 
    167     static const char* expectations[] = {
    168         "sRGB IEC61966-2.1",
    169         "<dc:title><rdf:Alt><rdf:li xml:lang=\"x-default\">test document",
    170         "<xmp:CreateDate>1999-12-31T23:59:59+00:00</xmp:CreateDate>",
    171         "/Subtype /XML",
    172         "/CreationDate (D:19991231235959+00'00')>>",
    173     };
    174     for (const char* expectation : expectations) {
    175         if (!contains(data->bytes(), data->size(), expectation)) {
    176             ERRORF(r, "PDFA expectation missing: '%s'.", expectation);
    177         }
    178     }
    179     pdfMetadata.fProducer = "phoney library";
    180     pdfMetadata.fPDFA = true;
    181     doc = SkDocument::MakePDF(&buffer, pdfMetadata);
    182     doc->beginPage(64, 64)->drawColor(SK_ColorRED);
    183     doc->close();
    184     data = buffer.detachAsData();
    185 
    186     static const char* moreExpectations[] = {
    187         "/Producer (phoney library)",
    188         "/ProductionLibrary (Skia/PDF m",
    189         "<!-- <skia:ProductionLibrary>Skia/PDF m",
    190         "<pdf:Producer>phoney library</pdf:Producer>",
    191     };
    192     for (const char* expectation : moreExpectations) {
    193         if (!contains(data->bytes(), data->size(), expectation)) {
    194             ERRORF(r, "PDFA expectation missing: '%s'.", expectation);
    195         }
    196     }
    197 }
    198