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