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