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