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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright 2013 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "SkLua.h"
    10 #if SK_SUPPORT_GPU
    11 #include "GrReducedClip.h"
    12 #endif
    14 #include "SkCanvas.h"
    15 #include "SkData.h"
    16 #include "SkDocument.h"
    17 #include "SkImage.h"
    18 #include "SkMatrix.h"
    19 #include "SkPaint.h"
    20 #include "SkPath.h"
    21 #include "SkPixelRef.h"
    22 #include "SkRRect.h"
    23 #include "SkString.h"
    24 #include "SkTypeface.h"
    26 extern "C" {
    27     #include "lua.h"
    28     #include "lualib.h"
    29     #include "lauxlib.h"
    30 }
    32 // return the metatable name for a given class
    33 template <typename T> const char* get_mtname();
    34 #define DEF_MTNAME(T)                           \
    35     template <> const char* get_mtname<T>() {   \
    36         return #T "_LuaMetaTableName";          \
    37     }
    39 DEF_MTNAME(SkCanvas)
    40 DEF_MTNAME(SkDocument)
    41 DEF_MTNAME(SkImage)
    42 DEF_MTNAME(SkMatrix)
    43 DEF_MTNAME(SkRRect)
    44 DEF_MTNAME(SkPath)
    45 DEF_MTNAME(SkPaint)
    46 DEF_MTNAME(SkShader)
    47 DEF_MTNAME(SkTypeface)
    49 template <typename T> T* push_new(lua_State* L) {
    50     T* addr = (T*)lua_newuserdata(L, sizeof(T));
    51     new (addr) T;
    52     luaL_getmetatable(L, get_mtname<T>());
    53     lua_setmetatable(L, -2);
    54     return addr;
    55 }
    57 template <typename T> void push_obj(lua_State* L, const T& obj) {
    58     new (lua_newuserdata(L, sizeof(T))) T(obj);
    59     luaL_getmetatable(L, get_mtname<T>());
    60     lua_setmetatable(L, -2);
    61 }
    63 template <typename T> void push_ref(lua_State* L, T* ref) {
    64     *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
    65     luaL_getmetatable(L, get_mtname<T>());
    66     lua_setmetatable(L, -2);
    67 }
    69 template <typename T> T* get_ref(lua_State* L, int index) {
    70     return *(T**)luaL_checkudata(L, index, get_mtname<T>());
    71 }
    73 template <typename T> T* get_obj(lua_State* L, int index) {
    74     return (T*)luaL_checkudata(L, index, get_mtname<T>());
    75 }
    77 static bool lua2bool(lua_State* L, int index) {
    78     return !!lua_toboolean(L, index);
    79 }
    81 ///////////////////////////////////////////////////////////////////////////////
    83 SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
    84     fL = luaL_newstate();
    85     luaL_openlibs(fL);
    86     SkLua::Load(fL);
    87 }
    89 SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
    91 SkLua::~SkLua() {
    92     if (fWeOwnL) {
    93         if (fTermCode.size() > 0) {
    94             lua_getglobal(fL, fTermCode.c_str());
    95             if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
    96                 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
    97             }
    98         }
    99         lua_close(fL);
   100     }
   101 }
   103 bool SkLua::runCode(const char code[]) {
   104     int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
   105     if (err) {
   106         SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
   107         return false;
   108     }
   109     return true;
   110 }
   112 bool SkLua::runCode(const void* code, size_t size) {
   113     SkString str((const char*)code, size);
   114     return this->runCode(str.c_str());
   115 }
   117 ///////////////////////////////////////////////////////////////////////////////
   119 #define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
   121 static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
   122     if (pred) {
   123         lua_pushboolean(L, true);
   124         lua_setfield(L, -2, key);
   125     }
   126 }
   128 static void setfield_string(lua_State* L, const char key[], const char value[]) {
   129     lua_pushstring(L, value);
   130     lua_setfield(L, -2, key);
   131 }
   133 static void setfield_number(lua_State* L, const char key[], double value) {
   134     lua_pushnumber(L, value);
   135     lua_setfield(L, -2, key);
   136 }
   138 static void setfield_boolean(lua_State* L, const char key[], bool value) {
   139     lua_pushboolean(L, value);
   140     lua_setfield(L, -2, key);
   141 }
   143 static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
   144     setfield_number(L, key, SkScalarToLua(value));
   145 }
   147 static void setfield_function(lua_State* L,
   148                               const char key[], lua_CFunction value) {
   149     lua_pushcfunction(L, value);
   150     lua_setfield(L, -2, key);
   151 }
   153 static void setarray_number(lua_State* L, int index, double value) {
   154     lua_pushnumber(L, value);
   155     lua_rawseti(L, -2, index);
   156 }
   158 void SkLua::pushBool(bool value, const char key[]) {
   159     lua_pushboolean(fL, value);
   160     CHECK_SETFIELD(key);
   161 }
   163 void SkLua::pushString(const char str[], const char key[]) {
   164     lua_pushstring(fL, str);
   165     CHECK_SETFIELD(key);
   166 }
   168 void SkLua::pushString(const char str[], size_t length, const char key[]) {
   169     // TODO: how to do this w/o making a copy?
   170     SkString s(str, length);
   171     lua_pushstring(fL, s.c_str());
   172     CHECK_SETFIELD(key);
   173 }
   175 void SkLua::pushString(const SkString& str, const char key[]) {
   176     lua_pushstring(fL, str.c_str());
   177     CHECK_SETFIELD(key);
   178 }
   180 void SkLua::pushColor(SkColor color, const char key[]) {
   181     lua_newtable(fL);
   182     setfield_number(fL, "a", SkColorGetA(color) / 255.0);
   183     setfield_number(fL, "r", SkColorGetR(color) / 255.0);
   184     setfield_number(fL, "g", SkColorGetG(color) / 255.0);
   185     setfield_number(fL, "b", SkColorGetB(color) / 255.0);
   186     CHECK_SETFIELD(key);
   187 }
   189 void SkLua::pushU32(uint32_t value, const char key[]) {
   190     lua_pushnumber(fL, (double)value);
   191     CHECK_SETFIELD(key);
   192 }
   194 void SkLua::pushScalar(SkScalar value, const char key[]) {
   195     lua_pushnumber(fL, SkScalarToLua(value));
   196     CHECK_SETFIELD(key);
   197 }
   199 void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
   200     lua_newtable(fL);
   201     for (int i = 0; i < count; ++i) {
   202         // make it base-1 to match lua convention
   203         setarray_number(fL, i + 1, (double)array[i]);
   204     }
   205     CHECK_SETFIELD(key);
   206 }
   208 void SkLua::pushRect(const SkRect& r, const char key[]) {
   209     lua_newtable(fL);
   210     setfield_scalar(fL, "left", r.fLeft);
   211     setfield_scalar(fL, "top", r.fTop);
   212     setfield_scalar(fL, "right", r.fRight);
   213     setfield_scalar(fL, "bottom", r.fBottom);
   214     CHECK_SETFIELD(key);
   215 }
   217 void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
   218     push_obj(fL, rr);
   219     CHECK_SETFIELD(key);
   220 }
   222 void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
   223     push_obj(fL, matrix);
   224     CHECK_SETFIELD(key);
   225 }
   227 void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
   228     push_obj(fL, paint);
   229     CHECK_SETFIELD(key);
   230 }
   232 void SkLua::pushPath(const SkPath& path, const char key[]) {
   233     push_obj(fL, path);
   234     CHECK_SETFIELD(key);
   235 }
   237 void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
   238     push_ref(fL, canvas);
   239     CHECK_SETFIELD(key);
   240 }
   242 static const char* element_type(SkClipStack::Element::Type type) {
   243     switch (type) {
   244         case SkClipStack::Element::kEmpty_Type:
   245             return "empty";
   246         case SkClipStack::Element::kRect_Type:
   247             return "rect";
   248         case SkClipStack::Element::kRRect_Type:
   249             return "rrect";
   250         case SkClipStack::Element::kPath_Type:
   251             return "path";
   252     }
   253     return "unknown";
   254 }
   256 static const char* region_op(SkRegion::Op op) {
   257     switch (op) {
   258         case SkRegion::kDifference_Op:
   259             return "difference";
   260         case SkRegion::kIntersect_Op:
   261             return "intersect";
   262         case SkRegion::kUnion_Op:
   263             return "union";
   264         case SkRegion::kXOR_Op:
   265             return "xor";
   266         case SkRegion::kReverseDifference_Op:
   267             return "reverse-difference";
   268         case SkRegion::kReplace_Op:
   269             return "replace";
   270     }
   271     return "unknown";
   272 }
   274 void SkLua::pushClipStack(const SkClipStack& stack, const char* key) {
   275     lua_newtable(fL);
   276     SkClipStack::B2TIter iter(stack);
   277     const SkClipStack::Element* element;
   278     int i = 0;
   279     while (NULL != (element = iter.next())) {
   280         this->pushClipStackElement(*element);
   281         lua_rawseti(fL, -2, ++i);
   282     }
   283     CHECK_SETFIELD(key);
   284 }
   286 void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) {
   287     lua_newtable(fL);
   288     SkClipStack::Element::Type type = element.getType();
   289     this->pushString(element_type(type), "type");
   290     switch (type) {
   291         case SkClipStack::Element::kEmpty_Type:
   292             break;
   293         case SkClipStack::Element::kRect_Type:
   294             this->pushRect(element.getRect(), "rect");
   295             break;
   296         case SkClipStack::Element::kRRect_Type:
   297             this->pushRRect(element.getRRect(), "rrect");
   298             break;
   299         case SkClipStack::Element::kPath_Type:
   300             this->pushPath(element.getPath(), "path");
   301             break;
   302     }
   303     this->pushString(region_op(element.getOp()), "op");
   304     this->pushBool(element.isAA(), "aa");
   305     CHECK_SETFIELD(key);
   306 }
   309 ///////////////////////////////////////////////////////////////////////////////
   310 ///////////////////////////////////////////////////////////////////////////////
   312 static SkScalar lua2scalar(lua_State* L, int index) {
   313     SkASSERT(lua_isnumber(L, index));
   314     return SkLuaToScalar(lua_tonumber(L, index));
   315 }
   317 static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
   318     if (lua_isnumber(L, index)) {
   319         return SkLuaToScalar(lua_tonumber(L, index));
   320     } else {
   321         return defaultValue;
   322     }
   323 }
   325 static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
   326     SkASSERT(lua_istable(L, index));
   327     lua_pushstring(L, key);
   328     lua_gettable(L, index);
   330     SkScalar value = lua2scalar(L, -1);
   331     lua_pop(L, 1);
   332     return value;
   333 }
   335 static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
   336     SkASSERT(lua_istable(L, index));
   337     lua_pushstring(L, key);
   338     lua_gettable(L, index);
   340     SkScalar value;
   341     if (lua_isnil(L, -1)) {
   342         value = def;
   343     } else {
   344         value = lua2scalar(L, -1);
   345     }
   346     lua_pop(L, 1);
   347     return value;
   348 }
   350 static U8CPU unit2byte(SkScalar x) {
   351     if (x <= 0) {
   352         return 0;
   353     } else if (x >= 1) {
   354         return 255;
   355     } else {
   356         return SkScalarRoundToInt(x * 255);
   357     }
   358 }
   360 static SkColor lua2color(lua_State* L, int index) {
   361     return SkColorSetARGB(unit2byte(getfield_scalar(L, index, "a")),
   362                           unit2byte(getfield_scalar(L, index, "r")),
   363                           unit2byte(getfield_scalar(L, index, "g")),
   364                           unit2byte(getfield_scalar(L, index, "b")));
   365 }
   367 static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
   368     rect->set(getfield_scalar_default(L, index, "left", 0),
   369               getfield_scalar_default(L, index, "top", 0),
   370               getfield_scalar(L, index, "right"),
   371               getfield_scalar(L, index, "bottom"));
   372     return rect;
   373 }
   375 static int lcanvas_drawColor(lua_State* L) {
   376     get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
   377     return 0;
   378 }
   380 static int lcanvas_drawRect(lua_State* L) {
   381     SkRect rect;
   382     get_ref<SkCanvas>(L, 1)->drawRect(*lua2rect(L, 2, &rect),
   383                                       *get_obj<SkPaint>(L, 3));
   384     return 0;
   385 }
   387 static int lcanvas_drawOval(lua_State* L) {
   388     SkRect rect;
   389     get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
   390                                       *get_obj<SkPaint>(L, 3));
   391     return 0;
   392 }
   394 static int lcanvas_drawCircle(lua_State* L) {
   395     get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
   396                                         lua2scalar(L, 3),
   397                                         lua2scalar(L, 4),
   398                                         *get_obj<SkPaint>(L, 5));
   399     return 0;
   400 }
   402 static int lcanvas_drawImage(lua_State* L) {
   403     SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
   404     SkImage* image = get_ref<SkImage>(L, 2);
   405     if (NULL == image) {
   406         return 0;
   407     }
   408     SkScalar x = lua2scalar(L, 3);
   409     SkScalar y = lua2scalar(L, 4);
   411     SkPaint paint;
   412     const SkPaint* paintPtr = NULL;
   413     if (lua_isnumber(L, 5)) {
   414         paint.setAlpha(SkScalarRoundToInt(lua2scalar(L, 5) * 255));
   415         paintPtr = &paint;
   416     }
   417     image->draw(canvas, x, y, paintPtr);
   418     return 0;
   419 }
   421 static int lcanvas_drawPath(lua_State* L) {
   422     get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
   423                                       *get_obj<SkPaint>(L, 3));
   424     return 0;
   425 }
   427 static int lcanvas_drawText(lua_State* L) {
   428     if (lua_gettop(L) < 5) {
   429         return 0;
   430     }
   432     if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
   433         size_t len;
   434         const char* text = lua_tolstring(L, 2, &len);
   435         get_ref<SkCanvas>(L, 1)->drawText(text, len,
   436                                           lua2scalar(L, 3), lua2scalar(L, 4),
   437                                           *get_obj<SkPaint>(L, 5));
   438     }
   439     return 0;
   440 }
   442 static int lcanvas_getSaveCount(lua_State* L) {
   443     lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
   444     return 1;
   445 }
   447 static int lcanvas_getTotalMatrix(lua_State* L) {
   448     SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
   449     return 1;
   450 }
   452 static int lcanvas_getClipStack(lua_State* L) {
   453     SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack());
   454     return 1;
   455 }
   457 int SkLua::lcanvas_getReducedClipStack(lua_State* L) {
   458 #if SK_SUPPORT_GPU
   459     const SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
   460     SkISize layerSize = canvas->getTopLayerSize();
   461     SkIPoint layerOrigin = canvas->getTopLayerOrigin();
   462     SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY,
   463                                             layerSize.fWidth, layerSize.fHeight);
   465     GrReducedClip::ElementList elements;
   466     GrReducedClip::InitialState initialState;
   467     int32_t genID;
   468     SkIRect resultBounds;
   470     const SkClipStack& stack = *canvas->getClipStack();
   472     GrReducedClip::ReduceClipStack(stack,
   473                                    queryBounds,
   474                                    &elements,
   475                                    &genID,
   476                                    &initialState,
   477                                    &resultBounds,
   478                                    NULL);
   480     GrReducedClip::ElementList::Iter iter(elements);
   481     int i = 0;
   482     lua_newtable(L);
   483     while(NULL != iter.get()) {
   484         SkLua(L).pushClipStackElement(*iter.get());
   485         iter.next();
   486         lua_rawseti(L, -2, ++i);
   487     }
   488     // Currently this only returns the element list to lua, not the initial state or result bounds.
   489     // It could return these as additional items on the lua stack.
   490     return 1;
   491 #else
   492     return 0;
   493 #endif
   494 }
   496 static int lcanvas_save(lua_State* L) {
   497     lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
   498     return 1;
   499 }
   501 static int lcanvas_restore(lua_State* L) {
   502     get_ref<SkCanvas>(L, 1)->restore();
   503     return 0;
   504 }
   506 static int lcanvas_scale(lua_State* L) {
   507     SkScalar sx = lua2scalar_def(L, 2, 1);
   508     SkScalar sy = lua2scalar_def(L, 3, sx);
   509     get_ref<SkCanvas>(L, 1)->scale(sx, sy);
   510     return 0;
   511 }
   513 static int lcanvas_translate(lua_State* L) {
   514     SkScalar tx = lua2scalar_def(L, 2, 0);
   515     SkScalar ty = lua2scalar_def(L, 3, 0);
   516     get_ref<SkCanvas>(L, 1)->translate(tx, ty);
   517     return 0;
   518 }
   520 static int lcanvas_rotate(lua_State* L) {
   521     SkScalar degrees = lua2scalar_def(L, 2, 0);
   522     get_ref<SkCanvas>(L, 1)->rotate(degrees);
   523     return 0;
   524 }
   526 static int lcanvas_gc(lua_State* L) {
   527     get_ref<SkCanvas>(L, 1)->unref();
   528     return 0;
   529 }
   531 const struct luaL_Reg gSkCanvas_Methods[] = {
   532     { "drawColor", lcanvas_drawColor },
   533     { "drawRect", lcanvas_drawRect },
   534     { "drawOval", lcanvas_drawOval },
   535     { "drawCircle", lcanvas_drawCircle },
   536     { "drawImage", lcanvas_drawImage },
   537     { "drawPath", lcanvas_drawPath },
   538     { "drawText", lcanvas_drawText },
   539     { "getSaveCount", lcanvas_getSaveCount },
   540     { "getTotalMatrix", lcanvas_getTotalMatrix },
   541     { "getClipStack", lcanvas_getClipStack },
   542 #if SK_SUPPORT_GPU
   543     { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
   544 #endif
   545     { "save", lcanvas_save },
   546     { "restore", lcanvas_restore },
   547     { "scale", lcanvas_scale },
   548     { "translate", lcanvas_translate },
   549     { "rotate", lcanvas_rotate },
   550     { "__gc", lcanvas_gc },
   551     { NULL, NULL }
   552 };
   554 ///////////////////////////////////////////////////////////////////////////////
   556 static int ldocument_beginPage(lua_State* L) {
   557     const SkRect* contentPtr = NULL;
   558     push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2),
   559                                                      lua2scalar(L, 3),
   560                                                      contentPtr));
   561     return 1;
   562 }
   564 static int ldocument_endPage(lua_State* L) {
   565     get_ref<SkDocument>(L, 1)->endPage();
   566     return 0;
   567 }
   569 static int ldocument_close(lua_State* L) {
   570     get_ref<SkDocument>(L, 1)->close();
   571     return 0;
   572 }
   574 static int ldocument_gc(lua_State* L) {
   575     get_ref<SkDocument>(L, 1)->unref();
   576     return 0;
   577 }
   579 static const struct luaL_Reg gSkDocument_Methods[] = {
   580     { "beginPage", ldocument_beginPage },
   581     { "endPage", ldocument_endPage },
   582     { "close", ldocument_close },
   583     { "__gc", ldocument_gc },
   584     { NULL, NULL }
   585 };
   587 ///////////////////////////////////////////////////////////////////////////////
   589 static int lpaint_isAntiAlias(lua_State* L) {
   590     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
   591     return 1;
   592 }
   594 static int lpaint_setAntiAlias(lua_State* L) {
   595     get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
   596     return 0;
   597 }
   599 static int lpaint_isDither(lua_State* L) {
   600     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
   601     return 1;
   602 }
   604 static int lpaint_isUnderlineText(lua_State* L) {
   605     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText());
   606     return 1;
   607 }
   609 static int lpaint_isStrikeThruText(lua_State* L) {
   610     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText());
   611     return 1;
   612 }
   614 static int lpaint_isFakeBoldText(lua_State* L) {
   615     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
   616     return 1;
   617 }
   619 static int lpaint_isLinearText(lua_State* L) {
   620     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
   621     return 1;
   622 }
   624 static int lpaint_isSubpixelText(lua_State* L) {
   625     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
   626     return 1;
   627 }
   629 static int lpaint_isDevKernText(lua_State* L) {
   630     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
   631     return 1;
   632 }
   634 static int lpaint_isLCDRenderText(lua_State* L) {
   635     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
   636     return 1;
   637 }
   639 static int lpaint_isEmbeddedBitmapText(lua_State* L) {
   640     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
   641     return 1;
   642 }
   644 static int lpaint_isAutohinted(lua_State* L) {
   645     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
   646     return 1;
   647 }
   649 static int lpaint_isVerticalText(lua_State* L) {
   650     lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
   651     return 1;
   652 }
   654 static int lpaint_getColor(lua_State* L) {
   655     SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
   656     return 1;
   657 }
   659 static int lpaint_setColor(lua_State* L) {
   660     get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
   661     return 0;
   662 }
   664 static int lpaint_getTextSize(lua_State* L) {
   665     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
   666     return 1;
   667 }
   669 static int lpaint_getTextScaleX(lua_State* L) {
   670     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
   671     return 1;
   672 }
   674 static int lpaint_getTextSkewX(lua_State* L) {
   675     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
   676     return 1;
   677 }
   679 static int lpaint_setTextSize(lua_State* L) {
   680     get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
   681     return 0;
   682 }
   684 static int lpaint_getTypeface(lua_State* L) {
   685     push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
   686     return 1;
   687 }
   689 static int lpaint_setTypeface(lua_State* L) {
   690     get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2));
   691     return 0;
   692 }
   694 static int lpaint_getHinting(lua_State* L) {
   695     SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
   696     return 1;
   697 }
   699 static int lpaint_getFontID(lua_State* L) {
   700     SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
   701     SkLua(L).pushU32(SkTypeface::UniqueID(face));
   702     return 1;
   703 }
   705 static const struct {
   706     const char*     fLabel;
   707     SkPaint::Align  fAlign;
   708 } gAlignRec[] = {
   709     { "left",   SkPaint::kLeft_Align },
   710     { "center", SkPaint::kCenter_Align },
   711     { "right",  SkPaint::kRight_Align },
   712 };
   714 static int lpaint_getTextAlign(lua_State* L) {
   715     SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
   716     for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
   717         if (gAlignRec[i].fAlign == align) {
   718             lua_pushstring(L, gAlignRec[i].fLabel);
   719             return 1;
   720         }
   721     }
   722     return 0;
   723 }
   725 static int lpaint_setTextAlign(lua_State* L) {
   726     if (lua_isstring(L, 2)) {
   727         size_t len;
   728         const char* label = lua_tolstring(L, 2, &len);
   730         for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
   731             if (!strcmp(gAlignRec[i].fLabel, label)) {
   732                 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
   733                 break;
   734             }
   735         }
   736     }
   737     return 0;
   738 }
   740 static int lpaint_getStroke(lua_State* L) {
   741     lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
   742     return 1;
   743 }
   745 static int lpaint_setStroke(lua_State* L) {
   746     SkPaint::Style style;
   748     if (lua_toboolean(L, 2)) {
   749         style = SkPaint::kStroke_Style;
   750     } else {
   751         style = SkPaint::kFill_Style;
   752     }
   753     get_obj<SkPaint>(L, 1)->setStyle(style);
   754     return 0;
   755 }
   757 static int lpaint_getStrokeCap(lua_State* L) {
   758     SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
   759     return 1;
   760 }
   762 static int lpaint_getStrokeJoin(lua_State* L) {
   763     SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
   764     return 1;
   765 }
   767 static int lpaint_getTextEncoding(lua_State* L) {
   768     SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
   769     return 1;
   770 }
   772 static int lpaint_getStrokeWidth(lua_State* L) {
   773     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
   774     return 1;
   775 }
   777 static int lpaint_setStrokeWidth(lua_State* L) {
   778     get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
   779     return 0;
   780 }
   782 static int lpaint_getStrokeMiter(lua_State* L) {
   783     SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
   784     return 1;
   785 }
   787 static int lpaint_measureText(lua_State* L) {
   788     if (lua_isstring(L, 2)) {
   789         size_t len;
   790         const char* text = lua_tolstring(L, 2, &len);
   791         SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
   792         return 1;
   793     }
   794     return 0;
   795 }
   797 struct FontMetrics {
   798     SkScalar    fTop;       //!< The greatest distance above the baseline for any glyph (will be <= 0)
   799     SkScalar    fAscent;    //!< The recommended distance above the baseline (will be <= 0)
   800     SkScalar    fDescent;   //!< The recommended distance below the baseline (will be >= 0)
   801     SkScalar    fBottom;    //!< The greatest distance below the baseline for any glyph (will be >= 0)
   802     SkScalar    fLeading;   //!< The recommended distance to add between lines of text (will be >= 0)
   803     SkScalar    fAvgCharWidth;  //!< the average charactor width (>= 0)
   804     SkScalar    fXMin;      //!< The minimum bounding box x value for all glyphs
   805     SkScalar    fXMax;      //!< The maximum bounding box x value for all glyphs
   806     SkScalar    fXHeight;   //!< the height of an 'x' in px, or 0 if no 'x' in face
   807 };
   809 static int lpaint_getFontMetrics(lua_State* L) {
   810     SkPaint::FontMetrics fm;
   811     SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
   813     lua_newtable(L);
   814     setfield_scalar(L, "top", fm.fTop);
   815     setfield_scalar(L, "ascent", fm.fAscent);
   816     setfield_scalar(L, "descent", fm.fDescent);
   817     setfield_scalar(L, "bottom", fm.fBottom);
   818     setfield_scalar(L, "leading", fm.fLeading);
   819     SkLua(L).pushScalar(height);
   820     return 2;
   821 }
   823 static int lpaint_getEffects(lua_State* L) {
   824     const SkPaint* paint = get_obj<SkPaint>(L, 1);
   826     lua_newtable(L);
   827     setfield_bool_if(L, "looper", !!paint->getLooper());
   828     setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
   829     setfield_bool_if(L, "rasterizer", !!paint->getRasterizer());
   830     setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
   831     setfield_bool_if(L, "shader", !!paint->getShader());
   832     setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
   833     setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
   834     setfield_bool_if(L, "xfermode", !!paint->getXfermode());
   835     return 1;
   836 }
   838 static int lpaint_getShader(lua_State* L) {
   839     const SkPaint* paint = get_obj<SkPaint>(L, 1);
   840     SkShader* shader = paint->getShader();
   841     if (shader) {
   842         push_ref(L, shader);
   843         return 1;
   844     }
   845     return 0;
   846 }
   848 static int lpaint_gc(lua_State* L) {
   849     get_obj<SkPaint>(L, 1)->~SkPaint();
   850     return 0;
   851 }
   853 static const struct luaL_Reg gSkPaint_Methods[] = {
   854     { "isAntiAlias", lpaint_isAntiAlias },
   855     { "setAntiAlias", lpaint_setAntiAlias },
   856     { "isDither", lpaint_isDither },
   857     { "isUnderlineText", lpaint_isUnderlineText },
   858     { "isStrikeThruText", lpaint_isStrikeThruText },
   859     { "isFakeBoldText", lpaint_isFakeBoldText },
   860     { "isLinearText", lpaint_isLinearText },
   861     { "isSubpixelText", lpaint_isSubpixelText },
   862     { "isDevKernText", lpaint_isDevKernText },
   863     { "isLCDRenderText", lpaint_isLCDRenderText },
   864     { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
   865     { "isAutohinted", lpaint_isAutohinted },
   866     { "isVerticalText", lpaint_isVerticalText },
   867     { "getColor", lpaint_getColor },
   868     { "setColor", lpaint_setColor },
   869     { "getTextSize", lpaint_getTextSize },
   870     { "setTextSize", lpaint_setTextSize },
   871     { "getTextScaleX", lpaint_getTextScaleX },
   872     { "getTextSkewX", lpaint_getTextSkewX },
   873     { "getTypeface", lpaint_getTypeface },
   874     { "setTypeface", lpaint_setTypeface },
   875     { "getHinting", lpaint_getHinting },
   876     { "getFontID", lpaint_getFontID },
   877     { "getTextAlign", lpaint_getTextAlign },
   878     { "setTextAlign", lpaint_setTextAlign },
   879     { "getStroke", lpaint_getStroke },
   880     { "setStroke", lpaint_setStroke },
   881     { "getStrokeCap", lpaint_getStrokeCap },
   882     { "getStrokeJoin", lpaint_getStrokeJoin },
   883     { "getTextEncoding", lpaint_getTextEncoding },
   884     { "getStrokeWidth", lpaint_getStrokeWidth },
   885     { "setStrokeWidth", lpaint_setStrokeWidth },
   886     { "getStrokeMiter", lpaint_getStrokeMiter },
   887     { "measureText", lpaint_measureText },
   888     { "getFontMetrics", lpaint_getFontMetrics },
   889     { "getEffects", lpaint_getEffects },
   890     { "getShader", lpaint_getShader },
   891     { "__gc", lpaint_gc },
   892     { NULL, NULL }
   893 };
   895 ///////////////////////////////////////////////////////////////////////////////
   897 static const char* mode2string(SkShader::TileMode mode) {
   898     static const char* gNames[] = { "clamp", "repeat", "mirror" };
   899     SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
   900     return gNames[mode];
   901 }
   903 static const char* gradtype2string(SkShader::GradientType t) {
   904     static const char* gNames[] = {
   905         "none", "color", "linear", "radial", "radial2", "sweep", "conical"
   906     };
   907     SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
   908     return gNames[t];
   909 }
   911 static int lshader_isOpaque(lua_State* L) {
   912     SkShader* shader = get_ref<SkShader>(L, 1);
   913     return shader && shader->isOpaque();
   914 }
   916 static int lshader_asABitmap(lua_State* L) {
   917     SkShader* shader = get_ref<SkShader>(L, 1);
   918     if (shader) {
   919         SkBitmap bm;
   920         SkMatrix matrix;
   921         SkShader::TileMode modes[2];
   922         switch (shader->asABitmap(&bm, &matrix, modes)) {
   923             case SkShader::kDefault_BitmapType:
   924                 lua_newtable(L);
   925                 setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0);
   926                 setfield_number(L, "width", bm.width());
   927                 setfield_number(L, "height", bm.height());
   928                 setfield_string(L, "tileX", mode2string(modes[0]));
   929                 setfield_string(L, "tileY", mode2string(modes[1]));
   930                 return 1;
   931             default:
   932                 break;
   933         }
   934     }
   935     return 0;
   936 }
   938 static int lshader_asAGradient(lua_State* L) {
   939     SkShader* shader = get_ref<SkShader>(L, 1);
   940     if (shader) {
   941         SkShader::GradientInfo info;
   942         sk_bzero(&info, sizeof(info));
   944         SkColor colors[3];  // hacked in for extracting info on 3 color case.
   945         SkScalar pos[3];
   947         info.fColorCount = 3;
   948         info.fColors = &colors[0];
   949         info.fColorOffsets = &pos[0];
   951         SkShader::GradientType t = shader->asAGradient(&info);
   953         if (SkShader::kNone_GradientType != t) {
   954             lua_newtable(L);
   955             setfield_string(L, "type", gradtype2string(t));
   956             setfield_number(L, "colorCount", info.fColorCount);
   957             setfield_string(L, "tile", mode2string(info.fTileMode));
   959             if (info.fColorCount == 3){
   960                 setfield_number(L, "midPos", pos[1]);
   961             }
   963             return 1;
   964         }
   965     }
   966     return 0;
   967 }
   969 static int lshader_gc(lua_State* L) {
   970     get_ref<SkShader>(L, 1)->unref();
   971     return 0;
   972 }
   974 static const struct luaL_Reg gSkShader_Methods[] = {
   975     { "isOpaque",       lshader_isOpaque },
   976     { "asABitmap",      lshader_asABitmap },
   977     { "asAGradient",    lshader_asAGradient },
   978     { "__gc",           lshader_gc },
   979     { NULL, NULL }
   980 };
   982 ///////////////////////////////////////////////////////////////////////////////
   984 static int lmatrix_getType(lua_State* L) {
   985     SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
   987     lua_newtable(L);
   988     setfield_boolean(L, "translate",   SkToBool(mask & SkMatrix::kTranslate_Mask));
   989     setfield_boolean(L, "scale",       SkToBool(mask & SkMatrix::kScale_Mask));
   990     setfield_boolean(L, "affine",      SkToBool(mask & SkMatrix::kAffine_Mask));
   991     setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
   992     return 1;
   993 }
   995 static int lmatrix_getScaleX(lua_State* L) {
   996     lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
   997     return 1;
   998 }
  1000 static int lmatrix_getScaleY(lua_State* L) {
  1001     lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
  1002     return 1;
  1005 static int lmatrix_getTranslateX(lua_State* L) {
  1006     lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
  1007     return 1;
  1010 static int lmatrix_getTranslateY(lua_State* L) {
  1011     lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
  1012     return 1;
  1015 static const struct luaL_Reg gSkMatrix_Methods[] = {
  1016     { "getType", lmatrix_getType },
  1017     { "getScaleX", lmatrix_getScaleX },
  1018     { "getScaleY", lmatrix_getScaleY },
  1019     { "getTranslateX", lmatrix_getTranslateX },
  1020     { "getTranslateY", lmatrix_getTranslateY },
  1021     { NULL, NULL }
  1022 };
  1024 ///////////////////////////////////////////////////////////////////////////////
  1026 static int lpath_getBounds(lua_State* L) {
  1027     SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
  1028     return 1;
  1031 static const char* fill_type_to_str(SkPath::FillType fill) {
  1032     switch (fill) {
  1033         case SkPath::kEvenOdd_FillType:
  1034             return "even-odd";
  1035         case SkPath::kWinding_FillType:
  1036             return "winding";
  1037         case SkPath::kInverseEvenOdd_FillType:
  1038             return "inverse-even-odd";
  1039         case SkPath::kInverseWinding_FillType:
  1040             return "inverse-winding";
  1042     return "unknown";
  1045 static int lpath_getFillType(lua_State* L) {
  1046     SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
  1047     SkLua(L).pushString(fill_type_to_str(fill));
  1048     return 1;
  1051 static SkString segment_masks_to_str(uint32_t segmentMasks) {
  1052     SkString result;
  1053     bool first = true;
  1054     if (SkPath::kLine_SegmentMask & segmentMasks) {
  1055         result.append("line");
  1056         first = false;
  1057         SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
  1059     if (SkPath::kQuad_SegmentMask & segmentMasks) {
  1060         if (!first) {
  1061             result.append(" ");
  1063         result.append("quad");
  1064         first = false;
  1065         SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
  1067     if (SkPath::kConic_SegmentMask & segmentMasks) {
  1068         if (!first) {
  1069             result.append(" ");
  1071         result.append("conic");
  1072         first = false;
  1073         SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
  1075     if (SkPath::kCubic_SegmentMask & segmentMasks) {
  1076         if (!first) {
  1077             result.append(" ");
  1079         result.append("cubic");
  1080         SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
  1082     SkASSERT(0 == segmentMasks);
  1083     return result;
  1086 static int lpath_getSegementTypes(lua_State* L) {
  1087     uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
  1088     SkLua(L).pushString(segment_masks_to_str(segMasks));
  1089     return 1;
  1092 static int lpath_isConvex(lua_State* L) {
  1093     bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
  1094     SkLua(L).pushBool(isConvex);
  1095     return 1;
  1098 static int lpath_isEmpty(lua_State* L) {
  1099     lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
  1100     return 1;
  1103 static int lpath_isRect(lua_State* L) {
  1104     SkRect r;
  1105     bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
  1106     int ret_count = 1;
  1107     lua_pushboolean(L, pred);
  1108     if (pred) {
  1109         SkLua(L).pushRect(r);
  1110         ret_count += 1;
  1112     return ret_count;
  1115 static const char* dir2string(SkPath::Direction dir) {
  1116     static const char* gStr[] = {
  1117         "unknown", "cw", "ccw"
  1118     };
  1119     SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
  1120     return gStr[dir];
  1123 static int lpath_isNestedRects(lua_State* L) {
  1124     SkRect rects[2];
  1125     SkPath::Direction dirs[2];
  1126     bool pred = get_obj<SkPath>(L, 1)->isNestedRects(rects, dirs);
  1127     int ret_count = 1;
  1128     lua_pushboolean(L, pred);
  1129     if (pred) {
  1130         SkLua lua(L);
  1131         lua.pushRect(rects[0]);
  1132         lua.pushRect(rects[1]);
  1133         lua_pushstring(L, dir2string(dirs[0]));
  1134         lua_pushstring(L, dir2string(dirs[0]));
  1135         ret_count += 4;
  1137     return ret_count;
  1140 static int lpath_countPoints(lua_State* L) {
  1141     lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
  1142     return 1;
  1145 static int lpath_reset(lua_State* L) {
  1146     get_obj<SkPath>(L, 1)->reset();
  1147     return 0;
  1150 static int lpath_moveTo(lua_State* L) {
  1151     get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
  1152     return 0;
  1155 static int lpath_lineTo(lua_State* L) {
  1156     get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
  1157     return 0;
  1160 static int lpath_quadTo(lua_State* L) {
  1161     get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
  1162                                   lua2scalar(L, 4), lua2scalar(L, 5));
  1163     return 0;
  1166 static int lpath_cubicTo(lua_State* L) {
  1167     get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
  1168                                    lua2scalar(L, 4), lua2scalar(L, 5),
  1169                                    lua2scalar(L, 6), lua2scalar(L, 7));
  1170     return 0;
  1173 static int lpath_close(lua_State* L) {
  1174     get_obj<SkPath>(L, 1)->close();
  1175     return 0;
  1178 static int lpath_gc(lua_State* L) {
  1179     get_obj<SkPath>(L, 1)->~SkPath();
  1180     return 0;
  1183 static const struct luaL_Reg gSkPath_Methods[] = {
  1184     { "getBounds", lpath_getBounds },
  1185     { "getFillType", lpath_getFillType },
  1186     { "getSegmentTypes", lpath_getSegementTypes },
  1187     { "isConvex", lpath_isConvex },
  1188     { "isEmpty", lpath_isEmpty },
  1189     { "isRect", lpath_isRect },
  1190     { "isNestedRects", lpath_isNestedRects },
  1191     { "countPoints", lpath_countPoints },
  1192     { "reset", lpath_reset },
  1193     { "moveTo", lpath_moveTo },
  1194     { "lineTo", lpath_lineTo },
  1195     { "quadTo", lpath_quadTo },
  1196     { "cubicTo", lpath_cubicTo },
  1197     { "close", lpath_close },
  1198     { "__gc", lpath_gc },
  1199     { NULL, NULL }
  1200 };
  1202 ///////////////////////////////////////////////////////////////////////////////
  1204 static const char* rrect_type(const SkRRect& rr) {
  1205     switch (rr.getType()) {
  1206         case SkRRect::kUnknown_Type: return "unknown";
  1207         case SkRRect::kEmpty_Type: return "empty";
  1208         case SkRRect::kRect_Type: return "rect";
  1209         case SkRRect::kOval_Type: return "oval";
  1210         case SkRRect::kSimple_Type: return "simple";
  1211         case SkRRect::kComplex_Type: return "complex";
  1213     SkDEBUGFAIL("never get here");
  1214     return "";
  1217 static int lrrect_rect(lua_State* L) {
  1218     SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
  1219     return 1;
  1222 static int lrrect_type(lua_State* L) {
  1223     lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
  1224     return 1;
  1227 static int lrrect_radii(lua_State* L) {
  1228     int corner = SkToInt(lua_tointeger(L, 2));
  1229     SkVector v;
  1230     if (corner < 0 || corner > 3) {
  1231         SkDebugf("bad corner index %d", corner);
  1232         v.set(0, 0);
  1233     } else {
  1234         v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
  1236     lua_pushnumber(L, v.fX);
  1237     lua_pushnumber(L, v.fY);
  1238     return 2;
  1241 static int lrrect_gc(lua_State* L) {
  1242     get_obj<SkRRect>(L, 1)->~SkRRect();
  1243     return 0;
  1246 static const struct luaL_Reg gSkRRect_Methods[] = {
  1247     { "rect", lrrect_rect },
  1248     { "type", lrrect_type },
  1249     { "radii", lrrect_radii },
  1250     { "__gc", lrrect_gc },
  1251     { NULL, NULL }
  1252 };
  1254 ///////////////////////////////////////////////////////////////////////////////
  1256 static int limage_width(lua_State* L) {
  1257     lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
  1258     return 1;
  1261 static int limage_height(lua_State* L) {
  1262     lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
  1263     return 1;
  1266 static int limage_gc(lua_State* L) {
  1267     get_ref<SkImage>(L, 1)->unref();
  1268     return 0;
  1271 static const struct luaL_Reg gSkImage_Methods[] = {
  1272     { "width", limage_width },
  1273     { "height", limage_height },
  1274     { "__gc", limage_gc },
  1275     { NULL, NULL }
  1276 };
  1278 ///////////////////////////////////////////////////////////////////////////////
  1280 static int ltypeface_gc(lua_State* L) {
  1281     SkSafeUnref(get_ref<SkTypeface>(L, 1));
  1282     return 0;
  1285 static const struct luaL_Reg gSkTypeface_Methods[] = {
  1286     { "__gc", ltypeface_gc },
  1287     { NULL, NULL }
  1288 };
  1290 ///////////////////////////////////////////////////////////////////////////////
  1292 class AutoCallLua {
  1293 public:
  1294     AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
  1295         lua_getglobal(L, func);
  1296         if (!lua_isfunction(L, -1)) {
  1297             int t = lua_type(L, -1);
  1298             SkDebugf("--- expected function %d\n", t);
  1301         lua_newtable(L);
  1302         setfield_string(L, "verb", verb);
  1305     ~AutoCallLua() {
  1306         if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
  1307             SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
  1309         lua_settop(fL, -1);
  1312 private:
  1313     lua_State* fL;
  1314 };
  1316 #define AUTO_LUA(verb)  AutoCallLua acl(fL, fFunc.c_str(), verb)
  1318 ///////////////////////////////////////////////////////////////////////////////
  1320 static int lsk_newDocumentPDF(lua_State* L) {
  1321     const char* file = NULL;
  1322     if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
  1323         file = lua_tolstring(L, 1, NULL);
  1326     SkDocument* doc = SkDocument::CreatePDF(file);
  1327     if (NULL == doc) {
  1328         // do I need to push a nil on the stack and return 1?
  1329         return 0;
  1330     } else {
  1331         push_ref(L, doc);
  1332         doc->unref();
  1333         return 1;
  1337 static int lsk_newPaint(lua_State* L) {
  1338     push_new<SkPaint>(L);
  1339     return 1;
  1342 static int lsk_newPath(lua_State* L) {
  1343     push_new<SkPath>(L);
  1344     return 1;
  1347 static int lsk_newRRect(lua_State* L) {
  1348     SkRRect* rr = push_new<SkRRect>(L);
  1349     rr->setEmpty();
  1350     return 1;
  1353 static int lsk_newTypeface(lua_State* L) {
  1354     const char* name = NULL;
  1355     int style = SkTypeface::kNormal;
  1357     int count = lua_gettop(L);
  1358     if (count > 0 && lua_isstring(L, 1)) {
  1359         name = lua_tolstring(L, 1, NULL);
  1360         if (count > 1 && lua_isnumber(L, 2)) {
  1361             style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic;
  1365     SkTypeface* face = SkTypeface::CreateFromName(name,
  1366                                                   (SkTypeface::Style)style);
  1367 //    SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
  1368     if (NULL == face) {
  1369         face = SkTypeface::RefDefault();
  1371     push_ref(L, face);
  1372     face->unref();
  1373     return 1;
  1376 static int lsk_loadImage(lua_State* L) {
  1377     if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
  1378         const char* name = lua_tolstring(L, 1, NULL);
  1379         SkAutoDataUnref data(SkData::NewFromFileName(name));
  1380         if (data.get()) {
  1381             SkImage* image = SkImage::NewEncodedData(data.get());
  1382             if (image) {
  1383                 push_ref(L, image);
  1384                 image->unref();
  1385                 return 1;
  1389     return 0;
  1392 static void register_Sk(lua_State* L) {
  1393     lua_newtable(L);
  1394     lua_pushvalue(L, -1);
  1395     lua_setglobal(L, "Sk");
  1396     // the Sk table is still on top
  1398     setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
  1399     setfield_function(L, "loadImage", lsk_loadImage);
  1400     setfield_function(L, "newPaint", lsk_newPaint);
  1401     setfield_function(L, "newPath", lsk_newPath);
  1402     setfield_function(L, "newRRect", lsk_newRRect);
  1403     setfield_function(L, "newTypeface", lsk_newTypeface);
  1404     lua_pop(L, 1);  // pop off the Sk table
  1407 #define REG_CLASS(L, C)                             \
  1408     do {                                            \
  1409         luaL_newmetatable(L, get_mtname<C>());      \
  1410         lua_pushvalue(L, -1);                       \
  1411         lua_setfield(L, -2, "__index");             \
  1412         luaL_setfuncs(L, g##C##_Methods, 0);        \
  1413         lua_pop(L, 1); /* pop off the meta-table */ \
  1414     } while (0)
  1416 void SkLua::Load(lua_State* L) {
  1417     register_Sk(L);
  1418     REG_CLASS(L, SkCanvas);
  1419     REG_CLASS(L, SkDocument);
  1420     REG_CLASS(L, SkImage);
  1421     REG_CLASS(L, SkPath);
  1422     REG_CLASS(L, SkPaint);
  1423     REG_CLASS(L, SkRRect);
  1424     REG_CLASS(L, SkShader);
  1425     REG_CLASS(L, SkTypeface);
  1426     REG_CLASS(L, SkMatrix);
  1429 extern "C" int luaopen_skia(lua_State* L);
  1430 extern "C" int luaopen_skia(lua_State* L) {
  1431     SkLua::Load(L);
  1432     return 0;

mercurial