Add getReducedClipStack to lua canvas

R=reed@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/180283004

git-svn-id: http://skia.googlecode.com/svn/trunk@13594 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gyp/tools.gyp b/gyp/tools.gyp
index 049e393..18f97ca 100644
--- a/gyp/tools.gyp
+++ b/gyp/tools.gyp
@@ -189,6 +189,11 @@
         '../tools/lua/lua_app.cpp',
         '../src/utils/SkLua.cpp',
       ],
+      'include_dirs': [
+        # Lua exposes GrReduceClip which in turn requires src/core for SkTLList
+        '../src/gpu/',
+        '../src/core/',
+      ],
       'dependencies': [
         'effects.gyp:effects',
         'images.gyp:images',
@@ -207,6 +212,11 @@
         '../src/utils/SkLuaCanvas.cpp',
         '../src/utils/SkLua.cpp',
       ],
+      'include_dirs': [
+        # Lua exposes GrReduceClip which in turn requires src/core for SkTLList
+        '../src/gpu/',
+        '../src/core/',
+      ],
       'dependencies': [
         'effects.gyp:effects',
         'flags.gyp:flags',
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index e639212..e9d4933 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -90,12 +90,16 @@
     void flush();
 
     /**
-     *  DEPRECATED: call imageInfo() instead.
-     *  Return the width/height of the underlying device. The current drawable
-     *  area may be small (due to clipping or saveLayer). For a canvas with
-     *  no device, 0,0 will be returned.
+     * Gets the size of the base or root layer in global canvas coordinates. The
+     * origin of the base layer is always (0,0). The current drawable area may be
+     * smaller (due to clipping or saveLayer).
      */
-    SkISize getDeviceSize() const;
+    SkISize getBaseLayerSize() const;
+
+    /**
+     *  DEPRECATED: call getBaseLayerSize
+     */
+    SkISize getDeviceSize() const { return this->getBaseLayerSize(); }
 
     /**
      *  DEPRECATED.
@@ -1129,6 +1133,7 @@
 
     friend class SkDrawIter;    // needs setupDrawForLayerDevice()
     friend class AutoDrawLooper;
+    friend class SkLua;         // needs top layer size and offset
 
     SkBaseDevice* createLayerDevice(const SkImageInfo&);
 
@@ -1143,6 +1148,12 @@
      */
     SkBaseDevice* setRootDevice(SkBaseDevice* device);
 
+    /**
+     * Gets the size/origin of the top level layer in global canvas coordinates. We don't want this
+     * to be public because it exposes decisions about layer sizes that are internal to the canvas.
+     */
+    SkISize getTopLayerSize() const;
+    SkIPoint getTopLayerOrigin() const;
 
     // internal methods are not virtual, so they can safely be called by other
     // canvas apis, without confusing subclasses (like SkPictureRecording)
diff --git a/include/utils/SkLua.h b/include/utils/SkLua.h
index f67502a..2f29343 100644
--- a/include/utils/SkLua.h
+++ b/include/utils/SkLua.h
@@ -8,6 +8,7 @@
 #ifndef SkLua_DEFINED
 #define SkLua_DEFINED
 
+#include "SkClipStack.h"
 #include "SkColor.h"
 #include "SkScalar.h"
 #include "SkString.h"
@@ -15,7 +16,6 @@
 struct lua_State;
 
 class SkCanvas;
-class SkClipStack;
 class SkMatrix;
 class SkPaint;
 class SkPath;
@@ -55,6 +55,10 @@
     void pushPath(const SkPath&, const char tableKey[] = NULL);
     void pushCanvas(SkCanvas*, const char tableKey[] = NULL);
     void pushClipStack(const SkClipStack&, const char tableKey[] = NULL);
+    void pushClipStackElement(const SkClipStack::Element& element, const char tableKey[] = NULL);
+
+    // This SkCanvas lua methods is declared here to benefit from SkLua's friendship with SkCanvas.
+    static int lcanvas_getReducedClipStack(lua_State* L);
 
 private:
     lua_State*  fL;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 8159adf..5ba6e8f 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -583,7 +583,17 @@
     }
 }
 
