1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/SkLua.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1433 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkLua.h" 1.12 + 1.13 +#if SK_SUPPORT_GPU 1.14 +#include "GrReducedClip.h" 1.15 +#endif 1.16 + 1.17 +#include "SkCanvas.h" 1.18 +#include "SkData.h" 1.19 +#include "SkDocument.h" 1.20 +#include "SkImage.h" 1.21 +#include "SkMatrix.h" 1.22 +#include "SkPaint.h" 1.23 +#include "SkPath.h" 1.24 +#include "SkPixelRef.h" 1.25 +#include "SkRRect.h" 1.26 +#include "SkString.h" 1.27 +#include "SkTypeface.h" 1.28 + 1.29 +extern "C" { 1.30 + #include "lua.h" 1.31 + #include "lualib.h" 1.32 + #include "lauxlib.h" 1.33 +} 1.34 + 1.35 +// return the metatable name for a given class 1.36 +template <typename T> const char* get_mtname(); 1.37 +#define DEF_MTNAME(T) \ 1.38 + template <> const char* get_mtname<T>() { \ 1.39 + return #T "_LuaMetaTableName"; \ 1.40 + } 1.41 + 1.42 +DEF_MTNAME(SkCanvas) 1.43 +DEF_MTNAME(SkDocument) 1.44 +DEF_MTNAME(SkImage) 1.45 +DEF_MTNAME(SkMatrix) 1.46 +DEF_MTNAME(SkRRect) 1.47 +DEF_MTNAME(SkPath) 1.48 +DEF_MTNAME(SkPaint) 1.49 +DEF_MTNAME(SkShader) 1.50 +DEF_MTNAME(SkTypeface) 1.51 + 1.52 +template <typename T> T* push_new(lua_State* L) { 1.53 + T* addr = (T*)lua_newuserdata(L, sizeof(T)); 1.54 + new (addr) T; 1.55 + luaL_getmetatable(L, get_mtname<T>()); 1.56 + lua_setmetatable(L, -2); 1.57 + return addr; 1.58 +} 1.59 + 1.60 +template <typename T> void push_obj(lua_State* L, const T& obj) { 1.61 + new (lua_newuserdata(L, sizeof(T))) T(obj); 1.62 + luaL_getmetatable(L, get_mtname<T>()); 1.63 + lua_setmetatable(L, -2); 1.64 +} 1.65 + 1.66 +template <typename T> void push_ref(lua_State* L, T* ref) { 1.67 + *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref); 1.68 + luaL_getmetatable(L, get_mtname<T>()); 1.69 + lua_setmetatable(L, -2); 1.70 +} 1.71 + 1.72 +template <typename T> T* get_ref(lua_State* L, int index) { 1.73 + return *(T**)luaL_checkudata(L, index, get_mtname<T>()); 1.74 +} 1.75 + 1.76 +template <typename T> T* get_obj(lua_State* L, int index) { 1.77 + return (T*)luaL_checkudata(L, index, get_mtname<T>()); 1.78 +} 1.79 + 1.80 +static bool lua2bool(lua_State* L, int index) { 1.81 + return !!lua_toboolean(L, index); 1.82 +} 1.83 + 1.84 +/////////////////////////////////////////////////////////////////////////////// 1.85 + 1.86 +SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) { 1.87 + fL = luaL_newstate(); 1.88 + luaL_openlibs(fL); 1.89 + SkLua::Load(fL); 1.90 +} 1.91 + 1.92 +SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {} 1.93 + 1.94 +SkLua::~SkLua() { 1.95 + if (fWeOwnL) { 1.96 + if (fTermCode.size() > 0) { 1.97 + lua_getglobal(fL, fTermCode.c_str()); 1.98 + if (lua_pcall(fL, 0, 0, 0) != LUA_OK) { 1.99 + SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); 1.100 + } 1.101 + } 1.102 + lua_close(fL); 1.103 + } 1.104 +} 1.105 + 1.106 +bool SkLua::runCode(const char code[]) { 1.107 + int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0); 1.108 + if (err) { 1.109 + SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1)); 1.110 + return false; 1.111 + } 1.112 + return true; 1.113 +} 1.114 + 1.115 +bool SkLua::runCode(const void* code, size_t size) { 1.116 + SkString str((const char*)code, size); 1.117 + return this->runCode(str.c_str()); 1.118 +} 1.119 + 1.120 +/////////////////////////////////////////////////////////////////////////////// 1.121 + 1.122 +#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0) 1.123 + 1.124 +static void setfield_bool_if(lua_State* L, const char key[], bool pred) { 1.125 + if (pred) { 1.126 + lua_pushboolean(L, true); 1.127 + lua_setfield(L, -2, key); 1.128 + } 1.129 +} 1.130 + 1.131 +static void setfield_string(lua_State* L, const char key[], const char value[]) { 1.132 + lua_pushstring(L, value); 1.133 + lua_setfield(L, -2, key); 1.134 +} 1.135 + 1.136 +static void setfield_number(lua_State* L, const char key[], double value) { 1.137 + lua_pushnumber(L, value); 1.138 + lua_setfield(L, -2, key); 1.139 +} 1.140 + 1.141 +static void setfield_boolean(lua_State* L, const char key[], bool value) { 1.142 + lua_pushboolean(L, value); 1.143 + lua_setfield(L, -2, key); 1.144 +} 1.145 + 1.146 +static void setfield_scalar(lua_State* L, const char key[], SkScalar value) { 1.147 + setfield_number(L, key, SkScalarToLua(value)); 1.148 +} 1.149 + 1.150 +static void setfield_function(lua_State* L, 1.151 + const char key[], lua_CFunction value) { 1.152 + lua_pushcfunction(L, value); 1.153 + lua_setfield(L, -2, key); 1.154 +} 1.155 + 1.156 +static void setarray_number(lua_State* L, int index, double value) { 1.157 + lua_pushnumber(L, value); 1.158 + lua_rawseti(L, -2, index); 1.159 +} 1.160 + 1.161 +void SkLua::pushBool(bool value, const char key[]) { 1.162 + lua_pushboolean(fL, value); 1.163 + CHECK_SETFIELD(key); 1.164 +} 1.165 + 1.166 +void SkLua::pushString(const char str[], const char key[]) { 1.167 + lua_pushstring(fL, str); 1.168 + CHECK_SETFIELD(key); 1.169 +} 1.170 + 1.171 +void SkLua::pushString(const char str[], size_t length, const char key[]) { 1.172 + // TODO: how to do this w/o making a copy? 1.173 + SkString s(str, length); 1.174 + lua_pushstring(fL, s.c_str()); 1.175 + CHECK_SETFIELD(key); 1.176 +} 1.177 + 1.178 +void SkLua::pushString(const SkString& str, const char key[]) { 1.179 + lua_pushstring(fL, str.c_str()); 1.180 + CHECK_SETFIELD(key); 1.181 +} 1.182 + 1.183 +void SkLua::pushColor(SkColor color, const char key[]) { 1.184 + lua_newtable(fL); 1.185 + setfield_number(fL, "a", SkColorGetA(color) / 255.0); 1.186 + setfield_number(fL, "r", SkColorGetR(color) / 255.0); 1.187 + setfield_number(fL, "g", SkColorGetG(color) / 255.0); 1.188 + setfield_number(fL, "b", SkColorGetB(color) / 255.0); 1.189 + CHECK_SETFIELD(key); 1.190 +} 1.191 + 1.192 +void SkLua::pushU32(uint32_t value, const char key[]) { 1.193 + lua_pushnumber(fL, (double)value); 1.194 + CHECK_SETFIELD(key); 1.195 +} 1.196 + 1.197 +void SkLua::pushScalar(SkScalar value, const char key[]) { 1.198 + lua_pushnumber(fL, SkScalarToLua(value)); 1.199 + CHECK_SETFIELD(key); 1.200 +} 1.201 + 1.202 +void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) { 1.203 + lua_newtable(fL); 1.204 + for (int i = 0; i < count; ++i) { 1.205 + // make it base-1 to match lua convention 1.206 + setarray_number(fL, i + 1, (double)array[i]); 1.207 + } 1.208 + CHECK_SETFIELD(key); 1.209 +} 1.210 + 1.211 +void SkLua::pushRect(const SkRect& r, const char key[]) { 1.212 + lua_newtable(fL); 1.213 + setfield_scalar(fL, "left", r.fLeft); 1.214 + setfield_scalar(fL, "top", r.fTop); 1.215 + setfield_scalar(fL, "right", r.fRight); 1.216 + setfield_scalar(fL, "bottom", r.fBottom); 1.217 + CHECK_SETFIELD(key); 1.218 +} 1.219 + 1.220 +void SkLua::pushRRect(const SkRRect& rr, const char key[]) { 1.221 + push_obj(fL, rr); 1.222 + CHECK_SETFIELD(key); 1.223 +} 1.224 + 1.225 +void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) { 1.226 + push_obj(fL, matrix); 1.227 + CHECK_SETFIELD(key); 1.228 +} 1.229 + 1.230 +void SkLua::pushPaint(const SkPaint& paint, const char key[]) { 1.231 + push_obj(fL, paint); 1.232 + CHECK_SETFIELD(key); 1.233 +} 1.234 + 1.235 +void SkLua::pushPath(const SkPath& path, const char key[]) { 1.236 + push_obj(fL, path); 1.237 + CHECK_SETFIELD(key); 1.238 +} 1.239 + 1.240 +void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) { 1.241 + push_ref(fL, canvas); 1.242 + CHECK_SETFIELD(key); 1.243 +} 1.244 + 1.245 +static const char* element_type(SkClipStack::Element::Type type) { 1.246 + switch (type) { 1.247 + case SkClipStack::Element::kEmpty_Type: 1.248 + return "empty"; 1.249 + case SkClipStack::Element::kRect_Type: 1.250 + return "rect"; 1.251 + case SkClipStack::Element::kRRect_Type: 1.252 + return "rrect"; 1.253 + case SkClipStack::Element::kPath_Type: 1.254 + return "path"; 1.255 + } 1.256 + return "unknown"; 1.257 +} 1.258 + 1.259 +static const char* region_op(SkRegion::Op op) { 1.260 + switch (op) { 1.261 + case SkRegion::kDifference_Op: 1.262 + return "difference"; 1.263 + case SkRegion::kIntersect_Op: 1.264 + return "intersect"; 1.265 + case SkRegion::kUnion_Op: 1.266 + return "union"; 1.267 + case SkRegion::kXOR_Op: 1.268 + return "xor"; 1.269 + case SkRegion::kReverseDifference_Op: 1.270 + return "reverse-difference"; 1.271 + case SkRegion::kReplace_Op: 1.272 + return "replace"; 1.273 + } 1.274 + return "unknown"; 1.275 +} 1.276 + 1.277 +void SkLua::pushClipStack(const SkClipStack& stack, const char* key) { 1.278 + lua_newtable(fL); 1.279 + SkClipStack::B2TIter iter(stack); 1.280 + const SkClipStack::Element* element; 1.281 + int i = 0; 1.282 + while (NULL != (element = iter.next())) { 1.283 + this->pushClipStackElement(*element); 1.284 + lua_rawseti(fL, -2, ++i); 1.285 + } 1.286 + CHECK_SETFIELD(key); 1.287 +} 1.288 + 1.289 +void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) { 1.290 + lua_newtable(fL); 1.291 + SkClipStack::Element::Type type = element.getType(); 1.292 + this->pushString(element_type(type), "type"); 1.293 + switch (type) { 1.294 + case SkClipStack::Element::kEmpty_Type: 1.295 + break; 1.296 + case SkClipStack::Element::kRect_Type: 1.297 + this->pushRect(element.getRect(), "rect"); 1.298 + break; 1.299 + case SkClipStack::Element::kRRect_Type: 1.300 + this->pushRRect(element.getRRect(), "rrect"); 1.301 + break; 1.302 + case SkClipStack::Element::kPath_Type: 1.303 + this->pushPath(element.getPath(), "path"); 1.304 + break; 1.305 + } 1.306 + this->pushString(region_op(element.getOp()), "op"); 1.307 + this->pushBool(element.isAA(), "aa"); 1.308 + CHECK_SETFIELD(key); 1.309 +} 1.310 + 1.311 + 1.312 +/////////////////////////////////////////////////////////////////////////////// 1.313 +/////////////////////////////////////////////////////////////////////////////// 1.314 + 1.315 +static SkScalar lua2scalar(lua_State* L, int index) { 1.316 + SkASSERT(lua_isnumber(L, index)); 1.317 + return SkLuaToScalar(lua_tonumber(L, index)); 1.318 +} 1.319 + 1.320 +static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) { 1.321 + if (lua_isnumber(L, index)) { 1.322 + return SkLuaToScalar(lua_tonumber(L, index)); 1.323 + } else { 1.324 + return defaultValue; 1.325 + } 1.326 +} 1.327 + 1.328 +static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) { 1.329 + SkASSERT(lua_istable(L, index)); 1.330 + lua_pushstring(L, key); 1.331 + lua_gettable(L, index); 1.332 + 1.333 + SkScalar value = lua2scalar(L, -1); 1.334 + lua_pop(L, 1); 1.335 + return value; 1.336 +} 1.337 + 1.338 +static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) { 1.339 + SkASSERT(lua_istable(L, index)); 1.340 + lua_pushstring(L, key); 1.341 + lua_gettable(L, index); 1.342 + 1.343 + SkScalar value; 1.344 + if (lua_isnil(L, -1)) { 1.345 + value = def; 1.346 + } else { 1.347 + value = lua2scalar(L, -1); 1.348 + } 1.349 + lua_pop(L, 1); 1.350 + return value; 1.351 +} 1.352 + 1.353 +static U8CPU unit2byte(SkScalar x) { 1.354 + if (x <= 0) { 1.355 + return 0; 1.356 + } else if (x >= 1) { 1.357 + return 255; 1.358 + } else { 1.359 + return SkScalarRoundToInt(x * 255); 1.360 + } 1.361 +} 1.362 + 1.363 +static SkColor lua2color(lua_State* L, int index) { 1.364 + return SkColorSetARGB(unit2byte(getfield_scalar(L, index, "a")), 1.365 + unit2byte(getfield_scalar(L, index, "r")), 1.366 + unit2byte(getfield_scalar(L, index, "g")), 1.367 + unit2byte(getfield_scalar(L, index, "b"))); 1.368 +} 1.369 + 1.370 +static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) { 1.371 + rect->set(getfield_scalar_default(L, index, "left", 0), 1.372 + getfield_scalar_default(L, index, "top", 0), 1.373 + getfield_scalar(L, index, "right"), 1.374 + getfield_scalar(L, index, "bottom")); 1.375 + return rect; 1.376 +} 1.377 + 1.378 +static int lcanvas_drawColor(lua_State* L) { 1.379 + get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2)); 1.380 + return 0; 1.381 +} 1.382 + 1.383 +static int lcanvas_drawRect(lua_State* L) { 1.384 + SkRect rect; 1.385 + get_ref<SkCanvas>(L, 1)->drawRect(*lua2rect(L, 2, &rect), 1.386 + *get_obj<SkPaint>(L, 3)); 1.387 + return 0; 1.388 +} 1.389 + 1.390 +static int lcanvas_drawOval(lua_State* L) { 1.391 + SkRect rect; 1.392 + get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect), 1.393 + *get_obj<SkPaint>(L, 3)); 1.394 + return 0; 1.395 +} 1.396 + 1.397 +static int lcanvas_drawCircle(lua_State* L) { 1.398 + get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2), 1.399 + lua2scalar(L, 3), 1.400 + lua2scalar(L, 4), 1.401 + *get_obj<SkPaint>(L, 5)); 1.402 + return 0; 1.403 +} 1.404 + 1.405 +static int lcanvas_drawImage(lua_State* L) { 1.406 + SkCanvas* canvas = get_ref<SkCanvas>(L, 1); 1.407 + SkImage* image = get_ref<SkImage>(L, 2); 1.408 + if (NULL == image) { 1.409 + return 0; 1.410 + } 1.411 + SkScalar x = lua2scalar(L, 3); 1.412 + SkScalar y = lua2scalar(L, 4); 1.413 + 1.414 + SkPaint paint; 1.415 + const SkPaint* paintPtr = NULL; 1.416 + if (lua_isnumber(L, 5)) { 1.417 + paint.setAlpha(SkScalarRoundToInt(lua2scalar(L, 5) * 255)); 1.418 + paintPtr = &paint; 1.419 + } 1.420 + image->draw(canvas, x, y, paintPtr); 1.421 + return 0; 1.422 +} 1.423 + 1.424 +static int lcanvas_drawPath(lua_State* L) { 1.425 + get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2), 1.426 + *get_obj<SkPaint>(L, 3)); 1.427 + return 0; 1.428 +} 1.429 + 1.430 +static int lcanvas_drawText(lua_State* L) { 1.431 + if (lua_gettop(L) < 5) { 1.432 + return 0; 1.433 + } 1.434 + 1.435 + if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) { 1.436 + size_t len; 1.437 + const char* text = lua_tolstring(L, 2, &len); 1.438 + get_ref<SkCanvas>(L, 1)->drawText(text, len, 1.439 + lua2scalar(L, 3), lua2scalar(L, 4), 1.440 + *get_obj<SkPaint>(L, 5)); 1.441 + } 1.442 + return 0; 1.443 +} 1.444 + 1.445 +static int lcanvas_getSaveCount(lua_State* L) { 1.446 + lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount()); 1.447 + return 1; 1.448 +} 1.449 + 1.450 +static int lcanvas_getTotalMatrix(lua_State* L) { 1.451 + SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix()); 1.452 + return 1; 1.453 +} 1.454 + 1.455 +static int lcanvas_getClipStack(lua_State* L) { 1.456 + SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack()); 1.457 + return 1; 1.458 +} 1.459 + 1.460 +int SkLua::lcanvas_getReducedClipStack(lua_State* L) { 1.461 +#if SK_SUPPORT_GPU 1.462 + const SkCanvas* canvas = get_ref<SkCanvas>(L, 1); 1.463 + SkISize layerSize = canvas->getTopLayerSize(); 1.464 + SkIPoint layerOrigin = canvas->getTopLayerOrigin(); 1.465 + SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY, 1.466 + layerSize.fWidth, layerSize.fHeight); 1.467 + 1.468 + GrReducedClip::ElementList elements; 1.469 + GrReducedClip::InitialState initialState; 1.470 + int32_t genID; 1.471 + SkIRect resultBounds; 1.472 + 1.473 + const SkClipStack& stack = *canvas->getClipStack(); 1.474 + 1.475 + GrReducedClip::ReduceClipStack(stack, 1.476 + queryBounds, 1.477 + &elements, 1.478 + &genID, 1.479 + &initialState, 1.480 + &resultBounds, 1.481 + NULL); 1.482 + 1.483 + GrReducedClip::ElementList::Iter iter(elements); 1.484 + int i = 0; 1.485 + lua_newtable(L); 1.486 + while(NULL != iter.get()) { 1.487 + SkLua(L).pushClipStackElement(*iter.get()); 1.488 + iter.next(); 1.489 + lua_rawseti(L, -2, ++i); 1.490 + } 1.491 + // Currently this only returns the element list to lua, not the initial state or result bounds. 1.492 + // It could return these as additional items on the lua stack. 1.493 + return 1; 1.494 +#else 1.495 + return 0; 1.496 +#endif 1.497 +} 1.498 + 1.499 +static int lcanvas_save(lua_State* L) { 1.500 + lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save()); 1.501 + return 1; 1.502 +} 1.503 + 1.504 +static int lcanvas_restore(lua_State* L) { 1.505 + get_ref<SkCanvas>(L, 1)->restore(); 1.506 + return 0; 1.507 +} 1.508 + 1.509 +static int lcanvas_scale(lua_State* L) { 1.510 + SkScalar sx = lua2scalar_def(L, 2, 1); 1.511 + SkScalar sy = lua2scalar_def(L, 3, sx); 1.512 + get_ref<SkCanvas>(L, 1)->scale(sx, sy); 1.513 + return 0; 1.514 +} 1.515 + 1.516 +static int lcanvas_translate(lua_State* L) { 1.517 + SkScalar tx = lua2scalar_def(L, 2, 0); 1.518 + SkScalar ty = lua2scalar_def(L, 3, 0); 1.519 + get_ref<SkCanvas>(L, 1)->translate(tx, ty); 1.520 + return 0; 1.521 +} 1.522 + 1.523 +static int lcanvas_rotate(lua_State* L) { 1.524 + SkScalar degrees = lua2scalar_def(L, 2, 0); 1.525 + get_ref<SkCanvas>(L, 1)->rotate(degrees); 1.526 + return 0; 1.527 +} 1.528 + 1.529 +static int lcanvas_gc(lua_State* L) { 1.530 + get_ref<SkCanvas>(L, 1)->unref(); 1.531 + return 0; 1.532 +} 1.533 + 1.534 +const struct luaL_Reg gSkCanvas_Methods[] = { 1.535 + { "drawColor", lcanvas_drawColor }, 1.536 + { "drawRect", lcanvas_drawRect }, 1.537 + { "drawOval", lcanvas_drawOval }, 1.538 + { "drawCircle", lcanvas_drawCircle }, 1.539 + { "drawImage", lcanvas_drawImage }, 1.540 + { "drawPath", lcanvas_drawPath }, 1.541 + { "drawText", lcanvas_drawText }, 1.542 + { "getSaveCount", lcanvas_getSaveCount }, 1.543 + { "getTotalMatrix", lcanvas_getTotalMatrix }, 1.544 + { "getClipStack", lcanvas_getClipStack }, 1.545 +#if SK_SUPPORT_GPU 1.546 + { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack }, 1.547 +#endif 1.548 + { "save", lcanvas_save }, 1.549 + { "restore", lcanvas_restore }, 1.550 + { "scale", lcanvas_scale }, 1.551 + { "translate", lcanvas_translate }, 1.552 + { "rotate", lcanvas_rotate }, 1.553 + { "__gc", lcanvas_gc }, 1.554 + { NULL, NULL } 1.555 +}; 1.556 + 1.557 +/////////////////////////////////////////////////////////////////////////////// 1.558 + 1.559 +static int ldocument_beginPage(lua_State* L) { 1.560 + const SkRect* contentPtr = NULL; 1.561 + push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2), 1.562 + lua2scalar(L, 3), 1.563 + contentPtr)); 1.564 + return 1; 1.565 +} 1.566 + 1.567 +static int ldocument_endPage(lua_State* L) { 1.568 + get_ref<SkDocument>(L, 1)->endPage(); 1.569 + return 0; 1.570 +} 1.571 + 1.572 +static int ldocument_close(lua_State* L) { 1.573 + get_ref<SkDocument>(L, 1)->close(); 1.574 + return 0; 1.575 +} 1.576 + 1.577 +static int ldocument_gc(lua_State* L) { 1.578 + get_ref<SkDocument>(L, 1)->unref(); 1.579 + return 0; 1.580 +} 1.581 + 1.582 +static const struct luaL_Reg gSkDocument_Methods[] = { 1.583 + { "beginPage", ldocument_beginPage }, 1.584 + { "endPage", ldocument_endPage }, 1.585 + { "close", ldocument_close }, 1.586 + { "__gc", ldocument_gc }, 1.587 + { NULL, NULL } 1.588 +}; 1.589 + 1.590 +/////////////////////////////////////////////////////////////////////////////// 1.591 + 1.592 +static int lpaint_isAntiAlias(lua_State* L) { 1.593 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias()); 1.594 + return 1; 1.595 +} 1.596 + 1.597 +static int lpaint_setAntiAlias(lua_State* L) { 1.598 + get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2)); 1.599 + return 0; 1.600 +} 1.601 + 1.602 +static int lpaint_isDither(lua_State* L) { 1.603 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither()); 1.604 + return 1; 1.605 +} 1.606 + 1.607 +static int lpaint_isUnderlineText(lua_State* L) { 1.608 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText()); 1.609 + return 1; 1.610 +} 1.611 + 1.612 +static int lpaint_isStrikeThruText(lua_State* L) { 1.613 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText()); 1.614 + return 1; 1.615 +} 1.616 + 1.617 +static int lpaint_isFakeBoldText(lua_State* L) { 1.618 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText()); 1.619 + return 1; 1.620 +} 1.621 + 1.622 +static int lpaint_isLinearText(lua_State* L) { 1.623 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText()); 1.624 + return 1; 1.625 +} 1.626 + 1.627 +static int lpaint_isSubpixelText(lua_State* L) { 1.628 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText()); 1.629 + return 1; 1.630 +} 1.631 + 1.632 +static int lpaint_isDevKernText(lua_State* L) { 1.633 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText()); 1.634 + return 1; 1.635 +} 1.636 + 1.637 +static int lpaint_isLCDRenderText(lua_State* L) { 1.638 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText()); 1.639 + return 1; 1.640 +} 1.641 + 1.642 +static int lpaint_isEmbeddedBitmapText(lua_State* L) { 1.643 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText()); 1.644 + return 1; 1.645 +} 1.646 + 1.647 +static int lpaint_isAutohinted(lua_State* L) { 1.648 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted()); 1.649 + return 1; 1.650 +} 1.651 + 1.652 +static int lpaint_isVerticalText(lua_State* L) { 1.653 + lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText()); 1.654 + return 1; 1.655 +} 1.656 + 1.657 +static int lpaint_getColor(lua_State* L) { 1.658 + SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor()); 1.659 + return 1; 1.660 +} 1.661 + 1.662 +static int lpaint_setColor(lua_State* L) { 1.663 + get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2)); 1.664 + return 0; 1.665 +} 1.666 + 1.667 +static int lpaint_getTextSize(lua_State* L) { 1.668 + SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize()); 1.669 + return 1; 1.670 +} 1.671 + 1.672 +static int lpaint_getTextScaleX(lua_State* L) { 1.673 + SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX()); 1.674 + return 1; 1.675 +} 1.676 + 1.677 +static int lpaint_getTextSkewX(lua_State* L) { 1.678 + SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX()); 1.679 + return 1; 1.680 +} 1.681 + 1.682 +static int lpaint_setTextSize(lua_State* L) { 1.683 + get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2)); 1.684 + return 0; 1.685 +} 1.686 + 1.687 +static int lpaint_getTypeface(lua_State* L) { 1.688 + push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface()); 1.689 + return 1; 1.690 +} 1.691 + 1.692 +static int lpaint_setTypeface(lua_State* L) { 1.693 + get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2)); 1.694 + return 0; 1.695 +} 1.696 + 1.697 +static int lpaint_getHinting(lua_State* L) { 1.698 + SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting()); 1.699 + return 1; 1.700 +} 1.701 + 1.702 +static int lpaint_getFontID(lua_State* L) { 1.703 + SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface(); 1.704 + SkLua(L).pushU32(SkTypeface::UniqueID(face)); 1.705 + return 1; 1.706 +} 1.707 + 1.708 +static const struct { 1.709 + const char* fLabel; 1.710 + SkPaint::Align fAlign; 1.711 +} gAlignRec[] = { 1.712 + { "left", SkPaint::kLeft_Align }, 1.713 + { "center", SkPaint::kCenter_Align }, 1.714 + { "right", SkPaint::kRight_Align }, 1.715 +}; 1.716 + 1.717 +static int lpaint_getTextAlign(lua_State* L) { 1.718 + SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign(); 1.719 + for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { 1.720 + if (gAlignRec[i].fAlign == align) { 1.721 + lua_pushstring(L, gAlignRec[i].fLabel); 1.722 + return 1; 1.723 + } 1.724 + } 1.725 + return 0; 1.726 +} 1.727 + 1.728 +static int lpaint_setTextAlign(lua_State* L) { 1.729 + if (lua_isstring(L, 2)) { 1.730 + size_t len; 1.731 + const char* label = lua_tolstring(L, 2, &len); 1.732 + 1.733 + for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { 1.734 + if (!strcmp(gAlignRec[i].fLabel, label)) { 1.735 + get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign); 1.736 + break; 1.737 + } 1.738 + } 1.739 + } 1.740 + return 0; 1.741 +} 1.742 + 1.743 +static int lpaint_getStroke(lua_State* L) { 1.744 + lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle()); 1.745 + return 1; 1.746 +} 1.747 + 1.748 +static int lpaint_setStroke(lua_State* L) { 1.749 + SkPaint::Style style; 1.750 + 1.751 + if (lua_toboolean(L, 2)) { 1.752 + style = SkPaint::kStroke_Style; 1.753 + } else { 1.754 + style = SkPaint::kFill_Style; 1.755 + } 1.756 + get_obj<SkPaint>(L, 1)->setStyle(style); 1.757 + return 0; 1.758 +} 1.759 + 1.760 +static int lpaint_getStrokeCap(lua_State* L) { 1.761 + SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap()); 1.762 + return 1; 1.763 +} 1.764 + 1.765 +static int lpaint_getStrokeJoin(lua_State* L) { 1.766 + SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin()); 1.767 + return 1; 1.768 +} 1.769 + 1.770 +static int lpaint_getTextEncoding(lua_State* L) { 1.771 + SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding()); 1.772 + return 1; 1.773 +} 1.774 + 1.775 +static int lpaint_getStrokeWidth(lua_State* L) { 1.776 + SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth()); 1.777 + return 1; 1.778 +} 1.779 + 1.780 +static int lpaint_setStrokeWidth(lua_State* L) { 1.781 + get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2)); 1.782 + return 0; 1.783 +} 1.784 + 1.785 +static int lpaint_getStrokeMiter(lua_State* L) { 1.786 + SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter()); 1.787 + return 1; 1.788 +} 1.789 + 1.790 +static int lpaint_measureText(lua_State* L) { 1.791 + if (lua_isstring(L, 2)) { 1.792 + size_t len; 1.793 + const char* text = lua_tolstring(L, 2, &len); 1.794 + SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len)); 1.795 + return 1; 1.796 + } 1.797 + return 0; 1.798 +} 1.799 + 1.800 +struct FontMetrics { 1.801 + SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0) 1.802 + SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0) 1.803 + SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0) 1.804 + SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0) 1.805 + SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0) 1.806 + SkScalar fAvgCharWidth; //!< the average charactor width (>= 0) 1.807 + SkScalar fXMin; //!< The minimum bounding box x value for all glyphs 1.808 + SkScalar fXMax; //!< The maximum bounding box x value for all glyphs 1.809 + SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face 1.810 +}; 1.811 + 1.812 +static int lpaint_getFontMetrics(lua_State* L) { 1.813 + SkPaint::FontMetrics fm; 1.814 + SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm); 1.815 + 1.816 + lua_newtable(L); 1.817 + setfield_scalar(L, "top", fm.fTop); 1.818 + setfield_scalar(L, "ascent", fm.fAscent); 1.819 + setfield_scalar(L, "descent", fm.fDescent); 1.820 + setfield_scalar(L, "bottom", fm.fBottom); 1.821 + setfield_scalar(L, "leading", fm.fLeading); 1.822 + SkLua(L).pushScalar(height); 1.823 + return 2; 1.824 +} 1.825 + 1.826 +static int lpaint_getEffects(lua_State* L) { 1.827 + const SkPaint* paint = get_obj<SkPaint>(L, 1); 1.828 + 1.829 + lua_newtable(L); 1.830 + setfield_bool_if(L, "looper", !!paint->getLooper()); 1.831 + setfield_bool_if(L, "pathEffect", !!paint->getPathEffect()); 1.832 + setfield_bool_if(L, "rasterizer", !!paint->getRasterizer()); 1.833 + setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter()); 1.834 + setfield_bool_if(L, "shader", !!paint->getShader()); 1.835 + setfield_bool_if(L, "colorFilter", !!paint->getColorFilter()); 1.836 + setfield_bool_if(L, "imageFilter", !!paint->getImageFilter()); 1.837 + setfield_bool_if(L, "xfermode", !!paint->getXfermode()); 1.838 + return 1; 1.839 +} 1.840 + 1.841 +static int lpaint_getShader(lua_State* L) { 1.842 + const SkPaint* paint = get_obj<SkPaint>(L, 1); 1.843 + SkShader* shader = paint->getShader(); 1.844 + if (shader) { 1.845 + push_ref(L, shader); 1.846 + return 1; 1.847 + } 1.848 + return 0; 1.849 +} 1.850 + 1.851 +static int lpaint_gc(lua_State* L) { 1.852 + get_obj<SkPaint>(L, 1)->~SkPaint(); 1.853 + return 0; 1.854 +} 1.855 + 1.856 +static const struct luaL_Reg gSkPaint_Methods[] = { 1.857 + { "isAntiAlias", lpaint_isAntiAlias }, 1.858 + { "setAntiAlias", lpaint_setAntiAlias }, 1.859 + { "isDither", lpaint_isDither }, 1.860 + { "isUnderlineText", lpaint_isUnderlineText }, 1.861 + { "isStrikeThruText", lpaint_isStrikeThruText }, 1.862 + { "isFakeBoldText", lpaint_isFakeBoldText }, 1.863 + { "isLinearText", lpaint_isLinearText }, 1.864 + { "isSubpixelText", lpaint_isSubpixelText }, 1.865 + { "isDevKernText", lpaint_isDevKernText }, 1.866 + { "isLCDRenderText", lpaint_isLCDRenderText }, 1.867 + { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText }, 1.868 + { "isAutohinted", lpaint_isAutohinted }, 1.869 + { "isVerticalText", lpaint_isVerticalText }, 1.870 + { "getColor", lpaint_getColor }, 1.871 + { "setColor", lpaint_setColor }, 1.872 + { "getTextSize", lpaint_getTextSize }, 1.873 + { "setTextSize", lpaint_setTextSize }, 1.874 + { "getTextScaleX", lpaint_getTextScaleX }, 1.875 + { "getTextSkewX", lpaint_getTextSkewX }, 1.876 + { "getTypeface", lpaint_getTypeface }, 1.877 + { "setTypeface", lpaint_setTypeface }, 1.878 + { "getHinting", lpaint_getHinting }, 1.879 + { "getFontID", lpaint_getFontID }, 1.880 + { "getTextAlign", lpaint_getTextAlign }, 1.881 + { "setTextAlign", lpaint_setTextAlign }, 1.882 + { "getStroke", lpaint_getStroke }, 1.883 + { "setStroke", lpaint_setStroke }, 1.884 + { "getStrokeCap", lpaint_getStrokeCap }, 1.885 + { "getStrokeJoin", lpaint_getStrokeJoin }, 1.886 + { "getTextEncoding", lpaint_getTextEncoding }, 1.887 + { "getStrokeWidth", lpaint_getStrokeWidth }, 1.888 + { "setStrokeWidth", lpaint_setStrokeWidth }, 1.889 + { "getStrokeMiter", lpaint_getStrokeMiter }, 1.890 + { "measureText", lpaint_measureText }, 1.891 + { "getFontMetrics", lpaint_getFontMetrics }, 1.892 + { "getEffects", lpaint_getEffects }, 1.893 + { "getShader", lpaint_getShader }, 1.894 + { "__gc", lpaint_gc }, 1.895 + { NULL, NULL } 1.896 +}; 1.897 + 1.898 +/////////////////////////////////////////////////////////////////////////////// 1.899 + 1.900 +static const char* mode2string(SkShader::TileMode mode) { 1.901 + static const char* gNames[] = { "clamp", "repeat", "mirror" }; 1.902 + SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames)); 1.903 + return gNames[mode]; 1.904 +} 1.905 + 1.906 +static const char* gradtype2string(SkShader::GradientType t) { 1.907 + static const char* gNames[] = { 1.908 + "none", "color", "linear", "radial", "radial2", "sweep", "conical" 1.909 + }; 1.910 + SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames)); 1.911 + return gNames[t]; 1.912 +} 1.913 + 1.914 +static int lshader_isOpaque(lua_State* L) { 1.915 + SkShader* shader = get_ref<SkShader>(L, 1); 1.916 + return shader && shader->isOpaque(); 1.917 +} 1.918 + 1.919 +static int lshader_asABitmap(lua_State* L) { 1.920 + SkShader* shader = get_ref<SkShader>(L, 1); 1.921 + if (shader) { 1.922 + SkBitmap bm; 1.923 + SkMatrix matrix; 1.924 + SkShader::TileMode modes[2]; 1.925 + switch (shader->asABitmap(&bm, &matrix, modes)) { 1.926 + case SkShader::kDefault_BitmapType: 1.927 + lua_newtable(L); 1.928 + setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0); 1.929 + setfield_number(L, "width", bm.width()); 1.930 + setfield_number(L, "height", bm.height()); 1.931 + setfield_string(L, "tileX", mode2string(modes[0])); 1.932 + setfield_string(L, "tileY", mode2string(modes[1])); 1.933 + return 1; 1.934 + default: 1.935 + break; 1.936 + } 1.937 + } 1.938 + return 0; 1.939 +} 1.940 + 1.941 +static int lshader_asAGradient(lua_State* L) { 1.942 + SkShader* shader = get_ref<SkShader>(L, 1); 1.943 + if (shader) { 1.944 + SkShader::GradientInfo info; 1.945 + sk_bzero(&info, sizeof(info)); 1.946 + 1.947 + SkColor colors[3]; // hacked in for extracting info on 3 color case. 1.948 + SkScalar pos[3]; 1.949 + 1.950 + info.fColorCount = 3; 1.951 + info.fColors = &colors[0]; 1.952 + info.fColorOffsets = &pos[0]; 1.953 + 1.954 + SkShader::GradientType t = shader->asAGradient(&info); 1.955 + 1.956 + if (SkShader::kNone_GradientType != t) { 1.957 + lua_newtable(L); 1.958 + setfield_string(L, "type", gradtype2string(t)); 1.959 + setfield_number(L, "colorCount", info.fColorCount); 1.960 + setfield_string(L, "tile", mode2string(info.fTileMode)); 1.961 + 1.962 + if (info.fColorCount == 3){ 1.963 + setfield_number(L, "midPos", pos[1]); 1.964 + } 1.965 + 1.966 + return 1; 1.967 + } 1.968 + } 1.969 + return 0; 1.970 +} 1.971 + 1.972 +static int lshader_gc(lua_State* L) { 1.973 + get_ref<SkShader>(L, 1)->unref(); 1.974 + return 0; 1.975 +} 1.976 + 1.977 +static const struct luaL_Reg gSkShader_Methods[] = { 1.978 + { "isOpaque", lshader_isOpaque }, 1.979 + { "asABitmap", lshader_asABitmap }, 1.980 + { "asAGradient", lshader_asAGradient }, 1.981 + { "__gc", lshader_gc }, 1.982 + { NULL, NULL } 1.983 +}; 1.984 + 1.985 +/////////////////////////////////////////////////////////////////////////////// 1.986 + 1.987 +static int lmatrix_getType(lua_State* L) { 1.988 + SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType(); 1.989 + 1.990 + lua_newtable(L); 1.991 + setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask)); 1.992 + setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask)); 1.993 + setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask)); 1.994 + setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask)); 1.995 + return 1; 1.996 +} 1.997 + 1.998 +static int lmatrix_getScaleX(lua_State* L) { 1.999 + lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX()); 1.1000 + return 1; 1.1001 +} 1.1002 + 1.1003 +static int lmatrix_getScaleY(lua_State* L) { 1.1004 + lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY()); 1.1005 + return 1; 1.1006 +} 1.1007 + 1.1008 +static int lmatrix_getTranslateX(lua_State* L) { 1.1009 + lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX()); 1.1010 + return 1; 1.1011 +} 1.1012 + 1.1013 +static int lmatrix_getTranslateY(lua_State* L) { 1.1014 + lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY()); 1.1015 + return 1; 1.1016 +} 1.1017 + 1.1018 +static const struct luaL_Reg gSkMatrix_Methods[] = { 1.1019 + { "getType", lmatrix_getType }, 1.1020 + { "getScaleX", lmatrix_getScaleX }, 1.1021 + { "getScaleY", lmatrix_getScaleY }, 1.1022 + { "getTranslateX", lmatrix_getTranslateX }, 1.1023 + { "getTranslateY", lmatrix_getTranslateY }, 1.1024 + { NULL, NULL } 1.1025 +}; 1.1026 + 1.1027 +/////////////////////////////////////////////////////////////////////////////// 1.1028 + 1.1029 +static int lpath_getBounds(lua_State* L) { 1.1030 + SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds()); 1.1031 + return 1; 1.1032 +} 1.1033 + 1.1034 +static const char* fill_type_to_str(SkPath::FillType fill) { 1.1035 + switch (fill) { 1.1036 + case SkPath::kEvenOdd_FillType: 1.1037 + return "even-odd"; 1.1038 + case SkPath::kWinding_FillType: 1.1039 + return "winding"; 1.1040 + case SkPath::kInverseEvenOdd_FillType: 1.1041 + return "inverse-even-odd"; 1.1042 + case SkPath::kInverseWinding_FillType: 1.1043 + return "inverse-winding"; 1.1044 + } 1.1045 + return "unknown"; 1.1046 +} 1.1047 + 1.1048 +static int lpath_getFillType(lua_State* L) { 1.1049 + SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType(); 1.1050 + SkLua(L).pushString(fill_type_to_str(fill)); 1.1051 + return 1; 1.1052 +} 1.1053 + 1.1054 +static SkString segment_masks_to_str(uint32_t segmentMasks) { 1.1055 + SkString result; 1.1056 + bool first = true; 1.1057 + if (SkPath::kLine_SegmentMask & segmentMasks) { 1.1058 + result.append("line"); 1.1059 + first = false; 1.1060 + SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;) 1.1061 + } 1.1062 + if (SkPath::kQuad_SegmentMask & segmentMasks) { 1.1063 + if (!first) { 1.1064 + result.append(" "); 1.1065 + } 1.1066 + result.append("quad"); 1.1067 + first = false; 1.1068 + SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;) 1.1069 + } 1.1070 + if (SkPath::kConic_SegmentMask & segmentMasks) { 1.1071 + if (!first) { 1.1072 + result.append(" "); 1.1073 + } 1.1074 + result.append("conic"); 1.1075 + first = false; 1.1076 + SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;) 1.1077 + } 1.1078 + if (SkPath::kCubic_SegmentMask & segmentMasks) { 1.1079 + if (!first) { 1.1080 + result.append(" "); 1.1081 + } 1.1082 + result.append("cubic"); 1.1083 + SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;) 1.1084 + } 1.1085 + SkASSERT(0 == segmentMasks); 1.1086 + return result; 1.1087 +} 1.1088 + 1.1089 +static int lpath_getSegementTypes(lua_State* L) { 1.1090 + uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks(); 1.1091 + SkLua(L).pushString(segment_masks_to_str(segMasks)); 1.1092 + return 1; 1.1093 +} 1.1094 + 1.1095 +static int lpath_isConvex(lua_State* L) { 1.1096 + bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity(); 1.1097 + SkLua(L).pushBool(isConvex); 1.1098 + return 1; 1.1099 +} 1.1100 + 1.1101 +static int lpath_isEmpty(lua_State* L) { 1.1102 + lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty()); 1.1103 + return 1; 1.1104 +} 1.1105 + 1.1106 +static int lpath_isRect(lua_State* L) { 1.1107 + SkRect r; 1.1108 + bool pred = get_obj<SkPath>(L, 1)->isRect(&r); 1.1109 + int ret_count = 1; 1.1110 + lua_pushboolean(L, pred); 1.1111 + if (pred) { 1.1112 + SkLua(L).pushRect(r); 1.1113 + ret_count += 1; 1.1114 + } 1.1115 + return ret_count; 1.1116 +} 1.1117 + 1.1118 +static const char* dir2string(SkPath::Direction dir) { 1.1119 + static const char* gStr[] = { 1.1120 + "unknown", "cw", "ccw" 1.1121 + }; 1.1122 + SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr)); 1.1123 + return gStr[dir]; 1.1124 +} 1.1125 + 1.1126 +static int lpath_isNestedRects(lua_State* L) { 1.1127 + SkRect rects[2]; 1.1128 + SkPath::Direction dirs[2]; 1.1129 + bool pred = get_obj<SkPath>(L, 1)->isNestedRects(rects, dirs); 1.1130 + int ret_count = 1; 1.1131 + lua_pushboolean(L, pred); 1.1132 + if (pred) { 1.1133 + SkLua lua(L); 1.1134 + lua.pushRect(rects[0]); 1.1135 + lua.pushRect(rects[1]); 1.1136 + lua_pushstring(L, dir2string(dirs[0])); 1.1137 + lua_pushstring(L, dir2string(dirs[0])); 1.1138 + ret_count += 4; 1.1139 + } 1.1140 + return ret_count; 1.1141 +} 1.1142 + 1.1143 +static int lpath_countPoints(lua_State* L) { 1.1144 + lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints()); 1.1145 + return 1; 1.1146 +} 1.1147 + 1.1148 +static int lpath_reset(lua_State* L) { 1.1149 + get_obj<SkPath>(L, 1)->reset(); 1.1150 + return 0; 1.1151 +} 1.1152 + 1.1153 +static int lpath_moveTo(lua_State* L) { 1.1154 + get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3)); 1.1155 + return 0; 1.1156 +} 1.1157 + 1.1158 +static int lpath_lineTo(lua_State* L) { 1.1159 + get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3)); 1.1160 + return 0; 1.1161 +} 1.1162 + 1.1163 +static int lpath_quadTo(lua_State* L) { 1.1164 + get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3), 1.1165 + lua2scalar(L, 4), lua2scalar(L, 5)); 1.1166 + return 0; 1.1167 +} 1.1168 + 1.1169 +static int lpath_cubicTo(lua_State* L) { 1.1170 + get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3), 1.1171 + lua2scalar(L, 4), lua2scalar(L, 5), 1.1172 + lua2scalar(L, 6), lua2scalar(L, 7)); 1.1173 + return 0; 1.1174 +} 1.1175 + 1.1176 +static int lpath_close(lua_State* L) { 1.1177 + get_obj<SkPath>(L, 1)->close(); 1.1178 + return 0; 1.1179 +} 1.1180 + 1.1181 +static int lpath_gc(lua_State* L) { 1.1182 + get_obj<SkPath>(L, 1)->~SkPath(); 1.1183 + return 0; 1.1184 +} 1.1185 + 1.1186 +static const struct luaL_Reg gSkPath_Methods[] = { 1.1187 + { "getBounds", lpath_getBounds }, 1.1188 + { "getFillType", lpath_getFillType }, 1.1189 + { "getSegmentTypes", lpath_getSegementTypes }, 1.1190 + { "isConvex", lpath_isConvex }, 1.1191 + { "isEmpty", lpath_isEmpty }, 1.1192 + { "isRect", lpath_isRect }, 1.1193 + { "isNestedRects", lpath_isNestedRects }, 1.1194 + { "countPoints", lpath_countPoints }, 1.1195 + { "reset", lpath_reset }, 1.1196 + { "moveTo", lpath_moveTo }, 1.1197 + { "lineTo", lpath_lineTo }, 1.1198 + { "quadTo", lpath_quadTo }, 1.1199 + { "cubicTo", lpath_cubicTo }, 1.1200 + { "close", lpath_close }, 1.1201 + { "__gc", lpath_gc }, 1.1202 + { NULL, NULL } 1.1203 +}; 1.1204 + 1.1205 +/////////////////////////////////////////////////////////////////////////////// 1.1206 + 1.1207 +static const char* rrect_type(const SkRRect& rr) { 1.1208 + switch (rr.getType()) { 1.1209 + case SkRRect::kUnknown_Type: return "unknown"; 1.1210 + case SkRRect::kEmpty_Type: return "empty"; 1.1211 + case SkRRect::kRect_Type: return "rect"; 1.1212 + case SkRRect::kOval_Type: return "oval"; 1.1213 + case SkRRect::kSimple_Type: return "simple"; 1.1214 + case SkRRect::kComplex_Type: return "complex"; 1.1215 + } 1.1216 + SkDEBUGFAIL("never get here"); 1.1217 + return ""; 1.1218 +} 1.1219 + 1.1220 +static int lrrect_rect(lua_State* L) { 1.1221 + SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect()); 1.1222 + return 1; 1.1223 +} 1.1224 + 1.1225 +static int lrrect_type(lua_State* L) { 1.1226 + lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1))); 1.1227 + return 1; 1.1228 +} 1.1229 + 1.1230 +static int lrrect_radii(lua_State* L) { 1.1231 + int corner = SkToInt(lua_tointeger(L, 2)); 1.1232 + SkVector v; 1.1233 + if (corner < 0 || corner > 3) { 1.1234 + SkDebugf("bad corner index %d", corner); 1.1235 + v.set(0, 0); 1.1236 + } else { 1.1237 + v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner); 1.1238 + } 1.1239 + lua_pushnumber(L, v.fX); 1.1240 + lua_pushnumber(L, v.fY); 1.1241 + return 2; 1.1242 +} 1.1243 + 1.1244 +static int lrrect_gc(lua_State* L) { 1.1245 + get_obj<SkRRect>(L, 1)->~SkRRect(); 1.1246 + return 0; 1.1247 +} 1.1248 + 1.1249 +static const struct luaL_Reg gSkRRect_Methods[] = { 1.1250 + { "rect", lrrect_rect }, 1.1251 + { "type", lrrect_type }, 1.1252 + { "radii", lrrect_radii }, 1.1253 + { "__gc", lrrect_gc }, 1.1254 + { NULL, NULL } 1.1255 +}; 1.1256 + 1.1257 +/////////////////////////////////////////////////////////////////////////////// 1.1258 + 1.1259 +static int limage_width(lua_State* L) { 1.1260 + lua_pushinteger(L, get_ref<SkImage>(L, 1)->width()); 1.1261 + return 1; 1.1262 +} 1.1263 + 1.1264 +static int limage_height(lua_State* L) { 1.1265 + lua_pushinteger(L, get_ref<SkImage>(L, 1)->height()); 1.1266 + return 1; 1.1267 +} 1.1268 + 1.1269 +static int limage_gc(lua_State* L) { 1.1270 + get_ref<SkImage>(L, 1)->unref(); 1.1271 + return 0; 1.1272 +} 1.1273 + 1.1274 +static const struct luaL_Reg gSkImage_Methods[] = { 1.1275 + { "width", limage_width }, 1.1276 + { "height", limage_height }, 1.1277 + { "__gc", limage_gc }, 1.1278 + { NULL, NULL } 1.1279 +}; 1.1280 + 1.1281 +/////////////////////////////////////////////////////////////////////////////// 1.1282 + 1.1283 +static int ltypeface_gc(lua_State* L) { 1.1284 + SkSafeUnref(get_ref<SkTypeface>(L, 1)); 1.1285 + return 0; 1.1286 +} 1.1287 + 1.1288 +static const struct luaL_Reg gSkTypeface_Methods[] = { 1.1289 + { "__gc", ltypeface_gc }, 1.1290 + { NULL, NULL } 1.1291 +}; 1.1292 + 1.1293 +/////////////////////////////////////////////////////////////////////////////// 1.1294 + 1.1295 +class AutoCallLua { 1.1296 +public: 1.1297 + AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) { 1.1298 + lua_getglobal(L, func); 1.1299 + if (!lua_isfunction(L, -1)) { 1.1300 + int t = lua_type(L, -1); 1.1301 + SkDebugf("--- expected function %d\n", t); 1.1302 + } 1.1303 + 1.1304 + lua_newtable(L); 1.1305 + setfield_string(L, "verb", verb); 1.1306 + } 1.1307 + 1.1308 + ~AutoCallLua() { 1.1309 + if (lua_pcall(fL, 1, 0, 0) != LUA_OK) { 1.1310 + SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); 1.1311 + } 1.1312 + lua_settop(fL, -1); 1.1313 + } 1.1314 + 1.1315 +private: 1.1316 + lua_State* fL; 1.1317 +}; 1.1318 + 1.1319 +#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb) 1.1320 + 1.1321 +/////////////////////////////////////////////////////////////////////////////// 1.1322 + 1.1323 +static int lsk_newDocumentPDF(lua_State* L) { 1.1324 + const char* file = NULL; 1.1325 + if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { 1.1326 + file = lua_tolstring(L, 1, NULL); 1.1327 + } 1.1328 + 1.1329 + SkDocument* doc = SkDocument::CreatePDF(file); 1.1330 + if (NULL == doc) { 1.1331 + // do I need to push a nil on the stack and return 1? 1.1332 + return 0; 1.1333 + } else { 1.1334 + push_ref(L, doc); 1.1335 + doc->unref(); 1.1336 + return 1; 1.1337 + } 1.1338 +} 1.1339 + 1.1340 +static int lsk_newPaint(lua_State* L) { 1.1341 + push_new<SkPaint>(L); 1.1342 + return 1; 1.1343 +} 1.1344 + 1.1345 +static int lsk_newPath(lua_State* L) { 1.1346 + push_new<SkPath>(L); 1.1347 + return 1; 1.1348 +} 1.1349 + 1.1350 +static int lsk_newRRect(lua_State* L) { 1.1351 + SkRRect* rr = push_new<SkRRect>(L); 1.1352 + rr->setEmpty(); 1.1353 + return 1; 1.1354 +} 1.1355 + 1.1356 +static int lsk_newTypeface(lua_State* L) { 1.1357 + const char* name = NULL; 1.1358 + int style = SkTypeface::kNormal; 1.1359 + 1.1360 + int count = lua_gettop(L); 1.1361 + if (count > 0 && lua_isstring(L, 1)) { 1.1362 + name = lua_tolstring(L, 1, NULL); 1.1363 + if (count > 1 && lua_isnumber(L, 2)) { 1.1364 + style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic; 1.1365 + } 1.1366 + } 1.1367 + 1.1368 + SkTypeface* face = SkTypeface::CreateFromName(name, 1.1369 + (SkTypeface::Style)style); 1.1370 +// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt()); 1.1371 + if (NULL == face) { 1.1372 + face = SkTypeface::RefDefault(); 1.1373 + } 1.1374 + push_ref(L, face); 1.1375 + face->unref(); 1.1376 + return 1; 1.1377 +} 1.1378 + 1.1379 +static int lsk_loadImage(lua_State* L) { 1.1380 + if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { 1.1381 + const char* name = lua_tolstring(L, 1, NULL); 1.1382 + SkAutoDataUnref data(SkData::NewFromFileName(name)); 1.1383 + if (data.get()) { 1.1384 + SkImage* image = SkImage::NewEncodedData(data.get()); 1.1385 + if (image) { 1.1386 + push_ref(L, image); 1.1387 + image->unref(); 1.1388 + return 1; 1.1389 + } 1.1390 + } 1.1391 + } 1.1392 + return 0; 1.1393 +} 1.1394 + 1.1395 +static void register_Sk(lua_State* L) { 1.1396 + lua_newtable(L); 1.1397 + lua_pushvalue(L, -1); 1.1398 + lua_setglobal(L, "Sk"); 1.1399 + // the Sk table is still on top 1.1400 + 1.1401 + setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF); 1.1402 + setfield_function(L, "loadImage", lsk_loadImage); 1.1403 + setfield_function(L, "newPaint", lsk_newPaint); 1.1404 + setfield_function(L, "newPath", lsk_newPath); 1.1405 + setfield_function(L, "newRRect", lsk_newRRect); 1.1406 + setfield_function(L, "newTypeface", lsk_newTypeface); 1.1407 + lua_pop(L, 1); // pop off the Sk table 1.1408 +} 1.1409 + 1.1410 +#define REG_CLASS(L, C) \ 1.1411 + do { \ 1.1412 + luaL_newmetatable(L, get_mtname<C>()); \ 1.1413 + lua_pushvalue(L, -1); \ 1.1414 + lua_setfield(L, -2, "__index"); \ 1.1415 + luaL_setfuncs(L, g##C##_Methods, 0); \ 1.1416 + lua_pop(L, 1); /* pop off the meta-table */ \ 1.1417 + } while (0) 1.1418 + 1.1419 +void SkLua::Load(lua_State* L) { 1.1420 + register_Sk(L); 1.1421 + REG_CLASS(L, SkCanvas); 1.1422 + REG_CLASS(L, SkDocument); 1.1423 + REG_CLASS(L, SkImage); 1.1424 + REG_CLASS(L, SkPath); 1.1425 + REG_CLASS(L, SkPaint); 1.1426 + REG_CLASS(L, SkRRect); 1.1427 + REG_CLASS(L, SkShader); 1.1428 + REG_CLASS(L, SkTypeface); 1.1429 + REG_CLASS(L, SkMatrix); 1.1430 +} 1.1431 + 1.1432 +extern "C" int luaopen_skia(lua_State* L); 1.1433 +extern "C" int luaopen_skia(lua_State* L) { 1.1434 + SkLua::Load(L); 1.1435 + return 0; 1.1436 +}