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