Optimization: SkDebugCanvas is capable of pausing and drawing incrementally instead...
authorchudy@google.com <chudy@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 1 Aug 2012 15:57:52 +0000 (15:57 +0000)
committerchudy@google.com <chudy@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 1 Aug 2012 15:57:52 +0000 (15:57 +0000)
Review URL: https://codereview.appspot.com/6458056

git-svn-id: http://skia.googlecode.com/svn/trunk@4891 2bbb7eff-a529-9590-31e7-b0007b416f81

debugger/QT/SkCanvasWidget.cpp
debugger/QT/SkCanvasWidget.h
debugger/QT/SkGLWidget.cpp
debugger/QT/SkRasterWidget.cpp
debugger/QT/SkRasterWidget.h
debugger/SkDebugCanvas.cpp
debugger/SkDebugCanvas.h

index 1056bbb..2ff21b0 100644 (file)
@@ -25,8 +25,8 @@ SkCanvasWidget::SkCanvasWidget() : QWidget()
 
     fIndex = 0;
     fPreviousPoint.set(0,0);
-    fTransform.set(0,0);
-    fScaleFactor = 1.0;
+    fUserOffset.set(0,0);
+    fUserScaleFactor = 1.0;
 
     setWidgetVisibility(kGPU_WidgetType, true);
     this->setDisabled(true);
@@ -58,42 +58,37 @@ void SkCanvasWidget::loadPicture(QString filename) {
     fDebugCanvas = new SkDebugCanvas(picture->width(), picture->height());
 
     picture->draw(fDebugCanvas);
-    fIndex = fDebugCanvas->getSize();
+    fIndex = fDebugCanvas->getSize() - 1;
     fRasterWidget.setDebugCanvas(fDebugCanvas);
     fGLWidget.setDebugCanvas(fDebugCanvas);
-
-    // TODO(chudy): Remove bounds from debug canvas storage.
     fDebugCanvas->setBounds(this->width(), this->height());
 }
 
 void SkCanvasWidget::mouseMoveEvent(QMouseEvent* event) {
     SkIPoint eventPoint = SkIPoint::Make(event->globalX(), event->globalY());
-    fTransform += eventPoint - fPreviousPoint;
+    fUserOffset += eventPoint - fPreviousPoint;
     fPreviousPoint = eventPoint;
-    updateWidgetTransform(kTranslate);
+    fDebugCanvas->setUserOffset(fUserOffset);
     drawTo(fIndex);
 }
 
 void SkCanvasWidget::mousePressEvent(QMouseEvent* event) {
     fPreviousPoint.set(event->globalX(), event->globalY());
     emit hitChanged(fDebugCanvas->getCommandAtPoint(event->x(), event->y(),
-            fIndex, fTransform, fScaleFactor));
+            fIndex));
 }
 
 void SkCanvasWidget::mouseDoubleClickEvent(QMouseEvent* event) {
-    fTransform.set(0,0);
-    fScaleFactor = 1.0;
-    emit scaleFactorChanged(fScaleFactor);
-    // TODO(chudy): Change to signal / slot mechanism.
     resetWidgetTransform();
-    drawTo(fIndex);
 }
 
 void SkCanvasWidget::resetWidgetTransform() {
-    fTransform.set(0,0);
-    fScaleFactor = 1.0;
-    updateWidgetTransform(kTranslate);
-    updateWidgetTransform(kScale);
+    fUserOffset.set(0,0);
+    fUserScaleFactor = 1.0;
+    fDebugCanvas->setUserOffset(fUserOffset);
+    fDebugCanvas->setUserScale(fUserScaleFactor);
+    emit scaleFactorChanged(fUserScaleFactor);
+    drawTo(fIndex);
 }
 
 void SkCanvasWidget::setWidgetVisibility(WidgetType type, bool isHidden) {
@@ -104,27 +99,17 @@ void SkCanvasWidget::setWidgetVisibility(WidgetType type, bool isHidden) {
     }
 }
 
