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