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) 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) 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) 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) 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); 189