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