-void SkCanvasWidget::updateWidgetTransform(TransformType type) {
-    if (type == kTranslate) {
-        fRasterWidget.setTranslate(fTransform);
-        fGLWidget.setTranslate(fTransform);
-    } else if (type == kScale) {
-        fRasterWidget.setScale(fScaleFactor);
-        fGLWidget.setScale(fScaleFactor);
-    }
-}
-
 void SkCanvasWidget::zoom(float zoomIncrement) {
-    fScaleFactor += zoomIncrement;
+    fUserScaleFactor += zoomIncrement;
 
-    /* The range of the fScaleFactor crosses over the range -1,0,1 frequently.
+    /* The range of the fUserScaleFactor crosses over the range -1,0,1 frequently.
     * Based on the code below, -1 and 1 both scale the image to it's original
     * size we do the following to never have a registered wheel scroll
-    * not effect the fScaleFactor. */
-    if (fScaleFactor == 0) {
-        fScaleFactor = 2 * zoomIncrement;
+    * not effect the fUserScaleFactor. */
+    if (fUserScaleFactor == 0) {
+        fUserScaleFactor = 2 * zoomIncrement;
     }
-    emit scaleFactorChanged(fScaleFactor);
-    updateWidgetTransform(kScale);
+    emit scaleFactorChanged(fUserScaleFactor);
+    fDebugCanvas->setUserScale(fUserScaleFactor);
     drawTo(fIndex);
 }
index 317a007..2c34240 100644 (file)
@@ -118,19 +118,12 @@ private:
     SkGLWidget fGLWidget;
     SkDebugCanvas* fDebugCanvas;
     SkIPoint fPreviousPoint;
-    SkIPoint fTransform;
-    float fScaleFactor;
+    SkIPoint fUserOffset;
+    float fUserScaleFactor;
     int fIndex;
 
-    enum TransformType {
-        kTranslate     = 1 << 0,
-        kScale                 = 1 << 1,
-    };
-
     void resetWidgetTransform();
 
-    void updateWidgetTransform(TransformType type);
-
     void mouseMoveEvent(QMouseEvent* event);
 
     void mousePressEvent(QMouseEvent* event);
index e3c4161..ff903ad 100644 (file)
@@ -18,12 +18,14 @@ SkGLWidget::SkGLWidget() : QGLWidget() {
     fCurIntf = NULL;
     fCurContext = NULL;
     fGpuDevice = NULL;
+    fCanvas = NULL;
 }
 
 SkGLWidget::~SkGLWidget() {
     SkSafeUnref(fCurIntf);
     SkSafeUnref(fCurContext);
     SkSafeUnref(fGpuDevice);
+    SkSafeUnref(fCanvas);
 }
 
 void SkGLWidget::initializeGL() {
@@ -31,6 +33,7 @@ void SkGLWidget::initializeGL() {
     fCurContext = GrContext::Create(kOpenGL_Shaders_GrEngine, (GrPlatform3DContext) fCurIntf);
     GrRenderTarget* curRenderTarget = fCurContext->createPlatformRenderTarget(getDesc(this->width(), this->height()));
     fGpuDevice = new SkGpuDevice(fCurContext, curRenderTarget);
+    fCanvas = new SkCanvas(fGpuDevice);
     curRenderTarget->unref();
 
     glClearColor(1, 1, 1, 0);
@@ -41,21 +44,17 @@ void SkGLWidget::initializeGL() {
 void SkGLWidget::resizeGL(int w, int h) {
     GrRenderTarget* curRenderTarget = fCurContext->createPlatformRenderTarget(getDesc(w,h));
     SkSafeUnref(fGpuDevice);
+    SkSafeUnref(fCanvas);
     fGpuDevice = new SkGpuDevice(fCurContext, curRenderTarget);
+    fCanvas = new SkCanvas(fGpuDevice);
     drawTo(fIndex);
 }
 
 void SkGLWidget::paintGL() {
     glClearColor(1, 1, 1, 0);
-    SkCanvas canvas(fGpuDevice);
-    canvas.translate(fTransform.fX, fTransform.fY);
-    if(fScaleFactor < 0) {
-        canvas.scale((1.0 / -fScaleFactor),(1.0 / -fScaleFactor));
-    } else if (fScaleFactor > 0) {
-        canvas.scale(fScaleFactor, fScaleFactor);
-    }
-    fDebugCanvas->drawTo(&canvas, fIndex);
-    canvas.flush();
+    fDebugCanvas->drawTo(fCanvas, fIndex);
+    // TODO(chudy): Implement an optional flush button in Gui.
+    fCanvas->flush();
 }
 
 GrPlatformRenderTargetDesc SkGLWidget::getDesc(int w, int h) {
index 2cf1f34..33728d0 100644 (file)
@@ -9,44 +9,40 @@
 
 #include "SkRasterWidget.h"
 
-SkRasterWidget::SkRasterWidget(QWidget* parent) : QWidget(parent) {
+SkRasterWidget::SkRasterWidget() : QWidget() {
     fBitmap.setConfig(SkBitmap::kARGB_8888_Config, 800, 800);
     fBitmap.allocPixels();
     fBitmap.eraseColor(0);
     fTransform.set(0,0);
     fScaleFactor = 1.0;
     fIndex = 0;
-    fDevice = NULL;
+    fDevice = new SkDevice(fBitmap);
     fDebugCanvas = NULL;
+    fCanvas = new SkCanvas(fDevice);
     this->setStyleSheet("QWidget {background-color: white; border: 1px solid #cccccc;}");
 }
 
 SkRasterWidget::~SkRasterWidget() {
-    delete fDevice;
+    SkSafeUnref(fCanvas);
+    SkSafeUnref(fDevice);
 }
 
 void SkRasterWidget::resizeEvent(QResizeEvent* event) {
     fBitmap.setConfig(SkBitmap::kARGB_8888_Config, event->size().width(), event->size().height());
     fBitmap.allocPixels();
-    delete fDevice;
+    SkSafeUnref(fCanvas);
+    SkSafeUnref(fDevice);
     fDevice = new SkDevice(fBitmap);
+    fCanvas = new SkCanvas(fDevice);
     this->update();
 }
 
 void SkRasterWidget::paintEvent(QPaintEvent* event) {
     if (fDebugCanvas) {
-        fBitmap.eraseColor(0);
-        SkCanvas canvas(fDevice);
-        canvas.translate(fTransform.fX, fTransform.fY);
-        if (fScaleFactor < 0) {
-            canvas.scale((1.0 / -fScaleFactor), (1.0 / -fScaleFactor));
-        } else if (fScaleFactor > 0) {
-            canvas.scale(fScaleFactor, fScaleFactor);
-        }
-
-        fMatrix = canvas.getTotalMatrix();
-        fClip = canvas.getTotalClip().getBounds();
-        fDebugCanvas->drawTo(&canvas, fIndex);
+        fDebugCanvas->drawTo(fCanvas, fIndex);
+        // TODO(chudy): Refactor into SkDebugCanvas.
+        fMatrix = fCanvas->getTotalMatrix();
+        fClip = fCanvas->getTotalClip().getBounds();
 
         QPainter painter(this);
         QStyleOption opt;
index 1692800..3fca4f3 100644 (file)
@@ -20,7 +20,7 @@
 class  SkRasterWidget : public QWidget {
 
 public:
-    SkRasterWidget(QWidget* parent = NULL);
+    SkRasterWidget();
 
     ~SkRasterWidget();
 
@@ -67,6 +67,7 @@ protected:
 private:
     SkBitmap fBitmap;
     SkDebugCanvas* fDebugCanvas;
+    SkCanvas* fCanvas;
     SkDevice* fDevice;
 
     SkMatrix fMatrix;
index 5fe1503..6070867 100644 (file)
@@ -18,6 +18,9 @@ SkDebugCanvas::SkDebugCanvas(int width, int height) {
     fBm.setConfig(SkBitmap::kNo_Config, fWidth, fHeight);
     this->setBitmapDevice(fBm);
     fFilter = false;
+    fIndex = 0;
+    fUserOffset.set(0,0);
+    fUserScale = 1.0;
 }
 
 SkDebugCanvas::~SkDebugCanvas() {}
@@ -34,21 +37,26 @@ void SkDebugCanvas::draw(SkCanvas* canvas) {
             }
         }
     }
+    fIndex = commandVector.size() - 1;
 }
 
-int SkDebugCanvas::getCommandAtPoint(int x, int y, int index,
-        SkIPoint transform, float scale) {
+void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
+    canvas->translate(fUserOffset.fX, fUserOffset.fY);
+    if (fUserScale < 0) {
+        canvas->scale((1.0 / -fUserScale), (1.0 / -fUserScale));
+    } else if (fUserScale > 0) {
+        canvas->scale(fUserScale, fUserScale);
+    }
+}
+
+int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
     SkBitmap bitmap;
     bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
     bitmap.allocPixels();
 
     SkCanvas canvas(bitmap);
-    canvas.translate(transform.fX - x, transform.fY - y);
-    if (scale < 0) {
-        canvas.scale((1.0 / -scale), (1.0 / -scale));
-    } else if (scale > 0) {
-        canvas.scale(scale, scale);
-    }
+    canvas.translate(-x, -y);
+    applyUserTransform(&canvas);
 
     int layer = 0;
     SkColor prev = bitmap.getColor(0,0);
@@ -68,7 +76,21 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
     int counter = 0;
     SkASSERT(!commandVector.empty());
     SkASSERT(index < (int)commandVector.size());
-    for (int i = 0; i <= index; i++) {
+    int i;
+
+    // This only works assuming the canvas and device are the same ones that
+    // were previously drawn into because they need to preserve all saves
+    // and restores.
+    if (fIndex < index) {
+        i = fIndex + 1;
+    } else {
+        i = 0;
+        canvas->clear(0);
+        canvas->resetMatrix();
+        applyUserTransform(canvas);
+    }
+
+    for (; i <= index; i++) {
         if (i == index && fFilter) {
             SkPaint p;
             p.setColor(0xAAFFFFFF);
@@ -87,6 +109,8 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
             commandVector[i]->execute(canvas);
         }
     }
+
+    fIndex = index;
 }
 
 SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) {
index c13ea10..c51e40f 100644 (file)
@@ -47,8 +47,7 @@ public:
     /**
         Returns the index of the last draw command to write to the pixel at (x,y)
      */
-    int getCommandAtPoint(int x, int y, int index,
-            SkIPoint transform, float scale);
+    int getCommandAtPoint(int x, int y, int index);
 
     /**
         Returns the draw command at the given index.
@@ -96,6 +95,14 @@ public:
         fHeight = height;
     }
 
+    void setUserOffset(SkIPoint offset) {
+        fUserOffset = offset;
+    }
+
+    void setUserScale(float scale) {
+        fUserScale = scale;
+    }
+
 ////////////////////////////////////////////////////////////////////////////////
 // Inherited from SkCanvas
 ////////////////////////////////////////////////////////////////////////////////
@@ -181,12 +188,21 @@ private:
     int fWidth;
     SkBitmap fBm;
     bool fFilter;
+    int fIndex;
+    SkIPoint fUserOffset;
+    float fUserScale;
 
     /**
         Adds the command to the classes vector of commands.
         @param command  The draw command for execution
      */
     void addDrawCommand(SkDrawCommand* command);
+
+    /**
+        Applies any panning and zooming the user has specified before
+        drawing anything else into the canvas.
+     */
+    void applyUserTransform(SkCanvas* canvas);
 };
 
 #endif