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 "SkBlurImageFilter.h" 15#include "SkCanvas.h" 16#include "SkColorFilter.h" 17#include "SkData.h" 18#include "SkDocument.h" 19#include "SkGradientShader.h" 20#include "SkImage.h" 21#include "SkMatrix.h" 22#include "SkPaint.h" 23#include "SkPath.h" 24#include "SkPictureRecorder.h" 25#include "SkPixelRef.h" 26#include "SkRRect.h" 27#include "SkString.h" 28#include "SkSurface.h" 29#include "SkTextBlob.h" 30#include "SkTypeface.h" 31#include "SkXfermode.h" 32 33extern "C" { 34 #include "lua.h" 35 #include "lualib.h" 36 #include "lauxlib.h" 37} 38 39// return the metatable name for a given class 40template <typename T> const char* get_mtname(); 41#define DEF_MTNAME(T) \ 42 template <> const char* get_mtname<T>() { \ 43 return #T "_LuaMetaTableName"; \ 44 } 45 46DEF_MTNAME(SkCanvas) 47DEF_MTNAME(SkColorFilter) 48DEF_MTNAME(SkDocument) 49DEF_MTNAME(SkImage) 50DEF_MTNAME(SkImageFilter) 51DEF_MTNAME(SkMatrix) 52DEF_MTNAME(SkRRect) 53DEF_MTNAME(SkPath) 54DEF_MTNAME(SkPaint) 55DEF_MTNAME(SkPathEffect) 56DEF_MTNAME(SkPicture) 57DEF_MTNAME(SkPictureRecorder) 58DEF_MTNAME(SkShader) 59DEF_MTNAME(SkSurface) 60DEF_MTNAME(SkTextBlob) 61DEF_MTNAME(SkTypeface) 62DEF_MTNAME(SkXfermode) 63 64template <typename T> T* push_new(lua_State* L) { 65 T* addr = (T*)lua_newuserdata(L, sizeof(T)); 66 new (addr) T; 67 luaL_getmetatable(L, get_mtname<T>()); 68 lua_setmetatable(L, -2); 69 return addr; 70} 71 72template <typename T> void push_obj(lua_State* L, const T& obj) { 73 new (lua_newuserdata(L, sizeof(T))) T(obj); 74 luaL_getmetatable(L, get_mtname<T>()); 75 lua_setmetatable(L, -2); 76} 77 78template <typename T> T* push_ref(lua_State* L, T* ref) { 79 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref); 80 luaL_getmetatable(L, get_mtname<T>()); 81 lua_setmetatable(L, -2); 82 return ref; 83} 84 85template <typename T> T* get_ref(lua_State* L, int index) { 86 return *(T**)luaL_checkudata(L, index, get_mtname<T>()); 87} 88 89template <typename T> T* get_obj(lua_State* L, int index) { 90 return (T*)luaL_checkudata(L, index, get_mtname<T>()); 91} 92 93static bool lua2bool(lua_State* L, int index) { 94 return !!lua_toboolean(L, index); 95} 96 97/////////////////////////////////////////////////////////////////////////////// 98 99SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) { 100 fL = luaL_newstate(); 101 luaL_openlibs(fL); 102 SkLua::Load(fL); 103} 104 105SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {} 106 107SkLua::~SkLua() { 108 if (fWeOwnL) { 109 if (fTermCode.size() > 0) { 110 lua_getglobal(fL, fTermCode.c_str()); 111 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) { 112 SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); 113 } 114 } 115 lua_close(fL); 116 } 117} 118 119bool SkLua::runCode(const char code[]) { 120 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0); 121 if (err) { 122 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1)); 123 return false; 124 } 125 return true; 126} 127 128bool SkLua::runCode(const void* code, size_t size) { 129 SkString str((const char*)code, size); 130 return this->runCode(str.c_str()); 131} 132 133/////////////////////////////////////////////////////////////////////////////// 134 135#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0) 136 137static void setfield_bool_if(lua_State* L, const char key[], bool pred) { 138 if (pred) { 139 lua_pushboolean(L, true); 140 lua_setfield(L, -2, key); 141 } 142} 143 144static void setfield_string(lua_State* L, const char key[], const char value[]) { 145 lua_pushstring(L, value); 146 lua_setfield(L, -2, key); 147} 148 149static void setfield_number(lua_State* L, const char key[], double value) { 150 lua_pushnumber(L, value); 151 lua_setfield(L, -2, key); 152} 153 154static void setfield_boolean(lua_State* L, const char key[], bool value) { 155 lua_pushboolean(L, value); 156 lua_setfield(L, -2, key); 157} 158 159static void setfield_scalar(lua_State* L, const char key[], SkScalar value) { 160 setfield_number(L, key, SkScalarToLua(value)); 161} 162 163static void setfield_function(lua_State* L, 164 const char key[], lua_CFunction value) { 165 lua_pushcfunction(L, value); 166 lua_setfield(L, -2, key); 167} 168 169static int lua2int_def(lua_State* L, int index, int defaultValue) { 170 if (lua_isnumber(L, index)) { 171 return (int)lua_tonumber(L, index); 172 } else { 173 return defaultValue; 174 } 175} 176 177static SkScalar lua2scalar(lua_State* L, int index) { 178 SkASSERT(lua_isnumber(L, index)); 179 return SkLuaToScalar(lua_tonumber(L, index)); 180} 181 182static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) { 183 if (lua_isnumber(L, index)) { 184 return SkLuaToScalar(lua_tonumber(L, index)); 185 } else { 186 return defaultValue; 187 } 188} 189 190static SkScalar getarray_scalar(lua_State* L, int stackIndex, int arrayIndex) { 191 SkASSERT(lua_istable(L, stackIndex)); 192 lua_rawgeti(L, stackIndex, arrayIndex); 193 194 SkScalar value = lua2scalar(L, -1); 195 lua_pop(L, 1); 196 return value; 197} 198 199static void getarray_scalars(lua_State* L, int stackIndex, SkScalar dst[], int count) { 200 for (int i = 0; i < count; ++i) { 201 dst[i] = getarray_scalar(L, stackIndex, i + 1); 202 } 203} 204 205static void getarray_points(lua_State* L, int stackIndex, SkPoint pts[], int count) { 206 getarray_scalars(L, stackIndex, &pts[0].fX, count * 2); 207} 208 209static void setarray_number(lua_State* L, int index, double value) { 210 lua_pushnumber(L, value); 211 lua_rawseti(L, -2, index); 212} 213 214static void setarray_scalar(lua_State* L, int index, SkScalar value) { 215 setarray_number(L, index, SkScalarToLua(value)); 216} 217 218void SkLua::pushBool(bool value, const char key[]) { 219 lua_pushboolean(fL, value); 220 CHECK_SETFIELD(key); 221} 222 223void SkLua::pushString(const char str[], const char key[]) { 224 lua_pushstring(fL, str); 225 CHECK_SETFIELD(key); 226} 227 228void SkLua::pushString(const char str[], size_t length, const char key[]) { 229 // TODO: how to do this w/o making a copy? 230 SkString s(str, length); 231 lua_pushstring(fL, s.c_str()); 232 CHECK_SETFIELD(key); 233} 234 235void SkLua::pushString(const SkString& str, const char key[]) { 236 lua_pushstring(fL, str.c_str()); 237 CHECK_SETFIELD(key); 238} 239 240void SkLua::pushColor(SkColor color, const char key[]) { 241 lua_newtable(fL); 242 setfield_number(fL, "a", SkColorGetA(color) / 255.0); 243 setfield_number(fL, "r", SkColorGetR(color) / 255.0); 244 setfield_number(fL, "g", SkColorGetG(color) / 255.0); 245 setfield_number(fL, "b", SkColorGetB(color) / 255.0); 246 CHECK_SETFIELD(key); 247} 248 249void SkLua::pushU32(uint32_t value, const char key[]) { 250 lua_pushnumber(fL, (double)value); 251 CHECK_SETFIELD(key); 252} 253 254void SkLua::pushScalar(SkScalar value, const char key[]) { 255 lua_pushnumber(fL, SkScalarToLua(value)); 256 CHECK_SETFIELD(key); 257} 258 259void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) { 260 lua_newtable(fL); 261 for (int i = 0; i < count; ++i) { 262 // make it base-1 to match lua convention 263 setarray_number(fL, i + 1, (double)array[i]); 264 } 265 CHECK_SETFIELD(key); 266} 267 268void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) { 269 lua_newtable(fL); 270 for (int i = 0; i < count; ++i) { 271 // make it base-1 to match lua convention 272 lua_newtable(fL); 273 this->pushScalar(array[i].fX, "x"); 274 this->pushScalar(array[i].fY, "y"); 275 lua_rawseti(fL, -2, i + 1); 276 } 277 CHECK_SETFIELD(key); 278} 279 280void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) { 281 lua_newtable(fL); 282 for (int i = 0; i < count; ++i) { 283 // make it base-1 to match lua convention 284 setarray_scalar(fL, i + 1, array[i]); 285 } 286 CHECK_SETFIELD(key); 287} 288 289void SkLua::pushRect(const SkRect& r, const char key[]) { 290 lua_newtable(fL); 291 setfield_scalar(fL, "left", r.fLeft); 292 setfield_scalar(fL, "top", r.fTop); 293 setfield_scalar(fL, "right", r.fRight); 294 setfield_scalar(fL, "bottom", r.fBottom); 295 CHECK_SETFIELD(key); 296} 297 298void SkLua::pushRRect(const SkRRect& rr, const char key[]) { 299 push_obj(fL, rr); 300 CHECK_SETFIELD(key); 301} 302 303void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) { 304 lua_newtable(fL); 305 setfield_scalar(fL, "phase", info.fPhase); 306 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals"); 307 CHECK_SETFIELD(key); 308} 309 310 311void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) { 312 push_obj(fL, matrix); 313 CHECK_SETFIELD(key); 314} 315 316void SkLua::pushPaint(const SkPaint& paint, const char key[]) { 317 push_obj(fL, paint); 318 CHECK_SETFIELD(key); 319} 320 321void SkLua::pushPath(const SkPath& path, const char key[]) { 322 push_obj(fL, path); 323 CHECK_SETFIELD(key); 324} 325 326void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) { 327 push_ref(fL, canvas); 328 CHECK_SETFIELD(key); 329} 330 331void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) { 332 push_ref(fL, const_cast<SkTextBlob*>(blob)); 333 CHECK_SETFIELD(key); 334} 335 336static const char* element_type(SkClipStack::Element::Type type) { 337 switch (type) { 338 case SkClipStack::Element::kEmpty_Type: 339 return "empty"; 340 case SkClipStack::Element::kRect_Type: 341 return "rect"; 342 case SkClipStack::Element::kRRect_Type: 343 return "rrect"; 344 case SkClipStack::Element::kPath_Type: 345 return "path"; 346 } 347 return "unknown"; 348} 349 350static const char* region_op(SkRegion::Op op) { 351 switch (op) { 352 case SkRegion::kDifference_Op: 353 return "difference"; 354 case SkRegion::kIntersect_Op: 355 return "intersect"; 356 case SkRegion::kUnion_Op: 357 return "union"; 358 case SkRegion::kXOR_Op: 359 return "xor"; 360 case SkRegion::kReverseDifference_Op: 361 return "reverse-difference"; 362 case SkRegion::kReplace_Op: 363 return "replace"; 364 } 365 return "unknown"; 366} 367 368void SkLua::pushClipStack(const SkClipStack& stack, const char* key) { 369 lua_newtable(fL); 370 SkClipStack::B2TIter iter(stack); 371 const SkClipStack::Element* element; 372 int i = 0; 373 while ((element = iter.next())) { 374 this->pushClipStackElement(*element); 375 lua_rawseti(fL, -2, ++i); 376 } 377 CHECK_SETFIELD(key); 378} 379 380void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) { 381 lua_newtable(fL); 382 SkClipStack::Element::Type type = element.getType(); 383 this->pushString(element_type(type), "type"); 384 switch (type) { 385 case SkClipStack::Element::kEmpty_Type: 386 break; 387 case SkClipStack::Element::kRect_Type: 388 this->pushRect(element.getRect(), "rect"); 389 break; 390 case SkClipStack::Element::kRRect_Type: 391 this->pushRRect(element.getRRect(), "rrect"); 392 break; 393 case SkClipStack::Element::kPath_Type: 394 this->pushPath(element.getPath(), "path"); 395 break; 396 } 397 this->pushString(region_op(element.getOp()), "op"); 398 this->pushBool(element.isAA(), "aa"); 399 CHECK_SETFIELD(key); 400} 401 402 403/////////////////////////////////////////////////////////////////////////////// 404/////////////////////////////////////////////////////////////////////////////// 405 406static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) { 407 SkASSERT(lua_istable(L, index)); 408 lua_pushstring(L, key); 409 lua_gettable(L, index); 410 411 SkScalar value = lua2scalar(L, -1); 412 lua_pop(L, 1); 413 return value; 414} 415 416static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) { 417 SkASSERT(lua_istable(L, index)); 418 lua_pushstring(L, key); 419 lua_gettable(L, index); 420 421 SkScalar value; 422 if (lua_isnil(L, -1)) { 423 value = def; 424 } else { 425 value = lua2scalar(L, -1); 426 } 427 lua_pop(L, 1); 428 return value; 429} 430 431static SkScalar byte2unit(U8CPU byte) { 432 return byte / 255.0f; 433} 434 435static U8CPU unit2byte(SkScalar x) { 436 if (x <= 0) { 437 return 0; 438 } else if (x >= 1) { 439 return 255; 440 } else { 441 return SkScalarRoundToInt(x * 255); 442 } 443} 444 445static SkColor lua2color(lua_State* L, int index) { 446 return SkColorSetARGB(unit2byte(getfield_scalar_default(L, index, "a", 1)), 447 unit2byte(getfield_scalar_default(L, index, "r", 0)), 448 unit2byte(getfield_scalar_default(L, index, "g", 0)), 449 unit2byte(getfield_scalar_default(L, index, "b", 0))); 450} 451 452static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) { 453 rect->set(getfield_scalar_default(L, index, "left", 0), 454 getfield_scalar_default(L, index, "top", 0), 455 getfield_scalar(L, index, "right"), 456 getfield_scalar(L, index, "bottom")); 457 return rect; 458} 459 460static int lcanvas_clear(lua_State* L) { 461 get_ref<SkCanvas>(L, 1)->clear(0); 462 return 0; 463} 464 465static int lcanvas_drawColor(lua_State* L) { 466 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2)); 467 return 0; 468} 469 470static int lcanvas_drawPaint(lua_State* L) { 471 get_ref<SkCanvas>(L, 1)->drawPaint(*get_obj<SkPaint>(L, 2)); 472 return 0; 473} 474 475static int lcanvas_drawRect(lua_State* L) { 476 SkRect rect; 477 lua2rect(L, 2, &rect); 478 const SkPaint* paint = get_obj<SkPaint>(L, 3); 479 get_ref<SkCanvas>(L, 1)->drawRect(rect, *paint); 480 return 0; 481} 482 483static int lcanvas_drawOval(lua_State* L) { 484 SkRect rect; 485 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect), 486 *get_obj<SkPaint>(L, 3)); 487 return 0; 488} 489 490static int lcanvas_drawCircle(lua_State* L) { 491 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2), 492 lua2scalar(L, 3), 493 lua2scalar(L, 4), 494 *get_obj<SkPaint>(L, 5)); 495 return 0; 496} 497 498static SkPaint* lua2OptionalPaint(lua_State* L, int index, SkPaint* paint) { 499 if (lua_isnumber(L, index)) { 500 paint->setAlpha(SkScalarRoundToInt(lua2scalar(L, index) * 255)); 501 return paint; 502 } else if (lua_isuserdata(L, index)) { 503 const SkPaint* ptr = get_obj<SkPaint>(L, index); 504 if (ptr) { 505 *paint = *ptr; 506 return paint; 507 } 508 } 509 return nullptr; 510} 511 512static int lcanvas_drawImage(lua_State* L) { 513 SkCanvas* canvas = get_ref<SkCanvas>(L, 1); 514 SkImage* image = get_ref<SkImage>(L, 2); 515 if (nullptr == image) { 516 return 0; 517 } 518 SkScalar x = lua2scalar(L, 3); 519 SkScalar y = lua2scalar(L, 4); 520 521 SkPaint paint; 522 canvas->drawImage(image, x, y, lua2OptionalPaint(L, 5, &paint)); 523 return 0; 524} 525 526static int lcanvas_drawImageRect(lua_State* L) { 527 SkCanvas* canvas = get_ref<SkCanvas>(L, 1); 528 SkImage* image = get_ref<SkImage>(L, 2); 529 if (nullptr == image) { 530 return 0; 531 } 532 533 SkRect srcR, dstR; 534 SkRect* srcRPtr = nullptr; 535 if (!lua_isnil(L, 3)) { 536 srcRPtr = lua2rect(L, 3, &srcR); 537 } 538 lua2rect(L, 4, &dstR); 539 540 SkPaint paint; 541 canvas->legacy_drawImageRect(image, srcRPtr, dstR, lua2OptionalPaint(L, 5, &paint)); 542 return 0; 543} 544 545static int lcanvas_drawPatch(lua_State* L) { 546 SkPoint cubics[12]; 547 SkColor colorStorage[4]; 548 SkPoint texStorage[4]; 549 550 const SkColor* colors = nullptr; 551 const SkPoint* texs = nullptr; 552 553 getarray_points(L, 2, cubics, 12); 554 555 colorStorage[0] = SK_ColorRED; 556 colorStorage[1] = SK_ColorGREEN; 557 colorStorage[2] = SK_ColorBLUE; 558 colorStorage[3] = SK_ColorGRAY; 559 560 if (lua_isnil(L, 4)) { 561 colors = colorStorage; 562 } else { 563 getarray_points(L, 4, texStorage, 4); 564 texs = texStorage; 565 } 566 567 get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, nullptr, *get_obj<SkPaint>(L, 5)); 568 return 0; 569} 570 571static int lcanvas_drawPath(lua_State* L) { 572 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2), 573 *get_obj<SkPaint>(L, 3)); 574 return 0; 575} 576 577// drawPicture(pic, x, y, paint) 578static int lcanvas_drawPicture(lua_State* L) { 579 SkCanvas* canvas = get_ref<SkCanvas>(L, 1); 580 SkPicture* picture = get_ref<SkPicture>(L, 2); 581 SkScalar x = lua2scalar_def(L, 3, 0); 582 SkScalar y = lua2scalar_def(L, 4, 0); 583 SkMatrix matrix, *matrixPtr = nullptr; 584 if (x || y) { 585 matrix.setTranslate(x, y); 586 matrixPtr = &matrix; 587 } 588 SkPaint paint; 589 canvas->drawPicture(picture, matrixPtr, lua2OptionalPaint(L, 5, &paint)); 590 return 0; 591} 592 593static int lcanvas_drawText(lua_State* L) { 594 if (lua_gettop(L) < 5) { 595 return 0; 596 } 597 598 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) { 599 size_t len; 600 const char* text = lua_tolstring(L, 2, &len); 601 get_ref<SkCanvas>(L, 1)->drawText(text, len, 602 lua2scalar(L, 3), lua2scalar(L, 4), 603 *get_obj<SkPaint>(L, 5)); 604 } 605 return 0; 606} 607 608static int lcanvas_drawTextBlob(lua_State* L) { 609 const SkTextBlob* blob = get_ref<SkTextBlob>(L, 2); 610 SkScalar x = lua2scalar(L, 3); 611 SkScalar y = lua2scalar(L, 4); 612 const SkPaint& paint = *get_obj<SkPaint>(L, 5); 613 get_ref<SkCanvas>(L, 1)->drawTextBlob(blob, x, y, paint); 614 return 0; 615} 616 617static int lcanvas_getSaveCount(lua_State* L) { 618 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount()); 619 return 1; 620} 621 622static int lcanvas_getTotalMatrix(lua_State* L) { 623 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix()); 624 return 1; 625} 626 627static int lcanvas_getClipStack(lua_State* L) { 628 SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack()); 629 return 1; 630} 631 632int SkLua::lcanvas_getReducedClipStack(lua_State* L) { 633#if SK_SUPPORT_GPU 634 const SkCanvas* canvas = get_ref<SkCanvas>(L, 1); 635 SkIRect queryBounds = canvas->getTopLayerBounds(); 636 637 GrReducedClip::ElementList elements; 638 GrReducedClip::InitialState initialState; 639 int32_t genID; 640 SkIRect resultBounds; 641 642 const SkClipStack& stack = *canvas->getClipStack(); 643 644 GrReducedClip::ReduceClipStack(stack, 645 queryBounds, 646 &elements, 647 &genID, 648 &initialState, 649 &resultBounds, 650 nullptr); 651 652 GrReducedClip::ElementList::Iter iter(elements); 653 int i = 0; 654 lua_newtable(L); 655 while(iter.get()) { 656 SkLua(L).pushClipStackElement(*iter.get()); 657 iter.next(); 658 lua_rawseti(L, -2, ++i); 659 } 660 // Currently this only returns the element list to lua, not the initial state or result bounds. 661 // It could return these as additional items on the lua stack. 662 return 1; 663#else 664 return 0; 665#endif 666} 667 668static int lcanvas_save(lua_State* L) { 669 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save()); 670 return 1; 671} 672 673static int lcanvas_saveLayer(lua_State* L) { 674 SkPaint paint; 675 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->saveLayer(nullptr, lua2OptionalPaint(L, 2, &paint))); 676 return 1; 677} 678 679static int lcanvas_restore(lua_State* L) { 680 get_ref<SkCanvas>(L, 1)->restore(); 681 return 0; 682} 683 684static int lcanvas_scale(lua_State* L) { 685 SkScalar sx = lua2scalar_def(L, 2, 1); 686 SkScalar sy = lua2scalar_def(L, 3, sx); 687 get_ref<SkCanvas>(L, 1)->scale(sx, sy); 688 return 0; 689} 690 691static int lcanvas_translate(lua_State* L) { 692 SkScalar tx = lua2scalar_def(L, 2, 0); 693 SkScalar ty = lua2scalar_def(L, 3, 0); 694 get_ref<SkCanvas>(L, 1)->translate(tx, ty); 695 return 0; 696} 697 698static int lcanvas_rotate(lua_State* L) { 699 SkScalar degrees = lua2scalar_def(L, 2, 0); 700 get_ref<SkCanvas>(L, 1)->rotate(degrees); 701 return 0; 702} 703 704static int lcanvas_concat(lua_State* L) { 705 get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2)); 706 return 0; 707} 708 709static int lcanvas_newSurface(lua_State* L) { 710 int width = lua2int_def(L, 2, 0); 711 int height = lua2int_def(L, 3, 0); 712 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); 713 SkSurface* surface = get_ref<SkCanvas>(L, 1)->newSurface(info); 714 if (nullptr == surface) { 715 lua_pushnil(L); 716 } else { 717 push_ref(L, surface)->unref(); 718 } 719 return 1; 720} 721 722static int lcanvas_gc(lua_State* L) { 723 get_ref<SkCanvas>(L, 1)->unref(); 724 return 0; 725} 726 727const struct luaL_Reg gSkCanvas_Methods[] = { 728 { "clear", lcanvas_clear }, 729 { "drawColor", lcanvas_drawColor }, 730 { "drawPaint", lcanvas_drawPaint }, 731 { "drawRect", lcanvas_drawRect }, 732 { "drawOval", lcanvas_drawOval }, 733 { "drawCircle", lcanvas_drawCircle }, 734 { "drawImage", lcanvas_drawImage }, 735 { "drawImageRect", lcanvas_drawImageRect }, 736 { "drawPatch", lcanvas_drawPatch }, 737 { "drawPath", lcanvas_drawPath }, 738 { "drawPicture", lcanvas_drawPicture }, 739 { "drawText", lcanvas_drawText }, 740 { "drawTextBlob", lcanvas_drawTextBlob }, 741 { "getSaveCount", lcanvas_getSaveCount }, 742 { "getTotalMatrix", lcanvas_getTotalMatrix }, 743 { "getClipStack", lcanvas_getClipStack }, 744#if SK_SUPPORT_GPU 745 { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack }, 746#endif 747 { "save", lcanvas_save }, 748 { "saveLayer", lcanvas_saveLayer }, 749 { "restore", lcanvas_restore }, 750 { "scale", lcanvas_scale }, 751 { "translate", lcanvas_translate }, 752 { "rotate", lcanvas_rotate }, 753 { "concat", lcanvas_concat }, 754 755 { "newSurface", lcanvas_newSurface }, 756 757 { "__gc", lcanvas_gc }, 758 { nullptr, nullptr } 759}; 760 761/////////////////////////////////////////////////////////////////////////////// 762 763static int ldocument_beginPage(lua_State* L) { 764 const SkRect* contentPtr = nullptr; 765 push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2), 766 lua2scalar(L, 3), 767 contentPtr)); 768 return 1; 769} 770 771static int ldocument_endPage(lua_State* L) { 772 get_ref<SkDocument>(L, 1)->endPage(); 773 return 0; 774} 775 776static int ldocument_close(lua_State* L) { 777 get_ref<SkDocument>(L, 1)->close(); 778 return 0; 779} 780 781static int ldocument_gc(lua_State* L) { 782 get_ref<SkDocument>(L, 1)->unref(); 783 return 0; 784} 785 786static const struct luaL_Reg gSkDocument_Methods[] = { 787 { "beginPage", ldocument_beginPage }, 788 { "endPage", ldocument_endPage }, 789 { "close", ldocument_close }, 790 { "__gc", ldocument_gc }, 791 { nullptr, nullptr } 792}; 793 794/////////////////////////////////////////////////////////////////////////////// 795 796static int lpaint_isAntiAlias(lua_State* L) { 797 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias()); 798 return 1; 799} 800 801static int lpaint_setAntiAlias(lua_State* L) { 802 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2)); 803 return 0; 804} 805 806static int lpaint_isDither(lua_State* L) { 807 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither()); 808 return 1; 809} 810 811static int lpaint_setDither(lua_State* L) { 812 get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2)); 813 return 0; 814} 815 816static int lpaint_isUnderlineText(lua_State* L) { 817 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText()); 818 return 1; 819} 820 821static int lpaint_isStrikeThruText(lua_State* L) { 822 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText()); 823 return 1; 824} 825 826static int lpaint_isFakeBoldText(lua_State* L) { 827 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText()); 828 return 1; 829} 830 831static int lpaint_isLinearText(lua_State* L) { 832 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText()); 833 return 1; 834} 835 836static int lpaint_isSubpixelText(lua_State* L) { 837 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText()); 838 return 1; 839} 840 841static int lpaint_setSubpixelText(lua_State* L) { 842 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2)); 843 return 1; 844} 845 846static int lpaint_isDevKernText(lua_State* L) { 847 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText()); 848 return 1; 849} 850 851static int lpaint_isLCDRenderText(lua_State* L) { 852 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText()); 853 return 1; 854} 855 856static int lpaint_setLCDRenderText(lua_State* L) { 857 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2)); 858 return 1; 859} 860 861static int lpaint_isEmbeddedBitmapText(lua_State* L) { 862 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText()); 863 return 1; 864} 865 866static int lpaint_isAutohinted(lua_State* L) { 867 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted()); 868 return 1; 869} 870 871static int lpaint_isVerticalText(lua_State* L) { 872 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText()); 873 return 1; 874} 875 876static int lpaint_getAlpha(lua_State* L) { 877 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha())); 878 return 1; 879} 880 881static int lpaint_setAlpha(lua_State* L) { 882 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2))); 883 return 0; 884} 885 886static int lpaint_getColor(lua_State* L) { 887 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor()); 888 return 1; 889} 890 891static int lpaint_setColor(lua_State* L) { 892 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2)); 893 return 0; 894} 895 896static int lpaint_getTextSize(lua_State* L) { 897 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize()); 898 return 1; 899} 900 901static int lpaint_getTextScaleX(lua_State* L) { 902 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX()); 903 return 1; 904} 905 906static int lpaint_getTextSkewX(lua_State* L) { 907 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX()); 908 return 1; 909} 910 911static int lpaint_setTextSize(lua_State* L) { 912 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2)); 913 return 0; 914} 915 916static int lpaint_getTypeface(lua_State* L) { 917 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface()); 918 return 1; 919} 920 921static int lpaint_setTypeface(lua_State* L) { 922 get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2)); 923 return 0; 924} 925 926static int lpaint_getHinting(lua_State* L) { 927 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting()); 928 return 1; 929} 930 931static int lpaint_getFilterQuality(lua_State* L) { 932 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality()); 933 return 1; 934} 935 936static int lpaint_setFilterQuality(lua_State* L) { 937 int level = lua2int_def(L, 2, -1); 938 if (level >= 0 && level <= 3) { 939 get_obj<SkPaint>(L, 1)->setFilterQuality((SkFilterQuality)level); 940 } 941 return 0; 942} 943 944static int lpaint_getFontID(lua_State* L) { 945 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface(); 946 SkLua(L).pushU32(SkTypeface::UniqueID(face)); 947 return 1; 948} 949 950static const struct { 951 const char* fLabel; 952 SkPaint::Align fAlign; 953} gAlignRec[] = { 954 { "left", SkPaint::kLeft_Align }, 955 { "center", SkPaint::kCenter_Align }, 956 { "right", SkPaint::kRight_Align }, 957}; 958 959static int lpaint_getTextAlign(lua_State* L) { 960 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign(); 961 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { 962 if (gAlignRec[i].fAlign == align) { 963 lua_pushstring(L, gAlignRec[i].fLabel); 964 return 1; 965 } 966 } 967 return 0; 968} 969 970static int lpaint_setTextAlign(lua_State* L) { 971 if (lua_isstring(L, 2)) { 972 size_t len; 973 const char* label = lua_tolstring(L, 2, &len); 974 975 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { 976 if (!strcmp(gAlignRec[i].fLabel, label)) { 977 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign); 978 break; 979 } 980 } 981 } 982 return 0; 983} 984 985static int lpaint_getStroke(lua_State* L) { 986 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle()); 987 return 1; 988} 989 990static int lpaint_setStroke(lua_State* L) { 991 SkPaint::Style style; 992 993 if (lua_toboolean(L, 2)) { 994 style = SkPaint::kStroke_Style; 995 } else { 996 style = SkPaint::kFill_Style; 997 } 998 get_obj<SkPaint>(L, 1)->setStyle(style); 999 return 0; 1000} 1001 1002static int lpaint_getStrokeCap(lua_State* L) { 1003 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap()); 1004 return 1; 1005} 1006 1007static int lpaint_getStrokeJoin(lua_State* L) { 1008 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin()); 1009 return 1; 1010} 1011 1012static int lpaint_getTextEncoding(lua_State* L) { 1013 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding()); 1014 return 1; 1015} 1016 1017static int lpaint_getStrokeWidth(lua_State* L) { 1018 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth()); 1019 return 1; 1020} 1021 1022static int lpaint_setStrokeWidth(lua_State* L) { 1023 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2)); 1024 return 0; 1025} 1026 1027static int lpaint_getStrokeMiter(lua_State* L) { 1028 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter()); 1029 return 1; 1030} 1031 1032static int lpaint_measureText(lua_State* L) { 1033 if (lua_isstring(L, 2)) { 1034 size_t len; 1035 const char* text = lua_tolstring(L, 2, &len); 1036 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len)); 1037 return 1; 1038 } 1039 return 0; 1040} 1041 1042struct FontMetrics { 1043 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0) 1044 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0) 1045 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0) 1046 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0) 1047 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0) 1048 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0) 1049 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs 1050 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs 1051 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face 1052}; 1053 1054static int lpaint_getFontMetrics(lua_State* L) { 1055 SkPaint::FontMetrics fm; 1056 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm); 1057 1058 lua_newtable(L); 1059 setfield_scalar(L, "top", fm.fTop); 1060 setfield_scalar(L, "ascent", fm.fAscent); 1061 setfield_scalar(L, "descent", fm.fDescent); 1062 setfield_scalar(L, "bottom", fm.fBottom); 1063 setfield_scalar(L, "leading", fm.fLeading); 1064 SkLua(L).pushScalar(height); 1065 return 2; 1066} 1067 1068static int lpaint_getEffects(lua_State* L) { 1069 const SkPaint* paint = get_obj<SkPaint>(L, 1); 1070 1071 lua_newtable(L); 1072 setfield_bool_if(L, "looper", !!paint->getLooper()); 1073 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect()); 1074 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer()); 1075 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter()); 1076 setfield_bool_if(L, "shader", !!paint->getShader()); 1077 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter()); 1078 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter()); 1079 setfield_bool_if(L, "xfermode", !!paint->getXfermode()); 1080 return 1; 1081} 1082 1083static int lpaint_getXfermode(lua_State* L) { 1084 const SkPaint* paint = get_obj<SkPaint>(L, 1); 1085 SkXfermode* xfermode = paint->getXfermode(); 1086 if (xfermode) { 1087 push_ref(L, xfermode); 1088 return 1; 1089 } 1090 return 0; 1091} 1092 1093static int lpaint_setXfermode(lua_State* L) { 1094 SkPaint* paint = get_obj<SkPaint>(L, 1); 1095 paint->setXfermode(get_ref<SkXfermode>(L, 2)); 1096 return 0; 1097} 1098 1099static int lpaint_getColorFilter(lua_State* L) { 1100 const SkPaint* paint = get_obj<SkPaint>(L, 1); 1101 SkColorFilter* cf = paint->getColorFilter(); 1102 if (cf) { 1103 push_ref(L, cf); 1104 return 1; 1105 } 1106 return 0; 1107} 1108 1109static int lpaint_setColorFilter(lua_State* L) { 1110 SkPaint* paint = get_obj<SkPaint>(L, 1); 1111 paint->setColorFilter(get_ref<SkColorFilter>(L, 2)); 1112 return 0; 1113} 1114 1115static int lpaint_getImageFilter(lua_State* L) { 1116 const SkPaint* paint = get_obj<SkPaint>(L, 1); 1117 SkImageFilter* imf = paint->getImageFilter(); 1118 if (imf) { 1119 push_ref(L, imf); 1120 return 1; 1121 } 1122 return 0; 1123} 1124 1125static int lpaint_setImageFilter(lua_State* L) { 1126 SkPaint* paint = get_obj<SkPaint>(L, 1); 1127 paint->setImageFilter(get_ref<SkImageFilter>(L, 2)); 1128 return 0; 1129} 1130 1131static int lpaint_getShader(lua_State* L) { 1132 const SkPaint* paint = get_obj<SkPaint>(L, 1); 1133 SkShader* shader = paint->getShader(); 1134 if (shader) { 1135 push_ref(L, shader); 1136 return 1; 1137 } 1138 return 0; 1139} 1140 1141static int lpaint_setShader(lua_State* L) { 1142 SkPaint* paint = get_obj<SkPaint>(L, 1); 1143 paint->setShader(get_ref<SkShader>(L, 2)); 1144 return 0; 1145} 1146 1147static int lpaint_getPathEffect(lua_State* L) { 1148 const SkPaint* paint = get_obj<SkPaint>(L, 1); 1149 SkPathEffect* pe = paint->getPathEffect(); 1150 if (pe) { 1151 push_ref(L, pe); 1152 return 1; 1153 } 1154 return 0; 1155} 1156 1157static int lpaint_gc(lua_State* L) { 1158 get_obj<SkPaint>(L, 1)->~SkPaint(); 1159 return 0; 1160} 1161 1162static const struct luaL_Reg gSkPaint_Methods[] = { 1163 { "isAntiAlias", lpaint_isAntiAlias }, 1164 { "setAntiAlias", lpaint_setAntiAlias }, 1165 { "isDither", lpaint_isDither }, 1166 { "setDither", lpaint_setDither }, 1167 { "getFilterQuality", lpaint_getFilterQuality }, 1168 { "setFilterQuality", lpaint_setFilterQuality }, 1169 { "isUnderlineText", lpaint_isUnderlineText }, 1170 { "isStrikeThruText", lpaint_isStrikeThruText }, 1171 { "isFakeBoldText", lpaint_isFakeBoldText }, 1172 { "isLinearText", lpaint_isLinearText }, 1173 { "isSubpixelText", lpaint_isSubpixelText }, 1174 { "setSubpixelText", lpaint_setSubpixelText }, 1175 { "isDevKernText", lpaint_isDevKernText }, 1176 { "isLCDRenderText", lpaint_isLCDRenderText }, 1177 { "setLCDRenderText", lpaint_setLCDRenderText }, 1178 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText }, 1179 { "isAutohinted", lpaint_isAutohinted }, 1180 { "isVerticalText", lpaint_isVerticalText }, 1181 { "getAlpha", lpaint_getAlpha }, 1182 { "setAlpha", lpaint_setAlpha }, 1183 { "getColor", lpaint_getColor }, 1184 { "setColor", lpaint_setColor }, 1185 { "getTextSize", lpaint_getTextSize }, 1186 { "setTextSize", lpaint_setTextSize }, 1187 { "getTextScaleX", lpaint_getTextScaleX }, 1188 { "getTextSkewX", lpaint_getTextSkewX }, 1189 { "getTypeface", lpaint_getTypeface }, 1190 { "setTypeface", lpaint_setTypeface }, 1191 { "getHinting", lpaint_getHinting }, 1192 { "getFontID", lpaint_getFontID }, 1193 { "getTextAlign", lpaint_getTextAlign }, 1194 { "setTextAlign", lpaint_setTextAlign }, 1195 { "getStroke", lpaint_getStroke }, 1196 { "setStroke", lpaint_setStroke }, 1197 { "getStrokeCap", lpaint_getStrokeCap }, 1198 { "getStrokeJoin", lpaint_getStrokeJoin }, 1199 { "getTextEncoding", lpaint_getTextEncoding }, 1200 { "getStrokeWidth", lpaint_getStrokeWidth }, 1201 { "setStrokeWidth", lpaint_setStrokeWidth }, 1202 { "getStrokeMiter", lpaint_getStrokeMiter }, 1203 { "measureText", lpaint_measureText }, 1204 { "getFontMetrics", lpaint_getFontMetrics }, 1205 { "getEffects", lpaint_getEffects }, 1206 { "getColorFilter", lpaint_getColorFilter }, 1207 { "setColorFilter", lpaint_setColorFilter }, 1208 { "getImageFilter", lpaint_getImageFilter }, 1209 { "setImageFilter", lpaint_setImageFilter }, 1210 { "getXfermode", lpaint_getXfermode }, 1211 { "setXfermode", lpaint_setXfermode }, 1212 { "getShader", lpaint_getShader }, 1213 { "setShader", lpaint_setShader }, 1214 { "getPathEffect", lpaint_getPathEffect }, 1215 { "__gc", lpaint_gc }, 1216 { nullptr, nullptr } 1217}; 1218 1219/////////////////////////////////////////////////////////////////////////////// 1220 1221static const char* mode2string(SkShader::TileMode mode) { 1222 static const char* gNames[] = { "clamp", "repeat", "mirror" }; 1223 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames)); 1224 return gNames[mode]; 1225} 1226 1227static const char* gradtype2string(SkShader::GradientType t) { 1228 static const char* gNames[] = { 1229 "none", "color", "linear", "radial", "radial2", "sweep", "conical" 1230 }; 1231 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames)); 1232 return gNames[t]; 1233} 1234 1235static int lshader_isOpaque(lua_State* L) { 1236 SkShader* shader = get_ref<SkShader>(L, 1); 1237 return shader && shader->isOpaque(); 1238} 1239 1240static int lshader_isABitmap(lua_State* L) { 1241 SkShader* shader = get_ref<SkShader>(L, 1); 1242 if (shader) { 1243 SkBitmap bm; 1244 SkMatrix matrix; 1245 SkShader::TileMode modes[2]; 1246 if (shader->isABitmap(&bm, &matrix, modes)) { 1247 lua_newtable(L); 1248 setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0); 1249 setfield_number(L, "width", bm.width()); 1250 setfield_number(L, "height", bm.height()); 1251 setfield_string(L, "tileX", mode2string(modes[0])); 1252 setfield_string(L, "tileY", mode2string(modes[1])); 1253 return 1; 1254 } 1255 } 1256 return 0; 1257} 1258 1259static int lshader_asAGradient(lua_State* L) { 1260 SkShader* shader = get_ref<SkShader>(L, 1); 1261 if (shader) { 1262 SkShader::GradientInfo info; 1263 sk_bzero(&info, sizeof(info)); 1264 1265 SkColor colors[3]; // hacked in for extracting info on 3 color case. 1266 SkScalar pos[3]; 1267 1268 info.fColorCount = 3; 1269 info.fColors = &colors[0]; 1270 info.fColorOffsets = &pos[0]; 1271 1272 SkShader::GradientType t = shader->asAGradient(&info); 1273 1274 if (SkShader::kNone_GradientType != t) { 1275 lua_newtable(L); 1276 setfield_string(L, "type", gradtype2string(t)); 1277 setfield_number(L, "colorCount", info.fColorCount); 1278 setfield_string(L, "tile", mode2string(info.fTileMode)); 1279 1280 if (info.fColorCount == 3){ 1281 setfield_number(L, "midPos", pos[1]); 1282 } 1283 1284 return 1; 1285 } 1286 } 1287 return 0; 1288} 1289 1290static int lshader_gc(lua_State* L) { 1291 get_ref<SkShader>(L, 1)->unref(); 1292 return 0; 1293} 1294 1295static const struct luaL_Reg gSkShader_Methods[] = { 1296 { "isOpaque", lshader_isOpaque }, 1297 { "isABitmap", lshader_isABitmap }, 1298 { "asAGradient", lshader_asAGradient }, 1299 { "__gc", lshader_gc }, 1300 { nullptr, nullptr } 1301}; 1302 1303/////////////////////////////////////////////////////////////////////////////// 1304 1305static int lpatheffect_asADash(lua_State* L) { 1306 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1); 1307 if (pe) { 1308 SkPathEffect::DashInfo info; 1309 SkPathEffect::DashType dashType = pe->asADash(&info); 1310 if (SkPathEffect::kDash_DashType == dashType) { 1311 SkAutoTArray<SkScalar> intervals(info.fCount); 1312 info.fIntervals = intervals.get(); 1313 pe->asADash(&info); 1314 SkLua(L).pushDash(info); 1315 return 1; 1316 } 1317 } 1318 return 0; 1319} 1320 1321static int lpatheffect_gc(lua_State* L) { 1322 get_ref<SkPathEffect>(L, 1)->unref(); 1323 return 0; 1324} 1325 1326static const struct luaL_Reg gSkPathEffect_Methods[] = { 1327 { "asADash", lpatheffect_asADash }, 1328 { "__gc", lpatheffect_gc }, 1329 { nullptr, nullptr } 1330}; 1331 1332/////////////////////////////////////////////////////////////////////////////// 1333 1334static int lpxfermode_getTypeName(lua_State* L) { 1335 lua_pushstring(L, get_ref<SkXfermode>(L, 1)->getTypeName()); 1336 return 1; 1337} 1338 1339static int lpxfermode_gc(lua_State* L) { 1340 get_ref<SkXfermode>(L, 1)->unref(); 1341 return 0; 1342} 1343 1344static const struct luaL_Reg gSkXfermode_Methods[] = { 1345 { "getTypeName", lpxfermode_getTypeName }, 1346 { "__gc", lpxfermode_gc }, 1347 { nullptr, nullptr } 1348}; 1349 1350/////////////////////////////////////////////////////////////////////////////// 1351 1352static int lpcolorfilter_gc(lua_State* L) { 1353 get_ref<SkColorFilter>(L, 1)->unref(); 1354 return 0; 1355} 1356 1357static const struct luaL_Reg gSkColorFilter_Methods[] = { 1358 { "__gc", lpcolorfilter_gc }, 1359 { nullptr, nullptr } 1360}; 1361 1362/////////////////////////////////////////////////////////////////////////////// 1363 1364static int lpimagefilter_gc(lua_State* L) { 1365 get_ref<SkImageFilter>(L, 1)->unref(); 1366 return 0; 1367} 1368 1369static const struct luaL_Reg gSkImageFilter_Methods[] = { 1370 { "__gc", lpimagefilter_gc }, 1371 { nullptr, nullptr } 1372}; 1373 1374/////////////////////////////////////////////////////////////////////////////// 1375 1376static int lmatrix_getType(lua_State* L) { 1377 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType(); 1378 1379 lua_newtable(L); 1380 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask)); 1381 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask)); 1382 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask)); 1383 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask)); 1384 return 1; 1385} 1386 1387static int lmatrix_getScaleX(lua_State* L) { 1388 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX()); 1389 return 1; 1390} 1391 1392static int lmatrix_getScaleY(lua_State* L) { 1393 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY()); 1394 return 1; 1395} 1396 1397static int lmatrix_getTranslateX(lua_State* L) { 1398 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX()); 1399 return 1; 1400} 1401 1402static int lmatrix_getTranslateY(lua_State* L) { 1403 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY()); 1404 return 1; 1405} 1406 1407static int lmatrix_invert(lua_State* L) { 1408 lua_pushboolean(L, get_obj<SkMatrix>(L, 1)->invert(get_obj<SkMatrix>(L, 2))); 1409 return 1; 1410} 1411 1412static int lmatrix_mapXY(lua_State* L) { 1413 SkPoint pt = { lua2scalar(L, 2), lua2scalar(L, 3) }; 1414 get_obj<SkMatrix>(L, 1)->mapPoints(&pt, &pt, 1); 1415 lua_pushnumber(L, pt.x()); 1416 lua_pushnumber(L, pt.y()); 1417 return 2; 1418} 1419 1420static int lmatrix_setRectToRect(lua_State* L) { 1421 SkMatrix* matrix = get_obj<SkMatrix>(L, 1); 1422 SkRect srcR, dstR; 1423 lua2rect(L, 2, &srcR); 1424 lua2rect(L, 3, &dstR); 1425 const char* scaleToFitStr = lua_tostring(L, 4); 1426 SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit; 1427 1428 if (scaleToFitStr) { 1429 const struct { 1430 const char* fName; 1431 SkMatrix::ScaleToFit fScaleToFit; 1432 } rec[] = { 1433 { "fill", SkMatrix::kFill_ScaleToFit }, 1434 { "start", SkMatrix::kStart_ScaleToFit }, 1435 { "center", SkMatrix::kCenter_ScaleToFit }, 1436 { "end", SkMatrix::kEnd_ScaleToFit }, 1437 }; 1438 1439 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) { 1440 if (strcmp(rec[i].fName, scaleToFitStr) == 0) { 1441 scaleToFit = rec[i].fScaleToFit; 1442 break; 1443 } 1444 } 1445 } 1446 1447 matrix->setRectToRect(srcR, dstR, scaleToFit); 1448 return 0; 1449} 1450 1451static const struct luaL_Reg gSkMatrix_Methods[] = { 1452 { "getType", lmatrix_getType }, 1453 { "getScaleX", lmatrix_getScaleX }, 1454 { "getScaleY", lmatrix_getScaleY }, 1455 { "getTranslateX", lmatrix_getTranslateX }, 1456 { "getTranslateY", lmatrix_getTranslateY }, 1457 { "setRectToRect", lmatrix_setRectToRect }, 1458 { "invert", lmatrix_invert }, 1459 { "mapXY", lmatrix_mapXY }, 1460 { nullptr, nullptr } 1461}; 1462 1463/////////////////////////////////////////////////////////////////////////////// 1464 1465static int lpath_getBounds(lua_State* L) { 1466 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds()); 1467 return 1; 1468} 1469 1470static const char* fill_type_to_str(SkPath::FillType fill) { 1471 switch (fill) { 1472 case SkPath::kEvenOdd_FillType: 1473 return "even-odd"; 1474 case SkPath::kWinding_FillType: 1475 return "winding"; 1476 case SkPath::kInverseEvenOdd_FillType: 1477 return "inverse-even-odd"; 1478 case SkPath::kInverseWinding_FillType: 1479 return "inverse-winding"; 1480 } 1481 return "unknown"; 1482} 1483 1484static int lpath_getFillType(lua_State* L) { 1485 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType(); 1486 SkLua(L).pushString(fill_type_to_str(fill)); 1487 return 1; 1488} 1489 1490static SkString segment_masks_to_str(uint32_t segmentMasks) { 1491 SkString result; 1492 bool first = true; 1493 if (SkPath::kLine_SegmentMask & segmentMasks) { 1494 result.append("line"); 1495 first = false; 1496 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;) 1497 } 1498 if (SkPath::kQuad_SegmentMask & segmentMasks) { 1499 if (!first) { 1500 result.append(" "); 1501 } 1502 result.append("quad"); 1503 first = false; 1504 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;) 1505 } 1506 if (SkPath::kConic_SegmentMask & segmentMasks) { 1507 if (!first) { 1508 result.append(" "); 1509 } 1510 result.append("conic"); 1511 first = false; 1512 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;) 1513 } 1514 if (SkPath::kCubic_SegmentMask & segmentMasks) { 1515 if (!first) { 1516 result.append(" "); 1517 } 1518 result.append("cubic"); 1519 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;) 1520 } 1521 SkASSERT(0 == segmentMasks); 1522 return result; 1523} 1524 1525static int lpath_getSegmentTypes(lua_State* L) { 1526 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks(); 1527 SkLua(L).pushString(segment_masks_to_str(segMasks)); 1528 return 1; 1529} 1530 1531static int lpath_isConvex(lua_State* L) { 1532 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity(); 1533 SkLua(L).pushBool(isConvex); 1534 return 1; 1535} 1536 1537static int lpath_isEmpty(lua_State* L) { 1538 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty()); 1539 return 1; 1540} 1541 1542static int lpath_isRect(lua_State* L) { 1543 SkRect r; 1544 bool pred = get_obj<SkPath>(L, 1)->isRect(&r); 1545 int ret_count = 1; 1546 lua_pushboolean(L, pred); 1547 if (pred) { 1548 SkLua(L).pushRect(r); 1549 ret_count += 1; 1550 } 1551 return ret_count; 1552} 1553 1554static const char* dir2string(SkPath::Direction dir) { 1555 static const char* gStr[] = { 1556 "unknown", "cw", "ccw" 1557 }; 1558 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr)); 1559 return gStr[dir]; 1560} 1561 1562static int lpath_isNestedFillRects(lua_State* L) { 1563 SkRect rects[2]; 1564 SkPath::Direction dirs[2]; 1565 bool pred = get_obj<SkPath>(L, 1)->isNestedFillRects(rects, dirs); 1566 int ret_count = 1; 1567 lua_pushboolean(L, pred); 1568 if (pred) { 1569 SkLua lua(L); 1570 lua.pushRect(rects[0]); 1571 lua.pushRect(rects[1]); 1572 lua_pushstring(L, dir2string(dirs[0])); 1573 lua_pushstring(L, dir2string(dirs[0])); 1574 ret_count += 4; 1575 } 1576 return ret_count; 1577} 1578 1579static int lpath_countPoints(lua_State* L) { 1580 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints()); 1581 return 1; 1582} 1583 1584static int lpath_reset(lua_State* L) { 1585 get_obj<SkPath>(L, 1)->reset(); 1586 return 0; 1587} 1588 1589static int lpath_moveTo(lua_State* L) { 1590 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3)); 1591 return 0; 1592} 1593 1594static int lpath_lineTo(lua_State* L) { 1595 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3)); 1596 return 0; 1597} 1598 1599static int lpath_quadTo(lua_State* L) { 1600 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3), 1601 lua2scalar(L, 4), lua2scalar(L, 5)); 1602 return 0; 1603} 1604 1605static int lpath_cubicTo(lua_State* L) { 1606 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3), 1607 lua2scalar(L, 4), lua2scalar(L, 5), 1608 lua2scalar(L, 6), lua2scalar(L, 7)); 1609 return 0; 1610} 1611 1612static int lpath_close(lua_State* L) { 1613 get_obj<SkPath>(L, 1)->close(); 1614 return 0; 1615} 1616 1617static int lpath_gc(lua_State* L) { 1618 get_obj<SkPath>(L, 1)->~SkPath(); 1619 return 0; 1620} 1621 1622static const struct luaL_Reg gSkPath_Methods[] = { 1623 { "getBounds", lpath_getBounds }, 1624 { "getFillType", lpath_getFillType }, 1625 { "getSegmentTypes", lpath_getSegmentTypes }, 1626 { "isConvex", lpath_isConvex }, 1627 { "isEmpty", lpath_isEmpty }, 1628 { "isRect", lpath_isRect }, 1629 { "isNestedFillRects", lpath_isNestedFillRects }, 1630 { "countPoints", lpath_countPoints }, 1631 { "reset", lpath_reset }, 1632 { "moveTo", lpath_moveTo }, 1633 { "lineTo", lpath_lineTo }, 1634 { "quadTo", lpath_quadTo }, 1635 { "cubicTo", lpath_cubicTo }, 1636 { "close", lpath_close }, 1637 { "__gc", lpath_gc }, 1638 { nullptr, nullptr } 1639}; 1640 1641/////////////////////////////////////////////////////////////////////////////// 1642 1643static const char* rrect_type(const SkRRect& rr) { 1644 switch (rr.getType()) { 1645 case SkRRect::kEmpty_Type: return "empty"; 1646 case SkRRect::kRect_Type: return "rect"; 1647 case SkRRect::kOval_Type: return "oval"; 1648 case SkRRect::kSimple_Type: return "simple"; 1649 case SkRRect::kNinePatch_Type: return "nine-patch"; 1650 case SkRRect::kComplex_Type: return "complex"; 1651 } 1652 SkDEBUGFAIL("never get here"); 1653 return ""; 1654} 1655 1656static int lrrect_rect(lua_State* L) { 1657 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect()); 1658 return 1; 1659} 1660 1661static int lrrect_type(lua_State* L) { 1662 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1))); 1663 return 1; 1664} 1665 1666static int lrrect_radii(lua_State* L) { 1667 int corner = SkToInt(lua_tointeger(L, 2)); 1668 SkVector v; 1669 if (corner < 0 || corner > 3) { 1670 SkDebugf("bad corner index %d", corner); 1671 v.set(0, 0); 1672 } else { 1673 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner); 1674 } 1675 lua_pushnumber(L, v.fX); 1676 lua_pushnumber(L, v.fY); 1677 return 2; 1678} 1679 1680static int lrrect_gc(lua_State* L) { 1681 get_obj<SkRRect>(L, 1)->~SkRRect(); 1682 return 0; 1683} 1684 1685static const struct luaL_Reg gSkRRect_Methods[] = { 1686 { "rect", lrrect_rect }, 1687 { "type", lrrect_type }, 1688 { "radii", lrrect_radii }, 1689 { "__gc", lrrect_gc }, 1690 { nullptr, nullptr } 1691}; 1692 1693/////////////////////////////////////////////////////////////////////////////// 1694 1695static int limage_width(lua_State* L) { 1696 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width()); 1697 return 1; 1698} 1699 1700static int limage_height(lua_State* L) { 1701 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height()); 1702 return 1; 1703} 1704 1705static int limage_newShader(lua_State* L) { 1706 SkShader::TileMode tmode = SkShader::kClamp_TileMode; 1707 const SkMatrix* localM = nullptr; 1708 SkAutoTUnref<SkShader> shader(get_ref<SkImage>(L, 1)->newShader(tmode, tmode, localM)); 1709 push_ref(L, shader.get()); 1710 return 1; 1711} 1712 1713static int limage_gc(lua_State* L) { 1714 get_ref<SkImage>(L, 1)->unref(); 1715 return 0; 1716} 1717 1718static const struct luaL_Reg gSkImage_Methods[] = { 1719 { "width", limage_width }, 1720 { "height", limage_height }, 1721 { "newShader", limage_newShader }, 1722 { "__gc", limage_gc }, 1723 { nullptr, nullptr } 1724}; 1725 1726/////////////////////////////////////////////////////////////////////////////// 1727 1728static int lsurface_width(lua_State* L) { 1729 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width()); 1730 return 1; 1731} 1732 1733static int lsurface_height(lua_State* L) { 1734 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height()); 1735 return 1; 1736} 1737 1738static int lsurface_getCanvas(lua_State* L) { 1739 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas(); 1740 if (nullptr == canvas) { 1741 lua_pushnil(L); 1742 } else { 1743 push_ref(L, canvas); 1744 // note: we don't unref canvas, since getCanvas did not ref it. 1745 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let 1746 // the real owner (the surface) go away, but still hold onto the canvas? 1747 // *really* we want to sort of ref the surface again, but have the native object 1748 // know that it is supposed to be treated as a canvas... 1749 } 1750 return 1; 1751} 1752 1753static int lsurface_newImageSnapshot(lua_State* L) { 1754 SkImage* image = get_ref<SkSurface>(L, 1)->newImageSnapshot(); 1755 if (nullptr == image) { 1756 lua_pushnil(L); 1757 } else { 1758 push_ref(L, image)->unref(); 1759 } 1760 return 1; 1761} 1762 1763static int lsurface_newSurface(lua_State* L) { 1764 int width = lua2int_def(L, 2, 0); 1765 int height = lua2int_def(L, 3, 0); 1766 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); 1767 SkSurface* surface = get_ref<SkSurface>(L, 1)->newSurface(info); 1768 if (nullptr == surface) { 1769 lua_pushnil(L); 1770 } else { 1771 push_ref(L, surface)->unref(); 1772 } 1773 return 1; 1774} 1775 1776static int lsurface_gc(lua_State* L) { 1777 get_ref<SkSurface>(L, 1)->unref(); 1778 return 0; 1779} 1780 1781static const struct luaL_Reg gSkSurface_Methods[] = { 1782 { "width", lsurface_width }, 1783 { "height", lsurface_height }, 1784 { "getCanvas", lsurface_getCanvas }, 1785 { "newImageSnapshot", lsurface_newImageSnapshot }, 1786 { "newSurface", lsurface_newSurface }, 1787 { "__gc", lsurface_gc }, 1788 { nullptr, nullptr } 1789}; 1790 1791/////////////////////////////////////////////////////////////////////////////// 1792 1793static int lpicturerecorder_beginRecording(lua_State* L) { 1794 const SkScalar w = lua2scalar_def(L, 2, -1); 1795 const SkScalar h = lua2scalar_def(L, 3, -1); 1796 if (w <= 0 || h <= 0) { 1797 lua_pushnil(L); 1798 return 1; 1799 } 1800 1801 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h); 1802 if (nullptr == canvas) { 1803 lua_pushnil(L); 1804 return 1; 1805 } 1806 1807 push_ref(L, canvas); 1808 return 1; 1809} 1810 1811static int lpicturerecorder_getCanvas(lua_State* L) { 1812 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas(); 1813 if (nullptr == canvas) { 1814 lua_pushnil(L); 1815 return 1; 1816 } 1817 push_ref(L, canvas); 1818 return 1; 1819} 1820 1821static int lpicturerecorder_endRecording(lua_State* L) { 1822 SkPicture* pic = get_obj<SkPictureRecorder>(L, 1)->endRecording(); 1823 if (nullptr == pic) { 1824 lua_pushnil(L); 1825 return 1; 1826 } 1827 push_ref(L, pic)->unref(); 1828 return 1; 1829} 1830 1831static int lpicturerecorder_gc(lua_State* L) { 1832 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder(); 1833 return 0; 1834} 1835 1836static const struct luaL_Reg gSkPictureRecorder_Methods[] = { 1837 { "beginRecording", lpicturerecorder_beginRecording }, 1838 { "getCanvas", lpicturerecorder_getCanvas }, 1839 { "endRecording", lpicturerecorder_endRecording }, 1840 { "__gc", lpicturerecorder_gc }, 1841 { nullptr, nullptr } 1842}; 1843 1844/////////////////////////////////////////////////////////////////////////////// 1845 1846static int lpicture_width(lua_State* L) { 1847 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width()); 1848 return 1; 1849} 1850 1851static int lpicture_height(lua_State* L) { 1852 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height()); 1853 return 1; 1854} 1855 1856static int lpicture_gc(lua_State* L) { 1857 get_ref<SkPicture>(L, 1)->unref(); 1858 return 0; 1859} 1860 1861static const struct luaL_Reg gSkPicture_Methods[] = { 1862 { "width", lpicture_width }, 1863 { "height", lpicture_height }, 1864 { "__gc", lpicture_gc }, 1865 { nullptr, nullptr } 1866}; 1867 1868/////////////////////////////////////////////////////////////////////////////// 1869 1870static int ltextblob_bounds(lua_State* L) { 1871 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds()); 1872 return 1; 1873} 1874 1875static int ltextblob_gc(lua_State* L) { 1876 SkSafeUnref(get_ref<SkTextBlob>(L, 1)); 1877 return 0; 1878} 1879 1880static const struct luaL_Reg gSkTextBlob_Methods[] = { 1881 { "bounds", ltextblob_bounds }, 1882 { "__gc", ltextblob_gc }, 1883 { nullptr, nullptr } 1884}; 1885 1886/////////////////////////////////////////////////////////////////////////////// 1887 1888static int ltypeface_getFamilyName(lua_State* L) { 1889 SkString str; 1890 get_ref<SkTypeface>(L, 1)->getFamilyName(&str); 1891 lua_pushstring(L, str.c_str()); 1892 return 1; 1893} 1894 1895static int ltypeface_getStyle(lua_State* L) { 1896 lua_pushnumber(L, (double)get_ref<SkTypeface>(L, 1)->style()); 1897 return 1; 1898} 1899 1900static int ltypeface_gc(lua_State* L) { 1901 SkSafeUnref(get_ref<SkTypeface>(L, 1)); 1902 return 0; 1903} 1904 1905static const struct luaL_Reg gSkTypeface_Methods[] = { 1906 { "getFamilyName", ltypeface_getFamilyName }, 1907 { "getStyle", ltypeface_getStyle }, 1908 { "__gc", ltypeface_gc }, 1909 { nullptr, nullptr } 1910}; 1911 1912/////////////////////////////////////////////////////////////////////////////// 1913 1914class AutoCallLua { 1915public: 1916 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) { 1917 lua_getglobal(L, func); 1918 if (!lua_isfunction(L, -1)) { 1919 int t = lua_type(L, -1); 1920 SkDebugf("--- expected function %d\n", t); 1921 } 1922 1923 lua_newtable(L); 1924 setfield_string(L, "verb", verb); 1925 } 1926 1927 ~AutoCallLua() { 1928 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) { 1929 SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); 1930 } 1931 lua_settop(fL, -1); 1932 } 1933 1934private: 1935 lua_State* fL; 1936}; 1937 1938#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb) 1939 1940/////////////////////////////////////////////////////////////////////////////// 1941 1942static int lsk_newDocumentPDF(lua_State* L) { 1943 const char* file = nullptr; 1944 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { 1945 file = lua_tolstring(L, 1, nullptr); 1946 } 1947 1948 SkDocument* doc = SkDocument::CreatePDF(file); 1949 if (nullptr == doc) { 1950 // do I need to push a nil on the stack and return 1? 1951 return 0; 1952 } else { 1953 push_ref(L, doc)->unref(); 1954 return 1; 1955 } 1956} 1957 1958static int lsk_newBlurImageFilter(lua_State* L) { 1959 SkScalar sigmaX = lua2scalar_def(L, 1, 0); 1960 SkScalar sigmaY = lua2scalar_def(L, 2, 0); 1961 SkImageFilter* imf = SkBlurImageFilter::Create(sigmaX, sigmaY); 1962 if (nullptr == imf) { 1963 lua_pushnil(L); 1964 } else { 1965 push_ref(L, imf)->unref(); 1966 } 1967 return 1; 1968} 1969 1970static int lsk_newLinearGradient(lua_State* L) { 1971 SkScalar x0 = lua2scalar_def(L, 1, 0); 1972 SkScalar y0 = lua2scalar_def(L, 2, 0); 1973 SkColor c0 = lua2color(L, 3); 1974 SkScalar x1 = lua2scalar_def(L, 4, 0); 1975 SkScalar y1 = lua2scalar_def(L, 5, 0); 1976 SkColor c1 = lua2color(L, 6); 1977 1978 SkPoint pts[] = { { x0, y0 }, { x1, y1 } }; 1979 SkColor colors[] = { c0, c1 }; 1980 SkShader* s = SkGradientShader::CreateLinear(pts, colors, nullptr, 2, SkShader::kClamp_TileMode); 1981 if (nullptr == s) { 1982 lua_pushnil(L); 1983 } else { 1984 push_ref(L, s)->unref(); 1985 } 1986 return 1; 1987} 1988 1989static int lsk_newMatrix(lua_State* L) { 1990 push_new<SkMatrix>(L)->reset(); 1991 return 1; 1992} 1993 1994static int lsk_newPaint(lua_State* L) { 1995 push_new<SkPaint>(L); 1996 return 1; 1997} 1998 1999static int lsk_newPath(lua_State* L) { 2000 push_new<SkPath>(L); 2001 return 1; 2002} 2003 2004static int lsk_newPictureRecorder(lua_State* L) { 2005 push_new<SkPictureRecorder>(L); 2006 return 1; 2007} 2008 2009static int lsk_newRRect(lua_State* L) { 2010 push_new<SkRRect>(L)->setEmpty(); 2011 return 1; 2012} 2013 2014#include "SkTextBox.h" 2015// Sk.newTextBlob(text, rect, paint) 2016static int lsk_newTextBlob(lua_State* L) { 2017 const char* text = lua_tolstring(L, 1, nullptr); 2018 SkRect bounds; 2019 lua2rect(L, 2, &bounds); 2020 const SkPaint& paint = *get_obj<SkPaint>(L, 3); 2021 2022 SkTextBox box; 2023 box.setMode(SkTextBox::kLineBreak_Mode); 2024 box.setBox(bounds); 2025 box.setText(text, strlen(text), paint); 2026 2027 SkScalar newBottom; 2028 SkAutoTUnref<SkTextBlob> blob(box.snapshotTextBlob(&newBottom)); 2029 push_ref<SkTextBlob>(L, blob); 2030 SkLua(L).pushScalar(newBottom); 2031 return 2; 2032} 2033 2034static int lsk_newTypeface(lua_State* L) { 2035 const char* name = nullptr; 2036 int style = SkTypeface::kNormal; 2037 2038 int count = lua_gettop(L); 2039 if (count > 0 && lua_isstring(L, 1)) { 2040 name = lua_tolstring(L, 1, nullptr); 2041 if (count > 1 && lua_isnumber(L, 2)) { 2042 style = lua_tointegerx(L, 2, nullptr) & SkTypeface::kBoldItalic; 2043 } 2044 } 2045 2046 SkTypeface* face = SkTypeface::CreateFromName(name, 2047 (SkTypeface::Style)style); 2048// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt()); 2049 if (nullptr == face) { 2050 face = SkTypeface::RefDefault(); 2051 } 2052 push_ref(L, face)->unref(); 2053 return 1; 2054} 2055 2056static int lsk_newRasterSurface(lua_State* L) { 2057 int width = lua2int_def(L, 1, 0); 2058 int height = lua2int_def(L, 2, 0); 2059 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); 2060 SkSurfaceProps props(0, kUnknown_SkPixelGeometry); 2061 SkSurface* surface = SkSurface::NewRaster(info, &props); 2062 if (nullptr == surface) { 2063 lua_pushnil(L); 2064 } else { 2065 push_ref(L, surface)->unref(); 2066 } 2067 return 1; 2068} 2069 2070static int lsk_loadImage(lua_State* L) { 2071 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { 2072 const char* name = lua_tolstring(L, 1, nullptr); 2073 SkAutoDataUnref data(SkData::NewFromFileName(name)); 2074 if (data.get()) { 2075 SkImage* image = SkImage::NewFromEncoded(data); 2076 if (image) { 2077 push_ref(L, image)->unref(); 2078 return 1; 2079 } 2080 } 2081 } 2082 return 0; 2083} 2084 2085static void register_Sk(lua_State* L) { 2086 lua_newtable(L); 2087 lua_pushvalue(L, -1); 2088 lua_setglobal(L, "Sk"); 2089 // the Sk table is still on top 2090 2091 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF); 2092 setfield_function(L, "loadImage", lsk_loadImage); 2093 setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter); 2094 setfield_function(L, "newLinearGradient", lsk_newLinearGradient); 2095 setfield_function(L, "newMatrix", lsk_newMatrix); 2096 setfield_function(L, "newPaint", lsk_newPaint); 2097 setfield_function(L, "newPath", lsk_newPath); 2098 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder); 2099 setfield_function(L, "newRRect", lsk_newRRect); 2100 setfield_function(L, "newRasterSurface", lsk_newRasterSurface); 2101 setfield_function(L, "newTextBlob", lsk_newTextBlob); 2102 setfield_function(L, "newTypeface", lsk_newTypeface); 2103 lua_pop(L, 1); // pop off the Sk table 2104} 2105 2106#define REG_CLASS(L, C) \ 2107 do { \ 2108 luaL_newmetatable(L, get_mtname<C>()); \ 2109 lua_pushvalue(L, -1); \ 2110 lua_setfield(L, -2, "__index"); \ 2111 luaL_setfuncs(L, g##C##_Methods, 0); \ 2112 lua_pop(L, 1); /* pop off the meta-table */ \ 2113 } while (0) 2114 2115void SkLua::Load(lua_State* L) { 2116 register_Sk(L); 2117 REG_CLASS(L, SkCanvas); 2118 REG_CLASS(L, SkColorFilter); 2119 REG_CLASS(L, SkDocument); 2120 REG_CLASS(L, SkImage); 2121 REG_CLASS(L, SkImageFilter); 2122 REG_CLASS(L, SkMatrix); 2123 REG_CLASS(L, SkPaint); 2124 REG_CLASS(L, SkPath); 2125 REG_CLASS(L, SkPathEffect); 2126 REG_CLASS(L, SkPicture); 2127 REG_CLASS(L, SkPictureRecorder); 2128 REG_CLASS(L, SkRRect); 2129 REG_CLASS(L, SkShader); 2130 REG_CLASS(L, SkSurface); 2131 REG_CLASS(L, SkTextBlob); 2132 REG_CLASS(L, SkTypeface); 2133 REG_CLASS(L, SkXfermode); 2134} 2135 2136extern "C" int luaopen_skia(lua_State* L); 2137extern "C" int luaopen_skia(lua_State* L) { 2138 SkLua::Load(L); 2139 return 0; 2140} 2141