-SkISize SkCanvas::getDeviceSize() const {
+SkISize SkCanvas::getTopLayerSize() const {
+    SkBaseDevice* d = this->getTopDevice();
+    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
+}
+
+SkIPoint SkCanvas::getTopLayerOrigin() const {
+    SkBaseDevice* d = this->getTopDevice();
+    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
+}
+
+SkISize SkCanvas::getBaseLayerSize() const {
     SkBaseDevice* d = this->getDevice();
     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
 }
diff --git a/src/core/SkTLList.h b/src/core/SkTLList.h
index 99b5bc6..aeae3f7 100644
--- a/src/core/SkTLList.h
+++ b/src/core/SkTLList.h
@@ -198,11 +198,11 @@
 
         Iter() {}
 
-        Iter(const SkTLList& list, IterStart start) {
+        Iter(const SkTLList& list, IterStart start = kHead_IterStart) {
             INHERITED::init(list.fList, start);
         }
 
-        T* init(const SkTLList& list, IterStart start) {
+        T* init(const SkTLList& list, IterStart start = kHead_IterStart) {
             return this->nodeToObj(INHERITED::init(list.fList, start));
         }
 
diff --git a/src/utils/SkLua.cpp b/src/utils/SkLua.cpp
index ec276db..282e4ef 100644
--- a/src/utils/SkLua.cpp
+++ b/src/utils/SkLua.cpp
@@ -6,8 +6,9 @@
  */
 
 #include "SkLua.h"
+
+#include "GrReducedClip.h"
 #include "SkCanvas.h"
-#include "SkClipStack.h"
 #include "SkData.h"
 #include "SkDocument.h"
 #include "SkImage.h"
@@ -273,29 +274,35 @@
     const SkClipStack::Element* element;
     int i = 0;
     while (NULL != (element = iter.next())) {
-        lua_newtable(fL);
-        SkClipStack::Element::Type type = element->getType();
-        this->pushString(element_type(type), "type");
-        switch (type) {
-            case SkClipStack::Element::kEmpty_Type:
-                break;
-            case SkClipStack::Element::kRect_Type:
-                this->pushRect(element->getRect(), "rect");
-                break;
-            case SkClipStack::Element::kRRect_Type:
-                this->pushRRect(element->getRRect(), "rrect");
-                break;
-            case SkClipStack::Element::kPath_Type:
-                this->pushPath(element->getPath(), "path");
-                break;
-        }
-        this->pushString(region_op(element->getOp()), "op");
-        this->pushBool(element->isAA(), "aa");
+        this->pushClipStackElement(*element);
         lua_rawseti(fL, -2, ++i);
     }
     CHECK_SETFIELD(key);
 }
 
+void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) {
+    lua_newtable(fL);
+    SkClipStack::Element::Type type = element.getType();
+    this->pushString(element_type(type), "type");
+    switch (type) {
+        case SkClipStack::Element::kEmpty_Type:
+            break;
+        case SkClipStack::Element::kRect_Type:
+            this->pushRect(element.getRect(), "rect");
+            break;
+        case SkClipStack::Element::kRRect_Type:
+            this->pushRRect(element.getRRect(), "rrect");
+            break;
+        case SkClipStack::Element::kPath_Type:
+            this->pushPath(element.getPath(), "path");
+            break;
+    }
+    this->pushString(region_op(element.getOp()), "op");
+    this->pushBool(element.isAA(), "aa");
+    CHECK_SETFIELD(key);
+}
+
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -444,6 +451,41 @@
     return 1;
 }
 
+int SkLua::lcanvas_getReducedClipStack(lua_State* L) {
+    const SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
+    SkISize layerSize = canvas->getTopLayerSize();
+    SkIPoint layerOrigin = canvas->getTopLayerOrigin();
+    SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY,
+                                            layerSize.fWidth, layerSize.fHeight);
+
+    GrReducedClip::ElementList elements;
+    GrReducedClip::InitialState initialState;
+    int32_t genID;
+    SkIRect resultBounds;
+
+    const SkClipStack& stack = *canvas->getClipStack();
+
+    GrReducedClip::ReduceClipStack(stack,
+                                   queryBounds,
+                                   &elements,
+                                   &genID,
+                                   &initialState,
+                                   &resultBounds,
+                                   NULL);
+
+    GrReducedClip::ElementList::Iter iter(elements);
+    int i = 0;
+    lua_newtable(L);
+    while(NULL != iter.get()) {
+        SkLua(L).pushClipStackElement(*iter.get());
+        iter.next();
+        lua_rawseti(L, -2, ++i);
+    }
+    // Currently this only returns the element list to lua, not the initial state or result bounds.
+    // It could return these as additional items on the lua stack.
+    return 1;
+}
+
 static int lcanvas_save(lua_State* L) {
     lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
     return 1;
@@ -479,7 +521,7 @@
     return 0;
 }
 
-static const struct luaL_Reg gSkCanvas_Methods[] = {
+const struct luaL_Reg gSkCanvas_Methods[] = {
     { "drawColor", lcanvas_drawColor },
     { "drawRect", lcanvas_drawRect },
     { "drawOval", lcanvas_drawOval },
@@ -490,6 +532,7 @@
     { "getSaveCount", lcanvas_getSaveCount },
     { "getTotalMatrix", lcanvas_getTotalMatrix },
     { "getClipStack", lcanvas_getClipStack },
+    { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
     { "save", lcanvas_save },
     { "restore", lcanvas_restore },
     { "scale", lcanvas_scale },
diff --git a/tools/lua/dump_clipstack_at_restore.lua b/tools/lua/dump_clipstack_at_restore.lua
index 4691b5b..eb5afb9 100644
--- a/tools/lua/dump_clipstack_at_restore.lua
+++ b/tools/lua/dump_clipstack_at_restore.lua
@@ -11,7 +11,8 @@
 function sk_scrape_accumulate(t)
     if (t.verb == "restore") then
         restoreCount = restoreCount + 1;
-        io.write("Clip Stack at restore #", restoreCount, ":\n")
+        -- io.write("Clip Stack at restore #", restoreCount, ":\n")
+        io.write("Reduced Clip Stack at restore #", restoreCount, ":\n")
         for i = 1, #clipstack do
             local element = clipstack[i];
             io.write("\t", element["op"], ", ", element["type"], ", aa:", tostring(element["aa"]))
@@ -24,7 +25,8 @@
         end
         io.write("\n")
     else
-        clipstack = canvas:getClipStack()
+        -- clipstack = canvas:getClipStack()
+        clipstack = canvas:getReducedClipStack()
     end
 end