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 "include/utils/SkLua.h"
9
10 #if SK_SUPPORT_GPU
11 //#include "src/gpu/GrReducedClip.h"
12 #endif
13
14 #include "include/core/SkCanvas.h"
15 #include "include/core/SkColorFilter.h"
16 #include "include/core/SkData.h"
17 #include "include/core/SkFont.h"
18 #include "include/core/SkFontMetrics.h"
19 #include "include/core/SkFontStyle.h"
20 #include "include/core/SkImage.h"
21 #include "include/core/SkMatrix.h"
22 #include "include/core/SkPaint.h"
23 #include "include/core/SkPath.h"
24 #include "include/core/SkPictureRecorder.h"
25 #include "include/core/SkRRect.h"
26 #include "include/core/SkString.h"
27 #include "include/core/SkSurface.h"
28 #include "include/core/SkTextBlob.h"
29 #include "include/core/SkTypeface.h"
30 #include "include/docs/SkPDFDocument.h"
31 #include "include/effects/SkGradientShader.h"
32 #include "include/effects/SkImageFilters.h"
33 #include "include/private/SkTo.h"
34 #include "modules/skshaper/include/SkShaper.h"
35 #include "src/core/SkMakeUnique.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, SkTextEncoding::kUTF8,
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, "pathEffect", !!paint->getPathEffect());
818 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
819 setfield_bool_if(L, "shader", !!paint->getShader());
820 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
821 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
822 return 1;
823 }
824
lpaint_getColorFilter(lua_State * L)825 static int lpaint_getColorFilter(lua_State* L) {
826 const SkPaint* paint = get_obj<SkPaint>(L, 1);
827 SkColorFilter* cf = paint->getColorFilter();
828 if (cf) {
829 push_ref(L, cf);
830 return 1;
831 }
832 return 0;
833 }
834
lpaint_setColorFilter(lua_State * L)835 static int lpaint_setColorFilter(lua_State* L) {
836 SkPaint* paint = get_obj<SkPaint>(L, 1);
837 paint->setColorFilter(sk_ref_sp(get_ref<SkColorFilter>(L, 2)));
838 return 0;
839 }
840
lpaint_getImageFilter(lua_State * L)841 static int lpaint_getImageFilter(lua_State* L) {
842 const SkPaint* paint = get_obj<SkPaint>(L, 1);
843 SkImageFilter* imf = paint->getImageFilter();
844 if (imf) {
845 push_ref(L, imf);
846 return 1;
847 }
848 return 0;
849 }
850
lpaint_setImageFilter(lua_State * L)851 static int lpaint_setImageFilter(lua_State* L) {
852 SkPaint* paint = get_obj<SkPaint>(L, 1);
853 paint->setImageFilter(sk_ref_sp(get_ref<SkImageFilter>(L, 2)));
854 return 0;
855 }
856
lpaint_getShader(lua_State * L)857 static int lpaint_getShader(lua_State* L) {
858 const SkPaint* paint = get_obj<SkPaint>(L, 1);
859 SkShader* shader = paint->getShader();
860 if (shader) {
861 push_ref(L, shader);
862 return 1;
863 }
864 return 0;
865 }
866
lpaint_setShader(lua_State * L)867 static int lpaint_setShader(lua_State* L) {
868 SkPaint* paint = get_obj<SkPaint>(L, 1);
869 paint->setShader(sk_ref_sp(get_ref<SkShader>(L, 2)));
870 return 0;
871 }
872
lpaint_getPathEffect(lua_State * L)873 static int lpaint_getPathEffect(lua_State* L) {
874 const SkPaint* paint = get_obj<SkPaint>(L, 1);
875 SkPathEffect* pe = paint->getPathEffect();
876 if (pe) {
877 push_ref(L, pe);
878 return 1;
879 }
880 return 0;
881 }
882
lpaint_getFillPath(lua_State * L)883 static int lpaint_getFillPath(lua_State* L) {
884 const SkPaint* paint = get_obj<SkPaint>(L, 1);
885 const SkPath* path = get_obj<SkPath>(L, 2);
886
887 SkPath fillpath;
888 paint->getFillPath(*path, &fillpath);
889
890 SkLua lua(L);
891 lua.pushPath(fillpath);
892
893 return 1;
894 }
895
lpaint_gc(lua_State * L)896 static int lpaint_gc(lua_State* L) {
897 get_obj<SkPaint>(L, 1)->~SkPaint();
898 return 0;
899 }
900
901 static const struct luaL_Reg gSkPaint_Methods[] = {
902 { "isAntiAlias", lpaint_isAntiAlias },
903 { "setAntiAlias", lpaint_setAntiAlias },
904 { "isDither", lpaint_isDither },
905 { "setDither", lpaint_setDither },
906 { "getFilterQuality", lpaint_getFilterQuality },
907 { "setFilterQuality", lpaint_setFilterQuality },
908 { "getAlpha", lpaint_getAlpha },
909 { "setAlpha", lpaint_setAlpha },
910 { "getColor", lpaint_getColor },
911 { "setColor", lpaint_setColor },
912 { "getStroke", lpaint_getStroke },
913 { "setStroke", lpaint_setStroke },
914 { "getStrokeCap", lpaint_getStrokeCap },
915 { "getStrokeJoin", lpaint_getStrokeJoin },
916 { "getStrokeWidth", lpaint_getStrokeWidth },
917 { "setStrokeWidth", lpaint_setStrokeWidth },
918 { "getStrokeMiter", lpaint_getStrokeMiter },
919 { "getEffects", lpaint_getEffects },
920 { "getColorFilter", lpaint_getColorFilter },
921 { "setColorFilter", lpaint_setColorFilter },
922 { "getImageFilter", lpaint_getImageFilter },
923 { "setImageFilter", lpaint_setImageFilter },
924 { "getShader", lpaint_getShader },
925 { "setShader", lpaint_setShader },
926 { "getPathEffect", lpaint_getPathEffect },
927 { "getFillPath", lpaint_getFillPath },
928 { "__gc", lpaint_gc },
929 { nullptr, nullptr }
930 };
931
932 ///////////////////////////////////////////////////////////////////////////////
933
lfont_getSize(lua_State * L)934 static int lfont_getSize(lua_State* L) {
935 SkLua(L).pushScalar(get_obj<SkFont>(L, 1)->getSize());
936 return 1;
937 }
938
lfont_getScaleX(lua_State * L)939 static int lfont_getScaleX(lua_State* L) {
940 SkLua(L).pushScalar(get_obj<SkFont>(L, 1)->getScaleX());
941 return 1;
942 }
943
lfont_getSkewX(lua_State * L)944 static int lfont_getSkewX(lua_State* L) {
945 SkLua(L).pushScalar(get_obj<SkFont>(L, 1)->getSkewX());
946 return 1;
947 }
948
lfont_setSize(lua_State * L)949 static int lfont_setSize(lua_State* L) {
950 get_obj<SkFont>(L, 1)->setSize(lua2scalar(L, 2));
951 return 0;
952 }
953
lfont_getTypeface(lua_State * L)954 static int lfont_getTypeface(lua_State* L) {
955 push_ref(L, get_obj<SkFont>(L, 1)->getTypefaceOrDefault());
956 return 1;
957 }
958
lfont_setTypeface(lua_State * L)959 static int lfont_setTypeface(lua_State* L) {
960 get_obj<SkFont>(L, 1)->setTypeface(sk_ref_sp(get_ref<SkTypeface>(L, 2)));
961 return 0;
962 }
963
lfont_getHinting(lua_State * L)964 static int lfont_getHinting(lua_State* L) {
965 SkLua(L).pushU32((unsigned)get_obj<SkFont>(L, 1)->getHinting());
966 return 1;
967 }
968
lfont_getFontID(lua_State * L)969 static int lfont_getFontID(lua_State* L) {
970 SkTypeface* face = get_obj<SkFont>(L, 1)->getTypefaceOrDefault();
971 SkLua(L).pushU32(SkTypeface::UniqueID(face));
972 return 1;
973 }
974
lfont_measureText(lua_State * L)975 static int lfont_measureText(lua_State* L) {
976 if (lua_isstring(L, 2)) {
977 size_t len;
978 const char* text = lua_tolstring(L, 2, &len);
979 SkLua(L).pushScalar(get_obj<SkFont>(L, 1)->measureText(text, len, SkTextEncoding::kUTF8));
980 return 1;
981 }
982 return 0;
983 }
984
lfont_getMetrics(lua_State * L)985 static int lfont_getMetrics(lua_State* L) {
986 SkFontMetrics fm;
987 SkScalar height = get_obj<SkFont>(L, 1)->getMetrics(&fm);
988
989 lua_newtable(L);
990 setfield_scalar(L, "top", fm.fTop);
991 setfield_scalar(L, "ascent", fm.fAscent);
992 setfield_scalar(L, "descent", fm.fDescent);
993 setfield_scalar(L, "bottom", fm.fBottom);
994 setfield_scalar(L, "leading", fm.fLeading);
995 SkLua(L).pushScalar(height);
996 return 2;
997 }
998
lfont_gc(lua_State * L)999 static int lfont_gc(lua_State* L) {
1000 get_obj<SkFont>(L, 1)->~SkFont();
1001 return 0;
1002 }
1003
1004 static const struct luaL_Reg gSkFont_Methods[] = {
1005 { "getSize", lfont_getSize },
1006 { "setSize", lfont_setSize },
1007 { "getScaleX", lfont_getScaleX },
1008 { "getSkewX", lfont_getSkewX },
1009 { "getTypeface", lfont_getTypeface },
1010 { "setTypeface", lfont_setTypeface },
1011 { "getHinting", lfont_getHinting },
1012 { "getFontID", lfont_getFontID },
1013 { "measureText", lfont_measureText },
1014 { "getMetrics", lfont_getMetrics },
1015 { "__gc", lfont_gc },
1016 { nullptr, nullptr }
1017 };
1018
1019 ///////////////////////////////////////////////////////////////////////////////
1020
mode2string(SkTileMode mode)1021 static const char* mode2string(SkTileMode mode) {
1022 static const char* gNames[] = { "clamp", "repeat", "mirror", "decal" };
1023 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
1024 return gNames[static_cast<int>(mode)];
1025 }
1026
gradtype2string(SkShader::GradientType t)1027 static const char* gradtype2string(SkShader::GradientType t) {
1028 static const char* gNames[] = {
1029 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
1030 };
1031 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
1032 return gNames[t];
1033 }
1034
lshader_isOpaque(lua_State * L)1035 static int lshader_isOpaque(lua_State* L) {
1036 SkShader* shader = get_ref<SkShader>(L, 1);
1037 return shader && shader->isOpaque();
1038 }
1039
lshader_isAImage(lua_State * L)1040 static int lshader_isAImage(lua_State* L) {
1041 SkShader* shader = get_ref<SkShader>(L, 1);
1042 if (shader) {
1043 SkMatrix matrix;
1044 SkTileMode modes[2];
1045 if (SkImage* image = shader->isAImage(&matrix, modes)) {
1046 lua_newtable(L);
1047 setfield_number(L, "id", image->uniqueID());
1048 setfield_number(L, "width", image->width());
1049 setfield_number(L, "height", image->height());
1050 setfield_string(L, "tileX", mode2string(modes[0]));
1051 setfield_string(L, "tileY", mode2string(modes[1]));
1052 return 1;
1053 }
1054 }
1055 return 0;
1056 }
1057
lshader_asAGradient(lua_State * L)1058 static int lshader_asAGradient(lua_State* L) {
1059 SkShader* shader = get_ref<SkShader>(L, 1);
1060 if (shader) {
1061 SkShader::GradientInfo info;
1062 sk_bzero(&info, sizeof(info));
1063
1064 SkShader::GradientType t = shader->asAGradient(&info);
1065
1066 if (SkShader::kNone_GradientType != t) {
1067 SkAutoTArray<SkScalar> pos(info.fColorCount);
1068 info.fColorOffsets = pos.get();
1069 shader->asAGradient(&info);
1070
1071 lua_newtable(L);
1072 setfield_string(L, "type", gradtype2string(t));
1073 setfield_string(L, "tile", mode2string((SkTileMode)info.fTileMode));
1074 setfield_number(L, "colorCount", info.fColorCount);
1075
1076 lua_newtable(L);
1077 for (int i = 0; i < info.fColorCount; i++) {
1078 // Lua uses 1-based indexing
1079 setarray_scalar(L, i+1, pos[i]);
1080 }
1081 lua_setfield(L, -2, "positions");
1082
1083 return 1;
1084 }
1085 }
1086 return 0;
1087 }
1088
lshader_gc(lua_State * L)1089 static int lshader_gc(lua_State* L) {
1090 get_ref<SkShader>(L, 1)->unref();
1091 return 0;
1092 }
1093
1094 static const struct luaL_Reg gSkShader_Methods[] = {
1095 { "isOpaque", lshader_isOpaque },
1096 { "isAImage", lshader_isAImage },
1097 { "asAGradient", lshader_asAGradient },
1098 { "__gc", lshader_gc },
1099 { nullptr, nullptr }
1100 };
1101
1102 ///////////////////////////////////////////////////////////////////////////////
1103
lpatheffect_asADash(lua_State * L)1104 static int lpatheffect_asADash(lua_State* L) {
1105 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1106 if (pe) {
1107 SkPathEffect::DashInfo info;
1108 SkPathEffect::DashType dashType = pe->asADash(&info);
1109 if (SkPathEffect::kDash_DashType == dashType) {
1110 SkAutoTArray<SkScalar> intervals(info.fCount);
1111 info.fIntervals = intervals.get();
1112 pe->asADash(&info);
1113 SkLua(L).pushDash(info);
1114 return 1;
1115 }
1116 }
1117 return 0;
1118 }
1119
lpatheffect_gc(lua_State * L)1120 static int lpatheffect_gc(lua_State* L) {
1121 get_ref<SkPathEffect>(L, 1)->unref();
1122 return 0;
1123 }
1124
1125 static const struct luaL_Reg gSkPathEffect_Methods[] = {
1126 { "asADash", lpatheffect_asADash },
1127 { "__gc", lpatheffect_gc },
1128 { nullptr, nullptr }
1129 };
1130
1131 ///////////////////////////////////////////////////////////////////////////////
1132
lpcolorfilter_gc(lua_State * L)1133 static int lpcolorfilter_gc(lua_State* L) {
1134 get_ref<SkColorFilter>(L, 1)->unref();
1135 return 0;
1136 }
1137
1138 static const struct luaL_Reg gSkColorFilter_Methods[] = {
1139 { "__gc", lpcolorfilter_gc },
1140 { nullptr, nullptr }
1141 };
1142
1143 ///////////////////////////////////////////////////////////////////////////////
1144
lpimagefilter_gc(lua_State * L)1145 static int lpimagefilter_gc(lua_State* L) {
1146 get_ref<SkImageFilter>(L, 1)->unref();
1147 return 0;
1148 }
1149
1150 static const struct luaL_Reg gSkImageFilter_Methods[] = {
1151 { "__gc", lpimagefilter_gc },
1152 { nullptr, nullptr }
1153 };
1154
1155 ///////////////////////////////////////////////////////////////////////////////
1156
lmatrix_getType(lua_State * L)1157 static int lmatrix_getType(lua_State* L) {
1158 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
1159
1160 lua_newtable(L);
1161 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1162 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1163 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1164 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1165 return 1;
1166 }
1167
lmatrix_getScaleX(lua_State * L)1168 static int lmatrix_getScaleX(lua_State* L) {
1169 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1170 return 1;
1171 }
1172
lmatrix_getScaleY(lua_State * L)1173 static int lmatrix_getScaleY(lua_State* L) {
1174 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1175 return 1;
1176 }
1177
lmatrix_getTranslateX(lua_State * L)1178 static int lmatrix_getTranslateX(lua_State* L) {
1179 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1180 return 1;
1181 }
1182
lmatrix_getTranslateY(lua_State * L)1183 static int lmatrix_getTranslateY(lua_State* L) {
1184 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1185 return 1;
1186 }
1187
lmatrix_invert(lua_State * L)1188 static int lmatrix_invert(lua_State* L) {
1189 lua_pushboolean(L, get_obj<SkMatrix>(L, 1)->invert(get_obj<SkMatrix>(L, 2)));
1190 return 1;
1191 }
1192
lmatrix_mapXY(lua_State * L)1193 static int lmatrix_mapXY(lua_State* L) {
1194 SkPoint pt = { lua2scalar(L, 2), lua2scalar(L, 3) };
1195 get_obj<SkMatrix>(L, 1)->mapPoints(&pt, &pt, 1);
1196 lua_pushnumber(L, pt.x());
1197 lua_pushnumber(L, pt.y());
1198 return 2;
1199 }
1200
lmatrix_setRectToRect(lua_State * L)1201 static int lmatrix_setRectToRect(lua_State* L) {
1202 SkMatrix* matrix = get_obj<SkMatrix>(L, 1);
1203 SkRect srcR, dstR;
1204 lua2rect(L, 2, &srcR);
1205 lua2rect(L, 3, &dstR);
1206 const char* scaleToFitStr = lua_tostring(L, 4);
1207 SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit;
1208
1209 if (scaleToFitStr) {
1210 const struct {
1211 const char* fName;
1212 SkMatrix::ScaleToFit fScaleToFit;
1213 } rec[] = {
1214 { "fill", SkMatrix::kFill_ScaleToFit },
1215 { "start", SkMatrix::kStart_ScaleToFit },
1216 { "center", SkMatrix::kCenter_ScaleToFit },
1217 { "end", SkMatrix::kEnd_ScaleToFit },
1218 };
1219
1220 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
1221 if (strcmp(rec[i].fName, scaleToFitStr) == 0) {
1222 scaleToFit = rec[i].fScaleToFit;
1223 break;
1224 }
1225 }
1226 }
1227
1228 matrix->setRectToRect(srcR, dstR, scaleToFit);
1229 return 0;
1230 }
1231
1232 static const struct luaL_Reg gSkMatrix_Methods[] = {
1233 { "getType", lmatrix_getType },
1234 { "getScaleX", lmatrix_getScaleX },
1235 { "getScaleY", lmatrix_getScaleY },
1236 { "getTranslateX", lmatrix_getTranslateX },
1237 { "getTranslateY", lmatrix_getTranslateY },
1238 { "setRectToRect", lmatrix_setRectToRect },
1239 { "invert", lmatrix_invert },
1240 { "mapXY", lmatrix_mapXY },
1241 { nullptr, nullptr }
1242 };
1243
1244 ///////////////////////////////////////////////////////////////////////////////
1245
lpath_getBounds(lua_State * L)1246 static int lpath_getBounds(lua_State* L) {
1247 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1248 return 1;
1249 }
1250
fill_type_to_str(SkPath::FillType fill)1251 static const char* fill_type_to_str(SkPath::FillType fill) {
1252 switch (fill) {
1253 case SkPath::kEvenOdd_FillType:
1254 return "even-odd";
1255 case SkPath::kWinding_FillType:
1256 return "winding";
1257 case SkPath::kInverseEvenOdd_FillType:
1258 return "inverse-even-odd";
1259 case SkPath::kInverseWinding_FillType:
1260 return "inverse-winding";
1261 }
1262 return "unknown";
1263 }
1264
lpath_getFillType(lua_State * L)1265 static int lpath_getFillType(lua_State* L) {
1266 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1267 SkLua(L).pushString(fill_type_to_str(fill));
1268 return 1;
1269 }
1270
segment_masks_to_str(uint32_t segmentMasks)1271 static SkString segment_masks_to_str(uint32_t segmentMasks) {
1272 SkString result;
1273 bool first = true;
1274 if (SkPath::kLine_SegmentMask & segmentMasks) {
1275 result.append("line");
1276 first = false;
1277 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1278 }
1279 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1280 if (!first) {
1281 result.append(" ");
1282 }
1283 result.append("quad");
1284 first = false;
1285 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1286 }
1287 if (SkPath::kConic_SegmentMask & segmentMasks) {
1288 if (!first) {
1289 result.append(" ");
1290 }
1291 result.append("conic");
1292 first = false;
1293 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1294 }
1295 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1296 if (!first) {
1297 result.append(" ");
1298 }
1299 result.append("cubic");
1300 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1301 }
1302 SkASSERT(0 == segmentMasks);
1303 return result;
1304 }
1305
lpath_getSegmentTypes(lua_State * L)1306 static int lpath_getSegmentTypes(lua_State* L) {
1307 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1308 SkLua(L).pushString(segment_masks_to_str(segMasks));
1309 return 1;
1310 }
1311
lpath_isConvex(lua_State * L)1312 static int lpath_isConvex(lua_State* L) {
1313 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1314 SkLua(L).pushBool(isConvex);
1315 return 1;
1316 }
1317
lpath_isEmpty(lua_State * L)1318 static int lpath_isEmpty(lua_State* L) {
1319 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1320 return 1;
1321 }
1322
lpath_isRect(lua_State * L)1323 static int lpath_isRect(lua_State* L) {
1324 SkRect r;
1325 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1326 int ret_count = 1;
1327 lua_pushboolean(L, pred);
1328 if (pred) {
1329 SkLua(L).pushRect(r);
1330 ret_count += 1;
1331 }
1332 return ret_count;
1333 }
1334
dir2string(SkPath::Direction dir)1335 static const char* dir2string(SkPath::Direction dir) {
1336 static const char* gStr[] = {
1337 "unknown", "cw", "ccw"
1338 };
1339 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1340 return gStr[dir];
1341 }
1342
lpath_isNestedFillRects(lua_State * L)1343 static int lpath_isNestedFillRects(lua_State* L) {
1344 SkRect rects[2];
1345 SkPath::Direction dirs[2];
1346 bool pred = get_obj<SkPath>(L, 1)->isNestedFillRects(rects, dirs);
1347 int ret_count = 1;
1348 lua_pushboolean(L, pred);
1349 if (pred) {
1350 SkLua lua(L);
1351 lua.pushRect(rects[0]);
1352 lua.pushRect(rects[1]);
1353 lua_pushstring(L, dir2string(dirs[0]));
1354 lua_pushstring(L, dir2string(dirs[0]));
1355 ret_count += 4;
1356 }
1357 return ret_count;
1358 }
1359
lpath_countPoints(lua_State * L)1360 static int lpath_countPoints(lua_State* L) {
1361 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1362 return 1;
1363 }
1364
lpath_getVerbs(lua_State * L)1365 static int lpath_getVerbs(lua_State* L) {
1366 const SkPath* path = get_obj<SkPath>(L, 1);
1367 SkPath::Iter iter(*path, false);
1368 SkPoint pts[4];
1369
1370 lua_newtable(L);
1371
1372 bool done = false;
1373 int i = 0;
1374 do {
1375 switch (iter.next(pts)) {
1376 case SkPath::kMove_Verb:
1377 setarray_string(L, ++i, "move");
1378 break;
1379 case SkPath::kClose_Verb:
1380 setarray_string(L, ++i, "close");
1381 break;
1382 case SkPath::kLine_Verb:
1383 setarray_string(L, ++i, "line");
1384 break;
1385 case SkPath::kQuad_Verb:
1386 setarray_string(L, ++i, "quad");
1387 break;
1388 case SkPath::kConic_Verb:
1389 setarray_string(L, ++i, "conic");
1390 break;
1391 case SkPath::kCubic_Verb:
1392 setarray_string(L, ++i, "cubic");
1393 break;
1394 case SkPath::kDone_Verb:
1395 setarray_string(L, ++i, "done");
1396 done = true;
1397 break;
1398 }
1399 } while (!done);
1400
1401 return 1;
1402 }
1403
lpath_reset(lua_State * L)1404 static int lpath_reset(lua_State* L) {
1405 get_obj<SkPath>(L, 1)->reset();
1406 return 0;
1407 }
1408
lpath_moveTo(lua_State * L)1409 static int lpath_moveTo(lua_State* L) {
1410 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1411 return 0;
1412 }
1413
lpath_lineTo(lua_State * L)1414 static int lpath_lineTo(lua_State* L) {
1415 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1416 return 0;
1417 }
1418
lpath_quadTo(lua_State * L)1419 static int lpath_quadTo(lua_State* L) {
1420 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1421 lua2scalar(L, 4), lua2scalar(L, 5));
1422 return 0;
1423 }
1424
lpath_cubicTo(lua_State * L)1425 static int lpath_cubicTo(lua_State* L) {
1426 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1427 lua2scalar(L, 4), lua2scalar(L, 5),
1428 lua2scalar(L, 6), lua2scalar(L, 7));
1429 return 0;
1430 }
1431
lpath_close(lua_State * L)1432 static int lpath_close(lua_State* L) {
1433 get_obj<SkPath>(L, 1)->close();
1434 return 0;
1435 }
1436
lpath_gc(lua_State * L)1437 static int lpath_gc(lua_State* L) {
1438 get_obj<SkPath>(L, 1)->~SkPath();
1439 return 0;
1440 }
1441
1442 static const struct luaL_Reg gSkPath_Methods[] = {
1443 { "getBounds", lpath_getBounds },
1444 { "getFillType", lpath_getFillType },
1445 { "getSegmentTypes", lpath_getSegmentTypes },
1446 { "getVerbs", lpath_getVerbs },
1447 { "isConvex", lpath_isConvex },
1448 { "isEmpty", lpath_isEmpty },
1449 { "isRect", lpath_isRect },
1450 { "isNestedFillRects", lpath_isNestedFillRects },
1451 { "countPoints", lpath_countPoints },
1452 { "reset", lpath_reset },
1453 { "moveTo", lpath_moveTo },
1454 { "lineTo", lpath_lineTo },
1455 { "quadTo", lpath_quadTo },
1456 { "cubicTo", lpath_cubicTo },
1457 { "close", lpath_close },
1458 { "__gc", lpath_gc },
1459 { nullptr, nullptr }
1460 };
1461
1462 ///////////////////////////////////////////////////////////////////////////////
1463
rrect_type(const SkRRect & rr)1464 static const char* rrect_type(const SkRRect& rr) {
1465 switch (rr.getType()) {
1466 case SkRRect::kEmpty_Type: return "empty";
1467 case SkRRect::kRect_Type: return "rect";
1468 case SkRRect::kOval_Type: return "oval";
1469 case SkRRect::kSimple_Type: return "simple";
1470 case SkRRect::kNinePatch_Type: return "nine-patch";
1471 case SkRRect::kComplex_Type: return "complex";
1472 }
1473 SkDEBUGFAIL("never get here");
1474 return "";
1475 }
1476
lrrect_rect(lua_State * L)1477 static int lrrect_rect(lua_State* L) {
1478 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1479 return 1;
1480 }
1481
lrrect_type(lua_State * L)1482 static int lrrect_type(lua_State* L) {
1483 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1484 return 1;
1485 }
1486
lrrect_radii(lua_State * L)1487 static int lrrect_radii(lua_State* L) {
1488 int corner = SkToInt(lua_tointeger(L, 2));
1489 SkVector v;
1490 if (corner < 0 || corner > 3) {
1491 SkDebugf("bad corner index %d", corner);
1492 v.set(0, 0);
1493 } else {
1494 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1495 }
1496 lua_pushnumber(L, v.fX);
1497 lua_pushnumber(L, v.fY);
1498 return 2;
1499 }
1500
lrrect_gc(lua_State * L)1501 static int lrrect_gc(lua_State* L) {
1502 get_obj<SkRRect>(L, 1)->~SkRRect();
1503 return 0;
1504 }
1505
1506 static const struct luaL_Reg gSkRRect_Methods[] = {
1507 { "rect", lrrect_rect },
1508 { "type", lrrect_type },
1509 { "radii", lrrect_radii },
1510 { "__gc", lrrect_gc },
1511 { nullptr, nullptr }
1512 };
1513
1514 ///////////////////////////////////////////////////////////////////////////////
1515
limage_width(lua_State * L)1516 static int limage_width(lua_State* L) {
1517 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1518 return 1;
1519 }
1520
limage_height(lua_State * L)1521 static int limage_height(lua_State* L) {
1522 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1523 return 1;
1524 }
1525
limage_newShader(lua_State * L)1526 static int limage_newShader(lua_State* L) {
1527 SkTileMode tmode = SkTileMode::kClamp;
1528 const SkMatrix* localM = nullptr;
1529 push_ref(L, get_ref<SkImage>(L, 1)->makeShader(tmode, tmode, localM));
1530 return 1;
1531 }
1532
limage_gc(lua_State * L)1533 static int limage_gc(lua_State* L) {
1534 get_ref<SkImage>(L, 1)->unref();
1535 return 0;
1536 }
1537
1538 static const struct luaL_Reg gSkImage_Methods[] = {
1539 { "width", limage_width },
1540 { "height", limage_height },
1541 { "newShader", limage_newShader },
1542 { "__gc", limage_gc },
1543 { nullptr, nullptr }
1544 };
1545
1546 ///////////////////////////////////////////////////////////////////////////////
1547
lsurface_width(lua_State * L)1548 static int lsurface_width(lua_State* L) {
1549 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1550 return 1;
1551 }
1552
lsurface_height(lua_State * L)1553 static int lsurface_height(lua_State* L) {
1554 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1555 return 1;
1556 }
1557
lsurface_getCanvas(lua_State * L)1558 static int lsurface_getCanvas(lua_State* L) {
1559 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
1560 if (nullptr == canvas) {
1561 lua_pushnil(L);
1562 } else {
1563 push_ptr(L, canvas);
1564 // note: we don't unref canvas, since getCanvas did not ref it.
1565 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1566 // the real owner (the surface) go away, but still hold onto the canvas?
1567 // *really* we want to sort of ref the surface again, but have the native object
1568 // know that it is supposed to be treated as a canvas...
1569 }
1570 return 1;
1571 }
1572
lsurface_newImageSnapshot(lua_State * L)1573 static int lsurface_newImageSnapshot(lua_State* L) {
1574 sk_sp<SkImage> image = get_ref<SkSurface>(L, 1)->makeImageSnapshot();
1575 if (!image) {
1576 lua_pushnil(L);
1577 } else {
1578 push_ref(L, image);
1579 }
1580 return 1;
1581 }
1582
lsurface_newSurface(lua_State * L)1583 static int lsurface_newSurface(lua_State* L) {
1584 int width = lua2int_def(L, 2, 0);
1585 int height = lua2int_def(L, 3, 0);
1586 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1587 auto surface = get_ref<SkSurface>(L, 1)->makeSurface(info);
1588 if (nullptr == surface) {
1589 lua_pushnil(L);
1590 } else {
1591 push_ref(L, surface);
1592 }
1593 return 1;
1594 }
1595
lsurface_gc(lua_State * L)1596 static int lsurface_gc(lua_State* L) {
1597 get_ref<SkSurface>(L, 1)->unref();
1598 return 0;
1599 }
1600
1601 static const struct luaL_Reg gSkSurface_Methods[] = {
1602 { "width", lsurface_width },
1603 { "height", lsurface_height },
1604 { "getCanvas", lsurface_getCanvas },
1605 { "newImageSnapshot", lsurface_newImageSnapshot },
1606 { "newSurface", lsurface_newSurface },
1607 { "__gc", lsurface_gc },
1608 { nullptr, nullptr }
1609 };
1610
1611 ///////////////////////////////////////////////////////////////////////////////
1612
lpicturerecorder_beginRecording(lua_State * L)1613 static int lpicturerecorder_beginRecording(lua_State* L) {
1614 const SkScalar w = lua2scalar_def(L, 2, -1);
1615 const SkScalar h = lua2scalar_def(L, 3, -1);
1616 if (w <= 0 || h <= 0) {
1617 lua_pushnil(L);
1618 return 1;
1619 }
1620
1621 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
1622 if (nullptr == canvas) {
1623 lua_pushnil(L);
1624 return 1;
1625 }
1626
1627 push_ptr(L, canvas);
1628 return 1;
1629 }
1630
lpicturerecorder_getCanvas(lua_State * L)1631 static int lpicturerecorder_getCanvas(lua_State* L) {
1632 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
1633 if (nullptr == canvas) {
1634 lua_pushnil(L);
1635 return 1;
1636 }
1637 push_ptr(L, canvas);
1638 return 1;
1639 }
1640
lpicturerecorder_endRecording(lua_State * L)1641 static int lpicturerecorder_endRecording(lua_State* L) {
1642 sk_sp<SkPicture> pic = get_obj<SkPictureRecorder>(L, 1)->finishRecordingAsPicture();
1643 if (!pic) {
1644 lua_pushnil(L);
1645 return 1;
1646 }
1647 push_ref(L, std::move(pic));
1648 return 1;
1649 }
1650
lpicturerecorder_gc(lua_State * L)1651 static int lpicturerecorder_gc(lua_State* L) {
1652 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1653 return 0;
1654 }
1655
1656 static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1657 { "beginRecording", lpicturerecorder_beginRecording },
1658 { "getCanvas", lpicturerecorder_getCanvas },
1659 { "endRecording", lpicturerecorder_endRecording },
1660 { "__gc", lpicturerecorder_gc },
1661 { nullptr, nullptr }
1662 };
1663
1664 ///////////////////////////////////////////////////////////////////////////////
1665
lpicture_width(lua_State * L)1666 static int lpicture_width(lua_State* L) {
1667 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1668 return 1;
1669 }
1670
lpicture_height(lua_State * L)1671 static int lpicture_height(lua_State* L) {
1672 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1673 return 1;
1674 }
1675
lpicture_gc(lua_State * L)1676 static int lpicture_gc(lua_State* L) {
1677 get_ref<SkPicture>(L, 1)->unref();
1678 return 0;
1679 }
1680
1681 static const struct luaL_Reg gSkPicture_Methods[] = {
1682 { "width", lpicture_width },
1683 { "height", lpicture_height },
1684 { "__gc", lpicture_gc },
1685 { nullptr, nullptr }
1686 };
1687
1688 ///////////////////////////////////////////////////////////////////////////////
1689
ltextblob_bounds(lua_State * L)1690 static int ltextblob_bounds(lua_State* L) {
1691 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
1692 return 1;
1693 }
1694
ltextblob_gc(lua_State * L)1695 static int ltextblob_gc(lua_State* L) {
1696 SkSafeUnref(get_ref<SkTextBlob>(L, 1));
1697 return 0;
1698 }
1699
1700 static const struct luaL_Reg gSkTextBlob_Methods[] = {
1701 { "bounds", ltextblob_bounds },
1702 { "__gc", ltextblob_gc },
1703 { nullptr, nullptr }
1704 };
1705
1706 ///////////////////////////////////////////////////////////////////////////////
1707
ltypeface_getFamilyName(lua_State * L)1708 static int ltypeface_getFamilyName(lua_State* L) {
1709 SkString str;
1710 get_ref<SkTypeface>(L, 1)->getFamilyName(&str);
1711 lua_pushstring(L, str.c_str());
1712 return 1;
1713 }
1714
ltypeface_getStyle(lua_State * L)1715 static int ltypeface_getStyle(lua_State* L) {
1716 push_obj(L, get_ref<SkTypeface>(L, 1)->fontStyle());
1717 return 1;
1718 }
1719
ltypeface_gc(lua_State * L)1720 static int ltypeface_gc(lua_State* L) {
1721 SkSafeUnref(get_ref<SkTypeface>(L, 1));
1722 return 0;
1723 }
1724
1725 static const struct luaL_Reg gSkTypeface_Methods[] = {
1726 { "getFamilyName", ltypeface_getFamilyName },
1727 { "getStyle", ltypeface_getStyle },
1728 { "__gc", ltypeface_gc },
1729 { nullptr, nullptr }
1730 };
1731
1732 ///////////////////////////////////////////////////////////////////////////////
1733
lfontstyle_weight(lua_State * L)1734 static int lfontstyle_weight(lua_State* L) {
1735 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->weight());
1736 return 1;
1737 }
1738
lfontstyle_width(lua_State * L)1739 static int lfontstyle_width(lua_State* L) {
1740 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->width());
1741 return 1;
1742 }
1743
lfontstyle_slant(lua_State * L)1744 static int lfontstyle_slant(lua_State* L) {
1745 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->slant());
1746 return 1;
1747 }
1748
lfontstyle_gc(lua_State * L)1749 static int lfontstyle_gc(lua_State* L) {
1750 get_obj<SkFontStyle>(L, 1)->~SkFontStyle();
1751 return 0;
1752 }
1753
1754 static const struct luaL_Reg gSkFontStyle_Methods[] = {
1755 { "weight", lfontstyle_weight },
1756 { "width", lfontstyle_width },
1757 { "slant", lfontstyle_slant },
1758 { "__gc", lfontstyle_gc },
1759 { nullptr, nullptr }
1760 };
1761
1762 ///////////////////////////////////////////////////////////////////////////////
1763
1764 class AutoCallLua {
1765 public:
AutoCallLua(lua_State * L,const char func[],const char verb[])1766 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1767 lua_getglobal(L, func);
1768 if (!lua_isfunction(L, -1)) {
1769 int t = lua_type(L, -1);
1770 SkDebugf("--- expected function %d\n", t);
1771 }
1772
1773 lua_newtable(L);
1774 setfield_string(L, "verb", verb);
1775 }
1776
~AutoCallLua()1777 ~AutoCallLua() {
1778 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1779 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1780 }
1781 lua_settop(fL, -1);
1782 }
1783
1784 private:
1785 lua_State* fL;
1786 };
1787
1788 #define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1789
1790 ///////////////////////////////////////////////////////////////////////////////
1791
lsk_newDocumentPDF(lua_State * L)1792 static int lsk_newDocumentPDF(lua_State* L) {
1793 const char* filename = nullptr;
1794 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1795 filename = lua_tolstring(L, 1, nullptr);
1796 }
1797 if (!filename) {
1798 return 0;
1799 }
1800 auto file = skstd::make_unique<SkFILEWStream>(filename);
1801 if (!file->isValid()) {
1802 return 0;
1803 }
1804 auto doc = SkPDF::MakeDocument(file.get());
1805 if (!doc) {
1806 return 0;
1807 }
1808 push_ptr(L, new DocHolder{std::move(doc), std::move(file)});
1809 return 1;
1810 }
1811
lsk_newBlurImageFilter(lua_State * L)1812 static int lsk_newBlurImageFilter(lua_State* L) {
1813 SkScalar sigmaX = lua2scalar_def(L, 1, 0);
1814 SkScalar sigmaY = lua2scalar_def(L, 2, 0);
1815 sk_sp<SkImageFilter> imf(SkImageFilters::Blur(sigmaX, sigmaY, nullptr));
1816 if (!imf) {
1817 lua_pushnil(L);
1818 } else {
1819 push_ref(L, std::move(imf));
1820 }
1821 return 1;
1822 }
1823
lsk_newLinearGradient(lua_State * L)1824 static int lsk_newLinearGradient(lua_State* L) {
1825 SkScalar x0 = lua2scalar_def(L, 1, 0);
1826 SkScalar y0 = lua2scalar_def(L, 2, 0);
1827 SkColor c0 = lua2color(L, 3);
1828 SkScalar x1 = lua2scalar_def(L, 4, 0);
1829 SkScalar y1 = lua2scalar_def(L, 5, 0);
1830 SkColor c1 = lua2color(L, 6);
1831
1832 SkPoint pts[] = { { x0, y0 }, { x1, y1 } };
1833 SkColor colors[] = { c0, c1 };
1834 sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
1835 if (!s) {
1836 lua_pushnil(L);
1837 } else {
1838 push_ref(L, std::move(s));
1839 }
1840 return 1;
1841 }
1842
lsk_newMatrix(lua_State * L)1843 static int lsk_newMatrix(lua_State* L) {
1844 push_new<SkMatrix>(L)->reset();
1845 return 1;
1846 }
1847
lsk_newPaint(lua_State * L)1848 static int lsk_newPaint(lua_State* L) {
1849 push_new<SkPaint>(L);
1850 return 1;
1851 }
1852
lsk_newPath(lua_State * L)1853 static int lsk_newPath(lua_State* L) {
1854 push_new<SkPath>(L);
1855 return 1;
1856 }
1857
lsk_newPictureRecorder(lua_State * L)1858 static int lsk_newPictureRecorder(lua_State* L) {
1859 push_new<SkPictureRecorder>(L);
1860 return 1;
1861 }
1862
lsk_newRRect(lua_State * L)1863 static int lsk_newRRect(lua_State* L) {
1864 push_new<SkRRect>(L)->setEmpty();
1865 return 1;
1866 }
1867
1868 // Sk.newTextBlob(text, rect, paint)
lsk_newTextBlob(lua_State * L)1869 static int lsk_newTextBlob(lua_State* L) {
1870 const char* text = lua_tolstring(L, 1, nullptr);
1871 SkRect bounds;
1872 lua2rect(L, 2, &bounds);
1873
1874 std::unique_ptr<SkShaper> shaper = SkShaper::Make();
1875
1876 // TODO: restore this logic based on SkFont instead of SkPaint
1877 #if 0
1878 const SkPaint& paint = *get_obj<SkPaint>(L, 3);
1879 SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
1880 #else
1881 SkFont font;
1882 #endif
1883 SkTextBlobBuilderRunHandler builder(text, { bounds.left(), bounds.top() });
1884 shaper->shape(text, strlen(text), font, true, bounds.width(), &builder);
1885
1886 push_ref<SkTextBlob>(L, builder.makeBlob());
1887 SkLua(L).pushScalar(builder.endPoint().fY);
1888 return 2;
1889 }
1890
lsk_newTypeface(lua_State * L)1891 static int lsk_newTypeface(lua_State* L) {
1892 const char* name = nullptr;
1893 SkFontStyle style;
1894
1895 int count = lua_gettop(L);
1896 if (count > 0 && lua_isstring(L, 1)) {
1897 name = lua_tolstring(L, 1, nullptr);
1898 if (count > 1) {
1899 SkFontStyle* passedStyle = get_obj<SkFontStyle>(L, 2);
1900 if (passedStyle) {
1901 style = *passedStyle;
1902 }
1903 }
1904 }
1905
1906 sk_sp<SkTypeface> face(SkTypeface::MakeFromName(name, style));
1907 // SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
1908 if (nullptr == face) {
1909 face = SkTypeface::MakeDefault();
1910 }
1911 push_ref(L, std::move(face));
1912 return 1;
1913 }
1914
lsk_newFontStyle(lua_State * L)1915 static int lsk_newFontStyle(lua_State* L) {
1916 int count = lua_gettop(L);
1917 int weight = SkFontStyle::kNormal_Weight;
1918 int width = SkFontStyle::kNormal_Width;
1919 SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
1920 if (count >= 1 && lua_isnumber(L, 1)) {
1921 weight = lua_tointegerx(L, 1, nullptr);
1922 }
1923 if (count >= 2 && lua_isnumber(L, 2)) {
1924 width = lua_tointegerx(L, 2, nullptr);
1925 }
1926 if (count >= 3 && lua_isnumber(L, 3)) {
1927 slant = static_cast<SkFontStyle::Slant>(lua_tointegerx(L, 3, nullptr));
1928 }
1929 push_new<SkFontStyle>(L, weight, width, slant);
1930 return 1;
1931 }
1932
lsk_newRasterSurface(lua_State * L)1933 static int lsk_newRasterSurface(lua_State* L) {
1934 int width = lua2int_def(L, 1, 0);
1935 int height = lua2int_def(L, 2, 0);
1936 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1937 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
1938 auto surface = SkSurface::MakeRaster(info, &props);
1939 if (nullptr == surface) {
1940 lua_pushnil(L);
1941 } else {
1942 push_ref(L, surface);
1943 }
1944 return 1;
1945 }
1946
lsk_loadImage(lua_State * L)1947 static int lsk_loadImage(lua_State* L) {
1948 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1949 const char* name = lua_tolstring(L, 1, nullptr);
1950 sk_sp<SkData> data(SkData::MakeFromFileName(name));
1951 if (data) {
1952 auto image = SkImage::MakeFromEncoded(std::move(data));
1953 if (image) {
1954 push_ref(L, std::move(image));
1955 return 1;
1956 }
1957 }
1958 }
1959 return 0;
1960 }
1961
register_Sk(lua_State * L)1962 static void register_Sk(lua_State* L) {
1963 lua_newtable(L);
1964 lua_pushvalue(L, -1);
1965 lua_setglobal(L, "Sk");
1966 // the Sk table is still on top
1967
1968 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
1969 setfield_function(L, "loadImage", lsk_loadImage);
1970 setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
1971 setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
1972 setfield_function(L, "newMatrix", lsk_newMatrix);
1973 setfield_function(L, "newPaint", lsk_newPaint);
1974 setfield_function(L, "newPath", lsk_newPath);
1975 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
1976 setfield_function(L, "newRRect", lsk_newRRect);
1977 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
1978 setfield_function(L, "newTextBlob", lsk_newTextBlob);
1979 setfield_function(L, "newTypeface", lsk_newTypeface);
1980 setfield_function(L, "newFontStyle", lsk_newFontStyle);
1981 lua_pop(L, 1); // pop off the Sk table
1982 }
1983
1984 #define REG_CLASS(L, C) \
1985 do { \
1986 luaL_newmetatable(L, get_mtname<C>()); \
1987 lua_pushvalue(L, -1); \
1988 lua_setfield(L, -2, "__index"); \
1989 luaL_setfuncs(L, g##C##_Methods, 0); \
1990 lua_pop(L, 1); /* pop off the meta-table */ \
1991 } while (0)
1992
Load(lua_State * L)1993 void SkLua::Load(lua_State* L) {
1994 register_Sk(L);
1995 REG_CLASS(L, SkCanvas);
1996 REG_CLASS(L, SkColorFilter);
1997 REG_CLASS(L, DocHolder);
1998 REG_CLASS(L, SkFont);
1999 REG_CLASS(L, SkImage);
2000 REG_CLASS(L, SkImageFilter);
2001 REG_CLASS(L, SkMatrix);
2002 REG_CLASS(L, SkPaint);
2003 REG_CLASS(L, SkPath);
2004 REG_CLASS(L, SkPathEffect);
2005 REG_CLASS(L, SkPicture);
2006 REG_CLASS(L, SkPictureRecorder);
2007 REG_CLASS(L, SkRRect);
2008 REG_CLASS(L, SkShader);
2009 REG_CLASS(L, SkSurface);
2010 REG_CLASS(L, SkTextBlob);
2011 REG_CLASS(L, SkTypeface);
2012 REG_CLASS(L, SkFontStyle);
2013 }
2014
2015 extern "C" int luaopen_skia(lua_State* L);
luaopen_skia(lua_State * L)2016 extern "C" int luaopen_skia(lua_State* L) {
2017 SkLua::Load(L);
2018 return 0;
2019 }
2020