1daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary/*
2daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary * Copyright 2014 Google Inc.
3daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary *
4daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary * Use of this source code is governed by a BSD-style license that can be
5daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary * found in the LICENSE file.
6daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary */
7daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
8daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary#include "SkDocument.h"
9daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary#include "SkCanvas.h"
10daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary#include "SkImageGenerator.h"
11daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary#include "SkData.h"
12daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary#include "SkStream.h"
13daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary#include "SkDecodingImageGenerator.h"
14daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
15daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary#include "Resources.h"
16daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary#include "Test.h"
17daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
18daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary// Returned bitmap is lazy.  Only lazy bitmaps hold onto the original data.
19daefa5b340d7aa36fe31865a3646f6fce321bb38halcanarystatic SkBitmap bitmap_from_data(SkData* data) {
20daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkASSERT(data);
21daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkBitmap bm;
22daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkInstallDiscardablePixelRef(
23daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary            SkDecodingImageGenerator::Create(
24daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary                    data, SkDecodingImageGenerator::Options()), &bm);
25daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    return bm;
26daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary}
27daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
28daefa5b340d7aa36fe31865a3646f6fce321bb38halcanarystatic bool is_subset_of(SkData* smaller, SkData* larger) {
29daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkASSERT(smaller && larger);
30daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    if (smaller->size() > larger->size()) {
31daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary        return false;
32daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    }
33daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    size_t size = smaller->size();
34daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    size_t size_diff = larger->size() - size;
35daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    for (size_t i = 0; i <= size_diff; ++i) {
36daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary        if (0 == memcmp(larger->bytes() + i, smaller->bytes(), size)) {
37daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary            return true;
38daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary        }
39daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    }
40daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    return false;
41daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary}
42daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
43daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
44daefa5b340d7aa36fe31865a3646f6fce321bb38halcanarystatic SkData* load_resource(
45daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary        skiatest::Reporter* r, const char* test, const char* filename) {
46daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkString path(GetResourcePath(filename));
47daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkData* data = SkData::NewFromFileName(path.c_str());
48daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    if (!data && r->verbose()) {
49daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary        SkDebugf("\n%s: Resource '%s' can not be found.\n",
50daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary                 test, filename);
51daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    }
52daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    return data;  // May return NULL.
53daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary}
54daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
55daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary/**
56daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary *  Test that for Jpeg files that use the JFIF colorspace, they are
57daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary *  directly embedded into the PDF (without re-encoding) when that
58daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary *  makes sense.
59daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary */
60daefa5b340d7aa36fe31865a3646f6fce321bb38halcanaryDEF_TEST(PDFJpegEmbedTest, r) {
61daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    const char test[] = "PDFJpegEmbedTest";
62daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkAutoTUnref<SkData> mandrillData(
63daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary            load_resource(r, test, "mandrill_512_q075.jpg"));
64daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkAutoTUnref<SkData> cmykData(load_resource(r, test, "CMYK.jpg"));
65daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    if (!mandrillData || !cmykData) {
66daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary        return;
67daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    }
68daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
69daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkDynamicMemoryWStream pdf;
70daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkAutoTUnref<SkDocument> document(SkDocument::CreatePDF(&pdf));
71daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkCanvas* canvas = document->beginPage(642, 1028);
72daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
73daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    canvas->clear(SK_ColorLTGRAY);
74daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
75daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkBitmap bm1(bitmap_from_data(mandrillData));
76daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    canvas->drawBitmap(bm1, 65.0, 0.0, NULL);
77daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkBitmap bm2(bitmap_from_data(cmykData));
78daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    canvas->drawBitmap(bm2, 0.0, 512.0, NULL);
79daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
80daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    canvas->flush();
81daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    document->endPage();
82daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    document->close();
83daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkAutoTUnref<SkData> pdfData(pdf.copyToData());
84daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    SkASSERT(pdfData);
85daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    pdf.reset();
86daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
87daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    REPORTER_ASSERT(r, is_subset_of(mandrillData, pdfData));
88daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
89daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    // This JPEG uses a nonstandard colorspace - it can not be
90daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    // embedded into the PDF directly.
91daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    REPORTER_ASSERT(r, !is_subset_of(cmykData, pdfData));
92daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary
93daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    // The following is for debugging purposes only.
94daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    const char* outputPath = getenv("SKIA_TESTS_PDF_JPEG_EMBED_OUTPUT_PATH");
95daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    if (outputPath) {
96daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary        SkFILEWStream output(outputPath);
97daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary        if (output.isValid()) {
98daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary            output.write(pdfData->data(), pdfData->size());
99daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary        }
100daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary    }
101daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary}
102