blob: a2234565cbca7a6d7091cd0b98c8520e9645d33f [file] [log] [blame]
reed@google.com74ce6f02013-05-22 15:13:18 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkLua.h"
bsalomon@google.com4ebe3822014-02-26 20:22:32 +00009
10#if SK_SUPPORT_GPU
11#include "GrReducedClip.h"
12#endif
13
reed468b1812014-10-19 11:42:54 -070014#include "SkBlurImageFilter.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000015#include "SkCanvas.h"
reed22a517f2015-12-04 20:45:59 -080016#include "SkColorFilter.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000017#include "SkData.h"
mike@reedtribe.orgfb858242013-06-08 16:39:44 +000018#include "SkDocument.h"
reed9fbc3f32014-10-21 07:12:58 -070019#include "SkGradientShader.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000020#include "SkImage.h"
21#include "SkMatrix.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000022#include "SkPaint.h"
23#include "SkPath.h"
reed96affcd2014-10-13 12:38:04 -070024#include "SkPictureRecorder.h"
reed@google.com5fdc9832013-07-24 15:47:52 +000025#include "SkPixelRef.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000026#include "SkRRect.h"
27#include "SkString.h"
reed485557f2014-10-12 10:36:47 -070028#include "SkSurface.h"
fmalitab7425172014-08-26 07:56:44 -070029#include "SkTextBlob.h"
reed@google.come3823fd2013-05-30 18:55:14 +000030#include "SkTypeface.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000031
32extern "C" {
reed@google.com3597b732013-05-22 20:12:50 +000033 #include "lua.h"
34 #include "lualib.h"
35 #include "lauxlib.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000036}
37
reed@google.comfd345872013-05-22 20:53:42 +000038// return the metatable name for a given class
reed@google.com3597b732013-05-22 20:12:50 +000039template <typename T> const char* get_mtname();
reed@google.comfd345872013-05-22 20:53:42 +000040#define DEF_MTNAME(T) \
41 template <> const char* get_mtname<T>() { \
42 return #T "_LuaMetaTableName"; \
43 }
44
45DEF_MTNAME(SkCanvas)
reed22a517f2015-12-04 20:45:59 -080046DEF_MTNAME(SkColorFilter)
mike@reedtribe.orgfb858242013-06-08 16:39:44 +000047DEF_MTNAME(SkDocument)
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000048DEF_MTNAME(SkImage)
reed468b1812014-10-19 11:42:54 -070049DEF_MTNAME(SkImageFilter)
reed@google.comfd345872013-05-22 20:53:42 +000050DEF_MTNAME(SkMatrix)
51DEF_MTNAME(SkRRect)
52DEF_MTNAME(SkPath)
53DEF_MTNAME(SkPaint)
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +000054DEF_MTNAME(SkPathEffect)
reed96affcd2014-10-13 12:38:04 -070055DEF_MTNAME(SkPicture)
56DEF_MTNAME(SkPictureRecorder)
reed@google.com5fdc9832013-07-24 15:47:52 +000057DEF_MTNAME(SkShader)
reed485557f2014-10-12 10:36:47 -070058DEF_MTNAME(SkSurface)
fmalitab7425172014-08-26 07:56:44 -070059DEF_MTNAME(SkTextBlob)
mike@reedtribe.orge6469f12013-06-08 03:15:47 +000060DEF_MTNAME(SkTypeface)
reed@google.com74ce6f02013-05-22 15:13:18 +000061
reed@google.com3597b732013-05-22 20:12:50 +000062template <typename T> T* push_new(lua_State* L) {
63 T* addr = (T*)lua_newuserdata(L, sizeof(T));
64 new (addr) T;
65 luaL_getmetatable(L, get_mtname<T>());
66 lua_setmetatable(L, -2);
67 return addr;
68}
reed@google.com74ce6f02013-05-22 15:13:18 +000069
70template <typename T> void push_obj(lua_State* L, const T& obj) {
71 new (lua_newuserdata(L, sizeof(T))) T(obj);
reed@google.com3597b732013-05-22 20:12:50 +000072 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000073 lua_setmetatable(L, -2);
74}
75
reed9fbc3f32014-10-21 07:12:58 -070076template <typename T> T* push_ref(lua_State* L, T* ref) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +000077 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
reed@google.com3597b732013-05-22 20:12:50 +000078 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000079 lua_setmetatable(L, -2);
reed9fbc3f32014-10-21 07:12:58 -070080 return ref;
reed@google.com74ce6f02013-05-22 15:13:18 +000081}
82
reed2ad1aa62016-03-09 09:50:50 -080083template <typename T> void push_ref(lua_State* L, sk_sp<T> sp) {
84 *(T**)lua_newuserdata(L, sizeof(T*)) = sp.release();
85 luaL_getmetatable(L, get_mtname<T>());
86 lua_setmetatable(L, -2);
87}
88
reed@google.com74ce6f02013-05-22 15:13:18 +000089template <typename T> T* get_ref(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +000090 return *(T**)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000091}
92
93template <typename T> T* get_obj(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +000094 return (T*)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000095}
96
reed@google.com88c9ec92013-05-22 15:43:21 +000097static bool lua2bool(lua_State* L, int index) {
98 return !!lua_toboolean(L, index);
99}
100
reed@google.com74ce6f02013-05-22 15:13:18 +0000101///////////////////////////////////////////////////////////////////////////////
102
reed@google.com3597b732013-05-22 20:12:50 +0000103SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
104 fL = luaL_newstate();
105 luaL_openlibs(fL);
106 SkLua::Load(fL);
107}
108
109SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
110
111SkLua::~SkLua() {
112 if (fWeOwnL) {
113 if (fTermCode.size() > 0) {
114 lua_getglobal(fL, fTermCode.c_str());
115 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
116 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
117 }
118 }
119 lua_close(fL);
120 }
121}
122
123bool SkLua::runCode(const char code[]) {
124 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
125 if (err) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000126 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
reed@google.com3597b732013-05-22 20:12:50 +0000127 return false;
128 }
129 return true;
130}
131
132bool SkLua::runCode(const void* code, size_t size) {
133 SkString str((const char*)code, size);
134 return this->runCode(str.c_str());
135}
136
137///////////////////////////////////////////////////////////////////////////////
138
139#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
140
reed@google.com29563872013-07-10 21:23:49 +0000141static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
142 if (pred) {
143 lua_pushboolean(L, true);
144 lua_setfield(L, -2, key);
145 }
146}
147
reed@google.com74ce6f02013-05-22 15:13:18 +0000148static void setfield_string(lua_State* L, const char key[], const char value[]) {
149 lua_pushstring(L, value);
150 lua_setfield(L, -2, key);
151}
152
153static void setfield_number(lua_State* L, const char key[], double value) {
154 lua_pushnumber(L, value);
155 lua_setfield(L, -2, key);
156}
157
humper@google.com2815c192013-07-10 22:42:30 +0000158static void setfield_boolean(lua_State* L, const char key[], bool value) {
159 lua_pushboolean(L, value);
160 lua_setfield(L, -2, key);
161}
162
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000163static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
164 setfield_number(L, key, SkScalarToLua(value));
165}
166
reed@google.com3597b732013-05-22 20:12:50 +0000167static void setfield_function(lua_State* L,
168 const char key[], lua_CFunction value) {
169 lua_pushcfunction(L, value);
170 lua_setfield(L, -2, key);
reed@google.com74ce6f02013-05-22 15:13:18 +0000171}
172
reed7a72c672014-11-07 10:23:55 -0800173static int lua2int_def(lua_State* L, int index, int defaultValue) {
174 if (lua_isnumber(L, index)) {
175 return (int)lua_tonumber(L, index);
176 } else {
177 return defaultValue;
178 }
179}
180
181static SkScalar lua2scalar(lua_State* L, int index) {
182 SkASSERT(lua_isnumber(L, index));
183 return SkLuaToScalar(lua_tonumber(L, index));
184}
185
186static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
187 if (lua_isnumber(L, index)) {
188 return SkLuaToScalar(lua_tonumber(L, index));
189 } else {
190 return defaultValue;
191 }
192}
193
194static SkScalar getarray_scalar(lua_State* L, int stackIndex, int arrayIndex) {
195 SkASSERT(lua_istable(L, stackIndex));
196 lua_rawgeti(L, stackIndex, arrayIndex);
mtklein8aacf202014-12-18 13:29:54 -0800197
reed7a72c672014-11-07 10:23:55 -0800198 SkScalar value = lua2scalar(L, -1);
199 lua_pop(L, 1);
200 return value;
201}
202
203static void getarray_scalars(lua_State* L, int stackIndex, SkScalar dst[], int count) {
204 for (int i = 0; i < count; ++i) {
205 dst[i] = getarray_scalar(L, stackIndex, i + 1);
206 }
207}
208
209static void getarray_points(lua_State* L, int stackIndex, SkPoint pts[], int count) {
210 getarray_scalars(L, stackIndex, &pts[0].fX, count * 2);
211}
212
reed@google.come3823fd2013-05-30 18:55:14 +0000213static void setarray_number(lua_State* L, int index, double value) {
214 lua_pushnumber(L, value);
215 lua_rawseti(L, -2, index);
216}
217
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000218static void setarray_scalar(lua_State* L, int index, SkScalar value) {
219 setarray_number(L, index, SkScalarToLua(value));
220}
221
hstern0b401ce2016-08-02 09:17:59 -0700222static void setarray_string(lua_State* L, int index, const char str[]) {
223 lua_pushstring(L, str);
224 lua_rawseti(L, -2, index);
225}
226
reed@google.com74ce6f02013-05-22 15:13:18 +0000227void SkLua::pushBool(bool value, const char key[]) {
228 lua_pushboolean(fL, value);
229 CHECK_SETFIELD(key);
230}
231
232void SkLua::pushString(const char str[], const char key[]) {
233 lua_pushstring(fL, str);
234 CHECK_SETFIELD(key);
235}
236
reed@google.come3823fd2013-05-30 18:55:14 +0000237void SkLua::pushString(const char str[], size_t length, const char key[]) {
238 // TODO: how to do this w/o making a copy?
239 SkString s(str, length);
240 lua_pushstring(fL, s.c_str());
241 CHECK_SETFIELD(key);
242}
243
reed@google.com74ce6f02013-05-22 15:13:18 +0000244void SkLua::pushString(const SkString& str, const char key[]) {
245 lua_pushstring(fL, str.c_str());
246 CHECK_SETFIELD(key);
247}
248
249void SkLua::pushColor(SkColor color, const char key[]) {
250 lua_newtable(fL);
251 setfield_number(fL, "a", SkColorGetA(color) / 255.0);
252 setfield_number(fL, "r", SkColorGetR(color) / 255.0);
253 setfield_number(fL, "g", SkColorGetG(color) / 255.0);
254 setfield_number(fL, "b", SkColorGetB(color) / 255.0);
255 CHECK_SETFIELD(key);
256}
257
reed@google.come3823fd2013-05-30 18:55:14 +0000258void SkLua::pushU32(uint32_t value, const char key[]) {
259 lua_pushnumber(fL, (double)value);
260 CHECK_SETFIELD(key);
261}
262
reed@google.com74ce6f02013-05-22 15:13:18 +0000263void SkLua::pushScalar(SkScalar value, const char key[]) {
264 lua_pushnumber(fL, SkScalarToLua(value));
265 CHECK_SETFIELD(key);
266}
267
reed@google.come3823fd2013-05-30 18:55:14 +0000268void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
269 lua_newtable(fL);
270 for (int i = 0; i < count; ++i) {
271 // make it base-1 to match lua convention
272 setarray_number(fL, i + 1, (double)array[i]);
273 }
274 CHECK_SETFIELD(key);
275}
276
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000277void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
278 lua_newtable(fL);
279 for (int i = 0; i < count; ++i) {
280 // make it base-1 to match lua convention
281 lua_newtable(fL);
282 this->pushScalar(array[i].fX, "x");
283 this->pushScalar(array[i].fY, "y");
284 lua_rawseti(fL, -2, i + 1);
285 }
286 CHECK_SETFIELD(key);
287}
288
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000289void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
290 lua_newtable(fL);
291 for (int i = 0; i < count; ++i) {
292 // make it base-1 to match lua convention
293 setarray_scalar(fL, i + 1, array[i]);
294 }
295 CHECK_SETFIELD(key);
296}
297
reed@google.com74ce6f02013-05-22 15:13:18 +0000298void SkLua::pushRect(const SkRect& r, const char key[]) {
299 lua_newtable(fL);
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000300 setfield_scalar(fL, "left", r.fLeft);
301 setfield_scalar(fL, "top", r.fTop);
302 setfield_scalar(fL, "right", r.fRight);
303 setfield_scalar(fL, "bottom", r.fBottom);
reed@google.com74ce6f02013-05-22 15:13:18 +0000304 CHECK_SETFIELD(key);
305}
306
307void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
308 push_obj(fL, rr);
309 CHECK_SETFIELD(key);
310}
311
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000312void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
313 lua_newtable(fL);
314 setfield_scalar(fL, "phase", info.fPhase);
315 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
316 CHECK_SETFIELD(key);
317}
318
319
reed@google.com74ce6f02013-05-22 15:13:18 +0000320void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
321 push_obj(fL, matrix);
322 CHECK_SETFIELD(key);
323}
324
325void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
326 push_obj(fL, paint);
327 CHECK_SETFIELD(key);
328}
329
330void SkLua::pushPath(const SkPath& path, const char key[]) {
331 push_obj(fL, path);
332 CHECK_SETFIELD(key);
333}
334
335void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
336 push_ref(fL, canvas);
337 CHECK_SETFIELD(key);
338}
339
fmalitab7425172014-08-26 07:56:44 -0700340void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
341 push_ref(fL, const_cast<SkTextBlob*>(blob));
342 CHECK_SETFIELD(key);
343}
344
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000345static const char* element_type(SkClipStack::Element::Type type) {
346 switch (type) {
347 case SkClipStack::Element::kEmpty_Type:
348 return "empty";
349 case SkClipStack::Element::kRect_Type:
350 return "rect";
351 case SkClipStack::Element::kRRect_Type:
352 return "rrect";
353 case SkClipStack::Element::kPath_Type:
354 return "path";
355 }
356 return "unknown";
357}
358
359static const char* region_op(SkRegion::Op op) {
360 switch (op) {
361 case SkRegion::kDifference_Op:
362 return "difference";
363 case SkRegion::kIntersect_Op:
364 return "intersect";
365 case SkRegion::kUnion_Op:
366 return "union";
367 case SkRegion::kXOR_Op:
368 return "xor";
369 case SkRegion::kReverseDifference_Op:
370 return "reverse-difference";
371 case SkRegion::kReplace_Op:
372 return "replace";
373 }
374 return "unknown";
375}
376
377void SkLua::pushClipStack(const SkClipStack& stack, const char* key) {
378 lua_newtable(fL);
379 SkClipStack::B2TIter iter(stack);
380 const SkClipStack::Element* element;
381 int i = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700382 while ((element = iter.next())) {
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000383 this->pushClipStackElement(*element);
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000384 lua_rawseti(fL, -2, ++i);
385 }
386 CHECK_SETFIELD(key);
387}
388
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000389void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) {
390 lua_newtable(fL);
391 SkClipStack::Element::Type type = element.getType();
392 this->pushString(element_type(type), "type");
393 switch (type) {
394 case SkClipStack::Element::kEmpty_Type:
395 break;
396 case SkClipStack::Element::kRect_Type:
397 this->pushRect(element.getRect(), "rect");
398 break;
399 case SkClipStack::Element::kRRect_Type:
400 this->pushRRect(element.getRRect(), "rrect");
401 break;
402 case SkClipStack::Element::kPath_Type:
403 this->pushPath(element.getPath(), "path");
404 break;
405 }
reed73603f32016-09-20 08:42:38 -0700406 this->pushString(region_op((SkRegion::Op)element.getOp()), "op");
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000407 this->pushBool(element.isAA(), "aa");
408 CHECK_SETFIELD(key);
409}
410
411
reed@google.com74ce6f02013-05-22 15:13:18 +0000412///////////////////////////////////////////////////////////////////////////////
413///////////////////////////////////////////////////////////////////////////////
414
reed@google.com74ce6f02013-05-22 15:13:18 +0000415static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
416 SkASSERT(lua_istable(L, index));
417 lua_pushstring(L, key);
418 lua_gettable(L, index);
mtklein8aacf202014-12-18 13:29:54 -0800419
reed@google.com74ce6f02013-05-22 15:13:18 +0000420 SkScalar value = lua2scalar(L, -1);
421 lua_pop(L, 1);
422 return value;
423}
424
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000425static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
426 SkASSERT(lua_istable(L, index));
427 lua_pushstring(L, key);
428 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000429
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000430 SkScalar value;
431 if (lua_isnil(L, -1)) {
432 value = def;
433 } else {
434 value = lua2scalar(L, -1);
435 }
436 lua_pop(L, 1);
437 return value;
438}
439
reed468b1812014-10-19 11:42:54 -0700440static SkScalar byte2unit(U8CPU byte) {
441 return byte / 255.0f;
442}
443
reed@google.com74ce6f02013-05-22 15:13:18 +0000444static U8CPU unit2byte(SkScalar x) {
445 if (x <= 0) {
446 return 0;
447 } else if (x >= 1) {
448 return 255;
449 } else {
450 return SkScalarRoundToInt(x * 255);
451 }
452}
453
454static SkColor lua2color(lua_State* L, int index) {
reed485557f2014-10-12 10:36:47 -0700455 return SkColorSetARGB(unit2byte(getfield_scalar_default(L, index, "a", 1)),
456 unit2byte(getfield_scalar_default(L, index, "r", 0)),
457 unit2byte(getfield_scalar_default(L, index, "g", 0)),
458 unit2byte(getfield_scalar_default(L, index, "b", 0)));
reed@google.com74ce6f02013-05-22 15:13:18 +0000459}
460
461static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000462 rect->set(getfield_scalar_default(L, index, "left", 0),
463 getfield_scalar_default(L, index, "top", 0),
reed@google.com74ce6f02013-05-22 15:13:18 +0000464 getfield_scalar(L, index, "right"),
465 getfield_scalar(L, index, "bottom"));
466 return rect;
467}
468
reedf355df52014-10-12 12:18:40 -0700469static int lcanvas_clear(lua_State* L) {
470 get_ref<SkCanvas>(L, 1)->clear(0);
471 return 0;
472}
473
reed@google.com74ce6f02013-05-22 15:13:18 +0000474static int lcanvas_drawColor(lua_State* L) {
475 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
476 return 0;
477}
478
reed9fbc3f32014-10-21 07:12:58 -0700479static int lcanvas_drawPaint(lua_State* L) {
480 get_ref<SkCanvas>(L, 1)->drawPaint(*get_obj<SkPaint>(L, 2));
481 return 0;
482}
483
reed@google.com74ce6f02013-05-22 15:13:18 +0000484static int lcanvas_drawRect(lua_State* L) {
485 SkRect rect;
reed7a72c672014-11-07 10:23:55 -0800486 lua2rect(L, 2, &rect);
487 const SkPaint* paint = get_obj<SkPaint>(L, 3);
488 get_ref<SkCanvas>(L, 1)->drawRect(rect, *paint);
reed@google.com74ce6f02013-05-22 15:13:18 +0000489 return 0;
490}
491
492static int lcanvas_drawOval(lua_State* L) {
493 SkRect rect;
494 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
495 *get_obj<SkPaint>(L, 3));
496 return 0;
497}
498
499static int lcanvas_drawCircle(lua_State* L) {
500 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
501 lua2scalar(L, 3),
502 lua2scalar(L, 4),
503 *get_obj<SkPaint>(L, 5));
504 return 0;
505}
506
reed485557f2014-10-12 10:36:47 -0700507static SkPaint* lua2OptionalPaint(lua_State* L, int index, SkPaint* paint) {
508 if (lua_isnumber(L, index)) {
509 paint->setAlpha(SkScalarRoundToInt(lua2scalar(L, index) * 255));
510 return paint;
reedf355df52014-10-12 12:18:40 -0700511 } else if (lua_isuserdata(L, index)) {
reed485557f2014-10-12 10:36:47 -0700512 const SkPaint* ptr = get_obj<SkPaint>(L, index);
513 if (ptr) {
514 *paint = *ptr;
515 return paint;
516 }
517 }
halcanary96fcdcc2015-08-27 07:41:13 -0700518 return nullptr;
reed485557f2014-10-12 10:36:47 -0700519}
520
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000521static int lcanvas_drawImage(lua_State* L) {
522 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
523 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700524 if (nullptr == image) {
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000525 return 0;
526 }
527 SkScalar x = lua2scalar(L, 3);
528 SkScalar y = lua2scalar(L, 4);
529
530 SkPaint paint;
reed485557f2014-10-12 10:36:47 -0700531 canvas->drawImage(image, x, y, lua2OptionalPaint(L, 5, &paint));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000532 return 0;
533}
534
reedba5fb932014-10-10 15:28:19 -0700535static int lcanvas_drawImageRect(lua_State* L) {
536 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
537 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700538 if (nullptr == image) {
reedba5fb932014-10-10 15:28:19 -0700539 return 0;
540 }
541
542 SkRect srcR, dstR;
halcanary96fcdcc2015-08-27 07:41:13 -0700543 SkRect* srcRPtr = nullptr;
reedba5fb932014-10-10 15:28:19 -0700544 if (!lua_isnil(L, 3)) {
545 srcRPtr = lua2rect(L, 3, &srcR);
546 }
547 lua2rect(L, 4, &dstR);
mtklein8aacf202014-12-18 13:29:54 -0800548
reedba5fb932014-10-10 15:28:19 -0700549 SkPaint paint;
reede47829b2015-08-06 10:02:53 -0700550 canvas->legacy_drawImageRect(image, srcRPtr, dstR, lua2OptionalPaint(L, 5, &paint));
reedba5fb932014-10-10 15:28:19 -0700551 return 0;
552}
553
reed7a72c672014-11-07 10:23:55 -0800554static int lcanvas_drawPatch(lua_State* L) {
555 SkPoint cubics[12];
556 SkColor colorStorage[4];
557 SkPoint texStorage[4];
558
halcanary96fcdcc2015-08-27 07:41:13 -0700559 const SkColor* colors = nullptr;
560 const SkPoint* texs = nullptr;
reed7a72c672014-11-07 10:23:55 -0800561
562 getarray_points(L, 2, cubics, 12);
563
564 colorStorage[0] = SK_ColorRED;
565 colorStorage[1] = SK_ColorGREEN;
566 colorStorage[2] = SK_ColorBLUE;
567 colorStorage[3] = SK_ColorGRAY;
568
569 if (lua_isnil(L, 4)) {
570 colors = colorStorage;
571 } else {
572 getarray_points(L, 4, texStorage, 4);
573 texs = texStorage;
574 }
575
Mike Reed7d954ad2016-10-28 15:42:34 -0400576 get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, *get_obj<SkPaint>(L, 5));
reed7a72c672014-11-07 10:23:55 -0800577 return 0;
578}
579
reed@google.comfd345872013-05-22 20:53:42 +0000580static int lcanvas_drawPath(lua_State* L) {
581 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
582 *get_obj<SkPaint>(L, 3));
583 return 0;
584}
585
reed96affcd2014-10-13 12:38:04 -0700586// drawPicture(pic, x, y, paint)
587static int lcanvas_drawPicture(lua_State* L) {
588 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
589 SkPicture* picture = get_ref<SkPicture>(L, 2);
590 SkScalar x = lua2scalar_def(L, 3, 0);
591 SkScalar y = lua2scalar_def(L, 4, 0);
halcanary96fcdcc2015-08-27 07:41:13 -0700592 SkMatrix matrix, *matrixPtr = nullptr;
reed96affcd2014-10-13 12:38:04 -0700593 if (x || y) {
594 matrix.setTranslate(x, y);
595 matrixPtr = &matrix;
596 }
597 SkPaint paint;
598 canvas->drawPicture(picture, matrixPtr, lua2OptionalPaint(L, 5, &paint));
599 return 0;
600}
601
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000602static int lcanvas_drawText(lua_State* L) {
603 if (lua_gettop(L) < 5) {
604 return 0;
605 }
606
607 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
608 size_t len;
609 const char* text = lua_tolstring(L, 2, &len);
610 get_ref<SkCanvas>(L, 1)->drawText(text, len,
611 lua2scalar(L, 3), lua2scalar(L, 4),
612 *get_obj<SkPaint>(L, 5));
613 }
614 return 0;
615}
616
reed1b6ab442014-11-03 19:55:41 -0800617static int lcanvas_drawTextBlob(lua_State* L) {
618 const SkTextBlob* blob = get_ref<SkTextBlob>(L, 2);
619 SkScalar x = lua2scalar(L, 3);
620 SkScalar y = lua2scalar(L, 4);
621 const SkPaint& paint = *get_obj<SkPaint>(L, 5);
622 get_ref<SkCanvas>(L, 1)->drawTextBlob(blob, x, y, paint);
623 return 0;
624}
625
reed@google.com74ce6f02013-05-22 15:13:18 +0000626static int lcanvas_getSaveCount(lua_State* L) {
627 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
628 return 1;
629}
630
631static int lcanvas_getTotalMatrix(lua_State* L) {
632 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
633 return 1;
634}
635
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000636static int lcanvas_getClipStack(lua_State* L) {
637 SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack());
638 return 1;
639}
640
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000641int SkLua::lcanvas_getReducedClipStack(lua_State* L) {
642#if SK_SUPPORT_GPU
643 const SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
csmartdaltoncbecb082016-07-22 08:59:08 -0700644 SkRect queryBounds = SkRect::Make(canvas->getTopLayerBounds());
csmartdalton77f2fae2016-08-08 09:55:06 -0700645 const GrReducedClip reducedClip(*canvas->getClipStack(), queryBounds);
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000646
csmartdalton77f2fae2016-08-08 09:55:06 -0700647 GrReducedClip::ElementList::Iter iter(reducedClip.elements());
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000648 int i = 0;
649 lua_newtable(L);
bsalomon49f085d2014-09-05 13:34:00 -0700650 while(iter.get()) {
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000651 SkLua(L).pushClipStackElement(*iter.get());
652 iter.next();
653 lua_rawseti(L, -2, ++i);
654 }
655 // Currently this only returns the element list to lua, not the initial state or result bounds.
656 // It could return these as additional items on the lua stack.
657 return 1;
658#else
659 return 0;
660#endif
661}
662
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000663static int lcanvas_save(lua_State* L) {
664 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
665 return 1;
666}
667
reed86217d82014-10-25 20:44:40 -0700668static int lcanvas_saveLayer(lua_State* L) {
669 SkPaint paint;
halcanary96fcdcc2015-08-27 07:41:13 -0700670 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->saveLayer(nullptr, lua2OptionalPaint(L, 2, &paint)));
reed86217d82014-10-25 20:44:40 -0700671 return 1;
672}
673
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000674static int lcanvas_restore(lua_State* L) {
675 get_ref<SkCanvas>(L, 1)->restore();
676 return 0;
677}
678
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000679static int lcanvas_scale(lua_State* L) {
680 SkScalar sx = lua2scalar_def(L, 2, 1);
681 SkScalar sy = lua2scalar_def(L, 3, sx);
682 get_ref<SkCanvas>(L, 1)->scale(sx, sy);
683 return 0;
684}
685
reed@google.com3597b732013-05-22 20:12:50 +0000686static int lcanvas_translate(lua_State* L) {
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000687 SkScalar tx = lua2scalar_def(L, 2, 0);
688 SkScalar ty = lua2scalar_def(L, 3, 0);
689 get_ref<SkCanvas>(L, 1)->translate(tx, ty);
690 return 0;
691}
692
693static int lcanvas_rotate(lua_State* L) {
694 SkScalar degrees = lua2scalar_def(L, 2, 0);
695 get_ref<SkCanvas>(L, 1)->rotate(degrees);
reed@google.com3597b732013-05-22 20:12:50 +0000696 return 0;
697}
698
reedbdc49ae2014-10-14 09:34:52 -0700699static int lcanvas_concat(lua_State* L) {
700 get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2));
701 return 0;
702}
703
reed485557f2014-10-12 10:36:47 -0700704static int lcanvas_newSurface(lua_State* L) {
705 int width = lua2int_def(L, 2, 0);
reed7a72c672014-11-07 10:23:55 -0800706 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -0700707 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -0700708 auto surface = get_ref<SkCanvas>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -0700709 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -0700710 lua_pushnil(L);
711 } else {
reede8f30622016-03-23 18:59:25 -0700712 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -0700713 }
714 return 1;
715}
716
reed@google.com74ce6f02013-05-22 15:13:18 +0000717static int lcanvas_gc(lua_State* L) {
718 get_ref<SkCanvas>(L, 1)->unref();
719 return 0;
720}
721
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000722const struct luaL_Reg gSkCanvas_Methods[] = {
reedf355df52014-10-12 12:18:40 -0700723 { "clear", lcanvas_clear },
reed@google.com74ce6f02013-05-22 15:13:18 +0000724 { "drawColor", lcanvas_drawColor },
reed9fbc3f32014-10-21 07:12:58 -0700725 { "drawPaint", lcanvas_drawPaint },
reed@google.com74ce6f02013-05-22 15:13:18 +0000726 { "drawRect", lcanvas_drawRect },
727 { "drawOval", lcanvas_drawOval },
728 { "drawCircle", lcanvas_drawCircle },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000729 { "drawImage", lcanvas_drawImage },
reedba5fb932014-10-10 15:28:19 -0700730 { "drawImageRect", lcanvas_drawImageRect },
reed7a72c672014-11-07 10:23:55 -0800731 { "drawPatch", lcanvas_drawPatch },
reed@google.comfd345872013-05-22 20:53:42 +0000732 { "drawPath", lcanvas_drawPath },
reed96affcd2014-10-13 12:38:04 -0700733 { "drawPicture", lcanvas_drawPicture },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000734 { "drawText", lcanvas_drawText },
reed1b6ab442014-11-03 19:55:41 -0800735 { "drawTextBlob", lcanvas_drawTextBlob },
reed@google.com74ce6f02013-05-22 15:13:18 +0000736 { "getSaveCount", lcanvas_getSaveCount },
737 { "getTotalMatrix", lcanvas_getTotalMatrix },
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000738 { "getClipStack", lcanvas_getClipStack },
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000739#if SK_SUPPORT_GPU
740 { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
741#endif
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000742 { "save", lcanvas_save },
reed86217d82014-10-25 20:44:40 -0700743 { "saveLayer", lcanvas_saveLayer },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000744 { "restore", lcanvas_restore },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000745 { "scale", lcanvas_scale },
reed@google.com3597b732013-05-22 20:12:50 +0000746 { "translate", lcanvas_translate },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000747 { "rotate", lcanvas_rotate },
reedbdc49ae2014-10-14 09:34:52 -0700748 { "concat", lcanvas_concat },
reed485557f2014-10-12 10:36:47 -0700749
750 { "newSurface", lcanvas_newSurface },
751
reed@google.com74ce6f02013-05-22 15:13:18 +0000752 { "__gc", lcanvas_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700753 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +0000754};
755
756///////////////////////////////////////////////////////////////////////////////
757
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000758static int ldocument_beginPage(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -0700759 const SkRect* contentPtr = nullptr;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000760 push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2),
761 lua2scalar(L, 3),
762 contentPtr));
763 return 1;
764}
765
766static int ldocument_endPage(lua_State* L) {
767 get_ref<SkDocument>(L, 1)->endPage();
768 return 0;
769}
770
771static int ldocument_close(lua_State* L) {
772 get_ref<SkDocument>(L, 1)->close();
773 return 0;
774}
775
776static int ldocument_gc(lua_State* L) {
777 get_ref<SkDocument>(L, 1)->unref();
778 return 0;
779}
780
781static const struct luaL_Reg gSkDocument_Methods[] = {
782 { "beginPage", ldocument_beginPage },
783 { "endPage", ldocument_endPage },
784 { "close", ldocument_close },
785 { "__gc", ldocument_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700786 { nullptr, nullptr }
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000787};
788
789///////////////////////////////////////////////////////////////////////////////
790
reed@google.com74ce6f02013-05-22 15:13:18 +0000791static int lpaint_isAntiAlias(lua_State* L) {
792 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
793 return 1;
794}
795
796static int lpaint_setAntiAlias(lua_State* L) {
reed@google.com88c9ec92013-05-22 15:43:21 +0000797 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +0000798 return 0;
799}
800
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000801static int lpaint_isDither(lua_State* L) {
802 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
803 return 1;
804}
805
reedbb8a0ab2014-11-03 22:32:07 -0800806static int lpaint_setDither(lua_State* L) {
807 get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2));
808 return 0;
809}
810
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000811static int lpaint_isUnderlineText(lua_State* L) {
812 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText());
813 return 1;
814}
815
816static int lpaint_isStrikeThruText(lua_State* L) {
817 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText());
818 return 1;
819}
820
821static int lpaint_isFakeBoldText(lua_State* L) {
822 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
823 return 1;
824}
825
826static int lpaint_isLinearText(lua_State* L) {
827 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
828 return 1;
829}
830
831static int lpaint_isSubpixelText(lua_State* L) {
832 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
833 return 1;
834}
835
reed09a1d672014-10-11 13:13:11 -0700836static int lpaint_setSubpixelText(lua_State* L) {
837 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
838 return 1;
839}
840
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000841static int lpaint_isDevKernText(lua_State* L) {
842 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
843 return 1;
844}
845
846static int lpaint_isLCDRenderText(lua_State* L) {
847 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
848 return 1;
849}
850
reed36c9c112014-11-04 10:58:42 -0800851static int lpaint_setLCDRenderText(lua_State* L) {
852 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2));
853 return 1;
854}
855
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000856static int lpaint_isEmbeddedBitmapText(lua_State* L) {
857 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
858 return 1;
859}
860
861static int lpaint_isAutohinted(lua_State* L) {
862 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
863 return 1;
864}
865
866static int lpaint_isVerticalText(lua_State* L) {
867 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
868 return 1;
869}
870
reed468b1812014-10-19 11:42:54 -0700871static int lpaint_getAlpha(lua_State* L) {
872 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha()));
873 return 1;
874}
875
876static int lpaint_setAlpha(lua_State* L) {
877 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2)));
878 return 0;
879}
880
reed@google.com74ce6f02013-05-22 15:13:18 +0000881static int lpaint_getColor(lua_State* L) {
882 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
883 return 1;
884}
885
886static int lpaint_setColor(lua_State* L) {
887 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
888 return 0;
889}
890
reed@google.come3823fd2013-05-30 18:55:14 +0000891static int lpaint_getTextSize(lua_State* L) {
892 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
893 return 1;
894}
895
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000896static int lpaint_getTextScaleX(lua_State* L) {
897 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
898 return 1;
899}
900
901static int lpaint_getTextSkewX(lua_State* L) {
902 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
903 return 1;
904}
905
reed@google.come3823fd2013-05-30 18:55:14 +0000906static int lpaint_setTextSize(lua_State* L) {
907 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
908 return 0;
909}
910
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000911static int lpaint_getTypeface(lua_State* L) {
912 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
913 return 1;
914}
915
916static int lpaint_setTypeface(lua_State* L) {
bungeman13b9c952016-05-12 10:09:30 -0700917 get_obj<SkPaint>(L, 1)->setTypeface(sk_ref_sp(get_ref<SkTypeface>(L, 2)));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000918 return 0;
919}
920
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000921static int lpaint_getHinting(lua_State* L) {
922 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
923 return 1;
924}
925
reed93a12152015-03-16 10:08:34 -0700926static int lpaint_getFilterQuality(lua_State* L) {
927 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality());
reed7a72c672014-11-07 10:23:55 -0800928 return 1;
929}
930
reed93a12152015-03-16 10:08:34 -0700931static int lpaint_setFilterQuality(lua_State* L) {
reed7a72c672014-11-07 10:23:55 -0800932 int level = lua2int_def(L, 2, -1);
933 if (level >= 0 && level <= 3) {
reed93a12152015-03-16 10:08:34 -0700934 get_obj<SkPaint>(L, 1)->setFilterQuality((SkFilterQuality)level);
reed7a72c672014-11-07 10:23:55 -0800935 }
936 return 0;
937}
938
reed@google.come3823fd2013-05-30 18:55:14 +0000939static int lpaint_getFontID(lua_State* L) {
940 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
941 SkLua(L).pushU32(SkTypeface::UniqueID(face));
942 return 1;
943}
944
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000945static const struct {
946 const char* fLabel;
947 SkPaint::Align fAlign;
948} gAlignRec[] = {
949 { "left", SkPaint::kLeft_Align },
950 { "center", SkPaint::kCenter_Align },
951 { "right", SkPaint::kRight_Align },
952};
953
954static int lpaint_getTextAlign(lua_State* L) {
955 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
956 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
957 if (gAlignRec[i].fAlign == align) {
958 lua_pushstring(L, gAlignRec[i].fLabel);
959 return 1;
960 }
961 }
962 return 0;
963}
964
965static int lpaint_setTextAlign(lua_State* L) {
966 if (lua_isstring(L, 2)) {
967 size_t len;
968 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000969
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000970 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
971 if (!strcmp(gAlignRec[i].fLabel, label)) {
972 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
973 break;
974 }
975 }
976 }
977 return 0;
978}
979
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000980static int lpaint_getStroke(lua_State* L) {
981 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
982 return 1;
983}
984
985static int lpaint_setStroke(lua_State* L) {
986 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000987
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000988 if (lua_toboolean(L, 2)) {
989 style = SkPaint::kStroke_Style;
990 } else {
991 style = SkPaint::kFill_Style;
992 }
993 get_obj<SkPaint>(L, 1)->setStyle(style);
994 return 0;
995}
996
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000997static int lpaint_getStrokeCap(lua_State* L) {
998 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
999 return 1;
1000}
1001
1002static int lpaint_getStrokeJoin(lua_State* L) {
1003 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
1004 return 1;
1005}
1006
1007static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +00001008 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001009 return 1;
1010}
1011
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001012static int lpaint_getStrokeWidth(lua_State* L) {
1013 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
1014 return 1;
1015}
1016
1017static int lpaint_setStrokeWidth(lua_State* L) {
1018 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
1019 return 0;
1020}
1021
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001022static int lpaint_getStrokeMiter(lua_State* L) {
1023 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
1024 return 1;
1025}
1026
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001027static int lpaint_measureText(lua_State* L) {
1028 if (lua_isstring(L, 2)) {
1029 size_t len;
1030 const char* text = lua_tolstring(L, 2, &len);
1031 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
1032 return 1;
1033 }
1034 return 0;
1035}
1036
1037struct FontMetrics {
1038 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
1039 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
1040 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
1041 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
1042 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
1043 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
1044 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
1045 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
1046 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
1047};
1048
1049static int lpaint_getFontMetrics(lua_State* L) {
1050 SkPaint::FontMetrics fm;
1051 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +00001052
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001053 lua_newtable(L);
1054 setfield_scalar(L, "top", fm.fTop);
1055 setfield_scalar(L, "ascent", fm.fAscent);
1056 setfield_scalar(L, "descent", fm.fDescent);
1057 setfield_scalar(L, "bottom", fm.fBottom);
1058 setfield_scalar(L, "leading", fm.fLeading);
1059 SkLua(L).pushScalar(height);
1060 return 2;
1061}
1062
reed@google.com29563872013-07-10 21:23:49 +00001063static int lpaint_getEffects(lua_State* L) {
1064 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001065
reed@google.com29563872013-07-10 21:23:49 +00001066 lua_newtable(L);
reed468b1812014-10-19 11:42:54 -07001067 setfield_bool_if(L, "looper", !!paint->getLooper());
1068 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
1069 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer());
1070 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
1071 setfield_bool_if(L, "shader", !!paint->getShader());
reed@google.com29563872013-07-10 21:23:49 +00001072 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
1073 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
reed@google.com29563872013-07-10 21:23:49 +00001074 return 1;
1075}
1076
reed22a517f2015-12-04 20:45:59 -08001077static int lpaint_getColorFilter(lua_State* L) {
1078 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1079 SkColorFilter* cf = paint->getColorFilter();
1080 if (cf) {
1081 push_ref(L, cf);
1082 return 1;
1083 }
1084 return 0;
1085}
1086
1087static int lpaint_setColorFilter(lua_State* L) {
1088 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedd053ce92016-03-22 10:17:23 -07001089 paint->setColorFilter(sk_ref_sp(get_ref<SkColorFilter>(L, 2)));
reed22a517f2015-12-04 20:45:59 -08001090 return 0;
1091}
1092
reed468b1812014-10-19 11:42:54 -07001093static int lpaint_getImageFilter(lua_State* L) {
1094 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1095 SkImageFilter* imf = paint->getImageFilter();
1096 if (imf) {
1097 push_ref(L, imf);
1098 return 1;
1099 }
1100 return 0;
1101}
1102
1103static int lpaint_setImageFilter(lua_State* L) {
1104 SkPaint* paint = get_obj<SkPaint>(L, 1);
Mike Reed5e257172016-11-01 11:22:05 -04001105 paint->setImageFilter(sk_ref_sp(get_ref<SkImageFilter>(L, 2)));
reed468b1812014-10-19 11:42:54 -07001106 return 0;
1107}
1108
reed@google.com5fdc9832013-07-24 15:47:52 +00001109static int lpaint_getShader(lua_State* L) {
1110 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1111 SkShader* shader = paint->getShader();
1112 if (shader) {
1113 push_ref(L, shader);
1114 return 1;
1115 }
1116 return 0;
1117}
1118
reed9fbc3f32014-10-21 07:12:58 -07001119static int lpaint_setShader(lua_State* L) {
1120 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedfe630452016-03-25 09:08:00 -07001121 paint->setShader(sk_ref_sp(get_ref<SkShader>(L, 2)));
reed9fbc3f32014-10-21 07:12:58 -07001122 return 0;
1123}
1124
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001125static int lpaint_getPathEffect(lua_State* L) {
1126 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1127 SkPathEffect* pe = paint->getPathEffect();
1128 if (pe) {
1129 push_ref(L, pe);
1130 return 1;
1131 }
1132 return 0;
1133}
1134
hstern0b401ce2016-08-02 09:17:59 -07001135static int lpaint_getFillPath(lua_State* L) {
1136 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1137 const SkPath* path = get_obj<SkPath>(L, 2);
1138
1139 SkPath fillpath;
1140 paint->getFillPath(*path, &fillpath);
1141
1142 SkLua lua(L);
1143 lua.pushPath(fillpath);
1144
1145 return 1;
1146}
1147
reed@google.com74ce6f02013-05-22 15:13:18 +00001148static int lpaint_gc(lua_State* L) {
1149 get_obj<SkPaint>(L, 1)->~SkPaint();
1150 return 0;
1151}
1152
1153static const struct luaL_Reg gSkPaint_Methods[] = {
1154 { "isAntiAlias", lpaint_isAntiAlias },
1155 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001156 { "isDither", lpaint_isDither },
reedbb8a0ab2014-11-03 22:32:07 -08001157 { "setDither", lpaint_setDither },
reed93a12152015-03-16 10:08:34 -07001158 { "getFilterQuality", lpaint_getFilterQuality },
1159 { "setFilterQuality", lpaint_setFilterQuality },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001160 { "isUnderlineText", lpaint_isUnderlineText },
1161 { "isStrikeThruText", lpaint_isStrikeThruText },
1162 { "isFakeBoldText", lpaint_isFakeBoldText },
1163 { "isLinearText", lpaint_isLinearText },
1164 { "isSubpixelText", lpaint_isSubpixelText },
reed09a1d672014-10-11 13:13:11 -07001165 { "setSubpixelText", lpaint_setSubpixelText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001166 { "isDevKernText", lpaint_isDevKernText },
1167 { "isLCDRenderText", lpaint_isLCDRenderText },
reed36c9c112014-11-04 10:58:42 -08001168 { "setLCDRenderText", lpaint_setLCDRenderText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001169 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
1170 { "isAutohinted", lpaint_isAutohinted },
1171 { "isVerticalText", lpaint_isVerticalText },
reed468b1812014-10-19 11:42:54 -07001172 { "getAlpha", lpaint_getAlpha },
1173 { "setAlpha", lpaint_setAlpha },
reed@google.com74ce6f02013-05-22 15:13:18 +00001174 { "getColor", lpaint_getColor },
1175 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +00001176 { "getTextSize", lpaint_getTextSize },
1177 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001178 { "getTextScaleX", lpaint_getTextScaleX },
1179 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001180 { "getTypeface", lpaint_getTypeface },
1181 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001182 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +00001183 { "getFontID", lpaint_getFontID },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001184 { "getTextAlign", lpaint_getTextAlign },
1185 { "setTextAlign", lpaint_setTextAlign },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001186 { "getStroke", lpaint_getStroke },
1187 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001188 { "getStrokeCap", lpaint_getStrokeCap },
1189 { "getStrokeJoin", lpaint_getStrokeJoin },
1190 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001191 { "getStrokeWidth", lpaint_getStrokeWidth },
1192 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001193 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001194 { "measureText", lpaint_measureText },
1195 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +00001196 { "getEffects", lpaint_getEffects },
reed22a517f2015-12-04 20:45:59 -08001197 { "getColorFilter", lpaint_getColorFilter },
1198 { "setColorFilter", lpaint_setColorFilter },
reed468b1812014-10-19 11:42:54 -07001199 { "getImageFilter", lpaint_getImageFilter },
1200 { "setImageFilter", lpaint_setImageFilter },
reed@google.com5fdc9832013-07-24 15:47:52 +00001201 { "getShader", lpaint_getShader },
reed9fbc3f32014-10-21 07:12:58 -07001202 { "setShader", lpaint_setShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001203 { "getPathEffect", lpaint_getPathEffect },
hstern0b401ce2016-08-02 09:17:59 -07001204 { "getFillPath", lpaint_getFillPath },
reed@google.com74ce6f02013-05-22 15:13:18 +00001205 { "__gc", lpaint_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001206 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001207};
1208
1209///////////////////////////////////////////////////////////////////////////////
1210
reed@google.com5fdc9832013-07-24 15:47:52 +00001211static const char* mode2string(SkShader::TileMode mode) {
1212 static const char* gNames[] = { "clamp", "repeat", "mirror" };
1213 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
1214 return gNames[mode];
1215}
1216
1217static const char* gradtype2string(SkShader::GradientType t) {
1218 static const char* gNames[] = {
1219 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
1220 };
1221 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
1222 return gNames[t];
1223}
1224
1225static int lshader_isOpaque(lua_State* L) {
1226 SkShader* shader = get_ref<SkShader>(L, 1);
1227 return shader && shader->isOpaque();
1228}
1229
Mike Reed627778d2016-09-28 17:13:38 -04001230static int lshader_isAImage(lua_State* L) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001231 SkShader* shader = get_ref<SkShader>(L, 1);
1232 if (shader) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001233 SkMatrix matrix;
1234 SkShader::TileMode modes[2];
Mike Reed627778d2016-09-28 17:13:38 -04001235 if (SkImage* image = shader->isAImage(&matrix, modes)) {
reedf5822822015-08-19 11:46:38 -07001236 lua_newtable(L);
Mike Reed627778d2016-09-28 17:13:38 -04001237 setfield_number(L, "id", image->uniqueID());
1238 setfield_number(L, "width", image->width());
1239 setfield_number(L, "height", image->height());
reedf5822822015-08-19 11:46:38 -07001240 setfield_string(L, "tileX", mode2string(modes[0]));
1241 setfield_string(L, "tileY", mode2string(modes[1]));
1242 return 1;
reed@google.com5fdc9832013-07-24 15:47:52 +00001243 }
1244 }
1245 return 0;
1246}
1247
1248static int lshader_asAGradient(lua_State* L) {
1249 SkShader* shader = get_ref<SkShader>(L, 1);
1250 if (shader) {
1251 SkShader::GradientInfo info;
1252 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001253
reed@google.com5fdc9832013-07-24 15:47:52 +00001254 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001255
reed@google.com5fdc9832013-07-24 15:47:52 +00001256 if (SkShader::kNone_GradientType != t) {
fmenozzib4f254e2016-06-28 14:03:03 -07001257 SkAutoTArray<SkScalar> pos(info.fColorCount);
1258 info.fColorOffsets = pos.get();
1259 shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001260
fmenozzib4f254e2016-06-28 14:03:03 -07001261 lua_newtable(L);
fmenozzi7f2c85e2016-07-12 09:17:39 -07001262 setfield_string(L, "type", gradtype2string(t));
1263 setfield_string(L, "tile", mode2string(info.fTileMode));
1264 setfield_number(L, "colorCount", info.fColorCount);
fmenozzib4f254e2016-06-28 14:03:03 -07001265
1266 lua_newtable(L);
1267 for (int i = 0; i < info.fColorCount; i++) {
1268 // Lua uses 1-based indexing
1269 setarray_scalar(L, i+1, pos[i]);
1270 }
1271 lua_setfield(L, -2, "positions");
1272
reed@google.com5fdc9832013-07-24 15:47:52 +00001273 return 1;
1274 }
1275 }
1276 return 0;
1277}
1278
1279static int lshader_gc(lua_State* L) {
1280 get_ref<SkShader>(L, 1)->unref();
1281 return 0;
1282}
1283
1284static const struct luaL_Reg gSkShader_Methods[] = {
1285 { "isOpaque", lshader_isOpaque },
Mike Reed627778d2016-09-28 17:13:38 -04001286 { "isAImage", lshader_isAImage },
reed@google.com5fdc9832013-07-24 15:47:52 +00001287 { "asAGradient", lshader_asAGradient },
1288 { "__gc", lshader_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001289 { nullptr, nullptr }
reed@google.com5fdc9832013-07-24 15:47:52 +00001290};
1291
1292///////////////////////////////////////////////////////////////////////////////
1293
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001294static int lpatheffect_asADash(lua_State* L) {
1295 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1296 if (pe) {
1297 SkPathEffect::DashInfo info;
1298 SkPathEffect::DashType dashType = pe->asADash(&info);
1299 if (SkPathEffect::kDash_DashType == dashType) {
1300 SkAutoTArray<SkScalar> intervals(info.fCount);
1301 info.fIntervals = intervals.get();
1302 pe->asADash(&info);
1303 SkLua(L).pushDash(info);
1304 return 1;
1305 }
1306 }
1307 return 0;
1308}
1309
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001310static int lpatheffect_gc(lua_State* L) {
1311 get_ref<SkPathEffect>(L, 1)->unref();
1312 return 0;
1313}
1314
1315static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001316 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001317 { "__gc", lpatheffect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001318 { nullptr, nullptr }
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001319};
1320
1321///////////////////////////////////////////////////////////////////////////////
1322
reed22a517f2015-12-04 20:45:59 -08001323static int lpcolorfilter_gc(lua_State* L) {
1324 get_ref<SkColorFilter>(L, 1)->unref();
1325 return 0;
1326}
1327
1328static const struct luaL_Reg gSkColorFilter_Methods[] = {
1329 { "__gc", lpcolorfilter_gc },
1330 { nullptr, nullptr }
1331};
1332
1333///////////////////////////////////////////////////////////////////////////////
1334
reed468b1812014-10-19 11:42:54 -07001335static int lpimagefilter_gc(lua_State* L) {
1336 get_ref<SkImageFilter>(L, 1)->unref();
1337 return 0;
1338}
1339
1340static const struct luaL_Reg gSkImageFilter_Methods[] = {
1341 { "__gc", lpimagefilter_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001342 { nullptr, nullptr }
reed468b1812014-10-19 11:42:54 -07001343};
1344
1345///////////////////////////////////////////////////////////////////////////////
1346
humper@google.com2815c192013-07-10 22:42:30 +00001347static int lmatrix_getType(lua_State* L) {
1348 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001349
humper@google.com2815c192013-07-10 22:42:30 +00001350 lua_newtable(L);
1351 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1352 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1353 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1354 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1355 return 1;
1356}
1357
humper@google.com0f48ee02013-07-26 15:23:43 +00001358static int lmatrix_getScaleX(lua_State* L) {
1359 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1360 return 1;
1361}
1362
1363static int lmatrix_getScaleY(lua_State* L) {
1364 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1365 return 1;
1366}
1367
1368static int lmatrix_getTranslateX(lua_State* L) {
1369 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1370 return 1;
1371}
1372
1373static int lmatrix_getTranslateY(lua_State* L) {
1374 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1375 return 1;
1376}
1377
reed7a72c672014-11-07 10:23:55 -08001378static int lmatrix_invert(lua_State* L) {
1379 lua_pushboolean(L, get_obj<SkMatrix>(L, 1)->invert(get_obj<SkMatrix>(L, 2)));
1380 return 1;
1381}
1382
1383static int lmatrix_mapXY(lua_State* L) {
1384 SkPoint pt = { lua2scalar(L, 2), lua2scalar(L, 3) };
1385 get_obj<SkMatrix>(L, 1)->mapPoints(&pt, &pt, 1);
1386 lua_pushnumber(L, pt.x());
1387 lua_pushnumber(L, pt.y());
1388 return 2;
1389}
1390
reedbdc49ae2014-10-14 09:34:52 -07001391static int lmatrix_setRectToRect(lua_State* L) {
1392 SkMatrix* matrix = get_obj<SkMatrix>(L, 1);
1393 SkRect srcR, dstR;
1394 lua2rect(L, 2, &srcR);
1395 lua2rect(L, 3, &dstR);
1396 const char* scaleToFitStr = lua_tostring(L, 4);
1397 SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit;
1398
1399 if (scaleToFitStr) {
1400 const struct {
1401 const char* fName;
1402 SkMatrix::ScaleToFit fScaleToFit;
1403 } rec[] = {
1404 { "fill", SkMatrix::kFill_ScaleToFit },
1405 { "start", SkMatrix::kStart_ScaleToFit },
1406 { "center", SkMatrix::kCenter_ScaleToFit },
1407 { "end", SkMatrix::kEnd_ScaleToFit },
1408 };
1409
1410 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
1411 if (strcmp(rec[i].fName, scaleToFitStr) == 0) {
1412 scaleToFit = rec[i].fScaleToFit;
1413 break;
1414 }
1415 }
1416 }
1417
1418 matrix->setRectToRect(srcR, dstR, scaleToFit);
1419 return 0;
1420}
1421
humper@google.com2815c192013-07-10 22:42:30 +00001422static const struct luaL_Reg gSkMatrix_Methods[] = {
1423 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001424 { "getScaleX", lmatrix_getScaleX },
1425 { "getScaleY", lmatrix_getScaleY },
1426 { "getTranslateX", lmatrix_getTranslateX },
1427 { "getTranslateY", lmatrix_getTranslateY },
reedbdc49ae2014-10-14 09:34:52 -07001428 { "setRectToRect", lmatrix_setRectToRect },
reed7a72c672014-11-07 10:23:55 -08001429 { "invert", lmatrix_invert },
1430 { "mapXY", lmatrix_mapXY },
halcanary96fcdcc2015-08-27 07:41:13 -07001431 { nullptr, nullptr }
humper@google.com2815c192013-07-10 22:42:30 +00001432};
1433
1434///////////////////////////////////////////////////////////////////////////////
1435
reed@google.com74ce6f02013-05-22 15:13:18 +00001436static int lpath_getBounds(lua_State* L) {
1437 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1438 return 1;
1439}
1440
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001441static const char* fill_type_to_str(SkPath::FillType fill) {
1442 switch (fill) {
1443 case SkPath::kEvenOdd_FillType:
1444 return "even-odd";
1445 case SkPath::kWinding_FillType:
1446 return "winding";
1447 case SkPath::kInverseEvenOdd_FillType:
1448 return "inverse-even-odd";
1449 case SkPath::kInverseWinding_FillType:
1450 return "inverse-winding";
1451 }
1452 return "unknown";
1453}
1454
1455static int lpath_getFillType(lua_State* L) {
1456 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1457 SkLua(L).pushString(fill_type_to_str(fill));
1458 return 1;
1459}
1460
1461static SkString segment_masks_to_str(uint32_t segmentMasks) {
1462 SkString result;
1463 bool first = true;
1464 if (SkPath::kLine_SegmentMask & segmentMasks) {
1465 result.append("line");
1466 first = false;
1467 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1468 }
1469 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1470 if (!first) {
1471 result.append(" ");
1472 }
1473 result.append("quad");
1474 first = false;
1475 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1476 }
1477 if (SkPath::kConic_SegmentMask & segmentMasks) {
1478 if (!first) {
1479 result.append(" ");
1480 }
1481 result.append("conic");
1482 first = false;
1483 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1484 }
1485 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1486 if (!first) {
1487 result.append(" ");
1488 }
1489 result.append("cubic");
1490 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1491 }
1492 SkASSERT(0 == segmentMasks);
1493 return result;
1494}
1495
krajcevski95498ed2014-08-18 08:02:33 -07001496static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001497 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1498 SkLua(L).pushString(segment_masks_to_str(segMasks));
1499 return 1;
1500}
1501
1502static int lpath_isConvex(lua_State* L) {
1503 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1504 SkLua(L).pushBool(isConvex);
1505 return 1;
1506}
1507
reed@google.com74ce6f02013-05-22 15:13:18 +00001508static int lpath_isEmpty(lua_State* L) {
1509 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1510 return 1;
1511}
1512
1513static int lpath_isRect(lua_State* L) {
1514 SkRect r;
1515 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1516 int ret_count = 1;
1517 lua_pushboolean(L, pred);
1518 if (pred) {
1519 SkLua(L).pushRect(r);
1520 ret_count += 1;
1521 }
1522 return ret_count;
1523}
1524
1525static const char* dir2string(SkPath::Direction dir) {
1526 static const char* gStr[] = {
1527 "unknown", "cw", "ccw"
1528 };
1529 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1530 return gStr[dir];
1531}
1532
caryclark95bc5f32015-04-08 08:34:15 -07001533static int lpath_isNestedFillRects(lua_State* L) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001534 SkRect rects[2];
1535 SkPath::Direction dirs[2];
caryclark95bc5f32015-04-08 08:34:15 -07001536 bool pred = get_obj<SkPath>(L, 1)->isNestedFillRects(rects, dirs);
reed@google.com74ce6f02013-05-22 15:13:18 +00001537 int ret_count = 1;
1538 lua_pushboolean(L, pred);
1539 if (pred) {
1540 SkLua lua(L);
1541 lua.pushRect(rects[0]);
1542 lua.pushRect(rects[1]);
1543 lua_pushstring(L, dir2string(dirs[0]));
1544 lua_pushstring(L, dir2string(dirs[0]));
1545 ret_count += 4;
1546 }
1547 return ret_count;
1548}
1549
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001550static int lpath_countPoints(lua_State* L) {
1551 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1552 return 1;
1553}
1554
hstern0b401ce2016-08-02 09:17:59 -07001555static int lpath_getVerbs(lua_State* L) {
1556 const SkPath* path = get_obj<SkPath>(L, 1);
1557 SkPath::Iter iter(*path, false);
1558 SkPoint pts[4];
1559
1560 lua_newtable(L);
1561
1562 bool done = false;
1563 int i = 0;
1564 do {
1565 switch (iter.next(pts, true)) {
1566 case SkPath::kMove_Verb:
1567 setarray_string(L, ++i, "move");
1568 break;
1569 case SkPath::kClose_Verb:
1570 setarray_string(L, ++i, "close");
1571 break;
1572 case SkPath::kLine_Verb:
1573 setarray_string(L, ++i, "line");
1574 break;
1575 case SkPath::kQuad_Verb:
1576 setarray_string(L, ++i, "quad");
1577 break;
1578 case SkPath::kConic_Verb:
1579 setarray_string(L, ++i, "conic");
1580 break;
1581 case SkPath::kCubic_Verb:
1582 setarray_string(L, ++i, "cubic");
1583 break;
1584 case SkPath::kDone_Verb:
1585 setarray_string(L, ++i, "done");
1586 done = true;
1587 break;
1588 }
1589 } while (!done);
1590
1591 return 1;
1592}
1593
reed@google.com74ce6f02013-05-22 15:13:18 +00001594static int lpath_reset(lua_State* L) {
1595 get_obj<SkPath>(L, 1)->reset();
1596 return 0;
1597}
1598
1599static int lpath_moveTo(lua_State* L) {
1600 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1601 return 0;
1602}
1603
1604static int lpath_lineTo(lua_State* L) {
1605 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1606 return 0;
1607}
1608
1609static int lpath_quadTo(lua_State* L) {
1610 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1611 lua2scalar(L, 4), lua2scalar(L, 5));
1612 return 0;
1613}
1614
1615static int lpath_cubicTo(lua_State* L) {
1616 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1617 lua2scalar(L, 4), lua2scalar(L, 5),
1618 lua2scalar(L, 6), lua2scalar(L, 7));
1619 return 0;
1620}
1621
1622static int lpath_close(lua_State* L) {
1623 get_obj<SkPath>(L, 1)->close();
1624 return 0;
1625}
1626
1627static int lpath_gc(lua_State* L) {
1628 get_obj<SkPath>(L, 1)->~SkPath();
1629 return 0;
1630}
1631
1632static const struct luaL_Reg gSkPath_Methods[] = {
1633 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001634 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001635 { "getSegmentTypes", lpath_getSegmentTypes },
hstern0b401ce2016-08-02 09:17:59 -07001636 { "getVerbs", lpath_getVerbs },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001637 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001638 { "isEmpty", lpath_isEmpty },
1639 { "isRect", lpath_isRect },
caryclark95bc5f32015-04-08 08:34:15 -07001640 { "isNestedFillRects", lpath_isNestedFillRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001641 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001642 { "reset", lpath_reset },
1643 { "moveTo", lpath_moveTo },
1644 { "lineTo", lpath_lineTo },
1645 { "quadTo", lpath_quadTo },
1646 { "cubicTo", lpath_cubicTo },
1647 { "close", lpath_close },
1648 { "__gc", lpath_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001649 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001650};
1651
1652///////////////////////////////////////////////////////////////////////////////
1653
1654static const char* rrect_type(const SkRRect& rr) {
1655 switch (rr.getType()) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001656 case SkRRect::kEmpty_Type: return "empty";
1657 case SkRRect::kRect_Type: return "rect";
1658 case SkRRect::kOval_Type: return "oval";
1659 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001660 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001661 case SkRRect::kComplex_Type: return "complex";
1662 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001663 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001664 return "";
1665}
1666
1667static int lrrect_rect(lua_State* L) {
1668 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1669 return 1;
1670}
1671
1672static int lrrect_type(lua_State* L) {
1673 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1674 return 1;
1675}
1676
1677static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001678 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001679 SkVector v;
1680 if (corner < 0 || corner > 3) {
1681 SkDebugf("bad corner index %d", corner);
1682 v.set(0, 0);
1683 } else {
1684 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1685 }
1686 lua_pushnumber(L, v.fX);
1687 lua_pushnumber(L, v.fY);
1688 return 2;
1689}
1690
1691static int lrrect_gc(lua_State* L) {
1692 get_obj<SkRRect>(L, 1)->~SkRRect();
1693 return 0;
1694}
1695
1696static const struct luaL_Reg gSkRRect_Methods[] = {
1697 { "rect", lrrect_rect },
1698 { "type", lrrect_type },
1699 { "radii", lrrect_radii },
1700 { "__gc", lrrect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001701 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001702};
1703
1704///////////////////////////////////////////////////////////////////////////////
1705
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001706static int limage_width(lua_State* L) {
1707 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1708 return 1;
1709}
1710
1711static int limage_height(lua_State* L) {
1712 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1713 return 1;
1714}
1715
reed7a72c672014-11-07 10:23:55 -08001716static int limage_newShader(lua_State* L) {
1717 SkShader::TileMode tmode = SkShader::kClamp_TileMode;
halcanary96fcdcc2015-08-27 07:41:13 -07001718 const SkMatrix* localM = nullptr;
reed5671c5b2016-03-09 14:47:34 -08001719 push_ref(L, get_ref<SkImage>(L, 1)->makeShader(tmode, tmode, localM));
reed7a72c672014-11-07 10:23:55 -08001720 return 1;
1721}
1722
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001723static int limage_gc(lua_State* L) {
1724 get_ref<SkImage>(L, 1)->unref();
1725 return 0;
1726}
1727
1728static const struct luaL_Reg gSkImage_Methods[] = {
1729 { "width", limage_width },
1730 { "height", limage_height },
reed7a72c672014-11-07 10:23:55 -08001731 { "newShader", limage_newShader },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001732 { "__gc", limage_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001733 { nullptr, nullptr }
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001734};
1735
1736///////////////////////////////////////////////////////////////////////////////
1737
reed485557f2014-10-12 10:36:47 -07001738static int lsurface_width(lua_State* L) {
1739 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1740 return 1;
1741}
1742
1743static int lsurface_height(lua_State* L) {
1744 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1745 return 1;
1746}
1747
1748static int lsurface_getCanvas(lua_State* L) {
1749 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001750 if (nullptr == canvas) {
reed485557f2014-10-12 10:36:47 -07001751 lua_pushnil(L);
1752 } else {
1753 push_ref(L, canvas);
1754 // note: we don't unref canvas, since getCanvas did not ref it.
1755 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1756 // the real owner (the surface) go away, but still hold onto the canvas?
1757 // *really* we want to sort of ref the surface again, but have the native object
1758 // know that it is supposed to be treated as a canvas...
1759 }
1760 return 1;
1761}
1762
1763static int lsurface_newImageSnapshot(lua_State* L) {
reed9ce9d672016-03-17 10:51:11 -07001764 sk_sp<SkImage> image = get_ref<SkSurface>(L, 1)->makeImageSnapshot();
1765 if (!image) {
reed485557f2014-10-12 10:36:47 -07001766 lua_pushnil(L);
1767 } else {
reed9ce9d672016-03-17 10:51:11 -07001768 push_ref(L, image);
reed485557f2014-10-12 10:36:47 -07001769 }
1770 return 1;
1771}
1772
1773static int lsurface_newSurface(lua_State* L) {
1774 int width = lua2int_def(L, 2, 0);
reed96affcd2014-10-13 12:38:04 -07001775 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -07001776 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -07001777 auto surface = get_ref<SkSurface>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -07001778 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07001779 lua_pushnil(L);
1780 } else {
reede8f30622016-03-23 18:59:25 -07001781 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07001782 }
1783 return 1;
1784}
1785
1786static int lsurface_gc(lua_State* L) {
1787 get_ref<SkSurface>(L, 1)->unref();
1788 return 0;
1789}
1790
1791static const struct luaL_Reg gSkSurface_Methods[] = {
1792 { "width", lsurface_width },
1793 { "height", lsurface_height },
1794 { "getCanvas", lsurface_getCanvas },
1795 { "newImageSnapshot", lsurface_newImageSnapshot },
1796 { "newSurface", lsurface_newSurface },
1797 { "__gc", lsurface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001798 { nullptr, nullptr }
reed485557f2014-10-12 10:36:47 -07001799};
1800
1801///////////////////////////////////////////////////////////////////////////////
1802
reed96affcd2014-10-13 12:38:04 -07001803static int lpicturerecorder_beginRecording(lua_State* L) {
1804 const SkScalar w = lua2scalar_def(L, 2, -1);
1805 const SkScalar h = lua2scalar_def(L, 3, -1);
1806 if (w <= 0 || h <= 0) {
1807 lua_pushnil(L);
1808 return 1;
1809 }
1810
1811 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
halcanary96fcdcc2015-08-27 07:41:13 -07001812 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001813 lua_pushnil(L);
1814 return 1;
1815 }
1816
1817 push_ref(L, canvas);
1818 return 1;
1819}
1820
1821static int lpicturerecorder_getCanvas(lua_State* L) {
1822 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001823 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001824 lua_pushnil(L);
1825 return 1;
1826 }
1827 push_ref(L, canvas);
1828 return 1;
1829}
1830
1831static int lpicturerecorder_endRecording(lua_State* L) {
reedca2622b2016-03-18 07:25:55 -07001832 sk_sp<SkPicture> pic = get_obj<SkPictureRecorder>(L, 1)->finishRecordingAsPicture();
1833 if (!pic) {
reed96affcd2014-10-13 12:38:04 -07001834 lua_pushnil(L);
1835 return 1;
1836 }
reedca2622b2016-03-18 07:25:55 -07001837 push_ref(L, std::move(pic));
reed96affcd2014-10-13 12:38:04 -07001838 return 1;
1839}
1840
1841static int lpicturerecorder_gc(lua_State* L) {
1842 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1843 return 0;
1844}
1845
1846static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1847 { "beginRecording", lpicturerecorder_beginRecording },
1848 { "getCanvas", lpicturerecorder_getCanvas },
1849 { "endRecording", lpicturerecorder_endRecording },
1850 { "__gc", lpicturerecorder_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001851 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001852};
1853
1854///////////////////////////////////////////////////////////////////////////////
1855
1856static int lpicture_width(lua_State* L) {
1857 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1858 return 1;
1859}
1860
1861static int lpicture_height(lua_State* L) {
1862 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1863 return 1;
1864}
1865
1866static int lpicture_gc(lua_State* L) {
1867 get_ref<SkPicture>(L, 1)->unref();
1868 return 0;
1869}
1870
1871static const struct luaL_Reg gSkPicture_Methods[] = {
1872 { "width", lpicture_width },
1873 { "height", lpicture_height },
1874 { "__gc", lpicture_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001875 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001876};
1877
1878///////////////////////////////////////////////////////////////////////////////
1879
reed1b6ab442014-11-03 19:55:41 -08001880static int ltextblob_bounds(lua_State* L) {
1881 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
1882 return 1;
1883}
1884
1885static int ltextblob_gc(lua_State* L) {
1886 SkSafeUnref(get_ref<SkTextBlob>(L, 1));
1887 return 0;
1888}
1889
1890static const struct luaL_Reg gSkTextBlob_Methods[] = {
1891 { "bounds", ltextblob_bounds },
1892 { "__gc", ltextblob_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001893 { nullptr, nullptr }
reed1b6ab442014-11-03 19:55:41 -08001894};
1895
1896///////////////////////////////////////////////////////////////////////////////
1897
reed36c9c112014-11-04 10:58:42 -08001898static int ltypeface_getFamilyName(lua_State* L) {
1899 SkString str;
1900 get_ref<SkTypeface>(L, 1)->getFamilyName(&str);
1901 lua_pushstring(L, str.c_str());
1902 return 1;
1903}
1904
1905static int ltypeface_getStyle(lua_State* L) {
1906 lua_pushnumber(L, (double)get_ref<SkTypeface>(L, 1)->style());
1907 return 1;
1908}
1909
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001910static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001911 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001912 return 0;
1913}
1914
1915static const struct luaL_Reg gSkTypeface_Methods[] = {
reed36c9c112014-11-04 10:58:42 -08001916 { "getFamilyName", ltypeface_getFamilyName },
1917 { "getStyle", ltypeface_getStyle },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001918 { "__gc", ltypeface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001919 { nullptr, nullptr }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001920};
1921
1922///////////////////////////////////////////////////////////////////////////////
1923
reed@google.com74ce6f02013-05-22 15:13:18 +00001924class AutoCallLua {
1925public:
1926 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1927 lua_getglobal(L, func);
1928 if (!lua_isfunction(L, -1)) {
1929 int t = lua_type(L, -1);
1930 SkDebugf("--- expected function %d\n", t);
1931 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001932
reed@google.com74ce6f02013-05-22 15:13:18 +00001933 lua_newtable(L);
1934 setfield_string(L, "verb", verb);
1935 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001936
reed@google.com74ce6f02013-05-22 15:13:18 +00001937 ~AutoCallLua() {
1938 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1939 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1940 }
1941 lua_settop(fL, -1);
1942 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001943
reed@google.com74ce6f02013-05-22 15:13:18 +00001944private:
1945 lua_State* fL;
1946};
1947
1948#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1949
1950///////////////////////////////////////////////////////////////////////////////
1951
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001952static int lsk_newDocumentPDF(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001953 const char* file = nullptr;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001954 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001955 file = lua_tolstring(L, 1, nullptr);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001956 }
1957
halcanary676ab682016-05-03 12:10:04 -07001958 sk_sp<SkDocument> doc = SkDocument::MakePDF(file);
halcanary96fcdcc2015-08-27 07:41:13 -07001959 if (nullptr == doc) {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001960 // do I need to push a nil on the stack and return 1?
1961 return 0;
1962 } else {
halcanary676ab682016-05-03 12:10:04 -07001963 push_ref(L, std::move(doc));
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001964 return 1;
1965 }
1966}
1967
reed468b1812014-10-19 11:42:54 -07001968static int lsk_newBlurImageFilter(lua_State* L) {
1969 SkScalar sigmaX = lua2scalar_def(L, 1, 0);
1970 SkScalar sigmaY = lua2scalar_def(L, 2, 0);
robertphillips6e7025a2016-04-04 04:31:25 -07001971 sk_sp<SkImageFilter> imf(SkBlurImageFilter::Make(sigmaX, sigmaY, nullptr));
1972 if (!imf) {
reed468b1812014-10-19 11:42:54 -07001973 lua_pushnil(L);
1974 } else {
robertphillips6e7025a2016-04-04 04:31:25 -07001975 push_ref(L, std::move(imf));
reed9fbc3f32014-10-21 07:12:58 -07001976 }
1977 return 1;
1978}
1979
1980static int lsk_newLinearGradient(lua_State* L) {
1981 SkScalar x0 = lua2scalar_def(L, 1, 0);
1982 SkScalar y0 = lua2scalar_def(L, 2, 0);
1983 SkColor c0 = lua2color(L, 3);
1984 SkScalar x1 = lua2scalar_def(L, 4, 0);
1985 SkScalar y1 = lua2scalar_def(L, 5, 0);
1986 SkColor c1 = lua2color(L, 6);
1987
1988 SkPoint pts[] = { { x0, y0 }, { x1, y1 } };
1989 SkColor colors[] = { c0, c1 };
robertphillips6e7025a2016-04-04 04:31:25 -07001990 sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
1991 SkShader::kClamp_TileMode));
reed2ad1aa62016-03-09 09:50:50 -08001992 if (!s) {
reed9fbc3f32014-10-21 07:12:58 -07001993 lua_pushnil(L);
1994 } else {
reed2ad1aa62016-03-09 09:50:50 -08001995 push_ref(L, std::move(s));
reed468b1812014-10-19 11:42:54 -07001996 }
1997 return 1;
1998}
1999
reedbdc49ae2014-10-14 09:34:52 -07002000static int lsk_newMatrix(lua_State* L) {
2001 push_new<SkMatrix>(L)->reset();
2002 return 1;
2003}
2004
reed@google.com3597b732013-05-22 20:12:50 +00002005static int lsk_newPaint(lua_State* L) {
2006 push_new<SkPaint>(L);
2007 return 1;
2008}
2009
2010static int lsk_newPath(lua_State* L) {
2011 push_new<SkPath>(L);
2012 return 1;
2013}
2014
reed96affcd2014-10-13 12:38:04 -07002015static int lsk_newPictureRecorder(lua_State* L) {
2016 push_new<SkPictureRecorder>(L);
2017 return 1;
2018}
2019
reed@google.com3597b732013-05-22 20:12:50 +00002020static int lsk_newRRect(lua_State* L) {
reedbdc49ae2014-10-14 09:34:52 -07002021 push_new<SkRRect>(L)->setEmpty();
reed@google.com3597b732013-05-22 20:12:50 +00002022 return 1;
2023}
2024
reed1b6ab442014-11-03 19:55:41 -08002025#include "SkTextBox.h"
2026// Sk.newTextBlob(text, rect, paint)
2027static int lsk_newTextBlob(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07002028 const char* text = lua_tolstring(L, 1, nullptr);
reed1b6ab442014-11-03 19:55:41 -08002029 SkRect bounds;
2030 lua2rect(L, 2, &bounds);
2031 const SkPaint& paint = *get_obj<SkPaint>(L, 3);
2032
2033 SkTextBox box;
2034 box.setMode(SkTextBox::kLineBreak_Mode);
2035 box.setBox(bounds);
2036 box.setText(text, strlen(text), paint);
2037
2038 SkScalar newBottom;
fmalita37283c22016-09-13 10:00:23 -07002039 push_ref<SkTextBlob>(L, box.snapshotTextBlob(&newBottom));
reed1b6ab442014-11-03 19:55:41 -08002040 SkLua(L).pushScalar(newBottom);
2041 return 2;
2042}
2043
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002044static int lsk_newTypeface(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07002045 const char* name = nullptr;
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002046 int style = SkTypeface::kNormal;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00002047
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002048 int count = lua_gettop(L);
2049 if (count > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002050 name = lua_tolstring(L, 1, nullptr);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002051 if (count > 1 && lua_isnumber(L, 2)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002052 style = lua_tointegerx(L, 2, nullptr) & SkTypeface::kBoldItalic;
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002053 }
2054 }
2055
mbocee6a9912016-05-31 11:42:36 -07002056 sk_sp<SkTypeface> face(SkTypeface::MakeFromName(name, SkFontStyle::FromOldStyle(style)));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002057// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
halcanary96fcdcc2015-08-27 07:41:13 -07002058 if (nullptr == face) {
bungeman13b9c952016-05-12 10:09:30 -07002059 face = SkTypeface::MakeDefault();
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002060 }
bungeman13b9c952016-05-12 10:09:30 -07002061 push_ref(L, std::move(face));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002062 return 1;
2063}
reed@google.com3597b732013-05-22 20:12:50 +00002064
reed485557f2014-10-12 10:36:47 -07002065static int lsk_newRasterSurface(lua_State* L) {
reed7b864662014-11-04 13:24:47 -08002066 int width = lua2int_def(L, 1, 0);
reed485557f2014-10-12 10:36:47 -07002067 int height = lua2int_def(L, 2, 0);
2068 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
robertphillips702edbd2015-06-23 06:26:08 -07002069 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
reede8f30622016-03-23 18:59:25 -07002070 auto surface = SkSurface::MakeRaster(info, &props);
halcanary96fcdcc2015-08-27 07:41:13 -07002071 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07002072 lua_pushnil(L);
2073 } else {
reede8f30622016-03-23 18:59:25 -07002074 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07002075 }
2076 return 1;
2077}
2078
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002079static int lsk_loadImage(lua_State* L) {
2080 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002081 const char* name = lua_tolstring(L, 1, nullptr);
reed9ce9d672016-03-17 10:51:11 -07002082 sk_sp<SkData> data(SkData::MakeFromFileName(name));
2083 if (data) {
2084 auto image = SkImage::MakeFromEncoded(std::move(data));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002085 if (image) {
reed9ce9d672016-03-17 10:51:11 -07002086 push_ref(L, std::move(image));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002087 return 1;
2088 }
2089 }
2090 }
2091 return 0;
2092}
2093
reed@google.com3597b732013-05-22 20:12:50 +00002094static void register_Sk(lua_State* L) {
2095 lua_newtable(L);
2096 lua_pushvalue(L, -1);
2097 lua_setglobal(L, "Sk");
2098 // the Sk table is still on top
2099
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00002100 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002101 setfield_function(L, "loadImage", lsk_loadImage);
reed468b1812014-10-19 11:42:54 -07002102 setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
reed9fbc3f32014-10-21 07:12:58 -07002103 setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
reedbdc49ae2014-10-14 09:34:52 -07002104 setfield_function(L, "newMatrix", lsk_newMatrix);
reed@google.com3597b732013-05-22 20:12:50 +00002105 setfield_function(L, "newPaint", lsk_newPaint);
2106 setfield_function(L, "newPath", lsk_newPath);
reed96affcd2014-10-13 12:38:04 -07002107 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
reed@google.com3597b732013-05-22 20:12:50 +00002108 setfield_function(L, "newRRect", lsk_newRRect);
reed485557f2014-10-12 10:36:47 -07002109 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
reed1b6ab442014-11-03 19:55:41 -08002110 setfield_function(L, "newTextBlob", lsk_newTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002111 setfield_function(L, "newTypeface", lsk_newTypeface);
reed@google.com3597b732013-05-22 20:12:50 +00002112 lua_pop(L, 1); // pop off the Sk table
2113}
2114
reed@google.com74ce6f02013-05-22 15:13:18 +00002115#define REG_CLASS(L, C) \
2116 do { \
reed@google.com3597b732013-05-22 20:12:50 +00002117 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00002118 lua_pushvalue(L, -1); \
2119 lua_setfield(L, -2, "__index"); \
2120 luaL_setfuncs(L, g##C##_Methods, 0); \
2121 lua_pop(L, 1); /* pop off the meta-table */ \
2122 } while (0)
2123
2124void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00002125 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00002126 REG_CLASS(L, SkCanvas);
reed22a517f2015-12-04 20:45:59 -08002127 REG_CLASS(L, SkColorFilter);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00002128 REG_CLASS(L, SkDocument);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002129 REG_CLASS(L, SkImage);
reed468b1812014-10-19 11:42:54 -07002130 REG_CLASS(L, SkImageFilter);
reed1b6ab442014-11-03 19:55:41 -08002131 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00002132 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00002133 REG_CLASS(L, SkPath);
2134 REG_CLASS(L, SkPathEffect);
reed96affcd2014-10-13 12:38:04 -07002135 REG_CLASS(L, SkPicture);
2136 REG_CLASS(L, SkPictureRecorder);
reed@google.com74ce6f02013-05-22 15:13:18 +00002137 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00002138 REG_CLASS(L, SkShader);
reed485557f2014-10-12 10:36:47 -07002139 REG_CLASS(L, SkSurface);
reed1b6ab442014-11-03 19:55:41 -08002140 REG_CLASS(L, SkTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002141 REG_CLASS(L, SkTypeface);
reed@google.com74ce6f02013-05-22 15:13:18 +00002142}
zachr@google.com28c27c82013-06-20 17:15:05 +00002143
reed@google.com7bce9982013-06-20 17:40:21 +00002144extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00002145extern "C" int luaopen_skia(lua_State* L) {
2146 SkLua::Load(L);
2147 return 0;
2148}