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)
DEF_MTNAME(SkColorFilter)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
push_obj(lua_State * L,const T & obj)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
push_ptr(lua_State * L,T * ptr)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
push_ref(lua_State * L,T * ref)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
push_ref(lua_State * L,sk_sp<T> sp)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
get_ref(lua_State * L,int index)96 template <typename T> T* get_ref(lua_State* L, int index) {
97 return *(T**)luaL_checkudata(L, index, get_mtname<T>());
98 }
99
get_obj(lua_State * L,int index)100 template <typename T> T* get_obj(lua_State* L, int index) {
101 return (T*)luaL_checkudata(L, index, get_mtname<T>());
102 }
103
lua2bool(lua_State * L,int index)104 static bool lua2bool(lua_State* L, int index) {
105 return !!lua_toboolean(L, index);
106 }
107
108 ///////////////////////////////////////////////////////////////////////////////
109
SkLua(const char termCode[])110 SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
111 fL = luaL_newstate();
112 luaL_openlibs(fL);
113 SkLua::Load(fL);
114 }
115
SkLua(lua_State * L)116 SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
117
~SkLua()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
runCode(const char code[])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
runCode(const void * code,size_t size)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
setfield_bool_if(lua_State * L,const char key[],bool pred)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
setfield_string(lua_State * L,const char key[],const char value[])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
setfield_number(lua_State * L,const char key[],double value)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
setfield_boolean(lua_State * L,const char key[],bool value)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
setfield_scalar(lua_State * L,const char key[],SkScalar value)170 static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
171 setfield_number(L, key, SkScalarToLua(value));
172 }
173
setfield_function(lua_State * L,const char key[],lua_CFunction value)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
lua2int_def(lua_State * L,int index,int defaultValue)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
lua2scalar(lua_State * L,int index)188 static SkScalar lua2scalar(lua_State* L, int index) {
189 SkASSERT(lua_isnumber(L, index));
190 return SkLuaToScalar(lua_tonumber(L, index));
191 }
192
lua2scalar_def(lua_State * L,int index,SkScalar defaultValue)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
getarray_scalar(lua_State * L,int stackIndex,int arrayIndex)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
getarray_scalars(lua_State * L,int stackIndex,SkScalar dst[],int count)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
getarray_points(lua_State * L,int stackIndex,SkPoint pts[],int count)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
setarray_number(lua_State * L,int index,double value)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
setarray_scalar(lua_State * L,int index,SkScalar value)225 static void setarray_scalar(lua_State* L, int index, SkScalar value) {
226 setarray_number(L, index, SkScalarToLua(value));
227 }
228
setarray_string(lua_State * L,int index,const char str[])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
pushBool(bool value,const char key[])234 void SkLua::pushBool(bool value, const char key[]) {
235 lua_pushboolean(fL, value);
236 CHECK_SETFIELD(key);
237 }
238
pushString(const char str[],const char key[])239 void SkLua::pushString(const char str[], const char key[]) {
240 lua_pushstring(fL, str);
241 CHECK_SETFIELD(key);
242 }
243
pushString(const char str[],size_t length,const char key[])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
pushString(const SkString & str,const char key[])251 void SkLua::pushString(const SkString& str, const char key[]) {
252 lua_pushstring(fL, str.c_str());
253 CHECK_SETFIELD(key);
254 }
255
pushColor(SkColor color,const char key[])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
pushU32(uint32_t value,const char key[])265 void SkLua::pushU32(uint32_t value, const char key[]) {
266 lua_pushnumber(fL, (double)value);
267 CHECK_SETFIELD(key);
268 }
269
pushScalar(SkScalar value,const char key[])270 void SkLua::pushScalar(SkScalar value, const char key[]) {
271 lua_pushnumber(fL, SkScalarToLua(value));
272 CHECK_SETFIELD(key);
273 }
274
pushArrayU16(const uint16_t array[],int count,const char key[])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
pushArrayPoint(const SkPoint array[],int count,const char key[])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
pushArrayScalar(const SkScalar array[],int count,const char key[])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
pushRect(const SkRect & r,const char key[])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
pushRRect(const SkRRect & rr,const char key[])314 void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
315 push_obj(fL, rr);
316 CHECK_SETFIELD(key);
317 }
318
pushDash(const SkPathEffect::DashInfo & info,const char key[])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
pushMatrix(const SkMatrix & matrix,const char key[])327 void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
328 push_obj(fL, matrix);
329 CHECK_SETFIELD(key);
330 }
331
pushPaint(const SkPaint & paint,const char key[])332 void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
333 push_obj(fL, paint);
334 CHECK_SETFIELD(key);
335 }
336
pushPath(const SkPath & path,const char key[])337 void SkLua::pushPath(const SkPath& path, const char key[]) {
338 push_obj(fL, path);
339 CHECK_SETFIELD(key);
340 }
341
pushCanvas(SkCanvas * canvas,const char key[])342 void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
343 push_ptr(fL, canvas);
344 CHECK_SETFIELD(key);
345 }
346
pushTextBlob(const SkTextBlob * blob,const char key[])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
getfield_scalar(lua_State * L,int index,const char key[])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
getfield_scalar_default(lua_State * L,int index,const char key[],SkScalar def)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
byte2unit(U8CPU byte)380 static SkScalar byte2unit(U8CPU byte) {
381 return byte / 255.0f;
382 }
383
unit2byte(SkScalar x)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
lua2color(lua_State * L,int index)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
lua2rect(lua_State * L,int index,SkRect * rect)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
lcanvas_clear(lua_State * L)409 static int lcanvas_clear(lua_State* L) {
410 get_ref<SkCanvas>(L, 1)->clear(0);
411 return 0;
412 }
413
lcanvas_drawColor(lua_State * L)414 static int lcanvas_drawColor(lua_State* L) {
415 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
416 return 0;
417 }
418
lcanvas_drawPaint(lua_State * L)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
lcanvas_drawRect(lua_State * L)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
lcanvas_drawOval(lua_State * L)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
lcanvas_drawCircle(lua_State * L)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
lua2OptionalPaint(lua_State * L,int index,SkPaint * paint)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
lcanvas_drawImage(lua_State * L)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
lcanvas_drawImageRect(lua_State * L)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
lcanvas_drawPatch(lua_State * L)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
lcanvas_drawPath(lua_State * L)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)
lcanvas_drawPicture(lua_State * L)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
lcanvas_drawText(lua_State * L)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
lcanvas_drawTextBlob(lua_State * L)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
lcanvas_getSaveCount(lua_State * L)566 static int lcanvas_getSaveCount(lua_State* L) {
567 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
568 return 1;
569 }
570
lcanvas_getTotalMatrix(lua_State * L)571 static int lcanvas_getTotalMatrix(lua_State* L) {
572 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
573 return 1;
574 }
575
lcanvas_save(lua_State * L)576 static int lcanvas_save(lua_State* L) {
577 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
578 return 1;
579 }
580
lcanvas_saveLayer(lua_State * L)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
lcanvas_restore(lua_State * L)587 static int lcanvas_restore(lua_State* L) {
588 get_ref<SkCanvas>(L, 1)->restore();
589 return 0;
590 }
591
lcanvas_scale(lua_State * L)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
lcanvas_translate(lua_State * L)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
lcanvas_rotate(lua_State * L)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
lcanvas_concat(lua_State * L)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
lcanvas_newSurface(lua_State * L)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
lcanvas_gc(lua_State * L)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
ldocument_beginPage(lua_State * L)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
ldocument_endPage(lua_State * L)675 static int ldocument_endPage(lua_State* L) {
676 get_ref<SkDocument>(L, 1)->endPage();
677 return 0;
678 }
679
ldocument_close(lua_State * L)680 static int ldocument_close(lua_State* L) {
681 get_ref<SkDocument>(L, 1)->close();
682 return 0;
683 }
684
ldocument_gc(lua_State * L)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
lpaint_isAntiAlias(lua_State * L)700 static int lpaint_isAntiAlias(lua_State* L) {
701 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
702 return 1;
703 }
704
lpaint_setAntiAlias(lua_State * L)705 static int lpaint_setAntiAlias(lua_State* L) {
706 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
707 return 0;
708 }
709
lpaint_isDither(lua_State * L)710 static int lpaint_isDither(lua_State* L) {
711 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
712 return 1;
713 }
714
lpaint_setDither(lua_State * L)715 static int lpaint_setDither(lua_State* L) {
716 get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2));
717 return 0;
718 }
719
lpaint_isFakeBoldText(lua_State * L)720 static int lpaint_isFakeBoldText(lua_State* L) {
721 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
722 return 1;
723 }
724
lpaint_isLinearText(lua_State * L)725 static int lpaint_isLinearText(lua_State* L) {
726 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
727 return 1;
728 }
729
lpaint_isSubpixelText(lua_State * L)730 static int lpaint_isSubpixelText(lua_State* L) {
731 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
732 return 1;
733 }
734
lpaint_setSubpixelText(lua_State * L)735 static int lpaint_setSubpixelText(lua_State* L) {
736 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
737 return 1;
738 }
739
lpaint_isDevKernText(lua_State * L)740 static int lpaint_isDevKernText(lua_State* L) {
741 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
742 return 1;
743 }
744
lpaint_isLCDRenderText(lua_State * L)745 static int lpaint_isLCDRenderText(lua_State* L) {
746 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
747 return 1;
748 }
749
lpaint_setLCDRenderText(lua_State * L)750 static int lpaint_setLCDRenderText(lua_State* L) {
751 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2));
752 return 1;
753 }
754
lpaint_isEmbeddedBitmapText(lua_State * L)755 static int lpaint_isEmbeddedBitmapText(lua_State* L) {
756 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
757 return 1;
758 }
759
lpaint_isAutohinted(lua_State * L)760 static int lpaint_isAutohinted(lua_State* L) {
761 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
762 return 1;
763 }
764
lpaint_isVerticalText(lua_State * L)765 static int lpaint_isVerticalText(lua_State* L) {
766 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
767 return 1;
768 }
769
lpaint_getAlpha(lua_State * L)770 static int lpaint_getAlpha(lua_State* L) {
771 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha()));
772 return 1;
773 }
774
lpaint_setAlpha(lua_State * L)775 static int lpaint_setAlpha(lua_State* L) {
776 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2)));
777 return 0;
778 }
779
lpaint_getColor(lua_State * L)780 static int lpaint_getColor(lua_State* L) {
781 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
782 return 1;
783 }
784
lpaint_setColor(lua_State * L)785 static int lpaint_setColor(lua_State* L) {
786 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
787 return 0;
788 }
789
lpaint_getTextSize(lua_State * L)790 static int lpaint_getTextSize(lua_State* L) {
791 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
792 return 1;
793 }
794
lpaint_getTextScaleX(lua_State * L)795 static int lpaint_getTextScaleX(lua_State* L) {
796 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
797 return 1;
798 }
799
lpaint_getTextSkewX(lua_State * L)800 static int lpaint_getTextSkewX(lua_State* L) {
801 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
802 return 1;
803 }
804
lpaint_setTextSize(lua_State * L)805 static int lpaint_setTextSize(lua_State* L) {
806 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
807 return 0;
808 }
809
lpaint_getTypeface(lua_State * L)810 static int lpaint_getTypeface(lua_State* L) {
811 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
812 return 1;
813 }
814
lpaint_setTypeface(lua_State * L)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
lpaint_getHinting(lua_State * L)820 static int lpaint_getHinting(lua_State* L) {
821 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
822 return 1;
823 }
824
lpaint_getFilterQuality(lua_State * L)825 static int lpaint_getFilterQuality(lua_State* L) {
826 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality());
827 return 1;
828 }
829
lpaint_setFilterQuality(lua_State * L)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
lpaint_getFontID(lua_State * L)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
lpaint_getTextAlign(lua_State * L)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
lpaint_setTextAlign(lua_State * L)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
lpaint_getStroke(lua_State * L)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
lpaint_setStroke(lua_State * L)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
lpaint_getStrokeCap(lua_State * L)896 static int lpaint_getStrokeCap(lua_State* L) {
897 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
898 return 1;
899 }
900
lpaint_getStrokeJoin(lua_State * L)901 static int lpaint_getStrokeJoin(lua_State* L) {
902 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
903 return 1;
904 }
905
lpaint_getTextEncoding(lua_State * L)906 static int lpaint_getTextEncoding(lua_State* L) {
907 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
908 return 1;
909 }
910
lpaint_getStrokeWidth(lua_State * L)911 static int lpaint_getStrokeWidth(lua_State* L) {
912 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
913 return 1;
914 }
915
lpaint_setStrokeWidth(lua_State * L)916 static int lpaint_setStrokeWidth(lua_State* L) {
917 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
918 return 0;
919 }
920
lpaint_getStrokeMiter(lua_State * L)921 static int lpaint_getStrokeMiter(lua_State* L) {
922 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
923 return 1;
924 }
925
lpaint_measureText(lua_State * L)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
lpaint_getFontMetrics(lua_State * L)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
lpaint_getEffects(lua_State * L)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
lpaint_getColorFilter(lua_State * L)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
lpaint_setColorFilter(lua_State * L)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
lpaint_getImageFilter(lua_State * L)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
lpaint_setImageFilter(lua_State * L)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
lpaint_getShader(lua_State * L)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
lpaint_setShader(lua_State * L)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
lpaint_getPathEffect(lua_State * L)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
lpaint_getFillPath(lua_State * L)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
lpaint_gc(lua_State * L)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
mode2string(SkShader::TileMode mode)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
gradtype2string(SkShader::GradientType t)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
lshader_isOpaque(lua_State * L)1122 static int lshader_isOpaque(lua_State* L) {
1123 SkShader* shader = get_ref<SkShader>(L, 1);
1124 return shader && shader->isOpaque();
1125 }
1126
lshader_isAImage(lua_State * L)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
lshader_asAGradient(lua_State * L)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
lshader_gc(lua_State * L)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
lpatheffect_asADash(lua_State * L)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
lpatheffect_gc(lua_State * L)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
lpcolorfilter_gc(lua_State * L)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
lpimagefilter_gc(lua_State * L)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
lmatrix_getType(lua_State * L)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
lmatrix_getScaleX(lua_State * L)1255 static int lmatrix_getScaleX(lua_State* L) {
1256 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1257 return 1;
1258 }
1259
lmatrix_getScaleY(lua_State * L)1260 static int lmatrix_getScaleY(lua_State* L) {
1261 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1262 return 1;
1263 }
1264
lmatrix_getTranslateX(lua_State * L)1265 static int lmatrix_getTranslateX(lua_State* L) {
1266 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1267 return 1;
1268 }
1269
lmatrix_getTranslateY(lua_State * L)1270 static int lmatrix_getTranslateY(lua_State* L) {
1271 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1272 return 1;
1273 }
1274
lmatrix_invert(lua_State * L)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
lmatrix_mapXY(lua_State * L)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
lmatrix_setRectToRect(lua_State * L)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
lpath_getBounds(lua_State * L)1333 static int lpath_getBounds(lua_State* L) {
1334 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1335 return 1;
1336 }
1337
fill_type_to_str(SkPath::FillType fill)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
lpath_getFillType(lua_State * L)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
segment_masks_to_str(uint32_t segmentMasks)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
lpath_getSegmentTypes(lua_State * L)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
lpath_isConvex(lua_State * L)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
lpath_isEmpty(lua_State * L)1405 static int lpath_isEmpty(lua_State* L) {
1406 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1407 return 1;
1408 }
1409
lpath_isRect(lua_State * L)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
dir2string(SkPath::Direction dir)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
lpath_isNestedFillRects(lua_State * L)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
lpath_countPoints(lua_State * L)1447 static int lpath_countPoints(lua_State* L) {
1448 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1449 return 1;
1450 }
1451
lpath_getVerbs(lua_State * L)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
lpath_reset(lua_State * L)1491 static int lpath_reset(lua_State* L) {
1492 get_obj<SkPath>(L, 1)->reset();
1493 return 0;
1494 }
1495
lpath_moveTo(lua_State * L)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
lpath_lineTo(lua_State * L)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
lpath_quadTo(lua_State * L)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
lpath_cubicTo(lua_State * L)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
lpath_close(lua_State * L)1519 static int lpath_close(lua_State* L) {
1520 get_obj<SkPath>(L, 1)->close();
1521 return 0;
1522 }
1523
lpath_gc(lua_State * L)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
rrect_type(const SkRRect & rr)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
lrrect_rect(lua_State * L)1564 static int lrrect_rect(lua_State* L) {
1565 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1566 return 1;
1567 }
1568
lrrect_type(lua_State * L)1569 static int lrrect_type(lua_State* L) {
1570 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1571 return 1;
1572 }
1573
lrrect_radii(lua_State * L)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
lrrect_gc(lua_State * L)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
limage_width(lua_State * L)1603 static int limage_width(lua_State* L) {
1604 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1605 return 1;
1606 }
1607
limage_height(lua_State * L)1608 static int limage_height(lua_State* L) {
1609 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1610 return 1;
1611 }
1612
limage_newShader(lua_State * L)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
limage_gc(lua_State * L)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
lsurface_width(lua_State * L)1635 static int lsurface_width(lua_State* L) {
1636 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1637 return 1;
1638 }
1639
lsurface_height(lua_State * L)1640 static int lsurface_height(lua_State* L) {
1641 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1642 return 1;
1643 }
1644
lsurface_getCanvas(lua_State * L)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
lsurface_newImageSnapshot(lua_State * L)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
lsurface_newSurface(lua_State * L)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
lsurface_gc(lua_State * L)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
lpicturerecorder_beginRecording(lua_State * L)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
lpicturerecorder_getCanvas(lua_State * L)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
lpicturerecorder_endRecording(lua_State * L)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
lpicturerecorder_gc(lua_State * L)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
lpicture_width(lua_State * L)1753 static int lpicture_width(lua_State* L) {
1754 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1755 return 1;
1756 }
1757
lpicture_height(lua_State * L)1758 static int lpicture_height(lua_State* L) {
1759 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1760 return 1;
1761 }
1762
lpicture_gc(lua_State * L)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
ltextblob_bounds(lua_State * L)1777 static int ltextblob_bounds(lua_State* L) {
1778 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
1779 return 1;
1780 }
1781
ltextblob_gc(lua_State * L)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
ltypeface_getFamilyName(lua_State * L)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
ltypeface_getStyle(lua_State * L)1802 static int ltypeface_getStyle(lua_State* L) {
1803 lua_pushnumber(L, (double)get_ref<SkTypeface>(L, 1)->style());
1804 return 1;
1805 }
1806
ltypeface_gc(lua_State * L)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:
AutoCallLua(lua_State * L,const char func[],const char verb[])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
~AutoCallLua()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
lsk_newDocumentPDF(lua_State * L)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
lsk_newBlurImageFilter(lua_State * L)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
lsk_newLinearGradient(lua_State * L)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
lsk_newMatrix(lua_State * L)1897 static int lsk_newMatrix(lua_State* L) {
1898 push_new<SkMatrix>(L)->reset();
1899 return 1;
1900 }
1901
lsk_newPaint(lua_State * L)1902 static int lsk_newPaint(lua_State* L) {
1903 push_new<SkPaint>(L);
1904 return 1;
1905 }
1906
lsk_newPath(lua_State * L)1907 static int lsk_newPath(lua_State* L) {
1908 push_new<SkPath>(L);
1909 return 1;
1910 }
1911
lsk_newPictureRecorder(lua_State * L)1912 static int lsk_newPictureRecorder(lua_State* L) {
1913 push_new<SkPictureRecorder>(L);
1914 return 1;
1915 }
1916
lsk_newRRect(lua_State * L)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)
lsk_newTextBlob(lua_State * L)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
lsk_newTypeface(lua_State * L)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
lsk_newRasterSurface(lua_State * L)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
lsk_loadImage(lua_State * L)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
register_Sk(lua_State * L)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
Load(lua_State * L)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);
luaopen_skia(lua_State * L)2042 extern "C" int luaopen_skia(lua_State* L) {
2043 SkLua::Load(L);
2044 return 0;
2045 }
2046