Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkLua.h"
      9 
     10 #if SK_SUPPORT_GPU
     11 #include "GrReducedClip.h"
     12 #endif
     13 
     14 #include "SkBlurImageFilter.h"
     15 #include "SkCanvas.h"
     16 #include "SkColorFilter.h"
     17 #include "SkData.h"
     18 #include "SkDocument.h"
     19 #include "SkGradientShader.h"
     20 #include "SkImage.h"
     21 #include "SkMatrix.h"
     22 #include "SkPaint.h"
     23 #include "SkPath.h"
     24 #include "SkPictureRecorder.h"
     25 #include "SkPixelRef.h"
     26 #include "SkRRect.h"
     27 #include "SkString.h"
     28 #include "SkSurface.h"
     29 #include "SkTextBlob.h"
     30 #include "SkTypeface.h"
     31 #include "SkXfermode.h"
     32 
     33 extern "C" {
     34     #include "lua.h"
     35     #include "lualib.h"
     36     #include "lauxlib.h"
     37 }
     38 
     39 // return the metatable name for a given class
     40 template <typename T> const char* get_mtname();
     41 #define DEF_MTNAME(T)                           \
     42     template <> const char* get_mtname<T>() {   \
     43         return #T "_LuaMetaTableName";          \
     44     }
     45 
     46 DEF_MTNAME(SkCanvas)
     47 DEF_MTNAME(SkColorFilter)
     48 DEF_MTNAME(SkDocument)
     49 DEF_MTNAME(SkImage)
     50 DEF_MTNAME(SkImageFilter)
     51 DEF_MTNAME(SkMatrix)
     52 DEF_MTNAME(SkRRect)
     53 DEF_MTNAME(SkPath)
     54 DEF_MTNAME(SkPaint)
     55 DEF_MTNAME(SkPathEffect)
     56 DEF_MTNAME(SkPicture)
     57 DEF_MTNAME(SkPictureRecorder)
     58 DEF_MTNAME(SkShader)
     59 DEF_MTNAME(SkSurface)
     60 DEF_MTNAME(SkTextBlob)
     61 DEF_MTNAME(SkTypeface)
     62 DEF_MTNAME(SkXfermode)
     63 
     64 template <typename T> T* push_new(lua_State* L) {
     65     T* addr = (T*)lua_newuserdata(L, sizeof(T));
     66     new (addr) T;
     67     luaL_getmetatable(L, get_mtname<T>());
     68     lua_setmetatable(L, -2);
     69     return addr;
     70 }
     71 
     72 template <typename T> void push_obj(lua_State* L, const T& obj) {
     73     new (lua_newuserdata(L, sizeof(T))) T(obj);
     74     luaL_getmetatable(L, get_mtname<T>());
     75     lua_setmetatable(L, -2);
     76 }
     77 
     78 template <typename T> T* push_ref(lua_State* L, T* ref) {
     79     *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
     80     luaL_getmetatable(L, get_mtname<T>());
     81     lua_setmetatable(L, -2);
     82     return ref;
     83 }
     84 
     85 template <typename T> T* get_ref(lua_State* L, int index) {
     86     return *(T**)luaL_checkudata(L, index, get_mtname<T>());
     87 }
     88 
     89 template <typename T> T* get_obj(lua_State* L, int index) {
     90     return (T*)luaL_checkudata(L, index, get_mtname<T>());
     91 }
     92 
     93 static bool lua2bool(lua_State* L, int index) {
     94     return !!lua_toboolean(L, index);
     95 }
     96 
     97 ///////////////////////////////////////////////////////////////////////////////
     98 
     99 SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
    100     fL = luaL_newstate();
    101     luaL_openlibs(fL);
    102     SkLua::Load(fL);
    103 }
    104 
    105 SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
    106 
    107 SkLua::~SkLua() {
    108     if (fWeOwnL) {
    109         if (fTermCode.size() > 0) {
    110             lua_getglobal(fL, fTermCode.c_str());
    111             if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
    112                 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
    113             }
    114         }
    115         lua_close(fL);
    116     }
    117 }
    118 
    119 bool SkLua::runCode(const char code[]) {
    120     int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
    121     if (err) {
    122         SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
    123         return false;
    124     }
    125     return true;
    126 }
    127 
    128 bool SkLua::runCode(const void* code, size_t size) {
    129     SkString str((const char*)code, size);
    130     return this->runCode(str.c_str());
    131 }
    132 
    133 ///////////////////////////////////////////////////////////////////////////////
    134 
    135 #define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
    136 
    137 static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
    138     if (pred) {
    139         lua_pushboolean(L, true);
    140         lua_setfield(L, -2, key);
    141     }
    142 }
    143 
    144 static void setfield_string(lua_State* L, const char key[], const char value[]) {
    145     lua_pushstring(L, value);
    146     lua_setfield(L, -2, key);
    147 }
    148 
    149 static void setfield_number(lua_State* L, const char key[], double value) {
    150     lua_pushnumber(L, value);
    151     lua_setfield(L, -2, key);
    152 }
    153 
    154 static void setfield_boolean(lua_State* L, const char key[], bool value) {
    155     lua_pushboolean(L, value);
    156     lua_setfield(L, -2, key);
    157 }
    158 
    159 static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
    160     setfield_number(L, key, SkScalarToLua(value));
    161 }
    162 
    163 static void setfield_function(lua_State* L,
    164                               const char key[], lua_CFunction value) {
    165     lua_pushcfunction(L, value);
    166     lua_setfield(L, -2, key);
    167 }
    168 
    169 static int lua2int_def(lua_State* L, int index, int defaultValue) {
    170     if (lua_isnumber(L, index)) {
    171         return (int)lua_tonumber(L, index);
    172     } else {
    173         return defaultValue;
    174     }
    175 }
    176 
    177 static SkScalar lua2scalar(lua_State* L, int index) {
    178     SkASSERT(lua_isnumber(L, index));
    179     return SkLuaToScalar(lua_tonumber(L, index));
    180 }
    181 
    182 static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
    183     if (lua_isnumber(L, index)) {
    184         return SkLuaToScalar(lua_tonumber(L, index));
    185     } else {
    186         return defaultValue;
    187     }
    188 }
    189 
    190 static SkScalar getarray_scalar(lua_State* L, int stackIndex, int arrayIndex) {
    191     SkASSERT(lua_istable(L, stackIndex));
    192     lua_rawgeti(L, stackIndex, arrayIndex);
    193 
    194     SkScalar value = lua2scalar(L, -1);
    195     lua_pop(L, 1);
    196     return value;
    197 }
    198 
    199 static void getarray_scalars(lua_State* L, int stackIndex, SkScalar dst[], int count) {
    200     for (int i = 0; i < count; ++i) {
    201         dst[i] = getarray_scalar(L, stackIndex, i + 1);
    202     }
    203 }
    204 
    205 static void getarray_points(lua_State* L, int stackIndex, SkPoint pts[], int count) {
    206     getarray_scalars(L, stackIndex, &pts[0].fX, count * 2);
    207 }
    208 
    209 static void setarray_number(lua_State* L, int index, double value) {
    210     lua_pushnumber(L, value);
    211     lua_rawseti(L, -2, index);
    212 }
    213 
    214 static void setarray_scalar(lua_State* L, int index, SkScalar value) {
    215     setarray_number(L, index, SkScalarToLua(value));
    216 }
    217 
    218 void SkLua::pushBool(bool value, const char key[]) {
    219     lua_pushboolean(fL, value);
    220     CHECK_SETFIELD(key);
    221 }
    222 
    223 void SkLua::pushString(const char str[], const char key[]) {
    224     lua_pushstring(fL, str);
    225     CHECK_SETFIELD(key);
    226 }
    227 
    228 void SkLua::pushString(const char str[], size_t length, const char key[]) {
    229     // TODO: how to do this w/o making a copy?
    230     SkString s(str, length);
    231     lua_pushstring(fL, s.c_str());
    232     CHECK_SETFIELD(key);
    233 }
    234 
    235 void SkLua::pushString(const SkString& str, const char key[]) {
    236     lua_pushstring(fL, str.c_str());
    237     CHECK_SETFIELD(key);
    238 }
    239 
    240 void SkLua::pushColor(SkColor color, const char key[]) {
    241     lua_newtable(fL);
    242     setfield_number(fL, "a", SkColorGetA(color) / 255.0);
    243     setfield_number(fL, "r", SkColorGetR(color) / 255.0);
    244     setfield_number(fL, "g", SkColorGetG(color) / 255.0);
    245     setfield_number(fL, "b", SkColorGetB(color) / 255.0);
    246     CHECK_SETFIELD(key);
    247 }
    248 
    249 void SkLua::pushU32(uint32_t value, const char key[]) {
    250     lua_pushnumber(fL, (double)value);
    251     CHECK_SETFIELD(key);
    252 }
    253 
    254 void SkLua::pushScalar(SkScalar value, const char key[]) {
    255     lua_pushnumber(fL, SkScalarToLua(value));
    256     CHECK_SETFIELD(key);
    257 }
    258 
    259 void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
    260     lua_newtable(fL);
    261     for (int i = 0; i < count; ++i) {
    262         // make it base-1 to match lua convention
    263         setarray_number(fL, i + 1, (double)array[i]);
    264     }
    265     CHECK_SETFIELD(key);
    266 }
    267 
    268 void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
    269     lua_newtable(fL);
    270     for (int i = 0; i < count; ++i) {
    271         // make it base-1 to match lua convention
    272         lua_newtable(fL);
    273         this->pushScalar(array[i].fX, "x");
    274         this->pushScalar(array[i].fY, "y");
    275         lua_rawseti(fL, -2, i + 1);
    276     }
    277     CHECK_SETFIELD(key);
    278 }
    279 
    280 void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
    281     lua_newtable(fL);
    282     for (int i = 0; i < count; ++i) {
    283         // make it base-1 to match lua convention
    284         setarray_scalar(fL, i + 1, array[i]);
    285     }
    286     CHECK_SETFIELD(key);
    287 }
    288 
    289 void SkLua::pushRect(const SkRect& r, const char key[]) {
    290     lua_newtable(fL);
    291     setfield_scalar(fL, "left", r.fLeft);
    292     setfield_scalar(fL, "top", r.fTop);
    293     setfield_scalar(fL, "right", r.fRight);
    294     setfield_scalar(fL, "bottom", r.fBottom);
    295     CHECK_SETFIELD(key);
    296 }
    297 
    298 void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
    299     push_obj(fL, rr);
    300     CHECK_SETFIELD(key);
    301 }
    302 
    303 void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
    304     lua_newtable(fL);
    305     setfield_scalar(fL, "phase", info.fPhase);
    306     this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
    307     CHECK_SETFIELD(key);
    308 }
    309 
    310 
    311 void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
    312     push_obj(fL, matrix);
    313     CHECK_SETFIELD(key);
    314 }
    315 
    316 void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
    317     push_obj(fL, paint);
    318     CHECK_SETFIELD(key);
    319 }
    320 
    321 void SkLua::pushPath(const SkPath& path, const char key[]) {
    322     push_obj(fL, path);
    323     CHECK_SETFIELD(key);
    324 }
    325 
    326 void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
    327     push_ref(fL, canvas);
    328     CHECK_SETFIELD(key);
    329 }
    330 
    331 void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
    332     push_ref(fL, const_cast<SkTextBlob*>(blob));
    333     CHECK_SETFIELD(key);
    334 }
    335 
    336 static const char* element_type(SkClipStack::Element::Type type) {
    337     switch (type) {
    338         case SkClipStack::Element::kEmpty_Type:
    339             return "empty";
    340         case SkClipStack::Element::kRect_Type:
    341             return "rect";
    342         case SkClipStack::Element::kRRect_Type:
    343             return "rrect";
    344         case SkClipStack::Element::kPath_Type:
    345             return "path";
    346     }
    347     return "unknown";
    348 }
    349 
    350 static const char* region_op(SkRegion::Op op) {
    351     switch (op) {
    352         case SkRegion::kDifference_Op:
    353             return "difference";
    354         case SkRegion::kIntersect_Op:
    355             return "intersect";
    356         case SkRegion::kUnion_Op:
    357             return "union";
    358         case SkRegion::kXOR_Op:
    359             return "xor";
    360         case SkRegion::kReverseDifference_Op:
    361             return "reverse-difference";
    362         case SkRegion::kReplace_Op:
    363             return "replace";
    364     }
    365     return "unknown";
    366 }
    367 
    368 void SkLua::pushClipStack(const SkClipStack& stack, const char* key) {
    369     lua_newtable(fL);
    370     SkClipStack::B2TIter iter(stack);
    371     const SkClipStack::Element* element;
    372     int i = 0;
    373     while ((element = iter.next())) {
    374         this->pushClipStackElement(*element);
    375         lua_rawseti(fL, -2, ++i);
    376     }
    377     CHECK_SETFIELD(key);
    378 }
    379 
    380 void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) {
    381     lua_newtable(fL);
    382     SkClipStack::Element::Type type = element.getType();
    383     this->pushString(element_type(type), "type");
    384     switch (type) {
    385         case SkClipStack::Element::kEmpty_Type:
    386             break;
    387         case SkClipStack::Element::kRect_Type:
    388             this->pushRect(element.getRect(), "rect");
    389             break;
    390         case SkClipStack::Element::kRRect_Type:
    391             this->pushRRect(element.getRRect(), "rrect");
    392             break;
    393         case SkClipStack::Element::kPath_Type:
    394             this->pushPath(element.getPath(), "path");
    395             break;
    396     }
    397     this->pushString(region_op(element.getOp()), "op");
    398     this->pushBool(element.isAA(), "aa");
    399     CHECK_SETFIELD(key);
    400 }
    401 
    402 
    403 ///////////////////////////////////////////////////////////////////////////////
    404 ///////////////////////////////////////////////////////////////////////////////
    405 
    406 static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
    407     SkASSERT(lua_istable(L, index));
    408     lua_pushstring(L, key);
    409     lua_gettable(L, index);
    410 
    411     SkScalar value = lua2scalar(L, -1);
    412     lua_pop(L, 1);
    413     return value;
    414 }
    415 
    416 static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
    417     SkASSERT(lua_istable(L, index));
    418     lua_pushstring(L, key);
    419     lua_gettable(L, index);
    420 
    421     SkScalar value;
    422     if (lua_isnil(L, -1)) {
    423         value = def;
    424     } else {
    425         value = lua2scalar(L, -1);
    426     }
    427     lua_pop(L, 1);
    428     return value;
    429 }
    430 
    431 static SkScalar byte2unit(U8CPU byte) {
    432     return byte / 255.0f;
    433 }
    434 
    435 static U8CPU unit2byte(SkScalar x) {
    436     if (x <= 0) {
    437         return 0;
    438     } else if (x >= 1) {
    439         return 255;
    440     } else {
    441         return SkScalarRoundToInt(x * 255);
    442     }
    443 }
    444 
    445 static SkColor lua2color(lua_State* L, int index) {
    446     return SkColorSetARGB(unit2byte(getfield_scalar_default(L, index, "a", 1)),
    447                           unit2byte(getfield_scalar_default(L, index, "r", 0)),
    448                           unit2byte(getfield_scalar_default(L, index, "g", 0)),
    449                           unit2byte(getfield_scalar_default(L, index, "b", 0)));
    450 }
    451 
    452 static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
    453     rect->set(getfield_scalar_default(L, index, "left", 0),
    454               getfield_scalar_default(L, index, "top", 0),
    455               getfield_scalar(L, index, "right"),
    456               getfield_scalar(L, index, "bottom"));
    457     return rect;
    458 }
    459 
    460 static int lcanvas_clear(lua_State* L) {
    461     get_ref<SkCanvas>(L, 1)->clear(0);
    462     return 0;
    463 }
    464 
    465 static int lcanvas_drawColor(lua_State* L) {
    466     get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
    467     return 0;
    468 }
    469 
    470 static int lcanvas_drawPaint(lua_State* L) {
    471     get_ref<SkCanvas>(L, 1)->drawPaint(*get_obj<SkPaint>(L, 2));
    472     return 0;
    473 }
    474 
    475 static int lcanvas_drawRect(lua_State* L) {
    476     SkRect rect;
    477     lua2rect(L, 2, &rect);
    478     const SkPaint* paint = get_obj<SkPaint>(L, 3);
    479     get_ref<SkCanvas>(L, 1)->drawRect(rect, *paint);
    480     return 0;
    481 }
    482 
    483 static int lcanvas_drawOval(lua_State* L) {
    484     SkRect rect;
    485     get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
    486                                       *get_obj<SkPaint>(L, 3));
    487     return 0;
    488 }
    489 
    490 static int lcanvas_drawCircle(lua_State* L) {
    491     get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
    492                                         lua2scalar(L, 3),
    493                                         lua2scalar(L, 4),
    494                                         *get_obj<SkPaint>(L, 5));
    495     return 0;
    496 }
    497 
    498 static SkPaint* lua2OptionalPaint(lua_State* L, int index, SkPaint* paint) {
    499     if (lua_isnumber(L, index)) {
    500         paint->setAlpha(SkScalarRoundToInt(lua2scalar(L, index) * 255));
    501         return paint;
    502     } else if (lua_isuserdata(L, index)) {
    503         const SkPaint* ptr = get_obj<SkPaint>(L, index);
    504         if (ptr) {
    505             *paint = *ptr;
    506             return paint;
    507         }
    508     }
    509     return nullptr;
    510 }
    511 
    512 static int lcanvas_drawImage(lua_State* L) {
    513     SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
    514     SkImage* image = get_ref<SkImage>(L, 2);
    515     if (nullptr == image) {
    516         return 0;
    517     }
    518     SkScalar x = lua2scalar(L, 3);
    519     SkScalar y = lua2scalar(L, 4);
    520 
    521     SkPaint paint;
    522     canvas->drawImage(image, x, y, lua2OptionalPaint(L, 5, &paint));
    523     return 0;
    524 }
    525 
    526 static int lcanvas_drawImageRect(lua_State* L) {
    527     SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
    528     SkImage* image = get_ref<SkImage>(L, 2);
    529     if (nullptr == image) {
    530         return 0;
    531     }
    532 
    533     SkRect srcR, dstR;
    534     SkRect* srcRPtr = nullptr;
    535     if (!lua_isnil(L, 3)) {
    536         srcRPtr = lua2rect(L, 3, &srcR);
    537     }
    538     lua2rect(L, 4, &dstR);
    539 
    540     SkPaint paint;
    541     canvas->legacy_drawImageRect(image, srcRPtr, dstR, lua2OptionalPaint(L, 5, &paint));
    542     return 0;
    543 }
    544 
    545 static int lcanvas_drawPatch(lua_State* L) {
    546     SkPoint cubics[12];
    547     SkColor colorStorage[4];
    548     SkPoint texStorage[4];
    549 
    550     const SkColor* colors = nullptr;
    551     const SkPoint* texs = nullptr;
    552 
    553     getarray_points(L, 2, cubics, 12);
    554 
    555     colorStorage[0] = SK_ColorRED;
    556     colorStorage[1] = SK_ColorGREEN;
    557     colorStorage[2] = SK_ColorBLUE;
    558     colorStorage[3] = SK_ColorGRAY;
    559 
    560     if (lua_isnil(L, 4)) {
    561         colors = colorStorage;
    562     } else {
    563         getarray_points(L, 4, texStorage, 4);
    564         texs = texStorage;
    565     }
    566 
    567     get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, nullptr, *get_obj<SkPaint>(L, 5));
    568     return 0;
    569 }
    570 
    571 static int lcanvas_drawPath(lua_State* L) {
    572     get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
    573                                       *get_obj<SkPaint>(L, 3));
    574     return 0;
    575 }
    576 
    577 // drawPicture(pic, x, y, paint)
    578 static int lcanvas_drawPicture(lua_State* L) {
    579     SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
    580     SkPicture* picture = get_ref<SkPicture>(L, 2);
    581     SkScalar x = lua2scalar_def(L, 3, 0);
    582     SkScalar y = lua2scalar_def(L, 4, 0);
    583     SkMatrix matrix, *matrixPtr = nullptr;
    584     if (x || y) {
    585         matrix.setTranslate(x, y);
    586         matrixPtr = &matrix;
    587     }
    588     SkPaint paint;
    589     canvas->drawPicture(picture, matrixPtr, lua2OptionalPaint(L, 5, &paint));
    590     return 0;
    591 }
    592 
    593 static int lcanvas_drawText(lua_State* L) {
    594     if (lua_gettop(L) < 5) {
    595         return 0;
    596     }
    597 
    598     if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
    599         size_t len;
    600         const char* text = lua_tolstring(L, 2, &len);
    601         get_ref<SkCanvas>(L, 1)->drawText(text, len,
    602                                           lua2scalar(L, 3), lua2scalar(L, 4),
    603                                           *get_obj<SkPaint>(L, 5));
    604     }
    605     return 0;
    606 }
    607 
    608 static int lcanvas_drawTextBlob(lua_State* L) {
    609     const SkTextBlob* blob = get_ref<SkTextBlob>(L, 2);
    610     SkScalar x = lua2scalar(L, 3);
    611     SkScalar y = lua2scalar(L, 4);
    612     const SkPaint& paint = *get_obj<SkPaint>(L, 5);
    613     get_ref<SkCanvas>(L, 1)->drawTextBlob(blob, x, y, paint);
    614     return 0;
    615 }
    616 
    617 static int lcanvas_getSaveCount(lua_State* L) {
    618     lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
    619     return 1;
    620 }
    621 
    622 static int lcanvas_getTotalMatrix(lua_State* L) {
    623     SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
    624     return 1;
    625 }
    626 
    627 static int lcanvas_getClipStack(lua_State* L) {
    628     SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack());
    629     return 1;
    630 }
    631 
    632 int SkLua::lcanvas_getReducedClipStack(lua_State* L) {
    633 #if SK_SUPPORT_GPU
    634     const SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
    635     SkIRect queryBounds = canvas->getTopLayerBounds();
    636 
    637     GrReducedClip::ElementList elements;
    638     GrReducedClip::InitialState initialState;
    639     int32_t genID;
    640     SkIRect resultBounds;
    641 
    642     const SkClipStack& stack = *canvas->getClipStack();
    643 
    644     GrReducedClip::ReduceClipStack(stack,
    645                                    queryBounds,
    646                                    &elements,
    647                                    &genID,
    648                                    &initialState,
    649                                    &resultBounds,
    650                                    nullptr);
    651 
    652     GrReducedClip::ElementList::Iter iter(elements);
    653     int i = 0;
    654     lua_newtable(L);
    655     while(iter.get()) {
    656         SkLua(L).pushClipStackElement(*iter.get());
    657         iter.next();
    658         lua_rawseti(L, -2, ++i);
    659     }
    660     // Currently this only returns the element list to lua, not the initial state or result bounds.
    661     // It could return these as additional items on the lua stack.
    662     return 1;
    663 #else
    664     return 0;
    665 #endif
    666 }
    667 
    668 static int lcanvas_save(lua_State* L) {
    669     lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
    670     return 1;
    671 }
    672 
    673 static int lcanvas_saveLayer(lua_State* L) {
    674     SkPaint paint;
    675     lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->saveLayer(nullptr, lua2OptionalPaint(L, 2, &paint)));
    676     return 1;
    677 }
    678 
    679 static int lcanvas_restore(lua_State* L) {
    680     get_ref<SkCanvas>(L, 1)->restore();
    681     return 0;
    682 }
    683 
    684 static int lcanvas_scale(lua_State* L) {
    685     SkScalar sx = lua2scalar_def(L, 2, 1);
    686     SkScalar sy = lua2scalar_def(L, 3, sx);
    687     get_ref<SkCanvas>(L, 1)->scale(sx, sy);
    688     return 0;
    689 }
    690 
    691 static int lcanvas_translate(lua_State* L) {
    692     SkScalar tx = lua2scalar_def(L, 2, 0);
    693     SkScalar ty = lua2scalar_def(L, 3, 0);
    694     get_ref<SkCanvas>(L, 1)->translate(tx, ty);
    695     return 0;
    696 }
    697 
    698 static int lcanvas_rotate(lua_State* L) {
    699     SkScalar degrees = lua2scalar_def(L, 2, 0);
    700     get_ref<SkCanvas>(L, 1)->rotate(degrees);
    701     return 0;
    702 }
    703 
    704 static int lcanvas_concat(lua_State* L) {
    705     get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2));
    706     return 0;
    707 }
    708 
    709 static int lcanvas_newSurface(lua_State* L) {
    710     int width = lua2int_def(L, 2, 0);
    711     int height = lua2int_def(L, 3, 0);
    712     SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
    713     SkSurface* surface = get_ref<SkCanvas>(L, 1)->newSurface(info);
    714     if (nullptr == surface) {
    715         lua_pushnil(L);
    716     } else {
    717         push_ref(L, surface)->unref();
    718     }
    719     return 1;
    720 }
    721 
    722 static int lcanvas_gc(lua_State* L) {
    723     get_ref<SkCanvas>(L, 1)->unref();
    724     return 0;
    725 }
    726 
    727 const struct luaL_Reg gSkCanvas_Methods[] = {
    728     { "clear", lcanvas_clear },
    729     { "drawColor", lcanvas_drawColor },
    730     { "drawPaint", lcanvas_drawPaint },
    731     { "drawRect", lcanvas_drawRect },
    732     { "drawOval", lcanvas_drawOval },
    733     { "drawCircle", lcanvas_drawCircle },
    734     { "drawImage", lcanvas_drawImage },
    735     { "drawImageRect", lcanvas_drawImageRect },
    736     { "drawPatch", lcanvas_drawPatch },
    737     { "drawPath", lcanvas_drawPath },
    738     { "drawPicture", lcanvas_drawPicture },
    739     { "drawText", lcanvas_drawText },
    740     { "drawTextBlob", lcanvas_drawTextBlob },
    741     { "getSaveCount", lcanvas_getSaveCount },
    742     { "getTotalMatrix", lcanvas_getTotalMatrix },
    743     { "getClipStack", lcanvas_getClipStack },
    744 #if SK_SUPPORT_GPU
    745     { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
    746 #endif
    747     { "save", lcanvas_save },
    748     { "saveLayer", lcanvas_saveLayer },
    749     { "restore", lcanvas_restore },
    750     { "scale", lcanvas_scale },
    751     { "translate", lcanvas_translate },
    752     { "rotate", lcanvas_rotate },
    753     { "concat", lcanvas_concat },
    754 
    755     { "newSurface", lcanvas_newSurface },
    756 
    757     { "__gc", lcanvas_gc },
    758     { nullptr, nullptr }
    759 };
    760 
    761 ///////////////////////////////////////////////////////////////////////////////
    762 
    763 static int ldocument_beginPage(lua_State* L) {
    764     const SkRect* contentPtr = nullptr;
    765     push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2),
    766                                                      lua2scalar(L, 3),
    767                                                      contentPtr));
    768     return 1;
    769 }
    770 
    771 static int ldocument_endPage(lua_State* L) {
    772     get_ref<SkDocument>(L, 1)->endPage();
    773     return 0;
    774 }
    775 
    776 static int ldocument_close(lua_State* L) {
    777     get_ref<SkDocument>(L, 1)->close();
    778     return 0;
    779 }
    780 
    781 static int ldocument_gc(lua_State* L) {
    782     get_ref<SkDocument>(L, 1)->unref();
    783     return 0;
    784 }
    785 
    786 static const struct luaL_Reg gSkDocument_Methods[] = {
    787     { "beginPage", ldocument_beginPage },
    788     { "endPage", ldocument_endPage },
    789     { "close", ldocument_close },
    790     { "__gc", ldocument_gc },
    791     { nullptr, nullptr }
    792 };
    793 
    794 ///////////////////////////////////////////////////////////////////////////////
    795 
    796 static int lpaint_isAntiAlias(lua_State* L) {
    797     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
    798     return 1;
    799 }
    800 
    801 static int lpaint_setAntiAlias(lua_State* L) {
    802     get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
    803     return 0;
    804 }
    805 
    806 static int lpaint_isDither(lua_State* L) {
    807     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
    808     return 1;
    809 }
    810 
    811 static int lpaint_setDither(lua_State* L) {
    812     get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2));
    813     return 0;
    814 }
    815 
    816 static int lpaint_isUnderlineText(lua_State* L) {
    817     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText());
    818     return 1;
    819 }
    820 
    821 static int lpaint_isStrikeThruText(lua_State* L) {
    822     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText());
    823     return 1;
    824 }
    825 
    826 static int lpaint_isFakeBoldText(lua_State* L) {
    827     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
    828     return 1;
    829 }
    830 
    831 static int lpaint_isLinearText(lua_State* L) {
    832     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
    833     return 1;
    834 }
    835 
    836 static int lpaint_isSubpixelText(lua_State* L) {
    837     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
    838     return 1;
    839 }
    840 
    841 static int lpaint_setSubpixelText(lua_State* L) {
    842     get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
    843     return 1;
    844 }
    845 
    846 static int lpaint_isDevKernText(lua_State* L) {
    847     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
    848     return 1;
    849 }
    850 
    851 static int lpaint_isLCDRenderText(lua_State* L) {
    852     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
    853     return 1;
    854 }
    855 
    856 static int lpaint_setLCDRenderText(lua_State* L) {
    857     get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2));
    858     return 1;
    859 }
    860 
    861 static int lpaint_isEmbeddedBitmapText(lua_State* L) {
    862     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
    863     return 1;
    864 }
    865 
    866 static int lpaint_isAutohinted(lua_State* L) {
    867     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
    868     return 1;
    869 }
    870 
    871 static int lpaint_isVerticalText(lua_State* L) {
    872     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
    873     return 1;
    874 }
    875 
    876 static int lpaint_getAlpha(lua_State* L) {
    877     SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha()));
    878     return 1;
    879 }
    880 
    881 static int lpaint_setAlpha(lua_State* L) {
    882     get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2)));
    883     return 0;
    884 }
    885 
    886 static int lpaint_getColor(lua_State* L) {
    887     SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
    888     return 1;
    889 }
    890 
    891 static int lpaint_setColor(lua_State* L) {
    892     get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
    893     return 0;
    894 }
    895 
    896 static int lpaint_getTextSize(lua_State* L) {
    897     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
    898     return 1;
    899 }
    900 
    901 static int lpaint_getTextScaleX(lua_State* L) {
    902     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
    903     return 1;
    904 }
    905 
    906 static int lpaint_getTextSkewX(lua_State* L) {
    907     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
    908     return 1;
    909 }
    910 
    911 static int lpaint_setTextSize(lua_State* L) {
    912     get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
    913     return 0;
    914 }
    915 
    916 static int lpaint_getTypeface(lua_State* L) {
    917     push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
    918     return 1;
    919 }
    920 
    921 static int lpaint_setTypeface(lua_State* L) {
    922     get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2));
    923     return 0;
    924 }
    925 
    926 static int lpaint_getHinting(lua_State* L) {
    927     SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
    928     return 1;
    929 }
    930 
    931 static int lpaint_getFilterQuality(lua_State* L) {
    932     SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality());
    933     return 1;
    934 }
    935 
    936 static int lpaint_setFilterQuality(lua_State* L) {
    937     int level = lua2int_def(L, 2, -1);
    938     if (level >= 0 && level <= 3) {
    939         get_obj<SkPaint>(L, 1)->setFilterQuality((SkFilterQuality)level);
    940     }
    941     return 0;
    942 }
    943 
    944 static int lpaint_getFontID(lua_State* L) {
    945     SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
    946     SkLua(L).pushU32(SkTypeface::UniqueID(face));
    947     return 1;
    948 }
    949 
    950 static const struct {
    951     const char*     fLabel;
    952     SkPaint::Align  fAlign;
    953 } gAlignRec[] = {
    954     { "left",   SkPaint::kLeft_Align },
    955     { "center", SkPaint::kCenter_Align },
    956     { "right",  SkPaint::kRight_Align },
    957 };
    958 
    959 static int lpaint_getTextAlign(lua_State* L) {
    960     SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
    961     for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
    962         if (gAlignRec[i].fAlign == align) {
    963             lua_pushstring(L, gAlignRec[i].fLabel);
    964             return 1;
    965         }
    966     }
    967     return 0;
    968 }
    969 
    970 static int lpaint_setTextAlign(lua_State* L) {
    971     if (lua_isstring(L, 2)) {
    972         size_t len;
    973         const char* label = lua_tolstring(L, 2, &len);
    974 
    975         for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
    976             if (!strcmp(gAlignRec[i].fLabel, label)) {
    977                 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
    978                 break;
    979             }
    980         }
    981     }
    982     return 0;
    983 }
    984 
    985 static int lpaint_getStroke(lua_State* L) {
    986     lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
    987     return 1;
    988 }
    989 
    990 static int lpaint_setStroke(lua_State* L) {
    991     SkPaint::Style style;
    992 
    993     if (lua_toboolean(L, 2)) {
    994         style = SkPaint::kStroke_Style;
    995     } else {
    996         style = SkPaint::kFill_Style;
    997     }
    998     get_obj<SkPaint>(L, 1)->setStyle(style);
    999     return 0;
   1000 }
   1001 
   1002 static int lpaint_getStrokeCap(lua_State* L) {
   1003     SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
   1004     return 1;
   1005 }
   1006 
   1007 static int lpaint_getStrokeJoin(lua_State* L) {
   1008     SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
   1009     return 1;
   1010 }
   1011 
   1012 static int lpaint_getTextEncoding(lua_State* L) {
   1013     SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
   1014     return 1;
   1015 }
   1016 
   1017 static int lpaint_getStrokeWidth(lua_State* L) {
   1018     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
   1019     return 1;
   1020 }
   1021 
   1022 static int lpaint_setStrokeWidth(lua_State* L) {
   1023     get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
   1024     return 0;
   1025 }
   1026 
   1027 static int lpaint_getStrokeMiter(lua_State* L) {
   1028     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
   1029     return 1;
   1030 }
   1031 
   1032 static int lpaint_measureText(lua_State* L) {
   1033     if (lua_isstring(L, 2)) {
   1034         size_t len;
   1035         const char* text = lua_tolstring(L, 2, &len);
   1036         SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
   1037         return 1;
   1038     }
   1039     return 0;
   1040 }
   1041 
   1042 struct FontMetrics {
   1043     SkScalar    fTop;       //!< The greatest distance above the baseline for any glyph (will be <= 0)
   1044     SkScalar    fAscent;    //!< The recommended distance above the baseline (will be <= 0)
   1045     SkScalar    fDescent;   //!< The recommended distance below the baseline (will be >= 0)
   1046     SkScalar    fBottom;    //!< The greatest distance below the baseline for any glyph (will be >= 0)
   1047     SkScalar    fLeading;   //!< The recommended distance to add between lines of text (will be >= 0)
   1048     SkScalar    fAvgCharWidth;  //!< the average charactor width (>= 0)
   1049     SkScalar    fXMin;      //!< The minimum bounding box x value for all glyphs
   1050     SkScalar    fXMax;      //!< The maximum bounding box x value for all glyphs
   1051     SkScalar    fXHeight;   //!< the height of an 'x' in px, or 0 if no 'x' in face
   1052 };
   1053 
   1054 static int lpaint_getFontMetrics(lua_State* L) {
   1055     SkPaint::FontMetrics fm;
   1056     SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
   1057 
   1058     lua_newtable(L);
   1059     setfield_scalar(L, "top", fm.fTop);
   1060     setfield_scalar(L, "ascent", fm.fAscent);
   1061     setfield_scalar(L, "descent", fm.fDescent);
   1062     setfield_scalar(L, "bottom", fm.fBottom);
   1063     setfield_scalar(L, "leading", fm.fLeading);
   1064     SkLua(L).pushScalar(height);
   1065     return 2;
   1066 }
   1067 
   1068 static int lpaint_getEffects(lua_State* L) {
   1069     const SkPaint* paint = get_obj<SkPaint>(L, 1);
   1070 
   1071     lua_newtable(L);
   1072     setfield_bool_if(L, "looper",      !!paint->getLooper());
   1073     setfield_bool_if(L, "pathEffect",  !!paint->getPathEffect());
   1074     setfield_bool_if(L, "rasterizer",  !!paint->getRasterizer());
   1075     setfield_bool_if(L, "maskFilter",  !!paint->getMaskFilter());
   1076     setfield_bool_if(L, "shader",      !!paint->getShader());
   1077     setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
   1078     setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
   1079     setfield_bool_if(L, "xfermode",    !!paint->getXfermode());
   1080     return 1;
   1081 }
   1082 
   1083 static int lpaint_getXfermode(lua_State* L) {
   1084     const SkPaint* paint = get_obj<SkPaint>(L, 1);
   1085     SkXfermode* xfermode = paint->getXfermode();
   1086     if (xfermode) {
   1087         push_ref(L, xfermode);
   1088         return 1;
   1089     }
   1090     return 0;
   1091 }
   1092 
   1093 static int lpaint_setXfermode(lua_State* L) {
   1094     SkPaint* paint = get_obj<SkPaint>(L, 1);
   1095     paint->setXfermode(get_ref<SkXfermode>(L, 2));
   1096     return 0;
   1097 }
   1098 
   1099 static int lpaint_getColorFilter(lua_State* L) {
   1100     const SkPaint* paint = get_obj<SkPaint>(L, 1);
   1101     SkColorFilter* cf = paint->getColorFilter();
   1102     if (cf) {
   1103         push_ref(L, cf);
   1104         return 1;
   1105     }
   1106     return 0;
   1107 }
   1108 
   1109 static int lpaint_setColorFilter(lua_State* L) {
   1110     SkPaint* paint = get_obj<SkPaint>(L, 1);
   1111     paint->setColorFilter(get_ref<SkColorFilter>(L, 2));
   1112     return 0;
   1113 }
   1114 
   1115 static int lpaint_getImageFilter(lua_State* L) {
   1116     const SkPaint* paint = get_obj<SkPaint>(L, 1);
   1117     SkImageFilter* imf = paint->getImageFilter();
   1118     if (imf) {
   1119         push_ref(L, imf);
   1120         return 1;
   1121     }
   1122     return 0;
   1123 }
   1124 
   1125 static int lpaint_setImageFilter(lua_State* L) {
   1126     SkPaint* paint = get_obj<SkPaint>(L, 1);
   1127     paint->setImageFilter(get_ref<SkImageFilter>(L, 2));
   1128     return 0;
   1129 }
   1130 
   1131 static int lpaint_getShader(lua_State* L) {
   1132     const SkPaint* paint = get_obj<SkPaint>(L, 1);
   1133     SkShader* shader = paint->getShader();
   1134     if (shader) {
   1135         push_ref(L, shader);
   1136         return 1;
   1137     }
   1138     return 0;
   1139 }
   1140 
   1141 static int lpaint_setShader(lua_State* L) {
   1142     SkPaint* paint = get_obj<SkPaint>(L, 1);
   1143     paint->setShader(get_ref<SkShader>(L, 2));
   1144     return 0;
   1145 }
   1146 
   1147 static int lpaint_getPathEffect(lua_State* L) {
   1148     const SkPaint* paint = get_obj<SkPaint>(L, 1);
   1149     SkPathEffect* pe = paint->getPathEffect();
   1150     if (pe) {
   1151         push_ref(L, pe);
   1152         return 1;
   1153     }
   1154     return 0;
   1155 }
   1156 
   1157 static int lpaint_gc(lua_State* L) {
   1158     get_obj<SkPaint>(L, 1)->~SkPaint();
   1159     return 0;
   1160 }
   1161 
   1162 static const struct luaL_Reg gSkPaint_Methods[] = {
   1163     { "isAntiAlias", lpaint_isAntiAlias },
   1164     { "setAntiAlias", lpaint_setAntiAlias },
   1165     { "isDither", lpaint_isDither },
   1166     { "setDither", lpaint_setDither },
   1167     { "getFilterQuality", lpaint_getFilterQuality },
   1168     { "setFilterQuality", lpaint_setFilterQuality },
   1169     { "isUnderlineText", lpaint_isUnderlineText },
   1170     { "isStrikeThruText", lpaint_isStrikeThruText },
   1171     { "isFakeBoldText", lpaint_isFakeBoldText },
   1172     { "isLinearText", lpaint_isLinearText },
   1173     { "isSubpixelText", lpaint_isSubpixelText },
   1174     { "setSubpixelText", lpaint_setSubpixelText },
   1175     { "isDevKernText", lpaint_isDevKernText },
   1176     { "isLCDRenderText", lpaint_isLCDRenderText },
   1177     { "setLCDRenderText", lpaint_setLCDRenderText },
   1178     { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
   1179     { "isAutohinted", lpaint_isAutohinted },
   1180     { "isVerticalText", lpaint_isVerticalText },
   1181     { "getAlpha", lpaint_getAlpha },
   1182     { "setAlpha", lpaint_setAlpha },
   1183     { "getColor", lpaint_getColor },
   1184     { "setColor", lpaint_setColor },
   1185     { "getTextSize", lpaint_getTextSize },
   1186     { "setTextSize", lpaint_setTextSize },
   1187     { "getTextScaleX", lpaint_getTextScaleX },
   1188     { "getTextSkewX", lpaint_getTextSkewX },
   1189     { "getTypeface", lpaint_getTypeface },
   1190     { "setTypeface", lpaint_setTypeface },
   1191     { "getHinting", lpaint_getHinting },
   1192     { "getFontID", lpaint_getFontID },
   1193     { "getTextAlign", lpaint_getTextAlign },
   1194     { "setTextAlign", lpaint_setTextAlign },
   1195     { "getStroke", lpaint_getStroke },
   1196     { "setStroke", lpaint_setStroke },
   1197     { "getStrokeCap", lpaint_getStrokeCap },
   1198     { "getStrokeJoin", lpaint_getStrokeJoin },
   1199     { "getTextEncoding", lpaint_getTextEncoding },
   1200     { "getStrokeWidth", lpaint_getStrokeWidth },
   1201     { "setStrokeWidth", lpaint_setStrokeWidth },
   1202     { "getStrokeMiter", lpaint_getStrokeMiter },
   1203     { "measureText", lpaint_measureText },
   1204     { "getFontMetrics", lpaint_getFontMetrics },
   1205     { "getEffects", lpaint_getEffects },
   1206     { "getColorFilter", lpaint_getColorFilter },
   1207     { "setColorFilter", lpaint_setColorFilter },
   1208     { "getImageFilter", lpaint_getImageFilter },
   1209     { "setImageFilter", lpaint_setImageFilter },
   1210     { "getXfermode", lpaint_getXfermode },
   1211     { "setXfermode", lpaint_setXfermode },
   1212     { "getShader", lpaint_getShader },
   1213     { "setShader", lpaint_setShader },
   1214     { "getPathEffect", lpaint_getPathEffect },
   1215     { "__gc", lpaint_gc },
   1216     { nullptr, nullptr }
   1217 };
   1218 
   1219 ///////////////////////////////////////////////////////////////////////////////
   1220 
   1221 static const char* mode2string(SkShader::TileMode mode) {
   1222     static const char* gNames[] = { "clamp", "repeat", "mirror" };
   1223     SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
   1224     return gNames[mode];
   1225 }
   1226 
   1227 static const char* gradtype2string(SkShader::GradientType t) {
   1228     static const char* gNames[] = {
   1229         "none", "color", "linear", "radial", "radial2", "sweep", "conical"
   1230     };
   1231     SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
   1232     return gNames[t];
   1233 }
   1234 
   1235 static int lshader_isOpaque(lua_State* L) {
   1236     SkShader* shader = get_ref<SkShader>(L, 1);
   1237     return shader && shader->isOpaque();
   1238 }
   1239 
   1240 static int lshader_isABitmap(lua_State* L) {
   1241     SkShader* shader = get_ref<SkShader>(L, 1);
   1242     if (shader) {
   1243         SkBitmap bm;
   1244         SkMatrix matrix;
   1245         SkShader::TileMode modes[2];
   1246         if (shader->isABitmap(&bm, &matrix, modes)) {
   1247             lua_newtable(L);
   1248             setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0);
   1249             setfield_number(L, "width", bm.width());
   1250             setfield_number(L, "height", bm.height());
   1251             setfield_string(L, "tileX", mode2string(modes[0]));
   1252             setfield_string(L, "tileY", mode2string(modes[1]));
   1253             return 1;
   1254         }
   1255     }
   1256     return 0;
   1257 }
   1258 
   1259 static int lshader_asAGradient(lua_State* L) {
   1260     SkShader* shader = get_ref<SkShader>(L, 1);
   1261     if (shader) {
   1262         SkShader::GradientInfo info;
   1263         sk_bzero(&info, sizeof(info));
   1264 
   1265         SkColor colors[3];  // hacked in for extracting info on 3 color case.
   1266         SkScalar pos[3];
   1267 
   1268         info.fColorCount = 3;
   1269         info.fColors = &colors[0];
   1270         info.fColorOffsets = &pos[0];
   1271 
   1272         SkShader::GradientType t = shader->asAGradient(&info);
   1273 
   1274         if (SkShader::kNone_GradientType != t) {
   1275             lua_newtable(L);
   1276             setfield_string(L, "type", gradtype2string(t));
   1277             setfield_number(L, "colorCount", info.fColorCount);
   1278             setfield_string(L, "tile", mode2string(info.fTileMode));
   1279 
   1280             if (info.fColorCount == 3){
   1281                 setfield_number(L, "midPos", pos[1]);
   1282             }
   1283 
   1284             return 1;
   1285         }
   1286     }
   1287     return 0;
   1288 }
   1289 
   1290 static int lshader_gc(lua_State* L) {
   1291     get_ref<SkShader>(L, 1)->unref();
   1292     return 0;
   1293 }
   1294 
   1295 static const struct luaL_Reg gSkShader_Methods[] = {
   1296     { "isOpaque",       lshader_isOpaque },
   1297     { "isABitmap",      lshader_isABitmap },
   1298     { "asAGradient",    lshader_asAGradient },
   1299     { "__gc",           lshader_gc },
   1300     { nullptr, nullptr }
   1301 };
   1302 
   1303 ///////////////////////////////////////////////////////////////////////////////
   1304 
   1305 static int lpatheffect_asADash(lua_State* L) {
   1306     SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
   1307     if (pe) {
   1308         SkPathEffect::DashInfo info;
   1309         SkPathEffect::DashType dashType = pe->asADash(&info);
   1310         if (SkPathEffect::kDash_DashType == dashType) {
   1311             SkAutoTArray<SkScalar> intervals(info.fCount);
   1312             info.fIntervals = intervals.get();
   1313             pe->asADash(&info);
   1314             SkLua(L).pushDash(info);
   1315             return 1;
   1316         }
   1317     }
   1318     return 0;
   1319 }
   1320 
   1321 static int lpatheffect_gc(lua_State* L) {
   1322     get_ref<SkPathEffect>(L, 1)->unref();
   1323     return 0;
   1324 }
   1325 
   1326 static const struct luaL_Reg gSkPathEffect_Methods[] = {
   1327     { "asADash",        lpatheffect_asADash },
   1328     { "__gc",           lpatheffect_gc },
   1329     { nullptr, nullptr }
   1330 };
   1331 
   1332 ///////////////////////////////////////////////////////////////////////////////
   1333 
   1334 static int lpxfermode_getTypeName(lua_State* L) {
   1335     lua_pushstring(L, get_ref<SkXfermode>(L, 1)->getTypeName());
   1336     return 1;
   1337 }
   1338 
   1339 static int lpxfermode_gc(lua_State* L) {
   1340     get_ref<SkXfermode>(L, 1)->unref();
   1341     return 0;
   1342 }
   1343 
   1344 static const struct luaL_Reg gSkXfermode_Methods[] = {
   1345     { "getTypeName",    lpxfermode_getTypeName },
   1346     { "__gc",           lpxfermode_gc },
   1347     { nullptr, nullptr }
   1348 };
   1349 
   1350 ///////////////////////////////////////////////////////////////////////////////
   1351 
   1352 static int lpcolorfilter_gc(lua_State* L) {
   1353     get_ref<SkColorFilter>(L, 1)->unref();
   1354     return 0;
   1355 }
   1356 
   1357 static const struct luaL_Reg gSkColorFilter_Methods[] = {
   1358     { "__gc",       lpcolorfilter_gc },
   1359     { nullptr, nullptr }
   1360 };
   1361 
   1362 ///////////////////////////////////////////////////////////////////////////////
   1363 
   1364 static int lpimagefilter_gc(lua_State* L) {
   1365     get_ref<SkImageFilter>(L, 1)->unref();
   1366     return 0;
   1367 }
   1368 
   1369 static const struct luaL_Reg gSkImageFilter_Methods[] = {
   1370     { "__gc",       lpimagefilter_gc },
   1371     { nullptr, nullptr }
   1372 };
   1373 
   1374 ///////////////////////////////////////////////////////////////////////////////
   1375 
   1376 static int lmatrix_getType(lua_State* L) {
   1377     SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
   1378 
   1379     lua_newtable(L);
   1380     setfield_boolean(L, "translate",   SkToBool(mask & SkMatrix::kTranslate_Mask));
   1381     setfield_boolean(L, "scale",       SkToBool(mask & SkMatrix::kScale_Mask));
   1382     setfield_boolean(L, "affine",      SkToBool(mask & SkMatrix::kAffine_Mask));
   1383     setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
   1384     return 1;
   1385 }
   1386 
   1387 static int lmatrix_getScaleX(lua_State* L) {
   1388     lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
   1389     return 1;
   1390 }
   1391 
   1392 static int lmatrix_getScaleY(lua_State* L) {
   1393     lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
   1394     return 1;
   1395 }
   1396 
   1397 static int lmatrix_getTranslateX(lua_State* L) {
   1398     lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
   1399     return 1;
   1400 }
   1401 
   1402 static int lmatrix_getTranslateY(lua_State* L) {
   1403     lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
   1404     return 1;
   1405 }
   1406 
   1407 static int lmatrix_invert(lua_State* L) {
   1408     lua_pushboolean(L, get_obj<SkMatrix>(L, 1)->invert(get_obj<SkMatrix>(L, 2)));
   1409     return 1;
   1410 }
   1411 
   1412 static int lmatrix_mapXY(lua_State* L) {
   1413     SkPoint pt = { lua2scalar(L, 2), lua2scalar(L, 3) };
   1414     get_obj<SkMatrix>(L, 1)->mapPoints(&pt, &pt, 1);
   1415     lua_pushnumber(L, pt.x());
   1416     lua_pushnumber(L, pt.y());
   1417     return 2;
   1418 }
   1419 
   1420 static int lmatrix_setRectToRect(lua_State* L) {
   1421     SkMatrix* matrix = get_obj<SkMatrix>(L, 1);
   1422     SkRect srcR, dstR;
   1423     lua2rect(L, 2, &srcR);
   1424     lua2rect(L, 3, &dstR);
   1425     const char* scaleToFitStr = lua_tostring(L, 4);
   1426     SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit;
   1427 
   1428     if (scaleToFitStr) {
   1429         const struct {
   1430             const char* fName;
   1431             SkMatrix::ScaleToFit fScaleToFit;
   1432         } rec[] = {
   1433             { "fill",   SkMatrix::kFill_ScaleToFit },
   1434             { "start",  SkMatrix::kStart_ScaleToFit },
   1435             { "center", SkMatrix::kCenter_ScaleToFit },
   1436             { "end",    SkMatrix::kEnd_ScaleToFit },
   1437         };
   1438 
   1439         for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
   1440             if (strcmp(rec[i].fName, scaleToFitStr) == 0) {
   1441                 scaleToFit = rec[i].fScaleToFit;
   1442                 break;
   1443             }
   1444         }
   1445     }
   1446 
   1447     matrix->setRectToRect(srcR, dstR, scaleToFit);
   1448     return 0;
   1449 }
   1450 
   1451 static const struct luaL_Reg gSkMatrix_Methods[] = {
   1452     { "getType", lmatrix_getType },
   1453     { "getScaleX", lmatrix_getScaleX },
   1454     { "getScaleY", lmatrix_getScaleY },
   1455     { "getTranslateX", lmatrix_getTranslateX },
   1456     { "getTranslateY", lmatrix_getTranslateY },
   1457     { "setRectToRect", lmatrix_setRectToRect },
   1458     { "invert", lmatrix_invert },
   1459     { "mapXY", lmatrix_mapXY },
   1460     { nullptr, nullptr }
   1461 };
   1462 
   1463 ///////////////////////////////////////////////////////////////////////////////
   1464 
   1465 static int lpath_getBounds(lua_State* L) {
   1466     SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
   1467     return 1;
   1468 }
   1469 
   1470 static const char* fill_type_to_str(SkPath::FillType fill) {
   1471     switch (fill) {
   1472         case SkPath::kEvenOdd_FillType:
   1473             return "even-odd";
   1474         case SkPath::kWinding_FillType:
   1475             return "winding";
   1476         case SkPath::kInverseEvenOdd_FillType:
   1477             return "inverse-even-odd";
   1478         case SkPath::kInverseWinding_FillType:
   1479             return "inverse-winding";
   1480     }
   1481     return "unknown";
   1482 }
   1483 
   1484 static int lpath_getFillType(lua_State* L) {
   1485     SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
   1486     SkLua(L).pushString(fill_type_to_str(fill));
   1487     return 1;
   1488 }
   1489 
   1490 static SkString segment_masks_to_str(uint32_t segmentMasks) {
   1491     SkString result;
   1492     bool first = true;
   1493     if (SkPath::kLine_SegmentMask & segmentMasks) {
   1494         result.append("line");
   1495         first = false;
   1496         SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
   1497     }
   1498     if (SkPath::kQuad_SegmentMask & segmentMasks) {
   1499         if (!first) {
   1500             result.append(" ");
   1501         }
   1502         result.append("quad");
   1503         first = false;
   1504         SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
   1505     }
   1506     if (SkPath::kConic_SegmentMask & segmentMasks) {
   1507         if (!first) {
   1508             result.append(" ");
   1509         }
   1510         result.append("conic");
   1511         first = false;
   1512         SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
   1513     }
   1514     if (SkPath::kCubic_SegmentMask & segmentMasks) {
   1515         if (!first) {
   1516             result.append(" ");
   1517         }
   1518         result.append("cubic");
   1519         SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
   1520     }
   1521     SkASSERT(0 == segmentMasks);
   1522     return result;
   1523 }
   1524 
   1525 static int lpath_getSegmentTypes(lua_State* L) {
   1526     uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
   1527     SkLua(L).pushString(segment_masks_to_str(segMasks));
   1528     return 1;
   1529 }
   1530 
   1531 static int lpath_isConvex(lua_State* L) {
   1532     bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
   1533     SkLua(L).pushBool(isConvex);
   1534     return 1;
   1535 }
   1536 
   1537 static int lpath_isEmpty(lua_State* L) {
   1538     lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
   1539     return 1;
   1540 }
   1541 
   1542 static int lpath_isRect(lua_State* L) {
   1543     SkRect r;
   1544     bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
   1545     int ret_count = 1;
   1546     lua_pushboolean(L, pred);
   1547     if (pred) {
   1548         SkLua(L).pushRect(r);
   1549         ret_count += 1;
   1550     }
   1551     return ret_count;
   1552 }
   1553 
   1554 static const char* dir2string(SkPath::Direction dir) {
   1555     static const char* gStr[] = {
   1556         "unknown", "cw", "ccw"
   1557     };
   1558     SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
   1559     return gStr[dir];
   1560 }
   1561 
   1562 static int lpath_isNestedFillRects(lua_State* L) {
   1563     SkRect rects[2];
   1564     SkPath::Direction dirs[2];
   1565     bool pred = get_obj<SkPath>(L, 1)->isNestedFillRects(rects, dirs);
   1566     int ret_count = 1;
   1567     lua_pushboolean(L, pred);
   1568     if (pred) {
   1569         SkLua lua(L);
   1570         lua.pushRect(rects[0]);
   1571         lua.pushRect(rects[1]);
   1572         lua_pushstring(L, dir2string(dirs[0]));
   1573         lua_pushstring(L, dir2string(dirs[0]));
   1574         ret_count += 4;
   1575     }
   1576     return ret_count;
   1577 }
   1578 
   1579 static int lpath_countPoints(lua_State* L) {
   1580     lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
   1581     return 1;
   1582 }
   1583 
   1584 static int lpath_reset(lua_State* L) {
   1585     get_obj<SkPath>(L, 1)->reset();
   1586     return 0;
   1587 }
   1588 
   1589 static int lpath_moveTo(lua_State* L) {
   1590     get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
   1591     return 0;
   1592 }
   1593 
   1594 static int lpath_lineTo(lua_State* L) {
   1595     get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
   1596     return 0;
   1597 }
   1598 
   1599 static int lpath_quadTo(lua_State* L) {
   1600     get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
   1601                                   lua2scalar(L, 4), lua2scalar(L, 5));
   1602     return 0;
   1603 }
   1604 
   1605 static int lpath_cubicTo(lua_State* L) {
   1606     get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
   1607                                    lua2scalar(L, 4), lua2scalar(L, 5),
   1608                                    lua2scalar(L, 6), lua2scalar(L, 7));
   1609     return 0;
   1610 }
   1611 
   1612 static int lpath_close(lua_State* L) {
   1613     get_obj<SkPath>(L, 1)->close();
   1614     return 0;
   1615 }
   1616 
   1617 static int lpath_gc(lua_State* L) {
   1618     get_obj<SkPath>(L, 1)->~SkPath();
   1619     return 0;
   1620 }
   1621 
   1622 static const struct luaL_Reg gSkPath_Methods[] = {
   1623     { "getBounds", lpath_getBounds },
   1624     { "getFillType", lpath_getFillType },
   1625     { "getSegmentTypes", lpath_getSegmentTypes },
   1626     { "isConvex", lpath_isConvex },
   1627     { "isEmpty", lpath_isEmpty },
   1628     { "isRect", lpath_isRect },
   1629     { "isNestedFillRects", lpath_isNestedFillRects },
   1630     { "countPoints", lpath_countPoints },
   1631     { "reset", lpath_reset },
   1632     { "moveTo", lpath_moveTo },
   1633     { "lineTo", lpath_lineTo },
   1634     { "quadTo", lpath_quadTo },
   1635     { "cubicTo", lpath_cubicTo },
   1636     { "close", lpath_close },
   1637     { "__gc", lpath_gc },
   1638     { nullptr, nullptr }
   1639 };
   1640 
   1641 ///////////////////////////////////////////////////////////////////////////////
   1642 
   1643 static const char* rrect_type(const SkRRect& rr) {
   1644     switch (rr.getType()) {
   1645         case SkRRect::kEmpty_Type: return "empty";
   1646         case SkRRect::kRect_Type: return "rect";
   1647         case SkRRect::kOval_Type: return "oval";
   1648         case SkRRect::kSimple_Type: return "simple";
   1649         case SkRRect::kNinePatch_Type: return "nine-patch";
   1650         case SkRRect::kComplex_Type: return "complex";
   1651     }
   1652     SkDEBUGFAIL("never get here");
   1653     return "";
   1654 }
   1655 
   1656 static int lrrect_rect(lua_State* L) {
   1657     SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
   1658     return 1;
   1659 }
   1660 
   1661 static int lrrect_type(lua_State* L) {
   1662     lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
   1663     return 1;
   1664 }
   1665 
   1666 static int lrrect_radii(lua_State* L) {
   1667     int corner = SkToInt(lua_tointeger(L, 2));
   1668     SkVector v;
   1669     if (corner < 0 || corner > 3) {
   1670         SkDebugf("bad corner index %d", corner);
   1671         v.set(0, 0);
   1672     } else {
   1673         v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
   1674     }
   1675     lua_pushnumber(L, v.fX);
   1676     lua_pushnumber(L, v.fY);
   1677     return 2;
   1678 }
   1679 
   1680 static int lrrect_gc(lua_State* L) {
   1681     get_obj<SkRRect>(L, 1)->~SkRRect();
   1682     return 0;
   1683 }
   1684 
   1685 static const struct luaL_Reg gSkRRect_Methods[] = {
   1686     { "rect", lrrect_rect },
   1687     { "type", lrrect_type },
   1688     { "radii", lrrect_radii },
   1689     { "__gc", lrrect_gc },
   1690     { nullptr, nullptr }
   1691 };
   1692 
   1693 ///////////////////////////////////////////////////////////////////////////////
   1694 
   1695 static int limage_width(lua_State* L) {
   1696     lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
   1697     return 1;
   1698 }
   1699 
   1700 static int limage_height(lua_State* L) {
   1701     lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
   1702     return 1;
   1703 }
   1704 
   1705 static int limage_newShader(lua_State* L) {
   1706     SkShader::TileMode tmode = SkShader::kClamp_TileMode;
   1707     const SkMatrix* localM = nullptr;
   1708     SkAutoTUnref<SkShader> shader(get_ref<SkImage>(L, 1)->newShader(tmode, tmode, localM));
   1709     push_ref(L, shader.get());
   1710     return 1;
   1711 }
   1712 
   1713 static int limage_gc(lua_State* L) {
   1714     get_ref<SkImage>(L, 1)->unref();
   1715     return 0;
   1716 }
   1717 
   1718 static const struct luaL_Reg gSkImage_Methods[] = {
   1719     { "width", limage_width },
   1720     { "height", limage_height },
   1721     { "newShader", limage_newShader },
   1722     { "__gc", limage_gc },
   1723     { nullptr, nullptr }
   1724 };
   1725 
   1726 ///////////////////////////////////////////////////////////////////////////////
   1727 
   1728 static int lsurface_width(lua_State* L) {
   1729     lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
   1730     return 1;
   1731 }
   1732 
   1733 static int lsurface_height(lua_State* L) {
   1734     lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
   1735     return 1;
   1736 }
   1737 
   1738 static int lsurface_getCanvas(lua_State* L) {
   1739     SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
   1740     if (nullptr == canvas) {
   1741         lua_pushnil(L);
   1742     } else {
   1743         push_ref(L, canvas);
   1744         // note: we don't unref canvas, since getCanvas did not ref it.
   1745         // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
   1746         // the real owner (the surface) go away, but still hold onto the canvas?
   1747         // *really* we want to sort of ref the surface again, but have the native object
   1748         // know that it is supposed to be treated as a canvas...
   1749     }
   1750     return 1;
   1751 }
   1752 
   1753 static int lsurface_newImageSnapshot(lua_State* L) {
   1754     SkImage* image = get_ref<SkSurface>(L, 1)->newImageSnapshot();
   1755     if (nullptr == image) {
   1756         lua_pushnil(L);
   1757     } else {
   1758         push_ref(L, image)->unref();
   1759     }
   1760     return 1;
   1761 }
   1762 
   1763 static int lsurface_newSurface(lua_State* L) {
   1764     int width = lua2int_def(L, 2, 0);
   1765     int height = lua2int_def(L, 3, 0);
   1766     SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
   1767     SkSurface* surface = get_ref<SkSurface>(L, 1)->newSurface(info);
   1768     if (nullptr == surface) {
   1769         lua_pushnil(L);
   1770     } else {
   1771         push_ref(L, surface)->unref();
   1772     }
   1773     return 1;
   1774 }
   1775 
   1776 static int lsurface_gc(lua_State* L) {
   1777     get_ref<SkSurface>(L, 1)->unref();
   1778     return 0;
   1779 }
   1780 
   1781 static const struct luaL_Reg gSkSurface_Methods[] = {
   1782     { "width", lsurface_width },
   1783     { "height", lsurface_height },
   1784     { "getCanvas", lsurface_getCanvas },
   1785     { "newImageSnapshot", lsurface_newImageSnapshot },
   1786     { "newSurface", lsurface_newSurface },
   1787     { "__gc", lsurface_gc },
   1788     { nullptr, nullptr }
   1789 };
   1790 
   1791 ///////////////////////////////////////////////////////////////////////////////
   1792 
   1793 static int lpicturerecorder_beginRecording(lua_State* L) {
   1794     const SkScalar w = lua2scalar_def(L, 2, -1);
   1795     const SkScalar h = lua2scalar_def(L, 3, -1);
   1796     if (w <= 0 || h <= 0) {
   1797         lua_pushnil(L);
   1798         return 1;
   1799     }
   1800 
   1801     SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
   1802     if (nullptr == canvas) {
   1803         lua_pushnil(L);
   1804         return 1;
   1805     }
   1806 
   1807     push_ref(L, canvas);
   1808     return 1;
   1809 }
   1810 
   1811 static int lpicturerecorder_getCanvas(lua_State* L) {
   1812     SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
   1813     if (nullptr == canvas) {
   1814         lua_pushnil(L);
   1815         return 1;
   1816     }
   1817     push_ref(L, canvas);
   1818     return 1;
   1819 }
   1820 
   1821 static int lpicturerecorder_endRecording(lua_State* L) {
   1822     SkPicture* pic = get_obj<SkPictureRecorder>(L, 1)->endRecording();
   1823     if (nullptr == pic) {
   1824         lua_pushnil(L);
   1825         return 1;
   1826     }
   1827     push_ref(L, pic)->unref();
   1828     return 1;
   1829 }
   1830 
   1831 static int lpicturerecorder_gc(lua_State* L) {
   1832     get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
   1833     return 0;
   1834 }
   1835 
   1836 static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
   1837     { "beginRecording", lpicturerecorder_beginRecording },
   1838     { "getCanvas", lpicturerecorder_getCanvas },
   1839     { "endRecording", lpicturerecorder_endRecording },
   1840     { "__gc", lpicturerecorder_gc },
   1841     { nullptr, nullptr }
   1842 };
   1843 
   1844 ///////////////////////////////////////////////////////////////////////////////
   1845 
   1846 static int lpicture_width(lua_State* L) {
   1847     lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
   1848     return 1;
   1849 }
   1850 
   1851 static int lpicture_height(lua_State* L) {
   1852     lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
   1853     return 1;
   1854 }
   1855 
   1856 static int lpicture_gc(lua_State* L) {
   1857     get_ref<SkPicture>(L, 1)->unref();
   1858     return 0;
   1859 }
   1860 
   1861 static const struct luaL_Reg gSkPicture_Methods[] = {
   1862     { "width", lpicture_width },
   1863     { "height", lpicture_height },
   1864     { "__gc", lpicture_gc },
   1865     { nullptr, nullptr }
   1866 };
   1867 
   1868 ///////////////////////////////////////////////////////////////////////////////
   1869 
   1870 static int ltextblob_bounds(lua_State* L) {
   1871     SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
   1872     return 1;
   1873 }
   1874 
   1875 static int ltextblob_gc(lua_State* L) {
   1876     SkSafeUnref(get_ref<SkTextBlob>(L, 1));
   1877     return 0;
   1878 }
   1879 
   1880 static const struct luaL_Reg gSkTextBlob_Methods[] = {
   1881     { "bounds", ltextblob_bounds },
   1882     { "__gc", ltextblob_gc },
   1883     { nullptr, nullptr }
   1884 };
   1885 
   1886 ///////////////////////////////////////////////////////////////////////////////
   1887 
   1888 static int ltypeface_getFamilyName(lua_State* L) {
   1889     SkString str;
   1890     get_ref<SkTypeface>(L, 1)->getFamilyName(&str);
   1891     lua_pushstring(L, str.c_str());
   1892     return 1;
   1893 }
   1894 
   1895 static int ltypeface_getStyle(lua_State* L) {
   1896     lua_pushnumber(L, (double)get_ref<SkTypeface>(L, 1)->style());
   1897     return 1;
   1898 }
   1899 
   1900 static int ltypeface_gc(lua_State* L) {
   1901     SkSafeUnref(get_ref<SkTypeface>(L, 1));
   1902     return 0;
   1903 }
   1904 
   1905 static const struct luaL_Reg gSkTypeface_Methods[] = {
   1906     { "getFamilyName", ltypeface_getFamilyName },
   1907     { "getStyle", ltypeface_getStyle },
   1908     { "__gc", ltypeface_gc },
   1909     { nullptr, nullptr }
   1910 };
   1911 
   1912 ///////////////////////////////////////////////////////////////////////////////
   1913 
   1914 class AutoCallLua {
   1915 public:
   1916     AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
   1917         lua_getglobal(L, func);
   1918         if (!lua_isfunction(L, -1)) {
   1919             int t = lua_type(L, -1);
   1920             SkDebugf("--- expected function %d\n", t);
   1921         }
   1922 
   1923         lua_newtable(L);
   1924         setfield_string(L, "verb", verb);
   1925     }
   1926 
   1927     ~AutoCallLua() {
   1928         if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
   1929             SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
   1930         }
   1931         lua_settop(fL, -1);
   1932     }
   1933 
   1934 private:
   1935     lua_State* fL;
   1936 };
   1937 
   1938 #define AUTO_LUA(verb)  AutoCallLua acl(fL, fFunc.c_str(), verb)
   1939 
   1940 ///////////////////////////////////////////////////////////////////////////////
   1941 
   1942 static int lsk_newDocumentPDF(lua_State* L) {
   1943     const char* file = nullptr;
   1944     if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
   1945         file = lua_tolstring(L, 1, nullptr);
   1946     }
   1947 
   1948     SkDocument* doc = SkDocument::CreatePDF(file);
   1949     if (nullptr == doc) {
   1950         // do I need to push a nil on the stack and return 1?
   1951         return 0;
   1952     } else {
   1953         push_ref(L, doc)->unref();
   1954         return 1;
   1955     }
   1956 }
   1957 
   1958 static int lsk_newBlurImageFilter(lua_State* L) {
   1959     SkScalar sigmaX = lua2scalar_def(L, 1, 0);
   1960     SkScalar sigmaY = lua2scalar_def(L, 2, 0);
   1961     SkImageFilter* imf = SkBlurImageFilter::Create(sigmaX, sigmaY);
   1962     if (nullptr == imf) {
   1963         lua_pushnil(L);
   1964     } else {
   1965         push_ref(L, imf)->unref();
   1966     }
   1967     return 1;
   1968 }
   1969 
   1970 static int lsk_newLinearGradient(lua_State* L) {
   1971     SkScalar x0 = lua2scalar_def(L, 1, 0);
   1972     SkScalar y0 = lua2scalar_def(L, 2, 0);
   1973     SkColor  c0 = lua2color(L, 3);
   1974     SkScalar x1 = lua2scalar_def(L, 4, 0);
   1975     SkScalar y1 = lua2scalar_def(L, 5, 0);
   1976     SkColor  c1 = lua2color(L, 6);
   1977 
   1978     SkPoint pts[] = { { x0, y0 }, { x1, y1 } };
   1979     SkColor colors[] = { c0, c1 };
   1980     SkShader* s = SkGradientShader::CreateLinear(pts, colors, nullptr, 2, SkShader::kClamp_TileMode);
   1981     if (nullptr == s) {
   1982         lua_pushnil(L);
   1983     } else {
   1984         push_ref(L, s)->unref();
   1985     }
   1986     return 1;
   1987 }
   1988 
   1989 static int lsk_newMatrix(lua_State* L) {
   1990     push_new<SkMatrix>(L)->reset();
   1991     return 1;
   1992 }
   1993 
   1994 static int lsk_newPaint(lua_State* L) {
   1995     push_new<SkPaint>(L);
   1996     return 1;
   1997 }
   1998 
   1999 static int lsk_newPath(lua_State* L) {
   2000     push_new<SkPath>(L);
   2001     return 1;
   2002 }
   2003 
   2004 static int lsk_newPictureRecorder(lua_State* L) {
   2005     push_new<SkPictureRecorder>(L);
   2006     return 1;
   2007 }
   2008 
   2009 static int lsk_newRRect(lua_State* L) {
   2010     push_new<SkRRect>(L)->setEmpty();
   2011     return 1;
   2012 }
   2013 
   2014 #include "SkTextBox.h"
   2015 // Sk.newTextBlob(text, rect, paint)
   2016 static int lsk_newTextBlob(lua_State* L) {
   2017     const char* text = lua_tolstring(L, 1, nullptr);
   2018     SkRect bounds;
   2019     lua2rect(L, 2, &bounds);
   2020     const SkPaint& paint = *get_obj<SkPaint>(L, 3);
   2021 
   2022     SkTextBox box;
   2023     box.setMode(SkTextBox::kLineBreak_Mode);
   2024     box.setBox(bounds);
   2025     box.setText(text, strlen(text), paint);
   2026 
   2027     SkScalar newBottom;
   2028     SkAutoTUnref<SkTextBlob> blob(box.snapshotTextBlob(&newBottom));
   2029     push_ref<SkTextBlob>(L, blob);
   2030     SkLua(L).pushScalar(newBottom);
   2031     return 2;
   2032 }
   2033 
   2034 static int lsk_newTypeface(lua_State* L) {
   2035     const char* name = nullptr;
   2036     int style = SkTypeface::kNormal;
   2037 
   2038     int count = lua_gettop(L);
   2039     if (count > 0 && lua_isstring(L, 1)) {
   2040         name = lua_tolstring(L, 1, nullptr);
   2041         if (count > 1 && lua_isnumber(L, 2)) {
   2042             style = lua_tointegerx(L, 2, nullptr) & SkTypeface::kBoldItalic;
   2043         }
   2044     }
   2045 
   2046     SkTypeface* face = SkTypeface::CreateFromName(name,
   2047                                                   (SkTypeface::Style)style);
   2048 //    SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
   2049     if (nullptr == face) {
   2050         face = SkTypeface::RefDefault();
   2051     }
   2052     push_ref(L, face)->unref();
   2053     return 1;
   2054 }
   2055 
   2056 static int lsk_newRasterSurface(lua_State* L) {
   2057     int width = lua2int_def(L, 1, 0);
   2058     int height = lua2int_def(L, 2, 0);
   2059     SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
   2060     SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
   2061     SkSurface* surface = SkSurface::NewRaster(info, &props);
   2062     if (nullptr == surface) {
   2063         lua_pushnil(L);
   2064     } else {
   2065         push_ref(L, surface)->unref();
   2066     }
   2067     return 1;
   2068 }
   2069 
   2070 static int lsk_loadImage(lua_State* L) {
   2071     if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
   2072         const char* name = lua_tolstring(L, 1, nullptr);
   2073         SkAutoDataUnref data(SkData::NewFromFileName(name));
   2074         if (data.get()) {
   2075             SkImage* image = SkImage::NewFromEncoded(data);
   2076             if (image) {
   2077                 push_ref(L, image)->unref();
   2078                 return 1;
   2079             }
   2080         }
   2081     }
   2082     return 0;
   2083 }
   2084 
   2085 static void register_Sk(lua_State* L) {
   2086     lua_newtable(L);
   2087     lua_pushvalue(L, -1);
   2088     lua_setglobal(L, "Sk");
   2089     // the Sk table is still on top
   2090 
   2091     setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
   2092     setfield_function(L, "loadImage", lsk_loadImage);
   2093     setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
   2094     setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
   2095     setfield_function(L, "newMatrix", lsk_newMatrix);
   2096     setfield_function(L, "newPaint", lsk_newPaint);
   2097     setfield_function(L, "newPath", lsk_newPath);
   2098     setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
   2099     setfield_function(L, "newRRect", lsk_newRRect);
   2100     setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
   2101     setfield_function(L, "newTextBlob", lsk_newTextBlob);
   2102     setfield_function(L, "newTypeface", lsk_newTypeface);
   2103     lua_pop(L, 1);  // pop off the Sk table
   2104 }
   2105 
   2106 #define REG_CLASS(L, C)                             \
   2107     do {                                            \
   2108         luaL_newmetatable(L, get_mtname<C>());      \
   2109         lua_pushvalue(L, -1);                       \
   2110         lua_setfield(L, -2, "__index");             \
   2111         luaL_setfuncs(L, g##C##_Methods, 0);        \
   2112         lua_pop(L, 1); /* pop off the meta-table */ \
   2113     } while (0)
   2114 
   2115 void SkLua::Load(lua_State* L) {
   2116     register_Sk(L);
   2117     REG_CLASS(L, SkCanvas);
   2118     REG_CLASS(L, SkColorFilter);
   2119     REG_CLASS(L, SkDocument);
   2120     REG_CLASS(L, SkImage);
   2121     REG_CLASS(L, SkImageFilter);
   2122     REG_CLASS(L, SkMatrix);
   2123     REG_CLASS(L, SkPaint);
   2124     REG_CLASS(L, SkPath);
   2125     REG_CLASS(L, SkPathEffect);
   2126     REG_CLASS(L, SkPicture);
   2127     REG_CLASS(L, SkPictureRecorder);
   2128     REG_CLASS(L, SkRRect);
   2129     REG_CLASS(L, SkShader);
   2130     REG_CLASS(L, SkSurface);
   2131     REG_CLASS(L, SkTextBlob);
   2132     REG_CLASS(L, SkTypeface);
   2133     REG_CLASS(L, SkXfermode);
   2134 }
   2135 
   2136 extern "C" int luaopen_skia(lua_State* L);
   2137 extern "C" int luaopen_skia(lua_State* L) {
   2138     SkLua::Load(L);
   2139     return 0;
   2140 }
   2141