#include "SkColorPriv.h"
#include "SkGraphics.h"
#include "SkImageEncoder.h"
+#include "SkNWayCanvas.h"
+#include "SkPicture.h"
#include "SkString.h"
#include "SkTime.h"
#include "SkBenchmark.h"
+static void erase(SkBitmap& bm) {
+ if (bm.config() == SkBitmap::kA8_Config) {
+ bm.eraseColor(0);
+ } else {
+ bm.eraseColor(SK_ColorWHITE);
+ }
+}
+
+static bool equal(const SkBitmap& bm1, const SkBitmap& bm2) {
+ if (bm1.width() != bm2.width() ||
+ bm1.height() != bm2.height() ||
+ bm1.config() != bm2.config()) {
+ return false;
+ }
+
+ size_t pixelBytes = bm1.width() * bm1.bytesPerPixel();
+ for (int y = 0; y < bm1.height(); y++) {
+ if (memcmp(bm1.getAddr(0, y), bm2.getAddr(0, y), pixelBytes)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
class Iter {
public:
Iter() {
canvas->translate(-x, -y);
}
+static void compare_pict_to_bitmap(SkPicture* pict, const SkBitmap& bm) {
+ SkBitmap bm2;
+
+ bm2.setConfig(bm.config(), bm.width(), bm.height());
+ bm2.allocPixels();
+ erase(bm2);
+
+ SkCanvas canvas(bm2);
+ canvas.drawPicture(*pict);
+
+ if (!equal(bm, bm2)) {
+ SkDebugf("----- compare_pict_to_bitmap failed\n");
+ }
+}
+
static const struct {
SkBitmap::Config fConfig;
const char* fName;
bool forceAA = true;
bool doRotate = false;
bool doClip = false;
+ bool doPict = false;
SkString outDir;
SkBitmap::Config outConfig = SkBitmap::kARGB_8888_Config;
outDir.append("/");
}
}
+ } else if (strcmp(*argv, "-pict") == 0) {
+ doPict = true;
} else if (strcmp(*argv, "-repeat") == 0) {
argv++;
if (argv < stop) {
SkBitmap bm;
bm.setConfig(outConfig, dim.fX, dim.fY);
bm.allocPixels();
-
- if (bm.config() == SkBitmap::kA8_Config) {
- bm.eraseColor(0);
- } else {
- bm.eraseColor(SK_ColorWHITE);
- }
+ erase(bm);
SkCanvas canvas(bm);
SkMSec now = SkTime::GetMSecs();
for (int i = 0; i < repeatDraw; i++) {
- SkAutoCanvasRestore acr(&canvas, true);
- bench->draw(&canvas);
+ SkCanvas* c = &canvas;
+
+ SkNWayCanvas nway;
+ SkPicture* pict = NULL;
+ if (doPict) {
+ pict = new SkPicture;
+ nway.addCanvas(pict->beginRecording(bm.width(), bm.height()));
+ nway.addCanvas(&canvas);
+ c = &nway;
+ }
+
+ SkAutoCanvasRestore acr(c, true);
+ bench->draw(c);
+
+ if (pict) {
+ compare_pict_to_bitmap(pict, bm);
+ pict->unref();
+ }
}
if (repeatDraw > 1) {
printf(" %4s:%7.2f", configName,
--- /dev/null
+
+#ifndef SkNWayCanvas_DEFINED
+#define SkNWayCanvas_DEFINED
+
+#include "SkCanvas.h"
+
+class SkNWayCanvas : public SkCanvas {
+public:
+ SkNWayCanvas();
+ virtual ~SkNWayCanvas();
+
+ void addCanvas(SkCanvas*);
+ void removeCanvas(SkCanvas*);
+ void removeAll();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // These are forwarded to the N canvases we're referencing
+
+ virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
+ virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags = kARGB_ClipLayer_SaveFlag);
+ virtual void restore();
+ virtual bool translate(SkScalar dx, SkScalar dy);
+ virtual bool scale(SkScalar sx, SkScalar sy);
+ virtual bool rotate(SkScalar degrees);
+ virtual bool skew(SkScalar sx, SkScalar sy);
+ virtual bool concat(const SkMatrix& matrix);
+ virtual void setMatrix(const SkMatrix& matrix);
+ virtual bool clipRect(const SkRect& rect,
+ SkRegion::Op op = SkRegion::kIntersect_Op);
+ virtual bool clipPath(const SkPath& path,
+ SkRegion::Op op = SkRegion::kIntersect_Op);
+ virtual bool clipRegion(const SkRegion& deviceRgn,
+ SkRegion::Op op = SkRegion::kIntersect_Op);
+
+ 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 drawPath(const SkPath& path, const SkPaint& paint);
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint* paint = NULL);
+ virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, const SkPaint* paint = NULL);
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ 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 SkBounder* setBounder(SkBounder* bounder);
+ virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
+
+private:
+ SkTDArray<SkCanvas*> fList;
+
+ class Iter;
+
+ typedef SkCanvas INHERITED;
+};
+
+
+#endif
+
--- /dev/null
+#include "SkNWayCanvas.h"
+
+SkNWayCanvas::SkNWayCanvas() {}
+
+SkNWayCanvas::~SkNWayCanvas() {
+ this->removeAll();
+}
+
+void SkNWayCanvas::addCanvas(SkCanvas* canvas) {
+ if (canvas) {
+ canvas->ref();
+ *fList.append() = canvas;
+ }
+}
+
+void SkNWayCanvas::removeCanvas(SkCanvas* canvas) {
+ int index = fList.find(canvas);
+ if (index >= 0) {
+ canvas->unref();
+ fList.removeShuffle(index);
+ }
+}
+
+void SkNWayCanvas::removeAll() {
+ fList.unrefAll();
+ fList.reset();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// These are forwarded to the N canvases we're referencing
+
+class SkNWayCanvas::Iter {
+public:
+ Iter(const SkTDArray<SkCanvas*>& list) : fList(list) {
+ fIndex = 0;
+ }
+ bool next() {
+ if (fIndex < fList.count()) {
+ fCanvas = fList[fIndex++];
+ return true;
+ }
+ return false;
+ }
+ SkCanvas* operator->() { return fCanvas; }
+
+private:
+ const SkTDArray<SkCanvas*>& fList;
+ int fIndex;
+ SkCanvas* fCanvas;
+};
+
+int SkNWayCanvas::save(SaveFlags flags) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->save(flags);
+ }
+ return this->INHERITED::save(flags);
+}
+
+int SkNWayCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->saveLayer(bounds, paint, flags);
+ }
+ return this->INHERITED::saveLayer(bounds, paint, flags);
+}
+
+void SkNWayCanvas::restore() {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->restore();
+ }
+ this->INHERITED::restore();
+}
+
+bool SkNWayCanvas::translate(SkScalar dx, SkScalar dy) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->translate(dx, dy);
+ }
+ return this->INHERITED::translate(dx, dy);
+}
+
+bool SkNWayCanvas::scale(SkScalar sx, SkScalar sy) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->scale(sx, sy);
+ }
+ return this->INHERITED::scale(sx, sy);
+}
+
+bool SkNWayCanvas::rotate(SkScalar degrees) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->rotate(degrees);
+ }
+ return this->INHERITED::rotate(degrees);
+}
+
+bool SkNWayCanvas::skew(SkScalar sx, SkScalar sy) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->skew(sx, sy);
+ }
+ return this->INHERITED::skew(sx, sy);
+}
+
+bool SkNWayCanvas::concat(const SkMatrix& matrix) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->concat(matrix);
+ }
+ return this->INHERITED::concat(matrix);
+}
+
+void SkNWayCanvas::setMatrix(const SkMatrix& matrix) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->setMatrix(matrix);
+ }
+ this->INHERITED::setMatrix(matrix);
+}
+
+bool SkNWayCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->clipRect(rect, op);
+ }
+ return this->INHERITED::clipRect(rect, op);
+}
+
+bool SkNWayCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->clipPath(path, op);
+ }
+ return this->INHERITED::clipPath(path, op);
+}
+
+bool SkNWayCanvas::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->clipRegion(deviceRgn, op);
+ }
+ return this->INHERITED::clipRegion(deviceRgn, op);
+}
+
+void SkNWayCanvas::drawPaint(const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawPaint(paint);
+ }
+}
+
+void SkNWayCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawPoints(mode, count, pts, paint);
+ }
+}
+
+void SkNWayCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawRect(rect, paint);
+ }
+}
+
+void SkNWayCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawPath(path, paint);
+ }
+}
+
+void SkNWayCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawBitmap(bitmap, x, y, paint);
+ }
+}
+
+void SkNWayCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, const SkPaint* paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawBitmapRect(bitmap, src, dst, paint);
+ }
+}
+
+void SkNWayCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawBitmapMatrix(bitmap, m, paint);
+ }
+}
+
+void SkNWayCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
+ const SkPaint* paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawSprite(bitmap, x, y, paint);
+ }
+}
+
+void SkNWayCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawText(text, byteLength, x, y, paint);
+ }
+}
+
+void SkNWayCanvas::drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawPosText(text, byteLength, pos, paint);
+ }
+}
+
+void SkNWayCanvas::drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawPosTextH(text, byteLength, xpos, constY, paint);
+ }
+}
+
+void SkNWayCanvas::drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawTextOnPath(text, byteLength, path, matrix, paint);
+ }
+}
+
+void SkNWayCanvas::drawPicture(SkPicture& picture) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawPicture(picture);
+ }
+}
+
+void SkNWayCanvas::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) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
+ indices, indexCount, paint);
+ }
+}
+
+SkBounder* SkNWayCanvas::setBounder(SkBounder* bounder) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->setBounder(bounder);
+ }
+ return this->INHERITED::setBounder(bounder);
+}
+
+SkDrawFilter* SkNWayCanvas::setDrawFilter(SkDrawFilter* filter) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->setDrawFilter(filter);
+ }
+ return this->INHERITED::setDrawFilter(filter);
+}
+
+