| Index: experimental/PdfViewer/SkPdfRenderer.cpp
|
| ===================================================================
|
| --- experimental/PdfViewer/SkPdfRenderer.cpp (revision 9970)
|
| +++ experimental/PdfViewer/SkPdfRenderer.cpp (working copy)
|
| @@ -45,7 +45,7 @@
|
|
|
| #include "SkPdfHeaders_autogen.h"
|
| #include "SkPdfMapper_autogen.h"
|
| -#include "SkPdfParser.h"
|
| +#include "SkPdfRenderer.h"
|
|
|
| #include "SkPdfBasics.h"
|
| #include "SkPdfUtils.h"
|
| @@ -72,6 +72,67 @@
|
|
|
| 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 @@
|
| return SkMatrixFromPdfMatrix(array);
|
| }
|
|
|
| +
|
| +extern "C" SkNativeParsedPDF* gDoc;
|
| SkBitmap* gDumpBitmap = NULL;
|
| SkCanvas* gDumpCanvas = NULL;
|
| char gLastKeyword[100] = "";
|
| @@ -148,6 +211,8 @@
|
| }
|
| #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 @@
|
| // 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);
|
|
|
| - // TODO(edisonn): page->GetCropBox(), page->GetTrimBox() ... how to use?
|
| + PdfContext pdfContext(fPdfDoc);
|
| + pdfContext.fOriginalMatrix = SkMatrix::I();
|
| + pdfContext.fGraphicsState.fResources = fPdfDoc->pageResources(page);
|
|
|
| - SkBitmap bitmap;
|
| + 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): 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
|
| - 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);
|
| + //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(w, h)};
|
| + //SkPoint skiaSpace[2] = {SkPoint::Make(w, z), SkPoint::Make(z, h)};
|
|
|
| - gDumpBitmap = &bitmap;
|
| + //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(z, h)};
|
| + //SkPoint skiaSpace[2] = {SkPoint::Make(z, h), SkPoint::Make(z, z)};
|
|
|
| - gDumpCanvas = &canvas;
|
| - doc->drawPage(pn, &canvas);
|
| + //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)};
|
|
|
| - 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;
|
| - }
|
| + 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);
|
| +}
|
|
|