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