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