• 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 "Sample.h"
9 #include "SkLua.h"
10 #include "SkCanvas.h"
11 #include "Resources.h"
12 #include "SkData.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:
onQuery(Sample::Event * evt)71     bool onQuery(Sample::Event* evt) override {
72         if (Sample::TitleQ(*evt)) {
73             Sample::TitleR(evt, "Lua");
74             return true;
75         }
76         SkUnichar uni;
77         if (Sample::CharQ(*evt, &uni)) {
78             lua_State* L = this->ensureLua();
79             lua_getglobal(L, gUnicharName);
80             if (lua_isfunction(L, -1)) {
81                 SkString str;
82                 str.appendUnichar(uni);
83                 fLua->pushString(str.c_str());
84                 if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
85                     SkDebugf("lua err: %s\n", lua_tostring(L, -1));
86                 } else {
87                     if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
88                         return true;
89                     }
90                 }
91             }
92         }
93         return this->INHERITED::onQuery(evt);
94     }
95 
onDrawContent(SkCanvas * canvas)96     void onDrawContent(SkCanvas* canvas) override {
97         lua_State* L = this->ensureLua();
98 
99         lua_getglobal(L, gDrawName);
100         if (!lua_isfunction(L, -1)) {
101             int t = lua_type(L, -1);
102             SkDebugf("--- expected %s function %d, ignoring.\n", gDrawName, t);
103             lua_pop(L, 1);
104         } else {
105             // does it make sense to try to "cache" the lua version of this
106             // canvas between draws?
107             fLua->pushCanvas(canvas);
108             fLua->pushScalar(this->width());
109             fLua->pushScalar(this->height());
110             if (lua_pcall(L, 3, 1, 0) != LUA_OK) {
111                 SkDebugf("lua err: %s\n", lua_tostring(L, -1));
112             }
113         }
114     }
115 
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)116     virtual Sample::Click* onFindClickHandler(SkScalar x, SkScalar y,
117                                               unsigned modi) override {
118         lua_State* L = this->ensureLua();
119         lua_getglobal(L, gClickName);
120         if (lua_isfunction(L, -1)) {
121             fLua->pushScalar(x);
122             fLua->pushScalar(y);
123             fLua->pushString("down");
124             if (lua_pcall(L, 3, 1, 0) != LUA_OK) {
125                 SkDebugf("lua err: %s\n", lua_tostring(L, -1));
126             } else {
127                 if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
128                     return new Click(this);
129                 }
130             }
131         }
132         return this->INHERITED::onFindClickHandler(x, y, modi);
133     }
134 
onClick(Click * click)135     bool onClick(Click* click) override {
136         const char* state = nullptr;
137         switch (click->fState) {
138             case Click::kMoved_State:
139                 state = "moved";
140                 break;
141             case Click::kUp_State:
142                 state = "up";
143                 break;
144             default:
145                 break;
146         }
147         if (state) {
148             lua_State* L = fLua->get();
149             lua_getglobal(L, gClickName);
150             fLua->pushScalar(click->fCurr.x());
151             fLua->pushScalar(click->fCurr.y());
152             fLua->pushString(state);
153             lua_pcall(L, 3, 1, 0);
154             return lua_isboolean(L, -1) && lua_toboolean(L, -1);
155         }
156         return true;
157     }
158 
159 private:
160     SkLua* fLua;
161 
162     typedef Sample INHERITED;
163 };
164 
165 //////////////////////////////////////////////////////////////////////////////
166 
167 DEF_SAMPLE( return new LuaView(); )
168