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             SkData* data = SkData::NewFromFileName(str.c_str());
     64             if (data) {
     65                 fLua->runCode(data->data(), data->size());
     66                 data->unref();
     67                 this->setImageFilename(fLua->get());
     68             } else {
     69                 fLua->runCode(gMissingCode);
     70             }
     71         }
     72         return fLua->get();
     73     }
     74 
     75 protected:
     76     bool onQuery(SkEvent* evt) override {
     77         if (SampleCode::TitleQ(*evt)) {
     78             SampleCode::TitleR(evt, "Lua");
     79             return true;
     80         }
     81         SkUnichar uni;
     82         if (SampleCode::CharQ(*evt, &uni)) {
     83             lua_State* L = this->ensureLua();
     84             lua_getglobal(L, gUnicharName);
     85             if (lua_isfunction(L, -1)) {
     86                 SkString str;
     87                 str.appendUnichar(uni);
     88                 fLua->pushString(str.c_str());
     89                 if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
     90                     SkDebugf("lua err: %s\n", lua_tostring(L, -1));
     91                 } else {
     92                     if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
     93                         this->inval(nullptr);
     94                         return true;
     95                     }
     96                 }
     97             }
     98         }
     99         return this->INHERITED::onQuery(evt);
    100     }
    101 
    102     void onDrawContent(SkCanvas* canvas) override {
    103         lua_State* L = this->ensureLua();
    104 
    105         lua_getglobal(L, gDrawName);
    106         if (!lua_isfunction(L, -1)) {
    107             int t = lua_type(L, -1);
    108             SkDebugf("--- expected %s function %d, ignoring.\n", gDrawName, t);
    109             lua_pop(L, 1);
    110         } else {
    111             // does it make sense to try to "cache" the lua version of this
    112             // canvas between draws?
    113             fLua->pushCanvas(canvas);
    114             fLua->pushScalar(this->width());
    115             fLua->pushScalar(this->height());
    116             if (lua_pcall(L, 3, 1, 0) != LUA_OK) {
    117                 SkDebugf("lua err: %s\n", lua_tostring(L, -1));
    118             } else {
    119                 if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
    120                     this->inval(nullptr);
    121                 }
    122             }
    123         }
    124     }
    125 
    126     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
    127                                               unsigned modi) override {
    128         lua_State* L = this->ensureLua();
    129         lua_getglobal(L, gClickName);
    130         if (lua_isfunction(L, -1)) {
    131             fLua->pushScalar(x);
    132             fLua->pushScalar(y);
    133             fLua->pushString("down");
    134             if (lua_pcall(L, 3, 1, 0) != LUA_OK) {
    135                 SkDebugf("lua err: %s\n", lua_tostring(L, -1));
    136             } else {
    137                 if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
    138                     this->inval(nullptr);
    139                     Click* c = new Click(this);
    140                     c->setType(gLuaClickHandlerName);
    141                     return c;
    142                 }
    143             }
    144         }
    145         return this->INHERITED::onFindClickHandler(x, y, modi);
    146     }
    147 
    148     bool onClick(Click* click) override {
    149         if (click->getType() != gLuaClickHandlerName) {
    150             return this->INHERITED::onClick(click);
    151         }
    152 
    153         const char* state = nullptr;
    154         switch (click->fState) {
    155             case Click::kMoved_State:
    156                 state = "moved";
    157                 break;
    158             case Click::kUp_State:
    159                 state = "up";
    160                 break;
    161             default:
    162                 break;
    163         }
    164         if (state) {
    165             this->inval(nullptr);
    166             lua_State* L = fLua->get();
    167             lua_getglobal(L, gClickName);
    168             fLua->pushScalar(click->fCurr.x());
    169             fLua->pushScalar(click->fCurr.y());
    170             fLua->pushString(state);
    171             lua_pcall(L, 3, 1, 0);
    172             return lua_isboolean(L, -1) && lua_toboolean(L, -1);
    173         }
    174         return true;
    175     }
    176 
    177 private:
    178     SkLua* fLua;
    179 
    180     typedef SampleView INHERITED;
    181 };
    182 
    183 //////////////////////////////////////////////////////////////////////////////
    184 
    185 static SkView* MyFactory() { return new LuaView; }
    186 static SkViewRegister reg(MyFactory);
    187