Simplify drawloopers and drawfilters. This allows the canvas to keep its
promise that const SkPaint& stay const (so we don't have bugs if a const paint
is referenced from two threads in pictures)



git-svn-id: http://skia.googlecode.com/svn/trunk@1074 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index a0e7e6e..1926d89 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -280,65 +280,65 @@
 
 class AutoDrawLooper {
 public:
-    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t)
-            : fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) {
-        if ((fLooper = paint.getLooper()) != NULL) {
-            fLooper->init(canvas, (SkPaint*)&paint);
-        } else {
-            fOnce = true;
-        }
+    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint) : fOrigPaint(paint) {
+        fCanvas = canvas;
+        fLooper = paint.getLooper();
         fFilter = canvas->getDrawFilter();
-        fNeedFilterRestore = false;
-    }
+        fPaint = NULL;
+        fSaveCount = canvas->getSaveCount();
+        fDone = false;
 
+        if (fLooper) {
+            fLooper->init(canvas);
+        }
+    }
+    
     ~AutoDrawLooper() {
-        if (fNeedFilterRestore) {
-            SkASSERT(fFilter);
-            fFilter->restore(fCanvas, fPaint, fType);
-        }
-        if (NULL != fLooper) {
-            fLooper->restore();
-        }
+        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
     }
-
-    bool next() {
-        SkDrawFilter* filter = fFilter;
-
-        // if we drew earlier with a filter, then we need to restore first
-        if (fNeedFilterRestore) {
-            SkASSERT(filter);
-            filter->restore(fCanvas, fPaint, fType);
-            fNeedFilterRestore = false;
-        }
-
-        bool result;
-
-        if (NULL != fLooper) {
-            result = fLooper->next();
-        } else {
-            result = fOnce;
-            fOnce = false;
-        }
-
-        // if we're gonna draw, give the filter a chance to do its work
-        if (result && NULL != filter) {
-            fNeedFilterRestore = result = filter->filter(fCanvas, fPaint,
-                                                         fType);
-        }
-        return result;
+    
+    const SkPaint& paint() const {
+        SkASSERT(fPaint);
+        return *fPaint;
     }
-
+    
+    bool next(SkDrawFilter::Type drawType);
+    
 private:
-    SkDrawLooper*   fLooper;
-    SkDrawFilter*   fFilter;
-    SkCanvas*       fCanvas;
-    SkPaint*        fPaint;
-    SkDrawFilter::Type  fType;
-    bool            fOnce;
-    bool            fNeedFilterRestore;
-
+    SkTLazy<SkPaint>    fLazyPaint;
+    SkCanvas*           fCanvas;
+    const SkPaint&      fOrigPaint;
+    SkDrawLooper*       fLooper;
+    SkDrawFilter*       fFilter;
+    const SkPaint*      fPaint;
+    int                 fSaveCount;
+    bool                fDone;
 };
 
+bool AutoDrawLooper::next(SkDrawFilter::Type drawType) {
+    if (fDone) {
+        fPaint = NULL;
+        return false;
+    }
+    if (!fLooper && !fFilter) {
+        fDone = true;
+        fPaint = &fOrigPaint;
+        return true;
+    }
+
+    SkPaint* paint = fLazyPaint.set(fOrigPaint);
+    if (fLooper && !fLooper->next(fCanvas, paint)) {
+        fDone = true;
+        fPaint = NULL;
+        return false;
+    }
+    if (fFilter) {
+        fFilter->filter(paint, drawType);
+    }
+    fPaint = paint;
+    return true;
+}
+
 /*  Stack helper for managing a SkBounder. In the destructor, if we were
     given a bounder, we call its commit() method, signifying that we are
     done accumulating bounds for that draw.
@@ -380,14 +380,14 @@
 
 ////////// macros to place around the internal draw calls //////////////////
 
-#define ITER_BEGIN(paint, type)                                     \
+#define LOOPER_BEGIN(paint, type)                                   \
 /*    AutoValidator   validator(fMCRec->fTopLayer->fDevice); */     \
