michael@0: /* michael@0: * Copyright 2013 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "SkLua.h" michael@0: michael@0: #if SK_SUPPORT_GPU michael@0: #include "GrReducedClip.h" michael@0: #endif michael@0: michael@0: #include "SkCanvas.h" michael@0: #include "SkData.h" michael@0: #include "SkDocument.h" michael@0: #include "SkImage.h" michael@0: #include "SkMatrix.h" michael@0: #include "SkPaint.h" michael@0: #include "SkPath.h" michael@0: #include "SkPixelRef.h" michael@0: #include "SkRRect.h" michael@0: #include "SkString.h" michael@0: #include "SkTypeface.h" michael@0: michael@0: extern "C" { michael@0: #include "lua.h" michael@0: #include "lualib.h" michael@0: #include "lauxlib.h" michael@0: } michael@0: michael@0: // return the metatable name for a given class michael@0: template const char* get_mtname(); michael@0: #define DEF_MTNAME(T) \ michael@0: template <> const char* get_mtname() { \ michael@0: return #T "_LuaMetaTableName"; \ michael@0: } michael@0: michael@0: DEF_MTNAME(SkCanvas) michael@0: DEF_MTNAME(SkDocument) michael@0: DEF_MTNAME(SkImage) michael@0: DEF_MTNAME(SkMatrix) michael@0: DEF_MTNAME(SkRRect) michael@0: DEF_MTNAME(SkPath) michael@0: DEF_MTNAME(SkPaint) michael@0: DEF_MTNAME(SkShader) michael@0: DEF_MTNAME(SkTypeface) michael@0: michael@0: template T* push_new(lua_State* L) { michael@0: T* addr = (T*)lua_newuserdata(L, sizeof(T)); michael@0: new (addr) T; michael@0: luaL_getmetatable(L, get_mtname()); michael@0: lua_setmetatable(L, -2); michael@0: return addr; michael@0: } michael@0: michael@0: template void push_obj(lua_State* L, const T& obj) { michael@0: new (lua_newuserdata(L, sizeof(T))) T(obj); michael@0: luaL_getmetatable(L, get_mtname()); michael@0: lua_setmetatable(L, -2); michael@0: } michael@0: michael@0: template void push_ref(lua_State* L, T* ref) { michael@0: *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref); michael@0: luaL_getmetatable(L, get_mtname()); michael@0: lua_setmetatable(L, -2); michael@0: } michael@0: michael@0: template T* get_ref(lua_State* L, int index) { michael@0: return *(T**)luaL_checkudata(L, index, get_mtname()); michael@0: } michael@0: michael@0: template T* get_obj(lua_State* L, int index) { michael@0: return (T*)luaL_checkudata(L, index, get_mtname()); michael@0: } michael@0: michael@0: static bool lua2bool(lua_State* L, int index) { michael@0: return !!lua_toboolean(L, index); michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) { michael@0: fL = luaL_newstate(); michael@0: luaL_openlibs(fL); michael@0: SkLua::Load(fL); michael@0: } michael@0: michael@0: SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {} michael@0: michael@0: SkLua::~SkLua() { michael@0: if (fWeOwnL) { michael@0: if (fTermCode.size() > 0) { michael@0: lua_getglobal(fL, fTermCode.c_str()); michael@0: if (lua_pcall(fL, 0, 0, 0) != LUA_OK) { michael@0: SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); michael@0: } michael@0: } michael@0: lua_close(fL); michael@0: } michael@0: } michael@0: michael@0: bool SkLua::runCode(const char code[]) { michael@0: int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0); michael@0: if (err) { michael@0: SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1)); michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool SkLua::runCode(const void* code, size_t size) { michael@0: SkString str((const char*)code, size); michael@0: return this->runCode(str.c_str()); michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: #define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0) michael@0: michael@0: static void setfield_bool_if(lua_State* L, const char key[], bool pred) { michael@0: if (pred) { michael@0: lua_pushboolean(L, true); michael@0: lua_setfield(L, -2, key); michael@0: } michael@0: } michael@0: michael@0: static void setfield_string(lua_State* L, const char key[], const char value[]) { michael@0: lua_pushstring(L, value); michael@0: lua_setfield(L, -2, key); michael@0: } michael@0: michael@0: static void setfield_number(lua_State* L, const char key[], double value) { michael@0: lua_pushnumber(L, value); michael@0: lua_setfield(L, -2, key); michael@0: } michael@0: michael@0: static void setfield_boolean(lua_State* L, const char key[], bool value) { michael@0: lua_pushboolean(L, value); michael@0: lua_setfield(L, -2, key); michael@0: } michael@0: michael@0: static void setfield_scalar(lua_State* L, const char key[], SkScalar value) { michael@0: setfield_number(L, key, SkScalarToLua(value)); michael@0: } michael@0: michael@0: static void setfield_function(lua_State* L, michael@0: const char key[], lua_CFunction value) { michael@0: lua_pushcfunction(L, value); michael@0: lua_setfield(L, -2, key); michael@0: } michael@0: michael@0: static void setarray_number(lua_State* L, int index, double value) { michael@0: lua_pushnumber(L, value); michael@0: lua_rawseti(L, -2, index); michael@0: } michael@0: michael@0: void SkLua::pushBool(bool value, const char key[]) { michael@0: lua_pushboolean(fL, value); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushString(const char str[], const char key[]) { michael@0: lua_pushstring(fL, str); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushString(const char str[], size_t length, const char key[]) { michael@0: // TODO: how to do this w/o making a copy? michael@0: SkString s(str, length); michael@0: lua_pushstring(fL, s.c_str()); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushString(const SkString& str, const char key[]) { michael@0: lua_pushstring(fL, str.c_str()); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushColor(SkColor color, const char key[]) { michael@0: lua_newtable(fL); michael@0: setfield_number(fL, "a", SkColorGetA(color) / 255.0); michael@0: setfield_number(fL, "r", SkColorGetR(color) / 255.0); michael@0: setfield_number(fL, "g", SkColorGetG(color) / 255.0); michael@0: setfield_number(fL, "b", SkColorGetB(color) / 255.0); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushU32(uint32_t value, const char key[]) { michael@0: lua_pushnumber(fL, (double)value); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushScalar(SkScalar value, const char key[]) { michael@0: lua_pushnumber(fL, SkScalarToLua(value)); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) { michael@0: lua_newtable(fL); michael@0: for (int i = 0; i < count; ++i) { michael@0: // make it base-1 to match lua convention michael@0: setarray_number(fL, i + 1, (double)array[i]); michael@0: } michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushRect(const SkRect& r, const char key[]) { michael@0: lua_newtable(fL); michael@0: setfield_scalar(fL, "left", r.fLeft); michael@0: setfield_scalar(fL, "top", r.fTop); michael@0: setfield_scalar(fL, "right", r.fRight); michael@0: setfield_scalar(fL, "bottom", r.fBottom); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushRRect(const SkRRect& rr, const char key[]) { michael@0: push_obj(fL, rr); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) { michael@0: push_obj(fL, matrix); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushPaint(const SkPaint& paint, const char key[]) { michael@0: push_obj(fL, paint); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushPath(const SkPath& path, const char key[]) { michael@0: push_obj(fL, path); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) { michael@0: push_ref(fL, canvas); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: static const char* element_type(SkClipStack::Element::Type type) { michael@0: switch (type) { michael@0: case SkClipStack::Element::kEmpty_Type: michael@0: return "empty"; michael@0: case SkClipStack::Element::kRect_Type: michael@0: return "rect"; michael@0: case SkClipStack::Element::kRRect_Type: michael@0: return "rrect"; michael@0: case SkClipStack::Element::kPath_Type: michael@0: return "path"; michael@0: } michael@0: return "unknown"; michael@0: } michael@0: michael@0: static const char* region_op(SkRegion::Op op) { michael@0: switch (op) { michael@0: case SkRegion::kDifference_Op: michael@0: return "difference"; michael@0: case SkRegion::kIntersect_Op: michael@0: return "intersect"; michael@0: case SkRegion::kUnion_Op: michael@0: return "union"; michael@0: case SkRegion::kXOR_Op: michael@0: return "xor"; michael@0: case SkRegion::kReverseDifference_Op: michael@0: return "reverse-difference"; michael@0: case SkRegion::kReplace_Op: michael@0: return "replace"; michael@0: } michael@0: return "unknown"; michael@0: } michael@0: michael@0: void SkLua::pushClipStack(const SkClipStack& stack, const char* key) { michael@0: lua_newtable(fL); michael@0: SkClipStack::B2TIter iter(stack); michael@0: const SkClipStack::Element* element; michael@0: int i = 0; michael@0: while (NULL != (element = iter.next())) { michael@0: this->pushClipStackElement(*element); michael@0: lua_rawseti(fL, -2, ++i); michael@0: } michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) { michael@0: lua_newtable(fL); michael@0: SkClipStack::Element::Type type = element.getType(); michael@0: this->pushString(element_type(type), "type"); michael@0: switch (type) { michael@0: case SkClipStack::Element::kEmpty_Type: michael@0: break; michael@0: case SkClipStack::Element::kRect_Type: michael@0: this->pushRect(element.getRect(), "rect"); michael@0: break; michael@0: case SkClipStack::Element::kRRect_Type: michael@0: this->pushRRect(element.getRRect(), "rrect"); michael@0: break; michael@0: case SkClipStack::Element::kPath_Type: michael@0: this->pushPath(element.getPath(), "path"); michael@0: break; michael@0: } michael@0: this->pushString(region_op(element.getOp()), "op"); michael@0: this->pushBool(element.isAA(), "aa"); michael@0: CHECK_SETFIELD(key); michael@0: } michael@0: michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static SkScalar lua2scalar(lua_State* L, int index) { michael@0: SkASSERT(lua_isnumber(L, index)); michael@0: return SkLuaToScalar(lua_tonumber(L, index)); michael@0: } michael@0: michael@0: static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) { michael@0: if (lua_isnumber(L, index)) { michael@0: return SkLuaToScalar(lua_tonumber(L, index)); michael@0: } else { michael@0: return defaultValue; michael@0: } michael@0: } michael@0: michael@0: static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) { michael@0: SkASSERT(lua_istable(L, index)); michael@0: lua_pushstring(L, key); michael@0: lua_gettable(L, index); michael@0: michael@0: SkScalar value = lua2scalar(L, -1); michael@0: lua_pop(L, 1); michael@0: return value; michael@0: } michael@0: michael@0: static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) { michael@0: SkASSERT(lua_istable(L, index)); michael@0: lua_pushstring(L, key); michael@0: lua_gettable(L, index); michael@0: michael@0: SkScalar value; michael@0: if (lua_isnil(L, -1)) { michael@0: value = def; michael@0: } else { michael@0: value = lua2scalar(L, -1); michael@0: } michael@0: lua_pop(L, 1); michael@0: return value; michael@0: } michael@0: michael@0: static U8CPU unit2byte(SkScalar x) { michael@0: if (x <= 0) { michael@0: return 0; michael@0: } else if (x >= 1) { michael@0: return 255; michael@0: } else { michael@0: return SkScalarRoundToInt(x * 255); michael@0: } michael@0: } michael@0: michael@0: static SkColor lua2color(lua_State* L, int index) { michael@0: return SkColorSetARGB(unit2byte(getfield_scalar(L, index, "a")), michael@0: unit2byte(getfield_scalar(L, index, "r")), michael@0: unit2byte(getfield_scalar(L, index, "g")), michael@0: unit2byte(getfield_scalar(L, index, "b"))); michael@0: } michael@0: michael@0: static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) { michael@0: rect->set(getfield_scalar_default(L, index, "left", 0), michael@0: getfield_scalar_default(L, index, "top", 0), michael@0: getfield_scalar(L, index, "right"), michael@0: getfield_scalar(L, index, "bottom")); michael@0: return rect; michael@0: } michael@0: michael@0: static int lcanvas_drawColor(lua_State* L) { michael@0: get_ref(L, 1)->drawColor(lua2color(L, 2)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_drawRect(lua_State* L) { michael@0: SkRect rect; michael@0: get_ref(L, 1)->drawRect(*lua2rect(L, 2, &rect), michael@0: *get_obj(L, 3)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_drawOval(lua_State* L) { michael@0: SkRect rect; michael@0: get_ref(L, 1)->drawOval(*lua2rect(L, 2, &rect), michael@0: *get_obj(L, 3)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_drawCircle(lua_State* L) { michael@0: get_ref(L, 1)->drawCircle(lua2scalar(L, 2), michael@0: lua2scalar(L, 3), michael@0: lua2scalar(L, 4), michael@0: *get_obj(L, 5)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_drawImage(lua_State* L) { michael@0: SkCanvas* canvas = get_ref(L, 1); michael@0: SkImage* image = get_ref(L, 2); michael@0: if (NULL == image) { michael@0: return 0; michael@0: } michael@0: SkScalar x = lua2scalar(L, 3); michael@0: SkScalar y = lua2scalar(L, 4); michael@0: michael@0: SkPaint paint; michael@0: const SkPaint* paintPtr = NULL; michael@0: if (lua_isnumber(L, 5)) { michael@0: paint.setAlpha(SkScalarRoundToInt(lua2scalar(L, 5) * 255)); michael@0: paintPtr = &paint; michael@0: } michael@0: image->draw(canvas, x, y, paintPtr); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_drawPath(lua_State* L) { michael@0: get_ref(L, 1)->drawPath(*get_obj(L, 2), michael@0: *get_obj(L, 3)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_drawText(lua_State* L) { michael@0: if (lua_gettop(L) < 5) { michael@0: return 0; michael@0: } michael@0: michael@0: if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) { michael@0: size_t len; michael@0: const char* text = lua_tolstring(L, 2, &len); michael@0: get_ref(L, 1)->drawText(text, len, michael@0: lua2scalar(L, 3), lua2scalar(L, 4), michael@0: *get_obj(L, 5)); michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_getSaveCount(lua_State* L) { michael@0: lua_pushnumber(L, get_ref(L, 1)->getSaveCount()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lcanvas_getTotalMatrix(lua_State* L) { michael@0: SkLua(L).pushMatrix(get_ref(L, 1)->getTotalMatrix()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lcanvas_getClipStack(lua_State* L) { michael@0: SkLua(L).pushClipStack(*get_ref(L, 1)->getClipStack()); michael@0: return 1; michael@0: } michael@0: michael@0: int SkLua::lcanvas_getReducedClipStack(lua_State* L) { michael@0: #if SK_SUPPORT_GPU michael@0: const SkCanvas* canvas = get_ref(L, 1); michael@0: SkISize layerSize = canvas->getTopLayerSize(); michael@0: SkIPoint layerOrigin = canvas->getTopLayerOrigin(); michael@0: SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY, michael@0: layerSize.fWidth, layerSize.fHeight); michael@0: michael@0: GrReducedClip::ElementList elements; michael@0: GrReducedClip::InitialState initialState; michael@0: int32_t genID; michael@0: SkIRect resultBounds; michael@0: michael@0: const SkClipStack& stack = *canvas->getClipStack(); michael@0: michael@0: GrReducedClip::ReduceClipStack(stack, michael@0: queryBounds, michael@0: &elements, michael@0: &genID, michael@0: &initialState, michael@0: &resultBounds, michael@0: NULL); michael@0: michael@0: GrReducedClip::ElementList::Iter iter(elements); michael@0: int i = 0; michael@0: lua_newtable(L); michael@0: while(NULL != iter.get()) { michael@0: SkLua(L).pushClipStackElement(*iter.get()); michael@0: iter.next(); michael@0: lua_rawseti(L, -2, ++i); michael@0: } michael@0: // Currently this only returns the element list to lua, not the initial state or result bounds. michael@0: // It could return these as additional items on the lua stack. michael@0: return 1; michael@0: #else michael@0: return 0; michael@0: #endif michael@0: } michael@0: michael@0: static int lcanvas_save(lua_State* L) { michael@0: lua_pushinteger(L, get_ref(L, 1)->save()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lcanvas_restore(lua_State* L) { michael@0: get_ref(L, 1)->restore(); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_scale(lua_State* L) { michael@0: SkScalar sx = lua2scalar_def(L, 2, 1); michael@0: SkScalar sy = lua2scalar_def(L, 3, sx); michael@0: get_ref(L, 1)->scale(sx, sy); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_translate(lua_State* L) { michael@0: SkScalar tx = lua2scalar_def(L, 2, 0); michael@0: SkScalar ty = lua2scalar_def(L, 3, 0); michael@0: get_ref(L, 1)->translate(tx, ty); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_rotate(lua_State* L) { michael@0: SkScalar degrees = lua2scalar_def(L, 2, 0); michael@0: get_ref(L, 1)->rotate(degrees); michael@0: return 0; michael@0: } michael@0: michael@0: static int lcanvas_gc(lua_State* L) { michael@0: get_ref(L, 1)->unref(); michael@0: return 0; michael@0: } michael@0: michael@0: const struct luaL_Reg gSkCanvas_Methods[] = { michael@0: { "drawColor", lcanvas_drawColor }, michael@0: { "drawRect", lcanvas_drawRect }, michael@0: { "drawOval", lcanvas_drawOval }, michael@0: { "drawCircle", lcanvas_drawCircle }, michael@0: { "drawImage", lcanvas_drawImage }, michael@0: { "drawPath", lcanvas_drawPath }, michael@0: { "drawText", lcanvas_drawText }, michael@0: { "getSaveCount", lcanvas_getSaveCount }, michael@0: { "getTotalMatrix", lcanvas_getTotalMatrix }, michael@0: { "getClipStack", lcanvas_getClipStack }, michael@0: #if SK_SUPPORT_GPU michael@0: { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack }, michael@0: #endif michael@0: { "save", lcanvas_save }, michael@0: { "restore", lcanvas_restore }, michael@0: { "scale", lcanvas_scale }, michael@0: { "translate", lcanvas_translate }, michael@0: { "rotate", lcanvas_rotate }, michael@0: { "__gc", lcanvas_gc }, michael@0: { NULL, NULL } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static int ldocument_beginPage(lua_State* L) { michael@0: const SkRect* contentPtr = NULL; michael@0: push_ref(L, get_ref(L, 1)->beginPage(lua2scalar(L, 2), michael@0: lua2scalar(L, 3), michael@0: contentPtr)); michael@0: return 1; michael@0: } michael@0: michael@0: static int ldocument_endPage(lua_State* L) { michael@0: get_ref(L, 1)->endPage(); michael@0: return 0; michael@0: } michael@0: michael@0: static int ldocument_close(lua_State* L) { michael@0: get_ref(L, 1)->close(); michael@0: return 0; michael@0: } michael@0: michael@0: static int ldocument_gc(lua_State* L) { michael@0: get_ref(L, 1)->unref(); michael@0: return 0; michael@0: } michael@0: michael@0: static const struct luaL_Reg gSkDocument_Methods[] = { michael@0: { "beginPage", ldocument_beginPage }, michael@0: { "endPage", ldocument_endPage }, michael@0: { "close", ldocument_close }, michael@0: { "__gc", ldocument_gc }, michael@0: { NULL, NULL } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static int lpaint_isAntiAlias(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isAntiAlias()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_setAntiAlias(lua_State* L) { michael@0: get_obj(L, 1)->setAntiAlias(lua2bool(L, 2)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpaint_isDither(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isDither()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isUnderlineText(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isUnderlineText()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isStrikeThruText(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isStrikeThruText()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isFakeBoldText(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isFakeBoldText()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isLinearText(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isLinearText()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isSubpixelText(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isSubpixelText()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isDevKernText(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isDevKernText()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isLCDRenderText(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isLCDRenderText()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isEmbeddedBitmapText(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isEmbeddedBitmapText()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isAutohinted(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isAutohinted()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_isVerticalText(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isVerticalText()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_getColor(lua_State* L) { michael@0: SkLua(L).pushColor(get_obj(L, 1)->getColor()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_setColor(lua_State* L) { michael@0: get_obj(L, 1)->setColor(lua2color(L, 2)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpaint_getTextSize(lua_State* L) { michael@0: SkLua(L).pushScalar(get_obj(L, 1)->getTextSize()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_getTextScaleX(lua_State* L) { michael@0: SkLua(L).pushScalar(get_obj(L, 1)->getTextScaleX()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_getTextSkewX(lua_State* L) { michael@0: SkLua(L).pushScalar(get_obj(L, 1)->getTextSkewX()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_setTextSize(lua_State* L) { michael@0: get_obj(L, 1)->setTextSize(lua2scalar(L, 2)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpaint_getTypeface(lua_State* L) { michael@0: push_ref(L, get_obj(L, 1)->getTypeface()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_setTypeface(lua_State* L) { michael@0: get_obj(L, 1)->setTypeface(get_ref(L, 2)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpaint_getHinting(lua_State* L) { michael@0: SkLua(L).pushU32(get_obj(L, 1)->getHinting()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_getFontID(lua_State* L) { michael@0: SkTypeface* face = get_obj(L, 1)->getTypeface(); michael@0: SkLua(L).pushU32(SkTypeface::UniqueID(face)); michael@0: return 1; michael@0: } michael@0: michael@0: static const struct { michael@0: const char* fLabel; michael@0: SkPaint::Align fAlign; michael@0: } gAlignRec[] = { michael@0: { "left", SkPaint::kLeft_Align }, michael@0: { "center", SkPaint::kCenter_Align }, michael@0: { "right", SkPaint::kRight_Align }, michael@0: }; michael@0: michael@0: static int lpaint_getTextAlign(lua_State* L) { michael@0: SkPaint::Align align = get_obj(L, 1)->getTextAlign(); michael@0: for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { michael@0: if (gAlignRec[i].fAlign == align) { michael@0: lua_pushstring(L, gAlignRec[i].fLabel); michael@0: return 1; michael@0: } michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: static int lpaint_setTextAlign(lua_State* L) { michael@0: if (lua_isstring(L, 2)) { michael@0: size_t len; michael@0: const char* label = lua_tolstring(L, 2, &len); michael@0: michael@0: for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { michael@0: if (!strcmp(gAlignRec[i].fLabel, label)) { michael@0: get_obj(L, 1)->setTextAlign(gAlignRec[i].fAlign); michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: static int lpaint_getStroke(lua_State* L) { michael@0: lua_pushboolean(L, SkPaint::kStroke_Style == get_obj(L, 1)->getStyle()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_setStroke(lua_State* L) { michael@0: SkPaint::Style style; michael@0: michael@0: if (lua_toboolean(L, 2)) { michael@0: style = SkPaint::kStroke_Style; michael@0: } else { michael@0: style = SkPaint::kFill_Style; michael@0: } michael@0: get_obj(L, 1)->setStyle(style); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpaint_getStrokeCap(lua_State* L) { michael@0: SkLua(L).pushU32(get_obj(L, 1)->getStrokeCap()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_getStrokeJoin(lua_State* L) { michael@0: SkLua(L).pushU32(get_obj(L, 1)->getStrokeJoin()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_getTextEncoding(lua_State* L) { michael@0: SkLua(L).pushU32(get_obj(L, 1)->getTextEncoding()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_getStrokeWidth(lua_State* L) { michael@0: SkLua(L).pushScalar(get_obj(L, 1)->getStrokeWidth()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_setStrokeWidth(lua_State* L) { michael@0: get_obj(L, 1)->setStrokeWidth(lua2scalar(L, 2)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpaint_getStrokeMiter(lua_State* L) { michael@0: SkLua(L).pushScalar(get_obj(L, 1)->getStrokeMiter()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_measureText(lua_State* L) { michael@0: if (lua_isstring(L, 2)) { michael@0: size_t len; michael@0: const char* text = lua_tolstring(L, 2, &len); michael@0: SkLua(L).pushScalar(get_obj(L, 1)->measureText(text, len)); michael@0: return 1; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: struct FontMetrics { michael@0: SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0) michael@0: SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0) michael@0: SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0) michael@0: SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0) michael@0: SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0) michael@0: SkScalar fAvgCharWidth; //!< the average charactor width (>= 0) michael@0: SkScalar fXMin; //!< The minimum bounding box x value for all glyphs michael@0: SkScalar fXMax; //!< The maximum bounding box x value for all glyphs michael@0: SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face michael@0: }; michael@0: michael@0: static int lpaint_getFontMetrics(lua_State* L) { michael@0: SkPaint::FontMetrics fm; michael@0: SkScalar height = get_obj(L, 1)->getFontMetrics(&fm); michael@0: michael@0: lua_newtable(L); michael@0: setfield_scalar(L, "top", fm.fTop); michael@0: setfield_scalar(L, "ascent", fm.fAscent); michael@0: setfield_scalar(L, "descent", fm.fDescent); michael@0: setfield_scalar(L, "bottom", fm.fBottom); michael@0: setfield_scalar(L, "leading", fm.fLeading); michael@0: SkLua(L).pushScalar(height); michael@0: return 2; michael@0: } michael@0: michael@0: static int lpaint_getEffects(lua_State* L) { michael@0: const SkPaint* paint = get_obj(L, 1); michael@0: michael@0: lua_newtable(L); michael@0: setfield_bool_if(L, "looper", !!paint->getLooper()); michael@0: setfield_bool_if(L, "pathEffect", !!paint->getPathEffect()); michael@0: setfield_bool_if(L, "rasterizer", !!paint->getRasterizer()); michael@0: setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter()); michael@0: setfield_bool_if(L, "shader", !!paint->getShader()); michael@0: setfield_bool_if(L, "colorFilter", !!paint->getColorFilter()); michael@0: setfield_bool_if(L, "imageFilter", !!paint->getImageFilter()); michael@0: setfield_bool_if(L, "xfermode", !!paint->getXfermode()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpaint_getShader(lua_State* L) { michael@0: const SkPaint* paint = get_obj(L, 1); michael@0: SkShader* shader = paint->getShader(); michael@0: if (shader) { michael@0: push_ref(L, shader); michael@0: return 1; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: static int lpaint_gc(lua_State* L) { michael@0: get_obj(L, 1)->~SkPaint(); michael@0: return 0; michael@0: } michael@0: michael@0: static const struct luaL_Reg gSkPaint_Methods[] = { michael@0: { "isAntiAlias", lpaint_isAntiAlias }, michael@0: { "setAntiAlias", lpaint_setAntiAlias }, michael@0: { "isDither", lpaint_isDither }, michael@0: { "isUnderlineText", lpaint_isUnderlineText }, michael@0: { "isStrikeThruText", lpaint_isStrikeThruText }, michael@0: { "isFakeBoldText", lpaint_isFakeBoldText }, michael@0: { "isLinearText", lpaint_isLinearText }, michael@0: { "isSubpixelText", lpaint_isSubpixelText }, michael@0: { "isDevKernText", lpaint_isDevKernText }, michael@0: { "isLCDRenderText", lpaint_isLCDRenderText }, michael@0: { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText }, michael@0: { "isAutohinted", lpaint_isAutohinted }, michael@0: { "isVerticalText", lpaint_isVerticalText }, michael@0: { "getColor", lpaint_getColor }, michael@0: { "setColor", lpaint_setColor }, michael@0: { "getTextSize", lpaint_getTextSize }, michael@0: { "setTextSize", lpaint_setTextSize }, michael@0: { "getTextScaleX", lpaint_getTextScaleX }, michael@0: { "getTextSkewX", lpaint_getTextSkewX }, michael@0: { "getTypeface", lpaint_getTypeface }, michael@0: { "setTypeface", lpaint_setTypeface }, michael@0: { "getHinting", lpaint_getHinting }, michael@0: { "getFontID", lpaint_getFontID }, michael@0: { "getTextAlign", lpaint_getTextAlign }, michael@0: { "setTextAlign", lpaint_setTextAlign }, michael@0: { "getStroke", lpaint_getStroke }, michael@0: { "setStroke", lpaint_setStroke }, michael@0: { "getStrokeCap", lpaint_getStrokeCap }, michael@0: { "getStrokeJoin", lpaint_getStrokeJoin }, michael@0: { "getTextEncoding", lpaint_getTextEncoding }, michael@0: { "getStrokeWidth", lpaint_getStrokeWidth }, michael@0: { "setStrokeWidth", lpaint_setStrokeWidth }, michael@0: { "getStrokeMiter", lpaint_getStrokeMiter }, michael@0: { "measureText", lpaint_measureText }, michael@0: { "getFontMetrics", lpaint_getFontMetrics }, michael@0: { "getEffects", lpaint_getEffects }, michael@0: { "getShader", lpaint_getShader }, michael@0: { "__gc", lpaint_gc }, michael@0: { NULL, NULL } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static const char* mode2string(SkShader::TileMode mode) { michael@0: static const char* gNames[] = { "clamp", "repeat", "mirror" }; michael@0: SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames)); michael@0: return gNames[mode]; michael@0: } michael@0: michael@0: static const char* gradtype2string(SkShader::GradientType t) { michael@0: static const char* gNames[] = { michael@0: "none", "color", "linear", "radial", "radial2", "sweep", "conical" michael@0: }; michael@0: SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames)); michael@0: return gNames[t]; michael@0: } michael@0: michael@0: static int lshader_isOpaque(lua_State* L) { michael@0: SkShader* shader = get_ref(L, 1); michael@0: return shader && shader->isOpaque(); michael@0: } michael@0: michael@0: static int lshader_asABitmap(lua_State* L) { michael@0: SkShader* shader = get_ref(L, 1); michael@0: if (shader) { michael@0: SkBitmap bm; michael@0: SkMatrix matrix; michael@0: SkShader::TileMode modes[2]; michael@0: switch (shader->asABitmap(&bm, &matrix, modes)) { michael@0: case SkShader::kDefault_BitmapType: michael@0: lua_newtable(L); michael@0: setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0); michael@0: setfield_number(L, "width", bm.width()); michael@0: setfield_number(L, "height", bm.height()); michael@0: setfield_string(L, "tileX", mode2string(modes[0])); michael@0: setfield_string(L, "tileY", mode2string(modes[1])); michael@0: return 1; michael@0: default: michael@0: break; michael@0: } michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: static int lshader_asAGradient(lua_State* L) { michael@0: SkShader* shader = get_ref(L, 1); michael@0: if (shader) { michael@0: SkShader::GradientInfo info; michael@0: sk_bzero(&info, sizeof(info)); michael@0: michael@0: SkColor colors[3]; // hacked in for extracting info on 3 color case. michael@0: SkScalar pos[3]; michael@0: michael@0: info.fColorCount = 3; michael@0: info.fColors = &colors[0]; michael@0: info.fColorOffsets = &pos[0]; michael@0: michael@0: SkShader::GradientType t = shader->asAGradient(&info); michael@0: michael@0: if (SkShader::kNone_GradientType != t) { michael@0: lua_newtable(L); michael@0: setfield_string(L, "type", gradtype2string(t)); michael@0: setfield_number(L, "colorCount", info.fColorCount); michael@0: setfield_string(L, "tile", mode2string(info.fTileMode)); michael@0: michael@0: if (info.fColorCount == 3){ michael@0: setfield_number(L, "midPos", pos[1]); michael@0: } michael@0: michael@0: return 1; michael@0: } michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: static int lshader_gc(lua_State* L) { michael@0: get_ref(L, 1)->unref(); michael@0: return 0; michael@0: } michael@0: michael@0: static const struct luaL_Reg gSkShader_Methods[] = { michael@0: { "isOpaque", lshader_isOpaque }, michael@0: { "asABitmap", lshader_asABitmap }, michael@0: { "asAGradient", lshader_asAGradient }, michael@0: { "__gc", lshader_gc }, michael@0: { NULL, NULL } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static int lmatrix_getType(lua_State* L) { michael@0: SkMatrix::TypeMask mask = get_obj(L, 1)->getType(); michael@0: michael@0: lua_newtable(L); michael@0: setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask)); michael@0: setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask)); michael@0: setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask)); michael@0: setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask)); michael@0: return 1; michael@0: } michael@0: michael@0: static int lmatrix_getScaleX(lua_State* L) { michael@0: lua_pushnumber(L, get_obj(L,1)->getScaleX()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lmatrix_getScaleY(lua_State* L) { michael@0: lua_pushnumber(L, get_obj(L,1)->getScaleY()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lmatrix_getTranslateX(lua_State* L) { michael@0: lua_pushnumber(L, get_obj(L,1)->getTranslateX()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lmatrix_getTranslateY(lua_State* L) { michael@0: lua_pushnumber(L, get_obj(L,1)->getTranslateY()); michael@0: return 1; michael@0: } michael@0: michael@0: static const struct luaL_Reg gSkMatrix_Methods[] = { michael@0: { "getType", lmatrix_getType }, michael@0: { "getScaleX", lmatrix_getScaleX }, michael@0: { "getScaleY", lmatrix_getScaleY }, michael@0: { "getTranslateX", lmatrix_getTranslateX }, michael@0: { "getTranslateY", lmatrix_getTranslateY }, michael@0: { NULL, NULL } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static int lpath_getBounds(lua_State* L) { michael@0: SkLua(L).pushRect(get_obj(L, 1)->getBounds()); michael@0: return 1; michael@0: } michael@0: michael@0: static const char* fill_type_to_str(SkPath::FillType fill) { michael@0: switch (fill) { michael@0: case SkPath::kEvenOdd_FillType: michael@0: return "even-odd"; michael@0: case SkPath::kWinding_FillType: michael@0: return "winding"; michael@0: case SkPath::kInverseEvenOdd_FillType: michael@0: return "inverse-even-odd"; michael@0: case SkPath::kInverseWinding_FillType: michael@0: return "inverse-winding"; michael@0: } michael@0: return "unknown"; michael@0: } michael@0: michael@0: static int lpath_getFillType(lua_State* L) { michael@0: SkPath::FillType fill = get_obj(L, 1)->getFillType(); michael@0: SkLua(L).pushString(fill_type_to_str(fill)); michael@0: return 1; michael@0: } michael@0: michael@0: static SkString segment_masks_to_str(uint32_t segmentMasks) { michael@0: SkString result; michael@0: bool first = true; michael@0: if (SkPath::kLine_SegmentMask & segmentMasks) { michael@0: result.append("line"); michael@0: first = false; michael@0: SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;) michael@0: } michael@0: if (SkPath::kQuad_SegmentMask & segmentMasks) { michael@0: if (!first) { michael@0: result.append(" "); michael@0: } michael@0: result.append("quad"); michael@0: first = false; michael@0: SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;) michael@0: } michael@0: if (SkPath::kConic_SegmentMask & segmentMasks) { michael@0: if (!first) { michael@0: result.append(" "); michael@0: } michael@0: result.append("conic"); michael@0: first = false; michael@0: SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;) michael@0: } michael@0: if (SkPath::kCubic_SegmentMask & segmentMasks) { michael@0: if (!first) { michael@0: result.append(" "); michael@0: } michael@0: result.append("cubic"); michael@0: SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;) michael@0: } michael@0: SkASSERT(0 == segmentMasks); michael@0: return result; michael@0: } michael@0: michael@0: static int lpath_getSegementTypes(lua_State* L) { michael@0: uint32_t segMasks = get_obj(L, 1)->getSegmentMasks(); michael@0: SkLua(L).pushString(segment_masks_to_str(segMasks)); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpath_isConvex(lua_State* L) { michael@0: bool isConvex = SkPath::kConvex_Convexity == get_obj(L, 1)->getConvexity(); michael@0: SkLua(L).pushBool(isConvex); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpath_isEmpty(lua_State* L) { michael@0: lua_pushboolean(L, get_obj(L, 1)->isEmpty()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpath_isRect(lua_State* L) { michael@0: SkRect r; michael@0: bool pred = get_obj(L, 1)->isRect(&r); michael@0: int ret_count = 1; michael@0: lua_pushboolean(L, pred); michael@0: if (pred) { michael@0: SkLua(L).pushRect(r); michael@0: ret_count += 1; michael@0: } michael@0: return ret_count; michael@0: } michael@0: michael@0: static const char* dir2string(SkPath::Direction dir) { michael@0: static const char* gStr[] = { michael@0: "unknown", "cw", "ccw" michael@0: }; michael@0: SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr)); michael@0: return gStr[dir]; michael@0: } michael@0: michael@0: static int lpath_isNestedRects(lua_State* L) { michael@0: SkRect rects[2]; michael@0: SkPath::Direction dirs[2]; michael@0: bool pred = get_obj(L, 1)->isNestedRects(rects, dirs); michael@0: int ret_count = 1; michael@0: lua_pushboolean(L, pred); michael@0: if (pred) { michael@0: SkLua lua(L); michael@0: lua.pushRect(rects[0]); michael@0: lua.pushRect(rects[1]); michael@0: lua_pushstring(L, dir2string(dirs[0])); michael@0: lua_pushstring(L, dir2string(dirs[0])); michael@0: ret_count += 4; michael@0: } michael@0: return ret_count; michael@0: } michael@0: michael@0: static int lpath_countPoints(lua_State* L) { michael@0: lua_pushinteger(L, get_obj(L, 1)->countPoints()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lpath_reset(lua_State* L) { michael@0: get_obj(L, 1)->reset(); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpath_moveTo(lua_State* L) { michael@0: get_obj(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpath_lineTo(lua_State* L) { michael@0: get_obj(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpath_quadTo(lua_State* L) { michael@0: get_obj(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3), michael@0: lua2scalar(L, 4), lua2scalar(L, 5)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpath_cubicTo(lua_State* L) { michael@0: get_obj(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3), michael@0: lua2scalar(L, 4), lua2scalar(L, 5), michael@0: lua2scalar(L, 6), lua2scalar(L, 7)); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpath_close(lua_State* L) { michael@0: get_obj(L, 1)->close(); michael@0: return 0; michael@0: } michael@0: michael@0: static int lpath_gc(lua_State* L) { michael@0: get_obj(L, 1)->~SkPath(); michael@0: return 0; michael@0: } michael@0: michael@0: static const struct luaL_Reg gSkPath_Methods[] = { michael@0: { "getBounds", lpath_getBounds }, michael@0: { "getFillType", lpath_getFillType }, michael@0: { "getSegmentTypes", lpath_getSegementTypes }, michael@0: { "isConvex", lpath_isConvex }, michael@0: { "isEmpty", lpath_isEmpty }, michael@0: { "isRect", lpath_isRect }, michael@0: { "isNestedRects", lpath_isNestedRects }, michael@0: { "countPoints", lpath_countPoints }, michael@0: { "reset", lpath_reset }, michael@0: { "moveTo", lpath_moveTo }, michael@0: { "lineTo", lpath_lineTo }, michael@0: { "quadTo", lpath_quadTo }, michael@0: { "cubicTo", lpath_cubicTo }, michael@0: { "close", lpath_close }, michael@0: { "__gc", lpath_gc }, michael@0: { NULL, NULL } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static const char* rrect_type(const SkRRect& rr) { michael@0: switch (rr.getType()) { michael@0: case SkRRect::kUnknown_Type: return "unknown"; michael@0: case SkRRect::kEmpty_Type: return "empty"; michael@0: case SkRRect::kRect_Type: return "rect"; michael@0: case SkRRect::kOval_Type: return "oval"; michael@0: case SkRRect::kSimple_Type: return "simple"; michael@0: case SkRRect::kComplex_Type: return "complex"; michael@0: } michael@0: SkDEBUGFAIL("never get here"); michael@0: return ""; michael@0: } michael@0: michael@0: static int lrrect_rect(lua_State* L) { michael@0: SkLua(L).pushRect(get_obj(L, 1)->rect()); michael@0: return 1; michael@0: } michael@0: michael@0: static int lrrect_type(lua_State* L) { michael@0: lua_pushstring(L, rrect_type(*get_obj(L, 1))); michael@0: return 1; michael@0: } michael@0: michael@0: static int lrrect_radii(lua_State* L) { michael@0: int corner = SkToInt(lua_tointeger(L, 2)); michael@0: SkVector v; michael@0: if (corner < 0 || corner > 3) { michael@0: SkDebugf("bad corner index %d", corner); michael@0: v.set(0, 0); michael@0: } else { michael@0: v = get_obj(L, 1)->radii((SkRRect::Corner)corner); michael@0: } michael@0: lua_pushnumber(L, v.fX); michael@0: lua_pushnumber(L, v.fY); michael@0: return 2; michael@0: } michael@0: michael@0: static int lrrect_gc(lua_State* L) { michael@0: get_obj(L, 1)->~SkRRect(); michael@0: return 0; michael@0: } michael@0: michael@0: static const struct luaL_Reg gSkRRect_Methods[] = { michael@0: { "rect", lrrect_rect }, michael@0: { "type", lrrect_type }, michael@0: { "radii", lrrect_radii }, michael@0: { "__gc", lrrect_gc }, michael@0: { NULL, NULL } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static int limage_width(lua_State* L) { michael@0: lua_pushinteger(L, get_ref(L, 1)->width()); michael@0: return 1; michael@0: } michael@0: michael@0: static int limage_height(lua_State* L) { michael@0: lua_pushinteger(L, get_ref(L, 1)->height()); michael@0: return 1; michael@0: } michael@0: michael@0: static int limage_gc(lua_State* L) { michael@0: get_ref(L, 1)->unref(); michael@0: return 0; michael@0: } michael@0: michael@0: static const struct luaL_Reg gSkImage_Methods[] = { michael@0: { "width", limage_width }, michael@0: { "height", limage_height }, michael@0: { "__gc", limage_gc }, michael@0: { NULL, NULL } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static int ltypeface_gc(lua_State* L) { michael@0: SkSafeUnref(get_ref(L, 1)); michael@0: return 0; michael@0: } michael@0: michael@0: static const struct luaL_Reg gSkTypeface_Methods[] = { michael@0: { "__gc", ltypeface_gc }, michael@0: { NULL, NULL } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: class AutoCallLua { michael@0: public: michael@0: AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) { michael@0: lua_getglobal(L, func); michael@0: if (!lua_isfunction(L, -1)) { michael@0: int t = lua_type(L, -1); michael@0: SkDebugf("--- expected function %d\n", t); michael@0: } michael@0: michael@0: lua_newtable(L); michael@0: setfield_string(L, "verb", verb); michael@0: } michael@0: michael@0: ~AutoCallLua() { michael@0: if (lua_pcall(fL, 1, 0, 0) != LUA_OK) { michael@0: SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); michael@0: } michael@0: lua_settop(fL, -1); michael@0: } michael@0: michael@0: private: michael@0: lua_State* fL; michael@0: }; michael@0: michael@0: #define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb) michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static int lsk_newDocumentPDF(lua_State* L) { michael@0: const char* file = NULL; michael@0: if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { michael@0: file = lua_tolstring(L, 1, NULL); michael@0: } michael@0: michael@0: SkDocument* doc = SkDocument::CreatePDF(file); michael@0: if (NULL == doc) { michael@0: // do I need to push a nil on the stack and return 1? michael@0: return 0; michael@0: } else { michael@0: push_ref(L, doc); michael@0: doc->unref(); michael@0: return 1; michael@0: } michael@0: } michael@0: michael@0: static int lsk_newPaint(lua_State* L) { michael@0: push_new(L); michael@0: return 1; michael@0: } michael@0: michael@0: static int lsk_newPath(lua_State* L) { michael@0: push_new(L); michael@0: return 1; michael@0: } michael@0: michael@0: static int lsk_newRRect(lua_State* L) { michael@0: SkRRect* rr = push_new(L); michael@0: rr->setEmpty(); michael@0: return 1; michael@0: } michael@0: michael@0: static int lsk_newTypeface(lua_State* L) { michael@0: const char* name = NULL; michael@0: int style = SkTypeface::kNormal; michael@0: michael@0: int count = lua_gettop(L); michael@0: if (count > 0 && lua_isstring(L, 1)) { michael@0: name = lua_tolstring(L, 1, NULL); michael@0: if (count > 1 && lua_isnumber(L, 2)) { michael@0: style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic; michael@0: } michael@0: } michael@0: michael@0: SkTypeface* face = SkTypeface::CreateFromName(name, michael@0: (SkTypeface::Style)style); michael@0: // SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt()); michael@0: if (NULL == face) { michael@0: face = SkTypeface::RefDefault(); michael@0: } michael@0: push_ref(L, face); michael@0: face->unref(); michael@0: return 1; michael@0: } michael@0: michael@0: static int lsk_loadImage(lua_State* L) { michael@0: if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { michael@0: const char* name = lua_tolstring(L, 1, NULL); michael@0: SkAutoDataUnref data(SkData::NewFromFileName(name)); michael@0: if (data.get()) { michael@0: SkImage* image = SkImage::NewEncodedData(data.get()); michael@0: if (image) { michael@0: push_ref(L, image); michael@0: image->unref(); michael@0: return 1; michael@0: } michael@0: } michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: static void register_Sk(lua_State* L) { michael@0: lua_newtable(L); michael@0: lua_pushvalue(L, -1); michael@0: lua_setglobal(L, "Sk"); michael@0: // the Sk table is still on top michael@0: michael@0: setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF); michael@0: setfield_function(L, "loadImage", lsk_loadImage); michael@0: setfield_function(L, "newPaint", lsk_newPaint); michael@0: setfield_function(L, "newPath", lsk_newPath); michael@0: setfield_function(L, "newRRect", lsk_newRRect); michael@0: setfield_function(L, "newTypeface", lsk_newTypeface); michael@0: lua_pop(L, 1); // pop off the Sk table michael@0: } michael@0: michael@0: #define REG_CLASS(L, C) \ michael@0: do { \ michael@0: luaL_newmetatable(L, get_mtname()); \ michael@0: lua_pushvalue(L, -1); \ michael@0: lua_setfield(L, -2, "__index"); \ michael@0: luaL_setfuncs(L, g##C##_Methods, 0); \ michael@0: lua_pop(L, 1); /* pop off the meta-table */ \ michael@0: } while (0) michael@0: michael@0: void SkLua::Load(lua_State* L) { michael@0: register_Sk(L); michael@0: REG_CLASS(L, SkCanvas); michael@0: REG_CLASS(L, SkDocument); michael@0: REG_CLASS(L, SkImage); michael@0: REG_CLASS(L, SkPath); michael@0: REG_CLASS(L, SkPaint); michael@0: REG_CLASS(L, SkRRect); michael@0: REG_CLASS(L, SkShader); michael@0: REG_CLASS(L, SkTypeface); michael@0: REG_CLASS(L, SkMatrix); michael@0: } michael@0: michael@0: extern "C" int luaopen_skia(lua_State* L); michael@0: extern "C" int luaopen_skia(lua_State* L) { michael@0: SkLua::Load(L); michael@0: return 0; michael@0: }