blob: 1336404d8c58d3542d4af4b22a4e357bdaed7a0f [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
696static int lpaint_isDevKernText(lua_State* L) {
697 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
698 return 1;
699}
700
701static int lpaint_isLCDRenderText(lua_State* L) {
702 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
703 return 1;
704}
705
706static int lpaint_isEmbeddedBitmapText(lua_State* L) {
707 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
708 return 1;
709}
710
711static int lpaint_isAutohinted(lua_State* L) {
712 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
713 return 1;
714}
715
716static int lpaint_isVerticalText(lua_State* L) {
717 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
718 return 1;
719}
720
reed@google.com74ce6f02013-05-22 15:13:18 +0000721static int lpaint_getColor(lua_State* L) {
722 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
723 return 1;
724}
725
726static int lpaint_setColor(lua_State* L) {
727 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
728 return 0;
729}
730
reed@google.come3823fd2013-05-30 18:55:14 +0000731static int lpaint_getTextSize(lua_State* L) {
732 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
733 return 1;
734}
735
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000736static int lpaint_getTextScaleX(lua_State* L) {
737 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
738 return 1;
739}
740
741static int lpaint_getTextSkewX(lua_State* L) {
742 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
743 return 1;
744}
745
reed@google.come3823fd2013-05-30 18:55:14 +0000746static int lpaint_setTextSize(lua_State* L) {
747 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
748 return 0;
749}
750
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000751static int lpaint_getTypeface(lua_State* L) {
752 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
753 return 1;
754}
755
756static int lpaint_setTypeface(lua_State* L) {
757 get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2));
758 return 0;
759}
760
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000761static int lpaint_getHinting(lua_State* L) {
762 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
763 return 1;
764}
765
reed@google.come3823fd2013-05-30 18:55:14 +0000766static int lpaint_getFontID(lua_State* L) {
767 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
768 SkLua(L).pushU32(SkTypeface::UniqueID(face));
769 return 1;
770}
771
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000772static const struct {
773 const char* fLabel;
774 SkPaint::Align fAlign;
775} gAlignRec[] = {
776 { "left", SkPaint::kLeft_Align },
777 { "center", SkPaint::kCenter_Align },
778 { "right", SkPaint::kRight_Align },
779};
780
781static int lpaint_getTextAlign(lua_State* L) {
782 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
783 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
784 if (gAlignRec[i].fAlign == align) {
785 lua_pushstring(L, gAlignRec[i].fLabel);
786 return 1;
787 }
788 }
789 return 0;
790}
791
792static int lpaint_setTextAlign(lua_State* L) {
793 if (lua_isstring(L, 2)) {
794 size_t len;
795 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000796
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000797 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
798 if (!strcmp(gAlignRec[i].fLabel, label)) {
799 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
800 break;
801 }
802 }
803 }
804 return 0;
805}
806
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000807static int lpaint_getStroke(lua_State* L) {
808 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
809 return 1;
810}
811
812static int lpaint_setStroke(lua_State* L) {
813 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000814
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000815 if (lua_toboolean(L, 2)) {
816 style = SkPaint::kStroke_Style;
817 } else {
818 style = SkPaint::kFill_Style;
819 }
820 get_obj<SkPaint>(L, 1)->setStyle(style);
821 return 0;
822}
823
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000824static int lpaint_getStrokeCap(lua_State* L) {
825 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
826 return 1;
827}
828
829static int lpaint_getStrokeJoin(lua_State* L) {
830 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
831 return 1;
832}
833
834static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +0000835 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000836 return 1;
837}
838
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000839static int lpaint_getStrokeWidth(lua_State* L) {
840 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
841 return 1;
842}
843
844static int lpaint_setStrokeWidth(lua_State* L) {
845 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
846 return 0;
847}
848
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000849static int lpaint_getStrokeMiter(lua_State* L) {
850 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
851 return 1;
852}
853
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000854static int lpaint_measureText(lua_State* L) {
855 if (lua_isstring(L, 2)) {
856 size_t len;
857 const char* text = lua_tolstring(L, 2, &len);
858 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
859 return 1;
860 }
861 return 0;
862}
863
864struct FontMetrics {
865 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
866 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
867 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
868 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
869 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
870 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
871 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
872 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
873 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
874};
875
876static int lpaint_getFontMetrics(lua_State* L) {
877 SkPaint::FontMetrics fm;
878 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000879
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000880 lua_newtable(L);
881 setfield_scalar(L, "top", fm.fTop);
882 setfield_scalar(L, "ascent", fm.fAscent);
883 setfield_scalar(L, "descent", fm.fDescent);
884 setfield_scalar(L, "bottom", fm.fBottom);
885 setfield_scalar(L, "leading", fm.fLeading);
886 SkLua(L).pushScalar(height);
887 return 2;
888}
889
reed@google.com29563872013-07-10 21:23:49 +0000890static int lpaint_getEffects(lua_State* L) {
891 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000892
reed@google.com29563872013-07-10 21:23:49 +0000893 lua_newtable(L);
894 setfield_bool_if(L, "looper", !!paint->getLooper());
895 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
896 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer());
897 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
898 setfield_bool_if(L, "shader", !!paint->getShader());
899 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
900 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
901 setfield_bool_if(L, "xfermode", !!paint->getXfermode());
902 return 1;
903}
904
reed@google.com5fdc9832013-07-24 15:47:52 +0000905static int lpaint_getShader(lua_State* L) {
906 const SkPaint* paint = get_obj<SkPaint>(L, 1);
907 SkShader* shader = paint->getShader();
908 if (shader) {
909 push_ref(L, shader);
910 return 1;
911 }
912 return 0;
913}
914
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000915static int lpaint_getPathEffect(lua_State* L) {
916 const SkPaint* paint = get_obj<SkPaint>(L, 1);
917 SkPathEffect* pe = paint->getPathEffect();
918 if (pe) {
919 push_ref(L, pe);
920 return 1;
921 }
922 return 0;
923}
924
reed@google.com74ce6f02013-05-22 15:13:18 +0000925static int lpaint_gc(lua_State* L) {
926 get_obj<SkPaint>(L, 1)->~SkPaint();
927 return 0;
928}
929
930static const struct luaL_Reg gSkPaint_Methods[] = {
931 { "isAntiAlias", lpaint_isAntiAlias },
932 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000933 { "isDither", lpaint_isDither },
934 { "isUnderlineText", lpaint_isUnderlineText },
935 { "isStrikeThruText", lpaint_isStrikeThruText },
936 { "isFakeBoldText", lpaint_isFakeBoldText },
937 { "isLinearText", lpaint_isLinearText },
938 { "isSubpixelText", lpaint_isSubpixelText },
939 { "isDevKernText", lpaint_isDevKernText },
940 { "isLCDRenderText", lpaint_isLCDRenderText },
941 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
942 { "isAutohinted", lpaint_isAutohinted },
943 { "isVerticalText", lpaint_isVerticalText },
reed@google.com74ce6f02013-05-22 15:13:18 +0000944 { "getColor", lpaint_getColor },
945 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +0000946 { "getTextSize", lpaint_getTextSize },
947 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000948 { "getTextScaleX", lpaint_getTextScaleX },
949 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000950 { "getTypeface", lpaint_getTypeface },
951 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000952 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +0000953 { "getFontID", lpaint_getFontID },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000954 { "getTextAlign", lpaint_getTextAlign },
955 { "setTextAlign", lpaint_setTextAlign },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000956 { "getStroke", lpaint_getStroke },
957 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000958 { "getStrokeCap", lpaint_getStrokeCap },
959 { "getStrokeJoin", lpaint_getStrokeJoin },
960 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000961 { "getStrokeWidth", lpaint_getStrokeWidth },
962 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000963 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000964 { "measureText", lpaint_measureText },
965 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +0000966 { "getEffects", lpaint_getEffects },
reed@google.com5fdc9832013-07-24 15:47:52 +0000967 { "getShader", lpaint_getShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000968 { "getPathEffect", lpaint_getPathEffect },
reed@google.com74ce6f02013-05-22 15:13:18 +0000969 { "__gc", lpaint_gc },
970 { NULL, NULL }
971};
972
973///////////////////////////////////////////////////////////////////////////////
974
reed@google.com5fdc9832013-07-24 15:47:52 +0000975static const char* mode2string(SkShader::TileMode mode) {
976 static const char* gNames[] = { "clamp", "repeat", "mirror" };
977 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
978 return gNames[mode];
979}
980
981static const char* gradtype2string(SkShader::GradientType t) {
982 static const char* gNames[] = {
983 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
984 };
985 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
986 return gNames[t];
987}
988
989static int lshader_isOpaque(lua_State* L) {
990 SkShader* shader = get_ref<SkShader>(L, 1);
991 return shader && shader->isOpaque();
992}
993
994static int lshader_asABitmap(lua_State* L) {
995 SkShader* shader = get_ref<SkShader>(L, 1);
996 if (shader) {
997 SkBitmap bm;
998 SkMatrix matrix;
999 SkShader::TileMode modes[2];
1000 switch (shader->asABitmap(&bm, &matrix, modes)) {
1001 case SkShader::kDefault_BitmapType:
1002 lua_newtable(L);
1003 setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0);
1004 setfield_number(L, "width", bm.width());
1005 setfield_number(L, "height", bm.height());
1006 setfield_string(L, "tileX", mode2string(modes[0]));
1007 setfield_string(L, "tileY", mode2string(modes[1]));
1008 return 1;
1009 default:
1010 break;
1011 }
1012 }
1013 return 0;
1014}
1015
1016static int lshader_asAGradient(lua_State* L) {
1017 SkShader* shader = get_ref<SkShader>(L, 1);
1018 if (shader) {
1019 SkShader::GradientInfo info;
1020 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001021
1022 SkColor colors[3]; // hacked in for extracting info on 3 color case.
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001023 SkScalar pos[3];
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001024
1025 info.fColorCount = 3;
1026 info.fColors = &colors[0];
1027 info.fColorOffsets = &pos[0];
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001028
reed@google.com5fdc9832013-07-24 15:47:52 +00001029 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001030
reed@google.com5fdc9832013-07-24 15:47:52 +00001031 if (SkShader::kNone_GradientType != t) {
1032 lua_newtable(L);
1033 setfield_string(L, "type", gradtype2string(t));
1034 setfield_number(L, "colorCount", info.fColorCount);
1035 setfield_string(L, "tile", mode2string(info.fTileMode));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001036
1037 if (info.fColorCount == 3){
1038 setfield_number(L, "midPos", pos[1]);
1039 }
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001040
reed@google.com5fdc9832013-07-24 15:47:52 +00001041 return 1;
1042 }
1043 }
1044 return 0;
1045}
1046
1047static int lshader_gc(lua_State* L) {
1048 get_ref<SkShader>(L, 1)->unref();
1049 return 0;
1050}
1051
1052static const struct luaL_Reg gSkShader_Methods[] = {
1053 { "isOpaque", lshader_isOpaque },
1054 { "asABitmap", lshader_asABitmap },
1055 { "asAGradient", lshader_asAGradient },
1056 { "__gc", lshader_gc },
1057 { NULL, NULL }
1058};
1059
1060///////////////////////////////////////////////////////////////////////////////
1061
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001062static int lpatheffect_asADash(lua_State* L) {
1063 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1064 if (pe) {
1065 SkPathEffect::DashInfo info;
1066 SkPathEffect::DashType dashType = pe->asADash(&info);
1067 if (SkPathEffect::kDash_DashType == dashType) {
1068 SkAutoTArray<SkScalar> intervals(info.fCount);
1069 info.fIntervals = intervals.get();
1070 pe->asADash(&info);
1071 SkLua(L).pushDash(info);
1072 return 1;
1073 }
1074 }
1075 return 0;
1076}
1077
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001078static int lpatheffect_gc(lua_State* L) {
1079 get_ref<SkPathEffect>(L, 1)->unref();
1080 return 0;
1081}
1082
1083static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001084 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001085 { "__gc", lpatheffect_gc },
1086 { NULL, NULL }
1087};
1088
1089///////////////////////////////////////////////////////////////////////////////
1090
humper@google.com2815c192013-07-10 22:42:30 +00001091static int lmatrix_getType(lua_State* L) {
1092 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001093
humper@google.com2815c192013-07-10 22:42:30 +00001094 lua_newtable(L);
1095 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1096 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1097 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1098 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1099 return 1;
1100}
1101
humper@google.com0f48ee02013-07-26 15:23:43 +00001102static int lmatrix_getScaleX(lua_State* L) {
1103 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1104 return 1;
1105}
1106
1107static int lmatrix_getScaleY(lua_State* L) {
1108 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1109 return 1;
1110}
1111
1112static int lmatrix_getTranslateX(lua_State* L) {
1113 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1114 return 1;
1115}
1116
1117static int lmatrix_getTranslateY(lua_State* L) {
1118 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1119 return 1;
1120}
1121
humper@google.com2815c192013-07-10 22:42:30 +00001122static const struct luaL_Reg gSkMatrix_Methods[] = {
1123 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001124 { "getScaleX", lmatrix_getScaleX },
1125 { "getScaleY", lmatrix_getScaleY },
1126 { "getTranslateX", lmatrix_getTranslateX },
1127 { "getTranslateY", lmatrix_getTranslateY },
humper@google.com2815c192013-07-10 22:42:30 +00001128 { NULL, NULL }
1129};
1130
1131///////////////////////////////////////////////////////////////////////////////
1132
reed@google.com74ce6f02013-05-22 15:13:18 +00001133static int lpath_getBounds(lua_State* L) {
1134 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1135 return 1;
1136}
1137
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001138static const char* fill_type_to_str(SkPath::FillType fill) {
1139 switch (fill) {
1140 case SkPath::kEvenOdd_FillType:
1141 return "even-odd";
1142 case SkPath::kWinding_FillType:
1143 return "winding";
1144 case SkPath::kInverseEvenOdd_FillType:
1145 return "inverse-even-odd";
1146 case SkPath::kInverseWinding_FillType:
1147 return "inverse-winding";
1148 }
1149 return "unknown";
1150}
1151
1152static int lpath_getFillType(lua_State* L) {
1153 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1154 SkLua(L).pushString(fill_type_to_str(fill));
1155 return 1;
1156}
1157
1158static SkString segment_masks_to_str(uint32_t segmentMasks) {
1159 SkString result;
1160 bool first = true;
1161 if (SkPath::kLine_SegmentMask & segmentMasks) {
1162 result.append("line");
1163 first = false;
1164 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1165 }
1166 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1167 if (!first) {
1168 result.append(" ");
1169 }
1170 result.append("quad");
1171 first = false;
1172 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1173 }
1174 if (SkPath::kConic_SegmentMask & segmentMasks) {
1175 if (!first) {
1176 result.append(" ");
1177 }
1178 result.append("conic");
1179 first = false;
1180 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1181 }
1182 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1183 if (!first) {
1184 result.append(" ");
1185 }
1186 result.append("cubic");
1187 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1188 }
1189 SkASSERT(0 == segmentMasks);
1190 return result;
1191}
1192
krajcevski95498ed2014-08-18 08:02:33 -07001193static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001194 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1195 SkLua(L).pushString(segment_masks_to_str(segMasks));
1196 return 1;
1197}
1198
1199static int lpath_isConvex(lua_State* L) {
1200 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1201 SkLua(L).pushBool(isConvex);
1202 return 1;
1203}
1204
reed@google.com74ce6f02013-05-22 15:13:18 +00001205static int lpath_isEmpty(lua_State* L) {
1206 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1207 return 1;
1208}
1209
1210static int lpath_isRect(lua_State* L) {
1211 SkRect r;
1212 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1213 int ret_count = 1;
1214 lua_pushboolean(L, pred);
1215 if (pred) {
1216 SkLua(L).pushRect(r);
1217 ret_count += 1;
1218 }
1219 return ret_count;
1220}
1221
1222static const char* dir2string(SkPath::Direction dir) {
1223 static const char* gStr[] = {
1224 "unknown", "cw", "ccw"
1225 };
1226 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1227 return gStr[dir];
1228}
1229
1230static int lpath_isNestedRects(lua_State* L) {
1231 SkRect rects[2];
1232 SkPath::Direction dirs[2];
1233 bool pred = get_obj<SkPath>(L, 1)->isNestedRects(rects, dirs);
1234 int ret_count = 1;
1235 lua_pushboolean(L, pred);
1236 if (pred) {
1237 SkLua lua(L);
1238 lua.pushRect(rects[0]);
1239 lua.pushRect(rects[1]);
1240 lua_pushstring(L, dir2string(dirs[0]));
1241 lua_pushstring(L, dir2string(dirs[0]));
1242 ret_count += 4;
1243 }
1244 return ret_count;
1245}
1246
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001247static int lpath_countPoints(lua_State* L) {
1248 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1249 return 1;
1250}
1251
reed@google.com74ce6f02013-05-22 15:13:18 +00001252static int lpath_reset(lua_State* L) {
1253 get_obj<SkPath>(L, 1)->reset();
1254 return 0;
1255}
1256
1257static int lpath_moveTo(lua_State* L) {
1258 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1259 return 0;
1260}
1261
1262static int lpath_lineTo(lua_State* L) {
1263 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1264 return 0;
1265}
1266
1267static int lpath_quadTo(lua_State* L) {
1268 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1269 lua2scalar(L, 4), lua2scalar(L, 5));
1270 return 0;
1271}
1272
1273static int lpath_cubicTo(lua_State* L) {
1274 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1275 lua2scalar(L, 4), lua2scalar(L, 5),
1276 lua2scalar(L, 6), lua2scalar(L, 7));
1277 return 0;
1278}
1279
1280static int lpath_close(lua_State* L) {
1281 get_obj<SkPath>(L, 1)->close();
1282 return 0;
1283}
1284
1285static int lpath_gc(lua_State* L) {
1286 get_obj<SkPath>(L, 1)->~SkPath();
1287 return 0;
1288}
1289
1290static const struct luaL_Reg gSkPath_Methods[] = {
1291 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001292 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001293 { "getSegmentTypes", lpath_getSegmentTypes },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001294 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001295 { "isEmpty", lpath_isEmpty },
1296 { "isRect", lpath_isRect },
1297 { "isNestedRects", lpath_isNestedRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001298 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001299 { "reset", lpath_reset },
1300 { "moveTo", lpath_moveTo },
1301 { "lineTo", lpath_lineTo },
1302 { "quadTo", lpath_quadTo },
1303 { "cubicTo", lpath_cubicTo },
1304 { "close", lpath_close },
1305 { "__gc", lpath_gc },
1306 { NULL, NULL }
1307};
1308
1309///////////////////////////////////////////////////////////////////////////////
1310
1311static const char* rrect_type(const SkRRect& rr) {
1312 switch (rr.getType()) {
1313 case SkRRect::kUnknown_Type: return "unknown";
1314 case SkRRect::kEmpty_Type: return "empty";
1315 case SkRRect::kRect_Type: return "rect";
1316 case SkRRect::kOval_Type: return "oval";
1317 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001318 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001319 case SkRRect::kComplex_Type: return "complex";
1320 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001321 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001322 return "";
1323}
1324
1325static int lrrect_rect(lua_State* L) {
1326 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1327 return 1;
1328}
1329
1330static int lrrect_type(lua_State* L) {
1331 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1332 return 1;
1333}
1334
1335static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001336 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001337 SkVector v;
1338 if (corner < 0 || corner > 3) {
1339 SkDebugf("bad corner index %d", corner);
1340 v.set(0, 0);
1341 } else {
1342 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1343 }
1344 lua_pushnumber(L, v.fX);
1345 lua_pushnumber(L, v.fY);
1346 return 2;
1347}
1348
1349static int lrrect_gc(lua_State* L) {
1350 get_obj<SkRRect>(L, 1)->~SkRRect();
1351 return 0;
1352}
1353
1354static const struct luaL_Reg gSkRRect_Methods[] = {
1355 { "rect", lrrect_rect },
1356 { "type", lrrect_type },
1357 { "radii", lrrect_radii },
1358 { "__gc", lrrect_gc },
1359 { NULL, NULL }
1360};
1361
1362///////////////////////////////////////////////////////////////////////////////
1363
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001364static int limage_width(lua_State* L) {
1365 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1366 return 1;
1367}
1368
1369static int limage_height(lua_State* L) {
1370 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1371 return 1;
1372}
1373
1374static int limage_gc(lua_State* L) {
1375 get_ref<SkImage>(L, 1)->unref();
1376 return 0;
1377}
1378
1379static const struct luaL_Reg gSkImage_Methods[] = {
1380 { "width", limage_width },
1381 { "height", limage_height },
1382 { "__gc", limage_gc },
1383 { NULL, NULL }
1384};
1385
1386///////////////////////////////////////////////////////////////////////////////
1387
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001388static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001389 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001390 return 0;
1391}
1392
1393static const struct luaL_Reg gSkTypeface_Methods[] = {
1394 { "__gc", ltypeface_gc },
1395 { NULL, NULL }
1396};
1397
1398///////////////////////////////////////////////////////////////////////////////
1399
reed@google.com74ce6f02013-05-22 15:13:18 +00001400class AutoCallLua {
1401public:
1402 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1403 lua_getglobal(L, func);
1404 if (!lua_isfunction(L, -1)) {
1405 int t = lua_type(L, -1);
1406 SkDebugf("--- expected function %d\n", t);
1407 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001408
reed@google.com74ce6f02013-05-22 15:13:18 +00001409 lua_newtable(L);
1410 setfield_string(L, "verb", verb);
1411 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001412
reed@google.com74ce6f02013-05-22 15:13:18 +00001413 ~AutoCallLua() {
1414 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1415 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1416 }
1417 lua_settop(fL, -1);
1418 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001419
reed@google.com74ce6f02013-05-22 15:13:18 +00001420private:
1421 lua_State* fL;
1422};
1423
1424#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1425
1426///////////////////////////////////////////////////////////////////////////////
1427
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001428static int lsk_newDocumentPDF(lua_State* L) {
1429 const char* file = NULL;
1430 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1431 file = lua_tolstring(L, 1, NULL);
1432 }
1433
1434 SkDocument* doc = SkDocument::CreatePDF(file);
1435 if (NULL == doc) {
1436 // do I need to push a nil on the stack and return 1?
1437 return 0;
1438 } else {
1439 push_ref(L, doc);
1440 doc->unref();
1441 return 1;
1442 }
1443}
1444
reed@google.com3597b732013-05-22 20:12:50 +00001445static int lsk_newPaint(lua_State* L) {
1446 push_new<SkPaint>(L);
1447 return 1;
1448}
1449
1450static int lsk_newPath(lua_State* L) {
1451 push_new<SkPath>(L);
1452 return 1;
1453}
1454
1455static int lsk_newRRect(lua_State* L) {
1456 SkRRect* rr = push_new<SkRRect>(L);
1457 rr->setEmpty();
1458 return 1;
1459}
1460
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001461static int lsk_newTypeface(lua_State* L) {
1462 const char* name = NULL;
1463 int style = SkTypeface::kNormal;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00001464
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001465 int count = lua_gettop(L);
1466 if (count > 0 && lua_isstring(L, 1)) {
1467 name = lua_tolstring(L, 1, NULL);
1468 if (count > 1 && lua_isnumber(L, 2)) {
1469 style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic;
1470 }
1471 }
1472
1473 SkTypeface* face = SkTypeface::CreateFromName(name,
1474 (SkTypeface::Style)style);
1475// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
1476 if (NULL == face) {
1477 face = SkTypeface::RefDefault();
1478 }
1479 push_ref(L, face);
1480 face->unref();
1481 return 1;
1482}
reed@google.com3597b732013-05-22 20:12:50 +00001483
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001484static int lsk_loadImage(lua_State* L) {
1485 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1486 const char* name = lua_tolstring(L, 1, NULL);
1487 SkAutoDataUnref data(SkData::NewFromFileName(name));
1488 if (data.get()) {
piotaixr4bcc2022014-09-17 14:33:30 -07001489 SkImage* image = SkImage::NewFromGenerator(
1490 SkDecodingImageGenerator::Create(data, SkDecodingImageGenerator::Options()));
1491
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001492 if (image) {
1493 push_ref(L, image);
1494 image->unref();
1495 return 1;
1496 }
1497 }
1498 }
1499 return 0;
1500}
1501
reed@google.com3597b732013-05-22 20:12:50 +00001502static void register_Sk(lua_State* L) {
1503 lua_newtable(L);
1504 lua_pushvalue(L, -1);
1505 lua_setglobal(L, "Sk");
1506 // the Sk table is still on top
1507
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001508 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001509 setfield_function(L, "loadImage", lsk_loadImage);
reed@google.com3597b732013-05-22 20:12:50 +00001510 setfield_function(L, "newPaint", lsk_newPaint);
1511 setfield_function(L, "newPath", lsk_newPath);
1512 setfield_function(L, "newRRect", lsk_newRRect);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001513 setfield_function(L, "newTypeface", lsk_newTypeface);
reed@google.com3597b732013-05-22 20:12:50 +00001514 lua_pop(L, 1); // pop off the Sk table
1515}
1516
reed@google.com74ce6f02013-05-22 15:13:18 +00001517#define REG_CLASS(L, C) \
1518 do { \
reed@google.com3597b732013-05-22 20:12:50 +00001519 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00001520 lua_pushvalue(L, -1); \
1521 lua_setfield(L, -2, "__index"); \
1522 luaL_setfuncs(L, g##C##_Methods, 0); \
1523 lua_pop(L, 1); /* pop off the meta-table */ \
1524 } while (0)
1525
1526void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00001527 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00001528 REG_CLASS(L, SkCanvas);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001529 REG_CLASS(L, SkDocument);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001530 REG_CLASS(L, SkImage);
reed@google.com74ce6f02013-05-22 15:13:18 +00001531 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001532 REG_CLASS(L, SkPath);
1533 REG_CLASS(L, SkPathEffect);
reed@google.com74ce6f02013-05-22 15:13:18 +00001534 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00001535 REG_CLASS(L, SkShader);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001536 REG_CLASS(L, SkTypeface);
humper@google.com2815c192013-07-10 22:42:30 +00001537 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00001538}
zachr@google.com28c27c82013-06-20 17:15:05 +00001539
reed@google.com7bce9982013-06-20 17:40:21 +00001540extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00001541extern "C" int luaopen_skia(lua_State* L) {
1542 SkLua::Load(L);
1543 return 0;
1544}