Home | History | Annotate | Download | only in samplecode
      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 "SampleCode.h"
      9 #include "SkView.h"
     10 #include "SkLua.h"
     11 #include "SkCanvas.h"
     12 #include "Resources.h"
     13 #include "SkData.h"
     14 
     15 extern "C" {
     16 #include "lua.h"
     17 #include "lualib.h"
     18 #include "lauxlib.h"
     19 }
     20 
     21 //#define LUA_FILENAME    "test.lua"
     22 #define LUA_FILENAME    "slides.lua"
     23 
     24 static const char gDrawName[] = "onDrawContent";
     25 static const char gClickName[] = "onClickHandler";
     26 static const char gUnicharName[] = "onCharHandler";
     27 
     28 static const char gLuaClickHandlerName[] = "lua-click-handler";
     29 
     30 static const char gMissingCode[] = ""
     31     "local paint = Sk.newPaint()"
     32     "paint:setAntiAlias(true)"
     33     "paint:setTextSize(30)"
     34     ""
     35     "function onDrawContent(canvas)"
     36     "   canvas:drawText('missing \"test.lua\"', 20, 50, paint)"
     37     "end"
     38     ;
     39 
     40 class LuaView : public SampleView {
     41 public:
     42     LuaView() : fLua(nullptr) {}
     43 
     44     virtual ~LuaView() { delete fLua; }
     45 
     46     void setImageFilename(lua_State* L) {
     47         SkString str = GetResourcePath("mandrill_256.png");
     48 
     49         lua_getglobal(L, "setImageFilename");
     50         if (lua_isfunction(L, -1)) {
     51             fLua->pushString(str.c_str());
     52             if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
     53                 SkDebugf("lua err: %s\n", lua_tostring(L, -1));
     54             }
     55         }
     56     }
     57 
     58     lua_State* ensureLua() {
     59         if (nullptr == fLua) {
     60             fLua = new SkLua;
     61 
     62             SkString str = GetResourcePath(LUA_FILENAME);
     63             sk_sp<SkData> data(SkData::MakeFromFileName(str.c_str()));
     64             if (data) {
     65                 fLua->runCode(data->data(), data->size());
     66                 this->setImageFilename(fLua->get());
     67             } else {
     68                 fLua->runCode(gMissingCode);
     69             }
     70         }
     71         return fLua->get();
     72     }
     73 
     74 protected:
     75     bool onQuery(SkEvent* evt) override {
     76         if (SampleCode::TitleQ(*evt)) {
     77             SampleCode::TitleR(evt, "Lua");
     78             return true;
     79         }
     80         SkUnichar uni;
     81         if (SampleCode::CharQ(*evt, &uni)) {
     82             lua_State* L = this->ensureLua();
     83             lua_getglobal(L, gUnicharName);
     84             if (lua_isfunction(L, -1)) {
     85                 SkString str;
     86                 str.appendUnichar(uni);
     87                 fLua->pushString(str.c_str());
     88                 if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
     89                     SkDebugf("lua err: %s\n", lua_tostring(L, -1));
     90                 } else {
     91                     if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
     92                         this->inval(nullptr);
     93                         return true;
     94                     }
     95                 }
     96             }
     97         }
     98         return this->INHERITED::onQuery(evt);
     99     }
    100 
    101     void onDrawContent(SkCanvas* canvas) override {
    102         lua_State* L = this->ensureLua();
    103 
    104         lua_getglobal(L, gDrawName);
    105         if (!lua_isfunction(L, -1)) {
    106             int t = lua_type(L, -1);
    107             SkDebugf("--- expected %s function %d, ignoring.\n", gDrawName, t);
    108             lua_pop(L, 1);
    109         } else {
    110             // does it make sense to try to "cache" the lua version of this
    111             // canvas between draws?
    112             fLua->pushCanvas(canvas);
    113             fLua->pushScalar(this->width());
    114             fLua->pushScalar(this->height());
    115             if (lua_pcall(L, 3, 1, 0) != LUA_OK) {
    116                 SkDebugf("lua err: %s\n", lua_tostring(L, -1));
    117             } else {
    118                 if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
    119                     this->inval(nullptr);
    120                 }
    121             }
    122         }
    123     }
    124 
    125     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
    126                                               unsigned modi) override {
    127         lua_State* L = this->ensureLua();
    128         lua_getglobal(L, gClickName);
    129         if (lua_isfunction(L, -1)) {
    130             fLua->pushScalar(x);
    131             fLua->pushScalar(y);
    132             fLua->pushString("down");
    133             if (lua_pcall(L, 3, 1, 0) != LUA_OK) {
    134                 SkDebugf("lua err: %s\n", lua_tostring(L, -1));
    135             } else {
    136                 if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
    137                     this->inval(nullptr);
    138                     Click* c = new Click(this);
    139                     c->setType(gLuaClickHandlerName);
    140                     return c;
    141                 }
    142             }
    143         }
    144         return this->INHERITED::onFindClickHandler(x, y, modi);
    145     }
    146 
    147     bool onClick(Click* click) override {
    148         if (click->getType() != gLuaClickHandlerName) {
    149             return this->INHERITED::onClick(click);
    150         }
    151 
    152         const char* state = nullptr;
    153         switch (click->fState) {
    154             case Click::kMoved_State:
    155                 state = "moved";
    156                 break;
    157             case Click::kUp_State:
    158                 state = "up";
    159                 break;
    160             default:
    161                 break;
    162         }
    163         if (state) {
    164             this->inval(nullptr);
    165             lua_State* L = fLua->get();
    166             lua_getglobal(L, gClickName);
    167             fLua->pushScalar(click->fCurr.x());
    168             fLua->pushScalar(click->fCurr.y());
    169             fLua->pushString(state);
    170             lua_pcall(L, 3, 1, 0);
    171             return lua_isboolean(L, -1) && lua_toboolean(L, -1);
    172         }
    173         return true;
    174     }
    175 
    176 private:
    177     SkLua* fLua;
    178 
    179     typedef SampleView INHERITED;
    180 };
    181 
    182 //////////////////////////////////////////////////////////////////////////////
    183 
    184 static SkView* MyFactory() { return new LuaView; }
    185 static SkViewRegister reg(MyFactory);
    186