aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/PdfViewer
diff options
context:
space:
mode:
authorGravatar edisonn@google.com <edisonn@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-10 22:33:10 +0000
committerGravatar edisonn@google.com <edisonn@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-10 22:33:10 +0000
commit222382b30a176db9d9044d9df1ae14e0fbe27181 (patch)
tree1637df5492b89c338b6e3666d993572a5487c7bf /experimental/PdfViewer
parent5857e0350d6c3b5e312e1ec9f220aef0fdba06a5 (diff)
pdf viewer: refactor, add -w parameter to pdfviewer, add -n to remove extenassion page when there is a single page (so skdiff can be run easily) and fix a bug (SkPdfobject should not reset on destruct)
Review URL: https://codereview.chromium.org/18435007 git-svn-id: http://skia.googlecode.com/svn/trunk@9983 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'experimental/PdfViewer')
-rw-r--r--experimental/PdfViewer/SkPdfFont.cpp1
-rw-r--r--experimental/PdfViewer/SkPdfParser.h88
-rw-r--r--experimental/PdfViewer/SkPdfRenderer.cpp (renamed from experimental/PdfViewer/SkPdfParser.cpp)192
-rw-r--r--experimental/PdfViewer/SkPdfRenderer.h41
-rw-r--r--experimental/PdfViewer/pdf_viewer_main.cpp118
-rw-r--r--experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp73
-rw-r--r--experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp32
-rw-r--r--experimental/PdfViewer/pdfparser/native/SkPdfObject.h8
8 files changed, 299 insertions, 254 deletions
diff --git a/experimental/PdfViewer/SkPdfFont.cpp b/experimental/PdfViewer/SkPdfFont.cpp
index 4f2b27986c..2574ce4165 100644
--- a/experimental/PdfViewer/SkPdfFont.cpp
+++ b/experimental/PdfViewer/SkPdfFont.cpp
@@ -1,5 +1,4 @@
#include "SkPdfFont.h"
-#include "SkPdfParser.h"
#include "SkStream.h"
#include "SkTypeface.h"
diff --git a/experimental/PdfViewer/SkPdfParser.h b/experimental/PdfViewer/SkPdfParser.h
deleted file mode 100644
index 00556dce69..0000000000
--- a/experimental/PdfViewer/SkPdfParser.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#ifndef SkPdfParser_DEFINED
-#define SkPdfParser_DEFINED
-
-#include "SkPdfBasics.h"
-#include "SkPdfNativeTokenizer.h"
-
-extern "C" PdfContext* gPdfContext;
-extern "C" SkBitmap* gDumpBitmap;
-extern "C" SkCanvas* gDumpCanvas;
-
-// TODO(edisonn): Document PdfTokenLooper and subclasses.
-class PdfTokenLooper {
-protected:
- PdfTokenLooper* fParent;
- SkPdfNativeTokenizer* fTokenizer;
- PdfContext* fPdfContext;
- SkCanvas* fCanvas;
-
-public:
- PdfTokenLooper(PdfTokenLooper* parent,
- SkPdfNativeTokenizer* tokenizer,
- PdfContext* pdfContext,
- SkCanvas* canvas)
- : fParent(parent), fTokenizer(tokenizer), fPdfContext(pdfContext), fCanvas(canvas) {}
-
- virtual ~PdfTokenLooper() {}
-
- virtual PdfResult consumeToken(PdfToken& token) = 0;
- virtual void loop() = 0;
-
- void setUp(PdfTokenLooper* parent) {
- fParent = parent;
- fTokenizer = parent->fTokenizer;
- fPdfContext = parent->fPdfContext;
- fCanvas = parent->fCanvas;
- }
-};
-
-class PdfMainLooper : public PdfTokenLooper {
-public:
- PdfMainLooper(PdfTokenLooper* parent,
- SkPdfNativeTokenizer* tokenizer,
- PdfContext* pdfContext,
- SkCanvas* canvas)
- : PdfTokenLooper(parent, tokenizer, pdfContext, canvas) {}
-
- virtual PdfResult consumeToken(PdfToken& token);
- virtual void loop();
-};
-
-class PdfInlineImageLooper : public PdfTokenLooper {
-public:
- PdfInlineImageLooper()
- : PdfTokenLooper(NULL, NULL, NULL, NULL) {}
-
- virtual PdfResult consumeToken(PdfToken& token);
- virtual void loop();
- PdfResult done();
-};
-
-class PdfCompatibilitySectionLooper : public PdfTokenLooper {
-public:
- PdfCompatibilitySectionLooper()
- : PdfTokenLooper(NULL, NULL, NULL, NULL) {}
-
- virtual PdfResult consumeToken(PdfToken& token);
- virtual void loop();
-};
-
-// TODO(edisonn): move in another file
-class SkPdfViewer : public SkRefCnt {
-public:
-
- bool load(const SkString inputFileName, SkPicture* out);
- bool write(void*) const { return false; }
-};
-
-void reportPdfRenderStats();
-
-#endif // SkPdfParser_DEFINED
diff --git a/experimental/PdfViewer/SkPdfParser.cpp b/experimental/PdfViewer/SkPdfRenderer.cpp
index 805b877418..39cae9c7d6 100644
--- a/experimental/PdfViewer/SkPdfParser.cpp
+++ b/experimental/PdfViewer/SkPdfRenderer.cpp
@@ -45,7 +45,7 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
#include "SkPdfHeaders_autogen.h"
#include "SkPdfMapper_autogen.h"
-#include "SkPdfParser.h"
+#include "SkPdfRenderer.h"
#include "SkPdfBasics.h"
#include "SkPdfUtils.h"
@@ -72,6 +72,67 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
using namespace std;
+
+
+// TODO(edisonn): Document PdfTokenLooper and subclasses.
+class PdfTokenLooper {
+protected:
+ PdfTokenLooper* fParent;
+ SkPdfNativeTokenizer* fTokenizer;
+ PdfContext* fPdfContext;
+ SkCanvas* fCanvas;
+
+public:
+ PdfTokenLooper(PdfTokenLooper* parent,
+ SkPdfNativeTokenizer* tokenizer,
+ PdfContext* pdfContext,
+ SkCanvas* canvas)
+ : fParent(parent), fTokenizer(tokenizer), fPdfContext(pdfContext), fCanvas(canvas) {}
+
+ virtual ~PdfTokenLooper() {}
+
+ virtual PdfResult consumeToken(PdfToken& token) = 0;
+ virtual void loop() = 0;
+
+ void setUp(PdfTokenLooper* parent) {
+ fParent = parent;
+ fTokenizer = parent->fTokenizer;
+ fPdfContext = parent->fPdfContext;
+ fCanvas = parent->fCanvas;
+ }
+};
+
+class PdfMainLooper : public PdfTokenLooper {
+public:
+ PdfMainLooper(PdfTokenLooper* parent,
+ SkPdfNativeTokenizer* tokenizer,
+ PdfContext* pdfContext,
+ SkCanvas* canvas)
+ : PdfTokenLooper(parent, tokenizer, pdfContext, canvas) {}
+
+ virtual PdfResult consumeToken(PdfToken& token);
+ virtual void loop();
+};
+
+class PdfInlineImageLooper : public PdfTokenLooper {
+public:
+ PdfInlineImageLooper()
+ : PdfTokenLooper(NULL, NULL, NULL, NULL) {}
+
+ virtual PdfResult consumeToken(PdfToken& token);
+ virtual void loop();
+ PdfResult done();
+};
+
+class PdfCompatibilitySectionLooper : public PdfTokenLooper {
+public:
+ PdfCompatibilitySectionLooper()
+ : PdfTokenLooper(NULL, NULL, NULL, NULL) {}
+
+ virtual PdfResult consumeToken(PdfToken& token);
+ virtual void loop();
+};
+
// Utilities
static void setup_bitmap(SkBitmap* bitmap, int width, int height, SkColor color = SK_ColorWHITE) {
bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
@@ -127,6 +188,8 @@ SkMatrix SkMatrixFromPdfArray(SkPdfArray* pdfArray) {
return SkMatrixFromPdfMatrix(array);
}
+
+extern "C" SkNativeParsedPDF* gDoc;
SkBitmap* gDumpBitmap = NULL;
SkCanvas* gDumpCanvas = NULL;
char gLastKeyword[100] = "";
@@ -148,6 +211,8 @@ static bool hasVisualEffect(const char* pdfOp) {
}
#endif // PDF_TRACE_DIFF_IN_PNG
+
+
// TODO(edisonn): Pass PdfContext and SkCanvasd only with the define for instrumentation.
static bool readToken(SkPdfNativeTokenizer* fTokenizer, PdfToken* token) {
bool ret = fTokenizer->readToken(token);
@@ -1856,54 +1921,101 @@ void PdfCompatibilitySectionLooper::loop() {
// TODO (edisonn): hide parser/tokenizer behind and interface and a query language, and resolve
// references automatically.
-bool SkPdfViewer::load(const SkString inputFileName, SkPicture* out) {
- std::cout << "PDF Loaded: " << inputFileName.c_str() << std::endl;
+PdfContext* gPdfContext = NULL;
- SkNativeParsedPDF* doc = new SkNativeParsedPDF(inputFileName.c_str());
- if (!doc->pages())
- {
- std::cout << "ERROR: Empty PDF Document" << inputFileName.c_str() << std::endl;
+bool SkPdfRenderer::renderPage(int page, SkCanvas* canvas) const {
+ if (!fPdfDoc) {
return false;
- } else {
+ }
- for (int pn = 0; pn < doc->pages(); ++pn) {
- // TODO(edisonn): implement inheritance properties as per PDF spec
- //SkRect rect = page->MediaBox();
- SkRect rect = doc->MediaBox(pn);
+ if (page < 0 || page >= pages()) {
+ return false;
+ }
-#ifdef PDF_TRACE
- printf("Page Width: %f, Page Height: %f\n", SkScalarToDouble(rect.width()), SkScalarToDouble(rect.height()));
-#endif
+ SkPdfNativeTokenizer* tokenizer = fPdfDoc->tokenizerOfPage(page);
+
+ PdfContext pdfContext(fPdfDoc);
+ pdfContext.fOriginalMatrix = SkMatrix::I();
+ pdfContext.fGraphicsState.fResources = fPdfDoc->pageResources(page);
+
+ gPdfContext = &pdfContext;
+
+ // TODO(edisonn): get matrix stuff right.
+ // TODO(edisonn): add DPI/scale/zoom.
+ SkScalar z = SkIntToScalar(0);
+ SkRect rect = fPdfDoc->MediaBox(page);
+ SkScalar w = rect.width();
+ SkScalar h = rect.height();
+
+ SkPoint pdfSpace[4] = {SkPoint::Make(z, z), SkPoint::Make(w, z), SkPoint::Make(w, h), SkPoint::Make(z, h)};
+// SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)};
- // TODO(edisonn): page->GetCropBox(), page->GetTrimBox() ... how to use?
+ // TODO(edisonn): add flag for this app to create sourunding buffer zone
+ // TODO(edisonn): add flagg for no clipping.
+ // Use larger image to make sure we do not draw anything outside of page
+ // could be used in tests.
- SkBitmap bitmap;
#ifdef PDF_DEBUG_3X
- setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(rect.width()), 3 * (int)SkScalarToDouble(rect.height()));
+ SkPoint skiaSpace[4] = {SkPoint::Make(w+z, h+h), SkPoint::Make(w+w, h+h), SkPoint::Make(w+w, h+z), SkPoint::Make(w+z, h+z)};
#else
- setup_bitmap(&bitmap, (int)SkScalarToDouble(rect.width()), (int)SkScalarToDouble(rect.height()));
+ SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)};
#endif
- SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap)));
- SkCanvas canvas(device);
-
- gDumpBitmap = &bitmap;
-
- gDumpCanvas = &canvas;
- doc->drawPage(pn, &canvas);
-
- SkString out;
- if (doc->pages() > 1) {
- out.appendf("%s-%i.png", inputFileName.c_str(), pn);
- } else {
- out = inputFileName;
- // .pdf -> .png
- out[out.size() - 2] = 'n';
- out[out.size() - 1] = 'g';
- }
- SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
- }
- return true;
- }
+ //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(w, h)};
+ //SkPoint skiaSpace[2] = {SkPoint::Make(w, z), SkPoint::Make(z, h)};
+
+ //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(z, h)};
+ //SkPoint skiaSpace[2] = {SkPoint::Make(z, h), SkPoint::Make(z, z)};
+
+ //SkPoint pdfSpace[3] = {SkPoint::Make(z, z), SkPoint::Make(z, h), SkPoint::Make(w, h)};
+ //SkPoint skiaSpace[3] = {SkPoint::Make(z, h), SkPoint::Make(z, z), SkPoint::Make(w, 0)};
+
+ SkAssertResult(pdfContext.fOriginalMatrix.setPolyToPoly(pdfSpace, skiaSpace, 4));
+ SkTraceMatrix(pdfContext.fOriginalMatrix, "Original matrix");
+
+
+ pdfContext.fGraphicsState.fMatrix = pdfContext.fOriginalMatrix;
+ pdfContext.fGraphicsState.fMatrixTm = pdfContext.fGraphicsState.fMatrix;
+ pdfContext.fGraphicsState.fMatrixTlm = pdfContext.fGraphicsState.fMatrix;
+
+ canvas->setMatrix(pdfContext.fOriginalMatrix);
+#ifndef PDF_DEBUG_NO_PAGE_CLIPING
+ canvas->clipRect(SkRect::MakeXYWH(z, z, w, h), SkRegion::kIntersect_Op, true);
+#endif
+
+// erase with red before?
+// SkPaint paint;
+// paint.setColor(SK_ColorRED);
+// canvas->drawRect(rect, paint);
+
+ PdfMainLooper looper(NULL, tokenizer, &pdfContext, canvas);
+ looper.loop();
+
+ delete tokenizer;
+
+ canvas->flush();
return true;
}
+
+bool SkPdfRenderer::load(const SkString inputFileName) {
+ unload();
+
+ // TODO(edisonn): create static function that could return NULL if there are errors
+ fPdfDoc = new SkNativeParsedPDF(inputFileName.c_str());
+
+ return fPdfDoc != NULL;
+}
+
+int SkPdfRenderer::pages() const {
+ return fPdfDoc != NULL ? fPdfDoc->pages() : 0;
+}
+
+void SkPdfRenderer::unload() {
+ delete fPdfDoc;
+ fPdfDoc = NULL;
+}
+
+SkRect SkPdfRenderer::MediaBox(int page) const {
+ SkASSERT(fPdfDoc);
+ return fPdfDoc->MediaBox(page);
+}
diff --git a/experimental/PdfViewer/SkPdfRenderer.h b/experimental/PdfViewer/SkPdfRenderer.h
new file mode 100644
index 0000000000..ba556ff390
--- /dev/null
+++ b/experimental/PdfViewer/SkPdfRenderer.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPdfParser_DEFINED
+#define SkPdfParser_DEFINED
+
+#include "SkPdfBasics.h"
+#include "SkPdfNativeTokenizer.h"
+
+extern "C" PdfContext* gPdfContext;
+extern "C" SkBitmap* gDumpBitmap;
+extern "C" SkCanvas* gDumpCanvas;
+
+class SkCanvas;
+class SkNativeParsedPDF;
+
+// TODO(edisonn): move in another file
+class SkPdfRenderer : public SkRefCnt {
+ SkNativeParsedPDF* fPdfDoc;
+public:
+ SkPdfRenderer() : fPdfDoc(NULL) {}
+ virtual ~SkPdfRenderer() {unload();}
+
+ // TODO(edisonn): add options to render forms, or not
+ bool renderPage(int page, SkCanvas* canvas) const;
+
+ bool load(const SkString inputFileName);
+ bool loaded() const {return fPdfDoc != NULL;}
+ int pages() const;
+ void unload();
+ SkRect MediaBox(int page) const;
+};
+
+void reportPdfRenderStats();
+
+#endif // SkPdfParser_DEFINED
diff --git a/experimental/PdfViewer/pdf_viewer_main.cpp b/experimental/PdfViewer/pdf_viewer_main.cpp
index ac1aef01ad..45bfff3990 100644
--- a/experimental/PdfViewer/pdf_viewer_main.cpp
+++ b/experimental/PdfViewer/pdf_viewer_main.cpp
@@ -11,7 +11,7 @@
#include "SkTArray.h"
#include "picture_utils.h"
-#include "SkPdfParser.h"
+#include "SkPdfRenderer.h"
/**
* Given list of directories and files to use as input, expects to find .pdf
@@ -30,7 +30,7 @@ static void usage(const char* argv0) {
SkDebugf("PDF to PNG rendering tool\n");
SkDebugf("\n"
"Usage: \n"
-" %s <input>... -w <outputDir> \n"
+" %s <input>... [-w <outputDir>] [-n | --no-page-ext] \n"
, argv0);
SkDebugf("\n\n");
SkDebugf(
@@ -38,6 +38,8 @@ static void usage(const char* argv0) {
" expected to have the .skp extension.\n\n");
SkDebugf(
" outputDir: directory to write the rendered pdfs.\n\n");
+ SkDebugf(
+" -n: no page extension if only one page.\n\n");
SkDebugf("\n");
}
@@ -48,8 +50,7 @@ static void usage(const char* argv0) {
* @returns false if the file did not has the expected extension.
* if false is returned, contents of path are undefined.
*/
-/*
-static bool replace_filename_extension(SkString* path,
+static bool add_page_and_replace_filename_extension(SkString* path, int page,
const char old_extension[],
const char new_extension[]) {
if (path->endsWith(old_extension)) {
@@ -58,12 +59,15 @@ static bool replace_filename_extension(SkString* path,
if (!path->endsWith(".")) {
return false;
}
+ if (page >= 0) {
+ path->appendf("%i.", page);
+ }
path->append(new_extension);
return true;
}
return false;
}
-*/
+
/** Builds the output filename. path = dir/name, and it replaces expected
* .skp extension with .pdf extention.
* @param path Output filename.
@@ -72,52 +76,76 @@ static bool replace_filename_extension(SkString* path,
* if false is returned, contents of path are undefined.
*/
-/*
+
static bool make_output_filepath(SkString* path, const SkString& dir,
- const SkString& name) {
+ const SkString& name,
+ int page) {
sk_tools::make_filepath(path, dir, name);
- return replace_filename_extension(path,
- PDF_FILE_EXTENSION,
- PNG_FILE_EXTENSION);
+ return add_page_and_replace_filename_extension(path, page,
+ PDF_FILE_EXTENSION,
+ PNG_FILE_EXTENSION);
+}
+
+static void setup_bitmap(SkBitmap* bitmap, int width, int height, SkColor color = SK_ColorWHITE) {
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
+
+ bitmap->allocPixels();
+ bitmap->eraseColor(color);
}
-*/
+
/** Write the output of pdf renderer to a file.
* @param outputDir Output dir.
* @param inputFilename The skp file that was read.
* @param renderer The object responsible to write the pdf file.
*/
-/*
-static bool write_output(const SkString& outputDir,
+
+static bool render_page(const SkString& outputDir,
const SkString& inputFilename,
- const SkPdfViewer& renderer) {
+ const SkPdfRenderer& renderer,
+ int page) {
if (outputDir.isEmpty()) {
- SkDynamicMemoryWStream stream;
- renderer.write(&stream);
- return true;
+ SkBitmap bitmap;
+ setup_bitmap(&bitmap, 1, 1);
+ SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap)));
+ SkCanvas canvas(device);
+ return renderer.renderPage(page < 0 ? 0 : page, &canvas);
}
SkString outputPath;
- if (!make_output_filepath(&outputPath, outputDir, inputFilename)) {
+ if (!make_output_filepath(&outputPath, outputDir, inputFilename, page)) {
return false;
}
- SkFILEWStream stream(outputPath.c_str());
- if (!stream.isValid()) {
- SkDebugf("Could not write to file %s\n", outputPath.c_str());
- return false;
- }
- renderer.write(&stream);
+ SkRect rect = renderer.MediaBox(page < 0 ? 0 :page);
+
+ SkBitmap bitmap;
+#ifdef PDF_DEBUG_3X
+ setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(rect.width()), 3 * (int)SkScalarToDouble(rect.height()));
+#else
+ setup_bitmap(&bitmap, (int)SkScalarToDouble(rect.width()), (int)SkScalarToDouble(rect.height()));
+#endif
+ SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap)));
+ SkCanvas canvas(device);
+
+ gDumpBitmap = &bitmap;
+
+ gDumpCanvas = &canvas;
+ renderer.renderPage(page, &canvas);
+
+ SkImageEncoder::EncodeFile(outputPath.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
return true;
}
-*/
+
/** Reads an skp file, renders it to pdf and writes the output to a pdf file
* @param inputPath The skp file to be read.
* @param outputDir Output dir.
* @param renderer The object responsible to render the skp object into pdf.
*/
-static bool parse_pdf(const SkString& inputPath, const SkString& outputDir,
- SkPdfViewer& renderer) {
+static bool process_pdf(const SkString& inputPath, const SkString& outputDir,
+ SkPdfRenderer& renderer, bool noPageExt) {
+ SkDebugf("Loading PDF: %s\n", inputPath.c_str());
+
SkString inputFilename;
sk_tools::get_basename(&inputFilename, inputPath);
@@ -130,12 +158,20 @@ static bool parse_pdf(const SkString& inputPath, const SkString& outputDir,
bool success = false;
- success = renderer.load(inputPath, NULL);
+ success = renderer.load(inputPath);
+ if (success) {
+ if (!renderer.pages())
+ {
+ SkDebugf("ERROR: Empty PDF Document %s\n", inputPath.c_str());
+ return false;
+ } else {
+ for (int pn = 0; pn < renderer.pages(); ++pn) {
+ success = render_page(outputDir, inputFilename, renderer, noPageExt && renderer.pages() == 1 ? -1 : pn) && success;
+ }
+ }
+ }
-// success = write_output(outputDir, inputFilename, renderer);
-
- //renderer.end();
return success;
}
@@ -146,7 +182,7 @@ static bool parse_pdf(const SkString& inputPath, const SkString& outputDir,
* @param renderer The object responsible to render the skp object into pdf.
*/
static int process_input(const SkString& input, const SkString& outputDir,
- SkPdfViewer& renderer) {
+ SkPdfRenderer& renderer, bool noPageExt) {
int failures = 0;
if (sk_isdir(input.c_str())) {
SkOSFile::Iter iter(input.c_str(), PDF_FILE_EXTENSION);
@@ -154,13 +190,13 @@ static int process_input(const SkString& input, const SkString& outputDir,
while (iter.next(&inputFilename)) {
SkString inputPath;
sk_tools::make_filepath(&inputPath, input, inputFilename);
- if (!parse_pdf(inputPath, outputDir, renderer)) {
+ if (!process_pdf(inputPath, outputDir, renderer, noPageExt)) {
++failures;
}
}
} else {
SkString inputPath(input);
- if (!parse_pdf(inputPath, outputDir, renderer)) {
+ if (!process_pdf(inputPath, outputDir, renderer, noPageExt)) {
++failures;
}
}
@@ -169,7 +205,7 @@ static int process_input(const SkString& input, const SkString& outputDir,
static void parse_commandline(int argc, char* const argv[],
SkTArray<SkString>* inputs,
- SkString* outputDir) {
+ SkString* outputDir, bool* noPageExt) {
const char* argv0 = argv[0];
char* const* stop = argv + argc;
@@ -177,6 +213,8 @@ static void parse_commandline(int argc, char* const argv[],
if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
usage(argv0);
exit(-1);
+ } else if ((0 == strcmp(*argv, "-n")) || (0 == strcmp(*argv, "--no-page-ext"))) {
+ *noPageExt = true;
} else if (0 == strcmp(*argv, "-w")) {
++argv;
if (argv >= stop) {
@@ -201,16 +239,16 @@ int tool_main(int argc, char** argv) {
SkAutoGraphics ag;
SkTArray<SkString> inputs;
- SkAutoTUnref<SkPdfViewer>
- renderer(SkNEW(SkPdfViewer));
- SkASSERT(renderer.get());
+ SkPdfRenderer renderer;
SkString outputDir;
- parse_commandline(argc, argv, &inputs, &outputDir);
+ bool noPageExt = false;
+ parse_commandline(argc, argv, &inputs, &outputDir, &noPageExt);
int failures = 0;
for (int i = 0; i < inputs.count(); i ++) {
- failures += process_input(inputs[i], outputDir, *renderer);
+ failures += process_input(inputs[i], outputDir, renderer, noPageExt);
+ renderer.unload();
}
reportPdfRenderStats();
diff --git a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
index b359a8d33d..5f16176376 100644
--- a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
@@ -1,7 +1,6 @@
#include "SkNativeParsedPDF.h"
#include "SkPdfNativeTokenizer.h"
#include "SkPdfBasics.h"
-#include "SkPdfParser.h"
#include "SkPdfObject.h"
#include <stdio.h>
@@ -59,6 +58,7 @@ static unsigned char* ignoreLine(unsigned char* current, unsigned char* end) {
return current;
}
+SkNativeParsedPDF* gDoc = NULL;
// TODO(edisonn): NYI
// TODO(edisonn): 3 constructuctors from URL, from stream, from file ...
@@ -68,10 +68,12 @@ static unsigned char* ignoreLine(unsigned char* current, unsigned char* end) {
// 2) recoverable corupt file: remove endobj, endsteam, remove other keywords, use other white spaces, insert comments randomly, ...
// 3) irrecoverable corrupt file
SkNativeParsedPDF::SkNativeParsedPDF(const char* path) : fAllocator(new SkPdfAllocator()) {
+ gDoc = this;
FILE* file = fopen(path, "r");
fContentLength = getFileSize(path);
- fFileContent = new unsigned char[fContentLength];
+ fFileContent = new unsigned char[fContentLength + 1];
fread(fFileContent, fContentLength, 1, file);
+ fFileContent[fContentLength] = '\0';
fclose(file);
file = NULL;
@@ -355,73 +357,6 @@ SkPdfString* SkNativeParsedPDF::createString(unsigned char* sz, size_t len) cons
return (SkPdfString*)obj;
}
-PdfContext* gPdfContext = NULL;
-
-void SkNativeParsedPDF::drawPage(int page, SkCanvas* canvas) {
- SkPdfNativeTokenizer* tokenizer = tokenizerOfPage(page);
-
- PdfContext pdfContext(this);
- pdfContext.fOriginalMatrix = SkMatrix::I();
- pdfContext.fGraphicsState.fResources = pageResources(page);
-
- gPdfContext = &pdfContext;
-
- // TODO(edisonn): get matrix stuff right.
- // TODO(edisonn): add DPI/scale/zoom.
- SkScalar z = SkIntToScalar(0);
- SkRect rect = MediaBox(page);
- SkScalar w = rect.width();
- SkScalar h = rect.height();
-
- SkPoint pdfSpace[4] = {SkPoint::Make(z, z), SkPoint::Make(w, z), SkPoint::Make(w, h), SkPoint::Make(z, h)};
-// SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)};
-
- // TODO(edisonn): add flag for this app to create sourunding buffer zone
- // TODO(edisonn): add flagg for no clipping.
- // Use larger image to make sure we do not draw anything outside of page
- // could be used in tests.
-
-#ifdef PDF_DEBUG_3X
- SkPoint skiaSpace[4] = {SkPoint::Make(w+z, h+h), SkPoint::Make(w+w, h+h), SkPoint::Make(w+w, h+z), SkPoint::Make(w+z, h+z)};
-#else
- SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)};
-#endif
- //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(w, h)};
- //SkPoint skiaSpace[2] = {SkPoint::Make(w, z), SkPoint::Make(z, h)};
-
- //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(z, h)};
- //SkPoint skiaSpace[2] = {SkPoint::Make(z, h), SkPoint::Make(z, z)};
-
- //SkPoint pdfSpace[3] = {SkPoint::Make(z, z), SkPoint::Make(z, h), SkPoint::Make(w, h)};
- //SkPoint skiaSpace[3] = {SkPoint::Make(z, h), SkPoint::Make(z, z), SkPoint::Make(w, 0)};
-
- SkAssertResult(pdfContext.fOriginalMatrix.setPolyToPoly(pdfSpace, skiaSpace, 4));
- SkTraceMatrix(pdfContext.fOriginalMatrix, "Original matrix");
-
-
- pdfContext.fGraphicsState.fMatrix = pdfContext.fOriginalMatrix;
- pdfContext.fGraphicsState.fMatrixTm = pdfContext.fGraphicsState.fMatrix;
- pdfContext.fGraphicsState.fMatrixTlm = pdfContext.fGraphicsState.fMatrix;
-
- canvas->setMatrix(pdfContext.fOriginalMatrix);
-
-#ifndef PDF_DEBUG_NO_PAGE_CLIPING
- canvas->clipRect(SkRect::MakeXYWH(z, z, w, h), SkRegion::kIntersect_Op, true);
-#endif
-
-// erase with red before?
-// SkPaint paint;
-// paint.setColor(SK_ColorRED);
-// canvas->drawRect(rect, paint);
-
- PdfMainLooper looper(NULL, tokenizer, &pdfContext, canvas);
- looper.loop();
-
- delete tokenizer;
-
- canvas->flush();
-}
-
SkPdfAllocator* SkNativeParsedPDF::allocator() const {
return fAllocator;
}
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
index 53987fa383..fc3e0b94ed 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
@@ -656,8 +656,14 @@ SkPdfAllocator::~SkPdfAllocator() {
free(fHandles[i]);
}
for (int i = 0 ; i < fHistory.count(); i++) {
+ for (int j = 0 ; j < BUFFER_SIZE; j++) {
+ fHistory[i][j].reset();
+ }
delete[] fHistory[i];
}
+ for (int j = 0 ; j < BUFFER_SIZE; j++) {
+ fCurrent[j].reset();
+ }
delete[] fCurrent;
}
@@ -667,7 +673,6 @@ SkPdfObject* SkPdfAllocator::allocObject() {
fCurrent = allocBlock();
fCurrentUsed = 0;
}
-
fCurrentUsed++;
return &fCurrent[fCurrentUsed - 1];
}
@@ -677,26 +682,28 @@ SkPdfNativeTokenizer::SkPdfNativeTokenizer(SkPdfObject* objWithStream, const SkP
unsigned char* buffer = NULL;
size_t len = 0;
objWithStream->GetFilteredStreamRef(&buffer, &len, fAllocator);
+ // TODO(edisonn): hack, find end of object
+ char* endobj = strstr((char*)buffer, "endobj");
+ if (endobj) {
+ len = endobj - (char*)buffer + strlen("endobj");
+ }
fUncompressedStreamStart = fUncompressedStream = (unsigned char*)fAllocator->alloc(len);
fUncompressedStreamEnd = fUncompressedStream + len;
- memcpy(fUncompressedStream, buffer, len);}
+ memcpy(fUncompressedStream, buffer, len);
+}
SkPdfNativeTokenizer::SkPdfNativeTokenizer(unsigned char* buffer, int len, const SkPdfMapper* mapper, SkPdfAllocator* allocator) : fMapper(mapper), fAllocator(allocator), fEmpty(false), fHasPutBack(false) {
+ // TODO(edisonn): hack, find end of object
+ char* endobj = strstr((char*)buffer, "endobj");
+ if (endobj) {
+ len = endobj - (char*)buffer + strlen("endobj");
+ }
fUncompressedStreamStart = fUncompressedStream = (unsigned char*)fAllocator->alloc(len);
fUncompressedStreamEnd = fUncompressedStream + len;
memcpy(fUncompressedStream, buffer, len);
}
SkPdfNativeTokenizer::~SkPdfNativeTokenizer() {
- // free the unparsed stream, we don't need it.
- // the parsed one is locked as it contains the strings and keywords referenced in objects
- if (fUncompressedStream) {
- void* dummy = realloc(fUncompressedStreamStart, fUncompressedStream - fUncompressedStreamStart);
- //SkASSERT(dummy == fUncompressedStreamStart);
- fUncompressedStreamStart = (unsigned char*)dummy; // suppress compiler warning
- } else {
- SkASSERT(false);
- }
}
bool SkPdfNativeTokenizer::readTokenCore(PdfToken* token) {
@@ -726,7 +733,7 @@ bool SkPdfNativeTokenizer::readTokenCore(PdfToken* token) {
#ifdef PDF_TRACE
static int read_op = 0;
read_op++;
- if (182749 == read_op) {
+ if (548 == read_op) {
printf("break;\n");
}
printf("%i READ %s %s\n", read_op, token->fType == kKeyword_TokenType ? "Keyword" : "Object", token->fKeyword ? std::string(token->fKeyword, token->fKeywordLength).c_str() : token->fObject->toString().c_str());
@@ -763,3 +770,4 @@ bool SkPdfNativeTokenizer::readToken(PdfToken* token) {
return readTokenCore(token);
}
+
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfObject.h b/experimental/PdfViewer/pdfparser/native/SkPdfObject.h
index 86963b0398..a215501056 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfObject.h
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfObject.h
@@ -86,7 +86,7 @@ private:
public:
- SkPdfObject() : fObjectType(kInvalid_PdfObjectType), fData(NULL) {}
+ SkPdfObject() : fObjectType(kInvalid_PdfObjectType), fMap(NULL), fData(NULL) {}
inline void* data() {
return fData;
@@ -96,9 +96,9 @@ public:
fData = data;
}
- ~SkPdfObject() {
- reset();
- }
+// ~SkPdfObject() {
+// //reset(); must be called manually!
+// }
void reset() {
switch (fObjectType) {