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