blob: 4a6546575f86ed630962a0bd08769ce2fd9019ef [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
reed@google.com74ce6f02013-05-22 15:13:18 +000014#include "SkCanvas.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000015#include "SkData.h"
piotaixr4bcc2022014-09-17 14:33:30 -070016#include "SkDecodingImageGenerator.h"
mike@reedtribe.orgfb858242013-06-08 16:39:44 +000017#include "SkDocument.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000018#include "SkImage.h"
19#include "SkMatrix.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000020#include "SkPaint.h"
21#include "SkPath.h"
reed@google.com5fdc9832013-07-24 15:47:52 +000022#include "SkPixelRef.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000023#include "SkRRect.h"
24#include "SkString.h"
fmalitab7425172014-08-26 07:56:44 -070025#include "SkTextBlob.h"
reed@google.come3823fd2013-05-30 18:55:14 +000026#include "SkTypeface.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000027
28extern "C" {
reed@google.com3597b732013-05-22 20:12:50 +000029 #include "lua.h"
30 #include "lualib.h"
31 #include "lauxlib.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000032}
33
reed@google.comfd345872013-05-22 20:53:42 +000034// return the metatable name for a given class
reed@google.com3597b732013-05-22 20:12:50 +000035template <typename T> const char* get_mtname();
reed@google.comfd345872013-05-22 20:53:42 +000036#define DEF_MTNAME(T) \
37 template <> const char* get_mtname<T>() { \
38 return #T "_LuaMetaTableName"; \
39 }
40
41DEF_MTNAME(SkCanvas)
mike@reedtribe.orgfb858242013-06-08 16:39:44 +000042DEF_MTNAME(SkDocument)
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000043DEF_MTNAME(SkImage)
reed@google.comfd345872013-05-22 20:53:42 +000044DEF_MTNAME(SkMatrix)
45DEF_MTNAME(SkRRect)
46DEF_MTNAME(SkPath)
47DEF_MTNAME(SkPaint)
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +000048DEF_MTNAME(SkPathEffect)
reed@google.com5fdc9832013-07-24 15:47:52 +000049DEF_MTNAME(SkShader)
fmalitab7425172014-08-26 07:56:44 -070050DEF_MTNAME(SkTextBlob)
mike@reedtribe.orge6469f12013-06-08 03:15:47 +000051DEF_MTNAME(SkTypeface)
reed@google.com74ce6f02013-05-22 15:13:18 +000052
reed@google.com3597b732013-05-22 20:12:50 +000053template <typename T> T* push_new(lua_State* L) {
54 T* addr = (T*)lua_newuserdata(L, sizeof(T));
55 new (addr) T;
56 luaL_getmetatable(L, get_mtname<T>());
57 lua_setmetatable(L, -2);
58 return addr;
59}
reed@google.com74ce6f02013-05-22 15:13:18 +000060
61template <typename T> void push_obj(lua_State* L, const T& obj) {
62 new (lua_newuserdata(L, sizeof(T))) T(obj);
reed@google.com3597b732013-05-22 20:12:50 +000063 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000064 lua_setmetatable(L, -2);
65}
66
67template <typename T> void push_ref(lua_State* L, T* ref) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +000068 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
reed@google.com3597b732013-05-22 20:12:50 +000069 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000070 lua_setmetatable(L, -2);
71}
72
73template <typename T> T* get_ref(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +000074 return *(T**)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000075}
76
77template <typename T> T* get_obj(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +000078 return (T*)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000079}
80
reed@google.com88c9ec92013-05-22 15:43:21 +000081static bool lua2bool(lua_State* L, int index) {
82 return !!lua_toboolean(L, index);
83}
84
reed@google.com74ce6f02013-05-22 15:13:18 +000085///////////////////////////////////////////////////////////////////////////////
86
reed@google.com3597b732013-05-22 20:12:50 +000087SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
88 fL = luaL_newstate();
89 luaL_openlibs(fL);
90 SkLua::Load(fL);
91}
92
93SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
94
95SkLua::~SkLua() {
96 if (fWeOwnL) {
97 if (fTermCode.size() > 0) {
98 lua_getglobal(fL, fTermCode.c_str());
99 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
100 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
101 }
102 }
103 lua_close(fL);
104 }
105}
106
107bool SkLua::runCode(const char code[]) {
108 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
109 if (err) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000110 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
reed@google.com3597b732013-05-22 20:12:50 +0000111 return false;
112 }
113 return true;
114}
115
116bool SkLua::runCode(const void* code, size_t size) {
117 SkString str((const char*)code, size);
118 return this->runCode(str.c_str());
119}
120
121///////////////////////////////////////////////////////////////////////////////
122
123#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
124
reed@google.com29563872013-07-10 21:23:49 +0000125static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
126 if (pred) {
127 lua_pushboolean(L, true);
128 lua_setfield(L, -2, key);
129 }
130}
131
reed@google.com74ce6f02013-05-22 15:13:18 +0000132static void setfield_string(lua_State* L, const char key[], const char value[]) {
133 lua_pushstring(L, value);
134 lua_setfield(L, -2, key);
135}
136
137static void setfield_number(lua_State* L, const char key[], double value) {
138 lua_pushnumber(L, value);
139 lua_setfield(L, -2, key);
140}
141
humper@google.com2815c192013-07-10 22:42:30 +0000142static void setfield_boolean(lua_State* L, const char key[], bool value) {
143 lua_pushboolean(L, value);
144 lua_setfield(L, -2, key);
145}
146
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000147static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
148 setfield_number(L, key, SkScalarToLua(value));
149}
150
reed@google.com3597b732013-05-22 20:12:50 +0000151static void setfield_function(lua_State* L,
152 const char key[], lua_CFunction value) {
153 lua_pushcfunction(L, value);
154 lua_setfield(L, -2, key);
reed@google.com74ce6f02013-05-22 15:13:18 +0000155}
156
reed@google.come3823fd2013-05-30 18:55:14 +0000157static void setarray_number(lua_State* L, int index, double value) {
158 lua_pushnumber(L, value);
159 lua_rawseti(L, -2, index);
160}
161
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000162static void setarray_scalar(lua_State* L, int index, SkScalar value) {
163 setarray_number(L, index, SkScalarToLua(value));
164}
165
reed@google.com74ce6f02013-05-22 15:13:18 +0000166void SkLua::pushBool(bool value, const char key[]) {
167 lua_pushboolean(fL, value);
168 CHECK_SETFIELD(key);
169}
170
171void SkLua::pushString(const char str[], const char key[]) {
172 lua_pushstring(fL, str);
173 CHECK_SETFIELD(key);
174}
175
reed@google.come3823fd2013-05-30 18:55:14 +0000176void SkLua::pushString(const char str[], size_t length, const char key[]) {
177 // TODO: how to do this w/o making a copy?
178 SkString s(str, length);
179 lua_pushstring(fL, s.c_str());
180 CHECK_SETFIELD(key);
181}
182
reed@google.com74ce6f02013-05-22 15:13:18 +0000183void SkLua::pushString(const SkString& str, const char key[]) {
184 lua_pushstring(fL, str.c_str());
185 CHECK_SETFIELD(key);
186}
187
188void SkLua::pushColor(SkColor color, const char key[]) {
189 lua_newtable(fL);
190 setfield_number(fL, "a", SkColorGetA(color) / 255.0);
191 setfield_number(fL, "r", SkColorGetR(color) / 255.0);
192 setfield_number(fL, "g", SkColorGetG(color) / 255.0);
193 setfield_number(fL, "b", SkColorGetB(color) / 255.0);
194 CHECK_SETFIELD(key);
195}
196
reed@google.come3823fd2013-05-30 18:55:14 +0000197void SkLua::pushU32(uint32_t value, const char key[]) {
198 lua_pushnumber(fL, (double)value);
199 CHECK_SETFIELD(key);
200}
201
reed@google.com74ce6f02013-05-22 15:13:18 +0000202void SkLua::pushScalar(SkScalar value, const char key[]) {
203 lua_pushnumber(fL, SkScalarToLua(value));
204 CHECK_SETFIELD(key);
205}
206
reed@google.come3823fd2013-05-30 18:55:14 +0000207void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
208 lua_newtable(fL);
209 for (int i = 0; i < count; ++i) {
210 // make it base-1 to match lua convention
211 setarray_number(fL, i + 1, (double)array[i]);
212 }
213 CHECK_SETFIELD(key);
214}
215
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000216void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
217 lua_newtable(fL);
218 for (int i = 0; i < count; ++i) {
219 // make it base-1 to match lua convention
220 lua_newtable(fL);
221 this->pushScalar(array[i].fX, "x");
222 this->pushScalar(array[i].fY, "y");
223 lua_rawseti(fL, -2, i + 1);
224 }
225 CHECK_SETFIELD(key);
226}
227
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000228void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
229 lua_newtable(fL);
230 for (int i = 0; i < count; ++i) {
231 // make it base-1 to match lua convention
232 setarray_scalar(fL, i + 1, array[i]);
233 }
234 CHECK_SETFIELD(key);
235}
236
reed@google.com74ce6f02013-05-22 15:13:18 +0000237void SkLua::pushRect(const SkRect& r, const char key[]) {
238 lua_newtable(fL);
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000239 setfield_scalar(fL, "left", r.fLeft);
240 setfield_scalar(fL, "top", r.fTop);
241 setfield_scalar(fL, "right", r.fRight);
242 setfield_scalar(fL, "bottom", r.fBottom);
reed@google.com74ce6f02013-05-22 15:13:18 +0000243 CHECK_SETFIELD(key);
244}
245
246void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
247 push_obj(fL, rr);
248 CHECK_SETFIELD(key);
249}
250
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000251void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
252 lua_newtable(fL);
253 setfield_scalar(fL, "phase", info.fPhase);
254 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
255 CHECK_SETFIELD(key);
256}
257
258
reed@google.com74ce6f02013-05-22 15:13:18 +0000259void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
260 push_obj(fL, matrix);
261 CHECK_SETFIELD(key);
262}
263
264void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
265 push_obj(fL, paint);
266 CHECK_SETFIELD(key);
267}
268
269void SkLua::pushPath(const SkPath& path, const char key[]) {
270 push_obj(fL, path);
271 CHECK_SETFIELD(key);
272}
273
274void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
275 push_ref(fL, canvas);
276 CHECK_SETFIELD(key);
277}
278
fmalitab7425172014-08-26 07:56:44 -0700279void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
280 push_ref(fL, const_cast<SkTextBlob*>(blob));
281 CHECK_SETFIELD(key);
282}
283
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000284static const char* element_type(SkClipStack::Element::Type type) {
285 switch (type) {
286 case SkClipStack::Element::kEmpty_Type:
287 return "empty";
288 case SkClipStack::Element::kRect_Type:
289 return "rect";
290 case SkClipStack::Element::kRRect_Type:
291 return "rrect";
292 case SkClipStack::Element::kPath_Type:
293 return "path";
294 }
295 return "unknown";
296}
297
298static const char* region_op(SkRegion::Op op) {
299 switch (op) {
300 case SkRegion::kDifference_Op:
301 return "difference";
302 case SkRegion::kIntersect_Op:
303 return "intersect";
304 case SkRegion::kUnion_Op:
305 return "union";
306 case SkRegion::kXOR_Op:
307 return "xor";
308 case SkRegion::kReverseDifference_Op:
309 return "reverse-difference";
310 case SkRegion::kReplace_Op:
311 return "replace";
312 }
313 return "unknown";
314}
315
316void SkLua::pushClipStack(const SkClipStack& stack, const char* key) {
317 lua_newtable(fL);
318 SkClipStack::B2TIter iter(stack);
319 const SkClipStack::Element* element;
320 int i = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700321 while ((element = iter.next())) {
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000322 this->pushClipStackElement(*element);
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000323 lua_rawseti(fL, -2, ++i);
324 }
325 CHECK_SETFIELD(key);
326}
327
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000328void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) {
329 lua_newtable(fL);
330 SkClipStack::Element::Type type = element.getType();
331 this->pushString(element_type(type), "type");
332 switch (type) {
333 case SkClipStack::Element::kEmpty_Type:
334 break;
335 case SkClipStack::Element::kRect_Type:
336 this->pushRect(element.getRect(), "rect");
337 break;
338 case SkClipStack::Element::kRRect_Type:
339 this->pushRRect(element.getRRect(), "rrect");
340 break;
341 case SkClipStack::Element::kPath_Type:
342 this->pushPath(element.getPath(), "path");
343 break;
344 }
345 this->pushString(region_op(element.getOp()), "op");
346 this->pushBool(element.isAA(), "aa");
347 CHECK_SETFIELD(key);
348}
349
350
reed@google.com74ce6f02013-05-22 15:13:18 +0000351///////////////////////////////////////////////////////////////////////////////
352///////////////////////////////////////////////////////////////////////////////
353
354static SkScalar lua2scalar(lua_State* L, int index) {
355 SkASSERT(lua_isnumber(L, index));
356 return SkLuaToScalar(lua_tonumber(L, index));
357}
358
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000359static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
360 if (lua_isnumber(L, index)) {
361 return SkLuaToScalar(lua_tonumber(L, index));
362 } else {
363 return defaultValue;
364 }
365}
366
reed@google.com74ce6f02013-05-22 15:13:18 +0000367static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
368 SkASSERT(lua_istable(L, index));
369 lua_pushstring(L, key);
370 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000371
reed@google.com74ce6f02013-05-22 15:13:18 +0000372 SkScalar value = lua2scalar(L, -1);
373 lua_pop(L, 1);
374 return value;
375}
376
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000377static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
378 SkASSERT(lua_istable(L, index));
379 lua_pushstring(L, key);
380 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000381
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000382 SkScalar value;
383 if (lua_isnil(L, -1)) {
384 value = def;
385 } else {
386 value = lua2scalar(L, -1);
387 }
388 lua_pop(L, 1);
389 return value;
390}
391
reed@google.com74ce6f02013-05-22 15:13:18 +0000392static U8CPU unit2byte(SkScalar x) {
393 if (x <= 0) {
394 return 0;
395 } else if (x >= 1) {
396 return 255;
397 } else {
398 return SkScalarRoundToInt(x * 255);
399 }
400}
401
402static SkColor lua2color(lua_State* L, int index) {
403 return SkColorSetARGB(unit2byte(getfield_scalar(L, index, "a")),
404 unit2byte(getfield_scalar(L, index, "r")),
405 unit2byte(getfield_scalar(L, index, "g")),
406 unit2byte(getfield_scalar(L, index, "b")));
407}
408
409static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000410 rect->set(getfield_scalar_default(L, index, "left", 0),
411 getfield_scalar_default(L, index, "top", 0),
reed@google.com74ce6f02013-05-22 15:13:18 +0000412 getfield_scalar(L, index, "right"),
413 getfield_scalar(L, index, "bottom"));
414 return rect;
415}
416
417static int lcanvas_drawColor(lua_State* L) {
418 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
419 return 0;
420}
421
422static int lcanvas_drawRect(lua_State* L) {
423 SkRect rect;
424 get_ref<SkCanvas>(L, 1)->drawRect(*lua2rect(L, 2, &rect),
425 *get_obj<SkPaint>(L, 3));
426 return 0;
427}
428
429static int lcanvas_drawOval(lua_State* L) {
430 SkRect rect;
431 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
432 *get_obj<SkPaint>(L, 3));
433 return 0;
434}
435
436static int lcanvas_drawCircle(lua_State* L) {
437 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
438 lua2scalar(L, 3),
439 lua2scalar(L, 4),
440 *get_obj<SkPaint>(L, 5));
441 return 0;
442}
443
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000444static int lcanvas_drawImage(lua_State* L) {
445 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
446 SkImage* image = get_ref<SkImage>(L, 2);
447 if (NULL == image) {
448 return 0;
449 }
450 SkScalar x = lua2scalar(L, 3);
451 SkScalar y = lua2scalar(L, 4);
452
453 SkPaint paint;
454 const SkPaint* paintPtr = NULL;
455 if (lua_isnumber(L, 5)) {
456 paint.setAlpha(SkScalarRoundToInt(lua2scalar(L, 5) * 255));
457 paintPtr = &paint;
458 }
piotaixrb5fae932014-09-24 13:03:30 -0700459 canvas->drawImage(image, x, y, paintPtr);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000460 return 0;
461}
462
reedba5fb932014-10-10 15:28:19 -0700463static int lcanvas_drawImageRect(lua_State* L) {
464 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
465 SkImage* image = get_ref<SkImage>(L, 2);
466 if (NULL == image) {
467 return 0;
468 }
469
470 SkRect srcR, dstR;
471 SkRect* srcRPtr = NULL;
472 if (!lua_isnil(L, 3)) {
473 srcRPtr = lua2rect(L, 3, &srcR);
474 }
475 lua2rect(L, 4, &dstR);
476
477 SkPaint paint;
478 const SkPaint* paintPtr = NULL;
479 if (lua_isnumber(L, 5)) {
480 paint.setAlpha(SkScalarRoundToInt(lua2scalar(L, 5) * 255));
481 paintPtr = &paint;
482 }
483 canvas->drawImageRect(image, srcRPtr, dstR, paintPtr);
484 return 0;
485}
486
reed@google.comfd345872013-05-22 20:53:42 +0000487static int lcanvas_drawPath(lua_State* L) {
488 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
489 *get_obj<SkPaint>(L, 3));
490 return 0;
491}
492
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000493static int lcanvas_drawText(lua_State* L) {
494 if (lua_gettop(L) < 5) {
495 return 0;
496 }
497
498 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
499 size_t len;
500 const char* text = lua_tolstring(L, 2, &len);
501 get_ref<SkCanvas>(L, 1)->drawText(text, len,
502 lua2scalar(L, 3), lua2scalar(L, 4),
503 *get_obj<SkPaint>(L, 5));
504 }
505 return 0;
506}
507
reed@google.com74ce6f02013-05-22 15:13:18 +0000508static int lcanvas_getSaveCount(lua_State* L) {
509 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
510 return 1;
511}
512
513static int lcanvas_getTotalMatrix(lua_State* L) {
514 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
515 return 1;
516}
517
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000518static int lcanvas_getClipStack(lua_State* L) {
519 SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack());
520 return 1;
521}
522
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000523int SkLua::lcanvas_getReducedClipStack(lua_State* L) {
524#if SK_SUPPORT_GPU
525 const SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
526 SkISize layerSize = canvas->getTopLayerSize();
527 SkIPoint layerOrigin = canvas->getTopLayerOrigin();
528 SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY,
529 layerSize.fWidth, layerSize.fHeight);
530
531 GrReducedClip::ElementList elements;
532 GrReducedClip::InitialState initialState;
533 int32_t genID;
534 SkIRect resultBounds;
535
536 const SkClipStack& stack = *canvas->getClipStack();
537
538 GrReducedClip::ReduceClipStack(stack,
539 queryBounds,
540 &elements,
541 &genID,
542 &initialState,
543 &resultBounds,
544 NULL);
545
546 GrReducedClip::ElementList::Iter iter(elements);
547 int i = 0;
548 lua_newtable(L);
bsalomon49f085d2014-09-05 13:34:00 -0700549 while(iter.get()) {
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000550 SkLua(L).pushClipStackElement(*iter.get());
551 iter.next();
552 lua_rawseti(L, -2, ++i);
553 }
554 // Currently this only returns the element list to lua, not the initial state or result bounds.
555 // It could return these as additional items on the lua stack.
556 return 1;
557#else
558 return 0;
559#endif
560}
561
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000562static int lcanvas_save(lua_State* L) {
563 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
564 return 1;
565}
566
567static int lcanvas_restore(lua_State* L) {
568 get_ref<SkCanvas>(L, 1)->restore();
569 return 0;
570}
571
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000572static int lcanvas_scale(lua_State* L) {
573 SkScalar sx = lua2scalar_def(L, 2, 1);
574 SkScalar sy = lua2scalar_def(L, 3, sx);
575 get_ref<SkCanvas>(L, 1)->scale(sx, sy);
576 return 0;
577}
578
reed@google.com3597b732013-05-22 20:12:50 +0000579static int lcanvas_translate(lua_State* L) {
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000580 SkScalar tx = lua2scalar_def(L, 2, 0);
581 SkScalar ty = lua2scalar_def(L, 3, 0);
582 get_ref<SkCanvas>(L, 1)->translate(tx, ty);
583 return 0;
584}
585
586static int lcanvas_rotate(lua_State* L) {
587 SkScalar degrees = lua2scalar_def(L, 2, 0);
588 get_ref<SkCanvas>(L, 1)->rotate(degrees);
reed@google.com3597b732013-05-22 20:12:50 +0000589 return 0;
590}
591
reed@google.com74ce6f02013-05-22 15:13:18 +0000592static int lcanvas_gc(lua_State* L) {
593 get_ref<SkCanvas>(L, 1)->unref();
594 return 0;
595}
596
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000597const struct luaL_Reg gSkCanvas_Methods[] = {
reed@google.com74ce6f02013-05-22 15:13:18 +0000598 { "drawColor", lcanvas_drawColor },
599 { "drawRect", lcanvas_drawRect },
600 { "drawOval", lcanvas_drawOval },
601 { "drawCircle", lcanvas_drawCircle },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000602 { "drawImage", lcanvas_drawImage },
reedba5fb932014-10-10 15:28:19 -0700603 { "drawImageRect", lcanvas_drawImageRect },
reed@google.comfd345872013-05-22 20:53:42 +0000604 { "drawPath", lcanvas_drawPath },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000605 { "drawText", lcanvas_drawText },
reed@google.com74ce6f02013-05-22 15:13:18 +0000606 { "getSaveCount", lcanvas_getSaveCount },
607 { "getTotalMatrix", lcanvas_getTotalMatrix },
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000608 { "getClipStack", lcanvas_getClipStack },
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000609#if SK_SUPPORT_GPU
610 { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
611#endif
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000612 { "save", lcanvas_save },
613 { "restore", lcanvas_restore },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000614 { "scale", lcanvas_scale },
reed@google.com3597b732013-05-22 20:12:50 +0000615 { "translate", lcanvas_translate },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000616 { "rotate", lcanvas_rotate },
reed@google.com74ce6f02013-05-22 15:13:18 +0000617 { "__gc", lcanvas_gc },
618 { NULL, NULL }
619};
620
621///////////////////////////////////////////////////////////////////////////////
622
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000623static int ldocument_beginPage(lua_State* L) {
624 const SkRect* contentPtr = NULL;
625 push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2),
626 lua2scalar(L, 3),
627 contentPtr));
628 return 1;
629}
630
631static int ldocument_endPage(lua_State* L) {
632 get_ref<SkDocument>(L, 1)->endPage();
633 return 0;
634}
635
636static int ldocument_close(lua_State* L) {
637 get_ref<SkDocument>(L, 1)->close();
638 return 0;
639}
640
641static int ldocument_gc(lua_State* L) {
642 get_ref<SkDocument>(L, 1)->unref();
643 return 0;
644}
645
646static const struct luaL_Reg gSkDocument_Methods[] = {
647 { "beginPage", ldocument_beginPage },
648 { "endPage", ldocument_endPage },
649 { "close", ldocument_close },
650 { "__gc", ldocument_gc },
651 { NULL, NULL }
652};
653
654///////////////////////////////////////////////////////////////////////////////
655
reed@google.com74ce6f02013-05-22 15:13:18 +0000656static int lpaint_isAntiAlias(lua_State* L) {
657 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
658 return 1;
659}
660
661static int lpaint_setAntiAlias(lua_State* L) {
reed@google.com88c9ec92013-05-22 15:43:21 +0000662 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +0000663 return 0;
664}
665
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000666static int lpaint_isDither(lua_State* L) {
667 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
668 return 1;
669}
670
671static int lpaint_isUnderlineText(lua_State* L) {
672 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText());
673 return 1;
674}
675
676static int lpaint_isStrikeThruText(lua_State* L) {
677 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText());
678 return 1;
679}
680
681static int lpaint_isFakeBoldText(lua_State* L) {
682 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
683 return 1;
684}
685
686static int lpaint_isLinearText(lua_State* L) {
687 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
688 return 1;
689}
690
691static int lpaint_isSubpixelText(lua_State* L) {
692 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
693 return 1;
694}
695
reed09a1d672014-10-11 13:13:11 -0700696static int lpaint_setSubpixelText(lua_State* L) {
697 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
698 return 1;
699}
700
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000701static int lpaint_isDevKernText(lua_State* L) {
702 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
703 return 1;
704}
705
706static int lpaint_isLCDRenderText(lua_State* L) {
707 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
708 return 1;
709}
710
711static int lpaint_isEmbeddedBitmapText(lua_State* L) {
712 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
713 return 1;
714}
715
716static int lpaint_isAutohinted(lua_State* L) {
717 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
718 return 1;
719}
720
721static int lpaint_isVerticalText(lua_State* L) {
722 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
723 return 1;
724}
725
reed@google.com74ce6f02013-05-22 15:13:18 +0000726static int lpaint_getColor(lua_State* L) {
727 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
728 return 1;
729}
730
731static int lpaint_setColor(lua_State* L) {
732 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
733 return 0;
734}
735
reed@google.come3823fd2013-05-30 18:55:14 +0000736static int lpaint_getTextSize(lua_State* L) {
737 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
738 return 1;
739}
740
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000741static int lpaint_getTextScaleX(lua_State* L) {
742 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
743 return 1;
744}
745
746static int lpaint_getTextSkewX(lua_State* L) {
747 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
748 return 1;
749}
750
reed@google.come3823fd2013-05-30 18:55:14 +0000751static int lpaint_setTextSize(lua_State* L) {
752 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
753 return 0;
754}
755
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000756static int lpaint_getTypeface(lua_State* L) {
757 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
758 return 1;
759}
760
761static int lpaint_setTypeface(lua_State* L) {
762 get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2));
763 return 0;
764}
765
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000766static int lpaint_getHinting(lua_State* L) {
767 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
768 return 1;
769}
770
reed@google.come3823fd2013-05-30 18:55:14 +0000771static int lpaint_getFontID(lua_State* L) {
772 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
773 SkLua(L).pushU32(SkTypeface::UniqueID(face));
774 return 1;
775}
776
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000777static const struct {
778 const char* fLabel;
779 SkPaint::Align fAlign;
780} gAlignRec[] = {
781 { "left", SkPaint::kLeft_Align },
782 { "center", SkPaint::kCenter_Align },
783 { "right", SkPaint::kRight_Align },
784};
785
786static int lpaint_getTextAlign(lua_State* L) {
787 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
788 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
789 if (gAlignRec[i].fAlign == align) {
790 lua_pushstring(L, gAlignRec[i].fLabel);
791 return 1;
792 }
793 }
794 return 0;
795}
796
797static int lpaint_setTextAlign(lua_State* L) {
798 if (lua_isstring(L, 2)) {
799 size_t len;
800 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000801
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000802 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
803 if (!strcmp(gAlignRec[i].fLabel, label)) {
804 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
805 break;
806 }
807 }
808 }
809 return 0;
810}
811
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000812static int lpaint_getStroke(lua_State* L) {
813 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
814 return 1;
815}
816
817static int lpaint_setStroke(lua_State* L) {
818 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000819
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000820 if (lua_toboolean(L, 2)) {
821 style = SkPaint::kStroke_Style;
822 } else {
823 style = SkPaint::kFill_Style;
824 }
825 get_obj<SkPaint>(L, 1)->setStyle(style);
826 return 0;
827}
828
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000829static int lpaint_getStrokeCap(lua_State* L) {
830 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
831 return 1;
832}
833
834static int lpaint_getStrokeJoin(lua_State* L) {
835 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
836 return 1;
837}
838
839static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +0000840 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000841 return 1;
842}
843
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000844static int lpaint_getStrokeWidth(lua_State* L) {
845 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
846 return 1;
847}
848
849static int lpaint_setStrokeWidth(lua_State* L) {
850 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
851 return 0;
852}
853
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000854static int lpaint_getStrokeMiter(lua_State* L) {
855 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
856 return 1;
857}
858
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000859static int lpaint_measureText(lua_State* L) {
860 if (lua_isstring(L, 2)) {
861 size_t len;
862 const char* text = lua_tolstring(L, 2, &len);
863 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
864 return 1;
865 }
866 return 0;
867}
868
869struct FontMetrics {
870 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
871 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
872 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
873 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
874 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
875 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
876 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
877 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
878 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
879};
880
881static int lpaint_getFontMetrics(lua_State* L) {
882 SkPaint::FontMetrics fm;
883 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000884
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000885 lua_newtable(L);
886 setfield_scalar(L, "top", fm.fTop);
887 setfield_scalar(L, "ascent", fm.fAscent);
888 setfield_scalar(L, "descent", fm.fDescent);
889 setfield_scalar(L, "bottom", fm.fBottom);
890 setfield_scalar(L, "leading", fm.fLeading);
891 SkLua(L).pushScalar(height);
892 return 2;
893}
894
reed@google.com29563872013-07-10 21:23:49 +0000895static int lpaint_getEffects(lua_State* L) {
896 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000897
reed@google.com29563872013-07-10 21:23:49 +0000898 lua_newtable(L);
899 setfield_bool_if(L, "looper", !!paint->getLooper());
900 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
901 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer());
902 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
903 setfield_bool_if(L, "shader", !!paint->getShader());
904 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
905 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
906 setfield_bool_if(L, "xfermode", !!paint->getXfermode());
907 return 1;
908}
909
reed@google.com5fdc9832013-07-24 15:47:52 +0000910static int lpaint_getShader(lua_State* L) {
911 const SkPaint* paint = get_obj<SkPaint>(L, 1);
912 SkShader* shader = paint->getShader();
913 if (shader) {
914 push_ref(L, shader);
915 return 1;
916 }
917 return 0;
918}
919
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000920static int lpaint_getPathEffect(lua_State* L) {
921 const SkPaint* paint = get_obj<SkPaint>(L, 1);
922 SkPathEffect* pe = paint->getPathEffect();
923 if (pe) {
924 push_ref(L, pe);
925 return 1;
926 }
927 return 0;
928}
929
reed@google.com74ce6f02013-05-22 15:13:18 +0000930static int lpaint_gc(lua_State* L) {
931 get_obj<SkPaint>(L, 1)->~SkPaint();
932 return 0;
933}
934
935static const struct luaL_Reg gSkPaint_Methods[] = {
936 { "isAntiAlias", lpaint_isAntiAlias },
937 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000938 { "isDither", lpaint_isDither },
939 { "isUnderlineText", lpaint_isUnderlineText },
940 { "isStrikeThruText", lpaint_isStrikeThruText },
941 { "isFakeBoldText", lpaint_isFakeBoldText },
942 { "isLinearText", lpaint_isLinearText },
943 { "isSubpixelText", lpaint_isSubpixelText },
reed09a1d672014-10-11 13:13:11 -0700944 { "setSubpixelText", lpaint_setSubpixelText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000945 { "isDevKernText", lpaint_isDevKernText },
946 { "isLCDRenderText", lpaint_isLCDRenderText },
947 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
948 { "isAutohinted", lpaint_isAutohinted },
949 { "isVerticalText", lpaint_isVerticalText },
reed@google.com74ce6f02013-05-22 15:13:18 +0000950 { "getColor", lpaint_getColor },
951 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +0000952 { "getTextSize", lpaint_getTextSize },
953 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000954 { "getTextScaleX", lpaint_getTextScaleX },
955 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000956 { "getTypeface", lpaint_getTypeface },
957 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000958 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +0000959 { "getFontID", lpaint_getFontID },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000960 { "getTextAlign", lpaint_getTextAlign },
961 { "setTextAlign", lpaint_setTextAlign },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000962 { "getStroke", lpaint_getStroke },
963 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000964 { "getStrokeCap", lpaint_getStrokeCap },
965 { "getStrokeJoin", lpaint_getStrokeJoin },
966 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000967 { "getStrokeWidth", lpaint_getStrokeWidth },
968 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000969 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000970 { "measureText", lpaint_measureText },
971 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +0000972 { "getEffects", lpaint_getEffects },
reed@google.com5fdc9832013-07-24 15:47:52 +0000973 { "getShader", lpaint_getShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000974 { "getPathEffect", lpaint_getPathEffect },
reed@google.com74ce6f02013-05-22 15:13:18 +0000975 { "__gc", lpaint_gc },
976 { NULL, NULL }
977};
978
979///////////////////////////////////////////////////////////////////////////////
980
reed@google.com5fdc9832013-07-24 15:47:52 +0000981static const char* mode2string(SkShader::TileMode mode) {
982 static const char* gNames[] = { "clamp", "repeat", "mirror" };
983 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
984 return gNames[mode];
985}
986
987static const char* gradtype2string(SkShader::GradientType t) {
988 static const char* gNames[] = {
989 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
990 };
991 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
992 return gNames[t];
993}
994
995static int lshader_isOpaque(lua_State* L) {
996 SkShader* shader = get_ref<SkShader>(L, 1);
997 return shader && shader->isOpaque();
998}
999
1000static int lshader_asABitmap(lua_State* L) {
1001 SkShader* shader = get_ref<SkShader>(L, 1);
1002 if (shader) {
1003 SkBitmap bm;
1004 SkMatrix matrix;
1005 SkShader::TileMode modes[2];
1006 switch (shader->asABitmap(&bm, &matrix, modes)) {
1007 case SkShader::kDefault_BitmapType:
1008 lua_newtable(L);
1009 setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0);
1010 setfield_number(L, "width", bm.width());
1011 setfield_number(L, "height", bm.height());
1012 setfield_string(L, "tileX", mode2string(modes[0]));
1013 setfield_string(L, "tileY", mode2string(modes[1]));
1014 return 1;
1015 default:
1016 break;
1017 }
1018 }
1019 return 0;
1020}
1021
1022static int lshader_asAGradient(lua_State* L) {
1023 SkShader* shader = get_ref<SkShader>(L, 1);
1024 if (shader) {
1025 SkShader::GradientInfo info;
1026 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001027
1028 SkColor colors[3]; // hacked in for extracting info on 3 color case.
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001029 SkScalar pos[3];
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001030
1031 info.fColorCount = 3;
1032 info.fColors = &colors[0];
1033 info.fColorOffsets = &pos[0];
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001034
reed@google.com5fdc9832013-07-24 15:47:52 +00001035 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001036
reed@google.com5fdc9832013-07-24 15:47:52 +00001037 if (SkShader::kNone_GradientType != t) {
1038 lua_newtable(L);
1039 setfield_string(L, "type", gradtype2string(t));
1040 setfield_number(L, "colorCount", info.fColorCount);
1041 setfield_string(L, "tile", mode2string(info.fTileMode));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001042
1043 if (info.fColorCount == 3){
1044 setfield_number(L, "midPos", pos[1]);
1045 }
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001046
reed@google.com5fdc9832013-07-24 15:47:52 +00001047 return 1;
1048 }
1049 }
1050 return 0;
1051}
1052
1053static int lshader_gc(lua_State* L) {
1054 get_ref<SkShader>(L, 1)->unref();
1055 return 0;
1056}
1057
1058static const struct luaL_Reg gSkShader_Methods[] = {
1059 { "isOpaque", lshader_isOpaque },
1060 { "asABitmap", lshader_asABitmap },
1061 { "asAGradient", lshader_asAGradient },
1062 { "__gc", lshader_gc },
1063 { NULL, NULL }
1064};
1065
1066///////////////////////////////////////////////////////////////////////////////
1067
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001068static int lpatheffect_asADash(lua_State* L) {
1069 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1070 if (pe) {
1071 SkPathEffect::DashInfo info;
1072 SkPathEffect::DashType dashType = pe->asADash(&info);
1073 if (SkPathEffect::kDash_DashType == dashType) {
1074 SkAutoTArray<SkScalar> intervals(info.fCount);
1075 info.fIntervals = intervals.get();
1076 pe->asADash(&info);
1077 SkLua(L).pushDash(info);
1078 return 1;
1079 }
1080 }
1081 return 0;
1082}
1083
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001084static int lpatheffect_gc(lua_State* L) {
1085 get_ref<SkPathEffect>(L, 1)->unref();
1086 return 0;
1087}
1088
1089static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001090 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001091 { "__gc", lpatheffect_gc },
1092 { NULL, NULL }
1093};
1094
1095///////////////////////////////////////////////////////////////////////////////
1096
humper@google.com2815c192013-07-10 22:42:30 +00001097static int lmatrix_getType(lua_State* L) {
1098 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001099
humper@google.com2815c192013-07-10 22:42:30 +00001100 lua_newtable(L);
1101 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1102 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1103 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1104 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1105 return 1;
1106}
1107
humper@google.com0f48ee02013-07-26 15:23:43 +00001108static int lmatrix_getScaleX(lua_State* L) {
1109 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1110 return 1;
1111}
1112
1113static int lmatrix_getScaleY(lua_State* L) {
1114 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1115 return 1;
1116}
1117
1118static int lmatrix_getTranslateX(lua_State* L) {
1119 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1120 return 1;
1121}
1122
1123static int lmatrix_getTranslateY(lua_State* L) {
1124 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1125 return 1;
1126}
1127
humper@google.com2815c192013-07-10 22:42:30 +00001128static const struct luaL_Reg gSkMatrix_Methods[] = {
1129 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001130 { "getScaleX", lmatrix_getScaleX },
1131 { "getScaleY", lmatrix_getScaleY },
1132 { "getTranslateX", lmatrix_getTranslateX },
1133 { "getTranslateY", lmatrix_getTranslateY },
humper@google.com2815c192013-07-10 22:42:30 +00001134 { NULL, NULL }
1135};
1136
1137///////////////////////////////////////////////////////////////////////////////
1138
reed@google.com74ce6f02013-05-22 15:13:18 +00001139static int lpath_getBounds(lua_State* L) {
1140 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1141 return 1;
1142}
1143
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001144static const char* fill_type_to_str(SkPath::FillType fill) {
1145 switch (fill) {
1146 case SkPath::kEvenOdd_FillType:
1147 return "even-odd";
1148 case SkPath::kWinding_FillType:
1149 return "winding";
1150 case SkPath::kInverseEvenOdd_FillType:
1151 return "inverse-even-odd";
1152 case SkPath::kInverseWinding_FillType:
1153 return "inverse-winding";
1154 }
1155 return "unknown";
1156}
1157
1158static int lpath_getFillType(lua_State* L) {
1159 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1160 SkLua(L).pushString(fill_type_to_str(fill));
1161 return 1;
1162}
1163
1164static SkString segment_masks_to_str(uint32_t segmentMasks) {
1165 SkString result;
1166 bool first = true;
1167 if (SkPath::kLine_SegmentMask & segmentMasks) {
1168 result.append("line");
1169 first = false;
1170 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1171 }
1172 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1173 if (!first) {
1174 result.append(" ");
1175 }
1176 result.append("quad");
1177 first = false;
1178 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1179 }
1180 if (SkPath::kConic_SegmentMask & segmentMasks) {
1181 if (!first) {
1182 result.append(" ");
1183 }
1184 result.append("conic");
1185 first = false;
1186 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1187 }
1188 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1189 if (!first) {
1190 result.append(" ");
1191 }
1192 result.append("cubic");
1193 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1194 }
1195 SkASSERT(0 == segmentMasks);
1196 return result;
1197}
1198
krajcevski95498ed2014-08-18 08:02:33 -07001199static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001200 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1201 SkLua(L).pushString(segment_masks_to_str(segMasks));
1202 return 1;
1203}
1204
1205static int lpath_isConvex(lua_State* L) {
1206 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1207 SkLua(L).pushBool(isConvex);
1208 return 1;
1209}
1210
reed@google.com74ce6f02013-05-22 15:13:18 +00001211static int lpath_isEmpty(lua_State* L) {
1212 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1213 return 1;
1214}
1215
1216static int lpath_isRect(lua_State* L) {
1217 SkRect r;
1218 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1219 int ret_count = 1;
1220 lua_pushboolean(L, pred);
1221 if (pred) {
1222 SkLua(L).pushRect(r);
1223 ret_count += 1;
1224 }
1225 return ret_count;
1226}
1227
1228static const char* dir2string(SkPath::Direction dir) {
1229 static const char* gStr[] = {
1230 "unknown", "cw", "ccw"
1231 };
1232 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1233 return gStr[dir];
1234}
1235
1236static int lpath_isNestedRects(lua_State* L) {
1237 SkRect rects[2];
1238 SkPath::Direction dirs[2];
1239 bool pred = get_obj<SkPath>(L, 1)->isNestedRects(rects, dirs);
1240 int ret_count = 1;
1241 lua_pushboolean(L, pred);
1242 if (pred) {
1243 SkLua lua(L);
1244 lua.pushRect(rects[0]);
1245 lua.pushRect(rects[1]);
1246 lua_pushstring(L, dir2string(dirs[0]));
1247 lua_pushstring(L, dir2string(dirs[0]));
1248 ret_count += 4;
1249 }
1250 return ret_count;
1251}
1252
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001253static int lpath_countPoints(lua_State* L) {
1254 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1255 return 1;
1256}
1257
reed@google.com74ce6f02013-05-22 15:13:18 +00001258static int lpath_reset(lua_State* L) {
1259 get_obj<SkPath>(L, 1)->reset();
1260 return 0;
1261}
1262
1263static int lpath_moveTo(lua_State* L) {
1264 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1265 return 0;
1266}
1267
1268static int lpath_lineTo(lua_State* L) {
1269 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1270 return 0;
1271}
1272
1273static int lpath_quadTo(lua_State* L) {
1274 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1275 lua2scalar(L, 4), lua2scalar(L, 5));
1276 return 0;
1277}
1278
1279static int lpath_cubicTo(lua_State* L) {
1280 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1281 lua2scalar(L, 4), lua2scalar(L, 5),
1282 lua2scalar(L, 6), lua2scalar(L, 7));
1283 return 0;
1284}
1285
1286static int lpath_close(lua_State* L) {
1287 get_obj<SkPath>(L, 1)->close();
1288 return 0;
1289}
1290
1291static int lpath_gc(lua_State* L) {
1292 get_obj<SkPath>(L, 1)->~SkPath();
1293 return 0;
1294}
1295
1296static const struct luaL_Reg gSkPath_Methods[] = {
1297 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001298 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001299 { "getSegmentTypes", lpath_getSegmentTypes },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001300 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001301 { "isEmpty", lpath_isEmpty },
1302 { "isRect", lpath_isRect },
1303 { "isNestedRects", lpath_isNestedRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001304 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001305 { "reset", lpath_reset },
1306 { "moveTo", lpath_moveTo },
1307 { "lineTo", lpath_lineTo },
1308 { "quadTo", lpath_quadTo },
1309 { "cubicTo", lpath_cubicTo },
1310 { "close", lpath_close },
1311 { "__gc", lpath_gc },
1312 { NULL, NULL }
1313};
1314
1315///////////////////////////////////////////////////////////////////////////////
1316
1317static const char* rrect_type(const SkRRect& rr) {
1318 switch (rr.getType()) {
1319 case SkRRect::kUnknown_Type: return "unknown";
1320 case SkRRect::kEmpty_Type: return "empty";
1321 case SkRRect::kRect_Type: return "rect";
1322 case SkRRect::kOval_Type: return "oval";
1323 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001324 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001325 case SkRRect::kComplex_Type: return "complex";
1326 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001327 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001328 return "";
1329}
1330
1331static int lrrect_rect(lua_State* L) {
1332 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1333 return 1;
1334}
1335
1336static int lrrect_type(lua_State* L) {
1337 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1338 return 1;
1339}
1340
1341static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001342 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001343 SkVector v;
1344 if (corner < 0 || corner > 3) {
1345 SkDebugf("bad corner index %d", corner);
1346 v.set(0, 0);
1347 } else {
1348 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1349 }
1350 lua_pushnumber(L, v.fX);
1351 lua_pushnumber(L, v.fY);
1352 return 2;
1353}
1354
1355static int lrrect_gc(lua_State* L) {
1356 get_obj<SkRRect>(L, 1)->~SkRRect();
1357 return 0;
1358}
1359
1360static const struct luaL_Reg gSkRRect_Methods[] = {
1361 { "rect", lrrect_rect },
1362 { "type", lrrect_type },
1363 { "radii", lrrect_radii },
1364 { "__gc", lrrect_gc },
1365 { NULL, NULL }
1366};
1367
1368///////////////////////////////////////////////////////////////////////////////
1369
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001370static int limage_width(lua_State* L) {
1371 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1372 return 1;
1373}
1374
1375static int limage_height(lua_State* L) {
1376 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1377 return 1;
1378}
1379
1380static int limage_gc(lua_State* L) {
1381 get_ref<SkImage>(L, 1)->unref();
1382 return 0;
1383}
1384
1385static const struct luaL_Reg gSkImage_Methods[] = {
1386 { "width", limage_width },
1387 { "height", limage_height },
1388 { "__gc", limage_gc },
1389 { NULL, NULL }
1390};
1391
1392///////////////////////////////////////////////////////////////////////////////
1393
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001394static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001395 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001396 return 0;
1397}
1398
1399static const struct luaL_Reg gSkTypeface_Methods[] = {
1400 { "__gc", ltypeface_gc },
1401 { NULL, NULL }
1402};
1403
1404///////////////////////////////////////////////////////////////////////////////
1405
reed@google.com74ce6f02013-05-22 15:13:18 +00001406class AutoCallLua {
1407public:
1408 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1409 lua_getglobal(L, func);
1410 if (!lua_isfunction(L, -1)) {
1411 int t = lua_type(L, -1);
1412 SkDebugf("--- expected function %d\n", t);
1413 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001414
reed@google.com74ce6f02013-05-22 15:13:18 +00001415 lua_newtable(L);
1416 setfield_string(L, "verb", verb);
1417 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001418
reed@google.com74ce6f02013-05-22 15:13:18 +00001419 ~AutoCallLua() {
1420 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1421 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1422 }
1423 lua_settop(fL, -1);
1424 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001425
reed@google.com74ce6f02013-05-22 15:13:18 +00001426private:
1427 lua_State* fL;
1428};
1429
1430#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1431
1432///////////////////////////////////////////////////////////////////////////////
1433
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001434static int lsk_newDocumentPDF(lua_State* L) {
1435 const char* file = NULL;
1436 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1437 file = lua_tolstring(L, 1, NULL);
1438 }
1439
1440 SkDocument* doc = SkDocument::CreatePDF(file);
1441 if (NULL == doc) {
1442 // do I need to push a nil on the stack and return 1?
1443 return 0;
1444 } else {
1445 push_ref(L, doc);
1446 doc->unref();
1447 return 1;
1448 }
1449}
1450
reed@google.com3597b732013-05-22 20:12:50 +00001451static int lsk_newPaint(lua_State* L) {
1452 push_new<SkPaint>(L);
1453 return 1;
1454}
1455
1456static int lsk_newPath(lua_State* L) {
1457 push_new<SkPath>(L);
1458 return 1;
1459}
1460
1461static int lsk_newRRect(lua_State* L) {
1462 SkRRect* rr = push_new<SkRRect>(L);
1463 rr->setEmpty();
1464 return 1;
1465}
1466
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001467static int lsk_newTypeface(lua_State* L) {
1468 const char* name = NULL;
1469 int style = SkTypeface::kNormal;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00001470
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001471 int count = lua_gettop(L);
1472 if (count > 0 && lua_isstring(L, 1)) {
1473 name = lua_tolstring(L, 1, NULL);
1474 if (count > 1 && lua_isnumber(L, 2)) {
1475 style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic;
1476 }
1477 }
1478
1479 SkTypeface* face = SkTypeface::CreateFromName(name,
1480 (SkTypeface::Style)style);
1481// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
1482 if (NULL == face) {
1483 face = SkTypeface::RefDefault();
1484 }
1485 push_ref(L, face);
1486 face->unref();
1487 return 1;
1488}
reed@google.com3597b732013-05-22 20:12:50 +00001489
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001490static int lsk_loadImage(lua_State* L) {
1491 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1492 const char* name = lua_tolstring(L, 1, NULL);
1493 SkAutoDataUnref data(SkData::NewFromFileName(name));
1494 if (data.get()) {
piotaixr4bcc2022014-09-17 14:33:30 -07001495 SkImage* image = SkImage::NewFromGenerator(
1496 SkDecodingImageGenerator::Create(data, SkDecodingImageGenerator::Options()));
1497
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001498 if (image) {
1499 push_ref(L, image);
1500 image->unref();
1501 return 1;
1502 }
1503 }
1504 }
1505 return 0;
1506}
1507
reed@google.com3597b732013-05-22 20:12:50 +00001508static void register_Sk(lua_State* L) {
1509 lua_newtable(L);
1510 lua_pushvalue(L, -1);
1511 lua_setglobal(L, "Sk");
1512 // the Sk table is still on top
1513
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001514 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001515 setfield_function(L, "loadImage", lsk_loadImage);
reed@google.com3597b732013-05-22 20:12:50 +00001516 setfield_function(L, "newPaint", lsk_newPaint);
1517 setfield_function(L, "newPath", lsk_newPath);
1518 setfield_function(L, "newRRect", lsk_newRRect);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001519 setfield_function(L, "newTypeface", lsk_newTypeface);
reed@google.com3597b732013-05-22 20:12:50 +00001520 lua_pop(L, 1); // pop off the Sk table
1521}
1522
reed@google.com74ce6f02013-05-22 15:13:18 +00001523#define REG_CLASS(L, C) \
1524 do { \
reed@google.com3597b732013-05-22 20:12:50 +00001525 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00001526 lua_pushvalue(L, -1); \
1527 lua_setfield(L, -2, "__index"); \
1528 luaL_setfuncs(L, g##C##_Methods, 0); \
1529 lua_pop(L, 1); /* pop off the meta-table */ \
1530 } while (0)
1531
1532void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00001533 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00001534 REG_CLASS(L, SkCanvas);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001535 REG_CLASS(L, SkDocument);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001536 REG_CLASS(L, SkImage);
reed@google.com74ce6f02013-05-22 15:13:18 +00001537 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001538 REG_CLASS(L, SkPath);
1539 REG_CLASS(L, SkPathEffect);
reed@google.com74ce6f02013-05-22 15:13:18 +00001540 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00001541 REG_CLASS(L, SkShader);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001542 REG_CLASS(L, SkTypeface);
humper@google.com2815c192013-07-10 22:42:30 +00001543 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00001544}
zachr@google.com28c27c82013-06-20 17:15:05 +00001545
reed@google.com7bce9982013-06-20 17:40:21 +00001546extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00001547extern "C" int luaopen_skia(lua_State* L) {
1548 SkLua::Load(L);
1549 return 0;
1550}