--- /dev/null
+#include "SkNulCanvas.h"
--- /dev/null
+#ifndef EXPERIMENTAL_PDFVIEWER_SKNULCANVAS_H_
+#define EXPERIMENTAL_PDFVIEWER_SKNULCANVAS_H_
+
+#include "SkCanvas.h"
+
+class SK_API SkNulCanvas : public SkCanvas {
+public:
+ SK_DECLARE_INST_COUNT(SkNulCanvas);
+
+ SkNulCanvas() {}
+ explicit SkNulCanvas(SkDevice* device) : SkCanvas(device) {}
+
+ explicit SkNulCanvas(const SkBitmap& bitmap) : SkCanvas(bitmap) {}
+ virtual ~SkNulCanvas() {}
+
+ virtual int save(SaveFlags flags = kMatrixClip_SaveFlag) {return 0;}
+ virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags = kARGB_ClipLayer_SaveFlag) {return 0;}
+ int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
+ SaveFlags flags = kARGB_ClipLayer_SaveFlag) {return 0;}
+ virtual void restore() {}
+ int getSaveCount() const {return 0;}
+ virtual bool isDrawingToLayer() const {return false;}
+ virtual bool translate(SkScalar dx, SkScalar dy) {return true;}
+ virtual bool scale(SkScalar sx, SkScalar sy) {return true;}
+ virtual bool rotate(SkScalar degrees) {return true;}
+ virtual bool skew(SkScalar sx, SkScalar sy) {return true;}
+ virtual bool concat(const SkMatrix& matrix) {return true;}
+ virtual void setMatrix(const SkMatrix& matrix) {}
+ virtual bool clipRect(const SkRect& rect,
+ SkRegion::Op op = SkRegion::kIntersect_Op,
+ bool doAntiAlias = false) {return true;}
+ virtual bool clipRRect(const SkRRect& rrect,
+ SkRegion::Op op = SkRegion::kIntersect_Op,
+ bool doAntiAlias = false) {return true;}
+ virtual bool clipPath(const SkPath& path,
+ SkRegion::Op op = SkRegion::kIntersect_Op,
+ bool doAntiAlias = false) {return true;}
+ virtual bool clipRegion(const SkRegion& deviceRgn,
+ SkRegion::Op op = SkRegion::kIntersect_Op) {return true;}
+ virtual void clear(SkColor) {}
+ virtual void drawPaint(const SkPaint& paint) {}
+ virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) {}
+ virtual void drawRect(const SkRect& rect, const SkPaint& paint) {}
+ virtual void drawOval(const SkRect& oval, const SkPaint&) {}
+ virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint) {}
+ virtual void drawPath(const SkPath& path, const SkPaint& paint) {}
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint* paint = NULL) {}
+ virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint) {}
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint = NULL) {}
+ virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+ const SkRect& dst, const SkPaint* paint = NULL) {}
+ virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint = NULL) {}
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) {}
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) {}
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) {}
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) {}
+ virtual void drawPicture(SkPicture& picture) {}
+ virtual void drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) {}
+ virtual void drawData(const void* data, size_t length) {}
+ virtual void beginCommentGroup(const char* description) {}
+ virtual void addComment(const char* kywd, const char* value) {}
+ virtual void endCommentGroup() {}
+ virtual SkBounder* setBounder(SkBounder* bounder) {return NULL;}
+ virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) {return NULL;}
+
+protected:
+ virtual SkCanvas* canvasForDrawIter() {return NULL;}
+ virtual SkDevice* setDevice(SkDevice* device) {return NULL;}
+
+private:
+ typedef SkCanvas INHERITED;
+};
+
+#endif // EXPERIMENTAL_PDFVIEWER_SKNULCANVAS_H_
--- /dev/null
+
+#include "SkTrackDevice.h"
+
--- /dev/null
+#ifndef EXPERIMENTAL_PDFVIEWER_SKTRACKDEVICE_H_
+#define EXPERIMENTAL_PDFVIEWER_SKTRACKDEVICE_H_
+
+#include "SkDevice.h"
+#include "SkTracker.h"
+
+class SkTrackDevice : public SkDevice {
+public:
+ SK_DECLARE_INST_COUNT(SkTrackDevice)
+
+ SkTrackDevice(const SkBitmap& bitmap) : SkDevice(bitmap)
+ , fTracker(NULL) {}
+
+ SkTrackDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
+ : SkDevice(bitmap, deviceProperties)
+ , fTracker(NULL) {}
+
+ SkTrackDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false)
+ : SkDevice(config, width, height, isOpaque)
+ , fTracker(NULL) {}
+
+ SkTrackDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
+ const SkDeviceProperties& deviceProperties)
+ : SkDevice(config, width, height, isOpaque, deviceProperties)
+ , fTracker(NULL) {}
+
+ virtual ~SkTrackDevice() {}
+
+ void installTracker(SkTracker* tracker) {
+ fTracker = tracker;
+ fTracker->newFrame();
+ }
+
+protected:
+ virtual void clear(SkColor color) {
+ before();
+ INHERITED::clear(color);
+ after();
+ }
+
+ virtual void drawPaint(const SkDraw& dummy1, const SkPaint& paint) {
+ before();
+ INHERITED::drawPaint(dummy1, paint);
+ after();
+ }
+
+ virtual void drawPoints(const SkDraw& dummy1, SkCanvas::PointMode mode, size_t count,
+ const SkPoint dummy2[], const SkPaint& paint) {
+ before();
+ INHERITED::drawPoints(dummy1, mode, count, dummy2, paint);
+ after();
+ }
+
+ virtual void drawRect(const SkDraw& dummy1, const SkRect& r,
+ const SkPaint& paint) {
+ before();
+ INHERITED::drawRect(dummy1, r, paint);
+ after();
+ }
+
+
+ virtual void drawOval(const SkDraw& dummy1, const SkRect& oval,
+ const SkPaint& paint) {
+ before();
+ INHERITED::drawOval(dummy1, oval, paint);
+ after();
+ }
+
+ virtual void drawRRect(const SkDraw& dummy1, const SkRRect& rr,
+ const SkPaint& paint) {
+ before();
+ INHERITED::drawRRect(dummy1, rr, paint);
+ after();
+ }
+
+ virtual void drawPath(const SkDraw& dummy1, const SkPath& path,
+ const SkPaint& paint,
+ const SkMatrix* prePathMatrix = NULL,
+ bool pathIsMutable = false) {
+ before();
+ INHERITED::drawPath(dummy1, path, paint, prePathMatrix, pathIsMutable);
+ after();
+ }
+
+ virtual void drawBitmap(const SkDraw& dummy1, const SkBitmap& bitmap,
+ const SkIRect* srcRectOrNull,
+ const SkMatrix& matrix, const SkPaint& paint) {
+ before();
+ INHERITED::drawBitmap(dummy1, bitmap, srcRectOrNull, matrix, paint);
+ after();
+ }
+
+ virtual void drawSprite(const SkDraw& dummy1, const SkBitmap& bitmap,
+ int x, int y, const SkPaint& paint) {
+ before();
+ INHERITED::drawSprite(dummy1, bitmap, x, y, paint);
+ after();
+ }
+
+ virtual void drawBitmapRect(const SkDraw& dummy1, const SkBitmap& dummy2,
+ const SkRect* srcOrNull, const SkRect& dst,
+ const SkPaint& paint) {
+ before();
+ INHERITED::drawBitmapRect(dummy1, dummy2, srcOrNull, dst, paint);
+ after();
+ }
+
+ virtual void drawText(const SkDraw& dummy1, const void* text, size_t len,
+ SkScalar x, SkScalar y, const SkPaint& paint) {
+ before();
+ INHERITED::drawText(dummy1, text, len, x, y, paint);
+ after();
+ }
+
+ virtual void drawPosText(const SkDraw& dummy1, const void* text, size_t len,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPos, const SkPaint& paint) {
+ before();
+ INHERITED::drawPosText(dummy1, text, len, pos, constY, scalarsPerPos, paint);
+ after();
+ }
+
+ virtual void drawTextOnPath(const SkDraw& dummy1, const void* text, size_t len,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) {
+ before();
+ INHERITED::drawTextOnPath(dummy1, text, len, path, matrix, paint);
+ after();
+ }
+
+#ifdef SK_BUILD_FOR_ANDROID
+ virtual void drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
+ const SkPoint pos[], const SkPaint& paint,
+ const SkPath& path, const SkMatrix* matrix) {
+ before();
+ INHERITED::drawPosTextOnPath(draw, text, len, pos, paint, path, matrix);
+ after();
+ }
+#endif
+ virtual void drawVertices(const SkDraw& dummy1, SkCanvas::VertexMode dummy2, int vertexCount,
+ const SkPoint verts[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) {
+ before();
+ INHERITED::drawVertices(dummy1, dummy2, vertexCount,verts, texs,colors, xmode, indices, indexCount, paint);
+ after();
+ }
+
+ virtual void drawDevice(const SkDraw& dummy1, SkDevice* dummy2, int x, int y,
+ const SkPaint& dummy3) {
+ before();
+ INHERITED::drawDevice(dummy1, dummy2, x, y, dummy3);
+ after();
+ }
+
+private:
+ void before() {
+ if (fTracker) {
+ fTracker->before(accessBitmap(false));
+ }
+ }
+
+ // any/all of the expected touched has to be changed, and all expected untouched must be intact
+ void after() {
+ if (fTracker) {
+ fTracker->after(accessBitmap(false));
+ }
+ }
+
+private:
+ SkTracker* fTracker;
+
+ typedef SkDevice INHERITED;
+};
+
+#endif // EXPERIMENTAL_PDFVIEWER_SKTRACKDEVICE_H_
--- /dev/null
+
+#include "SkTracker.h"
+
--- /dev/null
+#ifndef EXPERIMENTAL_PDFVIEWER_SKTRACKER_H_
+#define EXPERIMENTAL_PDFVIEWER_SKTRACKER_H_
+
+#include "SkBitmap.h"
+#include "SkPoint.h"
+
+#define MAX_TRACKING_POINTS 100
+
+class SkTracker {
+public:
+ SkTracker() : fEnabled(false)
+ , fBreakOnAny(false)
+ , fCntExpectedTouched(0)
+ , fCntExpectedUntouched(0)
+ , fHits(0) {}
+
+ virtual ~SkTracker() {}
+
+ void clearPoints() {
+ fCntExpectedTouched = 0;
+ fCntExpectedUntouched = 0;
+ }
+
+ void enableTracking(bool b) {
+ fEnabled = b;
+ }
+
+ bool trackingEnabled() {
+ return fEnabled;
+ }
+
+ void any() {
+ fBreakOnAny = true;
+ }
+
+ void all() {
+ fBreakOnAny = false;
+ }
+
+ bool requireAllExpectedTouched() {
+ return !fBreakOnAny;
+ }
+
+ int cntExpectedTouched() {
+ return fCntExpectedTouched;
+ }
+
+ const SkIPoint* expectedTouched() {
+ return fExpectedTouched;
+ }
+
+ int cntExpectedUntouched() {
+ return fCntExpectedUntouched;
+ }
+
+ const SkIPoint* expectedUntouched() {
+ return fExpectedUntouched;
+ }
+
+ bool addExpectTouch(int x, int y) {
+ if (fCntExpectedTouched >= MAX_TRACKING_POINTS) {
+ return false;
+ }
+ if (found(x, y)) {
+ return false;
+ }
+ fExpectedTouched[fCntExpectedTouched] = SkIPoint::Make(x, y);
+ fCntExpectedTouched++;
+ return true;
+ }
+
+ bool addExpectUntouch(int x, int y) {
+ if (fCntExpectedUntouched >= MAX_TRACKING_POINTS) {
+ return false;
+ }
+ if (found(x, y)) {
+ return false;
+ }
+ fExpectedUntouched[fCntExpectedUntouched] = SkIPoint::Make(x, y);
+ fCntExpectedUntouched++;
+ return true;
+ }
+
+ void newFrame() {
+ fHits = 0;
+ }
+
+ int hits() {
+ return fHits;
+ }
+
+ void before(const SkBitmap& bitmap) {
+ if (fCntExpectedTouched == 0) {
+ return;
+ }
+
+ for (int i = 0 ; i < fCntExpectedTouched; i++) {
+ fBeforeTouched[i] = pickColor(bitmap, fExpectedTouched[i].x(), fExpectedTouched[i].y());
+ }
+ for (int i = 0 ; i < fCntExpectedUntouched; i++) {
+ fBeforeUntouched[i] = pickColor(bitmap, fExpectedUntouched[i].x(), fExpectedUntouched[i].y());
+ }
+ }
+
+ // any/all of the expected touched has to be changed, and all expected untouched must be intact
+ void after(const SkBitmap& bitmap) {
+ if (fCntExpectedTouched == 0) {
+ return;
+ }
+
+ bool doBreak;
+ if (fBreakOnAny) {
+ doBreak = false;
+ for (int i = 0 ; i < fCntExpectedTouched; i++) {
+ doBreak = doBreak || fBeforeTouched[i] != pickColor(bitmap, fExpectedTouched[i].x(), fExpectedTouched[i].y());
+ }
+ } else {
+ doBreak = true;
+ for (int i = 0 ; i < fCntExpectedTouched; i++) {
+ doBreak = doBreak && fBeforeTouched[i] != pickColor(bitmap, fExpectedTouched[i].x(), fExpectedTouched[i].y());
+ }
+ }
+
+ for (int i = 0 ; i < fCntExpectedUntouched; i++) {
+ doBreak = doBreak && fBeforeUntouched[i] == pickColor(bitmap, fExpectedUntouched[i].x(), fExpectedUntouched[i].y());
+ }
+
+ if (doBreak) {
+ fHits++;
+ if (fEnabled) {
+ breakExecution();
+ }
+ }
+ }
+
+private:
+ inline SkColor pickColor(const SkBitmap& bitmap, int x, int y) {
+ return bitmap.getColor(x, y);
+ }
+
+ void breakExecution() {
+ printf("break;\n");
+ }
+
+ inline bool found(int x, int y) {
+ for (int i = 0 ; i < fCntExpectedTouched; i++) {
+ if (x == fExpectedTouched[i].x() && y == fExpectedTouched[i].y()) {
+ return true;
+ }
+ }
+ for (int i = 0 ; i < fCntExpectedUntouched; i++) {
+ if (x == fExpectedUntouched[i].x() && y == fExpectedUntouched[i].y()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ bool fEnabled;
+ // break on any change on expected touched or all.
+ bool fBreakOnAny;
+ SkIPoint fExpectedTouched[MAX_TRACKING_POINTS];
+ SkColor fBeforeTouched[MAX_TRACKING_POINTS];
+ int fCntExpectedTouched;
+
+ SkIPoint fExpectedUntouched[MAX_TRACKING_POINTS];
+ SkColor fBeforeUntouched[MAX_TRACKING_POINTS];
+ int fCntExpectedUntouched;
+
+ int fHits;
+};
+
+#endif // EXPERIMENTAL_PDFVIEWER_SKTRACKER_H_
#include "SkTypeface.h"
#include "SkTArray.h"
#include "picture_utils.h"
+#include "SkNulCanvas.h"
#include "SkPdfRenderer.h"
DEFINE_int32(benchLoad, 0, "Load the pdf file minimally N times, without any rendering and \n"
"\tminimal parsing to ensure correctness. Default 0 (disabled).");
DEFINE_int32(benchRender, 0, "Render the pdf content N times. Default 0 (disabled)");
+DEFINE_string2(config, c, "8888", "Canvas to render:\n"
+ "\t8888 - all pages\n"
+ "\tnul - all pages, in reverse order\n"
+ );
// TODO(edisonn): add config for device target(gpu, raster, pdf), + ability not to render at all
int page) {
SkRect rect = renderer.MediaBox(page < 0 ? 0 :page);
- SkBitmap bitmap;
- SkScalar width = SkScalarMul(rect.width(), SkDoubleToScalar(sqrt(FLAGS_DPI / 72.0)));
- SkScalar height = SkScalarMul(rect.height(), SkDoubleToScalar(sqrt(FLAGS_DPI / 72.0)));
+ // Exercise all pdf codepaths as in normal rendering, but no actual bits are changed.
+ if (!FLAGS_config.isEmpty() && strcmp(FLAGS_config[0], "nul") == 0) {
+ SkBitmap bitmap;
+ SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap)));
+ SkNulCanvas canvas(device);
+ renderer.renderPage(page < 0 ? 0 : page, &canvas, rect);
+ } else {
+ // 8888
+ SkRect rect = renderer.MediaBox(page < 0 ? 0 :page);
+
+ SkBitmap bitmap;
+ SkScalar width = SkScalarMul(rect.width(), SkDoubleToScalar(sqrt(FLAGS_DPI / 72.0)));
+ SkScalar height = SkScalarMul(rect.height(), SkDoubleToScalar(sqrt(FLAGS_DPI / 72.0)));
- rect = SkRect::MakeWH(width, height);
+ rect = SkRect::MakeWH(width, height);
#ifdef PDF_DEBUG_3X
- setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(width), 3 * (int)SkScalarToDouble(height));
+ setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(width), 3 * (int)SkScalarToDouble(height));
#else
- setup_bitmap(&bitmap, (int)SkScalarToDouble(width), (int)SkScalarToDouble(height));
+ setup_bitmap(&bitmap, (int)SkScalarToDouble(width), (int)SkScalarToDouble(height));
#endif
- SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap)));
- SkCanvas canvas(device);
+ SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap)));
+ SkCanvas canvas(device);
- gDumpBitmap = &bitmap;
+ gDumpBitmap = &bitmap;
- gDumpCanvas = &canvas;
- renderer.renderPage(page < 0 ? 0 : page, &canvas, rect);
+ gDumpCanvas = &canvas;
+ renderer.renderPage(page < 0 ? 0 : page, &canvas, rect);
- SkString outputPath;
- if (!make_output_filepath(&outputPath, outputDir, inputFilename, page)) {
- return false;
- }
- SkImageEncoder::EncodeFile(outputPath.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
+ SkString outputPath;
+ if (!make_output_filepath(&outputPath, outputDir, inputFilename, page)) {
+ return false;
+ }
+ SkImageEncoder::EncodeFile(outputPath.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
- if (FLAGS_showMemoryUsage) {
- SkDebugf("Memory usage after page %i rendered: %u\n", page < 0 ? 0 : page, (unsigned int)renderer.bytesUsed());
+ if (FLAGS_showMemoryUsage) {
+ SkDebugf("Memory usage after page %i rendered: %u\n", page < 0 ? 0 : page, (unsigned int)renderer.bytesUsed());
+ }
}
-
return true;
}
'../experimental/PdfViewer/SkPdfRenderer.cpp',
'../experimental/PdfViewer/SkPdfUtils.cpp',
#'../experimental/PdfViewer/SkPdfNYI.cpp',
+ '../experimental/PdfViewer/SkTrackDevice.cpp',
+ '../experimental/PdfViewer/SkTracker.cpp',
'../experimental/PdfViewer/pdfparser/native/SkPdfObject.cpp',
'../experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp',
'../experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp',