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 33 extern "C" { 34 #include "lua.h" 35 #include "lualib.h" 36 #include "lauxlib.h" 37 } 38 39 // return the metatable name for a given class 40 template <typename T> const char* get_mtname(); 41 #define DEF_MTNAME(T) \ 42 template <> const char* get_mtname<T>() { \ 43 return #T "_LuaMetaTableName"; \ 44 } 45 46 DEF_MTNAME(SkCanvas) 47 DEF_MTNAME(SkColorFilter) 48 DEF_MTNAME(SkDocument) 49 DEF_MTNAME(SkImage) 50 DEF_MTNAME(SkImageFilter) 51 DEF_MTNAME(SkMatrix) 52 DEF_MTNAME(SkRRect) 53 DEF_MTNAME(SkPath) 54 DEF_MTNAME(SkPaint) 55 DEF_MTNAME(SkPathEffect) 56 DEF_MTNAME(SkPicture) 57 DEF_MTNAME(SkPictureRecorder) 58 DEF_MTNAME(SkShader) 59 DEF_MTNAME(SkSurface) 60 DEF_MTNAME(SkTextBlob) 61 DEF_MTNAME(SkTypeface) 62 DEF_MTNAME(SkXfermode) 63 64 template <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 72 template <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 78 template <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 85 template <typename T> T* get_ref(lua_State* L, int index) { 86 return *(T**)luaL_checkudata(L, index, get_mtname<T>()); 87 } 88 89 template <typename T> T* get_obj(lua_State* L, int index) { 90 return (T*)luaL_checkudata(L, index, get_mtname<T>()); 91 } 92 93 static bool lua2bool(lua_State* L, int index) { 94 return !!lua_toboolean(L, index); 95 } 96 97 /////////////////////////////////////////////////////////////////////////////// 98 99 SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) { 100 fL = luaL_newstate(); 101 luaL_openlibs(fL); 102 SkLua::Load(fL); 103 } 104 105 SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {} 106 107 SkLua::~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 119 bool 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 128 bool 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 137 static 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 144 static 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 149 static void setfield_number(lua_State* L, const char key[], double value) { 150 lua_pushnumber(L, value); 151 lua_setfield(L, -2, key); 152 } 153 154 static void setfield_boolean(lua_State* L, const char key[], bool value) { 155 lua_pushboolean(L, value); 156 lua_setfield(L, -2, key); 157 } 158 159 static void setfield_scalar(lua_State* L, const char key[], SkScalar value) { 160 setfield_number(L, key, SkScalarToLua(value)); 161 } 162 163 static 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 169 static 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 177 static SkScalar lua2scalar(lua_State* L, int index) { 178 SkASSERT(lua_isnumber(L, index)); 179 return SkLuaToScalar(lua_tonumber(L, index)); 180 } 181 182 static 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 190 static 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 199 static 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 205 static void getarray_points(lua_State* L, int stackIndex, SkPoint pts[], int count) { 206 getarray_scalars(L, stackIndex, &pts[0].fX, count * 2); 207 } 208 209 static void setarray_number(lua_State* L, int index, double value) { 210 lua_pushnumber(L, value); 211 lua_rawseti(L, -2, index); 212 } 213 214 static void setarray_scalar(lua_State* L, int index, SkScalar value) { 215 setarray_number(L, index, SkScalarToLua(value)); 216 } 217 218 void SkLua::pushBool(bool value, const char key[]) { 219 lua_pushboolean(fL, value); 220 CHECK_SETFIELD(key); 221 } 222 223 void SkLua::pushString(const char str[], const char key[]) { 224 lua_pushstring(fL, str); 225 CHECK_SETFIELD(key); 226 } 227 228 void 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 235 void SkLua::pushString(const SkString& str, const char key[]) { 236 lua_pushstring(fL, str.c_str()); 237 CHECK_SETFIELD(key); 238 } 239 240 void 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 249 void SkLua::pushU32(uint32_t value, const char key[]) { 250 lua_pushnumber(fL, (double)value); 251 CHECK_SETFIELD(key); 252 } 253 254 void SkLua::pushScalar(SkScalar value, const char key[]) { 255 lua_pushnumber(fL, SkScalarToLua(value)); 256 CHECK_SETFIELD(key); 257 } 258 259 void 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 268 void 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 280 void 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 289 void 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 298 void SkLua::pushRRect(const SkRRect& rr, const char key[]) { 299 push_obj(fL, rr); 300 CHECK_SETFIELD(key); 301 } 302 303 void 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 311 void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) { 312 push_obj(fL, matrix); 313 CHECK_SETFIELD(key); 314 } 315 316 void SkLua::pushPaint(const SkPaint& paint, const char key[]) { 317 push_obj(fL, paint); 318 CHECK_SETFIELD(key); 319 } 320 321 void SkLua::pushPath(const SkPath& path, const char key[]) { 322 push_obj(fL, path); 323 CHECK_SETFIELD(key); 324 } 325 326 void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) { 327 push_ref(fL, canvas); 328 CHECK_SETFIELD(key); 329 } 330 331 void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) { 332 push_ref(fL, const_cast<SkTextBlob*>(blob)); 333 CHECK_SETFIELD(key); 334 } 335 336 static 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 350 static 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 368 void 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 380 void 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 406 static 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 416 static 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 431 static SkScalar byte2unit(U8CPU byte) { 432 return byte / 255.0f; 433 } 434 435 static 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 445 static 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 452 static 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 460 static int lcanvas_clear(lua_State* L) { 461 get_ref<SkCanvas>(L, 1)->clear(0); 462 return 0; 463 } 464 465 static int lcanvas_drawColor(lua_State* L) { 466 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2)); 467 return 0; 468 } 469 470 static int lcanvas_drawPaint(lua_State* L) { 471 get_ref<SkCanvas>(L, 1)->drawPaint(*get_obj<SkPaint>(L, 2)); 472 return 0; 473 } 474 475 static 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 483 static 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 490 static 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 498 static 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 512 static 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 526 static 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 545 static 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 571 static 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) 578 static 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 593 static 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 608 static 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 617 static int lcanvas_getSaveCount(lua_State* L) { 618 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount()); 619 return 1; 620 } 621 622 static int lcanvas_getTotalMatrix(lua_State* L) { 623 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix()); 624 return 1; 625 } 626 627 static int lcanvas_getClipStack(lua_State* L) { 628 SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack()); 629 return 1; 630 } 631 632 int 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 668 static int lcanvas_save(lua_State* L) { 669 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save()); 670 return 1; 671 } 672 673 static 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 679 static int lcanvas_restore(lua_State* L) { 680 get_ref<SkCanvas>(L, 1)->restore(); 681 return 0; 682 } 683 684 static 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 691 static 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 698 static 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 704 static int lcanvas_concat(lua_State* L) { 705 get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2)); 706 return 0; 707 } 708 709 static 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 722 static int lcanvas_gc(lua_State* L) { 723 get_ref<SkCanvas>(L, 1)->unref(); 724 return 0; 725 } 726 727 const 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 763 static 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 771 static int ldocument_endPage(lua_State* L) { 772 get_ref<SkDocument>(L, 1)->endPage(); 773 return 0; 774 } 775 776 static int ldocument_close(lua_State* L) { 777 get_ref<SkDocument>(L, 1)->close(); 778 return 0; 779 } 780 781 static int ldocument_gc(lua_State* L) { 782 get_ref<SkDocument>(L, 1)->unref(); 783 return 0; 784 } 785 786 static 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 796 static int lpaint_isAntiAlias(lua_State* L) { 797 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias()); 798 return 1; 799 } 800 801 static int lpaint_setAntiAlias(lua_State* L) { 802 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2)); 803 return 0; 804 } 805 806 static int lpaint_isDither(lua_State* L) { 807 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither()); 808 return 1; 809 } 810 811 static int lpaint_setDither(lua_State* L) { 812 get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2)); 813 return 0; 814 } 815 816 static int lpaint_isUnderlineText(lua_State* L) { 817 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText()); 818 return 1; 819 } 820 821 static int lpaint_isStrikeThruText(lua_State* L) { 822 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText()); 823 return 1; 824 } 825 826 static int lpaint_isFakeBoldText(lua_State* L) { 827 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText()); 828 return 1; 829 } 830 831 static int lpaint_isLinearText(lua_State* L) { 832 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText()); 833 return 1; 834 } 835 836 static int lpaint_isSubpixelText(lua_State* L) { 837 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText()); 838 return 1; 839 } 840 841 static int lpaint_setSubpixelText(lua_State* L) { 842 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2)); 843 return 1; 844 } 845 846 static int lpaint_isDevKernText(lua_State* L) { 847 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText()); 848 return 1; 849 } 850 851 static int lpaint_isLCDRenderText(lua_State* L) { 852 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText()); 853 return 1; 854 } 855 856 static int lpaint_setLCDRenderText(lua_State* L) { 857 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2)); 858 return 1; 859 } 860 861 static int lpaint_isEmbeddedBitmapText(lua_State* L) { 862 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText()); 863 return 1; 864 } 865 866 static int lpaint_isAutohinted(lua_State* L) { 867 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted()); 868 return 1; 869 } 870 871 static int lpaint_isVerticalText(lua_State* L) { 872 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText()); 873 return 1; 874 } 875 876 static int lpaint_getAlpha(lua_State* L) { 877 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha())); 878 return 1; 879 } 880 881 static int lpaint_setAlpha(lua_State* L) { 882 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2))); 883 return 0; 884 } 885 886 static int lpaint_getColor(lua_State* L) { 887 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor()); 888 return 1; 889 } 890 891 static int lpaint_setColor(lua_State* L) { 892 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2)); 893 return 0; 894 } 895 896 static int lpaint_getTextSize(lua_State* L) { 897 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize()); 898 return 1; 899 } 900 901 static int lpaint_getTextScaleX(lua_State* L) { 902 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX()); 903 return 1; 904 } 905 906 static int lpaint_getTextSkewX(lua_State* L) { 907 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX()); 908 return 1; 909 } 910 911 static int lpaint_setTextSize(lua_State* L) { 912 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2)); 913 return 0; 914 } 915 916 static int lpaint_getTypeface(lua_State* L) { 917 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface()); 918 return 1; 919 } 920 921 static int lpaint_setTypeface(lua_State* L) { 922 get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2)); 923 return 0; 924 } 925 926 static int lpaint_getHinting(lua_State* L) { 927 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting()); 928 return 1; 929 } 930 931 static int lpaint_getFilterQuality(lua_State* L) { 932 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality()); 933 return 1; 934 } 935 936 static 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 944 static 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 950 static 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 959 static 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 970 static 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 985 static int lpaint_getStroke(lua_State* L) { 986 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle()); 987 return 1; 988 } 989 990 static 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 1002 static int lpaint_getStrokeCap(lua_State* L) { 1003 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap()); 1004 return 1; 1005 } 1006 1007 static int lpaint_getStrokeJoin(lua_State* L) { 1008 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin()); 1009 return 1; 1010 } 1011 1012 static int lpaint_getTextEncoding(lua_State* L) { 1013 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding()); 1014 return 1; 1015 } 1016 1017 static int lpaint_getStrokeWidth(lua_State* L) { 1018 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth()); 1019 return 1; 1020 } 1021 1022 static int lpaint_setStrokeWidth(lua_State* L) { 1023 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2)); 1024 return 0; 1025 } 1026 1027 static int lpaint_getStrokeMiter(lua_State* L) { 1028 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter()); 1029 return 1; 1030 } 1031 1032 static 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 1042 struct 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 1054 static 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 1068 static 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 1083 static 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 1093 static 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 1099 static 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 1109 static 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 1115 static 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 1125 static 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 1131 static 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 1141 static 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 1147 static 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 1157 static int lpaint_gc(lua_State* L) { 1158 get_obj<SkPaint>(L, 1)->~SkPaint(); 1159 return 0; 1160 } 1161 1162 static 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 1221 static 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 1227 static 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 1235 static int lshader_isOpaque(lua_State* L) { 1236 SkShader* shader = get_ref<SkShader>(L, 1); 1237 return shader && shader->isOpaque(); 1238 } 1239 1240 static 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 1259 static 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 1290 static int lshader_gc(lua_State* L) { 1291 get_ref<SkShader>(L, 1)->unref(); 1292 return 0; 1293 } 1294 1295 static 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 1305 static 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 1321 static int lpatheffect_gc(lua_State* L) { 1322 get_ref<SkPathEffect>(L, 1)->unref(); 1323 return 0; 1324 } 1325 1326 static const struct luaL_Reg gSkPathEffect_Methods[] = { 1327 { "asADash", lpatheffect_asADash }, 1328 { "__gc", lpatheffect_gc }, 1329 { nullptr, nullptr } 1330 }; 1331 1332 /////////////////////////////////////////////////////////////////////////////// 1333 1334 static int lpxfermode_getTypeName(lua_State* L) { 1335 lua_pushstring(L, get_ref<SkXfermode>(L, 1)->getTypeName()); 1336 return 1; 1337 } 1338 1339 static int lpxfermode_gc(lua_State* L) { 1340 get_ref<SkXfermode>(L, 1)->unref(); 1341 return 0; 1342 } 1343 1344 static const struct luaL_Reg gSkXfermode_Methods[] = { 1345 { "getTypeName", lpxfermode_getTypeName }, 1346 { "__gc", lpxfermode_gc }, 1347 { nullptr, nullptr } 1348 }; 1349 1350 /////////////////////////////////////////////////////////////////////////////// 1351 1352 static int lpcolorfilter_gc(lua_State* L) { 1353 get_ref<SkColorFilter>(L, 1)->unref(); 1354 return 0; 1355 } 1356 1357 static const struct luaL_Reg gSkColorFilter_Methods[] = { 1358 { "__gc", lpcolorfilter_gc }, 1359 { nullptr, nullptr } 1360 }; 1361 1362 /////////////////////////////////////////////////////////////////////////////// 1363 1364 static int lpimagefilter_gc(lua_State* L) { 1365 get_ref<SkImageFilter>(L, 1)->unref(); 1366 return 0; 1367 } 1368 1369 static const struct luaL_Reg gSkImageFilter_Methods[] = { 1370 { "__gc", lpimagefilter_gc }, 1371 { nullptr, nullptr } 1372 }; 1373 1374 /////////////////////////////////////////////////////////////////////////////// 1375 1376 static 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 1387 static int lmatrix_getScaleX(lua_State* L) { 1388 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX()); 1389 return 1; 1390 } 1391 1392 static int lmatrix_getScaleY(lua_State* L) { 1393 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY()); 1394 return 1; 1395 } 1396 1397 static int lmatrix_getTranslateX(lua_State* L) { 1398 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX()); 1399 return 1; 1400 } 1401 1402 static int lmatrix_getTranslateY(lua_State* L) { 1403 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY()); 1404 return 1; 1405 } 1406 1407 static 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 1412 static 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 1420 static 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 1451 static 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 1465 static int lpath_getBounds(lua_State* L) { 1466 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds()); 1467 return 1; 1468 } 1469 1470 static 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 1484 static 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 1490 static 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 1525 static 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 1531 static 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 1537 static int lpath_isEmpty(lua_State* L) { 1538 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty()); 1539 return 1; 1540 } 1541 1542 static 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 1554 static 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 1562 static 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 1579 static int lpath_countPoints(lua_State* L) { 1580 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints()); 1581 return 1; 1582 } 1583 1584 static int lpath_reset(lua_State* L) { 1585 get_obj<SkPath>(L, 1)->reset(); 1586 return 0; 1587 } 1588 1589 static int lpath_moveTo(lua_State* L) { 1590 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3)); 1591 return 0; 1592 } 1593 1594 static int lpath_lineTo(lua_State* L) { 1595 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3)); 1596 return 0; 1597 } 1598 1599 static 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 1605 static 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 1612 static int lpath_close(lua_State* L) { 1613 get_obj<SkPath>(L, 1)->close(); 1614 return 0; 1615 } 1616 1617 static int lpath_gc(lua_State* L) { 1618 get_obj<SkPath>(L, 1)->~SkPath(); 1619 return 0; 1620 } 1621 1622 static 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 1643 static 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 1656 static int lrrect_rect(lua_State* L) { 1657 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect()); 1658 return 1; 1659 } 1660 1661 static int lrrect_type(lua_State* L) { 1662 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1))); 1663 return 1; 1664 } 1665 1666 static 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 1680 static int lrrect_gc(lua_State* L) { 1681 get_obj<SkRRect>(L, 1)->~SkRRect(); 1682 return 0; 1683 } 1684 1685 static 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 1695 static int limage_width(lua_State* L) { 1696 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width()); 1697 return 1; 1698 } 1699 1700 static int limage_height(lua_State* L) { 1701 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height()); 1702 return 1; 1703 } 1704 1705 static 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 1713 static int limage_gc(lua_State* L) { 1714 get_ref<SkImage>(L, 1)->unref(); 1715 return 0; 1716 } 1717 1718 static 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 1728 static int lsurface_width(lua_State* L) { 1729 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width()); 1730 return 1; 1731 } 1732 1733 static int lsurface_height(lua_State* L) { 1734 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height()); 1735 return 1; 1736 } 1737 1738 static 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 1753 static 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 1763 static 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 1776 static int lsurface_gc(lua_State* L) { 1777 get_ref<SkSurface>(L, 1)->unref(); 1778 return 0; 1779 } 1780 1781 static 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 1793 static 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 1811 static 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 1821 static 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 1831 static int lpicturerecorder_gc(lua_State* L) { 1832 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder(); 1833 return 0; 1834 } 1835 1836 static 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 1846 static int lpicture_width(lua_State* L) { 1847 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width()); 1848 return 1; 1849 } 1850 1851 static int lpicture_height(lua_State* L) { 1852 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height()); 1853 return 1; 1854 } 1855 1856 static int lpicture_gc(lua_State* L) { 1857 get_ref<SkPicture>(L, 1)->unref(); 1858 return 0; 1859 } 1860 1861 static 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 1870 static int ltextblob_bounds(lua_State* L) { 1871 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds()); 1872 return 1; 1873 } 1874 1875 static int ltextblob_gc(lua_State* L) { 1876 SkSafeUnref(get_ref<SkTextBlob>(L, 1)); 1877 return 0; 1878 } 1879 1880 static const struct luaL_Reg gSkTextBlob_Methods[] = { 1881 { "bounds", ltextblob_bounds }, 1882 { "__gc", ltextblob_gc }, 1883 { nullptr, nullptr } 1884 }; 1885 1886 /////////////////////////////////////////////////////////////////////////////// 1887 1888 static 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 1895 static int ltypeface_getStyle(lua_State* L) { 1896 lua_pushnumber(L, (double)get_ref<SkTypeface>(L, 1)->style()); 1897 return 1; 1898 } 1899 1900 static int ltypeface_gc(lua_State* L) { 1901 SkSafeUnref(get_ref<SkTypeface>(L, 1)); 1902 return 0; 1903 } 1904 1905 static 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 1914 class AutoCallLua { 1915 public: 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 1934 private: 1935 lua_State* fL; 1936 }; 1937 1938 #define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb) 1939 1940 /////////////////////////////////////////////////////////////////////////////// 1941 1942 static 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 1958 static 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 1970 static 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 1989 static int lsk_newMatrix(lua_State* L) { 1990 push_new<SkMatrix>(L)->reset(); 1991 return 1; 1992 } 1993 1994 static int lsk_newPaint(lua_State* L) { 1995 push_new<SkPaint>(L); 1996 return 1; 1997 } 1998 1999 static int lsk_newPath(lua_State* L) { 2000 push_new<SkPath>(L); 2001 return 1; 2002 } 2003 2004 static int lsk_newPictureRecorder(lua_State* L) { 2005 push_new<SkPictureRecorder>(L); 2006 return 1; 2007 } 2008 2009 static 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) 2016 static 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 2034 static 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 2056 static 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 2070 static 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 2085 static 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 2115 void 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 2136 extern "C" int luaopen_skia(lua_State* L); 2137 extern "C" int luaopen_skia(lua_State* L) { 2138 SkLua::Load(L); 2139 return 0; 2140 } 2141