blob: dd79a34b909a8328cb81f105151a2889805221cd [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
reedbdc49ae2014-10-14 09:34:52 -0700630static int lcanvas_concat(lua_State* L) {
631 get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2));
632 return 0;
633}
634
reed485557f2014-10-12 10:36:47 -0700635static int lcanvas_newSurface(lua_State* L) {
636 int width = lua2int_def(L, 2, 0);
637 int height = lua2int_def(L, 2, 0);
638 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
639 SkSurface* surface = get_ref<SkCanvas>(L, 1)->newSurface(info);
640 if (NULL == surface) {
641 lua_pushnil(L);
642 } else {
643 push_ref(L, surface);
644 surface->unref();
645 }
646 return 1;
647}
648
reed@google.com74ce6f02013-05-22 15:13:18 +0000649static int lcanvas_gc(lua_State* L) {
650 get_ref<SkCanvas>(L, 1)->unref();
651 return 0;
652}
653
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000654const struct luaL_Reg gSkCanvas_Methods[] = {
reedf355df52014-10-12 12:18:40 -0700655 { "clear", lcanvas_clear },
reed@google.com74ce6f02013-05-22 15:13:18 +0000656 { "drawColor", lcanvas_drawColor },
657 { "drawRect", lcanvas_drawRect },
658 { "drawOval", lcanvas_drawOval },
659 { "drawCircle", lcanvas_drawCircle },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000660 { "drawImage", lcanvas_drawImage },
reedba5fb932014-10-10 15:28:19 -0700661 { "drawImageRect", lcanvas_drawImageRect },
reed@google.comfd345872013-05-22 20:53:42 +0000662 { "drawPath", lcanvas_drawPath },
reed96affcd2014-10-13 12:38:04 -0700663 { "drawPicture", lcanvas_drawPicture },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000664 { "drawText", lcanvas_drawText },
reed@google.com74ce6f02013-05-22 15:13:18 +0000665 { "getSaveCount", lcanvas_getSaveCount },
666 { "getTotalMatrix", lcanvas_getTotalMatrix },
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000667 { "getClipStack", lcanvas_getClipStack },
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000668#if SK_SUPPORT_GPU
669 { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
670#endif
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000671 { "save", lcanvas_save },
672 { "restore", lcanvas_restore },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000673 { "scale", lcanvas_scale },
reed@google.com3597b732013-05-22 20:12:50 +0000674 { "translate", lcanvas_translate },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000675 { "rotate", lcanvas_rotate },
reedbdc49ae2014-10-14 09:34:52 -0700676 { "concat", lcanvas_concat },
reed485557f2014-10-12 10:36:47 -0700677
678 { "newSurface", lcanvas_newSurface },
679
reed@google.com74ce6f02013-05-22 15:13:18 +0000680 { "__gc", lcanvas_gc },
681 { NULL, NULL }
682};
683
684///////////////////////////////////////////////////////////////////////////////
685
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000686static int ldocument_beginPage(lua_State* L) {
687 const SkRect* contentPtr = NULL;
688 push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2),
689 lua2scalar(L, 3),
690 contentPtr));
691 return 1;
692}
693
694static int ldocument_endPage(lua_State* L) {
695 get_ref<SkDocument>(L, 1)->endPage();
696 return 0;
697}
698
699static int ldocument_close(lua_State* L) {
700 get_ref<SkDocument>(L, 1)->close();
701 return 0;
702}
703
704static int ldocument_gc(lua_State* L) {
705 get_ref<SkDocument>(L, 1)->unref();
706 return 0;
707}
708
709static const struct luaL_Reg gSkDocument_Methods[] = {
710 { "beginPage", ldocument_beginPage },
711 { "endPage", ldocument_endPage },
712 { "close", ldocument_close },
713 { "__gc", ldocument_gc },
714 { NULL, NULL }
715};
716
717///////////////////////////////////////////////////////////////////////////////
718
reed@google.com74ce6f02013-05-22 15:13:18 +0000719static int lpaint_isAntiAlias(lua_State* L) {
720 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
721 return 1;
722}
723
724static int lpaint_setAntiAlias(lua_State* L) {
reed@google.com88c9ec92013-05-22 15:43:21 +0000725 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +0000726 return 0;
727}
728
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000729static int lpaint_isDither(lua_State* L) {
730 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
731 return 1;
732}
733
734static int lpaint_isUnderlineText(lua_State* L) {
735 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText());
736 return 1;
737}
738
739static int lpaint_isStrikeThruText(lua_State* L) {
740 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText());
741 return 1;
742}
743
744static int lpaint_isFakeBoldText(lua_State* L) {
745 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
746 return 1;
747}
748
749static int lpaint_isLinearText(lua_State* L) {
750 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
751 return 1;
752}
753
754static int lpaint_isSubpixelText(lua_State* L) {
755 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
756 return 1;
757}
758
reed09a1d672014-10-11 13:13:11 -0700759static int lpaint_setSubpixelText(lua_State* L) {
760 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
761 return 1;
762}
763
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000764static int lpaint_isDevKernText(lua_State* L) {
765 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
766 return 1;
767}
768
769static int lpaint_isLCDRenderText(lua_State* L) {
770 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
771 return 1;
772}
773
774static int lpaint_isEmbeddedBitmapText(lua_State* L) {
775 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
776 return 1;
777}
778
779static int lpaint_isAutohinted(lua_State* L) {
780 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
781 return 1;
782}
783
784static int lpaint_isVerticalText(lua_State* L) {
785 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
786 return 1;
787}
788
reed@google.com74ce6f02013-05-22 15:13:18 +0000789static int lpaint_getColor(lua_State* L) {
790 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
791 return 1;
792}
793
794static int lpaint_setColor(lua_State* L) {
795 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
796 return 0;
797}
798
reed@google.come3823fd2013-05-30 18:55:14 +0000799static int lpaint_getTextSize(lua_State* L) {
800 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
801 return 1;
802}
803
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000804static int lpaint_getTextScaleX(lua_State* L) {
805 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
806 return 1;
807}
808
809static int lpaint_getTextSkewX(lua_State* L) {
810 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
811 return 1;
812}
813
reed@google.come3823fd2013-05-30 18:55:14 +0000814static int lpaint_setTextSize(lua_State* L) {
815 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
816 return 0;
817}
818
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000819static int lpaint_getTypeface(lua_State* L) {
820 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
821 return 1;
822}
823
824static int lpaint_setTypeface(lua_State* L) {
825 get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2));
826 return 0;
827}
828
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000829static int lpaint_getHinting(lua_State* L) {
830 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
831 return 1;
832}
833
reed@google.come3823fd2013-05-30 18:55:14 +0000834static int lpaint_getFontID(lua_State* L) {
835 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
836 SkLua(L).pushU32(SkTypeface::UniqueID(face));
837 return 1;
838}
839
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000840static const struct {
841 const char* fLabel;
842 SkPaint::Align fAlign;
843} gAlignRec[] = {
844 { "left", SkPaint::kLeft_Align },
845 { "center", SkPaint::kCenter_Align },
846 { "right", SkPaint::kRight_Align },
847};
848
849static int lpaint_getTextAlign(lua_State* L) {
850 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
851 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
852 if (gAlignRec[i].fAlign == align) {
853 lua_pushstring(L, gAlignRec[i].fLabel);
854 return 1;
855 }
856 }
857 return 0;
858}
859
860static int lpaint_setTextAlign(lua_State* L) {
861 if (lua_isstring(L, 2)) {
862 size_t len;
863 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000864
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000865 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
866 if (!strcmp(gAlignRec[i].fLabel, label)) {
867 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
868 break;
869 }
870 }
871 }
872 return 0;
873}
874
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000875static int lpaint_getStroke(lua_State* L) {
876 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
877 return 1;
878}
879
880static int lpaint_setStroke(lua_State* L) {
881 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000882
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000883 if (lua_toboolean(L, 2)) {
884 style = SkPaint::kStroke_Style;
885 } else {
886 style = SkPaint::kFill_Style;
887 }
888 get_obj<SkPaint>(L, 1)->setStyle(style);
889 return 0;
890}
891
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000892static int lpaint_getStrokeCap(lua_State* L) {
893 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
894 return 1;
895}
896
897static int lpaint_getStrokeJoin(lua_State* L) {
898 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
899 return 1;
900}
901
902static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +0000903 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000904 return 1;
905}
906
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000907static int lpaint_getStrokeWidth(lua_State* L) {
908 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
909 return 1;
910}
911
912static int lpaint_setStrokeWidth(lua_State* L) {
913 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
914 return 0;
915}
916
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000917static int lpaint_getStrokeMiter(lua_State* L) {
918 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
919 return 1;
920}
921
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000922static int lpaint_measureText(lua_State* L) {
923 if (lua_isstring(L, 2)) {
924 size_t len;
925 const char* text = lua_tolstring(L, 2, &len);
926 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
927 return 1;
928 }
929 return 0;
930}
931
932struct FontMetrics {
933 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
934 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
935 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
936 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
937 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
938 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
939 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
940 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
941 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
942};
943
944static int lpaint_getFontMetrics(lua_State* L) {
945 SkPaint::FontMetrics fm;
946 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000947
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000948 lua_newtable(L);
949 setfield_scalar(L, "top", fm.fTop);
950 setfield_scalar(L, "ascent", fm.fAscent);
951 setfield_scalar(L, "descent", fm.fDescent);
952 setfield_scalar(L, "bottom", fm.fBottom);
953 setfield_scalar(L, "leading", fm.fLeading);
954 SkLua(L).pushScalar(height);
955 return 2;
956}
957
reed@google.com29563872013-07-10 21:23:49 +0000958static int lpaint_getEffects(lua_State* L) {
959 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000960
reed@google.com29563872013-07-10 21:23:49 +0000961 lua_newtable(L);
962 setfield_bool_if(L, "looper", !!paint->getLooper());
963 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
964 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer());
965 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
966 setfield_bool_if(L, "shader", !!paint->getShader());
967 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
968 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
969 setfield_bool_if(L, "xfermode", !!paint->getXfermode());
970 return 1;
971}
972
reed@google.com5fdc9832013-07-24 15:47:52 +0000973static int lpaint_getShader(lua_State* L) {
974 const SkPaint* paint = get_obj<SkPaint>(L, 1);
975 SkShader* shader = paint->getShader();
976 if (shader) {
977 push_ref(L, shader);
978 return 1;
979 }
980 return 0;
981}
982
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000983static int lpaint_getPathEffect(lua_State* L) {
984 const SkPaint* paint = get_obj<SkPaint>(L, 1);
985 SkPathEffect* pe = paint->getPathEffect();
986 if (pe) {
987 push_ref(L, pe);
988 return 1;
989 }
990 return 0;
991}
992
reed@google.com74ce6f02013-05-22 15:13:18 +0000993static int lpaint_gc(lua_State* L) {
994 get_obj<SkPaint>(L, 1)->~SkPaint();
995 return 0;
996}
997
998static const struct luaL_Reg gSkPaint_Methods[] = {
999 { "isAntiAlias", lpaint_isAntiAlias },
1000 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001001 { "isDither", lpaint_isDither },
1002 { "isUnderlineText", lpaint_isUnderlineText },
1003 { "isStrikeThruText", lpaint_isStrikeThruText },
1004 { "isFakeBoldText", lpaint_isFakeBoldText },
1005 { "isLinearText", lpaint_isLinearText },
1006 { "isSubpixelText", lpaint_isSubpixelText },
reed09a1d672014-10-11 13:13:11 -07001007 { "setSubpixelText", lpaint_setSubpixelText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001008 { "isDevKernText", lpaint_isDevKernText },
1009 { "isLCDRenderText", lpaint_isLCDRenderText },
1010 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
1011 { "isAutohinted", lpaint_isAutohinted },
1012 { "isVerticalText", lpaint_isVerticalText },
reed@google.com74ce6f02013-05-22 15:13:18 +00001013 { "getColor", lpaint_getColor },
1014 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +00001015 { "getTextSize", lpaint_getTextSize },
1016 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001017 { "getTextScaleX", lpaint_getTextScaleX },
1018 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001019 { "getTypeface", lpaint_getTypeface },
1020 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001021 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +00001022 { "getFontID", lpaint_getFontID },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001023 { "getTextAlign", lpaint_getTextAlign },
1024 { "setTextAlign", lpaint_setTextAlign },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001025 { "getStroke", lpaint_getStroke },
1026 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001027 { "getStrokeCap", lpaint_getStrokeCap },
1028 { "getStrokeJoin", lpaint_getStrokeJoin },
1029 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001030 { "getStrokeWidth", lpaint_getStrokeWidth },
1031 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001032 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001033 { "measureText", lpaint_measureText },
1034 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +00001035 { "getEffects", lpaint_getEffects },
reed@google.com5fdc9832013-07-24 15:47:52 +00001036 { "getShader", lpaint_getShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001037 { "getPathEffect", lpaint_getPathEffect },
reed@google.com74ce6f02013-05-22 15:13:18 +00001038 { "__gc", lpaint_gc },
1039 { NULL, NULL }
1040};
1041
1042///////////////////////////////////////////////////////////////////////////////
1043
reed@google.com5fdc9832013-07-24 15:47:52 +00001044static const char* mode2string(SkShader::TileMode mode) {
1045 static const char* gNames[] = { "clamp", "repeat", "mirror" };
1046 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
1047 return gNames[mode];
1048}
1049
1050static const char* gradtype2string(SkShader::GradientType t) {
1051 static const char* gNames[] = {
1052 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
1053 };
1054 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
1055 return gNames[t];
1056}
1057
1058static int lshader_isOpaque(lua_State* L) {
1059 SkShader* shader = get_ref<SkShader>(L, 1);
1060 return shader && shader->isOpaque();
1061}
1062
1063static int lshader_asABitmap(lua_State* L) {
1064 SkShader* shader = get_ref<SkShader>(L, 1);
1065 if (shader) {
1066 SkBitmap bm;
1067 SkMatrix matrix;
1068 SkShader::TileMode modes[2];
1069 switch (shader->asABitmap(&bm, &matrix, modes)) {
1070 case SkShader::kDefault_BitmapType:
1071 lua_newtable(L);
1072 setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0);
1073 setfield_number(L, "width", bm.width());
1074 setfield_number(L, "height", bm.height());
1075 setfield_string(L, "tileX", mode2string(modes[0]));
1076 setfield_string(L, "tileY", mode2string(modes[1]));
1077 return 1;
1078 default:
1079 break;
1080 }
1081 }
1082 return 0;
1083}
1084
1085static int lshader_asAGradient(lua_State* L) {
1086 SkShader* shader = get_ref<SkShader>(L, 1);
1087 if (shader) {
1088 SkShader::GradientInfo info;
1089 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001090
1091 SkColor colors[3]; // hacked in for extracting info on 3 color case.
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001092 SkScalar pos[3];
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001093
1094 info.fColorCount = 3;
1095 info.fColors = &colors[0];
1096 info.fColorOffsets = &pos[0];
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001097
reed@google.com5fdc9832013-07-24 15:47:52 +00001098 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001099
reed@google.com5fdc9832013-07-24 15:47:52 +00001100 if (SkShader::kNone_GradientType != t) {
1101 lua_newtable(L);
1102 setfield_string(L, "type", gradtype2string(t));
1103 setfield_number(L, "colorCount", info.fColorCount);
1104 setfield_string(L, "tile", mode2string(info.fTileMode));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001105
1106 if (info.fColorCount == 3){
1107 setfield_number(L, "midPos", pos[1]);
1108 }
skia.committer@gmail.combd74add2013-08-02 07:00:59 +00001109
reed@google.com5fdc9832013-07-24 15:47:52 +00001110 return 1;
1111 }
1112 }
1113 return 0;
1114}
1115
1116static int lshader_gc(lua_State* L) {
1117 get_ref<SkShader>(L, 1)->unref();
1118 return 0;
1119}
1120
1121static const struct luaL_Reg gSkShader_Methods[] = {
1122 { "isOpaque", lshader_isOpaque },
1123 { "asABitmap", lshader_asABitmap },
1124 { "asAGradient", lshader_asAGradient },
1125 { "__gc", lshader_gc },
1126 { NULL, NULL }
1127};
1128
1129///////////////////////////////////////////////////////////////////////////////
1130
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001131static int lpatheffect_asADash(lua_State* L) {
1132 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1133 if (pe) {
1134 SkPathEffect::DashInfo info;
1135 SkPathEffect::DashType dashType = pe->asADash(&info);
1136 if (SkPathEffect::kDash_DashType == dashType) {
1137 SkAutoTArray<SkScalar> intervals(info.fCount);
1138 info.fIntervals = intervals.get();
1139 pe->asADash(&info);
1140 SkLua(L).pushDash(info);
1141 return 1;
1142 }
1143 }
1144 return 0;
1145}
1146
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001147static int lpatheffect_gc(lua_State* L) {
1148 get_ref<SkPathEffect>(L, 1)->unref();
1149 return 0;
1150}
1151
1152static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001153 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001154 { "__gc", lpatheffect_gc },
1155 { NULL, NULL }
1156};
1157
1158///////////////////////////////////////////////////////////////////////////////
1159
humper@google.com2815c192013-07-10 22:42:30 +00001160static int lmatrix_getType(lua_State* L) {
1161 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001162
humper@google.com2815c192013-07-10 22:42:30 +00001163 lua_newtable(L);
1164 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1165 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1166 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1167 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1168 return 1;
1169}
1170
humper@google.com0f48ee02013-07-26 15:23:43 +00001171static int lmatrix_getScaleX(lua_State* L) {
1172 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1173 return 1;
1174}
1175
1176static int lmatrix_getScaleY(lua_State* L) {
1177 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1178 return 1;
1179}
1180
1181static int lmatrix_getTranslateX(lua_State* L) {
1182 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1183 return 1;
1184}
1185
1186static int lmatrix_getTranslateY(lua_State* L) {
1187 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1188 return 1;
1189}
1190
reedbdc49ae2014-10-14 09:34:52 -07001191static int lmatrix_setRectToRect(lua_State* L) {
1192 SkMatrix* matrix = get_obj<SkMatrix>(L, 1);
1193 SkRect srcR, dstR;
1194 lua2rect(L, 2, &srcR);
1195 lua2rect(L, 3, &dstR);
1196 const char* scaleToFitStr = lua_tostring(L, 4);
1197 SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit;
1198
1199 if (scaleToFitStr) {
1200 const struct {
1201 const char* fName;
1202 SkMatrix::ScaleToFit fScaleToFit;
1203 } rec[] = {
1204 { "fill", SkMatrix::kFill_ScaleToFit },
1205 { "start", SkMatrix::kStart_ScaleToFit },
1206 { "center", SkMatrix::kCenter_ScaleToFit },
1207 { "end", SkMatrix::kEnd_ScaleToFit },
1208 };
1209
1210 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
1211 if (strcmp(rec[i].fName, scaleToFitStr) == 0) {
1212 scaleToFit = rec[i].fScaleToFit;
1213 break;
1214 }
1215 }
1216 }
1217
1218 matrix->setRectToRect(srcR, dstR, scaleToFit);
1219 return 0;
1220}
1221
humper@google.com2815c192013-07-10 22:42:30 +00001222static const struct luaL_Reg gSkMatrix_Methods[] = {
1223 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001224 { "getScaleX", lmatrix_getScaleX },
1225 { "getScaleY", lmatrix_getScaleY },
1226 { "getTranslateX", lmatrix_getTranslateX },
1227 { "getTranslateY", lmatrix_getTranslateY },
reedbdc49ae2014-10-14 09:34:52 -07001228 { "setRectToRect", lmatrix_setRectToRect },
humper@google.com2815c192013-07-10 22:42:30 +00001229 { NULL, NULL }
1230};
1231
1232///////////////////////////////////////////////////////////////////////////////
1233
reed@google.com74ce6f02013-05-22 15:13:18 +00001234static int lpath_getBounds(lua_State* L) {
1235 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1236 return 1;
1237}
1238
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001239static const char* fill_type_to_str(SkPath::FillType fill) {
1240 switch (fill) {
1241 case SkPath::kEvenOdd_FillType:
1242 return "even-odd";
1243 case SkPath::kWinding_FillType:
1244 return "winding";
1245 case SkPath::kInverseEvenOdd_FillType:
1246 return "inverse-even-odd";
1247 case SkPath::kInverseWinding_FillType:
1248 return "inverse-winding";
1249 }
1250 return "unknown";
1251}
1252
1253static int lpath_getFillType(lua_State* L) {
1254 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1255 SkLua(L).pushString(fill_type_to_str(fill));
1256 return 1;
1257}
1258
1259static SkString segment_masks_to_str(uint32_t segmentMasks) {
1260 SkString result;
1261 bool first = true;
1262 if (SkPath::kLine_SegmentMask & segmentMasks) {
1263 result.append("line");
1264 first = false;
1265 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1266 }
1267 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1268 if (!first) {
1269 result.append(" ");
1270 }
1271 result.append("quad");
1272 first = false;
1273 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1274 }
1275 if (SkPath::kConic_SegmentMask & segmentMasks) {
1276 if (!first) {
1277 result.append(" ");
1278 }
1279 result.append("conic");
1280 first = false;
1281 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1282 }
1283 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1284 if (!first) {
1285 result.append(" ");
1286 }
1287 result.append("cubic");
1288 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1289 }
1290 SkASSERT(0 == segmentMasks);
1291 return result;
1292}
1293
krajcevski95498ed2014-08-18 08:02:33 -07001294static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001295 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1296 SkLua(L).pushString(segment_masks_to_str(segMasks));
1297 return 1;
1298}
1299
1300static int lpath_isConvex(lua_State* L) {
1301 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1302 SkLua(L).pushBool(isConvex);
1303 return 1;
1304}
1305
reed@google.com74ce6f02013-05-22 15:13:18 +00001306static int lpath_isEmpty(lua_State* L) {
1307 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1308 return 1;
1309}
1310
1311static int lpath_isRect(lua_State* L) {
1312 SkRect r;
1313 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1314 int ret_count = 1;
1315 lua_pushboolean(L, pred);
1316 if (pred) {
1317 SkLua(L).pushRect(r);
1318 ret_count += 1;
1319 }
1320 return ret_count;
1321}
1322
1323static const char* dir2string(SkPath::Direction dir) {
1324 static const char* gStr[] = {
1325 "unknown", "cw", "ccw"
1326 };
1327 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1328 return gStr[dir];
1329}
1330
1331static int lpath_isNestedRects(lua_State* L) {
1332 SkRect rects[2];
1333 SkPath::Direction dirs[2];
1334 bool pred = get_obj<SkPath>(L, 1)->isNestedRects(rects, dirs);
1335 int ret_count = 1;
1336 lua_pushboolean(L, pred);
1337 if (pred) {
1338 SkLua lua(L);
1339 lua.pushRect(rects[0]);
1340 lua.pushRect(rects[1]);
1341 lua_pushstring(L, dir2string(dirs[0]));
1342 lua_pushstring(L, dir2string(dirs[0]));
1343 ret_count += 4;
1344 }
1345 return ret_count;
1346}
1347
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001348static int lpath_countPoints(lua_State* L) {
1349 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1350 return 1;
1351}
1352
reed@google.com74ce6f02013-05-22 15:13:18 +00001353static int lpath_reset(lua_State* L) {
1354 get_obj<SkPath>(L, 1)->reset();
1355 return 0;
1356}
1357
1358static int lpath_moveTo(lua_State* L) {
1359 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1360 return 0;
1361}
1362
1363static int lpath_lineTo(lua_State* L) {
1364 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1365 return 0;
1366}
1367
1368static int lpath_quadTo(lua_State* L) {
1369 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1370 lua2scalar(L, 4), lua2scalar(L, 5));
1371 return 0;
1372}
1373
1374static int lpath_cubicTo(lua_State* L) {
1375 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1376 lua2scalar(L, 4), lua2scalar(L, 5),
1377 lua2scalar(L, 6), lua2scalar(L, 7));
1378 return 0;
1379}
1380
1381static int lpath_close(lua_State* L) {
1382 get_obj<SkPath>(L, 1)->close();
1383 return 0;
1384}
1385
1386static int lpath_gc(lua_State* L) {
1387 get_obj<SkPath>(L, 1)->~SkPath();
1388 return 0;
1389}
1390
1391static const struct luaL_Reg gSkPath_Methods[] = {
1392 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001393 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001394 { "getSegmentTypes", lpath_getSegmentTypes },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001395 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001396 { "isEmpty", lpath_isEmpty },
1397 { "isRect", lpath_isRect },
1398 { "isNestedRects", lpath_isNestedRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001399 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001400 { "reset", lpath_reset },
1401 { "moveTo", lpath_moveTo },
1402 { "lineTo", lpath_lineTo },
1403 { "quadTo", lpath_quadTo },
1404 { "cubicTo", lpath_cubicTo },
1405 { "close", lpath_close },
1406 { "__gc", lpath_gc },
1407 { NULL, NULL }
1408};
1409
1410///////////////////////////////////////////////////////////////////////////////
1411
1412static const char* rrect_type(const SkRRect& rr) {
1413 switch (rr.getType()) {
1414 case SkRRect::kUnknown_Type: return "unknown";
1415 case SkRRect::kEmpty_Type: return "empty";
1416 case SkRRect::kRect_Type: return "rect";
1417 case SkRRect::kOval_Type: return "oval";
1418 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001419 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001420 case SkRRect::kComplex_Type: return "complex";
1421 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001422 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001423 return "";
1424}
1425
1426static int lrrect_rect(lua_State* L) {
1427 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1428 return 1;
1429}
1430
1431static int lrrect_type(lua_State* L) {
1432 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1433 return 1;
1434}
1435
1436static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001437 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001438 SkVector v;
1439 if (corner < 0 || corner > 3) {
1440 SkDebugf("bad corner index %d", corner);
1441 v.set(0, 0);
1442 } else {
1443 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1444 }
1445 lua_pushnumber(L, v.fX);
1446 lua_pushnumber(L, v.fY);
1447 return 2;
1448}
1449
1450static int lrrect_gc(lua_State* L) {
1451 get_obj<SkRRect>(L, 1)->~SkRRect();
1452 return 0;
1453}
1454
1455static const struct luaL_Reg gSkRRect_Methods[] = {
1456 { "rect", lrrect_rect },
1457 { "type", lrrect_type },
1458 { "radii", lrrect_radii },
1459 { "__gc", lrrect_gc },
1460 { NULL, NULL }
1461};
1462
1463///////////////////////////////////////////////////////////////////////////////
1464
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001465static int limage_width(lua_State* L) {
1466 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1467 return 1;
1468}
1469
1470static int limage_height(lua_State* L) {
1471 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1472 return 1;
1473}
1474
1475static int limage_gc(lua_State* L) {
1476 get_ref<SkImage>(L, 1)->unref();
1477 return 0;
1478}
1479
1480static const struct luaL_Reg gSkImage_Methods[] = {
1481 { "width", limage_width },
1482 { "height", limage_height },
1483 { "__gc", limage_gc },
1484 { NULL, NULL }
1485};
1486
1487///////////////////////////////////////////////////////////////////////////////
1488
reed485557f2014-10-12 10:36:47 -07001489static int lsurface_width(lua_State* L) {
1490 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1491 return 1;
1492}
1493
1494static int lsurface_height(lua_State* L) {
1495 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1496 return 1;
1497}
1498
1499static int lsurface_getCanvas(lua_State* L) {
1500 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
1501 if (NULL == canvas) {
1502 lua_pushnil(L);
1503 } else {
1504 push_ref(L, canvas);
1505 // note: we don't unref canvas, since getCanvas did not ref it.
1506 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1507 // the real owner (the surface) go away, but still hold onto the canvas?
1508 // *really* we want to sort of ref the surface again, but have the native object
1509 // know that it is supposed to be treated as a canvas...
1510 }
1511 return 1;
1512}
1513
1514static int lsurface_newImageSnapshot(lua_State* L) {
1515 SkImage* image = get_ref<SkSurface>(L, 1)->newImageSnapshot();
1516 if (NULL == image) {
1517 lua_pushnil(L);
1518 } else {
1519 push_ref(L, image);
1520 image->unref();
1521 }
1522 return 1;
1523}
1524
1525static int lsurface_newSurface(lua_State* L) {
1526 int width = lua2int_def(L, 2, 0);
reed96affcd2014-10-13 12:38:04 -07001527 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -07001528 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1529 SkSurface* surface = get_ref<SkSurface>(L, 1)->newSurface(info);
1530 if (NULL == surface) {
1531 lua_pushnil(L);
1532 } else {
1533 push_ref(L, surface);
1534 surface->unref();
1535 }
1536 return 1;
1537}
1538
1539static int lsurface_gc(lua_State* L) {
1540 get_ref<SkSurface>(L, 1)->unref();
1541 return 0;
1542}
1543
1544static const struct luaL_Reg gSkSurface_Methods[] = {
1545 { "width", lsurface_width },
1546 { "height", lsurface_height },
1547 { "getCanvas", lsurface_getCanvas },
1548 { "newImageSnapshot", lsurface_newImageSnapshot },
1549 { "newSurface", lsurface_newSurface },
1550 { "__gc", lsurface_gc },
1551 { NULL, NULL }
1552};
1553
1554///////////////////////////////////////////////////////////////////////////////
1555
reed96affcd2014-10-13 12:38:04 -07001556static int lpicturerecorder_beginRecording(lua_State* L) {
1557 const SkScalar w = lua2scalar_def(L, 2, -1);
1558 const SkScalar h = lua2scalar_def(L, 3, -1);
1559 if (w <= 0 || h <= 0) {
1560 lua_pushnil(L);
1561 return 1;
1562 }
1563
1564 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
1565 if (NULL == canvas) {
1566 lua_pushnil(L);
1567 return 1;
1568 }
1569
1570 push_ref(L, canvas);
1571 return 1;
1572}
1573
1574static int lpicturerecorder_getCanvas(lua_State* L) {
1575 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
1576 if (NULL == canvas) {
1577 lua_pushnil(L);
1578 return 1;
1579 }
1580 push_ref(L, canvas);
1581 return 1;
1582}
1583
1584static int lpicturerecorder_endRecording(lua_State* L) {
1585 SkPicture* pic = get_obj<SkPictureRecorder>(L, 1)->endRecording();
1586 if (NULL == pic) {
1587 lua_pushnil(L);
1588 return 1;
1589 }
1590 push_ref(L, pic);
1591 pic->unref(); // lua is the only owner, so we unref ours
1592 return 1;
1593}
1594
1595static int lpicturerecorder_gc(lua_State* L) {
1596 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1597 return 0;
1598}
1599
1600static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1601 { "beginRecording", lpicturerecorder_beginRecording },
1602 { "getCanvas", lpicturerecorder_getCanvas },
1603 { "endRecording", lpicturerecorder_endRecording },
1604 { "__gc", lpicturerecorder_gc },
1605 { NULL, NULL }
1606};
1607
1608///////////////////////////////////////////////////////////////////////////////
1609
1610static int lpicture_width(lua_State* L) {
1611 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1612 return 1;
1613}
1614
1615static int lpicture_height(lua_State* L) {
1616 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1617 return 1;
1618}
1619
1620static int lpicture_gc(lua_State* L) {
1621 get_ref<SkPicture>(L, 1)->unref();
1622 return 0;
1623}
1624
1625static const struct luaL_Reg gSkPicture_Methods[] = {
1626 { "width", lpicture_width },
1627 { "height", lpicture_height },
1628 { "__gc", lpicture_gc },
1629 { NULL, NULL }
1630};
1631
1632///////////////////////////////////////////////////////////////////////////////
1633
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001634static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001635 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001636 return 0;
1637}
1638
1639static const struct luaL_Reg gSkTypeface_Methods[] = {
1640 { "__gc", ltypeface_gc },
1641 { NULL, NULL }
1642};
1643
1644///////////////////////////////////////////////////////////////////////////////
1645
reed@google.com74ce6f02013-05-22 15:13:18 +00001646class AutoCallLua {
1647public:
1648 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1649 lua_getglobal(L, func);
1650 if (!lua_isfunction(L, -1)) {
1651 int t = lua_type(L, -1);
1652 SkDebugf("--- expected function %d\n", t);
1653 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001654
reed@google.com74ce6f02013-05-22 15:13:18 +00001655 lua_newtable(L);
1656 setfield_string(L, "verb", verb);
1657 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001658
reed@google.com74ce6f02013-05-22 15:13:18 +00001659 ~AutoCallLua() {
1660 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1661 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1662 }
1663 lua_settop(fL, -1);
1664 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001665
reed@google.com74ce6f02013-05-22 15:13:18 +00001666private:
1667 lua_State* fL;
1668};
1669
1670#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1671
1672///////////////////////////////////////////////////////////////////////////////
1673
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001674static int lsk_newDocumentPDF(lua_State* L) {
1675 const char* file = NULL;
1676 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1677 file = lua_tolstring(L, 1, NULL);
1678 }
1679
1680 SkDocument* doc = SkDocument::CreatePDF(file);
1681 if (NULL == doc) {
1682 // do I need to push a nil on the stack and return 1?
1683 return 0;
1684 } else {
1685 push_ref(L, doc);
1686 doc->unref();
1687 return 1;
1688 }
1689}
1690
reedbdc49ae2014-10-14 09:34:52 -07001691static int lsk_newMatrix(lua_State* L) {
1692 push_new<SkMatrix>(L)->reset();
1693 return 1;
1694}
1695
reed@google.com3597b732013-05-22 20:12:50 +00001696static int lsk_newPaint(lua_State* L) {
1697 push_new<SkPaint>(L);
1698 return 1;
1699}
1700
1701static int lsk_newPath(lua_State* L) {
1702 push_new<SkPath>(L);
1703 return 1;
1704}
1705
reed96affcd2014-10-13 12:38:04 -07001706static int lsk_newPictureRecorder(lua_State* L) {
1707 push_new<SkPictureRecorder>(L);
1708 return 1;
1709}
1710
reed@google.com3597b732013-05-22 20:12:50 +00001711static int lsk_newRRect(lua_State* L) {
reedbdc49ae2014-10-14 09:34:52 -07001712 push_new<SkRRect>(L)->setEmpty();
reed@google.com3597b732013-05-22 20:12:50 +00001713 return 1;
1714}
1715
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001716static int lsk_newTypeface(lua_State* L) {
1717 const char* name = NULL;
1718 int style = SkTypeface::kNormal;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00001719
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001720 int count = lua_gettop(L);
1721 if (count > 0 && lua_isstring(L, 1)) {
1722 name = lua_tolstring(L, 1, NULL);
1723 if (count > 1 && lua_isnumber(L, 2)) {
1724 style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic;
1725 }
1726 }
1727
1728 SkTypeface* face = SkTypeface::CreateFromName(name,
1729 (SkTypeface::Style)style);
1730// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
1731 if (NULL == face) {
1732 face = SkTypeface::RefDefault();
1733 }
1734 push_ref(L, face);
1735 face->unref();
1736 return 1;
1737}
reed@google.com3597b732013-05-22 20:12:50 +00001738
reed485557f2014-10-12 10:36:47 -07001739static int lsk_newRasterSurface(lua_State* L) {
1740 int width = lua2int_def(L, 2, 0);
1741 int height = lua2int_def(L, 2, 0);
1742 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1743 SkSurface* surface = SkSurface::NewRaster(info);
1744 if (NULL == surface) {
1745 lua_pushnil(L);
1746 } else {
1747 push_ref(L, surface);
1748 surface->unref();
1749 }
1750 return 1;
1751}
1752
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001753static int lsk_loadImage(lua_State* L) {
1754 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
1755 const char* name = lua_tolstring(L, 1, NULL);
1756 SkAutoDataUnref data(SkData::NewFromFileName(name));
1757 if (data.get()) {
piotaixr4bcc2022014-09-17 14:33:30 -07001758 SkImage* image = SkImage::NewFromGenerator(
1759 SkDecodingImageGenerator::Create(data, SkDecodingImageGenerator::Options()));
1760
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001761 if (image) {
1762 push_ref(L, image);
1763 image->unref();
1764 return 1;
1765 }
1766 }
1767 }
1768 return 0;
1769}
1770
reed@google.com3597b732013-05-22 20:12:50 +00001771static void register_Sk(lua_State* L) {
1772 lua_newtable(L);
1773 lua_pushvalue(L, -1);
1774 lua_setglobal(L, "Sk");
1775 // the Sk table is still on top
1776
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001777 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001778 setfield_function(L, "loadImage", lsk_loadImage);
reedbdc49ae2014-10-14 09:34:52 -07001779 setfield_function(L, "newMatrix", lsk_newMatrix);
reed@google.com3597b732013-05-22 20:12:50 +00001780 setfield_function(L, "newPaint", lsk_newPaint);
1781 setfield_function(L, "newPath", lsk_newPath);
reed96affcd2014-10-13 12:38:04 -07001782 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
reed@google.com3597b732013-05-22 20:12:50 +00001783 setfield_function(L, "newRRect", lsk_newRRect);
reed485557f2014-10-12 10:36:47 -07001784 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001785 setfield_function(L, "newTypeface", lsk_newTypeface);
reed@google.com3597b732013-05-22 20:12:50 +00001786 lua_pop(L, 1); // pop off the Sk table
1787}
1788
reed@google.com74ce6f02013-05-22 15:13:18 +00001789#define REG_CLASS(L, C) \
1790 do { \
reed@google.com3597b732013-05-22 20:12:50 +00001791 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00001792 lua_pushvalue(L, -1); \
1793 lua_setfield(L, -2, "__index"); \
1794 luaL_setfuncs(L, g##C##_Methods, 0); \
1795 lua_pop(L, 1); /* pop off the meta-table */ \
1796 } while (0)
1797
1798void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00001799 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00001800 REG_CLASS(L, SkCanvas);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001801 REG_CLASS(L, SkDocument);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001802 REG_CLASS(L, SkImage);
reed@google.com74ce6f02013-05-22 15:13:18 +00001803 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001804 REG_CLASS(L, SkPath);
1805 REG_CLASS(L, SkPathEffect);
reed96affcd2014-10-13 12:38:04 -07001806 REG_CLASS(L, SkPicture);
1807 REG_CLASS(L, SkPictureRecorder);
reed@google.com74ce6f02013-05-22 15:13:18 +00001808 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00001809 REG_CLASS(L, SkShader);
reed485557f2014-10-12 10:36:47 -07001810 REG_CLASS(L, SkSurface);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001811 REG_CLASS(L, SkTypeface);
humper@google.com2815c192013-07-10 22:42:30 +00001812 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00001813}
zachr@google.com28c27c82013-06-20 17:15:05 +00001814
reed@google.com7bce9982013-06-20 17:40:21 +00001815extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00001816extern "C" int luaopen_skia(lua_State* L) {
1817 SkLua::Load(L);
1818 return 0;
1819}