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 #include "SkCanvas.h" 10 #include "SkData.h" 11 #include "SkDocument.h" 12 #include "SkImage.h" 13 #include "SkMatrix.h" 14 #include "SkPaint.h" 15 #include "SkPath.h" 16 #include "SkPixelRef.h" 17 #include "SkRRect.h" 18 #include "SkString.h" 19 #include "SkTypeface.h" 20 21 extern "C" { 22 #include "lua.h" 23 #include "lualib.h" 24 #include "lauxlib.h" 25 } 26 27 // return the metatable name for a given class 28 template <typename T> const char* get_mtname(); 29 #define DEF_MTNAME(T) \ 30 template <> const char* get_mtname<T>() { \ 31 return #T "_LuaMetaTableName"; \ 32 } 33 34 DEF_MTNAME(SkCanvas) 35 DEF_MTNAME(SkDocument) 36 DEF_MTNAME(SkImage) 37 DEF_MTNAME(SkMatrix) 38 DEF_MTNAME(SkRRect) 39 DEF_MTNAME(SkPath) 40 DEF_MTNAME(SkPaint) 41 DEF_MTNAME(SkShader) 42 DEF_MTNAME(SkTypeface) 43 44 template <typename T> T* push_new(lua_State* L) { 45 T* addr = (T*)lua_newuserdata(L, sizeof(T)); 46 new (addr) T; 47 luaL_getmetatable(L, get_mtname<T>()); 48 lua_setmetatable(L, -2); 49 return addr; 50 } 51 52 template <typename T> void push_obj(lua_State* L, const T& obj) { 53 new (lua_newuserdata(L, sizeof(T))) T(obj); 54 luaL_getmetatable(L, get_mtname<T>()); 55 lua_setmetatable(L, -2); 56 } 57 58 template <typename T> void push_ref(lua_State* L, T* ref) { 59 *(T**)lua_newuserdata(L, sizeof(T*)) = SkRef(ref); 60 luaL_getmetatable(L, get_mtname<T>()); 61 lua_setmetatable(L, -2); 62 } 63 64 template <typename T> T* get_ref(lua_State* L, int index) { 65 return *(T**)luaL_checkudata(L, index, get_mtname<T>()); 66 } 67 68 template <typename T> T* get_obj(lua_State* L, int index) { 69 return (T*)luaL_checkudata(L, index, get_mtname<T>()); 70 } 71 72 static bool lua2bool(lua_State* L, int index) { 73 return !!lua_toboolean(L, index); 74 } 75 76 /////////////////////////////////////////////////////////////////////////////// 77 78 SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) { 79 fL = luaL_newstate(); 80 luaL_openlibs(fL); 81 SkLua::Load(fL); 82 } 83 84 SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {} 85 86 SkLua::~SkLua() { 87 if (fWeOwnL) { 88 if (fTermCode.size() > 0) { 89 lua_getglobal(fL, fTermCode.c_str()); 90 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) { 91 SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); 92 } 93 } 94 lua_close(fL); 95 } 96 } 97 98 bool SkLua::runCode(const char code[]) { 99 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0); 100 if (err) { 101 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1)); 102 return false; 103 } 104 return true; 105 } 106 107 bool SkLua::runCode(const void* code, size_t size) { 108 SkString str((const char*)code, size); 109 return this->runCode(str.c_str()); 110 } 111 112 /////////////////////////////////////////////////////////////////////////////// 113 114 #define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0) 115 116 static void setfield_bool_if(lua_State* L, const char key[], bool pred) { 117 if (pred) { 118 lua_pushboolean(L, true); 119 lua_setfield(L, -2, key); 120 } 121 } 122 123 static void setfield_string(lua_State* L, const char key[], const char value[]) { 124 lua_pushstring(L, value); 125 lua_setfield(L, -2, key); 126 } 127 128 static void setfield_number(lua_State* L, const char key[], double value) { 129 lua_pushnumber(L, value); 130 lua_setfield(L, -2, key); 131 } 132 133 static void setfield_boolean(lua_State* L, const char key[], bool value) { 134 lua_pushboolean(L, value); 135 lua_setfield(L, -2, key); 136 } 137 138 static void setfield_scalar(lua_State* L, const char key[], SkScalar value) { 139 setfield_number(L, key, SkScalarToLua(value)); 140 } 141 142 static void setfield_function(lua_State* L, 143 const char key[], lua_CFunction value) { 144 lua_pushcfunction(L, value); 145 lua_setfield(L, -2, key); 146 } 147 148 static void setarray_number(lua_State* L, int index, double value) { 149 lua_pushnumber(L, value); 150 lua_rawseti(L, -2, index); 151 } 152 153 void SkLua::pushBool(bool value, const char key[]) { 154 lua_pushboolean(fL, value); 155 CHECK_SETFIELD(key); 156 } 157 158 void SkLua::pushString(const char str[], const char key[]) { 159 lua_pushstring(fL, str); 160 CHECK_SETFIELD(key); 161 } 162 163 void SkLua::pushString(const char str[], size_t length, const char key[]) { 164 // TODO: how to do this w/o making a copy? 165 SkString s(str, length); 166 lua_pushstring(fL, s.c_str()); 167 CHECK_SETFIELD(key); 168 } 169 170 void SkLua::pushString(const SkString& str, const char key[]) { 171 lua_pushstring(fL, str.c_str()); 172 CHECK_SETFIELD(key); 173 } 174 175 void SkLua::pushColor(SkColor color, const char key[]) { 176 lua_newtable(fL); 177 setfield_number(fL, "a", SkColorGetA(color) / 255.0); 178 setfield_number(fL, "r", SkColorGetR(color) / 255.0); 179 setfield_number(fL, "g", SkColorGetG(color) / 255.0); 180 setfield_number(fL, "b", SkColorGetB(color) / 255.0); 181 CHECK_SETFIELD(key); 182 } 183 184 void SkLua::pushU32(uint32_t value, const char key[]) { 185 lua_pushnumber(fL, (double)value); 186 CHECK_SETFIELD(key); 187 } 188 189 void SkLua::pushScalar(SkScalar value, const char key[]) { 190 lua_pushnumber(fL, SkScalarToLua(value)); 191 CHECK_SETFIELD(key); 192 } 193 194 void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) { 195 lua_newtable(fL); 196 for (int i = 0; i < count; ++i) { 197 // make it base-1 to match lua convention 198 setarray_number(fL, i + 1, (double)array[i]); 199 } 200 CHECK_SETFIELD(key); 201 } 202 203 void SkLua::pushRect(const SkRect& r, const char key[]) { 204 lua_newtable(fL); 205 setfield_scalar(fL, "left", r.fLeft); 206 setfield_scalar(fL, "top", r.fTop); 207 setfield_scalar(fL, "right", r.fRight); 208 setfield_scalar(fL, "bottom", r.fBottom); 209 CHECK_SETFIELD(key); 210 } 211 212 void SkLua::pushRRect(const SkRRect& rr, const char key[]) { 213 push_obj(fL, rr); 214 CHECK_SETFIELD(key); 215 } 216 217 void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) { 218 push_obj(fL, matrix); 219 CHECK_SETFIELD(key); 220 } 221 222 void SkLua::pushPaint(const SkPaint& paint, const char key[]) { 223 push_obj(fL, paint); 224 CHECK_SETFIELD(key); 225 } 226 227 void SkLua::pushPath(const SkPath& path, const char key[]) { 228 push_obj(fL, path); 229 CHECK_SETFIELD(key); 230 } 231 232 void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) { 233 push_ref(fL, canvas); 234 CHECK_SETFIELD(key); 235 } 236 237 /////////////////////////////////////////////////////////////////////////////// 238 /////////////////////////////////////////////////////////////////////////////// 239 240 static SkScalar lua2scalar(lua_State* L, int index) { 241 SkASSERT(lua_isnumber(L, index)); 242 return SkLuaToScalar(lua_tonumber(L, index)); 243 } 244 245 static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) { 246 if (lua_isnumber(L, index)) { 247 return SkLuaToScalar(lua_tonumber(L, index)); 248 } else { 249 return defaultValue; 250 } 251 } 252 253 static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) { 254 SkASSERT(lua_istable(L, index)); 255 lua_pushstring(L, key); 256 lua_gettable(L, index); 257 258 SkScalar value = lua2scalar(L, -1); 259 lua_pop(L, 1); 260 return value; 261 } 262 263 static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) { 264 SkASSERT(lua_istable(L, index)); 265 lua_pushstring(L, key); 266 lua_gettable(L, index); 267 268 SkScalar value; 269 if (lua_isnil(L, -1)) { 270 value = def; 271 } else { 272 value = lua2scalar(L, -1); 273 } 274 lua_pop(L, 1); 275 return value; 276 } 277 278 static U8CPU unit2byte(SkScalar x) { 279 if (x <= 0) { 280 return 0; 281 } else if (x >= 1) { 282 return 255; 283 } else { 284 return SkScalarRoundToInt(x * 255); 285 } 286 } 287 288 static SkColor lua2color(lua_State* L, int index) { 289 return SkColorSetARGB(unit2byte(getfield_scalar(L, index, "a")), 290 unit2byte(getfield_scalar(L, index, "r")), 291 unit2byte(getfield_scalar(L, index, "g")), 292 unit2byte(getfield_scalar(L, index, "b"))); 293 } 294 295 static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) { 296 rect->set(getfield_scalar_default(L, index, "left", 0), 297 getfield_scalar_default(L, index, "top", 0), 298 getfield_scalar(L, index, "right"), 299 getfield_scalar(L, index, "bottom")); 300 return rect; 301 } 302 303 static int lcanvas_drawColor(lua_State* L) { 304 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2)); 305 return 0; 306 } 307 308 static int lcanvas_drawRect(lua_State* L) { 309 SkRect rect; 310 get_ref<SkCanvas>(L, 1)->drawRect(*lua2rect(L, 2, &rect), 311 *get_obj<SkPaint>(L, 3)); 312 return 0; 313 } 314 315 static int lcanvas_drawOval(lua_State* L) { 316 SkRect rect; 317 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect), 318 *get_obj<SkPaint>(L, 3)); 319 return 0; 320 } 321 322 static int lcanvas_drawCircle(lua_State* L) { 323 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2), 324 lua2scalar(L, 3), 325 lua2scalar(L, 4), 326 *get_obj<SkPaint>(L, 5)); 327 return 0; 328 } 329 330 static int lcanvas_drawImage(lua_State* L) { 331 SkCanvas* canvas = get_ref<SkCanvas>(L, 1); 332 SkImage* image = get_ref<SkImage>(L, 2); 333 if (NULL == image) { 334 return 0; 335 } 336 SkScalar x = lua2scalar(L, 3); 337 SkScalar y = lua2scalar(L, 4); 338 339 SkPaint paint; 340 const SkPaint* paintPtr = NULL; 341 if (lua_isnumber(L, 5)) { 342 paint.setAlpha(SkScalarRoundToInt(lua2scalar(L, 5) * 255)); 343 paintPtr = &paint; 344 } 345 image->draw(canvas, x, y, paintPtr); 346 return 0; 347 } 348 349 static int lcanvas_drawPath(lua_State* L) { 350 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2), 351 *get_obj<SkPaint>(L, 3)); 352 return 0; 353 } 354 355 static int lcanvas_drawText(lua_State* L) { 356 if (lua_gettop(L) < 5) { 357 return 0; 358 } 359 360 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) { 361 size_t len; 362 const char* text = lua_tolstring(L, 2, &len); 363 get_ref<SkCanvas>(L, 1)->drawText(text, len, 364 lua2scalar(L, 3), lua2scalar(L, 4), 365 *get_obj<SkPaint>(L, 5)); 366 } 367 return 0; 368 } 369 370 static int lcanvas_getSaveCount(lua_State* L) { 371 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount()); 372 return 1; 373 } 374 375 static int lcanvas_getTotalMatrix(lua_State* L) { 376 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix()); 377 return 1; 378 } 379 380 static int lcanvas_save(lua_State* L) { 381 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save()); 382 return 1; 383 } 384 385 static int lcanvas_restore(lua_State* L) { 386 get_ref<SkCanvas>(L, 1)->restore(); 387 return 0; 388 } 389 390 static int lcanvas_scale(lua_State* L) { 391 SkScalar sx = lua2scalar_def(L, 2, 1); 392 SkScalar sy = lua2scalar_def(L, 3, sx); 393 get_ref<SkCanvas>(L, 1)->scale(sx, sy); 394 return 0; 395 } 396 397 static int lcanvas_translate(lua_State* L) { 398 SkScalar tx = lua2scalar_def(L, 2, 0); 399 SkScalar ty = lua2scalar_def(L, 3, 0); 400 get_ref<SkCanvas>(L, 1)->translate(tx, ty); 401 return 0; 402 } 403 404 static int lcanvas_rotate(lua_State* L) { 405 SkScalar degrees = lua2scalar_def(L, 2, 0); 406 get_ref<SkCanvas>(L, 1)->rotate(degrees); 407 return 0; 408 } 409 410 static int lcanvas_gc(lua_State* L) { 411 get_ref<SkCanvas>(L, 1)->unref(); 412 return 0; 413 } 414 415 static const struct luaL_Reg gSkCanvas_Methods[] = { 416 { "drawColor", lcanvas_drawColor }, 417 { "drawRect", lcanvas_drawRect }, 418 { "drawOval", lcanvas_drawOval }, 419 { "drawCircle", lcanvas_drawCircle }, 420 { "drawImage", lcanvas_drawImage }, 421 { "drawPath", lcanvas_drawPath }, 422 { "drawText", lcanvas_drawText }, 423 { "getSaveCount", lcanvas_getSaveCount }, 424 { "getTotalMatrix", lcanvas_getTotalMatrix }, 425 { "save", lcanvas_save }, 426 { "restore", lcanvas_restore }, 427 { "scale", lcanvas_scale }, 428 { "translate", lcanvas_translate }, 429 { "rotate", lcanvas_rotate }, 430 { "__gc", lcanvas_gc }, 431 { NULL, NULL } 432 }; 433 434 /////////////////////////////////////////////////////////////////////////////// 435 436 static int ldocument_beginPage(lua_State* L) { 437 const SkRect* contentPtr = NULL; 438 push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2), 439 lua2scalar(L, 3), 440 contentPtr)); 441 return 1; 442 } 443 444 static int ldocument_endPage(lua_State* L) { 445 get_ref<SkDocument>(L, 1)->endPage(); 446 return 0; 447 } 448 449 static int ldocument_close(lua_State* L) { 450 get_ref<SkDocument>(L, 1)->close(); 451 return 0; 452 } 453 454 static int ldocument_gc(lua_State* L) { 455 get_ref<SkDocument>(L, 1)->unref(); 456 return 0; 457 } 458 459 static const struct luaL_Reg gSkDocument_Methods[] = { 460 { "beginPage", ldocument_beginPage }, 461 { "endPage", ldocument_endPage }, 462 { "close", ldocument_close }, 463 { "__gc", ldocument_gc }, 464 { NULL, NULL } 465 }; 466 467 /////////////////////////////////////////////////////////////////////////////// 468 469 static int lpaint_isAntiAlias(lua_State* L) { 470 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias()); 471 return 1; 472 } 473 474 static int lpaint_setAntiAlias(lua_State* L) { 475 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2)); 476 return 0; 477 } 478 479 static int lpaint_getColor(lua_State* L) { 480 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor()); 481 return 1; 482 } 483 484 static int lpaint_setColor(lua_State* L) { 485 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2)); 486 return 0; 487 } 488 489 static int lpaint_getTextSize(lua_State* L) { 490 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize()); 491 return 1; 492 } 493 494 static int lpaint_setTextSize(lua_State* L) { 495 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2)); 496 return 0; 497 } 498 499 static int lpaint_getTypeface(lua_State* L) { 500 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface()); 501 return 1; 502 } 503 504 static int lpaint_setTypeface(lua_State* L) { 505 get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2)); 506 return 0; 507 } 508 509 static int lpaint_getFontID(lua_State* L) { 510 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface(); 511 SkLua(L).pushU32(SkTypeface::UniqueID(face)); 512 return 1; 513 } 514 515 static const struct { 516 const char* fLabel; 517 SkPaint::Align fAlign; 518 } gAlignRec[] = { 519 { "left", SkPaint::kLeft_Align }, 520 { "center", SkPaint::kCenter_Align }, 521 { "right", SkPaint::kRight_Align }, 522 }; 523 524 static int lpaint_getTextAlign(lua_State* L) { 525 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign(); 526 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { 527 if (gAlignRec[i].fAlign == align) { 528 lua_pushstring(L, gAlignRec[i].fLabel); 529 return 1; 530 } 531 } 532 return 0; 533 } 534 535 static int lpaint_setTextAlign(lua_State* L) { 536 if (lua_isstring(L, 2)) { 537 size_t len; 538 const char* label = lua_tolstring(L, 2, &len); 539 540 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { 541 if (!strcmp(gAlignRec[i].fLabel, label)) { 542 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign); 543 break; 544 } 545 } 546 } 547 return 0; 548 } 549 550 static int lpaint_getStroke(lua_State* L) { 551 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle()); 552 return 1; 553 } 554 555 static int lpaint_setStroke(lua_State* L) { 556 SkPaint::Style style; 557 558 if (lua_toboolean(L, 2)) { 559 style = SkPaint::kStroke_Style; 560 } else { 561 style = SkPaint::kFill_Style; 562 } 563 get_obj<SkPaint>(L, 1)->setStyle(style); 564 return 0; 565 } 566 567 static int lpaint_getStrokeWidth(lua_State* L) { 568 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth()); 569 return 1; 570 } 571 572 static int lpaint_setStrokeWidth(lua_State* L) { 573 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2)); 574 return 0; 575 } 576 577 static int lpaint_measureText(lua_State* L) { 578 if (lua_isstring(L, 2)) { 579 size_t len; 580 const char* text = lua_tolstring(L, 2, &len); 581 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len)); 582 return 1; 583 } 584 return 0; 585 } 586 587 struct FontMetrics { 588 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0) 589 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0) 590 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0) 591 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0) 592 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0) 593 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0) 594 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs 595 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs 596 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face 597 }; 598 599 static int lpaint_getFontMetrics(lua_State* L) { 600 SkPaint::FontMetrics fm; 601 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm); 602 603 lua_newtable(L); 604 setfield_scalar(L, "top", fm.fTop); 605 setfield_scalar(L, "ascent", fm.fAscent); 606 setfield_scalar(L, "descent", fm.fDescent); 607 setfield_scalar(L, "bottom", fm.fBottom); 608 setfield_scalar(L, "leading", fm.fLeading); 609 SkLua(L).pushScalar(height); 610 return 2; 611 } 612 613 static int lpaint_getEffects(lua_State* L) { 614 const SkPaint* paint = get_obj<SkPaint>(L, 1); 615 616 lua_newtable(L); 617 setfield_bool_if(L, "looper", !!paint->getLooper()); 618 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect()); 619 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer()); 620 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter()); 621 setfield_bool_if(L, "shader", !!paint->getShader()); 622 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter()); 623 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter()); 624 setfield_bool_if(L, "xfermode", !!paint->getXfermode()); 625 return 1; 626 } 627 628 static int lpaint_getShader(lua_State* L) { 629 const SkPaint* paint = get_obj<SkPaint>(L, 1); 630 SkShader* shader = paint->getShader(); 631 if (shader) { 632 push_ref(L, shader); 633 return 1; 634 } 635 return 0; 636 } 637 638 static int lpaint_gc(lua_State* L) { 639 get_obj<SkPaint>(L, 1)->~SkPaint(); 640 return 0; 641 } 642 643 static const struct luaL_Reg gSkPaint_Methods[] = { 644 { "isAntiAlias", lpaint_isAntiAlias }, 645 { "setAntiAlias", lpaint_setAntiAlias }, 646 { "getColor", lpaint_getColor }, 647 { "setColor", lpaint_setColor }, 648 { "getTextSize", lpaint_getTextSize }, 649 { "setTextSize", lpaint_setTextSize }, 650 { "getTypeface", lpaint_getTypeface }, 651 { "setTypeface", lpaint_setTypeface }, 652 { "getFontID", lpaint_getFontID }, 653 { "getTextAlign", lpaint_getTextAlign }, 654 { "setTextAlign", lpaint_setTextAlign }, 655 { "getStroke", lpaint_getStroke }, 656 { "setStroke", lpaint_setStroke }, 657 { "getStrokeWidth", lpaint_getStrokeWidth }, 658 { "setStrokeWidth", lpaint_setStrokeWidth }, 659 { "measureText", lpaint_measureText }, 660 { "getFontMetrics", lpaint_getFontMetrics }, 661 { "getEffects", lpaint_getEffects }, 662 { "getShader", lpaint_getShader }, 663 { "__gc", lpaint_gc }, 664 { NULL, NULL } 665 }; 666 667 /////////////////////////////////////////////////////////////////////////////// 668 669 static const char* mode2string(SkShader::TileMode mode) { 670 static const char* gNames[] = { "clamp", "repeat", "mirror" }; 671 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames)); 672 return gNames[mode]; 673 } 674 675 static const char* gradtype2string(SkShader::GradientType t) { 676 static const char* gNames[] = { 677 "none", "color", "linear", "radial", "radial2", "sweep", "conical" 678 }; 679 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames)); 680 return gNames[t]; 681 } 682 683 static int lshader_isOpaque(lua_State* L) { 684 SkShader* shader = get_ref<SkShader>(L, 1); 685 return shader && shader->isOpaque(); 686 } 687 688 static int lshader_asABitmap(lua_State* L) { 689 SkShader* shader = get_ref<SkShader>(L, 1); 690 if (shader) { 691 SkBitmap bm; 692 SkMatrix matrix; 693 SkShader::TileMode modes[2]; 694 switch (shader->asABitmap(&bm, &matrix, modes)) { 695 case SkShader::kDefault_BitmapType: 696 lua_newtable(L); 697 setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0); 698 setfield_number(L, "width", bm.width()); 699 setfield_number(L, "height", bm.height()); 700 setfield_string(L, "tileX", mode2string(modes[0])); 701 setfield_string(L, "tileY", mode2string(modes[1])); 702 return 1; 703 default: 704 break; 705 } 706 } 707 return 0; 708 } 709 710 static int lshader_asAGradient(lua_State* L) { 711 SkShader* shader = get_ref<SkShader>(L, 1); 712 if (shader) { 713 SkShader::GradientInfo info; 714 sk_bzero(&info, sizeof(info)); 715 716 SkColor colors[3]; // hacked in for extracting info on 3 color case. 717 SkScalar pos[3]; 718 719 info.fColorCount = 3; 720 info.fColors = &colors[0]; 721 info.fColorOffsets = &pos[0]; 722 723 SkShader::GradientType t = shader->asAGradient(&info); 724 725 if (SkShader::kNone_GradientType != t) { 726 lua_newtable(L); 727 setfield_string(L, "type", gradtype2string(t)); 728 setfield_number(L, "colorCount", info.fColorCount); 729 setfield_string(L, "tile", mode2string(info.fTileMode)); 730 731 if (info.fColorCount == 3){ 732 setfield_number(L, "midPos", pos[1]); 733 } 734 735 return 1; 736 } 737 } 738 return 0; 739 } 740 741 static int lshader_gc(lua_State* L) { 742 get_ref<SkShader>(L, 1)->unref(); 743 return 0; 744 } 745 746 static const struct luaL_Reg gSkShader_Methods[] = { 747 { "isOpaque", lshader_isOpaque }, 748 { "asABitmap", lshader_asABitmap }, 749 { "asAGradient", lshader_asAGradient }, 750 { "__gc", lshader_gc }, 751 { NULL, NULL } 752 }; 753 754 /////////////////////////////////////////////////////////////////////////////// 755 756 static int lmatrix_getType(lua_State* L) { 757 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType(); 758 759 lua_newtable(L); 760 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask)); 761 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask)); 762 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask)); 763 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask)); 764 return 1; 765 } 766 767 static int lmatrix_getScaleX(lua_State* L) { 768 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX()); 769 return 1; 770 } 771 772 static int lmatrix_getScaleY(lua_State* L) { 773 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY()); 774 return 1; 775 } 776 777 static int lmatrix_getTranslateX(lua_State* L) { 778 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX()); 779 return 1; 780 } 781 782 static int lmatrix_getTranslateY(lua_State* L) { 783 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY()); 784 return 1; 785 } 786 787 static const struct luaL_Reg gSkMatrix_Methods[] = { 788 { "getType", lmatrix_getType }, 789 { "getScaleX", lmatrix_getScaleX }, 790 { "getScaleY", lmatrix_getScaleY }, 791 { "getTranslateX", lmatrix_getTranslateX }, 792 { "getTranslateY", lmatrix_getTranslateY }, 793 { NULL, NULL } 794 }; 795 796 /////////////////////////////////////////////////////////////////////////////// 797 798 static int lpath_getBounds(lua_State* L) { 799 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds()); 800 return 1; 801 } 802 803 static int lpath_isEmpty(lua_State* L) { 804 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty()); 805 return 1; 806 } 807 808 static int lpath_isRect(lua_State* L) { 809 SkRect r; 810 bool pred = get_obj<SkPath>(L, 1)->isRect(&r); 811 int ret_count = 1; 812 lua_pushboolean(L, pred); 813 if (pred) { 814 SkLua(L).pushRect(r); 815 ret_count += 1; 816 } 817 return ret_count; 818 } 819 820 static const char* dir2string(SkPath::Direction dir) { 821 static const char* gStr[] = { 822 "unknown", "cw", "ccw" 823 }; 824 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr)); 825 return gStr[dir]; 826 } 827 828 static int lpath_isNestedRects(lua_State* L) { 829 SkRect rects[2]; 830 SkPath::Direction dirs[2]; 831 bool pred = get_obj<SkPath>(L, 1)->isNestedRects(rects, dirs); 832 int ret_count = 1; 833 lua_pushboolean(L, pred); 834 if (pred) { 835 SkLua lua(L); 836 lua.pushRect(rects[0]); 837 lua.pushRect(rects[1]); 838 lua_pushstring(L, dir2string(dirs[0])); 839 lua_pushstring(L, dir2string(dirs[0])); 840 ret_count += 4; 841 } 842 return ret_count; 843 } 844 845 static int lpath_reset(lua_State* L) { 846 get_obj<SkPath>(L, 1)->reset(); 847 return 0; 848 } 849 850 static int lpath_moveTo(lua_State* L) { 851 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3)); 852 return 0; 853 } 854 855 static int lpath_lineTo(lua_State* L) { 856 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3)); 857 return 0; 858 } 859 860 static int lpath_quadTo(lua_State* L) { 861 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3), 862 lua2scalar(L, 4), lua2scalar(L, 5)); 863 return 0; 864 } 865 866 static int lpath_cubicTo(lua_State* L) { 867 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3), 868 lua2scalar(L, 4), lua2scalar(L, 5), 869 lua2scalar(L, 6), lua2scalar(L, 7)); 870 return 0; 871 } 872 873 static int lpath_close(lua_State* L) { 874 get_obj<SkPath>(L, 1)->close(); 875 return 0; 876 } 877 878 static int lpath_gc(lua_State* L) { 879 get_obj<SkPath>(L, 1)->~SkPath(); 880 return 0; 881 } 882 883 static const struct luaL_Reg gSkPath_Methods[] = { 884 { "getBounds", lpath_getBounds }, 885 { "isEmpty", lpath_isEmpty }, 886 { "isRect", lpath_isRect }, 887 { "isNestedRects", lpath_isNestedRects }, 888 { "reset", lpath_reset }, 889 { "moveTo", lpath_moveTo }, 890 { "lineTo", lpath_lineTo }, 891 { "quadTo", lpath_quadTo }, 892 { "cubicTo", lpath_cubicTo }, 893 { "close", lpath_close }, 894 { "__gc", lpath_gc }, 895 { NULL, NULL } 896 }; 897 898 /////////////////////////////////////////////////////////////////////////////// 899 900 static const char* rrect_type(const SkRRect& rr) { 901 switch (rr.getType()) { 902 case SkRRect::kUnknown_Type: return "unknown"; 903 case SkRRect::kEmpty_Type: return "empty"; 904 case SkRRect::kRect_Type: return "rect"; 905 case SkRRect::kOval_Type: return "oval"; 906 case SkRRect::kSimple_Type: return "simple"; 907 case SkRRect::kComplex_Type: return "complex"; 908 } 909 SkDEBUGFAIL("never get here"); 910 return ""; 911 } 912 913 static int lrrect_rect(lua_State* L) { 914 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect()); 915 return 1; 916 } 917 918 static int lrrect_type(lua_State* L) { 919 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1))); 920 return 1; 921 } 922 923 static int lrrect_radii(lua_State* L) { 924 int corner = lua_tointeger(L, 2); 925 SkVector v; 926 if (corner < 0 || corner > 3) { 927 SkDebugf("bad corner index %d", corner); 928 v.set(0, 0); 929 } else { 930 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner); 931 } 932 lua_pushnumber(L, v.fX); 933 lua_pushnumber(L, v.fY); 934 return 2; 935 } 936 937 static int lrrect_gc(lua_State* L) { 938 get_obj<SkRRect>(L, 1)->~SkRRect(); 939 return 0; 940 } 941 942 static const struct luaL_Reg gSkRRect_Methods[] = { 943 { "rect", lrrect_rect }, 944 { "type", lrrect_type }, 945 { "radii", lrrect_radii }, 946 { "__gc", lrrect_gc }, 947 { NULL, NULL } 948 }; 949 950 /////////////////////////////////////////////////////////////////////////////// 951 952 static int limage_width(lua_State* L) { 953 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width()); 954 return 1; 955 } 956 957 static int limage_height(lua_State* L) { 958 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height()); 959 return 1; 960 } 961 962 static int limage_gc(lua_State* L) { 963 get_ref<SkImage>(L, 1)->unref(); 964 return 0; 965 } 966 967 static const struct luaL_Reg gSkImage_Methods[] = { 968 { "width", limage_width }, 969 { "height", limage_height }, 970 { "__gc", limage_gc }, 971 { NULL, NULL } 972 }; 973 974 /////////////////////////////////////////////////////////////////////////////// 975 976 static int ltypeface_gc(lua_State* L) { 977 get_ref<SkTypeface>(L, 1)->unref(); 978 return 0; 979 } 980 981 static const struct luaL_Reg gSkTypeface_Methods[] = { 982 { "__gc", ltypeface_gc }, 983 { NULL, NULL } 984 }; 985 986 /////////////////////////////////////////////////////////////////////////////// 987 988 class AutoCallLua { 989 public: 990 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) { 991 lua_getglobal(L, func); 992 if (!lua_isfunction(L, -1)) { 993 int t = lua_type(L, -1); 994 SkDebugf("--- expected function %d\n", t); 995 } 996 997 lua_newtable(L); 998 setfield_string(L, "verb", verb); 999 } 1000 1001 ~AutoCallLua() { 1002 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) { 1003 SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); 1004 } 1005 lua_settop(fL, -1); 1006 } 1007 1008 private: 1009 lua_State* fL; 1010 }; 1011 1012 #define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb) 1013 1014 /////////////////////////////////////////////////////////////////////////////// 1015 1016 static int lsk_newDocumentPDF(lua_State* L) { 1017 const char* file = NULL; 1018 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { 1019 file = lua_tolstring(L, 1, NULL); 1020 } 1021 1022 SkDocument* doc = SkDocument::CreatePDF(file); 1023 if (NULL == doc) { 1024 // do I need to push a nil on the stack and return 1? 1025 return 0; 1026 } else { 1027 push_ref(L, doc); 1028 doc->unref(); 1029 return 1; 1030 } 1031 } 1032 1033 static int lsk_newPaint(lua_State* L) { 1034 push_new<SkPaint>(L); 1035 return 1; 1036 } 1037 1038 static int lsk_newPath(lua_State* L) { 1039 push_new<SkPath>(L); 1040 return 1; 1041 } 1042 1043 static int lsk_newRRect(lua_State* L) { 1044 SkRRect* rr = push_new<SkRRect>(L); 1045 rr->setEmpty(); 1046 return 1; 1047 } 1048 1049 static int lsk_newTypeface(lua_State* L) { 1050 const char* name = NULL; 1051 int style = SkTypeface::kNormal; 1052 1053 int count = lua_gettop(L); 1054 if (count > 0 && lua_isstring(L, 1)) { 1055 name = lua_tolstring(L, 1, NULL); 1056 if (count > 1 && lua_isnumber(L, 2)) { 1057 style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic; 1058 } 1059 } 1060 1061 SkTypeface* face = SkTypeface::CreateFromName(name, 1062 (SkTypeface::Style)style); 1063 // SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt()); 1064 if (NULL == face) { 1065 face = SkTypeface::RefDefault(); 1066 } 1067 push_ref(L, face); 1068 face->unref(); 1069 return 1; 1070 } 1071 1072 static int lsk_loadImage(lua_State* L) { 1073 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { 1074 const char* name = lua_tolstring(L, 1, NULL); 1075 SkAutoDataUnref data(SkData::NewFromFileName(name)); 1076 if (data.get()) { 1077 SkImage* image = SkImage::NewEncodedData(data.get()); 1078 if (image) { 1079 push_ref(L, image); 1080 image->unref(); 1081 return 1; 1082 } 1083 } 1084 } 1085 return 0; 1086 } 1087 1088 static void register_Sk(lua_State* L) { 1089 lua_newtable(L); 1090 lua_pushvalue(L, -1); 1091 lua_setglobal(L, "Sk"); 1092 // the Sk table is still on top 1093 1094 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF); 1095 setfield_function(L, "loadImage", lsk_loadImage); 1096 setfield_function(L, "newPaint", lsk_newPaint); 1097 setfield_function(L, "newPath", lsk_newPath); 1098 setfield_function(L, "newRRect", lsk_newRRect); 1099 setfield_function(L, "newTypeface", lsk_newTypeface); 1100 lua_pop(L, 1); // pop off the Sk table 1101 } 1102 1103 #define REG_CLASS(L, C) \ 1104 do { \ 1105 luaL_newmetatable(L, get_mtname<C>()); \ 1106 lua_pushvalue(L, -1); \ 1107 lua_setfield(L, -2, "__index"); \ 1108 luaL_setfuncs(L, g##C##_Methods, 0); \ 1109 lua_pop(L, 1); /* pop off the meta-table */ \ 1110 } while (0) 1111 1112 void SkLua::Load(lua_State* L) { 1113 register_Sk(L); 1114 REG_CLASS(L, SkCanvas); 1115 REG_CLASS(L, SkDocument); 1116 REG_CLASS(L, SkImage); 1117 REG_CLASS(L, SkPath); 1118 REG_CLASS(L, SkPaint); 1119 REG_CLASS(L, SkRRect); 1120 REG_CLASS(L, SkShader); 1121 REG_CLASS(L, SkTypeface); 1122 REG_CLASS(L, SkMatrix); 1123 } 1124 1125 extern "C" int luaopen_skia(lua_State* L); 1126 extern "C" int luaopen_skia(lua_State* L) { 1127 SkLua::Load(L); 1128 return 0; 1129 } 1130