gfx/skia/trunk/src/utils/SkLua.cpp

changeset 0
6474c204b198
     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 +}

mercurial