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