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