diff options
author | edisonn@google.com <edisonn@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-10 22:33:10 +0000 |
---|---|---|
committer | edisonn@google.com <edisonn@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-10 22:33:10 +0000 |
commit | 222382b30a176db9d9044d9df1ae14e0fbe27181 (patch) | |
tree | 1637df5492b89c338b6e3666d993572a5487c7bf /experimental/PdfViewer | |
parent | 5857e0350d6c3b5e312e1ec9f220aef0fdba06a5 (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.cpp | 1 | ||||
-rw-r--r-- | experimental/PdfViewer/SkPdfParser.h | 88 | ||||
-rw-r--r-- | experimental/PdfViewer/SkPdfRenderer.cpp (renamed from experimental/PdfViewer/SkPdfParser.cpp) | 192 | ||||
-rw-r--r-- | experimental/PdfViewer/SkPdfRenderer.h | 41 | ||||
-rw-r--r-- | experimental/PdfViewer/pdf_viewer_main.cpp | 118 | ||||
-rw-r--r-- | experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp | 73 | ||||
-rw-r--r-- | experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp | 32 | ||||
-rw-r--r-- | experimental/PdfViewer/pdfparser/native/SkPdfObject.h | 8 |
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) { |