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