-    AutoDrawLooper  looper(this, paint, type);                      \
-    while (looper.next()) {                                         \
+    AutoDrawLooper  looper(this, paint);                            \
+    while (looper.next(type)) {                                     \
         SkAutoBounderCommit ac(fBounder);                           \
         SkDrawIter          iter(this);
 
-#define ITER_END    }
+#define LOOPER_END    }
 
 ////////////////////////////////////////////////////////////////////////////
 
@@ -853,12 +853,12 @@
         paint = &tmp;
     }
 
-    ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
+    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
     while (iter.next()) {
         iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(),
-                                 *paint);
+                                 looper.paint());
     }
-    ITER_END
+    LOOPER_END
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -1190,13 +1190,13 @@
 //////////////////////////////////////////////////////////////////////////////
 
 void SkCanvas::drawPaint(const SkPaint& paint) {
-    ITER_BEGIN(paint, SkDrawFilter::kPaint_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type)
 
     while (iter.next()) {
-        iter.fDevice->drawPaint(iter, paint);
+        iter.fDevice->drawPaint(iter, looper.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
@@ -1207,13 +1207,13 @@
 
     SkASSERT(pts != NULL);
 
-    ITER_BEGIN(paint, SkDrawFilter::kPoint_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type)
 
     while (iter.next()) {
-        iter.fDevice->drawPoints(iter, mode, count, pts, paint);
+        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
@@ -1225,13 +1225,13 @@
         }
     }
 
-    ITER_BEGIN(paint, SkDrawFilter::kRect_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type)
 
     while (iter.next()) {
-        iter.fDevice->drawRect(iter, r, paint);
+        iter.fDevice->drawRect(iter, r, looper.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
@@ -1244,13 +1244,13 @@
         }
     }
 
-    ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
 
     while (iter.next()) {
-        iter.fDevice->drawPath(iter, path, paint);
+        iter.fDevice->drawPath(iter, path, looper.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
@@ -1328,13 +1328,13 @@
                                 const SkMatrix& matrix, const SkPaint& paint) {
     SkDEBUGCODE(bitmap.validate();)
 
-    ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
 
     while (iter.next()) {
-        iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint);
+        iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
@@ -1350,13 +1350,13 @@
         paint = &tmp;
     }
 
-    ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
+    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
 
     while (iter.next()) {
         iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(),
-                                 *paint);
+                                 looper.paint());
     }
-    ITER_END
+    LOOPER_END
 }
 
 class SkDeviceFilteredPaint {
@@ -1382,54 +1382,54 @@
 
 void SkCanvas::drawText(const void* text, size_t byteLength,
                         SkScalar x, SkScalar y, const SkPaint& paint) {
-    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
 
     while (iter.next()) {
-        SkDeviceFilteredPaint dfp(iter.fDevice, paint);
+        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
         iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 void SkCanvas::drawPosText(const void* text, size_t byteLength,
                            const SkPoint pos[], const SkPaint& paint) {
-    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
 
     while (iter.next()) {
-        SkDeviceFilteredPaint dfp(iter.fDevice, paint);
+        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
         iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
                                   dfp.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
                             const SkScalar xpos[], SkScalar constY,
                             const SkPaint& paint) {
-    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
 
     while (iter.next()) {
-        SkDeviceFilteredPaint dfp(iter.fDevice, paint);
+        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
         iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
                                   dfp.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
                               const SkPath& path, const SkMatrix* matrix,
                               const SkPaint& paint) {
-    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
 
     while (iter.next()) {
         iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
-                                     matrix, paint);
+                                     matrix, looper.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 #ifdef ANDROID
@@ -1437,14 +1437,14 @@
                                  const SkPoint pos[], const SkPaint& paint,
                                  const SkPath& path, const SkMatrix* matrix) {
 
-    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
 
     while (iter.next()) {
         iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
-                                        paint, path, matrix);
+                                        looper.paint(), path, matrix);
     }
 
-    ITER_END
+    LOOPER_END
 }
 #endif
 
@@ -1453,14 +1453,15 @@
                             const SkColor colors[], SkXfermode* xmode,
                             const uint16_t indices[], int indexCount,
                             const SkPaint& paint) {
-    ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
+    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
 
     while (iter.next()) {
         iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
-                                   colors, xmode, indices, indexCount, paint);
+                                   colors, xmode, indices, indexCount,
+                                   looper.paint());
     }
 
-    ITER_END
+    LOOPER_END
 }
 
 void SkCanvas::drawData(const void* data, size_t length) {