blob: 827abc64f83de1d8d2c5ac868f2fc5df127285ff [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"
reed96affcd2014-10-13 12:38:04 -070022#include "SkPictureRecorder.h"
reed@google.com5fdc9832013-07-24 15:47:52 +000023#include "SkPixelRef.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000024#include "SkRRect.h"
25#include "SkString.h"
reed485557f2014-10-12 10:36:47 -070026#include "SkSurface.h"
fmalitab7425172014-08-26 07:56:44 -070027#include "SkTextBlob.h"
reed@google.come3823fd2013-05-30 18:55:14 +000028#include "SkTypeface.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000029
30extern "C" {
reed@google.com3597b732013-05-22 20:12:50 +000031 #include "lua.h"
32 #include "lualib.h"
33 #include "lauxlib.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000034}
35
reed@google.comfd345872013-05-22 20:53:42 +000036// return the metatable name for a given class
reed@google.com3597b732013-05-22 20:12:50 +000037template <typename T> const char* get_mtname();
reed@google.comfd345872013-05-22 20:53:42 +000038#define DEF_MTNAME(T) \
39 template <> const char* get_mtname<T>() { \
40 return #T "_LuaMetaTableName"; \
41 }
42
43DEF_MTNAME(SkCanvas)
mike@reedtribe.orgfb858242013-06-08 16:39:44 +000044DEF_MTNAME(SkDocument)
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000045DEF_MTNAME(SkImage)
reed@google.comfd345872013-05-22 20:53:42 +000046DEF_MTNAME(SkMatrix)
47DEF_MTNAME(SkRRect)
48DEF_MTNAME(SkPath)
49DEF_MTNAME(SkPaint)
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +000050DEF_MTNAME(SkPathEffect)
reed96affcd2014-10-13 12:38:04 -070051DEF_MTNAME(SkPicture)
52DEF_MTNAME(SkPictureRecorder)
reed@google.com5fdc9832013-07-24 15:47:52 +000053DEF_MTNAME(SkShader)
reed485557f2014-10-12 10:36:47 -070054DEF_MTNAME(SkSurface)
fmalitab7425172014-08-26 07:56:44 -070055DEF_MTNAME(SkTextBlob)
mike@reedtribe.orge6469f12013-06-08 03:15:47 +000056DEF_MTNAME(SkTypeface)
reed@google.com74ce6f02013-05-22 15:13:18 +000057
reed@google.com3597b732013-05-22 20:12:50 +000058template <typename T> T* push_new(lua_State* L) {
59 T* addr = (T*)lua_newuserdata(L, sizeof(T));
60 new (addr) T;
61 luaL_getmetatable(L, get_mtname<T>());
62 lua_setmetatable(L, -2);
63 return addr;
64}
reed@google.com74ce6f02013-05-22 15:13:18 +000065
66template <typename T> void push_obj(lua_State* L, const T& obj) {
67 new (lua_newuserdata(L, sizeof(T))) T(obj);
reed@google.com3597b732013-05-22 20:12:50 +000068 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000069 lua_setmetatable(L, -2);
70}
71
72template <typename T> void push_ref(lua_State* L, T* ref) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +000073 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
reed@google.com3597b732013-05-22 20:12:50 +000074 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000075 lua_setmetatable(L, -2);
76}
77
78template <typename T> T* get_ref(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +000079 return *(T**)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000080}
81
82template <typename T> T* get_obj(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +000083 return (T*)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000084}
85
reed@google.com88c9ec92013-05-22 15:43:21 +000086static bool lua2bool(lua_State* L, int index) {
87 return !!lua_toboolean(L, index);
88}
89
reed@google.com74ce6f02013-05-22 15:13:18 +000090///////////////////////////////////////////////////////////////////////////////
91
reed@google.com3597b732013-05-22 20:12:50 +000092SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
93 fL = luaL_newstate();
94 luaL_openlibs(fL);
95 SkLua::Load(fL);
96}
97
98SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
99
100SkLua::~SkLua() {
101 if (fWeOwnL) {
102 if (fTermCode.size() > 0) {
103 lua_getglobal(fL, fTermCode.c_str());
104 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
105 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
106 }
107 }
108 lua_close(fL);
109 }
110}
111
112bool SkLua::runCode(const char code[]) {
113 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
114 if (err) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000115 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
reed@google.com3597b732013-05-22 20:12:50 +0000116 return false;
117 }
118 return true;
119}
120
121bool SkLua::runCode(const void* code, size_t size) {
122 SkString str((const char*)code, size);
123 return this->runCode(str.c_str());
124}
125
126///////////////////////////////////////////////////////////////////////////////
127
128#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
129
reed@google.com29563872013-07-10 21:23:49 +0000130static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
131 if (pred) {
132 lua_pushboolean(L, true);
133 lua_setfield(L, -2, key);
134 }
135}
136
reed@google.com74ce6f02013-05-22 15:13:18 +0000137static void setfield_string(lua_State* L, const char key[], const char value[]) {
138 lua_pushstring(L, value);
139 lua_setfield(L, -2, key);
140}
141
142static void setfield_number(lua_State* L, const char key[], double value) {
143 lua_pushnumber(L, value);
144 lua_setfield(L, -2, key);
145}
146
humper@google.com2815c192013-07-10 22:42:30 +0000147static void setfield_boolean(lua_State* L, const char key[], bool value) {
148 lua_pushboolean(L, value);
149 lua_setfield(L, -2, key);
150}
151
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000152static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
153 setfield_number(L, key, SkScalarToLua(value));
154}
155
reed@google.com3597b732013-05-22 20:12:50 +0000156static void setfield_function(lua_State* L,
157 const char key[], lua_CFunction value) {
158 lua_pushcfunction(L, value);
159 lua_setfield(L, -2, key);
reed@google.com74ce6f02013-05-22 15:13:18 +0000160}
161
reed@google.come3823fd2013-05-30 18:55:14 +0000162static void setarray_number(lua_State* L, int index, double value) {
163 lua_pushnumber(L, value);
164 lua_rawseti(L, -2, index);
165}
166
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000167static void setarray_scalar(lua_State* L, int index, SkScalar value) {
168 setarray_number(L, index, SkScalarToLua(value));
169}
170
reed@google.com74ce6f02013-05-22 15:13:18 +0000171void SkLua::pushBool(bool value, const char key[]) {
172 lua_pushboolean(fL, value);
173 CHECK_SETFIELD(key);
174}
175
176void SkLua::pushString(const char str[], const char key[]) {
177 lua_pushstring(fL, str);
178 CHECK_SETFIELD(key);
179}
180
reed@google.come3823fd2013-05-30 18:55:14 +0000181void SkLua::pushString(const char str[], size_t length, const char key[]) {
182 // TODO: how to do this w/o making a copy?
183 SkString s(str, length);
184 lua_pushstring(fL, s.c_str());
185 CHECK_SETFIELD(key);
186}
187
reed@google.com74ce6f02013-05-22 15:13:18 +0000188void SkLua::pushString(const SkString& str, const char key[]) {
189 lua_pushstring(fL, str.c_str());
190 CHECK_SETFIELD(key);
191}
192
193void SkLua::pushColor(SkColor color, const char key[]) {
194 lua_newtable(fL);
195 setfield_number(fL, "a", SkColorGetA(color) / 255.0);
196 setfield_number(fL, "r", SkColorGetR(color) / 255.0);
197 setfield_number(fL, "g", SkColorGetG(color) / 255.0);
198 setfield_number(fL, "b", SkColorGetB(color) / 255.0);
199 CHECK_SETFIELD(key);
200}
201
reed@google.come3823fd2013-05-30 18:55:14 +0000202void SkLua::pushU32(uint32_t value, const char key[]) {
203 lua_pushnumber(fL, (double)value);
204 CHECK_SETFIELD(key);
205}
206
reed@google.com74ce6f02013-05-22 15:13:18 +0000207void SkLua::pushScalar(SkScalar value, const char key[]) {
208 lua_pushnumber(fL, SkScalarToLua(value));
209 CHECK_SETFIELD(key);
210}
211
reed@google.come3823fd2013-05-30 18:55:14 +0000212void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
213 lua_newtable(fL);
214 for (int i = 0; i < count; ++i) {
215 // make it base-1 to match lua convention
216 setarray_number(fL, i + 1, (double)array[i]);
217 }
218 CHECK_SETFIELD(key);
219}
220
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000221void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
222 lua_newtable(fL);
223 for (int i = 0; i < count; ++i) {
224 // make it base-1 to match lua convention
225 lua_newtable(fL);
226 this->pushScalar(array[i].fX, "x");
227 this->pushScalar(array[i].fY, "y");
228 lua_rawseti(fL, -2, i + 1);
229 }
230 CHECK_SETFIELD(key);
231}
232
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000233void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
234 lua_newtable(fL);
235 for (int i = 0; i < count; ++i) {
236 // make it base-1 to match lua convention
237 setarray_scalar(fL, i + 1, array[i]);
238 }
239 CHECK_SETFIELD(key);
240}
241
reed@google.com74ce6f02013-05-22 15:13:18 +0000242void SkLua::pushRect(const SkRect& r, const char key[]) {
243 lua_newtable(fL);
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000244 setfield_scalar(fL, "left", r.fLeft);
245 setfield_scalar(fL, "top", r.fTop);
246 setfield_scalar(fL, "right", r.fRight);
247 setfield_scalar(fL, "bottom", r.fBottom);
reed@google.com74ce6f02013-05-22 15:13:18 +0000248 CHECK_SETFIELD(key);
249}
250
251void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
252 push_obj(fL, rr);
253 CHECK_SETFIELD(key);
254}
255
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000256void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
257 lua_newtable(fL);
258 setfield_scalar(fL, "phase", info.fPhase);
259 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
260 CHECK_SETFIELD(key);
261}
262
263
reed@google.com74ce6f02013-05-22 15:13:18 +0000264void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
265 push_obj(fL, matrix);
266 CHECK_SETFIELD(key);
267}
268
269void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
270 push_obj(fL, paint);
271 CHECK_SETFIELD(key);
272}
273
274void SkLua::pushPath(const SkPath& path, const char key[]) {
275 push_obj(fL, path);
276 CHECK_SETFIELD(key);
277}
278
279void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
280 push_ref(fL, canvas);
281 CHECK_SETFIELD(key);
282}
283
fmalitab7425172014-08-26 07:56:44 -0700284void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
285 push_ref(fL, const_cast<SkTextBlob*>(blob));
286 CHECK_SETFIELD(key);
287}
288
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000289static const char* element_type(SkClipStack::Element::Type type) {
290 switch (type) {
291 case SkClipStack::Element::kEmpty_Type:
292 return "empty";
293 case SkClipStack::Element::kRect_Type:
294 return "rect";
295 case SkClipStack::Element::kRRect_Type:
296 return "rrect";
297 case SkClipStack::Element::kPath_Type:
298 return "path";
299 }
300 return "unknown";
301}
302
303static const char* region_op(SkRegion::Op op) {
304 switch (op) {
305 case SkRegion::kDifference_Op:
306 return "difference";
307 case SkRegion::kIntersect_Op:
308 return "intersect";
309 case SkRegion::kUnion_Op:
310 return "union";
311 case SkRegion::kXOR_Op:
312 return "xor";
313 case SkRegion::kReverseDifference_Op:
314 return "reverse-difference";
315 case SkRegion::kReplace_Op:
316 return "replace";
317 }
318 return "unknown";
319}
320
321void SkLua::pushClipStack(const SkClipStack& stack, const char* key) {
322 lua_newtable(fL);
323 SkClipStack::B2TIter iter(stack);
324 const SkClipStack::Element* element;
325 int i = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700326 while ((element = iter.next())) {
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000327 this->pushClipStackElement(*element);
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000328 lua_rawseti(fL, -2, ++i);
329 }
330 CHECK_SETFIELD(key);
331}
332
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000333void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) {
334 lua_newtable(fL);
335 SkClipStack::Element::Type type = element.getType();
336 this->pushString(element_type(type), "type");
337 switch (type) {
338 case SkClipStack::Element::kEmpty_Type:
339 break;
340 case SkClipStack::Element::kRect_Type:
341 this->pushRect(element.getRect(), "rect");
342 break;
343 case SkClipStack::Element::kRRect_Type:
344 this->pushRRect(element.getRRect(), "rrect");
345 break;
346 case SkClipStack::Element::kPath_Type:
347 this->pushPath(element.getPath(), "path");
348 break;
349 }
350 this->pushString(region_op(element.getOp()), "op");
351 this->pushBool(element.isAA(), "aa");
352 CHECK_SETFIELD(key);
353}
354
355
reed@google.com74ce6f02013-05-22 15:13:18 +0000356///////////////////////////////////////////////////////////////////////////////
357///////////////////////////////////////////////////////////////////////////////
358
reed485557f2014-10-12 10:36:47 -0700359static int lua2int_def(lua_State* L, int index, int defaultValue) {
360 if (lua_isnumber(L, index)) {
361 return (int)lua_tonumber(L, index);
362 } else {
363 return defaultValue;
364 }
365}
366
reed@google.com74ce6f02013-05-22 15:13:18 +0000367static SkScalar lua2scalar(lua_State* L, int index) {
368 SkASSERT(lua_isnumber(L, index));
369 return SkLuaToScalar(lua_tonumber(L, index));
370}
371
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000372static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
373 if (lua_isnumber(L, index)) {
374 return SkLuaToScalar(lua_tonumber(L, index));
375 } else {
376 return defaultValue;
377 }
378}
379
reed@google.com74ce6f02013-05-22 15:13:18 +0000380static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
381 SkASSERT(lua_istable(L, index));
382 lua_pushstring(L, key);
383 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000384
reed@google.com74ce6f02013-05-22 15:13:18 +0000385 SkScalar value = lua2scalar(L, -1);
386 lua_pop(L, 1);
387 return value;
388}
389
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000390static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
391 SkASSERT(lua_istable(L, index));
392 lua_pushstring(L, key);
393 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000394
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000395 SkScalar value;
396 if (lua_isnil(L, -1)) {
397 value = def;
398 } else {
399 value = lua2scalar(L, -1);
400 }
401 lua_pop(L, 1);
402 return value;
403}
404
reed@google.com74ce6f02013-05-22 15:13:18 +0000405static U8CPU unit2byte(SkScalar x) {
406 if (x <= 0) {
407 return 0;
408 } else if (x >= 1) {
409 return 255;
410 } else {
411 return SkScalarRoundToInt(x * 255);
412 }
413}
414
415static SkColor lua2color(lua_State* L, int index) {
reed485557f2014-10-12 10:36:47 -0700416 return SkColorSetARGB(unit2byte(getfield_scalar_default(L, index, "a", 1)),
417 unit2byte(getfield_scalar_default(L, index, "r", 0)),
418 unit2byte(getfield_scalar_default(L, index, "g", 0)),
419 unit2byte(getfield_scalar_default(L, index, "b", 0)));
reed@google.com74ce6f02013-05-22 15:13:18 +0000420}
421
422static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000423 rect->set(getfield_scalar_default(L, index, "left", 0),
424 getfield_scalar_default(L, index, "top", 0),
reed@google.com74ce6f02013-05-22 15:13:18 +0000425 getfield_scalar(L, index, "right"),
426 getfield_scalar(L, index, "bottom"));
427 return rect;
428}
429
reedf355df52014-10-12 12:18:40 -0700430static int lcanvas_clear(lua_State* L) {
431 get_ref<SkCanvas>(L, 1)->clear(0);
432 return 0;
433}
434
reed@google.com74ce6f02013-05-22 15:13:18 +0000435static int lcanvas_drawColor(lua_State* L) {
436 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
437 return 0;
438}
439
440static int lcanvas_drawRect(lua_State* L) {
441 SkRect rect;
442 get_ref<SkCanvas>(L, 1)->drawRect(*lua2rect(L, 2, &rect),
443 *get_obj<SkPaint>(L, 3));
444 return 0;
445}
446
447static int lcanvas_drawOval(lua_State* L) {
448 SkRect rect;
449 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
450 *get_obj<SkPaint>(L, 3));
451 return 0;
452}
453
454static int lcanvas_drawCircle(lua_State* L) {
455 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
456 lua2scalar(L, 3),
457 lua2scalar(L, 4),
458 *get_obj<SkPaint>(L, 5));
459 return 0;
460}
461
reed485557f2014-10-12 10:36:47 -0700462static SkPaint* lua2OptionalPaint(lua_State* L, int index, SkPaint* paint) {
463 if (lua_isnumber(L, index)) {
464 paint->setAlpha(SkScalarRoundToInt(lua2scalar(L, index) * 255));
465 return paint;
reedf355df52014-10-12 12:18:40 -0700466 } else if (lua_isuserdata(L, index)) {
reed485557f2014-10-12 10:36:47 -0700467 const SkPaint* ptr = get_obj<SkPaint>(L, index);
468 if (ptr) {
469 *paint = *ptr;
470 return paint;
471 }
472 }
473 return NULL;
474}
475
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000476static int lcanvas_drawImage(lua_State* L) {
477 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
478 SkImage* image = get_ref<SkImage>(L, 2);
479 if (NULL == image) {
480 return 0;
481 }
482 SkScalar x = lua2scalar(L, 3);
483 SkScalar y = lua2scalar(L, 4);
484
485 SkPaint paint;
reed485557f2014-10-12 10:36:47 -0700486 canvas->drawImage(image, x, y, lua2OptionalPaint(L, 5, &paint));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000487 return 0;
488}
489
reedba5fb932014-10-10 15:28:19 -0700490static int lcanvas_drawImageRect(lua_State* L) {
491 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
492 SkImage* image = get_ref<SkImage>(L, 2);
493 if (NULL == image) {
494 return 0;
495 }
496
497 SkRect srcR, dstR;
498 SkRect* srcRPtr = NULL;
499 if (!lua_isnil(L, 3)) {
500 srcRPtr = lua2rect(L, 3, &srcR);
501 }
502 lua2rect(L, 4, &dstR);
503
504 SkPaint paint;
reed485557f2014-10-12 10:36:47 -0700505 canvas->drawImageRect(image, srcRPtr, dstR, lua2OptionalPaint(L, 5, &paint));
reedba5fb932014-10-10 15:28:19 -0700506 return 0;
507}
508
reed@google.comfd345872013-05-22 20:53:42 +0000509static int lcanvas_drawPath(lua_State* L) {
510 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
511 *get_obj<SkPaint>(L, 3));
512 return 0;
513}
514
reed96affcd2014-10-13 12:38:04 -0700515// drawPicture(pic, x, y, paint)
516static int lcanvas_drawPicture(lua_State* L) {
517 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
518 SkPicture* picture = get_ref<SkPicture>(L, 2);
519 SkScalar x = lua2scalar_def(L, 3, 0);
520 SkScalar y = lua2scalar_def(L, 4, 0);
521 SkMatrix matrix, *matrixPtr = NULL;
522 if (x || y) {
523 matrix.setTranslate(x, y);
524 matrixPtr = &matrix;
525 }
526 SkPaint paint;
527 canvas->drawPicture(picture, matrixPtr, lua2OptionalPaint(L, 5, &paint));
528 return 0;
529}
530
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000531static int lcanvas_drawText(lua_State* L) {
532 if (lua_gettop(L) < 5) {
533 return 0;
534 }
535
536 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
537 size_t len;
538 const char* text = lua_tolstring(L, 2, &len);
539 get_ref<SkCanvas>(L, 1)->drawText(text, len,
540 lua2scalar(L, 3), lua2scalar(L, 4),
541 *get_obj<SkPaint>(L, 5));
542 }
543 return 0;
544}
545
reed@google.com74ce6f02013-05-22 15:13:18 +0000546static int lcanvas_getSaveCount(lua_State* L) {
547 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
548 return 1;
549}
550
551static int lcanvas_getTotalMatrix(lua_State* L) {
552 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
553 return 1;
554}
555
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000556static int lcanvas_getClipStack(lua_State* L) {
557 SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack());
558 return 1;
559}
560
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000561int SkLua::lcanvas_getReducedClipStack(lua_State* L) {
562#if SK_SUPPORT_GPU
563 const SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
564 SkISize layerSize = canvas->getTopLayerSize();
565 SkIPoint layerOrigin = canvas->getTopLayerOrigin();
566 SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY,
567 layerSize.fWidth, layerSize.fHeight);
568
569 GrReducedClip::ElementList elements;
570 GrReducedClip::InitialState initialState;
571 int32_t genID;
572 SkIRect resultBounds;
573
574 const SkClipStack& stack = *canvas->getClipStack();
575
576 GrReducedClip::ReduceClipStack(stack,
577 queryBounds,
578 &elements,
579 &genID,
580 &initialState,
581 &resultBounds,
582 NULL);
583
584 GrReducedClip::ElementList::Iter iter(elements);
585 int i = 0;
586 lua_newtable(L);
bsalomon49f085d2014-09-05 13:34:00 -0700587 while(iter.get()) {
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000588 SkLua(L).pushClipStackElement(*iter.get());
589 iter.next();
590 lua_rawseti(L, -2, ++i);
591 }
592 // Currently this only returns the element list to lua, not the initial state or result bounds.
593 // It could return these as additional items on the lua stack.
594 return 1;
595#else
596 return 0;
597#endif
598}
599
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000600static int lcanvas_save(lua_State* L) {
601 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
602 return 1;
603}
604
605static int lcanvas_restore(lua_State* L) {
606 get_ref<SkCanvas>(L, 1)->restore();
607 return 0;
608}
609
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000610static int lcanvas_scale(lua_State* L) {
611 SkScalar sx = lua2scalar_def(L, 2, 1);
612 SkScalar sy = lua2scalar_def(L, 3, sx);
613 get_ref<SkCanvas>(L, 1)->scale(sx, sy);
614 return 0;
615}
616
reed@google.com3597b732013-05-22 20:12:50 +0000617static int lcanvas_translate(lua_State* L) {
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000618 SkScalar tx = lua2scalar_def(L, 2, 0);
619 SkScalar ty = lua2scalar_def(L, 3, 0);
620 get_ref<SkCanvas>(L, 1)->translate(tx, ty);
621 return 0;
622}
623
624static int lcanvas_rotate(lua_State* L) {
625 SkScalar degrees = lua2scalar_def(L, 2, 0);
626 get_ref<SkCanvas>(L, 1)->rotate(degrees);
reed@google.com3597b732013-05-22 20:12:50 +0000627 return 0;
628}
629
reed485557f2014-10-12 10:36:47 -0700630static int lcanvas_newSurface(lua_State* L) {
631 int width = lua2int_def(L, 2, 0);
632 int height = lua2int_def(L, 2, 0);
633 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
634 SkSurface* surface = get_ref<SkCanvas>(L, 1)->newSurface(info);
635 if (NULL == surface) {
636 lua_pushnil(L);
637 } else {
638 push_ref(L, surface);
639 surface->unref();
640 }
641 return 1;
642}
643
reed@google.com74ce6f02013-05-22 15:13:18 +0000644static int lcanvas_gc(lua_State* L) {
645 get_ref<SkCanvas>(L, 1)->unref();
646 return 0;
647}
648
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000649const struct luaL_Reg gSkCanvas_Methods[] = {
reedf355df52014-10-12 12:18:40 -0700650 { "clear", lcanvas_clear },
reed@google.com74ce6f02013-05-22 15:13:18 +0000651 { "drawColor", lcanvas_drawColor },
652 { "drawRect", lcanvas_drawRect },
653 { "drawOval", lcanvas_drawOval },
654 { "drawCircle", lcanvas_drawCircle },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000655 { "drawImage", lcanvas_drawImage },
reedba5fb932014-10-10 15:28:19 -0700656 { "drawImageRect", lcanvas_drawImageRect },
reed@google.comfd345872013-05-22 20:53:42 +0000657 { "drawPath", lcanvas_drawPath },
reed96affcd2014-10-13 12:38:04 -0700658 { "drawPicture", lcanvas_drawPicture },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000659 { "drawText", lcanvas_drawText },
reed@google.com74ce6f02013-05-22 15:13:18 +0000660 { "getSaveCount", lcanvas_getSaveCount },
661 { "getTotalMatrix", lcanvas_getTotalMatrix },
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000662 { "getClipStack", lcanvas_getClipStack },
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000663#if SK_SUPPORT_GPU
664 { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
665#endif
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000666 { "save", lcanvas_save },
667 { "restore", lcanvas_restore },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000668 { "scale", lcanvas_scale },
reed@google.com3597b732013-05-22 20:12:50 +0000669 { "translate", lcanvas_translate },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000670 { "rotate", lcanvas_rotate },
reed485557f2014-10-12 10:36:47 -0700671
672 { "newSurface", lcanvas_newSurface },
673
reed@google.com74ce6f02013-05-22 15:13:18 +0000674 { "__gc", lcanvas_gc },
675 { NULL, NULL }
676};
677
678///////////////////////////////////////////////////////////////////////////////
679
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000680static int ldocument_beginPage(lua_State* L) {
681 const SkRect* contentPtr = NULL;
682 push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2),
683 lua2scalar(L, 3),
684 contentPtr));
685 return 1;
686}
687
688static int ldocument_endPage(lua_State* L) {
689 get_ref<SkDocument>(L, 1)->endPage();
690 return 0;
691}
692
693static int ldocument_close(lua_State* L) {
694 get_ref<SkDocument>(L, 1)->close();
695 return 0;
696}
697
698static int ldocument_gc(lua_State* L) {
699 get_ref<SkDocument>(L, 1)->unref();
700 return 0;
701}
702
703static const struct luaL_Reg gSkDocument_Methods[] = {
704 { "beginPage", ldocument_beginPage },
705 { "endPage", ldocument_endPage },
706 { "close", ldocument_close },
707 { "__gc", ldocument_gc },
708 { NULL, NULL }
709};
710
711///////////////////////////////////////////////////////////////////////////////
712
reed@google.com74ce6f02013-05-22 15:13:18 +0000713static int lpaint_isAntiAlias(lua_State* L) {
714 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
715 return 1;
716}
717
718static int lpaint_setAntiAlias(lua_State* L) {
reed@google.com88c9ec92013-05-22 15:43:21 +0000719 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +0000720 return 0;
721}
722
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000723static int lpaint_isDither(lua_State* L) {
724 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
725 return 1;
726}
727
728static int lpaint_isUnderlineText(lua_State* L) {
729 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText());
730 return 1;
731}
732
733static int lpaint_isStrikeThruText(lua_State* L) {
734 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText());
735 return 1;
736}
737
738static int lpaint_isFakeBoldText(lua_State* L) {
739 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
740 return 1;
741}
742
743static int lpaint_isLinearText(lua_State* L) {
744 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
745 return 1;
746}
747
748static int lpaint_isSubpixelText(lua_State* L) {
749 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
750 return 1;
751}
752
reed09a1d672014-10-11 13:13:11 -0700753static int lpaint_setSubpixelText(lua_State* L) {
754 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
755 return 1;
756}
757
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000758static int lpaint_isDevKernText(lua_State* L) {
759 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
760 return 1;
761}
762
763static int lpaint_isLCDRenderText(lua_State* L) {
764 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
765 return 1;
766}
767
768static int lpaint_isEmbeddedBitmapText(lua_State* L) {
769 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
770 return 1;
771}
772
773static int lpaint_isAutohinted(lua_State* L) {
774 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
775 return 1;
776}
777
778static int lpaint_isVerticalText(lua_State* L) {
779 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
780 return 1;
781}
782
reed@google.com74ce6f02013-05-22 15:13:18 +0000783static int lpaint_getColor(lua_State* L) {
784 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
785 return 1;
786}
787
788static int lpaint_setColor(lua_State* L) {
789 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
790 return 0;
791}
792
reed@google.come3823fd2013-05-30 18:55:14 +0000793static int lpaint_getTextSize(lua_State* L) {
794 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
795 return 1;
796}
797
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000798static int lpaint_getTextScaleX(lua_State* L) {
799 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
800 return 1;
801}
802
803static int lpaint_getTextSkewX(lua_State* L) {
804 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
805 return 1;
806}
807
reed@google.come3823fd2013-05-30 18:55:14 +0000808static int lpaint_setTextSize(lua_State* L) {
809 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
810 return 0;
811}
812
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000813static int lpaint_getTypeface(lua_State* L) {
814 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
815 return 1;
816}
817
818static int lpaint_setTypeface(lua_State* L) {
819 get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2));
820 return 0;
821}
822
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000823static int lpaint_getHinting(lua_State* L) {
824 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
825 return 1;
826}
827
reed@google.come3823fd2013-05-30 18:55:14 +0000828static int lpaint_getFontID(lua_State* L) {
829 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
830 SkLua(L).pushU32(SkTypeface::UniqueID(face));
831 return 1;
832}
833
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000834static const struct {
835 const char* fLabel;
836 SkPaint::Align fAlign;
837} gAlignRec[] = {
838 { "left", SkPaint::kLeft_Align },
839 { "center", SkPaint::kCenter_Align },
840 { "right", SkPaint::kRight_Align },
841};
842
843static int lpaint_getTextAlign(lua_State* L) {
844 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
845 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
846 if (gAlignRec[i].fAlign == align) {
847 lua_pushstring(L, gAlignRec[i].fLabel);
848 return 1;
849 }
850 }
851 return 0;
852}
853
854static int lpaint_setTextAlign(lua_State* L) {
855 if (lua_isstring(L, 2)) {
856 size_t len;
857 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000858
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000859 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
860 if (!strcmp(gAlignRec[i].fLabel, label)) {
861 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
862 break;
863 }
864 }
865 }
866 return 0;
867}
868
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000869static int lpaint_getStroke(lua_State* L) {
870 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
871 return 1;
872}
873
874static int lpaint_setStroke(lua_State* L) {
875 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000876
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000877 if (lua_toboolean(L, 2)) {
878 style = SkPaint::kStroke_Style;
879 } else {
880 style = SkPaint::kFill_Style;
881 }
882 get_obj<SkPaint>(L, 1)->setStyle(style);
883 return 0;
884}
885
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000886static int lpaint_getStrokeCap(lua_State* L) {
887 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
888 return 1;
889}
890
891static int lpaint_getStrokeJoin(lua_State* L) {
892 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
893 return 1;
894}
895
896static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +0000897 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000898 return 1;
899}
900
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000901static int lpaint_getStrokeWidth(lua_State* L) {
902 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
903 return 1;
904}
905
906static int lpaint_setStrokeWidth(lua_State* L) {
907 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
908 return 0;
909}
910
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000911static int lpaint_getStrokeMiter(lua_State* L) {
912 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
913 return 1;
914}
915
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000916static int lpaint_measureText(lua_State* L) {
917 if (lua_isstring(L, 2)) {
918 size_t len;
919 const char* text = lua_tolstring(L, 2, &len);
920 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
921 return 1;
922 }
923 return 0;
924}
925
926struct FontMetrics {
927 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
928 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
929 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
930 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
931 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
932 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
933 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
934 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
935 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
936};
937
938static int lpaint_getFontMetrics(lua_State* L) {
939 SkPaint::FontMetrics fm;
940 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000941
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000942 lua_newtable(L);
943 setfield_scalar(L, "top", fm.fTop);
944 setfield_scalar(L, "ascent", fm.fAscent);
945 setfield_scalar(L, "descent", fm.fDescent);
946 setfield_scalar(L, "bottom", fm.fBottom);
947 setfield_scalar(L, "leading", fm.fLeading);
948 SkLua(L).pushScalar(height);
949 return 2;
950}
951
reed@google.com29563872013-07-10 21:23:49 +0000952static int lpaint_getEffects(lua_State* L) {
953 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000954
reed@google.com29563872013-07-10 21:23:49 +0000955 lua_newtable(L);
956 setfield_bool_if(L, "looper", !!paint->getLooper());
957 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
958 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer());
959 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
960 setfield_bool_if(L, "shader", !!paint->getShader());
961 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
962 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
963 setfield_bool_if(L, "xfermode", !!paint->getXfermode());
964 return 1;
965}
966
reed@google.com5fdc9832013-07-24 15:47:52 +0000967static int lpaint_getShader(lua_State* L) {
968 const SkPaint* paint = get_obj<SkPaint>(L, 1);
969 SkShader* shader = paint->getShader();
970 if (shader) {
971 push_ref(L, shader);
972 return 1;
973 }
974 return 0;
975}
976
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000977static int lpaint_getPathEffect(lua_State* L) {
978 const SkPaint* paint = get_obj<SkPaint>(L, 1);
979 SkPathEffect* pe = paint->getPathEffect();
980 if (pe) {
981 push_ref(L, pe);
982 return 1;
983 }
984 return 0;
985}
986
reed@google.com74ce6f02013-05-22 15:13:18 +0000987static int lpaint_gc(lua_State* L) {
988 get_obj<SkPaint>(L, 1)->~SkPaint();
989 return 0;
990}
991
992static const struct luaL_Reg gSkPaint_Methods[] = {
993 { "isAntiAlias", lpaint_isAntiAlias },
994 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000995 { "isDither", lpaint_isDither },
996 { "isUnderlineText", lpaint_isUnderlineText },
997 { "isStrikeThruText", lpaint_isStrikeThruText },
998 { "isFakeBoldText", lpaint_isFakeBoldText },
999 { "isLinearText", lpaint_isLinearText },
1000 { "isSubpixelText", lpaint_isSubpixelText },
reed09a1d672014-10-11 13:13:11 -07001001 { "setSubpixelText", lpaint_setSubpixelText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001002 { "isDevKernText", lpaint_isDevKernText },
1003 { "isLCDRenderText", lpaint_isLCDRenderText },
1004 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
1005 { "isAutohinted", lpaint_isAutohinted },
1006 { "isVerticalText", lpaint_isVerticalText },
reed@google.com74ce6f02013-05-22 15:13:18 +00001007 { "getColor", lpaint_getColor },
1008 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +00001009 { "getTextSize", lpaint_getTextSize },
1010 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001011 { "getTextScaleX", lpaint_getTextScaleX },
1012 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001013 { "getTypeface", lpaint_getTypeface },
1014 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001015 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +00001016 { "getFontID", lpaint_getFontID },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001017 { "getTextAlign", lpaint_getTextAlign },
1018 { "setTextAlign", lpaint_setTextAlign },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001019 { "getStroke", lpaint_getStroke },
1020 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001021 { "getStrokeCap", lpaint_getStrokeCap },
1022 { "getStrokeJoin", lpaint_getStrokeJoin },
1023 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001024 { "getStrokeWidth", lpaint_getStrokeWidth },
1025 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001026 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001027 { "measureText", lpaint_measureText },
1028 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +00001029 { "getEffects", lpaint_getEffects },
reed@google.com5fdc9832013-07-24 15:47:52 +00001030 { "getShader", lpaint_getShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001031 { "getPathEffect", lpaint_getPathEffect },
reed@google.com74ce6f02013-05-22 15:13:18 +00001032 { "__gc", lpaint_gc },
1033 { NULL, NULL }
1034};
1035
1036///////////////////////////////////////////////////////////////////////////////
1037
reed@google.com5fdc9832013-07-24 15:47:52 +00001038static const char* mode2string(SkShader::TileMode mode) {
1039 static const char* gNames[] = { "clamp", "repeat", "mirror" };
1040 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
1041 return gNames[mode];
1042}
1043
1044static const char* gradtype2string(SkShader::GradientType t) {
1045 static const char* gNames[] = {
1046 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
1047 };
1048 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
1049 return gNames[t];
1050}
1051
1052static int lshader_isOpaque(lua_State* L) {
1053 SkShader* shader = get_ref<SkShader>(L, 1);
1054 return shader && shader->isOpaque();
1055}
1056
1057static int lshader_asABitmap(lua_State* L) {
1058 SkShader* shader = get_ref<SkShader>(L, 1);
1059 if (shader) {
1060 SkBitmap bm;
1061 SkMatrix matrix;
1062 SkShader::TileMode modes[2];
1063 switch (shader->asABitmap(&bm, &matrix, modes)) {
1064 case SkShader::kDefault_BitmapType:
1065 lua_newtable(L);
1066 setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0);
1067 setfield_number(L, "width", bm.width());
1068 setfield_number(L, "height", bm.height());
1069 setfield_string(L, "tileX", mode2string(modes[0]));
1070 setfield_string(L, "tileY", mode2string(modes[1]));
1071 return 1;
1072 default:
1073 break;
1074 }
1075 }
1076 return 0;
1077}
1078
1079static int lshader_asAGradient(lua_State* L) {
1080 SkShader* shader = get_ref<SkShader>(L, 1);
1081 if (shader) {
1082 SkShader::GradientInfo info;
1083 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001084
1085 SkColor colors[3]; // hacked in for extracting info on 3 color case.
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001086 SkScalar pos[3];
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001087
1088 info.fColorCount = 3;
1089 info.fColors = &colors[0];
1090 info.fColorOffsets = &pos[0];
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001091
reed@google.com5fdc9832013-07-24 15:47:52 +00001092 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001093
reed@google.com5fdc9832013-07-24 15:47:52 +00001094 if (SkShader::kNone_GradientType != t) {
1095 lua_newtable(L);
1096 setfield_string(L, "type", gradtype2string(t));
1097 setfield_number(L, "colorCount", info.fColorCount);
1098 setfield_string(L, "tile", mode2string(info.fTileMode));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001099
1100 if (info.fColorCount == 3){
1101 setfield_number(L, "midPos", pos[1]);
1102 }
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001103
reed@google.com5fdc9832013-07-24 15:47:52 +00001104 return 1;
1105 }
1106 }
1107 return 0;
1108}
1109
1110static int lshader_gc(lua_State* L) {
1111 get_ref<SkShader>(L, 1)->unref();
1112 return 0;
1113}
1114
1115static const struct luaL_Reg gSkShader_Methods[] = {
1116 { "isOpaque", lshader_isOpaque },
1117 { "asABitmap", lshader_asABitmap },
1118 { "asAGradient", lshader_asAGradient },
1119 { "__gc", lshader_gc },
1120 { NULL, NULL }
1121};
1122
1123///////////////////////////////////////////////////////////////////////////////
1124
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001125static int lpatheffect_asADash(lua_State* L) {
1126 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1127 if (pe) {
1128 SkPathEffect::DashInfo info;
1129 SkPathEffect::DashType dashType = pe->asADash(&info);
1130 if (SkPathEffect::kDash_DashType == dashType) {
1131 SkAutoTArray<SkScalar> intervals(info.fCount);
1132 info.fIntervals = intervals.get();
1133 pe->asADash(&info);
1134 SkLua(L).pushDash(info);
1135 return 1;
1136 }
1137 }
1138 return 0;
1139}
1140
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001141static int lpatheffect_gc(lua_State* L) {
1142 get_ref<SkPathEffect>(L, 1)->unref();
1143 return 0;
1144}
1145
1146static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001147 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001148 { "__gc", lpatheffect_gc },
1149 { NULL, NULL }
1150};
1151
1152///////////////////////////////////////////////////////////////////////////////
1153
humper@google.com2815c192013-07-10 22:42:30 +00001154static int lmatrix_getType(lua_State* L) {
1155 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001156
humper@google.com2815c192013-07-10 22:42:30 +00001157 lua_newtable(L);
1158 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1159 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1160 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1161 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1162 return 1;
1163}
1164
humper@google.com0f48ee02013-07-26 15:23:43 +00001165static int lmatrix_getScaleX(lua_State* L) {
1166 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1167 return 1;
1168}
1169
1170static int lmatrix_getScaleY(lua_State* L) {
1171 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1172 return 1;
1173}
1174
1175static int lmatrix_getTranslateX(lua_State* L) {
1176 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1177 return 1;
1178}
1179
1180static int lmatrix_getTranslateY(lua_State* L) {
1181 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1182 return 1;
1183}
1184
humper@google.com2815c192013-07-10 22:42:30 +00001185static const struct luaL_Reg gSkMatrix_Methods[] = {
1186 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001187 { "getScaleX", lmatrix_getScaleX },
1188 { "getScaleY", lmatrix_getScaleY },
1189 { "getTranslateX", lmatrix_getTranslateX },
1190 { "getTranslateY", lmatrix_getTranslateY },
humper@google.com2815c192013-07-10 22:42:30 +00001191 { NULL, NULL }
1192};
1193
1194///////////////////////////////////////////////////////////////////////////////
1195
reed@google.com74ce6f02013-05-22 15:13:18 +00001196static int lpath_getBounds(lua_State* L) {
1197 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1198 return 1;
1199}
1200
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001201static const char* fill_type_to_str(SkPath::FillType fill) {
1202 switch (fill) {
1203 case SkPath::kEvenOdd_FillType:
1204 return "even-odd";
1205 case SkPath::kWinding_FillType:
1206 return "winding";
1207 case SkPath::kInverseEvenOdd_FillType:
1208 return "inverse-even-odd";
1209 case SkPath::kInverseWinding_FillType:
1210 return "inverse-winding";
1211 }
1212 return "unknown";
1213}
1214
1215static int lpath_getFillType(lua_State* L) {
1216 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1217 SkLua(L).pushString(fill_type_to_str(fill));
1218 return 1;
1219}
1220
1221static SkString segment_masks_to_str(uint32_t segmentMasks) {
1222 SkString result;
1223 bool first = true;
1224 if (SkPath::kLine_SegmentMask & segmentMasks) {
1225 result.append("line");
1226 first = false;
1227 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1228 }
1229 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1230 if (!first) {
1231 result.append(" ");
1232 }
1233 result.append("quad");
1234 first = false;
1235 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1236 }
1237 if (SkPath::kConic_SegmentMask & segmentMasks) {
1238 if (!first) {
1239 result.append(" ");
1240 }
1241 result.append("conic");
1242 first = false;
1243 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1244 }
1245 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1246 if (!first) {
1247 result.append(" ");
1248 }
1249 result.append("cubic");
1250 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1251 }
1252 SkASSERT(0 == segmentMasks);
1253 return result;
1254}
1255
krajcevski95498ed2014-08-18 08:02:33 -07001256static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001257 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1258 SkLua(L).pushString(segment_masks_to_str(segMasks));
1259 return 1;
1260}
1261
1262static int lpath_isConvex(lua_State* L) {
1263 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1264 SkLua(L).pushBool(isConvex);
1265 return 1;
1266}
1267
reed@google.com74ce6f02013-05-22 15:13:18 +00001268static int lpath_isEmpty(lua_State* L) {
1269 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1270 return 1;
1271}
1272
1273static int lpath_isRect(lua_State* L) {
1274 SkRect r;
1275 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1276 int ret_count = 1;
1277 lua_pushboolean(L, pred);
1278 if (pred) {
1279 SkLua(L).pushRect(r);
1280 ret_count += 1;
1281 }
1282 return ret_count;
1283}
1284
1285static const char* dir2string(SkPath::Direction dir) {
1286 static const char* gStr[] = {
1287 "unknown", "cw", "ccw"
1288 };
1289 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1290 return gStr[dir];
1291}
1292
1293static int lpath_isNestedRects(lua_State* L) {
1294 SkRect rects[2];
1295 SkPath::Direction dirs[2];
1296 bool pred = get_obj<SkPath>(L, 1)->isNestedRects(rects, dirs);
1297 int ret_count = 1;
1298 lua_pushboolean(L, pred);
1299 if (pred) {
1300 SkLua lua(L);
1301 lua.pushRect(rects[0]);
1302 lua.pushRect(rects[1]);
1303 lua_pushstring(L, dir2string(dirs[0]));
1304 lua_pushstring(L, dir2string(dirs[0]));
1305 ret_count += 4;
1306 }
1307 return ret_count;
1308}
1309
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001310static int lpath_countPoints(lua_State* L) {
1311 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1312 return 1;
1313}
1314
reed@google.com74ce6f02013-05-22 15:13:18 +00001315static int lpath_reset(lua_State* L) {
1316 get_obj<SkPath>(L, 1)->reset();
1317 return 0;
1318}
1319
1320static int lpath_moveTo(lua_State* L) {
1321 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1322 return 0;
1323}
1324
1325static int lpath_lineTo(lua_State* L) {
1326 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1327 return 0;
1328}
1329
1330static int lpath_quadTo(lua_State* L) {
1331 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1332 lua2scalar(L, 4), lua2scalar(L, 5));
1333 return 0;
1334}
1335
1336static int lpath_cubicTo(lua_State* L) {
1337 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1338 lua2scalar(L, 4), lua2scalar(L, 5),
1339 lua2scalar(L, 6), lua2scalar(L, 7));
1340 return 0;
1341}
1342
1343static int lpath_close(lua_State* L) {
1344 get_obj<SkPath>(L, 1)->close();
1345 return 0;
1346}
1347
1348static int lpath_gc(lua_State* L) {
1349 get_obj<SkPath>(L, 1)->~SkPath();
1350 return 0;
1351}
1352
1353static const struct luaL_Reg gSkPath_Methods[] = {
1354 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001355 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001356 { "getSegmentTypes", lpath_getSegmentTypes },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001357 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001358 { "isEmpty", lpath_isEmpty },
1359 { "isRect", lpath_isRect },
1360 { "isNestedRects", lpath_isNestedRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001361 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001362 { "reset", lpath_reset },
1363 { "moveTo", lpath_moveTo },
1364 { "lineTo", lpath_lineTo },
1365 { "quadTo", lpath_quadTo },
1366 { "cubicTo", lpath_cubicTo },
1367 { "close", lpath_close },
1368 { "__gc", lpath_gc },
1369 { NULL, NULL }
1370};
1371
1372///////////////////////////////////////////////////////////////////////////////
1373
1374static const char* rrect_type(const SkRRect& rr) {
1375 switch (rr.getType()) {
1376 case SkRRect::kUnknown_Type: return "unknown";
1377 case SkRRect::kEmpty_Type: return "empty";
1378 case SkRRect::kRect_Type: return "rect";
1379 case SkRRect::kOval_Type: return "oval";
1380 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001381 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001382 case SkRRect::kComplex_Type: return "complex";
1383 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001384 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001385 return "";
1386}
1387
1388static int lrrect_rect(lua_State* L) {
1389 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1390 return 1;
1391}
1392
1393static int lrrect_type(lua_State* L) {
1394 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1395 return 1;
1396}
1397
1398static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001399 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001400 SkVector v;
1401 if (corner < 0 || corner > 3) {
1402 SkDebugf("bad corner index %d", corner);
1403 v.set(0, 0);
1404 } else {
1405 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1406 }
1407 lua_pushnumber(L, v.fX);
1408 lua_pushnumber(L, v.fY);
1409 return 2;
1410}
1411
1412static int lrrect_gc(lua_State* L) {
1413 get_obj<SkRRect>(L, 1)->~SkRRect();
1414 return 0;
1415}
1416
1417static const struct luaL_Reg gSkRRect_Methods[] = {
1418 { "rect", lrrect_rect },
1419 { "type", lrrect_type },
1420 { "radii", lrrect_radii },
1421 { "__gc", lrrect_gc },
1422 { NULL, NULL }
1423};
1424
1425///////////////////////////////////////////////////////////////////////////////
1426
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001427static int limage_width(lua_State* L) {
1428 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1429 return 1;
1430}
1431
1432static int limage_height(lua_State* L) {
1433 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1434 return 1;
1435}
1436
1437static int limage_gc(lua_State* L) {
1438 get_ref<SkImage>(L, 1)->unref();
1439 return 0;
1440}
1441
1442static const struct luaL_Reg gSkImage_Methods[] = {
1443 { "width", limage_width },
1444 { "height", limage_height },
1445 { "__gc", limage_gc },
1446 { NULL, NULL }
1447};
1448
1449///////////////////////////////////////////////////////////////////////////////
1450
reed485557f2014-10-12 10:36:47 -07001451static int lsurface_width(lua_State* L) {
1452 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1453 return 1;
1454}
1455
1456static int lsurface_height(lua_State* L) {
1457 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1458 return 1;
1459}
1460
1461static int lsurface_getCanvas(lua_State* L) {
1462 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
1463 if (NULL == canvas) {
1464 lua_pushnil(L);
1465 } else {
1466 push_ref(L, canvas);
1467 // note: we don't unref canvas, since getCanvas did not ref it.
1468 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1469 // the real owner (the surface) go away, but still hold onto the canvas?
1470 // *really* we want to sort of ref the surface again, but have the native object
1471 // know that it is supposed to be treated as a canvas...
1472 }
1473 return 1;
1474}
1475
1476static int lsurface_newImageSnapshot(lua_State* L) {
1477 SkImage* image = get_ref<SkSurface>(L, 1)->newImageSnapshot();
1478 if (NULL == image) {
1479 lua_pushnil(L);
1480 } else {
1481 push_ref(L, image);
1482 image->unref();
1483 }
1484 return 1;
1485}
1486
1487static int lsurface_newSurface(lua_State* L) {
1488 int width = lua2int_def(L, 2, 0);
reed96affcd2014-10-13 12:38:04 -07001489 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -07001490 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1491 SkSurface* surface = get_ref<SkSurface>(L, 1)->newSurface(info);
1492 if (NULL == surface) {
1493 lua_pushnil(L);
1494 } else {
1495 push_ref(L, surface);
1496 surface->unref();
1497 }
1498 return 1;
1499}
1500
1501static int lsurface_gc(lua_State* L) {
1502 get_ref<SkSurface>(L, 1)->unref();
1503 return 0;
1504}
1505
1506static const struct luaL_Reg gSkSurface_Methods[] = {
1507 { "width", lsurface_width },
1508 { "height", lsurface_height },
1509 { "getCanvas", lsurface_getCanvas },
1510 { "newImageSnapshot", lsurface_newImageSnapshot },
1511 { "newSurface", lsurface_newSurface },
1512 { "__gc", lsurface_gc },
1513 { NULL, NULL }
1514};
1515
1516///////////////////////////////////////////////////////////////////////////////
1517
reed96affcd2014-10-13 12:38:04 -07001518static int lpicturerecorder_beginRecording(lua_State* L) {
1519 const SkScalar w = lua2scalar_def(L, 2, -1);
1520 const SkScalar h = lua2scalar_def(L, 3, -1);
1521 if (w <= 0 || h <= 0) {
1522 lua_pushnil(L);
1523 return 1;
1524 }
1525
1526 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
1527 if (NULL == canvas) {
1528 lua_pushnil(L);
1529 return 1;
1530 }
1531
1532 push_ref(L, canvas);
1533 return 1;
1534}
1535
1536static int lpicturerecorder_getCanvas(lua_State* L) {
1537 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
1538 if (NULL == canvas) {
1539 lua_pushnil(L);
1540 return 1;
1541 }
1542 push_ref(L, canvas);
1543 return 1;
1544}
1545
1546static int lpicturerecorder_endRecording(lua_State* L) {
1547 SkPicture* pic = get_obj<SkPictureRecorder>(L, 1)->endRecording();
1548 if (NULL == pic) {
1549 lua_pushnil(L);
1550 return 1;
1551 }
1552 push_ref(L, pic);
1553 pic->unref(); // lua is the only owner, so we unref ours
1554 return 1;
1555}
1556
1557static int lpicturerecorder_gc(lua_State* L) {
1558 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1559 return 0;
1560}
1561
1562static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1563 { "beginRecording", lpicturerecorder_beginRecording },
1564 { "getCanvas", lpicturerecorder_getCanvas },
1565 { "endRecording", lpicturerecorder_endRecording },
1566 { "__gc", lpicturerecorder_gc },
1567 { NULL, NULL }
1568};
1569
1570///////////////////////////////////////////////////////////////////////////////
1571
1572static int lpicture_width(lua_State* L) {
1573 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1574 return 1;
1575}
1576
1577static int lpicture_height(lua_State* L) {
1578 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1579 return 1;
1580}
1581
1582static int lpicture_gc(lua_State* L) {
1583 get_ref<SkPicture>(L, 1)->unref();
1584 return 0;
1585}
1586
1587static const struct luaL_Reg gSkPicture_Methods[] = {
1588 { "width", lpicture_width },
1589 { "height", lpicture_height },
1590 { "__gc", lpicture_gc },
1591 { NULL, NULL }
1592};
1593
1594///////////////////////////////////////////////////////////////////////////////
1595
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001596static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001597 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001598 return 0;
1599}
1600
1601static const struct luaL_Reg gSkTypeface_Methods[] = {
1602 { "__gc", ltypeface_gc },
1603 { NULL, NULL }
1604};
1605
1606///////////////////////////////////////////////////////////////////////////////
1607
reed@google.com74ce6f02013-05-22 15:13:18 +00001608class AutoCallLua {
1609public:
1610 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1611 lua_getglobal(L, func);
1612 if (!lua_isfunction(L, -1)) {
1613 int t = lua_type(L, -1);
1614 SkDebugf("--- expected function %d\n", t);
1615 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001616
reed@google.com74ce6f02013-05-22 15:13:18 +00001617 lua_newtable(L);
1618 setfield_string(L, "verb", verb);
1619 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001620
reed@google.com74ce6f02013-05-22 15:13:18 +00001621 ~AutoCallLua() {
1622 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1623 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1624 }
1625 lua_settop(fL, -1);
1626 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001627
reed@google.com74ce6f02013-05-22 15:13:18 +00001628private:
1629 lua_State* fL;
1630};
1631
1632#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1633
1634///////////////////////////////////////////////////////////////////////////////
1635
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001636static int lsk_newDocumentPDF(lua_State* L) {
1637 const char* file = NULL;
1638 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1639 file = lua_tolstring(L, 1, NULL);
1640 }
1641
1642 SkDocument* doc = SkDocument::CreatePDF(file);
1643 if (NULL == doc) {
1644 // do I need to push a nil on the stack and return 1?
1645 return 0;
1646 } else {
1647 push_ref(L, doc);
1648 doc->unref();
1649 return 1;
1650 }
1651}
1652
reed@google.com3597b732013-05-22 20:12:50 +00001653static int lsk_newPaint(lua_State* L) {
1654 push_new<SkPaint>(L);
1655 return 1;
1656}
1657
1658static int lsk_newPath(lua_State* L) {
1659 push_new<SkPath>(L);
1660 return 1;
1661}
1662
reed96affcd2014-10-13 12:38:04 -07001663static int lsk_newPictureRecorder(lua_State* L) {
1664 push_new<SkPictureRecorder>(L);
1665 return 1;
1666}
1667
reed@google.com3597b732013-05-22 20:12:50 +00001668static int lsk_newRRect(lua_State* L) {
1669 SkRRect* rr = push_new<SkRRect>(L);
1670 rr->setEmpty();
1671 return 1;
1672}
1673
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001674static int lsk_newTypeface(lua_State* L) {
1675 const char* name = NULL;
1676 int style = SkTypeface::kNormal;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00001677
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001678 int count = lua_gettop(L);
1679 if (count > 0 && lua_isstring(L, 1)) {
1680 name = lua_tolstring(L, 1, NULL);
1681 if (count > 1 && lua_isnumber(L, 2)) {
1682 style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic;
1683 }
1684 }
1685
1686 SkTypeface* face = SkTypeface::CreateFromName(name,
1687 (SkTypeface::Style)style);
1688// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
1689 if (NULL == face) {
1690 face = SkTypeface::RefDefault();
1691 }
1692 push_ref(L, face);
1693 face->unref();
1694 return 1;
1695}
reed@google.com3597b732013-05-22 20:12:50 +00001696
reed485557f2014-10-12 10:36:47 -07001697static int lsk_newRasterSurface(lua_State* L) {
1698 int width = lua2int_def(L, 2, 0);
1699 int height = lua2int_def(L, 2, 0);
1700 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1701 SkSurface* surface = SkSurface::NewRaster(info);
1702 if (NULL == surface) {
1703 lua_pushnil(L);
1704 } else {
1705 push_ref(L, surface);
1706 surface->unref();
1707 }
1708 return 1;
1709}
1710
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001711static int lsk_loadImage(lua_State* L) {
1712 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1713 const char* name = lua_tolstring(L, 1, NULL);
1714 SkAutoDataUnref data(SkData::NewFromFileName(name));
1715 if (data.get()) {
piotaixr4bcc2022014-09-17 14:33:30 -07001716 SkImage* image = SkImage::NewFromGenerator(
1717 SkDecodingImageGenerator::Create(data, SkDecodingImageGenerator::Options()));
1718
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001719 if (image) {
1720 push_ref(L, image);
1721 image->unref();
1722 return 1;
1723 }
1724 }
1725 }
1726 return 0;
1727}
1728
reed@google.com3597b732013-05-22 20:12:50 +00001729static void register_Sk(lua_State* L) {
1730 lua_newtable(L);
1731 lua_pushvalue(L, -1);
1732 lua_setglobal(L, "Sk");
1733 // the Sk table is still on top
1734
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001735 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001736 setfield_function(L, "loadImage", lsk_loadImage);
reed@google.com3597b732013-05-22 20:12:50 +00001737 setfield_function(L, "newPaint", lsk_newPaint);
1738 setfield_function(L, "newPath", lsk_newPath);
reed96affcd2014-10-13 12:38:04 -07001739 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
reed@google.com3597b732013-05-22 20:12:50 +00001740 setfield_function(L, "newRRect", lsk_newRRect);
reed485557f2014-10-12 10:36:47 -07001741 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001742 setfield_function(L, "newTypeface", lsk_newTypeface);
reed@google.com3597b732013-05-22 20:12:50 +00001743 lua_pop(L, 1); // pop off the Sk table
1744}
1745
reed@google.com74ce6f02013-05-22 15:13:18 +00001746#define REG_CLASS(L, C) \
1747 do { \
reed@google.com3597b732013-05-22 20:12:50 +00001748 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00001749 lua_pushvalue(L, -1); \
1750 lua_setfield(L, -2, "__index"); \
1751 luaL_setfuncs(L, g##C##_Methods, 0); \
1752 lua_pop(L, 1); /* pop off the meta-table */ \
1753 } while (0)
1754
1755void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00001756 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00001757 REG_CLASS(L, SkCanvas);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001758 REG_CLASS(L, SkDocument);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001759 REG_CLASS(L, SkImage);
reed@google.com74ce6f02013-05-22 15:13:18 +00001760 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001761 REG_CLASS(L, SkPath);
1762 REG_CLASS(L, SkPathEffect);
reed96affcd2014-10-13 12:38:04 -07001763 REG_CLASS(L, SkPicture);
1764 REG_CLASS(L, SkPictureRecorder);
reed@google.com74ce6f02013-05-22 15:13:18 +00001765 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00001766 REG_CLASS(L, SkShader);
reed485557f2014-10-12 10:36:47 -07001767 REG_CLASS(L, SkSurface);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001768 REG_CLASS(L, SkTypeface);
humper@google.com2815c192013-07-10 22:42:30 +00001769 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00001770}
zachr@google.com28c27c82013-06-20 17:15:05 +00001771
reed@google.com7bce9982013-06-20 17:40:21 +00001772extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00001773extern "C" int luaopen_skia(lua_State* L) {
1774 SkLua::Load(L);
1775 return 0;
1776}