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