aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--experimental/tools/skp_to_pdf_md5.cpp153
-rw-r--r--gyp/experimental.gyp16
2 files changed, 169 insertions, 0 deletions
diff --git a/experimental/tools/skp_to_pdf_md5.cpp b/experimental/tools/skp_to_pdf_md5.cpp
new file mode 100644
index 0000000000..3232c57ed3
--- /dev/null
+++ b/experimental/tools/skp_to_pdf_md5.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "SkCanvas.h"
+#include "SkCommandLineFlags.h"
+#include "SkDocument.h"
+#include "SkForceLinking.h"
+#include "SkGraphics.h"
+#include "SkMD5.h"
+#include "SkOSFile.h"
+#include "SkPicture.h"
+#include "SkStream.h"
+#include "SkTArray.h"
+#include "SkTSort.h"
+
+static const char kUsage[] =
+ "This program takes a list of Skia Picture (SKP) files and renders\n"
+ "each as a multipage PDF, then prints out the MD5 checksum of the\n"
+ "PDF file. This can be used to verify that changes to the PDF\n"
+ "backend will not change PDF output.\n";
+
+__SK_FORCE_IMAGE_DECODER_LINKING;
+
+DEFINE_string2(inputPaths,
+ r,
+ "",
+ "A list of directories and files to use as input.\n"
+ "Files are expected to have the .skp extension.");
+
+static const char SKP_FILE_EXTENSION[] = ".skp";
+
+// Used by SkTQSort<SkString>()
+static bool operator<(const SkString& a, const SkString& b) {
+ return strcmp(a.c_str(), b.c_str()) < 0;
+}
+
+// Process --inputPaths defined on the command line. Return false if
+// no files found.
+static bool process_input_files(SkTArray<SkString>* files) {
+ for (int i = 0; i < FLAGS_inputPaths.count(); i++) {
+ const char* input = FLAGS_inputPaths[i];
+ if (sk_isdir(input)) {
+ SkOSFile::Iter iter(input, SKP_FILE_EXTENSION);
+ SkString inputFilename;
+ while (iter.next(&inputFilename)) {
+ files->push_back(SkOSPath::Join(input, inputFilename.c_str()));
+ }
+ } else {
+ if (SkStrEndsWith(input, SKP_FILE_EXTENSION)) {
+ if (sk_exists(input)) {
+ files->push_back(SkString(input));
+ } else {
+ SkDebugf("file_does_not_exist %s\n", input);
+ }
+ } else {
+ SkDebugf("skipping_file %s\n", input);
+ }
+ }
+ }
+ if (files->count() > 0) {
+ SkTQSort<SkString>(files->begin(), files->end() - 1);
+ return true;
+ }
+ return false;
+}
+
+// Print the given SkPicture to a PDF, breaking on 8.5x11 pages.
+static void picture_to_pdf(const SkPicture& picture, SkWStream* out) {
+ SkAutoTUnref<SkDocument> pdfDocument(SkDocument::CreatePDF(out));
+
+ int width = picture.cullRect().width();
+ int height = picture.cullRect().height();
+
+ const int kLetterWidth = 612; // 8.5 * 72
+ const int kLetterHeight = 792; // 11 * 72
+ SkRect letterRect = SkRect::MakeWH(SkIntToScalar(kLetterWidth),
+ SkIntToScalar(kLetterHeight));
+
+ int xPages = ((width - 1) / kLetterWidth) + 1;
+ int yPages = ((height - 1) / kLetterHeight) + 1;
+
+ for (int y = 0; y < yPages; ++y) {
+ for (int x = 0; x < xPages; ++x) {
+ int w = SkTMin(kLetterWidth, width - (x * kLetterWidth));
+ int h = SkTMin(kLetterHeight, height - (y * kLetterHeight));
+ SkCanvas* canvas = pdfDocument->beginPage(w, h);
+ canvas->clipRect(letterRect);
+ canvas->translate(SkIntToScalar(-kLetterWidth * x),
+ SkIntToScalar(-kLetterHeight * y));
+ canvas->drawPicture(&picture);
+ canvas->flush();
+ pdfDocument->endPage();
+ }
+ }
+ pdfDocument->close();
+ out->flush();
+}
+
+static bool skp_to_pdf_md5(SkStream* input, SkMD5::Digest* digest) {
+ SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(input));
+ if (NULL == picture.get()) {
+ return false;
+ }
+
+ SkMD5 checksumWStream;
+ picture_to_pdf(*picture, &checksumWStream);
+ checksumWStream.finish(*digest);
+ return true;
+}
+
+SkString digest_to_hex(const SkMD5::Digest& digest) {
+ static const char kHex[] = "0123456789ABCDEF";
+ SkString string(2 * sizeof(digest.data));
+ char* p = string.writable_str();
+ for (size_t i = 0; i < sizeof(digest.data); ++i) {
+ uint8_t c = digest.data[i];
+ *(p++) = kHex[c >> 4];
+ *(p++) = kHex[c & 0xF];
+ }
+ return string;
+}
+
+int main(int argc, char** argv) {
+ SkCommandLineFlags::SetUsage(kUsage);
+ SkCommandLineFlags::Parse(argc, argv);
+ SkAutoGraphics ag;
+ int successCount = 0;
+ SkTArray<SkString> files;
+ if (!process_input_files(&files)) {
+ SkDebugf("You need to specify a --inputPaths option.\n");
+ return 1;
+ }
+ for (int i = 0; i < files.count(); ++i) {
+ SkString basename = SkOSPath::Basename(files[i].c_str());
+ SkFILEStream inputStream(files[i].c_str());
+ if (!inputStream.isValid()) {
+ SkDebugf("could_not_open %s\n", basename.c_str());
+ continue;
+ }
+ SkMD5::Digest digest;
+ if (!skp_to_pdf_md5(&inputStream, &digest)) {
+ SkDebugf("invalid_skp %s\n", basename.c_str());
+ continue;
+ }
+ SkString hexDigest = digest_to_hex(digest);
+ printf("%s %s\n", hexDigest.c_str(), basename.c_str());
+ ++successCount;
+ }
+ return successCount == files.count() ? 0 : 1;
+}
diff --git a/gyp/experimental.gyp b/gyp/experimental.gyp
index 87fe920371..8ad3bff860 100644
--- a/gyp/experimental.gyp
+++ b/gyp/experimental.gyp
@@ -89,6 +89,22 @@
],
},
{
+ 'target_name': 'skp_to_pdf_md5',
+ 'type': 'executable',
+ 'sources': [
+ '../experimental/tools/skp_to_pdf_md5.cpp',
+ ],
+ 'include_dirs': [
+ '../src/core',
+ '../tools/flags',
+ ],
+ 'dependencies': [
+ 'pdf.gyp:pdf',
+ 'skia_lib.gyp:skia_lib',
+ 'tools.gyp:sk_tool_utils',
+ ],
+ },
+ {
'target_name': 'gmtoskp',
'type': 'executable',
'sources': [