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 "SkCanvas.h" 15 #include "SkData.h" 16 #include "SkDecodingImageGenerator.h" 17 #include "SkDocument.h" 18 #include "SkImage.h" 19 #include "SkMatrix.h" 20 #include "SkPaint.h" 21 #include "SkPath.h" 22 #include "SkPixelRef.h" 23 #include "SkRRect.h" 24 #include "SkString.h" 25 #include "SkTextBlob.h" 26 #include "SkTypeface.h" 27 28 extern "C" { 29 #include "lua.h" 30 #include "lualib.h" 31 #include "lauxlib.h" 32 } 33 34 // return the metatable name for a given class 35 template <typename T> const char* get_mtname(); 36 #define DEF_MTNAME(T) \ 37 template <> const char* get_mtname<T>() { \ 38 return #T "_LuaMetaTableName"; \ 39 } 40 41 DEF_MTNAME(SkCanvas) 42 DEF_MTNAME(SkDocument) 43 DEF_MTNAME(SkImage) 44 DEF_MTNAME(SkMatrix) 45 DEF_MTNAME(SkRRect) 46 DEF_MTNAME(SkPath) 47 DEF_MTNAME(SkPaint) 48 DEF_MTNAME(SkPathEffect) 49 DEF_MTNAME(SkShader) 50 DEF_MTNAME(SkTextBlob) 51 DEF_MTNAME(SkTypeface) 52 53 template <typename T> T* push_new(lua_State* L) { 54 T* addr = (T*)lua_newuserdata(L, sizeof(T)); 55 new (addr) T; 56 luaL_getmetatable(L, get_mtname<T>()); 57 lua_setmetatable(L, -2); 58 return addr; 59 } 60 61 template <typename T> void push_obj(lua_State* L, const T& obj) { 62 new (lua_newuserdata(L, sizeof(T))) T(obj); 63 luaL_getmetatable(L, get_mtname<T>()); 64 lua_setmetatable(L, -2); 65 } 66 67 template <typename T> void push_ref(lua_State* L, T* ref) { 68 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref); 69 luaL_getmetatable(L, get_mtname<T>()); 70 lua_setmetatable(L, -2); 71 } 72 73 template <typename T> T* get_ref(lua_State* L, int index) { 74 return *(T**)luaL_checkudata(L, index, get_mtname<T>()); 75 } 76 77 template <typename T> T* get_obj(lua_State* L, int index) { 78 return (T*)luaL_checkudata(L, index, get_mtname<T>()); 79 } 80 81 static bool lua2bool(lua_State* L, int index) { 82 return !!lua_toboolean(L, index); 83 } 84 85 /////////////////////////////////////////////////////////////////////////////// 86 87 SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) { 88 fL = luaL_newstate(); 89 luaL_openlibs(fL); 90 SkLua::Load(fL); 91 } 92 93 SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {} 94 95 SkLua::~SkLua() { 96 if (fWeOwnL) { 97 if (fTermCode.size() > 0) { 98 lua_getglobal(fL, fTermCode.c_str()); 99 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) { 100 SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); 101 } 102 } 103 lua_close(fL); 104 } 105 } 106 107 bool SkLua::runCode(const char code[]) { 108 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0); 109 if (err) { 110 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1)); 111 return false; 112 } 113 return true; 114 } 115 116 bool SkLua::runCode(const void* code, size_t size) { 117 SkString str((const char*)code, size); 118 return this->runCode(str.c_str()); 119 } 120 121 /////////////////////////////////////////////////////////////////////////////// 122 123 #define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0) 124 125 static void setfield_bool_if(lua_State* L, const char key[], bool pred) { 126 if (pred) { 127 lua_pushboolean(L, true); 128 lua_setfield(L, -2, key); 129 } 130 } 131 132 static void setfield_string(lua_State* L, const char key[], const char value[]) { 133 lua_pushstring(L, value); 134 lua_setfield(L, -2, key); 135 } 136 137 static void setfield_number(lua_State* L, const char key[], double value) { 138 lua_pushnumber(L, value); 139 lua_setfield(L, -2, key); 140 } 141 142 static void setfield_boolean(lua_State* L, const char key[], bool value) { 143 lua_pushboolean(L, value); 144 lua_setfield(L, -2, key); 145 } 146 147 static void setfield_scalar(lua_State* L, const char key[], SkScalar value) { 148 setfield_number(L, key, SkScalarToLua(value)); 149 } 150 151 static void setfield_function(lua_State* L, 152 const char key[], lua_CFunction value) { 153 lua_pushcfunction(L, value); 154 lua_setfield(L, -2, key); 155 } 156 157 static void setarray_number(lua_State* L, int index, double value) { 158 lua_pushnumber(L, value); 159 lua_rawseti(L, -2, index); 160 } 161 162 static void setarray_scalar(lua_State* L, int index, SkScalar value) { 163 setarray_number(L, index, SkScalarToLua(value)); 164 } 165 166 void SkLua::pushBool(bool value, const char key[]) { 167 lua_pushboolean(fL, value); 168 CHECK_SETFIELD(key); 169 } 170 171 void SkLua::pushString(const char str[], const char key[]) { 172 lua_pushstring(fL, str); 173 CHECK_SETFIELD(key); 174 } 175 176 void SkLua::pushString(const char str[], size_t length, const char key[]) { 177 // TODO: how to do this w/o making a copy? 178 SkString s(str, length); 179 lua_pushstring(fL, s.c_str()); 180 CHECK_SETFIELD(key); 181 } 182 183 void SkLua::pushString(const SkString& str, const char key[]) { 184 lua_pushstring(fL, str.c_str()); 185 CHECK_SETFIELD(key); 186 } 187 188 void SkLua::pushColor(SkColor color, const char key[]) { 189 lua_newtable(fL); 190 setfield_number(fL, "a", SkColorGetA(color) / 255.0); 191 setfield_number(fL, "r", SkColorGetR(color) / 255.0); 192 setfield_number(fL, "g", SkColorGetG(color) / 255.0); 193 setfield_number(fL, "b", SkColorGetB(color) / 255.0); 194 CHECK_SETFIELD(key); 195 } 196 197 void SkLua::pushU32(uint32_t value, const char key[]) { 198 lua_pushnumber(fL, (double)value); 199 CHECK_SETFIELD(key); 200 } 201 202 void SkLua::pushScalar(SkScalar value, const char key[]) { 203 lua_pushnumber(fL, SkScalarToLua(value)); 204 CHECK_SETFIELD(key); 205 } 206 207 void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) { 208 lua_newtable(fL); 209 for (int i = 0; i < count; ++i) { 210 // make it base-1 to match lua convention 211 setarray_number(fL, i + 1, (double)array[i]); 212 } 213 CHECK_SETFIELD(key); 214 } 215 216 void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) { 217 lua_newtable(fL); 218 for (int i = 0; i < count; ++i) { 219 // make it base-1 to match lua convention 220 lua_newtable(fL); 221 this->pushScalar(array[i].fX, "x"); 222 this->pushScalar(array[i].fY, "y"); 223 lua_rawseti(fL, -2, i + 1); 224 } 225 CHECK_SETFIELD(key); 226 } 227 228 void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) { 229 lua_newtable(fL); 230 for (int i = 0; i < count; ++i) { 231 // make it base-1 to match lua convention 232 setarray_scalar(fL, i + 1, array[i]); 233 } 234 CHECK_SETFIELD(key); 235 } 236 237 void SkLua::pushRect(const SkRect& r, const char key[]) { 238 lua_newtable(fL); 239 setfield_scalar(fL, "left", r.fLeft); 240 setfield_scalar(fL, "top", r.fTop); 241 setfield_scalar(fL, "right", r.fRight); 242 setfield_scalar(fL, "bottom", r.fBottom); 243 CHECK_SETFIELD(key); 244 } 245 246 void SkLua::pushRRect(const SkRRect& rr, const char key[]) { 247 push_obj(fL, rr); 248 CHECK_SETFIELD(key); 249 } 250 251 void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) { 252 lua_newtable(fL); 253 setfield_scalar(fL, "phase", info.fPhase); 254 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals"); 255 CHECK_SETFIELD(key); 256 } 257 258 259 void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) { 260 push_obj(fL, matrix); 261 CHECK_SETFIELD(key); 262 } 263 264 void SkLua::pushPaint(const SkPaint& paint, const char key[]) { 265 push_obj(fL, paint); 266 CHECK_SETFIELD(key); 267 } 268 269 void SkLua::pushPath(const SkPath& path, const char key[]) { 270 push_obj(fL, path); 271 CHECK_SETFIELD(key); 272 } 273 274 void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) { 275 push_ref(fL, canvas); 276 CHECK_SETFIELD(key); 277 } 278 279 void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) { 280 push_ref(fL, const_cast<SkTextBlob*>(blob)); 281 CHECK_SETFIELD(key); 282 } 283 284 static const char* element_type(SkClipStack::Element::Type type) { 285 switch (type) { 286 case SkClipStack::Element::kEmpty_Type: 287 return "empty"; 288 case SkClipStack::Element::kRect_Type: 289 return "rect"; 290 case SkClipStack::Element::kRRect_Type: 291 return "rrect"; 292 case SkClipStack::Element::kPath_Type: 293 return "path"; 294 } 295 return "unknown"; 296 } 297 298 static const char* region_op(SkRegion::Op op) { 299 switch (op) { 300 case SkRegion::kDifference_Op: 301 return "difference"; 302 case SkRegion::kIntersect_Op: 303 return "intersect"; 304 case SkRegion::kUnion_Op: 305 return "union"; 306 case SkRegion::kXOR_Op: 307 return "xor"; 308 case SkRegion::kReverseDifference_Op: 309 return "reverse-difference"; 310 case SkRegion::kReplace_Op: 311 return "replace"; 312 } 313 return "unknown"; 314 } 315 316 void SkLua::pushClipStack(const SkClipStack& stack, const char* key) { 317 lua_newtable(fL); 318 SkClipStack::B2TIter iter(stack); 319 const SkClipStack::Element* element; 320 int i = 0; 321 while ((element = iter.next())) { 322 this->pushClipStackElement(*element); 323 lua_rawseti(fL, -2, ++i); 324 } 325 CHECK_SETFIELD(key); 326 } 327 328 void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) { 329 lua_newtable(fL); 330 SkClipStack::Element::Type type = element.getType(); 331 this->pushString(element_type(type), "type"); 332 switch (type) { 333 case SkClipStack::Element::kEmpty_Type: 334 break; 335 case SkClipStack::Element::kRect_Type: 336 this->pushRect(element.getRect(), "rect"); 337 break; 338 case SkClipStack::Element::kRRect_Type: 339 this->pushRRect(element.getRRect(), "rrect"); 340 break; 341 case SkClipStack::Element::kPath_Type: 342 this->pushPath(element.getPath(), "path"); 343 break; 344 } 345 this->pushString(region_op(element.getOp()), "op"); 346 this->pushBool(element.isAA(), "aa"); 347 CHECK_SETFIELD(key); 348 } 349 350 351 /////////////////////////////////////////////////////////////////////////////// 352 /////////////////////////////////////////////////////////////////////////////// 353 354 static SkScalar lua2scalar(lua_State* L, int index) { 355 SkASSERT(lua_isnumber(L, index)); 356 return SkLuaToScalar(lua_tonumber(L, index)); 357 } 358 359 static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) { 360 if (lua_isnumber(L, index)) { 361 return SkLuaToScalar(lua_tonumber(L, index)); 362 } else { 363 return defaultValue; 364 } 365 } 366 367 static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) { 368 SkASSERT(lua_istable(L, index)); 369 lua_pushstring(L, key); 370 lua_gettable(L, index); 371 372 SkScalar value = lua2scalar(L, -1); 373 lua_pop(L, 1); 374 return value; 375 } 376 377 static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) { 378 SkASSERT(lua_istable(L, index)); 379 lua_pushstring(L, key); 380 lua_gettable(L, index); 381 382 SkScalar value; 383 if (lua_isnil(L, -1)) { 384 value = def; 385 } else { 386 value = lua2scalar(L, -1); 387 } 388 lua_pop(L, 1); 389 return value; 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(L, index, "a")), 404 unit2byte(getfield_scalar(L, index, "r")), 405 unit2byte(getfield_scalar(L, index, "g")), 406 unit2byte(getfield_scalar(L, index, "b"))); 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_drawColor(lua_State* L) { 418 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2)); 419 return 0; 420 } 421 422 static int lcanvas_drawRect(lua_State* L) { 423 SkRect rect; 424 get_ref<SkCanvas>(L, 1)->drawRect(*lua2rect(L, 2, &rect), 425 *get_obj<SkPaint>(L, 3)); 426 return 0; 427 } 428 429 static int lcanvas_drawOval(lua_State* L) { 430 SkRect rect; 431 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect), 432 *get_obj<SkPaint>(L, 3)); 433 return 0; 434 } 435 436 static int lcanvas_drawCircle(lua_State* L) { 437 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2), 438 lua2scalar(L, 3), 439 lua2scalar(L, 4), 440 *get_obj<SkPaint>(L, 5)); 441 return 0; 442 } 443 444 static int lcanvas_drawImage(lua_State* L) { 445 SkCanvas* canvas = get_ref<SkCanvas>(L, 1); 446 SkImage* image = get_ref<SkImage>(L, 2); 447 if (NULL == image) { 448 return 0; 449 } 450 SkScalar x = lua2scalar(L, 3); 451 SkScalar y = lua2scalar(L, 4); 452 453 SkPaint paint; 454 const SkPaint* paintPtr = NULL; 455 if (lua_isnumber(L, 5)) { 456 paint.setAlpha(SkScalarRoundToInt(lua2scalar(L, 5) * 255)); 457 paintPtr = &paint; 458 } 459 canvas->drawImage(image, x, y, paintPtr); 460 return 0; 461 } 462 463 static int lcanvas_drawPath(lua_State* L) { 464 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2), 465 *get_obj<SkPaint>(L, 3)); 466 return 0; 467 } 468 469 static int lcanvas_drawText(lua_State* L) { 470 if (lua_gettop(L) < 5) { 471 return 0; 472 } 473 474 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) { 475 size_t len; 476 const char* text = lua_tolstring(L, 2, &len); 477 get_ref<SkCanvas>(L, 1)->drawText(text, len, 478 lua2scalar(L, 3), lua2scalar(L, 4), 479 *get_obj<SkPaint>(L, 5)); 480 } 481 return 0; 482 } 483 484 static int lcanvas_getSaveCount(lua_State* L) { 485 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount()); 486 return 1; 487 } 488 489 static int lcanvas_getTotalMatrix(lua_State* L) { 490 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix()); 491 return 1; 492 } 493 494 static int lcanvas_getClipStack(lua_State* L) { 495 SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack()); 496 return 1; 497 } 498 499 int SkLua::lcanvas_getReducedClipStack(lua_State* L) { 500 #if SK_SUPPORT_GPU 501 const SkCanvas* canvas = get_ref<SkCanvas>(L, 1); 502 SkISize layerSize = canvas->getTopLayerSize(); 503 SkIPoint layerOrigin = canvas->getTopLayerOrigin(); 504 SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY, 505 layerSize.fWidth, layerSize.fHeight); 506 507 GrReducedClip::ElementList elements; 508 GrReducedClip::InitialState initialState; 509 int32_t genID; 510 SkIRect resultBounds; 511 512 const SkClipStack& stack = *canvas->getClipStack(); 513 514 GrReducedClip::ReduceClipStack(stack, 515 queryBounds, 516 &elements, 517 &genID, 518 &initialState, 519 &resultBounds, 520 NULL); 521 522 GrReducedClip::ElementList::Iter iter(elements); 523 int i = 0; 524 lua_newtable(L); 525 while(iter.get()) { 526 SkLua(L).pushClipStackElement(*iter.get()); 527 iter.next(); 528 lua_rawseti(L, -2, ++i); 529 } 530 // Currently this only returns the element list to lua, not the initial state or result bounds. 531 // It could return these as additional items on the lua stack. 532 return 1; 533 #else 534 return 0; 535 #endif 536 } 537 538 static int lcanvas_save(lua_State* L) { 539 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save()); 540 return 1; 541 } 542 543 static int lcanvas_restore(lua_State* L) { 544 get_ref<SkCanvas>(L, 1)->restore(); 545 return 0; 546 } 547 548 static int lcanvas_scale(lua_State* L) { 549 SkScalar sx = lua2scalar_def(L, 2, 1); 550 SkScalar sy = lua2scalar_def(L, 3, sx); 551 get_ref<SkCanvas>(L, 1)->scale(sx, sy); 552 return 0; 553 } 554 555 static int lcanvas_translate(lua_State* L) { 556 SkScalar tx = lua2scalar_def(L, 2, 0); 557 SkScalar ty = lua2scalar_def(L, 3, 0); 558 get_ref<SkCanvas>(L, 1)->translate(tx, ty); 559 return 0; 560 } 561 562 static int lcanvas_rotate(lua_State* L) { 563 SkScalar degrees = lua2scalar_def(L, 2, 0); 564 get_ref<SkCanvas>(L, 1)->rotate(degrees); 565 return 0; 566 } 567 568 static int lcanvas_gc(lua_State* L) { 569 get_ref<SkCanvas>(L, 1)->unref(); 570 return 0; 571 } 572 573 const struct luaL_Reg gSkCanvas_Methods[] = { 574 { "drawColor", lcanvas_drawColor }, 575 { "drawRect", lcanvas_drawRect }, 576 { "drawOval", lcanvas_drawOval }, 577 { "drawCircle", lcanvas_drawCircle }, 578 { "drawImage", lcanvas_drawImage }, 579 { "drawPath", lcanvas_drawPath }, 580 { "drawText", lcanvas_drawText }, 581 { "getSaveCount", lcanvas_getSaveCount }, 582 { "getTotalMatrix", lcanvas_getTotalMatrix }, 583 { "getClipStack", lcanvas_getClipStack }, 584 #if SK_SUPPORT_GPU 585 { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack }, 586 #endif 587 { "save", lcanvas_save }, 588 { "restore", lcanvas_restore }, 589 { "scale", lcanvas_scale }, 590 { "translate", lcanvas_translate }, 591 { "rotate", lcanvas_rotate }, 592 { "__gc", lcanvas_gc }, 593 { NULL, NULL } 594 }; 595 596 /////////////////////////////////////////////////////////////////////////////// 597 598 static int ldocument_beginPage(lua_State* L) { 599 const SkRect* contentPtr = NULL; 600 push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2), 601 lua2scalar(L, 3), 602 contentPtr)); 603 return 1; 604 } 605 606 static int ldocument_endPage(lua_State* L) { 607 get_ref<SkDocument>(L, 1)->endPage(); 608 return 0; 609 } 610 611 static int ldocument_close(lua_State* L) { 612 get_ref<SkDocument>(L, 1)->close(); 613 return 0; 614 } 615 616 static int ldocument_gc(lua_State* L) { 617 get_ref<SkDocument>(L, 1)->unref(); 618 return 0; 619 } 620 621 static const struct luaL_Reg gSkDocument_Methods[] = { 622 { "beginPage", ldocument_beginPage }, 623 { "endPage", ldocument_endPage }, 624 { "close", ldocument_close }, 625 { "__gc", ldocument_gc }, 626 { NULL, NULL } 627 }; 628 629 /////////////////////////////////////////////////////////////////////////////// 630 631 static int lpaint_isAntiAlias(lua_State* L) { 632 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias()); 633 return 1; 634 } 635 636 static int lpaint_setAntiAlias(lua_State* L) { 637 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2)); 638 return 0; 639 } 640 641 static int lpaint_isDither(lua_State* L) { 642 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither()); 643 return 1; 644 } 645 646 static int lpaint_isUnderlineText(lua_State* L) { 647 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText()); 648 return 1; 649 } 650 651 static int lpaint_isStrikeThruText(lua_State* L) { 652 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText()); 653 return 1; 654 } 655 656 static int lpaint_isFakeBoldText(lua_State* L) { 657 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText()); 658 return 1; 659 } 660 661 static int lpaint_isLinearText(lua_State* L) { 662 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText()); 663 return 1; 664 } 665 666 static int lpaint_isSubpixelText(lua_State* L) { 667 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText()); 668 return 1; 669 } 670 671 static int lpaint_isDevKernText(lua_State* L) { 672 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText()); 673 return 1; 674 } 675 676 static int lpaint_isLCDRenderText(lua_State* L) { 677 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText()); 678 return 1; 679 } 680 681 static int lpaint_isEmbeddedBitmapText(lua_State* L) { 682 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText()); 683 return 1; 684 } 685 686 static int lpaint_isAutohinted(lua_State* L) { 687 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted()); 688 return 1; 689 } 690 691 static int lpaint_isVerticalText(lua_State* L) { 692 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText()); 693 return 1; 694 } 695 696 static int lpaint_getColor(lua_State* L) { 697 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor()); 698 return 1; 699 } 700 701 static int lpaint_setColor(lua_State* L) { 702 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2)); 703 return 0; 704 } 705 706 static int lpaint_getTextSize(lua_State* L) { 707 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize()); 708 return 1; 709 } 710 711 static int lpaint_getTextScaleX(lua_State* L) { 712 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX()); 713 return 1; 714 } 715 716 static int lpaint_getTextSkewX(lua_State* L) { 717 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX()); 718 return 1; 719 } 720 721 static int lpaint_setTextSize(lua_State* L) { 722 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2)); 723 return 0; 724 } 725 726 static int lpaint_getTypeface(lua_State* L) { 727 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface()); 728 return 1; 729 } 730 731 static int lpaint_setTypeface(lua_State* L) { 732 get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2)); 733 return 0; 734 } 735 736 static int lpaint_getHinting(lua_State* L) { 737 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting()); 738 return 1; 739 } 740 741 static int lpaint_getFontID(lua_State* L) { 742 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface(); 743 SkLua(L).pushU32(SkTypeface::UniqueID(face)); 744 return 1; 745 } 746 747 static const struct { 748 const char* fLabel; 749 SkPaint::Align fAlign; 750 } gAlignRec[] = { 751 { "left", SkPaint::kLeft_Align }, 752 { "center", SkPaint::kCenter_Align }, 753 { "right", SkPaint::kRight_Align }, 754 }; 755 756 static int lpaint_getTextAlign(lua_State* L) { 757 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign(); 758 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { 759 if (gAlignRec[i].fAlign == align) { 760 lua_pushstring(L, gAlignRec[i].fLabel); 761 return 1; 762 } 763 } 764 return 0; 765 } 766 767 static int lpaint_setTextAlign(lua_State* L) { 768 if (lua_isstring(L, 2)) { 769 size_t len; 770 const char* label = lua_tolstring(L, 2, &len); 771 772 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { 773 if (!strcmp(gAlignRec[i].fLabel, label)) { 774 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign); 775 break; 776 } 777 } 778 } 779 return 0; 780 } 781 782 static int lpaint_getStroke(lua_State* L) { 783 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle()); 784 return 1; 785 } 786 787 static int lpaint_setStroke(lua_State* L) { 788 SkPaint::Style style; 789 790 if (lua_toboolean(L, 2)) { 791 style = SkPaint::kStroke_Style; 792 } else { 793 style = SkPaint::kFill_Style; 794 } 795 get_obj<SkPaint>(L, 1)->setStyle(style); 796 return 0; 797 } 798 799 static int lpaint_getStrokeCap(lua_State* L) { 800 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap()); 801 return 1; 802 } 803 804 static int lpaint_getStrokeJoin(lua_State* L) { 805 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin()); 806 return 1; 807 } 808 809 static int lpaint_getTextEncoding(lua_State* L) { 810 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding()); 811 return 1; 812 } 813 814 static int lpaint_getStrokeWidth(lua_State* L) { 815 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth()); 816 return 1; 817 } 818 819 static int lpaint_setStrokeWidth(lua_State* L) { 820 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2)); 821 return 0; 822 } 823 824 static int lpaint_getStrokeMiter(lua_State* L) { 825 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter()); 826 return 1; 827 } 828 829 static int lpaint_measureText(lua_State* L) { 830 if (lua_isstring(L, 2)) { 831 size_t len; 832 const char* text = lua_tolstring(L, 2, &len); 833 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len)); 834 return 1; 835 } 836 return 0; 837 } 838 839 struct FontMetrics { 840 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0) 841 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0) 842 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0) 843 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0) 844 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0) 845 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0) 846 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs 847 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs 848 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face 849 }; 850 851 static int lpaint_getFontMetrics(lua_State* L) { 852 SkPaint::FontMetrics fm; 853 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm); 854 855 lua_newtable(L); 856 setfield_scalar(L, "top", fm.fTop); 857 setfield_scalar(L, "ascent", fm.fAscent); 858 setfield_scalar(L, "descent", fm.fDescent); 859 setfield_scalar(L, "bottom", fm.fBottom); 860 setfield_scalar(L, "leading", fm.fLeading); 861 SkLua(L).pushScalar(height); 862 return 2; 863 } 864 865 static int lpaint_getEffects(lua_State* L) { 866 const SkPaint* paint = get_obj<SkPaint>(L, 1); 867 868 lua_newtable(L); 869 setfield_bool_if(L, "looper", !!paint->getLooper()); 870 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect()); 871 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer()); 872 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter()); 873 setfield_bool_if(L, "shader", !!paint->getShader()); 874 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter()); 875 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter()); 876 setfield_bool_if(L, "xfermode", !!paint->getXfermode()); 877 return 1; 878 } 879 880 static int lpaint_getShader(lua_State* L) { 881 const SkPaint* paint = get_obj<SkPaint>(L, 1); 882 SkShader* shader = paint->getShader(); 883 if (shader) { 884 push_ref(L, shader); 885 return 1; 886 } 887 return 0; 888 } 889 890 static int lpaint_getPathEffect(lua_State* L) { 891 const SkPaint* paint = get_obj<SkPaint>(L, 1); 892 SkPathEffect* pe = paint->getPathEffect(); 893 if (pe) { 894 push_ref(L, pe); 895 return 1; 896 } 897 return 0; 898 } 899 900 static int lpaint_gc(lua_State* L) { 901 get_obj<SkPaint>(L, 1)->~SkPaint(); 902 return 0; 903 } 904 905 static const struct luaL_Reg gSkPaint_Methods[] = { 906 { "isAntiAlias", lpaint_isAntiAlias }, 907 { "setAntiAlias", lpaint_setAntiAlias }, 908 { "isDither", lpaint_isDither }, 909 { "isUnderlineText", lpaint_isUnderlineText }, 910 { "isStrikeThruText", lpaint_isStrikeThruText }, 911 { "isFakeBoldText", lpaint_isFakeBoldText }, 912 { "isLinearText", lpaint_isLinearText }, 913 { "isSubpixelText", lpaint_isSubpixelText }, 914 { "isDevKernText", lpaint_isDevKernText }, 915 { "isLCDRenderText", lpaint_isLCDRenderText }, 916 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText }, 917 { "isAutohinted", lpaint_isAutohinted }, 918 { "isVerticalText", lpaint_isVerticalText }, 919 { "getColor", lpaint_getColor }, 920 { "setColor", lpaint_setColor }, 921 { "getTextSize", lpaint_getTextSize }, 922 { "setTextSize", lpaint_setTextSize }, 923 { "getTextScaleX", lpaint_getTextScaleX }, 924 { "getTextSkewX", lpaint_getTextSkewX }, 925 { "getTypeface", lpaint_getTypeface }, 926 { "setTypeface", lpaint_setTypeface }, 927 { "getHinting", lpaint_getHinting }, 928 { "getFontID", lpaint_getFontID }, 929 { "getTextAlign", lpaint_getTextAlign }, 930 { "setTextAlign", lpaint_setTextAlign }, 931 { "getStroke", lpaint_getStroke }, 932 { "setStroke", lpaint_setStroke }, 933 { "getStrokeCap", lpaint_getStrokeCap }, 934 { "getStrokeJoin", lpaint_getStrokeJoin }, 935 { "getTextEncoding", lpaint_getTextEncoding }, 936 { "getStrokeWidth", lpaint_getStrokeWidth }, 937 { "setStrokeWidth", lpaint_setStrokeWidth }, 938 { "getStrokeMiter", lpaint_getStrokeMiter }, 939 { "measureText", lpaint_measureText }, 940 { "getFontMetrics", lpaint_getFontMetrics }, 941 { "getEffects", lpaint_getEffects }, 942 { "getShader", lpaint_getShader }, 943 { "getPathEffect", lpaint_getPathEffect }, 944 { "__gc", lpaint_gc }, 945 { NULL, NULL } 946 }; 947 948 /////////////////////////////////////////////////////////////////////////////// 949 950 static const char* mode2string(SkShader::TileMode mode) { 951 static const char* gNames[] = { "clamp", "repeat", "mirror" }; 952 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames)); 953 return gNames[mode]; 954 } 955 956 static const char* gradtype2string(SkShader::GradientType t) { 957 static const char* gNames[] = { 958 "none", "color", "linear", "radial", "radial2", "sweep", "conical" 959 }; 960 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames)); 961 return gNames[t]; 962 } 963 964 static int lshader_isOpaque(lua_State* L) { 965 SkShader* shader = get_ref<SkShader>(L, 1); 966 return shader && shader->isOpaque(); 967 } 968 969 static int lshader_asABitmap(lua_State* L) { 970 SkShader* shader = get_ref<SkShader>(L, 1); 971 if (shader) { 972 SkBitmap bm; 973 SkMatrix matrix; 974 SkShader::TileMode modes[2]; 975 switch (shader->asABitmap(&bm, &matrix, modes)) { 976 case SkShader::kDefault_BitmapType: 977 lua_newtable(L); 978 setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0); 979 setfield_number(L, "width", bm.width()); 980 setfield_number(L, "height", bm.height()); 981 setfield_string(L, "tileX", mode2string(modes[0])); 982 setfield_string(L, "tileY", mode2string(modes[1])); 983 return 1; 984 default: 985 break; 986 } 987 } 988 return 0; 989 } 990 991 static int lshader_asAGradient(lua_State* L) { 992 SkShader* shader = get_ref<SkShader>(L, 1); 993 if (shader) { 994 SkShader::GradientInfo info; 995 sk_bzero(&info, sizeof(info)); 996 997 SkColor colors[3]; // hacked in for extracting info on 3 color case. 998 SkScalar pos[3]; 999 1000 info.fColorCount = 3; 1001 info.fColors = &colors[0]; 1002 info.fColorOffsets = &pos[0]; 1003 1004 SkShader::GradientType t = shader->asAGradient(&info); 1005 1006 if (SkShader::kNone_GradientType != t) { 1007 lua_newtable(L); 1008 setfield_string(L, "type", gradtype2string(t)); 1009 setfield_number(L, "colorCount", info.fColorCount); 1010 setfield_string(L, "tile", mode2string(info.fTileMode)); 1011 1012 if (info.fColorCount == 3){ 1013 setfield_number(L, "midPos", pos[1]); 1014 } 1015 1016 return 1; 1017 } 1018 } 1019 return 0; 1020 } 1021 1022 static int lshader_gc(lua_State* L) { 1023 get_ref<SkShader>(L, 1)->unref(); 1024 return 0; 1025 } 1026 1027 static const struct luaL_Reg gSkShader_Methods[] = { 1028 { "isOpaque", lshader_isOpaque }, 1029 { "asABitmap", lshader_asABitmap }, 1030 { "asAGradient", lshader_asAGradient }, 1031 { "__gc", lshader_gc }, 1032 { NULL, NULL } 1033 }; 1034 1035 /////////////////////////////////////////////////////////////////////////////// 1036 1037 static int lpatheffect_asADash(lua_State* L) { 1038 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1); 1039 if (pe) { 1040 SkPathEffect::DashInfo info; 1041 SkPathEffect::DashType dashType = pe->asADash(&info); 1042 if (SkPathEffect::kDash_DashType == dashType) { 1043 SkAutoTArray<SkScalar> intervals(info.fCount); 1044 info.fIntervals = intervals.get(); 1045 pe->asADash(&info); 1046 SkLua(L).pushDash(info); 1047 return 1; 1048 } 1049 } 1050 return 0; 1051 } 1052 1053 static int lpatheffect_gc(lua_State* L) { 1054 get_ref<SkPathEffect>(L, 1)->unref(); 1055 return 0; 1056 } 1057 1058 static const struct luaL_Reg gSkPathEffect_Methods[] = { 1059 { "asADash", lpatheffect_asADash }, 1060 { "__gc", lpatheffect_gc }, 1061 { NULL, NULL } 1062 }; 1063 1064 /////////////////////////////////////////////////////////////////////////////// 1065 1066 static int lmatrix_getType(lua_State* L) { 1067 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType(); 1068 1069 lua_newtable(L); 1070 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask)); 1071 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask)); 1072 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask)); 1073 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask)); 1074 return 1; 1075 } 1076 1077 static int lmatrix_getScaleX(lua_State* L) { 1078 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX()); 1079 return 1; 1080 } 1081 1082 static int lmatrix_getScaleY(lua_State* L) { 1083 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY()); 1084 return 1; 1085 } 1086 1087 static int lmatrix_getTranslateX(lua_State* L) { 1088 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX()); 1089 return 1; 1090 } 1091 1092 static int lmatrix_getTranslateY(lua_State* L) { 1093 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY()); 1094 return 1; 1095 } 1096 1097 static const struct luaL_Reg gSkMatrix_Methods[] = { 1098 { "getType", lmatrix_getType }, 1099 { "getScaleX", lmatrix_getScaleX }, 1100 { "getScaleY", lmatrix_getScaleY }, 1101 { "getTranslateX", lmatrix_getTranslateX }, 1102 { "getTranslateY", lmatrix_getTranslateY }, 1103 { NULL, NULL } 1104 }; 1105 1106 /////////////////////////////////////////////////////////////////////////////// 1107 1108 static int lpath_getBounds(lua_State* L) { 1109 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds()); 1110 return 1; 1111 } 1112 1113 static const char* fill_type_to_str(SkPath::FillType fill) { 1114 switch (fill) { 1115 case SkPath::kEvenOdd_FillType: 1116 return "even-odd"; 1117 case SkPath::kWinding_FillType: 1118 return "winding"; 1119 case SkPath::kInverseEvenOdd_FillType: 1120 return "inverse-even-odd"; 1121 case SkPath::kInverseWinding_FillType: 1122 return "inverse-winding"; 1123 } 1124 return "unknown"; 1125 } 1126 1127 static int lpath_getFillType(lua_State* L) { 1128 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType(); 1129 SkLua(L).pushString(fill_type_to_str(fill)); 1130 return 1; 1131 } 1132 1133 static SkString segment_masks_to_str(uint32_t segmentMasks) { 1134 SkString result; 1135 bool first = true; 1136 if (SkPath::kLine_SegmentMask & segmentMasks) { 1137 result.append("line"); 1138 first = false; 1139 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;) 1140 } 1141 if (SkPath::kQuad_SegmentMask & segmentMasks) { 1142 if (!first) { 1143 result.append(" "); 1144 } 1145 result.append("quad"); 1146 first = false; 1147 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;) 1148 } 1149 if (SkPath::kConic_SegmentMask & segmentMasks) { 1150 if (!first) { 1151 result.append(" "); 1152 } 1153 result.append("conic"); 1154 first = false; 1155 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;) 1156 } 1157 if (SkPath::kCubic_SegmentMask & segmentMasks) { 1158 if (!first) { 1159 result.append(" "); 1160 } 1161 result.append("cubic"); 1162 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;) 1163 } 1164 SkASSERT(0 == segmentMasks); 1165 return result; 1166 } 1167 1168 static int lpath_getSegmentTypes(lua_State* L) { 1169 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks(); 1170 SkLua(L).pushString(segment_masks_to_str(segMasks)); 1171 return 1; 1172 } 1173 1174 static int lpath_isConvex(lua_State* L) { 1175 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity(); 1176 SkLua(L).pushBool(isConvex); 1177 return 1; 1178 } 1179 1180 static int lpath_isEmpty(lua_State* L) { 1181 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty()); 1182 return 1; 1183 } 1184 1185 static int lpath_isRect(lua_State* L) { 1186 SkRect r; 1187 bool pred = get_obj<SkPath>(L, 1)->isRect(&r); 1188 int ret_count = 1; 1189 lua_pushboolean(L, pred); 1190 if (pred) { 1191 SkLua(L).pushRect(r); 1192 ret_count += 1; 1193 } 1194 return ret_count; 1195 } 1196 1197 static const char* dir2string(SkPath::Direction dir) { 1198 static const char* gStr[] = { 1199 "unknown", "cw", "ccw" 1200 }; 1201 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr)); 1202 return gStr[dir]; 1203 } 1204 1205 static int lpath_isNestedRects(lua_State* L) { 1206 SkRect rects[2]; 1207 SkPath::Direction dirs[2]; 1208 bool pred = get_obj<SkPath>(L, 1)->isNestedRects(rects, dirs); 1209 int ret_count = 1; 1210 lua_pushboolean(L, pred); 1211 if (pred) { 1212 SkLua lua(L); 1213 lua.pushRect(rects[0]); 1214 lua.pushRect(rects[1]); 1215 lua_pushstring(L, dir2string(dirs[0])); 1216 lua_pushstring(L, dir2string(dirs[0])); 1217 ret_count += 4; 1218 } 1219 return ret_count; 1220 } 1221 1222 static int lpath_countPoints(lua_State* L) { 1223 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints()); 1224 return 1; 1225 } 1226 1227 static int lpath_reset(lua_State* L) { 1228 get_obj<SkPath>(L, 1)->reset(); 1229 return 0; 1230 } 1231 1232 static int lpath_moveTo(lua_State* L) { 1233 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3)); 1234 return 0; 1235 } 1236 1237 static int lpath_lineTo(lua_State* L) { 1238 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3)); 1239 return 0; 1240 } 1241 1242 static int lpath_quadTo(lua_State* L) { 1243 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3), 1244 lua2scalar(L, 4), lua2scalar(L, 5)); 1245 return 0; 1246 } 1247 1248 static int lpath_cubicTo(lua_State* L) { 1249 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3), 1250 lua2scalar(L, 4), lua2scalar(L, 5), 1251 lua2scalar(L, 6), lua2scalar(L, 7)); 1252 return 0; 1253 } 1254 1255 static int lpath_close(lua_State* L) { 1256 get_obj<SkPath>(L, 1)->close(); 1257 return 0; 1258 } 1259 1260 static int lpath_gc(lua_State* L) { 1261 get_obj<SkPath>(L, 1)->~SkPath(); 1262 return 0; 1263 } 1264 1265 static const struct luaL_Reg gSkPath_Methods[] = { 1266 { "getBounds", lpath_getBounds }, 1267 { "getFillType", lpath_getFillType }, 1268 { "getSegmentTypes", lpath_getSegmentTypes }, 1269 { "isConvex", lpath_isConvex }, 1270 { "isEmpty", lpath_isEmpty }, 1271 { "isRect", lpath_isRect }, 1272 { "isNestedRects", lpath_isNestedRects }, 1273 { "countPoints", lpath_countPoints }, 1274 { "reset", lpath_reset }, 1275 { "moveTo", lpath_moveTo }, 1276 { "lineTo", lpath_lineTo }, 1277 { "quadTo", lpath_quadTo }, 1278 { "cubicTo", lpath_cubicTo }, 1279 { "close", lpath_close }, 1280 { "__gc", lpath_gc }, 1281 { NULL, NULL } 1282 }; 1283 1284 /////////////////////////////////////////////////////////////////////////////// 1285 1286 static const char* rrect_type(const SkRRect& rr) { 1287 switch (rr.getType()) { 1288 case SkRRect::kUnknown_Type: return "unknown"; 1289 case SkRRect::kEmpty_Type: return "empty"; 1290 case SkRRect::kRect_Type: return "rect"; 1291 case SkRRect::kOval_Type: return "oval"; 1292 case SkRRect::kSimple_Type: return "simple"; 1293 case SkRRect::kNinePatch_Type: return "nine-patch"; 1294 case SkRRect::kComplex_Type: return "complex"; 1295 } 1296 SkDEBUGFAIL("never get here"); 1297 return ""; 1298 } 1299 1300 static int lrrect_rect(lua_State* L) { 1301 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect()); 1302 return 1; 1303 } 1304 1305 static int lrrect_type(lua_State* L) { 1306 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1))); 1307 return 1; 1308 } 1309 1310 static int lrrect_radii(lua_State* L) { 1311 int corner = SkToInt(lua_tointeger(L, 2)); 1312 SkVector v; 1313 if (corner < 0 || corner > 3) { 1314 SkDebugf("bad corner index %d", corner); 1315 v.set(0, 0); 1316 } else { 1317 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner); 1318 } 1319 lua_pushnumber(L, v.fX); 1320 lua_pushnumber(L, v.fY); 1321 return 2; 1322 } 1323 1324 static int lrrect_gc(lua_State* L) { 1325 get_obj<SkRRect>(L, 1)->~SkRRect(); 1326 return 0; 1327 } 1328 1329 static const struct luaL_Reg gSkRRect_Methods[] = { 1330 { "rect", lrrect_rect }, 1331 { "type", lrrect_type }, 1332 { "radii", lrrect_radii }, 1333 { "__gc", lrrect_gc }, 1334 { NULL, NULL } 1335 }; 1336 1337 /////////////////////////////////////////////////////////////////////////////// 1338 1339 static int limage_width(lua_State* L) { 1340 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width()); 1341 return 1; 1342 } 1343 1344 static int limage_height(lua_State* L) { 1345 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height()); 1346 return 1; 1347 } 1348 1349 static int limage_gc(lua_State* L) { 1350 get_ref<SkImage>(L, 1)->unref(); 1351 return 0; 1352 } 1353 1354 static const struct luaL_Reg gSkImage_Methods[] = { 1355 { "width", limage_width }, 1356 { "height", limage_height }, 1357 { "__gc", limage_gc }, 1358 { NULL, NULL } 1359 }; 1360 1361 /////////////////////////////////////////////////////////////////////////////// 1362 1363 static int ltypeface_gc(lua_State* L) { 1364 SkSafeUnref(get_ref<SkTypeface>(L, 1)); 1365 return 0; 1366 } 1367 1368 static const struct luaL_Reg gSkTypeface_Methods[] = { 1369 { "__gc", ltypeface_gc }, 1370 { NULL, NULL } 1371 }; 1372 1373 /////////////////////////////////////////////////////////////////////////////// 1374 1375 class AutoCallLua { 1376 public: 1377 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) { 1378 lua_getglobal(L, func); 1379 if (!lua_isfunction(L, -1)) { 1380 int t = lua_type(L, -1); 1381 SkDebugf("--- expected function %d\n", t); 1382 } 1383 1384 lua_newtable(L); 1385 setfield_string(L, "verb", verb); 1386 } 1387 1388 ~AutoCallLua() { 1389 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) { 1390 SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); 1391 } 1392 lua_settop(fL, -1); 1393 } 1394 1395 private: 1396 lua_State* fL; 1397 }; 1398 1399 #define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb) 1400 1401 /////////////////////////////////////////////////////////////////////////////// 1402 1403 static int lsk_newDocumentPDF(lua_State* L) { 1404 const char* file = NULL; 1405 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { 1406 file = lua_tolstring(L, 1, NULL); 1407 } 1408 1409 SkDocument* doc = SkDocument::CreatePDF(file); 1410 if (NULL == doc) { 1411 // do I need to push a nil on the stack and return 1? 1412 return 0; 1413 } else { 1414 push_ref(L, doc); 1415 doc->unref(); 1416 return 1; 1417 } 1418 } 1419 1420 static int lsk_newPaint(lua_State* L) { 1421 push_new<SkPaint>(L); 1422 return 1; 1423 } 1424 1425 static int lsk_newPath(lua_State* L) { 1426 push_new<SkPath>(L); 1427 return 1; 1428 } 1429 1430 static int lsk_newRRect(lua_State* L) { 1431 SkRRect* rr = push_new<SkRRect>(L); 1432 rr->setEmpty(); 1433 return 1; 1434 } 1435 1436 static int lsk_newTypeface(lua_State* L) { 1437 const char* name = NULL; 1438 int style = SkTypeface::kNormal; 1439 1440 int count = lua_gettop(L); 1441 if (count > 0 && lua_isstring(L, 1)) { 1442 name = lua_tolstring(L, 1, NULL); 1443 if (count > 1 && lua_isnumber(L, 2)) { 1444 style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic; 1445 } 1446 } 1447 1448 SkTypeface* face = SkTypeface::CreateFromName(name, 1449 (SkTypeface::Style)style); 1450 // SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt()); 1451 if (NULL == face) { 1452 face = SkTypeface::RefDefault(); 1453 } 1454 push_ref(L, face); 1455 face->unref(); 1456 return 1; 1457 } 1458 1459 static int lsk_loadImage(lua_State* L) { 1460 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { 1461 const char* name = lua_tolstring(L, 1, NULL); 1462 SkAutoDataUnref data(SkData::NewFromFileName(name)); 1463 if (data.get()) { 1464 SkImage* image = SkImage::NewFromGenerator( 1465 SkDecodingImageGenerator::Create(data, SkDecodingImageGenerator::Options())); 1466 1467 if (image) { 1468 push_ref(L, image); 1469 image->unref(); 1470 return 1; 1471 } 1472 } 1473 } 1474 return 0; 1475 } 1476 1477 static void register_Sk(lua_State* L) { 1478 lua_newtable(L); 1479 lua_pushvalue(L, -1); 1480 lua_setglobal(L, "Sk"); 1481 // the Sk table is still on top 1482 1483 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF); 1484 setfield_function(L, "loadImage", lsk_loadImage); 1485 setfield_function(L, "newPaint", lsk_newPaint); 1486 setfield_function(L, "newPath", lsk_newPath); 1487 setfield_function(L, "newRRect", lsk_newRRect); 1488 setfield_function(L, "newTypeface", lsk_newTypeface); 1489 lua_pop(L, 1); // pop off the Sk table 1490 } 1491 1492 #define REG_CLASS(L, C) \ 1493 do { \ 1494 luaL_newmetatable(L, get_mtname<C>()); \ 1495 lua_pushvalue(L, -1); \ 1496 lua_setfield(L, -2, "__index"); \ 1497 luaL_setfuncs(L, g##C##_Methods, 0); \ 1498 lua_pop(L, 1); /* pop off the meta-table */ \ 1499 } while (0) 1500 1501 void SkLua::Load(lua_State* L) { 1502 register_Sk(L); 1503 REG_CLASS(L, SkCanvas); 1504 REG_CLASS(L, SkDocument); 1505 REG_CLASS(L, SkImage); 1506 REG_CLASS(L, SkPaint); 1507 REG_CLASS(L, SkPath); 1508 REG_CLASS(L, SkPathEffect); 1509 REG_CLASS(L, SkRRect); 1510 REG_CLASS(L, SkShader); 1511 REG_CLASS(L, SkTypeface); 1512 REG_CLASS(L, SkMatrix); 1513 } 1514 1515 extern "C" int luaopen_skia(lua_State* L); 1516 extern "C" int luaopen_skia(lua_State* L) { 1517 SkLua::Load(L); 1518 return 0; 1519 } 1520