/** * Test that for Jpeg files that use the JFIF colorspace, they are * directly embedded into the PDF (without re-encoding) when that * makes sense. */ DEF_TEST(PDFJpegEmbedTest, r) { const char test[] = "PDFJpegEmbedTest"; SkAutoTUnref<SkData> mandrillData( load_resource(r, test, "mandrill_512_q075.jpg")); SkAutoTUnref<SkData> cmykData(load_resource(r, test, "CMYK.jpg")); if (!mandrillData || !cmykData) { return; } //////////////////////////////////////////////////////////////////////////// SkDynamicMemoryWStream pdf; SkAutoTUnref<SkDocument> document(SkDocument::CreatePDF(&pdf)); SkCanvas* canvas = document->beginPage(642, 1028); canvas->clear(SK_ColorLTGRAY); SkBitmap bm1(bitmap_from_data(mandrillData)); canvas->drawBitmap(bm1, 65.0, 0.0, nullptr); SkBitmap bm2(bitmap_from_data(cmykData)); canvas->drawBitmap(bm2, 0.0, 512.0, nullptr); canvas->flush(); document->endPage(); document->close(); SkAutoTUnref<SkData> pdfData(pdf.copyToData()); SkASSERT(pdfData); pdf.reset(); REPORTER_ASSERT(r, is_subset_of(mandrillData, pdfData)); // This JPEG uses a nonstandard colorspace - it can not be // embedded into the PDF directly. REPORTER_ASSERT(r, !is_subset_of(cmykData, pdfData)); //////////////////////////////////////////////////////////////////////////// pdf.reset(); document.reset(SkDocument::CreatePDF(&pdf)); canvas = document->beginPage(642, 1028); canvas->clear(SK_ColorLTGRAY); SkAutoTUnref<SkImage> im1(SkImage::NewFromEncoded(mandrillData)); canvas->drawImage(im1, 65.0, 0.0, nullptr); SkAutoTUnref<SkImage> im2(SkImage::NewFromEncoded(cmykData)); canvas->drawImage(im2, 0.0, 512.0, nullptr); canvas->flush(); document->endPage(); document->close(); pdfData.reset(pdf.copyToData()); SkASSERT(pdfData); pdf.reset(); REPORTER_ASSERT(r, is_subset_of(mandrillData, pdfData)); // This JPEG uses a nonstandard colorspace - it can not be // embedded into the PDF directly. REPORTER_ASSERT(r, !is_subset_of(cmykData, pdfData)); }
static void TestFlate(skiatest::Reporter* reporter, SkMemoryStream* testStream, size_t dataSize) { if (testStream == NULL) return; SkMemoryStream testData(dataSize); uint8_t* data = (uint8_t*)testData.getMemoryBase(); srand(0); // Make data deterministic. for (size_t i = 0; i < dataSize; i++) data[i] = rand() & 0xFF; testStream->setMemory(testData.getMemoryBase(), dataSize, true); SkDynamicMemoryWStream compressed; bool status = SkFlate::Deflate(testStream, &compressed); REPORTER_ASSERT(reporter, status); // Check that the input data wasn't changed. size_t inputSize = testStream->getLength(); if (inputSize == 0) inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); REPORTER_ASSERT(reporter, testData.getLength() == inputSize); REPORTER_ASSERT(reporter, memcmp(testData.getMemoryBase(), testStream->getMemoryBase(), testData.getLength()) == 0); // Assume there are two test sizes, big and small. if (dataSize < 1024) REPORTER_ASSERT(reporter, compressed.getOffset() < 1024); else REPORTER_ASSERT(reporter, compressed.getOffset() > 1024); SkAutoDataUnref data1(compressed.copyToData()); testStream->setData(data1.get())->unref(); SkDynamicMemoryWStream uncompressed; status = SkFlate::Inflate(testStream, &uncompressed); REPORTER_ASSERT(reporter, status); // Check that the input data wasn't changed. inputSize = testStream->getLength(); if (inputSize == 0) inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); REPORTER_ASSERT(reporter, data1->size() == inputSize); REPORTER_ASSERT(reporter, memcmp(testStream->getMemoryBase(), data1->data(), data1->size()) == 0); // Check that the uncompressed data matches the source data. SkAutoDataUnref data2(uncompressed.copyToData()); REPORTER_ASSERT(reporter, testData.getLength() == uncompressed.getOffset()); REPORTER_ASSERT(reporter, memcmp(testData.getMemoryBase(), data2->data(), testData.getLength()) == 0); }
bool DrawingDisplayItem::equals(const DisplayItem& other) const { if (!DisplayItem::equals(other)) return false; RefPtr<const SkPicture> picture = this->picture(); RefPtr<const SkPicture> otherPicture = static_cast<const DrawingDisplayItem&>(other).picture(); if (!picture && !otherPicture) return true; if (!picture || !otherPicture) return false; switch (getUnderInvalidationCheckingMode()) { case DrawingDisplayItem::CheckPicture: { if (picture->approximateOpCount() != otherPicture->approximateOpCount()) return false; SkDynamicMemoryWStream pictureSerialized; picture->serialize(&pictureSerialized); SkDynamicMemoryWStream otherPictureSerialized; otherPicture->serialize(&otherPictureSerialized); if (pictureSerialized.bytesWritten() != otherPictureSerialized.bytesWritten()) return false; RefPtr<SkData> oldData = adoptRef(otherPictureSerialized.copyToData()); RefPtr<SkData> newData = adoptRef(pictureSerialized.copyToData()); return oldData->equals(newData.get()); } case DrawingDisplayItem::CheckBitmap: { SkRect rect = picture->cullRect(); if (rect != otherPicture->cullRect()) return false; SkBitmap bitmap; bitmap.allocPixels(SkImageInfo::MakeN32Premul(rect.width(), rect.height())); SkCanvas canvas(bitmap); canvas.translate(-rect.x(), -rect.y()); canvas.drawPicture(otherPicture.get()); SkPaint diffPaint; diffPaint.setXfermodeMode(SkXfermode::kDifference_Mode); canvas.drawPicture(picture.get(), nullptr, &diffPaint); return bitmapIsAllZero(bitmap); } default: ASSERT_NOT_REACHED(); } return false; }
int DownloadHandler::handle(Request* request, MHD_Connection* connection, const char* url, const char* method, const char* upload_data, size_t* upload_data_size) { if (!request->hasPicture()) { return MHD_NO; } // TODO move to a function // Playback into picture recorder SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(Request::kImageWidth, Request::kImageHeight); request->fDebugCanvas->draw(canvas); SkAutoTUnref<SkPicture> picture(recorder.endRecording()); SkDynamicMemoryWStream outStream; SkAutoTUnref<SkPixelSerializer> serializer(SkImageEncoder::CreatePixelSerializer()); picture->serialize(&outStream, serializer); SkAutoTUnref<SkData> data(outStream.copyToData()); // TODO fancier name handling return SendData(connection, data, "application/octet-stream", true, "attachment; filename=something.skp;"); }
static void test_bitmap_with_encoded_data(skiatest::Reporter* reporter) { // Create a bitmap that will be encoded. SkBitmap original; make_bm(&original, 100, 100, SK_ColorBLUE, true); SkDynamicMemoryWStream wStream; if (!SkImageEncoder::EncodeStream(&wStream, original, SkImageEncoder::kPNG_Type, 100)) { return; } SkAutoDataUnref data(wStream.copyToData()); SkBitmap bm; bool installSuccess = SkDecodingImageGenerator::Install(data, &bm); REPORTER_ASSERT(reporter, installSuccess); // Write both bitmaps to pictures, and ensure that the resulting data streams are the same. // Flattening original will follow the old path of performing an encode, while flattening bm // will use the already encoded data. SkAutoDataUnref picture1(serialized_picture_from_bitmap(original)); SkAutoDataUnref picture2(serialized_picture_from_bitmap(bm)); REPORTER_ASSERT(reporter, picture1->equals(picture2)); // Now test that a parse error was generated when trying to create a new SkPicture without // providing a function to decode the bitmap. ErrorContext context; context.fErrors = 0; context.fReporter = reporter; SkSetErrorCallback(assert_one_parse_error_cb, &context); SkMemoryStream pictureStream(picture1); SkClearLastError(); SkAutoUnref pictureFromStream(SkPicture::CreateFromStream(&pictureStream, NULL)); REPORTER_ASSERT(reporter, pictureFromStream.get() != NULL); SkClearLastError(); SkSetErrorCallback(NULL, NULL); }
static void TestWStream(skiatest::Reporter* reporter) { SkDynamicMemoryWStream ds; const char s[] = "abcdefghijklmnopqrstuvwxyz"; int i; for (i = 0; i < 100; i++) { REPORTER_ASSERT(reporter, ds.write(s, 26)); } REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26); char* dst = new char[100 * 26 + 1]; dst[100*26] = '*'; ds.copyTo(dst); REPORTER_ASSERT(reporter, dst[100*26] == '*'); // char* p = dst; for (i = 0; i < 100; i++) { REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0); } { SkData* data = ds.copyToData(); REPORTER_ASSERT(reporter, 100 * 26 == data->size()); REPORTER_ASSERT(reporter, memcmp(dst, data->data(), data->size()) == 0); data->unref(); } delete[] dst; }
static SkData* create_data_from_bitmap(const SkBitmap& bm) { SkDynamicMemoryWStream stream; if (SkImageEncoder::EncodeStream(&stream, bm, SkImageEncoder::kPNG_Type, 100)) { return stream.copyToData(); } return NULL; }
SkData* Request::getJsonBatchList(int n) { SkCanvas* canvas = this->getCanvas(); SkASSERT(fGPUEnabled); // TODO if this is inefficient we could add a method to GrAuditTrail which takes // a Json::Value and is only compiled in this file Json::Value parsedFromString; #if SK_SUPPORT_GPU GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); SkASSERT(rt); GrContext* ctx = rt->getContext(); SkASSERT(ctx); GrAuditTrail* at = ctx->getAuditTrail(); GrAuditTrail::AutoManageBatchList enable(at); fDebugCanvas->drawTo(canvas, n); Json::Reader reader; SkDEBUGCODE(bool parsingSuccessful = )reader.parse(at->toJson(true).c_str(), parsedFromString); SkASSERT(parsingSuccessful); #endif SkDynamicMemoryWStream stream; stream.writeText(Json::FastWriter().write(parsedFromString).c_str()); return stream.copyToData(); }
static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) { SkPicture picture; SkCanvas* canvas = picture.beginRecording(bitmap.width(), bitmap.height()); canvas->drawBitmap(bitmap, 0, 0); SkDynamicMemoryWStream wStream; picture.serialize(&wStream, &encode_bitmap_to_data); return wStream.copyToData(); }
static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset, const void* buffer, size_t len) { SkAutoDataUnref data(stream.copyToData()); if (offset + len > data->size()) { return false; } return memcmp(data->bytes() + offset, buffer, len) == 0; }
static int SendJSON(MHD_Connection* connection, SkDebugCanvas* debugCanvas, int n) { SkDynamicMemoryWStream stream; SkAutoTUnref<SkJSONCanvas> jsonCanvas(new SkJSONCanvas(kImageWidth, kImageHeight, stream)); debugCanvas->drawTo(jsonCanvas, n); jsonCanvas->finish(); SkAutoTUnref<SkData> data(stream.copyToData()); return SendData(connection, data, "application/json"); }
SkData* Request::getJsonOps(int n) { SkCanvas* canvas = this->getCanvas(); Json::Value root = fDebugCanvas->toJSON(fUrlDataManager, n, canvas); root["mode"] = Json::Value(fGPUEnabled ? "gpu" : "cpu"); SkDynamicMemoryWStream stream; stream.writeText(Json::FastWriter().write(root).c_str()); return stream.copyToData(); }
SkData* Request::writeCanvasToPng(SkCanvas* canvas) { // capture pixels SkAutoTDelete<SkBitmap> bmp(getBitmapFromCanvas(canvas)); SkASSERT(bmp); // write to png SkDynamicMemoryWStream buffer; write_png((const png_bytep) bmp->getPixels(), bmp->width(), bmp->height(), buffer); return buffer.copyToData(); }
SkData* Request::getJsonBatchList(int n) { SkCanvas* canvas = this->getCanvas(); SkASSERT(fGPUEnabled); Json::Value result = fDebugCanvas->toJSONBatchList(n, canvas); SkDynamicMemoryWStream stream; stream.writeText(Json::FastWriter().write(result).c_str()); return stream.copyToData(); }
static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) { SkASSERT(typeface); SkDynamicMemoryWStream stream; typeface->serialize(&stream); size_t size = stream.getOffset(); if (writer) { writer->write32(size); SkAutoDataUnref data(stream.copyToData()); writer->writePad(data->data(), size); } return 4 + SkAlign4(size); }
static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); canvas->drawBitmap(bitmap, 0, 0); SkAutoTUnref<SkPicture> picture(recorder.endRecording()); SkDynamicMemoryWStream wStream; sk_tool_utils::PngPixelSerializer serializer; picture->serialize(&wStream, &serializer); return wStream.copyToData(); }
DEF_TEST(Picture_EncodedData, reporter) { // Create a bitmap that will be encoded. SkBitmap original; make_bm(&original, 100, 100, SK_ColorBLUE, true); SkDynamicMemoryWStream wStream; if (!SkImageEncoder::EncodeStream(&wStream, original, SkImageEncoder::kPNG_Type, 100)) { return; } SkAutoDataUnref data(wStream.copyToData()); SkBitmap bm; bool installSuccess = SkDEPRECATED_InstallDiscardablePixelRef(data, &bm); REPORTER_ASSERT(reporter, installSuccess); // Write both bitmaps to pictures, and ensure that the resulting data streams are the same. // Flattening original will follow the old path of performing an encode, while flattening bm // will use the already encoded data. SkAutoDataUnref picture1(serialized_picture_from_bitmap(original)); SkAutoDataUnref picture2(serialized_picture_from_bitmap(bm)); REPORTER_ASSERT(reporter, picture1->equals(picture2)); // Now test that a parse error was generated when trying to create a new SkPicture without // providing a function to decode the bitmap. ErrorContext context; context.fErrors = 0; context.fReporter = reporter; SkSetErrorCallback(assert_one_parse_error_cb, &context); SkMemoryStream pictureStream(picture1); SkClearLastError(); sk_sp<SkPicture> pictureFromStream(SkPicture::MakeFromStream(&pictureStream, nullptr)); REPORTER_ASSERT(reporter, pictureFromStream.get() != nullptr); SkClearLastError(); SkSetErrorCallback(nullptr, nullptr); // Test that using the version of CreateFromStream that just takes a stream also decodes the // bitmap. Drawing this picture should look exactly like the original bitmap. SkMD5::Digest referenceDigest; md5(original, &referenceDigest); SkBitmap dst; dst.allocPixels(original.info()); dst.eraseColor(SK_ColorRED); SkCanvas canvas(dst); pictureStream.rewind(); pictureFromStream = SkPicture::MakeFromStream(&pictureStream); canvas.drawPicture(pictureFromStream.get()); SkMD5::Digest digest2; md5(dst, &digest2); REPORTER_ASSERT(reporter, referenceDigest == digest2); }
static bool stream_contains(const SkDynamicMemoryWStream& stream, const char* buffer) { SkAutoDataUnref data(stream.copyToData()); int len = strlen(buffer); // our buffer does not have EOSs. for (int offset = 0 ; offset < (int)data->size() - len; offset++) { if (memcmp(data->bytes() + offset, buffer, len) == 0) { return true; } } return false; }
static void TestPDFStream(skiatest::Reporter* reporter) { char streamBytes[] = "Test\nFoo\tBar"; SkAutoTDelete<SkMemoryStream> streamData(new SkMemoryStream( streamBytes, strlen(streamBytes), true)); SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData.get())); ASSERT_EMIT_EQ(reporter, *stream, "<</Length 12>> stream\nTest\nFoo\tBar\nendstream"); stream->insertInt("Attribute", 42); ASSERT_EMIT_EQ(reporter, *stream, "<</Length 12\n/Attribute 42>> stream\n" "Test\nFoo\tBar\nendstream"); { char streamBytes2[] = "This is a longer string, so that compression " "can do something with it. With shorter strings, " "the short circuit logic cuts in and we end up " "with an uncompressed string."; SkAutoDataUnref streamData2(SkData::NewWithCopy(streamBytes2, strlen(streamBytes2))); SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData2.get())); SkDynamicMemoryWStream compressedByteStream; SkFlate::Deflate(streamData2.get(), &compressedByteStream); SkAutoDataUnref compressedData(compressedByteStream.copyToData()); SkDynamicMemoryWStream expected; expected.writeText("<</Filter /FlateDecode\n/Length 116>> stream\n"); expected.write(compressedData->data(), compressedData->size()); expected.writeText("\nendstream"); SkAutoDataUnref expectedResultData2(expected.copyToData()); SkString result = emit_to_string(*stream); ASSERT_EQL(reporter, result, (const char*)expectedResultData2->data(), expectedResultData2->size()); } }
static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); canvas->drawBitmap(bitmap, 0, 0); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); SkDynamicMemoryWStream wStream; SkAutoTUnref<SkPixelSerializer> serializer( SkImageEncoder::CreatePixelSerializer()); picture->serialize(&wStream, serializer); return wStream.copyToData(); }
static void TestPDFStream(skiatest::Reporter* reporter) { char streamBytes[] = "Test\nFoo\tBar"; SkRefPtr<SkMemoryStream> streamData = new SkMemoryStream( streamBytes, strlen(streamBytes), true); streamData->unref(); // SkRefPtr and new both took a reference. SkRefPtr<SkPDFStream> stream = new SkPDFStream(streamData.get()); stream->unref(); // SkRefPtr and new both took a reference. SimpleCheckObjectOutput( reporter, stream.get(), "<</Length 12\n>> stream\nTest\nFoo\tBar\nendstream"); stream->insert("Attribute", new SkPDFInt(42))->unref(); SimpleCheckObjectOutput(reporter, stream.get(), "<</Length 12\n/Attribute 42\n>> stream\n" "Test\nFoo\tBar\nendstream"); if (SkFlate::HaveFlate()) { char streamBytes2[] = "This is a longer string, so that compression " "can do something with it. With shorter strings, " "the short circuit logic cuts in and we end up " "with an uncompressed string."; SkAutoDataUnref streamData2(SkData::NewWithCopy(streamBytes2, strlen(streamBytes2))); SkRefPtr<SkPDFStream> stream = new SkPDFStream(streamData2.get()); stream->unref(); // SkRefPtr and new both took a reference. SkDynamicMemoryWStream compressedByteStream; SkFlate::Deflate(streamData2.get(), &compressedByteStream); SkAutoDataUnref compressedData(compressedByteStream.copyToData()); // Check first without compression. SkDynamicMemoryWStream expectedResult1; expectedResult1.writeText("<</Length 167\n>> stream\n"); expectedResult1.writeText(streamBytes2); expectedResult1.writeText("\nendstream"); SkAutoDataUnref expectedResultData1(expectedResult1.copyToData()); CheckObjectOutput(reporter, stream.get(), (const char*) expectedResultData1->data(), expectedResultData1->size(), true, false); // Then again with compression. SkDynamicMemoryWStream expectedResult2; expectedResult2.writeText("<</Filter /FlateDecode\n/Length 116\n" ">> stream\n"); expectedResult2.write(compressedData->data(), compressedData->size()); expectedResult2.writeText("\nendstream"); SkAutoDataUnref expectedResultData2(expectedResult2.copyToData()); CheckObjectOutput(reporter, stream.get(), (const char*) expectedResultData2->data(), expectedResultData2->size(), true, true); } }
SkData* Request::writeCanvasToPng(SkCanvas* canvas) { // capture pixels SkAutoTDelete<SkBitmap> bmp(this->getBitmapFromCanvas(canvas)); SkASSERT(bmp); // Convert to format suitable for PNG output sk_sp<SkData> encodedBitmap = sk_tools::encode_bitmap_for_png(*bmp); SkASSERT(encodedBitmap.get()); // write to an opaque png (black background) SkDynamicMemoryWStream buffer; SkDrawCommand::WritePNG((const png_bytep) encodedBitmap->bytes(), bmp->width(), bmp->height(), buffer, true); return buffer.copyToData(); }
DEF_TEST(Annotation_PdfLink, reporter) { REQUIRE_PDF_DOCUMENT(Annotation_PdfLink, reporter); SkDynamicMemoryWStream outStream; SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&outStream)); SkCanvas* canvas = doc->beginPage(612.0f, 792.0f); REPORTER_ASSERT(reporter, canvas); SkRect r = SkRect::MakeXYWH(SkIntToScalar(72), SkIntToScalar(72), SkIntToScalar(288), SkIntToScalar(72)); SkAutoDataUnref data(SkData::NewWithCString("http://www.gooogle.com")); SkAnnotateRectWithURL(canvas, r, data.get()); REPORTER_ASSERT(reporter, doc->close()); SkAutoDataUnref out(outStream.copyToData()); const char* rawOutput = (const char*)out->data(); REPORTER_ASSERT(reporter, ContainsString(rawOutput, out->size(), "/Annots ")); }
DEF_TEST(Annotation_NamedDestination, reporter) { REQUIRE_PDF_DOCUMENT(Annotation_NamedDestination, reporter); SkDynamicMemoryWStream outStream; SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&outStream)); SkCanvas* canvas = doc->beginPage(612.0f, 792.0f); REPORTER_ASSERT(reporter, canvas); SkPoint p = SkPoint::Make(SkIntToScalar(72), SkIntToScalar(72)); SkAutoDataUnref data(SkData::NewWithCString("example")); SkAnnotateNamedDestination(canvas, p, data.get()); REPORTER_ASSERT(reporter, doc->close()); SkAutoDataUnref out(outStream.copyToData()); const char* rawOutput = (const char*)out->data(); REPORTER_ASSERT(reporter, ContainsString(rawOutput, out->size(), "/example ")); }
SkData* Request::writeOutSkp() { // Playback into picture recorder SkIRect bounds = this->getBounds(); SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bounds.width()), SkIntToScalar(bounds.height())); fDebugCanvas->draw(canvas); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); SkDynamicMemoryWStream outStream; SkAutoTUnref<SkPixelSerializer> serializer(SkImageEncoder::CreatePixelSerializer()); picture->serialize(&outStream, serializer); return outStream.copyToData(); }
DEF_TEST(SkPDF_MetadataAttribute, r) { REQUIRE_PDF_DOCUMENT(SkPDF_MetadataAttribute, r); SkDynamicMemoryWStream pdf; SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&pdf)); typedef SkDocument::Attribute Attr; Attr info[] = { Attr(SkString("Title"), SkString("A1")), Attr(SkString("Author"), SkString("A2")), Attr(SkString("Subject"), SkString("A3")), Attr(SkString("Keywords"), SkString("A4")), Attr(SkString("Creator"), SkString("A5")), }; int infoCount = sizeof(info) / sizeof(info[0]); SkTime::DateTime now; SkTime::GetDateTime(&now); doc->setMetadata(&info[0], infoCount, &now, &now); doc->beginPage(612.0f, 792.0f); doc->close(); SkAutoTUnref<SkData> data(pdf.copyToData()); static const char* expectations[] = { "/Title (A1)", "/Author (A2)", "/Subject (A3)", "/Keywords (A4)", "/Creator (A5)", "/Producer (Skia/PDF ", "/CreationDate (D:", "/ModDate (D:" }; for (const char* expectation : expectations) { bool found = false; size_t N = 1 + data->size() - strlen(expectation); for (size_t i = 0; i < N; ++i) { if (0 == memcmp(data->bytes() + i, expectation, strlen(expectation))) { found = true; break; } } if (!found) { ERRORF(r, "expectation missing: '%s'.", expectation); } } }
static void stream_copy_test(skiatest::Reporter* reporter, const void* srcData, size_t N, SkStream* stream) { SkDynamicMemoryWStream tgt; if (!SkStreamCopy(&tgt, stream)) { ERRORF(reporter, "SkStreamCopy failed"); return; } SkAutoTUnref<SkData> data(tgt.copyToData()); tgt.reset(); if (data->size() != N) { ERRORF(reporter, "SkStreamCopy incorrect size"); return; } if (0 != memcmp(data->data(), srcData, N)) { ERRORF(reporter, "SkStreamCopy bad copy"); } }
/** * Test that for Jpeg files that use the JFIF colorspace, they are * directly embedded into the PDF (without re-encoding) when that * makes sense. */ DEF_TEST(PDFJpegEmbedTest, r) { const char test[] = "PDFJpegEmbedTest"; SkAutoTUnref<SkData> mandrillData( load_resource(r, test, "mandrill_512_q075.jpg")); SkAutoTUnref<SkData> cmykData(load_resource(r, test, "CMYK.jpg")); if (!mandrillData || !cmykData) { return; } SkDynamicMemoryWStream pdf; SkAutoTUnref<SkDocument> document(SkDocument::CreatePDF(&pdf)); SkCanvas* canvas = document->beginPage(642, 1028); canvas->clear(SK_ColorLTGRAY); SkBitmap bm1(bitmap_from_data(mandrillData)); canvas->drawBitmap(bm1, 65.0, 0.0, NULL); SkBitmap bm2(bitmap_from_data(cmykData)); canvas->drawBitmap(bm2, 0.0, 512.0, NULL); canvas->flush(); document->endPage(); document->close(); SkAutoTUnref<SkData> pdfData(pdf.copyToData()); SkASSERT(pdfData); pdf.reset(); // Test disabled, waiting on resolution to http://skbug.com/3180 // REPORTER_ASSERT(r, is_subset_of(mandrillData, pdfData)); // This JPEG uses a nonstandard colorspace - it can not be // embedded into the PDF directly. REPORTER_ASSERT(r, !is_subset_of(cmykData, pdfData)); // The following is for debugging purposes only. const char* outputPath = getenv("SKIA_TESTS_PDF_JPEG_EMBED_OUTPUT_PATH"); if (outputPath) { SkFILEWStream output(outputPath); if (output.isValid()) { output.write(pdfData->data(), pdfData->size()); } } }
String ImageBuffer::toDataURL(const String&, const double*) const { // Encode the image into a vector. SkDynamicMemoryWStream pngStream; const SkBitmap& dst = imageBufferCanvas(this)->getDevice()->accessBitmap(true); SkImageEncoder::EncodeStream(&pngStream, dst, SkImageEncoder::kPNG_Type, 100); // Convert it into base64. Vector<char> pngEncodedData; SkData* streamData = pngStream.copyToData(); pngEncodedData.append((char*)streamData->data(), streamData->size()); streamData->unref(); Vector<char> base64EncodedData; base64Encode(pngEncodedData, base64EncodedData); // Append with a \0 so that it's a valid string. base64EncodedData.append('\0'); // And the resulting string. return String::format("data:image/png;base64,%s", base64EncodedData.data()); }
static void TestPDFStream(skiatest::Reporter* reporter) { char streamBytes[] = "Test\nFoo\tBar"; std::unique_ptr<SkStreamAsset> streamData(new SkMemoryStream( streamBytes, strlen(streamBytes), true)); auto stream = sk_make_sp<SkPDFStream>(std::move(streamData)); assert_emit_eq(reporter, *stream, "<</Length 12>> stream\nTest\nFoo\tBar\nendstream"); stream->dict()->insertInt("Attribute", 42); assert_emit_eq(reporter, *stream, "<</Length 12\n/Attribute 42>> stream\n" "Test\nFoo\tBar\nendstream"); { char streamBytes2[] = "This is a longer string, so that compression " "can do something with it. With shorter strings, " "the short circuit logic cuts in and we end up " "with an uncompressed string."; auto stream = sk_make_sp<SkPDFStream>( SkData::MakeWithCopy(streamBytes2, strlen(streamBytes2))); SkDynamicMemoryWStream compressedByteStream; SkDeflateWStream deflateWStream(&compressedByteStream); deflateWStream.write(streamBytes2, strlen(streamBytes2)); deflateWStream.finalize(); SkDynamicMemoryWStream expected; expected.writeText("<</Filter /FlateDecode\n/Length 116>> stream\n"); compressedByteStream.writeToStream(&expected); compressedByteStream.reset(); expected.writeText("\nendstream"); SkAutoDataUnref expectedResultData2(expected.copyToData()); SkString result = emit_to_string(*stream); assert_eql(reporter, result, (const char*)expectedResultData2->data(), expectedResultData2->size()); } }