|  | /* | 
|  | * Copyright 2013 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "SampleCode.h" | 
|  | #include "SkView.h" | 
|  | #include "SkLua.h" | 
|  | #include "SkCanvas.h" | 
|  | #include "Resources.h" | 
|  | #include "SkData.h" | 
|  |  | 
|  | extern "C" { | 
|  | #include "lua.h" | 
|  | #include "lualib.h" | 
|  | #include "lauxlib.h" | 
|  | } | 
|  |  | 
|  | //#define LUA_FILENAME    "test.lua" | 
|  | #define LUA_FILENAME    "slides.lua" | 
|  |  | 
|  | static const char gDrawName[] = "onDrawContent"; | 
|  | static const char gClickName[] = "onClickHandler"; | 
|  | static const char gUnicharName[] = "onCharHandler"; | 
|  |  | 
|  | static const char gLuaClickHandlerName[] = "lua-click-handler"; | 
|  |  | 
|  | static const char gMissingCode[] = "" | 
|  | "local paint = Sk.newPaint()" | 
|  | "paint:setAntiAlias(true)" | 
|  | "paint:setTextSize(30)" | 
|  | "" | 
|  | "function onDrawContent(canvas)" | 
|  | "   canvas:drawText('missing \"test.lua\"', 20, 50, paint)" | 
|  | "end" | 
|  | ; | 
|  |  | 
|  | class LuaView : public SampleView { | 
|  | public: | 
|  | LuaView() : fLua(nullptr) {} | 
|  |  | 
|  | virtual ~LuaView() { delete fLua; } | 
|  |  | 
|  | void setImageFilename(lua_State* L) { | 
|  | SkString str = GetResourcePath("mandrill_256.png"); | 
|  |  | 
|  | lua_getglobal(L, "setImageFilename"); | 
|  | if (lua_isfunction(L, -1)) { | 
|  | fLua->pushString(str.c_str()); | 
|  | if (lua_pcall(L, 1, 0, 0) != LUA_OK) { | 
|  | SkDebugf("lua err: %s\n", lua_tostring(L, -1)); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | lua_State* ensureLua() { | 
|  | if (nullptr == fLua) { | 
|  | fLua = new SkLua; | 
|  |  | 
|  | SkString str = GetResourcePath(LUA_FILENAME); | 
|  | SkData* data = SkData::NewFromFileName(str.c_str()); | 
|  | if (data) { | 
|  | fLua->runCode(data->data(), data->size()); | 
|  | data->unref(); | 
|  | this->setImageFilename(fLua->get()); | 
|  | } else { | 
|  | fLua->runCode(gMissingCode); | 
|  | } | 
|  | } | 
|  | return fLua->get(); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | bool onQuery(SkEvent* evt) override { | 
|  | if (SampleCode::TitleQ(*evt)) { | 
|  | SampleCode::TitleR(evt, "Lua"); | 
|  | return true; | 
|  | } | 
|  | SkUnichar uni; | 
|  | if (SampleCode::CharQ(*evt, &uni)) { | 
|  | lua_State* L = this->ensureLua(); | 
|  | lua_getglobal(L, gUnicharName); | 
|  | if (lua_isfunction(L, -1)) { | 
|  | SkString str; | 
|  | str.appendUnichar(uni); | 
|  | fLua->pushString(str.c_str()); | 
|  | if (lua_pcall(L, 1, 1, 0) != LUA_OK) { | 
|  | SkDebugf("lua err: %s\n", lua_tostring(L, -1)); | 
|  | } else { | 
|  | if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) { | 
|  | this->inval(nullptr); | 
|  | return true; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | return this->INHERITED::onQuery(evt); | 
|  | } | 
|  |  | 
|  | void onDrawContent(SkCanvas* canvas) override { | 
|  | lua_State* L = this->ensureLua(); | 
|  |  | 
|  | lua_getglobal(L, gDrawName); | 
|  | if (!lua_isfunction(L, -1)) { | 
|  | int t = lua_type(L, -1); | 
|  | SkDebugf("--- expected %s function %d, ignoring.\n", gDrawName, t); | 
|  | lua_pop(L, 1); | 
|  | } else { | 
|  | // does it make sense to try to "cache" the lua version of this | 
|  | // canvas between draws? | 
|  | fLua->pushCanvas(canvas); | 
|  | fLua->pushScalar(this->width()); | 
|  | fLua->pushScalar(this->height()); | 
|  | if (lua_pcall(L, 3, 1, 0) != LUA_OK) { | 
|  | SkDebugf("lua err: %s\n", lua_tostring(L, -1)); | 
|  | } else { | 
|  | if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) { | 
|  | this->inval(nullptr); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, | 
|  | unsigned modi) override { | 
|  | lua_State* L = this->ensureLua(); | 
|  | lua_getglobal(L, gClickName); | 
|  | if (lua_isfunction(L, -1)) { | 
|  | fLua->pushScalar(x); | 
|  | fLua->pushScalar(y); | 
|  | fLua->pushString("down"); | 
|  | if (lua_pcall(L, 3, 1, 0) != LUA_OK) { | 
|  | SkDebugf("lua err: %s\n", lua_tostring(L, -1)); | 
|  | } else { | 
|  | if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) { | 
|  | this->inval(nullptr); | 
|  | Click* c = new Click(this); | 
|  | c->setType(gLuaClickHandlerName); | 
|  | return c; | 
|  | } | 
|  | } | 
|  | } | 
|  | return this->INHERITED::onFindClickHandler(x, y, modi); | 
|  | } | 
|  |  | 
|  | bool onClick(Click* click) override { | 
|  | if (click->getType() != gLuaClickHandlerName) { | 
|  | return this->INHERITED::onClick(click); | 
|  | } | 
|  |  | 
|  | const char* state = nullptr; | 
|  | switch (click->fState) { | 
|  | case Click::kMoved_State: | 
|  | state = "moved"; | 
|  | break; | 
|  | case Click::kUp_State: | 
|  | state = "up"; | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | if (state) { | 
|  | this->inval(nullptr); | 
|  | lua_State* L = fLua->get(); | 
|  | lua_getglobal(L, gClickName); | 
|  | fLua->pushScalar(click->fCurr.x()); | 
|  | fLua->pushScalar(click->fCurr.y()); | 
|  | fLua->pushString(state); | 
|  | lua_pcall(L, 3, 1, 0); | 
|  | return lua_isboolean(L, -1) && lua_toboolean(L, -1); | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | private: | 
|  | SkLua* fLua; | 
|  |  | 
|  | typedef SampleView INHERITED; | 
|  | }; | 
|  |  | 
|  | ////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | static SkView* MyFactory() { return new LuaView; } | 
|  | static SkViewRegister reg(MyFactory); |