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 
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->setLTRB(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 
lpath_countPoints(lua_State * L)1335 static int lpath_countPoints(lua_State* L) {
1336     lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1337     return 1;
1338 }
1339 
lpath_getVerbs(lua_State * L)1340 static int lpath_getVerbs(lua_State* L) {
1341     const SkPath* path = get_obj<SkPath>(L, 1);
1342     SkPath::Iter iter(*path, false);
1343     SkPoint pts[4];
1344 
1345     lua_newtable(L);
1346 
1347     bool done = false;
1348     int i = 0;
1349     do {
1350         switch (iter.next(pts)) {
1351             case SkPath::kMove_Verb:
1352                 setarray_string(L, ++i, "move");
1353                 break;
1354             case SkPath::kClose_Verb:
1355                 setarray_string(L, ++i, "close");
1356                 break;
1357             case SkPath::kLine_Verb:
1358                 setarray_string(L, ++i, "line");
1359                 break;
1360             case SkPath::kQuad_Verb:
1361                 setarray_string(L, ++i, "quad");
1362                 break;
1363             case SkPath::kConic_Verb:
1364                 setarray_string(L, ++i, "conic");
1365                 break;
1366             case SkPath::kCubic_Verb:
1367                 setarray_string(L, ++i, "cubic");
1368                 break;
1369             case SkPath::kDone_Verb:
1370                 setarray_string(L, ++i, "done");
1371                 done = true;
1372                 break;
1373         }
1374     } while (!done);
1375 
1376     return 1;
1377 }
1378 
lpath_reset(lua_State * L)1379 static int lpath_reset(lua_State* L) {
1380     get_obj<SkPath>(L, 1)->reset();
1381     return 0;
1382 }
1383 
lpath_moveTo(lua_State * L)1384 static int lpath_moveTo(lua_State* L) {
1385     get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1386     return 0;
1387 }
1388 
lpath_lineTo(lua_State * L)1389 static int lpath_lineTo(lua_State* L) {
1390     get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1391     return 0;
1392 }
1393 
lpath_quadTo(lua_State * L)1394 static int lpath_quadTo(lua_State* L) {
1395     get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1396                                   lua2scalar(L, 4), lua2scalar(L, 5));
1397     return 0;
1398 }
1399 
lpath_cubicTo(lua_State * L)1400 static int lpath_cubicTo(lua_State* L) {
1401     get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1402                                    lua2scalar(L, 4), lua2scalar(L, 5),
1403                                    lua2scalar(L, 6), lua2scalar(L, 7));
1404     return 0;
1405 }
1406 
lpath_close(lua_State * L)1407 static int lpath_close(lua_State* L) {
1408     get_obj<SkPath>(L, 1)->close();
1409     return 0;
1410 }
1411 
lpath_gc(lua_State * L)1412 static int lpath_gc(lua_State* L) {
1413     get_obj<SkPath>(L, 1)->~SkPath();
1414     return 0;
1415 }
1416 
1417 static const struct luaL_Reg gSkPath_Methods[] = {
1418     { "getBounds", lpath_getBounds },
1419     { "getFillType", lpath_getFillType },
1420     { "getSegmentTypes", lpath_getSegmentTypes },
1421     { "getVerbs", lpath_getVerbs },
1422     { "isConvex", lpath_isConvex },
1423     { "isEmpty", lpath_isEmpty },
1424     { "isRect", lpath_isRect },
1425     { "countPoints", lpath_countPoints },
1426     { "reset", lpath_reset },
1427     { "moveTo", lpath_moveTo },
1428     { "lineTo", lpath_lineTo },
1429     { "quadTo", lpath_quadTo },
1430     { "cubicTo", lpath_cubicTo },
1431     { "close", lpath_close },
1432     { "__gc", lpath_gc },
1433     { nullptr, nullptr }
1434 };
1435 
1436 ///////////////////////////////////////////////////////////////////////////////
1437 
rrect_type(const SkRRect & rr)1438 static const char* rrect_type(const SkRRect& rr) {
1439     switch (rr.getType()) {
1440         case SkRRect::kEmpty_Type: return "empty";
1441         case SkRRect::kRect_Type: return "rect";
1442         case SkRRect::kOval_Type: return "oval";
1443         case SkRRect::kSimple_Type: return "simple";
1444         case SkRRect::kNinePatch_Type: return "nine-patch";
1445         case SkRRect::kComplex_Type: return "complex";
1446     }
1447     SkDEBUGFAIL("never get here");
1448     return "";
1449 }
1450 
lrrect_rect(lua_State * L)1451 static int lrrect_rect(lua_State* L) {
1452     SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1453     return 1;
1454 }
1455 
lrrect_type(lua_State * L)1456 static int lrrect_type(lua_State* L) {
1457     lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1458     return 1;
1459 }
1460 
lrrect_radii(lua_State * L)1461 static int lrrect_radii(lua_State* L) {
1462     int corner = SkToInt(lua_tointeger(L, 2));
1463     SkVector v;
1464     if (corner < 0 || corner > 3) {
1465         SkDebugf("bad corner index %d", corner);
1466         v.set(0, 0);
1467     } else {
1468         v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1469     }
1470     lua_pushnumber(L, v.fX);
1471     lua_pushnumber(L, v.fY);
1472     return 2;
1473 }
1474 
lrrect_gc(lua_State * L)1475 static int lrrect_gc(lua_State* L) {
1476     get_obj<SkRRect>(L, 1)->~SkRRect();
1477     return 0;
1478 }
1479 
1480 static const struct luaL_Reg gSkRRect_Methods[] = {
1481     { "rect", lrrect_rect },
1482     { "type", lrrect_type },
1483     { "radii", lrrect_radii },
1484     { "__gc", lrrect_gc },
1485     { nullptr, nullptr }
1486 };
1487 
1488 ///////////////////////////////////////////////////////////////////////////////
1489 
limage_width(lua_State * L)1490 static int limage_width(lua_State* L) {
1491     lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1492     return 1;
1493 }
1494 
limage_height(lua_State * L)1495 static int limage_height(lua_State* L) {
1496     lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1497     return 1;
1498 }
1499 
limage_newShader(lua_State * L)1500 static int limage_newShader(lua_State* L) {
1501     SkTileMode tmode = SkTileMode::kClamp;
1502     const SkMatrix* localM = nullptr;
1503     push_ref(L, get_ref<SkImage>(L, 1)->makeShader(tmode, tmode, localM));
1504     return 1;
1505 }
1506 
limage_gc(lua_State * L)1507 static int limage_gc(lua_State* L) {
1508     get_ref<SkImage>(L, 1)->unref();
1509     return 0;
1510 }
1511 
1512 static const struct luaL_Reg gSkImage_Methods[] = {
1513     { "width", limage_width },
1514     { "height", limage_height },
1515     { "newShader", limage_newShader },
1516     { "__gc", limage_gc },
1517     { nullptr, nullptr }
1518 };
1519 
1520 ///////////////////////////////////////////////////////////////////////////////
1521 
lsurface_width(lua_State * L)1522 static int lsurface_width(lua_State* L) {
1523     lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1524     return 1;
1525 }
1526 
lsurface_height(lua_State * L)1527 static int lsurface_height(lua_State* L) {
1528     lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1529     return 1;
1530 }
1531 
lsurface_getCanvas(lua_State * L)1532 static int lsurface_getCanvas(lua_State* L) {
1533     SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
1534     if (nullptr == canvas) {
1535         lua_pushnil(L);
1536     } else {
1537         push_ptr(L, canvas);
1538         // note: we don't unref canvas, since getCanvas did not ref it.
1539         // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1540         // the real owner (the surface) go away, but still hold onto the canvas?
1541         // *really* we want to sort of ref the surface again, but have the native object
1542         // know that it is supposed to be treated as a canvas...
1543     }
1544     return 1;
1545 }
1546 
lsurface_newImageSnapshot(lua_State * L)1547 static int lsurface_newImageSnapshot(lua_State* L) {
1548     sk_sp<SkImage> image = get_ref<SkSurface>(L, 1)->makeImageSnapshot();
1549     if (!image) {
1550         lua_pushnil(L);
1551     } else {
1552         push_ref(L, image);
1553     }
1554     return 1;
1555 }
1556 
lsurface_newSurface(lua_State * L)1557 static int lsurface_newSurface(lua_State* L) {
1558     int width = lua2int_def(L, 2, 0);
1559     int height = lua2int_def(L, 3, 0);
1560     SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1561     auto surface = get_ref<SkSurface>(L, 1)->makeSurface(info);
1562     if (nullptr == surface) {
1563         lua_pushnil(L);
1564     } else {
1565         push_ref(L, surface);
1566     }
1567     return 1;
1568 }
1569 
lsurface_gc(lua_State * L)1570 static int lsurface_gc(lua_State* L) {
1571     get_ref<SkSurface>(L, 1)->unref();
1572     return 0;
1573 }
1574 
1575 static const struct luaL_Reg gSkSurface_Methods[] = {
1576     { "width", lsurface_width },
1577     { "height", lsurface_height },
1578     { "getCanvas", lsurface_getCanvas },
1579     { "newImageSnapshot", lsurface_newImageSnapshot },
1580     { "newSurface", lsurface_newSurface },
1581     { "__gc", lsurface_gc },
1582     { nullptr, nullptr }
1583 };
1584 
1585 ///////////////////////////////////////////////////////////////////////////////
1586 
lpicturerecorder_beginRecording(lua_State * L)1587 static int lpicturerecorder_beginRecording(lua_State* L) {
1588     const SkScalar w = lua2scalar_def(L, 2, -1);
1589     const SkScalar h = lua2scalar_def(L, 3, -1);
1590     if (w <= 0 || h <= 0) {
1591         lua_pushnil(L);
1592         return 1;
1593     }
1594 
1595     SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
1596     if (nullptr == canvas) {
1597         lua_pushnil(L);
1598         return 1;
1599     }
1600 
1601     push_ptr(L, canvas);
1602     return 1;
1603 }
1604 
lpicturerecorder_getCanvas(lua_State * L)1605 static int lpicturerecorder_getCanvas(lua_State* L) {
1606     SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
1607     if (nullptr == canvas) {
1608         lua_pushnil(L);
1609         return 1;
1610     }
1611     push_ptr(L, canvas);
1612     return 1;
1613 }
1614 
lpicturerecorder_endRecording(lua_State * L)1615 static int lpicturerecorder_endRecording(lua_State* L) {
1616     sk_sp<SkPicture> pic = get_obj<SkPictureRecorder>(L, 1)->finishRecordingAsPicture();
1617     if (!pic) {
1618         lua_pushnil(L);
1619         return 1;
1620     }
1621     push_ref(L, std::move(pic));
1622     return 1;
1623 }
1624 
lpicturerecorder_gc(lua_State * L)1625 static int lpicturerecorder_gc(lua_State* L) {
1626     get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1627     return 0;
1628 }
1629 
1630 static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1631     { "beginRecording", lpicturerecorder_beginRecording },
1632     { "getCanvas", lpicturerecorder_getCanvas },
1633     { "endRecording", lpicturerecorder_endRecording },
1634     { "__gc", lpicturerecorder_gc },
1635     { nullptr, nullptr }
1636 };
1637 
1638 ///////////////////////////////////////////////////////////////////////////////
1639 
lpicture_width(lua_State * L)1640 static int lpicture_width(lua_State* L) {
1641     lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1642     return 1;
1643 }
1644 
lpicture_height(lua_State * L)1645 static int lpicture_height(lua_State* L) {
1646     lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1647     return 1;
1648 }
1649 
lpicture_gc(lua_State * L)1650 static int lpicture_gc(lua_State* L) {
1651     get_ref<SkPicture>(L, 1)->unref();
1652     return 0;
1653 }
1654 
1655 static const struct luaL_Reg gSkPicture_Methods[] = {
1656     { "width", lpicture_width },
1657     { "height", lpicture_height },
1658     { "__gc", lpicture_gc },
1659     { nullptr, nullptr }
1660 };
1661 
1662 ///////////////////////////////////////////////////////////////////////////////
1663 
ltextblob_bounds(lua_State * L)1664 static int ltextblob_bounds(lua_State* L) {
1665     SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
1666     return 1;
1667 }
1668 
ltextblob_gc(lua_State * L)1669 static int ltextblob_gc(lua_State* L) {
1670     SkSafeUnref(get_ref<SkTextBlob>(L, 1));
1671     return 0;
1672 }
1673 
1674 static const struct luaL_Reg gSkTextBlob_Methods[] = {
1675     { "bounds", ltextblob_bounds },
1676     { "__gc", ltextblob_gc },
1677     { nullptr, nullptr }
1678 };
1679 
1680 ///////////////////////////////////////////////////////////////////////////////
1681 
ltypeface_getFamilyName(lua_State * L)1682 static int ltypeface_getFamilyName(lua_State* L) {
1683     SkString str;
1684     get_ref<SkTypeface>(L, 1)->getFamilyName(&str);
1685     lua_pushstring(L, str.c_str());
1686     return 1;
1687 }
1688 
ltypeface_getStyle(lua_State * L)1689 static int ltypeface_getStyle(lua_State* L) {
1690     push_obj(L, get_ref<SkTypeface>(L, 1)->fontStyle());
1691     return 1;
1692 }
1693 
ltypeface_gc(lua_State * L)1694 static int ltypeface_gc(lua_State* L) {
1695     SkSafeUnref(get_ref<SkTypeface>(L, 1));
1696     return 0;
1697 }
1698 
1699 static const struct luaL_Reg gSkTypeface_Methods[] = {
1700     { "getFamilyName", ltypeface_getFamilyName },
1701     { "getStyle", ltypeface_getStyle },
1702     { "__gc", ltypeface_gc },
1703     { nullptr, nullptr }
1704 };
1705 
1706 ///////////////////////////////////////////////////////////////////////////////
1707 
lfontstyle_weight(lua_State * L)1708 static int lfontstyle_weight(lua_State* L) {
1709     lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->weight());
1710     return 1;
1711 }
1712 
lfontstyle_width(lua_State * L)1713 static int lfontstyle_width(lua_State* L) {
1714     lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->width());
1715     return 1;
1716 }
1717 
lfontstyle_slant(lua_State * L)1718 static int lfontstyle_slant(lua_State* L) {
1719     lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->slant());
1720     return 1;
1721 }
1722 
lfontstyle_gc(lua_State * L)1723 static int lfontstyle_gc(lua_State* L) {
1724     get_obj<SkFontStyle>(L, 1)->~SkFontStyle();
1725     return 0;
1726 }
1727 
1728 static const struct luaL_Reg gSkFontStyle_Methods[] = {
1729     { "weight", lfontstyle_weight },
1730     { "width", lfontstyle_width },
1731     { "slant", lfontstyle_slant },
1732     { "__gc", lfontstyle_gc },
1733     { nullptr, nullptr }
1734 };
1735 
1736 ///////////////////////////////////////////////////////////////////////////////
1737 
1738 class AutoCallLua {
1739 public:
AutoCallLua(lua_State * L,const char func[],const char verb[])1740     AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1741         lua_getglobal(L, func);
1742         if (!lua_isfunction(L, -1)) {
1743             int t = lua_type(L, -1);
1744             SkDebugf("--- expected function %d\n", t);
1745         }
1746 
1747         lua_newtable(L);
1748         setfield_string(L, "verb", verb);
1749     }
1750 
~AutoCallLua()1751     ~AutoCallLua() {
1752         if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1753             SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1754         }
1755         lua_settop(fL, -1);
1756     }
1757 
1758 private:
1759     lua_State* fL;
1760 };
1761 
1762 #define AUTO_LUA(verb)  AutoCallLua acl(fL, fFunc.c_str(), verb)
1763 
1764 ///////////////////////////////////////////////////////////////////////////////
1765 
lsk_newDocumentPDF(lua_State * L)1766 static int lsk_newDocumentPDF(lua_State* L) {
1767     const char* filename = nullptr;
1768     if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1769         filename = lua_tolstring(L, 1, nullptr);
1770     }
1771     if (!filename) {
1772         return 0;
1773     }
1774     auto file = skstd::make_unique<SkFILEWStream>(filename);
1775     if (!file->isValid()) {
1776         return 0;
1777     }
1778     auto doc = SkPDF::MakeDocument(file.get());
1779     if (!doc) {
1780         return 0;
1781     }
1782     push_ptr(L, new DocHolder{std::move(doc), std::move(file)});
1783     return 1;
1784 }
1785 
lsk_newBlurImageFilter(lua_State * L)1786 static int lsk_newBlurImageFilter(lua_State* L) {
1787     SkScalar sigmaX = lua2scalar_def(L, 1, 0);
1788     SkScalar sigmaY = lua2scalar_def(L, 2, 0);
1789     sk_sp<SkImageFilter> imf(SkImageFilters::Blur(sigmaX, sigmaY, nullptr));
1790     if (!imf) {
1791         lua_pushnil(L);
1792     } else {
1793         push_ref(L, std::move(imf));
1794     }
1795     return 1;
1796 }
1797 
lsk_newLinearGradient(lua_State * L)1798 static int lsk_newLinearGradient(lua_State* L) {
1799     SkScalar x0 = lua2scalar_def(L, 1, 0);
1800     SkScalar y0 = lua2scalar_def(L, 2, 0);
1801     SkColor  c0 = lua2color(L, 3);
1802     SkScalar x1 = lua2scalar_def(L, 4, 0);
1803     SkScalar y1 = lua2scalar_def(L, 5, 0);
1804     SkColor  c1 = lua2color(L, 6);
1805 
1806     SkPoint pts[] = { { x0, y0 }, { x1, y1 } };
1807     SkColor colors[] = { c0, c1 };
1808     sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
1809     if (!s) {
1810         lua_pushnil(L);
1811     } else {
1812         push_ref(L, std::move(s));
1813     }
1814     return 1;
1815 }
1816 
lsk_newMatrix(lua_State * L)1817 static int lsk_newMatrix(lua_State* L) {
1818     push_new<SkMatrix>(L)->reset();
1819     return 1;
1820 }
1821 
lsk_newPaint(lua_State * L)1822 static int lsk_newPaint(lua_State* L) {
1823     push_new<SkPaint>(L);
1824     return 1;
1825 }
1826 
lsk_newPath(lua_State * L)1827 static int lsk_newPath(lua_State* L) {
1828     push_new<SkPath>(L);
1829     return 1;
1830 }
1831 
lsk_newPictureRecorder(lua_State * L)1832 static int lsk_newPictureRecorder(lua_State* L) {
1833     push_new<SkPictureRecorder>(L);
1834     return 1;
1835 }
1836 
lsk_newRRect(lua_State * L)1837 static int lsk_newRRect(lua_State* L) {
1838     push_new<SkRRect>(L)->setEmpty();
1839     return 1;
1840 }
1841 
1842 // Sk.newTextBlob(text, rect, paint)
lsk_newTextBlob(lua_State * L)1843 static int lsk_newTextBlob(lua_State* L) {
1844     const char* text = lua_tolstring(L, 1, nullptr);
1845     SkRect bounds;
1846     lua2rect(L, 2, &bounds);
1847 
1848     std::unique_ptr<SkShaper> shaper = SkShaper::Make();
1849 
1850     // TODO: restore this logic based on SkFont instead of SkPaint
1851 #if 0
1852     const SkPaint& paint = *get_obj<SkPaint>(L, 3);
1853     SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
1854 #else
1855     SkFont font;
1856 #endif
1857     SkTextBlobBuilderRunHandler builder(text, { bounds.left(), bounds.top() });
1858     shaper->shape(text, strlen(text), font, true, bounds.width(), &builder);
1859 
1860     push_ref<SkTextBlob>(L, builder.makeBlob());
1861     SkLua(L).pushScalar(builder.endPoint().fY);
1862     return 2;
1863 }
1864 
lsk_newTypeface(lua_State * L)1865 static int lsk_newTypeface(lua_State* L) {
1866     const char* name = nullptr;
1867     SkFontStyle style;
1868 
1869     int count = lua_gettop(L);
1870     if (count > 0 && lua_isstring(L, 1)) {
1871         name = lua_tolstring(L, 1, nullptr);
1872         if (count > 1) {
1873             SkFontStyle* passedStyle = get_obj<SkFontStyle>(L, 2);
1874             if (passedStyle) {
1875                 style = *passedStyle;
1876             }
1877         }
1878     }
1879 
1880     sk_sp<SkTypeface> face(SkTypeface::MakeFromName(name, style));
1881 //    SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
1882     if (nullptr == face) {
1883         face = SkTypeface::MakeDefault();
1884     }
1885     push_ref(L, std::move(face));
1886     return 1;
1887 }
1888 
lsk_newFontStyle(lua_State * L)1889 static int lsk_newFontStyle(lua_State* L) {
1890     int count = lua_gettop(L);
1891     int weight = SkFontStyle::kNormal_Weight;
1892     int width = SkFontStyle::kNormal_Width;
1893     SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
1894     if (count >= 1 && lua_isnumber(L, 1)) {
1895         weight = lua_tointegerx(L, 1, nullptr);
1896     }
1897     if (count >= 2 && lua_isnumber(L, 2)) {
1898         width = lua_tointegerx(L, 2, nullptr);
1899     }
1900     if (count >= 3 && lua_isnumber(L, 3)) {
1901         slant = static_cast<SkFontStyle::Slant>(lua_tointegerx(L, 3, nullptr));
1902     }
1903     push_new<SkFontStyle>(L, weight, width, slant);
1904     return 1;
1905 }
1906 
lsk_newRasterSurface(lua_State * L)1907 static int lsk_newRasterSurface(lua_State* L) {
1908     int width = lua2int_def(L, 1, 0);
1909     int height = lua2int_def(L, 2, 0);
1910     SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1911     SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
1912     auto surface = SkSurface::MakeRaster(info, &props);
1913     if (nullptr == surface) {
1914         lua_pushnil(L);
1915     } else {
1916         push_ref(L, surface);
1917     }
1918     return 1;
1919 }
1920 
lsk_loadImage(lua_State * L)1921 static int lsk_loadImage(lua_State* L) {
1922     if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1923         const char* name = lua_tolstring(L, 1, nullptr);
1924         sk_sp<SkData> data(SkData::MakeFromFileName(name));
1925         if (data) {
1926             auto image = SkImage::MakeFromEncoded(std::move(data));
1927             if (image) {
1928                 push_ref(L, std::move(image));
1929                 return 1;
1930             }
1931         }
1932     }
1933     return 0;
1934 }
1935 
register_Sk(lua_State * L)1936 static void register_Sk(lua_State* L) {
1937     lua_newtable(L);
1938     lua_pushvalue(L, -1);
1939     lua_setglobal(L, "Sk");
1940     // the Sk table is still on top
1941 
1942     setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
1943     setfield_function(L, "loadImage", lsk_loadImage);
1944     setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
1945     setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
1946     setfield_function(L, "newMatrix", lsk_newMatrix);
1947     setfield_function(L, "newPaint", lsk_newPaint);
1948     setfield_function(L, "newPath", lsk_newPath);
1949     setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
1950     setfield_function(L, "newRRect", lsk_newRRect);
1951     setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
1952     setfield_function(L, "newTextBlob", lsk_newTextBlob);
1953     setfield_function(L, "newTypeface", lsk_newTypeface);
1954     setfield_function(L, "newFontStyle", lsk_newFontStyle);
1955     lua_pop(L, 1);  // pop off the Sk table
1956 }
1957 
1958 #define REG_CLASS(L, C)                             \
1959     do {                                            \
1960         luaL_newmetatable(L, get_mtname<C>());      \
1961         lua_pushvalue(L, -1);                       \
1962         lua_setfield(L, -2, "__index");             \
1963         luaL_setfuncs(L, g##C##_Methods, 0);        \
1964         lua_pop(L, 1); /* pop off the meta-table */ \
1965     } while (0)
1966 
Load(lua_State * L)1967 void SkLua::Load(lua_State* L) {
1968     register_Sk(L);
1969     REG_CLASS(L, SkCanvas);
1970     REG_CLASS(L, SkColorFilter);
1971     REG_CLASS(L, DocHolder);
1972     REG_CLASS(L, SkFont);
1973     REG_CLASS(L, SkImage);
1974     REG_CLASS(L, SkImageFilter);
1975     REG_CLASS(L, SkMatrix);
1976     REG_CLASS(L, SkPaint);
1977     REG_CLASS(L, SkPath);
1978     REG_CLASS(L, SkPathEffect);
1979     REG_CLASS(L, SkPicture);
1980     REG_CLASS(L, SkPictureRecorder);
1981     REG_CLASS(L, SkRRect);
1982     REG_CLASS(L, SkShader);
1983     REG_CLASS(L, SkSurface);
1984     REG_CLASS(L, SkTextBlob);
1985     REG_CLASS(L, SkTypeface);
1986     REG_CLASS(L, SkFontStyle);
1987 }
1988 
1989 extern "C" int luaopen_skia(lua_State* L);
luaopen_skia(lua_State * L)1990 extern "C" int luaopen_skia(lua_State* L) {
1991     SkLua::Load(L);
1992     return 0;
1993 }
1994