f21c7de5d8580b9eccca28ca641ae89a2b385848
[platform/upstream/libSkiaSharp.git] / samplecode / SampleLua.cpp
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) SK_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) SK_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) SK_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) SK_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);