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