blob: 27127df6a803074dfa31b7385c7224367c0f4109 [file] [log] [blame]
reed@google.com74ce6f02013-05-22 15:13:18 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkLua.h"
bsalomon@google.com4ebe3822014-02-26 20:22:32 +00009
10#if SK_SUPPORT_GPU
11#include "GrReducedClip.h"
12#endif
13
reed468b1812014-10-19 11:42:54 -070014#include "SkBlurImageFilter.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000015#include "SkCanvas.h"
reed22a517f2015-12-04 20:45:59 -080016#include "SkColorFilter.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000017#include "SkData.h"
mike@reedtribe.orgfb858242013-06-08 16:39:44 +000018#include "SkDocument.h"
reed9fbc3f32014-10-21 07:12:58 -070019#include "SkGradientShader.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000020#include "SkImage.h"
21#include "SkMatrix.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000022#include "SkPaint.h"
23#include "SkPath.h"
reed96affcd2014-10-13 12:38:04 -070024#include "SkPictureRecorder.h"
reed@google.com5fdc9832013-07-24 15:47:52 +000025#include "SkPixelRef.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000026#include "SkRRect.h"
27#include "SkString.h"
reed485557f2014-10-12 10:36:47 -070028#include "SkSurface.h"
fmalitab7425172014-08-26 07:56:44 -070029#include "SkTextBlob.h"
reed@google.come3823fd2013-05-30 18:55:14 +000030#include "SkTypeface.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000031
32extern "C" {
reed@google.com3597b732013-05-22 20:12:50 +000033 #include "lua.h"
34 #include "lualib.h"
35 #include "lauxlib.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000036}
37
reed@google.comfd345872013-05-22 20:53:42 +000038// return the metatable name for a given class
reed@google.com3597b732013-05-22 20:12:50 +000039template <typename T> const char* get_mtname();
reed@google.comfd345872013-05-22 20:53:42 +000040#define DEF_MTNAME(T) \
41 template <> const char* get_mtname<T>() { \
42 return #T "_LuaMetaTableName"; \
43 }
44
45DEF_MTNAME(SkCanvas)
reed22a517f2015-12-04 20:45:59 -080046DEF_MTNAME(SkColorFilter)
mike@reedtribe.orgfb858242013-06-08 16:39:44 +000047DEF_MTNAME(SkDocument)
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000048DEF_MTNAME(SkImage)
reed468b1812014-10-19 11:42:54 -070049DEF_MTNAME(SkImageFilter)
reed@google.comfd345872013-05-22 20:53:42 +000050DEF_MTNAME(SkMatrix)
51DEF_MTNAME(SkRRect)
52DEF_MTNAME(SkPath)
53DEF_MTNAME(SkPaint)
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +000054DEF_MTNAME(SkPathEffect)
reed96affcd2014-10-13 12:38:04 -070055DEF_MTNAME(SkPicture)
56DEF_MTNAME(SkPictureRecorder)
reed@google.com5fdc9832013-07-24 15:47:52 +000057DEF_MTNAME(SkShader)
reed485557f2014-10-12 10:36:47 -070058DEF_MTNAME(SkSurface)
fmalitab7425172014-08-26 07:56:44 -070059DEF_MTNAME(SkTextBlob)
mike@reedtribe.orge6469f12013-06-08 03:15:47 +000060DEF_MTNAME(SkTypeface)
reed@google.com74ce6f02013-05-22 15:13:18 +000061
reed@google.com3597b732013-05-22 20:12:50 +000062template <typename T> T* push_new(lua_State* L) {
63 T* addr = (T*)lua_newuserdata(L, sizeof(T));
64 new (addr) T;
65 luaL_getmetatable(L, get_mtname<T>());
66 lua_setmetatable(L, -2);
67 return addr;
68}
reed@google.com74ce6f02013-05-22 15:13:18 +000069
70template <typename T> void push_obj(lua_State* L, const T& obj) {
71 new (lua_newuserdata(L, sizeof(T))) T(obj);
reed@google.com3597b732013-05-22 20:12:50 +000072 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000073 lua_setmetatable(L, -2);
74}
75
Mike Reed5df49342016-11-12 08:06:55 -060076template <typename T> T* push_ptr(lua_State* L, T* ptr) {
77 *(T**)lua_newuserdata(L, sizeof(T*)) = ptr;
78 luaL_getmetatable(L, get_mtname<T>());
79 lua_setmetatable(L, -2);
80 return ptr;
81}
82
reed9fbc3f32014-10-21 07:12:58 -070083template <typename T> T* push_ref(lua_State* L, T* ref) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +000084 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
reed@google.com3597b732013-05-22 20:12:50 +000085 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000086 lua_setmetatable(L, -2);
reed9fbc3f32014-10-21 07:12:58 -070087 return ref;
reed@google.com74ce6f02013-05-22 15:13:18 +000088}
89
reed2ad1aa62016-03-09 09:50:50 -080090template <typename T> void push_ref(lua_State* L, sk_sp<T> sp) {
91 *(T**)lua_newuserdata(L, sizeof(T*)) = sp.release();
92 luaL_getmetatable(L, get_mtname<T>());
93 lua_setmetatable(L, -2);
94}
95
reed@google.com74ce6f02013-05-22 15:13:18 +000096template <typename T> T* get_ref(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +000097 return *(T**)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000098}
99
100template <typename T> T* get_obj(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +0000101 return (T*)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +0000102}
103
reed@google.com88c9ec92013-05-22 15:43:21 +0000104static bool lua2bool(lua_State* L, int index) {
105 return !!lua_toboolean(L, index);
106}
107
reed@google.com74ce6f02013-05-22 15:13:18 +0000108///////////////////////////////////////////////////////////////////////////////
109
reed@google.com3597b732013-05-22 20:12:50 +0000110SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
111 fL = luaL_newstate();
112 luaL_openlibs(fL);
113 SkLua::Load(fL);
114}
115
116SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
117
118SkLua::~SkLua() {
119 if (fWeOwnL) {
120 if (fTermCode.size() > 0) {
121 lua_getglobal(fL, fTermCode.c_str());
122 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
123 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
124 }
125 }
126 lua_close(fL);
127 }
128}
129
130bool SkLua::runCode(const char code[]) {
131 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
132 if (err) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000133 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
reed@google.com3597b732013-05-22 20:12:50 +0000134 return false;
135 }
136 return true;
137}
138
139bool SkLua::runCode(const void* code, size_t size) {
140 SkString str((const char*)code, size);
141 return this->runCode(str.c_str());
142}
143
144///////////////////////////////////////////////////////////////////////////////
145
146#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
147
reed@google.com29563872013-07-10 21:23:49 +0000148static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
149 if (pred) {
150 lua_pushboolean(L, true);
151 lua_setfield(L, -2, key);
152 }
153}
154
reed@google.com74ce6f02013-05-22 15:13:18 +0000155static void setfield_string(lua_State* L, const char key[], const char value[]) {
156 lua_pushstring(L, value);
157 lua_setfield(L, -2, key);
158}
159
160static void setfield_number(lua_State* L, const char key[], double value) {
161 lua_pushnumber(L, value);
162 lua_setfield(L, -2, key);
163}
164
humper@google.com2815c192013-07-10 22:42:30 +0000165static void setfield_boolean(lua_State* L, const char key[], bool value) {
166 lua_pushboolean(L, value);
167 lua_setfield(L, -2, key);
168}
169
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000170static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
171 setfield_number(L, key, SkScalarToLua(value));
172}
173
reed@google.com3597b732013-05-22 20:12:50 +0000174static void setfield_function(lua_State* L,
175 const char key[], lua_CFunction value) {
176 lua_pushcfunction(L, value);
177 lua_setfield(L, -2, key);
reed@google.com74ce6f02013-05-22 15:13:18 +0000178}
179
reed7a72c672014-11-07 10:23:55 -0800180static int lua2int_def(lua_State* L, int index, int defaultValue) {
181 if (lua_isnumber(L, index)) {
182 return (int)lua_tonumber(L, index);
183 } else {
184 return defaultValue;
185 }
186}
187
188static SkScalar lua2scalar(lua_State* L, int index) {
189 SkASSERT(lua_isnumber(L, index));
190 return SkLuaToScalar(lua_tonumber(L, index));
191}
192
193static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
194 if (lua_isnumber(L, index)) {
195 return SkLuaToScalar(lua_tonumber(L, index));
196 } else {
197 return defaultValue;
198 }
199}
200
201static SkScalar getarray_scalar(lua_State* L, int stackIndex, int arrayIndex) {
202 SkASSERT(lua_istable(L, stackIndex));
203 lua_rawgeti(L, stackIndex, arrayIndex);
mtklein8aacf202014-12-18 13:29:54 -0800204
reed7a72c672014-11-07 10:23:55 -0800205 SkScalar value = lua2scalar(L, -1);
206 lua_pop(L, 1);
207 return value;
208}
209
210static void getarray_scalars(lua_State* L, int stackIndex, SkScalar dst[], int count) {
211 for (int i = 0; i < count; ++i) {
212 dst[i] = getarray_scalar(L, stackIndex, i + 1);
213 }
214}
215
216static void getarray_points(lua_State* L, int stackIndex, SkPoint pts[], int count) {
217 getarray_scalars(L, stackIndex, &pts[0].fX, count * 2);
218}
219
reed@google.come3823fd2013-05-30 18:55:14 +0000220static void setarray_number(lua_State* L, int index, double value) {
221 lua_pushnumber(L, value);
222 lua_rawseti(L, -2, index);
223}
224
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000225static void setarray_scalar(lua_State* L, int index, SkScalar value) {
226 setarray_number(L, index, SkScalarToLua(value));
227}
228
hstern0b401ce2016-08-02 09:17:59 -0700229static void setarray_string(lua_State* L, int index, const char str[]) {
230 lua_pushstring(L, str);
231 lua_rawseti(L, -2, index);
232}
233
reed@google.com74ce6f02013-05-22 15:13:18 +0000234void SkLua::pushBool(bool value, const char key[]) {
235 lua_pushboolean(fL, value);
236 CHECK_SETFIELD(key);
237}
238
239void SkLua::pushString(const char str[], const char key[]) {
240 lua_pushstring(fL, str);
241 CHECK_SETFIELD(key);
242}
243
reed@google.come3823fd2013-05-30 18:55:14 +0000244void SkLua::pushString(const char str[], size_t length, const char key[]) {
245 // TODO: how to do this w/o making a copy?
246 SkString s(str, length);
247 lua_pushstring(fL, s.c_str());
248 CHECK_SETFIELD(key);
249}
250
reed@google.com74ce6f02013-05-22 15:13:18 +0000251void SkLua::pushString(const SkString& str, const char key[]) {
252 lua_pushstring(fL, str.c_str());
253 CHECK_SETFIELD(key);
254}
255
256void SkLua::pushColor(SkColor color, const char key[]) {
257 lua_newtable(fL);
258 setfield_number(fL, "a", SkColorGetA(color) / 255.0);
259 setfield_number(fL, "r", SkColorGetR(color) / 255.0);
260 setfield_number(fL, "g", SkColorGetG(color) / 255.0);
261 setfield_number(fL, "b", SkColorGetB(color) / 255.0);
262 CHECK_SETFIELD(key);
263}
264
reed@google.come3823fd2013-05-30 18:55:14 +0000265void SkLua::pushU32(uint32_t value, const char key[]) {
266 lua_pushnumber(fL, (double)value);
267 CHECK_SETFIELD(key);
268}
269
reed@google.com74ce6f02013-05-22 15:13:18 +0000270void SkLua::pushScalar(SkScalar value, const char key[]) {
271 lua_pushnumber(fL, SkScalarToLua(value));
272 CHECK_SETFIELD(key);
273}
274
reed@google.come3823fd2013-05-30 18:55:14 +0000275void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
276 lua_newtable(fL);
277 for (int i = 0; i < count; ++i) {
278 // make it base-1 to match lua convention
279 setarray_number(fL, i + 1, (double)array[i]);
280 }
281 CHECK_SETFIELD(key);
282}
283
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000284void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
285 lua_newtable(fL);
286 for (int i = 0; i < count; ++i) {
287 // make it base-1 to match lua convention
288 lua_newtable(fL);
289 this->pushScalar(array[i].fX, "x");
290 this->pushScalar(array[i].fY, "y");
291 lua_rawseti(fL, -2, i + 1);
292 }
293 CHECK_SETFIELD(key);
294}
295
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000296void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
297 lua_newtable(fL);
298 for (int i = 0; i < count; ++i) {
299 // make it base-1 to match lua convention
300 setarray_scalar(fL, i + 1, array[i]);
301 }
302 CHECK_SETFIELD(key);
303}
304
reed@google.com74ce6f02013-05-22 15:13:18 +0000305void SkLua::pushRect(const SkRect& r, const char key[]) {
306 lua_newtable(fL);
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000307 setfield_scalar(fL, "left", r.fLeft);
308 setfield_scalar(fL, "top", r.fTop);
309 setfield_scalar(fL, "right", r.fRight);
310 setfield_scalar(fL, "bottom", r.fBottom);
reed@google.com74ce6f02013-05-22 15:13:18 +0000311 CHECK_SETFIELD(key);
312}
313
314void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
315 push_obj(fL, rr);
316 CHECK_SETFIELD(key);
317}
318
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000319void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
320 lua_newtable(fL);
321 setfield_scalar(fL, "phase", info.fPhase);
322 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
323 CHECK_SETFIELD(key);
324}
325
326
reed@google.com74ce6f02013-05-22 15:13:18 +0000327void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
328 push_obj(fL, matrix);
329 CHECK_SETFIELD(key);
330}
331
332void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
333 push_obj(fL, paint);
334 CHECK_SETFIELD(key);
335}
336
337void SkLua::pushPath(const SkPath& path, const char key[]) {
338 push_obj(fL, path);
339 CHECK_SETFIELD(key);
340}
341
342void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
Mike Reed5df49342016-11-12 08:06:55 -0600343 push_ptr(fL, canvas);
reed@google.com74ce6f02013-05-22 15:13:18 +0000344 CHECK_SETFIELD(key);
345}
346
fmalitab7425172014-08-26 07:56:44 -0700347void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
348 push_ref(fL, const_cast<SkTextBlob*>(blob));
349 CHECK_SETFIELD(key);
350}
351
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000352static const char* element_type(SkClipStack::Element::Type type) {
353 switch (type) {
354 case SkClipStack::Element::kEmpty_Type:
355 return "empty";
356 case SkClipStack::Element::kRect_Type:
357 return "rect";
358 case SkClipStack::Element::kRRect_Type:
359 return "rrect";
360 case SkClipStack::Element::kPath_Type:
361 return "path";
362 }
363 return "unknown";
364}
365
366static const char* region_op(SkRegion::Op op) {
367 switch (op) {
368 case SkRegion::kDifference_Op:
369 return "difference";
370 case SkRegion::kIntersect_Op:
371 return "intersect";
372 case SkRegion::kUnion_Op:
373 return "union";
374 case SkRegion::kXOR_Op:
375 return "xor";
376 case SkRegion::kReverseDifference_Op:
377 return "reverse-difference";
378 case SkRegion::kReplace_Op:
379 return "replace";
380 }
381 return "unknown";
382}
383
384void SkLua::pushClipStack(const SkClipStack& stack, const char* key) {
385 lua_newtable(fL);
386 SkClipStack::B2TIter iter(stack);
387 const SkClipStack::Element* element;
388 int i = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700389 while ((element = iter.next())) {
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000390 this->pushClipStackElement(*element);
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000391 lua_rawseti(fL, -2, ++i);
392 }
393 CHECK_SETFIELD(key);
394}
395
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000396void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) {
397 lua_newtable(fL);
398 SkClipStack::Element::Type type = element.getType();
399 this->pushString(element_type(type), "type");
400 switch (type) {
401 case SkClipStack::Element::kEmpty_Type:
402 break;
403 case SkClipStack::Element::kRect_Type:
404 this->pushRect(element.getRect(), "rect");
405 break;
406 case SkClipStack::Element::kRRect_Type:
407 this->pushRRect(element.getRRect(), "rrect");
408 break;
409 case SkClipStack::Element::kPath_Type:
410 this->pushPath(element.getPath(), "path");
411 break;
412 }
reed73603f32016-09-20 08:42:38 -0700413 this->pushString(region_op((SkRegion::Op)element.getOp()), "op");
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000414 this->pushBool(element.isAA(), "aa");
415 CHECK_SETFIELD(key);
416}
417
418
reed@google.com74ce6f02013-05-22 15:13:18 +0000419///////////////////////////////////////////////////////////////////////////////
420///////////////////////////////////////////////////////////////////////////////
421
reed@google.com74ce6f02013-05-22 15:13:18 +0000422static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
423 SkASSERT(lua_istable(L, index));
424 lua_pushstring(L, key);
425 lua_gettable(L, index);
mtklein8aacf202014-12-18 13:29:54 -0800426
reed@google.com74ce6f02013-05-22 15:13:18 +0000427 SkScalar value = lua2scalar(L, -1);
428 lua_pop(L, 1);
429 return value;
430}
431
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000432static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
433 SkASSERT(lua_istable(L, index));
434 lua_pushstring(L, key);
435 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000436
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000437 SkScalar value;
438 if (lua_isnil(L, -1)) {
439 value = def;
440 } else {
441 value = lua2scalar(L, -1);
442 }
443 lua_pop(L, 1);
444 return value;
445}
446
reed468b1812014-10-19 11:42:54 -0700447static SkScalar byte2unit(U8CPU byte) {
448 return byte / 255.0f;
449}
450
reed@google.com74ce6f02013-05-22 15:13:18 +0000451static U8CPU unit2byte(SkScalar x) {
452 if (x <= 0) {
453 return 0;
454 } else if (x >= 1) {
455 return 255;
456 } else {
457 return SkScalarRoundToInt(x * 255);
458 }
459}
460
461static SkColor lua2color(lua_State* L, int index) {
reed485557f2014-10-12 10:36:47 -0700462 return SkColorSetARGB(unit2byte(getfield_scalar_default(L, index, "a", 1)),
463 unit2byte(getfield_scalar_default(L, index, "r", 0)),
464 unit2byte(getfield_scalar_default(L, index, "g", 0)),
465 unit2byte(getfield_scalar_default(L, index, "b", 0)));
reed@google.com74ce6f02013-05-22 15:13:18 +0000466}
467
468static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000469 rect->set(getfield_scalar_default(L, index, "left", 0),
470 getfield_scalar_default(L, index, "top", 0),
reed@google.com74ce6f02013-05-22 15:13:18 +0000471 getfield_scalar(L, index, "right"),
472 getfield_scalar(L, index, "bottom"));
473 return rect;
474}
475
reedf355df52014-10-12 12:18:40 -0700476static int lcanvas_clear(lua_State* L) {
477 get_ref<SkCanvas>(L, 1)->clear(0);
478 return 0;
479}
480
reed@google.com74ce6f02013-05-22 15:13:18 +0000481static int lcanvas_drawColor(lua_State* L) {
482 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
483 return 0;
484}
485
reed9fbc3f32014-10-21 07:12:58 -0700486static int lcanvas_drawPaint(lua_State* L) {
487 get_ref<SkCanvas>(L, 1)->drawPaint(*get_obj<SkPaint>(L, 2));
488 return 0;
489}
490
reed@google.com74ce6f02013-05-22 15:13:18 +0000491static int lcanvas_drawRect(lua_State* L) {
492 SkRect rect;
reed7a72c672014-11-07 10:23:55 -0800493 lua2rect(L, 2, &rect);
494 const SkPaint* paint = get_obj<SkPaint>(L, 3);
495 get_ref<SkCanvas>(L, 1)->drawRect(rect, *paint);
reed@google.com74ce6f02013-05-22 15:13:18 +0000496 return 0;
497}
498
499static int lcanvas_drawOval(lua_State* L) {
500 SkRect rect;
501 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
502 *get_obj<SkPaint>(L, 3));
503 return 0;
504}
505
506static int lcanvas_drawCircle(lua_State* L) {
507 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
508 lua2scalar(L, 3),
509 lua2scalar(L, 4),
510 *get_obj<SkPaint>(L, 5));
511 return 0;
512}
513
reed485557f2014-10-12 10:36:47 -0700514static SkPaint* lua2OptionalPaint(lua_State* L, int index, SkPaint* paint) {
515 if (lua_isnumber(L, index)) {
516 paint->setAlpha(SkScalarRoundToInt(lua2scalar(L, index) * 255));
517 return paint;
reedf355df52014-10-12 12:18:40 -0700518 } else if (lua_isuserdata(L, index)) {
reed485557f2014-10-12 10:36:47 -0700519 const SkPaint* ptr = get_obj<SkPaint>(L, index);
520 if (ptr) {
521 *paint = *ptr;
522 return paint;
523 }
524 }
halcanary96fcdcc2015-08-27 07:41:13 -0700525 return nullptr;
reed485557f2014-10-12 10:36:47 -0700526}
527
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000528static int lcanvas_drawImage(lua_State* L) {
529 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
530 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700531 if (nullptr == image) {
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000532 return 0;
533 }
534 SkScalar x = lua2scalar(L, 3);
535 SkScalar y = lua2scalar(L, 4);
536
537 SkPaint paint;
reed485557f2014-10-12 10:36:47 -0700538 canvas->drawImage(image, x, y, lua2OptionalPaint(L, 5, &paint));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000539 return 0;
540}
541
reedba5fb932014-10-10 15:28:19 -0700542static int lcanvas_drawImageRect(lua_State* L) {
543 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
544 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700545 if (nullptr == image) {
reedba5fb932014-10-10 15:28:19 -0700546 return 0;
547 }
548
549 SkRect srcR, dstR;
halcanary96fcdcc2015-08-27 07:41:13 -0700550 SkRect* srcRPtr = nullptr;
reedba5fb932014-10-10 15:28:19 -0700551 if (!lua_isnil(L, 3)) {
552 srcRPtr = lua2rect(L, 3, &srcR);
553 }
554 lua2rect(L, 4, &dstR);
mtklein8aacf202014-12-18 13:29:54 -0800555
reedba5fb932014-10-10 15:28:19 -0700556 SkPaint paint;
reede47829b2015-08-06 10:02:53 -0700557 canvas->legacy_drawImageRect(image, srcRPtr, dstR, lua2OptionalPaint(L, 5, &paint));
reedba5fb932014-10-10 15:28:19 -0700558 return 0;
559}
560
reed7a72c672014-11-07 10:23:55 -0800561static int lcanvas_drawPatch(lua_State* L) {
562 SkPoint cubics[12];
563 SkColor colorStorage[4];
564 SkPoint texStorage[4];
565
halcanary96fcdcc2015-08-27 07:41:13 -0700566 const SkColor* colors = nullptr;
567 const SkPoint* texs = nullptr;
reed7a72c672014-11-07 10:23:55 -0800568
569 getarray_points(L, 2, cubics, 12);
570
571 colorStorage[0] = SK_ColorRED;
572 colorStorage[1] = SK_ColorGREEN;
573 colorStorage[2] = SK_ColorBLUE;
574 colorStorage[3] = SK_ColorGRAY;
575
576 if (lua_isnil(L, 4)) {
577 colors = colorStorage;
578 } else {
579 getarray_points(L, 4, texStorage, 4);
580 texs = texStorage;
581 }
582
Mike Reed7d954ad2016-10-28 15:42:34 -0400583 get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, *get_obj<SkPaint>(L, 5));
reed7a72c672014-11-07 10:23:55 -0800584 return 0;
585}
586
reed@google.comfd345872013-05-22 20:53:42 +0000587static int lcanvas_drawPath(lua_State* L) {
588 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
589 *get_obj<SkPaint>(L, 3));
590 return 0;
591}
592
reed96affcd2014-10-13 12:38:04 -0700593// drawPicture(pic, x, y, paint)
594static int lcanvas_drawPicture(lua_State* L) {
595 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
596 SkPicture* picture = get_ref<SkPicture>(L, 2);
597 SkScalar x = lua2scalar_def(L, 3, 0);
598 SkScalar y = lua2scalar_def(L, 4, 0);
halcanary96fcdcc2015-08-27 07:41:13 -0700599 SkMatrix matrix, *matrixPtr = nullptr;
reed96affcd2014-10-13 12:38:04 -0700600 if (x || y) {
601 matrix.setTranslate(x, y);
602 matrixPtr = &matrix;
603 }
604 SkPaint paint;
605 canvas->drawPicture(picture, matrixPtr, lua2OptionalPaint(L, 5, &paint));
606 return 0;
607}
608
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000609static int lcanvas_drawText(lua_State* L) {
610 if (lua_gettop(L) < 5) {
611 return 0;
612 }
613
614 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
615 size_t len;
616 const char* text = lua_tolstring(L, 2, &len);
617 get_ref<SkCanvas>(L, 1)->drawText(text, len,
618 lua2scalar(L, 3), lua2scalar(L, 4),
619 *get_obj<SkPaint>(L, 5));
620 }
621 return 0;
622}
623
reed1b6ab442014-11-03 19:55:41 -0800624static int lcanvas_drawTextBlob(lua_State* L) {
625 const SkTextBlob* blob = get_ref<SkTextBlob>(L, 2);
626 SkScalar x = lua2scalar(L, 3);
627 SkScalar y = lua2scalar(L, 4);
628 const SkPaint& paint = *get_obj<SkPaint>(L, 5);
629 get_ref<SkCanvas>(L, 1)->drawTextBlob(blob, x, y, paint);
630 return 0;
631}
632
reed@google.com74ce6f02013-05-22 15:13:18 +0000633static int lcanvas_getSaveCount(lua_State* L) {
634 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
635 return 1;
636}
637
638static int lcanvas_getTotalMatrix(lua_State* L) {
639 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
640 return 1;
641}
642
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000643static int lcanvas_getClipStack(lua_State* L) {
644 SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack());
645 return 1;
646}
647
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000648int SkLua::lcanvas_getReducedClipStack(lua_State* L) {
649#if SK_SUPPORT_GPU
650 const SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
csmartdaltoncbecb082016-07-22 08:59:08 -0700651 SkRect queryBounds = SkRect::Make(canvas->getTopLayerBounds());
csmartdalton77f2fae2016-08-08 09:55:06 -0700652 const GrReducedClip reducedClip(*canvas->getClipStack(), queryBounds);
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000653
csmartdalton77f2fae2016-08-08 09:55:06 -0700654 GrReducedClip::ElementList::Iter iter(reducedClip.elements());
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000655 int i = 0;
656 lua_newtable(L);
bsalomon49f085d2014-09-05 13:34:00 -0700657 while(iter.get()) {
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000658 SkLua(L).pushClipStackElement(*iter.get());
659 iter.next();
660 lua_rawseti(L, -2, ++i);
661 }
662 // Currently this only returns the element list to lua, not the initial state or result bounds.
663 // It could return these as additional items on the lua stack.
664 return 1;
665#else
666 return 0;
667#endif
668}
669
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000670static int lcanvas_save(lua_State* L) {
671 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
672 return 1;
673}
674
reed86217d82014-10-25 20:44:40 -0700675static int lcanvas_saveLayer(lua_State* L) {
676 SkPaint paint;
halcanary96fcdcc2015-08-27 07:41:13 -0700677 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->saveLayer(nullptr, lua2OptionalPaint(L, 2, &paint)));
reed86217d82014-10-25 20:44:40 -0700678 return 1;
679}
680
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000681static int lcanvas_restore(lua_State* L) {
682 get_ref<SkCanvas>(L, 1)->restore();
683 return 0;
684}
685
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000686static int lcanvas_scale(lua_State* L) {
687 SkScalar sx = lua2scalar_def(L, 2, 1);
688 SkScalar sy = lua2scalar_def(L, 3, sx);
689 get_ref<SkCanvas>(L, 1)->scale(sx, sy);
690 return 0;
691}
692
reed@google.com3597b732013-05-22 20:12:50 +0000693static int lcanvas_translate(lua_State* L) {
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000694 SkScalar tx = lua2scalar_def(L, 2, 0);
695 SkScalar ty = lua2scalar_def(L, 3, 0);
696 get_ref<SkCanvas>(L, 1)->translate(tx, ty);
697 return 0;
698}
699
700static int lcanvas_rotate(lua_State* L) {
701 SkScalar degrees = lua2scalar_def(L, 2, 0);
702 get_ref<SkCanvas>(L, 1)->rotate(degrees);
reed@google.com3597b732013-05-22 20:12:50 +0000703 return 0;
704}
705
reedbdc49ae2014-10-14 09:34:52 -0700706static int lcanvas_concat(lua_State* L) {
707 get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2));
708 return 0;
709}
710
reed485557f2014-10-12 10:36:47 -0700711static int lcanvas_newSurface(lua_State* L) {
712 int width = lua2int_def(L, 2, 0);
reed7a72c672014-11-07 10:23:55 -0800713 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -0700714 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -0700715 auto surface = get_ref<SkCanvas>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -0700716 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -0700717 lua_pushnil(L);
718 } else {
reede8f30622016-03-23 18:59:25 -0700719 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -0700720 }
721 return 1;
722}
723
reed@google.com74ce6f02013-05-22 15:13:18 +0000724static int lcanvas_gc(lua_State* L) {
Mike Reed5df49342016-11-12 08:06:55 -0600725 // don't know how to track a ptr...
reed@google.com74ce6f02013-05-22 15:13:18 +0000726 return 0;
727}
728
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000729const struct luaL_Reg gSkCanvas_Methods[] = {
reedf355df52014-10-12 12:18:40 -0700730 { "clear", lcanvas_clear },
reed@google.com74ce6f02013-05-22 15:13:18 +0000731 { "drawColor", lcanvas_drawColor },
reed9fbc3f32014-10-21 07:12:58 -0700732 { "drawPaint", lcanvas_drawPaint },
reed@google.com74ce6f02013-05-22 15:13:18 +0000733 { "drawRect", lcanvas_drawRect },
734 { "drawOval", lcanvas_drawOval },
735 { "drawCircle", lcanvas_drawCircle },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000736 { "drawImage", lcanvas_drawImage },
reedba5fb932014-10-10 15:28:19 -0700737 { "drawImageRect", lcanvas_drawImageRect },
reed7a72c672014-11-07 10:23:55 -0800738 { "drawPatch", lcanvas_drawPatch },
reed@google.comfd345872013-05-22 20:53:42 +0000739 { "drawPath", lcanvas_drawPath },
reed96affcd2014-10-13 12:38:04 -0700740 { "drawPicture", lcanvas_drawPicture },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000741 { "drawText", lcanvas_drawText },
reed1b6ab442014-11-03 19:55:41 -0800742 { "drawTextBlob", lcanvas_drawTextBlob },
reed@google.com74ce6f02013-05-22 15:13:18 +0000743 { "getSaveCount", lcanvas_getSaveCount },
744 { "getTotalMatrix", lcanvas_getTotalMatrix },
commit-bot@chromium.org5cc25352014-02-24 18:59:48 +0000745 { "getClipStack", lcanvas_getClipStack },
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000746#if SK_SUPPORT_GPU
747 { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
748#endif
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000749 { "save", lcanvas_save },
reed86217d82014-10-25 20:44:40 -0700750 { "saveLayer", lcanvas_saveLayer },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000751 { "restore", lcanvas_restore },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000752 { "scale", lcanvas_scale },
reed@google.com3597b732013-05-22 20:12:50 +0000753 { "translate", lcanvas_translate },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000754 { "rotate", lcanvas_rotate },
reedbdc49ae2014-10-14 09:34:52 -0700755 { "concat", lcanvas_concat },
reed485557f2014-10-12 10:36:47 -0700756
757 { "newSurface", lcanvas_newSurface },
758
reed@google.com74ce6f02013-05-22 15:13:18 +0000759 { "__gc", lcanvas_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700760 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +0000761};
762
763///////////////////////////////////////////////////////////////////////////////
764
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000765static int ldocument_beginPage(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -0700766 const SkRect* contentPtr = nullptr;
Mike Reed5df49342016-11-12 08:06:55 -0600767 push_ptr(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2),
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000768 lua2scalar(L, 3),
769 contentPtr));
770 return 1;
771}
772
773static int ldocument_endPage(lua_State* L) {
774 get_ref<SkDocument>(L, 1)->endPage();
775 return 0;
776}
777
778static int ldocument_close(lua_State* L) {
779 get_ref<SkDocument>(L, 1)->close();
780 return 0;
781}
782
783static int ldocument_gc(lua_State* L) {
784 get_ref<SkDocument>(L, 1)->unref();
785 return 0;
786}
787
788static const struct luaL_Reg gSkDocument_Methods[] = {
789 { "beginPage", ldocument_beginPage },
790 { "endPage", ldocument_endPage },
791 { "close", ldocument_close },
792 { "__gc", ldocument_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700793 { nullptr, nullptr }
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000794};
795
796///////////////////////////////////////////////////////////////////////////////
797
reed@google.com74ce6f02013-05-22 15:13:18 +0000798static int lpaint_isAntiAlias(lua_State* L) {
799 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
800 return 1;
801}
802
803static int lpaint_setAntiAlias(lua_State* L) {
reed@google.com88c9ec92013-05-22 15:43:21 +0000804 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +0000805 return 0;
806}
807
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000808static int lpaint_isDither(lua_State* L) {
809 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
810 return 1;
811}
812
reedbb8a0ab2014-11-03 22:32:07 -0800813static int lpaint_setDither(lua_State* L) {
814 get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2));
815 return 0;
816}
817
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000818static int lpaint_isUnderlineText(lua_State* L) {
819 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText());
820 return 1;
821}
822
823static int lpaint_isStrikeThruText(lua_State* L) {
824 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText());
825 return 1;
826}
827
828static int lpaint_isFakeBoldText(lua_State* L) {
829 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
830 return 1;
831}
832
833static int lpaint_isLinearText(lua_State* L) {
834 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
835 return 1;
836}
837
838static int lpaint_isSubpixelText(lua_State* L) {
839 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
840 return 1;
841}
842
reed09a1d672014-10-11 13:13:11 -0700843static int lpaint_setSubpixelText(lua_State* L) {
844 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
845 return 1;
846}
847
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000848static int lpaint_isDevKernText(lua_State* L) {
849 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
850 return 1;
851}
852
853static int lpaint_isLCDRenderText(lua_State* L) {
854 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
855 return 1;
856}
857
reed36c9c112014-11-04 10:58:42 -0800858static int lpaint_setLCDRenderText(lua_State* L) {
859 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2));
860 return 1;
861}
862
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000863static int lpaint_isEmbeddedBitmapText(lua_State* L) {
864 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
865 return 1;
866}
867
868static int lpaint_isAutohinted(lua_State* L) {
869 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
870 return 1;
871}
872
873static int lpaint_isVerticalText(lua_State* L) {
874 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
875 return 1;
876}
877
reed468b1812014-10-19 11:42:54 -0700878static int lpaint_getAlpha(lua_State* L) {
879 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha()));
880 return 1;
881}
882
883static int lpaint_setAlpha(lua_State* L) {
884 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2)));
885 return 0;
886}
887
reed@google.com74ce6f02013-05-22 15:13:18 +0000888static int lpaint_getColor(lua_State* L) {
889 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
890 return 1;
891}
892
893static int lpaint_setColor(lua_State* L) {
894 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
895 return 0;
896}
897
reed@google.come3823fd2013-05-30 18:55:14 +0000898static int lpaint_getTextSize(lua_State* L) {
899 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
900 return 1;
901}
902
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000903static int lpaint_getTextScaleX(lua_State* L) {
904 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
905 return 1;
906}
907
908static int lpaint_getTextSkewX(lua_State* L) {
909 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
910 return 1;
911}
912
reed@google.come3823fd2013-05-30 18:55:14 +0000913static int lpaint_setTextSize(lua_State* L) {
914 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
915 return 0;
916}
917
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000918static int lpaint_getTypeface(lua_State* L) {
919 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
920 return 1;
921}
922
923static int lpaint_setTypeface(lua_State* L) {
bungeman13b9c952016-05-12 10:09:30 -0700924 get_obj<SkPaint>(L, 1)->setTypeface(sk_ref_sp(get_ref<SkTypeface>(L, 2)));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000925 return 0;
926}
927
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000928static int lpaint_getHinting(lua_State* L) {
929 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
930 return 1;
931}
932
reed93a12152015-03-16 10:08:34 -0700933static int lpaint_getFilterQuality(lua_State* L) {
934 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality());
reed7a72c672014-11-07 10:23:55 -0800935 return 1;
936}
937
reed93a12152015-03-16 10:08:34 -0700938static int lpaint_setFilterQuality(lua_State* L) {
reed7a72c672014-11-07 10:23:55 -0800939 int level = lua2int_def(L, 2, -1);
940 if (level >= 0 && level <= 3) {
reed93a12152015-03-16 10:08:34 -0700941 get_obj<SkPaint>(L, 1)->setFilterQuality((SkFilterQuality)level);
reed7a72c672014-11-07 10:23:55 -0800942 }
943 return 0;
944}
945
reed@google.come3823fd2013-05-30 18:55:14 +0000946static int lpaint_getFontID(lua_State* L) {
947 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
948 SkLua(L).pushU32(SkTypeface::UniqueID(face));
949 return 1;
950}
951
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000952static const struct {
953 const char* fLabel;
954 SkPaint::Align fAlign;
955} gAlignRec[] = {
956 { "left", SkPaint::kLeft_Align },
957 { "center", SkPaint::kCenter_Align },
958 { "right", SkPaint::kRight_Align },
959};
960
961static int lpaint_getTextAlign(lua_State* L) {
962 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
963 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
964 if (gAlignRec[i].fAlign == align) {
965 lua_pushstring(L, gAlignRec[i].fLabel);
966 return 1;
967 }
968 }
969 return 0;
970}
971
972static int lpaint_setTextAlign(lua_State* L) {
973 if (lua_isstring(L, 2)) {
974 size_t len;
975 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000976
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000977 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
978 if (!strcmp(gAlignRec[i].fLabel, label)) {
979 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
980 break;
981 }
982 }
983 }
984 return 0;
985}
986
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000987static int lpaint_getStroke(lua_State* L) {
988 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
989 return 1;
990}
991
992static int lpaint_setStroke(lua_State* L) {
993 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000994
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000995 if (lua_toboolean(L, 2)) {
996 style = SkPaint::kStroke_Style;
997 } else {
998 style = SkPaint::kFill_Style;
999 }
1000 get_obj<SkPaint>(L, 1)->setStyle(style);
1001 return 0;
1002}
1003
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001004static int lpaint_getStrokeCap(lua_State* L) {
1005 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
1006 return 1;
1007}
1008
1009static int lpaint_getStrokeJoin(lua_State* L) {
1010 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
1011 return 1;
1012}
1013
1014static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +00001015 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001016 return 1;
1017}
1018
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001019static int lpaint_getStrokeWidth(lua_State* L) {
1020 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
1021 return 1;
1022}
1023
1024static int lpaint_setStrokeWidth(lua_State* L) {
1025 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
1026 return 0;
1027}
1028
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001029static int lpaint_getStrokeMiter(lua_State* L) {
1030 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
1031 return 1;
1032}
1033
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001034static int lpaint_measureText(lua_State* L) {
1035 if (lua_isstring(L, 2)) {
1036 size_t len;
1037 const char* text = lua_tolstring(L, 2, &len);
1038 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
1039 return 1;
1040 }
1041 return 0;
1042}
1043
1044struct FontMetrics {
1045 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
1046 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
1047 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
1048 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
1049 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
1050 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
1051 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
1052 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
1053 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
1054};
1055
1056static int lpaint_getFontMetrics(lua_State* L) {
1057 SkPaint::FontMetrics fm;
1058 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +00001059
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001060 lua_newtable(L);
1061 setfield_scalar(L, "top", fm.fTop);
1062 setfield_scalar(L, "ascent", fm.fAscent);
1063 setfield_scalar(L, "descent", fm.fDescent);
1064 setfield_scalar(L, "bottom", fm.fBottom);
1065 setfield_scalar(L, "leading", fm.fLeading);
1066 SkLua(L).pushScalar(height);
1067 return 2;
1068}
1069
reed@google.com29563872013-07-10 21:23:49 +00001070static int lpaint_getEffects(lua_State* L) {
1071 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001072
reed@google.com29563872013-07-10 21:23:49 +00001073 lua_newtable(L);
reed468b1812014-10-19 11:42:54 -07001074 setfield_bool_if(L, "looper", !!paint->getLooper());
1075 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
1076 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer());
1077 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
1078 setfield_bool_if(L, "shader", !!paint->getShader());
reed@google.com29563872013-07-10 21:23:49 +00001079 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
1080 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
reed@google.com29563872013-07-10 21:23:49 +00001081 return 1;
1082}
1083
reed22a517f2015-12-04 20:45:59 -08001084static int lpaint_getColorFilter(lua_State* L) {
1085 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1086 SkColorFilter* cf = paint->getColorFilter();
1087 if (cf) {
1088 push_ref(L, cf);
1089 return 1;
1090 }
1091 return 0;
1092}
1093
1094static int lpaint_setColorFilter(lua_State* L) {
1095 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedd053ce92016-03-22 10:17:23 -07001096 paint->setColorFilter(sk_ref_sp(get_ref<SkColorFilter>(L, 2)));
reed22a517f2015-12-04 20:45:59 -08001097 return 0;
1098}
1099
reed468b1812014-10-19 11:42:54 -07001100static int lpaint_getImageFilter(lua_State* L) {
1101 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1102 SkImageFilter* imf = paint->getImageFilter();
1103 if (imf) {
1104 push_ref(L, imf);
1105 return 1;
1106 }
1107 return 0;
1108}
1109
1110static int lpaint_setImageFilter(lua_State* L) {
1111 SkPaint* paint = get_obj<SkPaint>(L, 1);
Mike Reed5e257172016-11-01 11:22:05 -04001112 paint->setImageFilter(sk_ref_sp(get_ref<SkImageFilter>(L, 2)));
reed468b1812014-10-19 11:42:54 -07001113 return 0;
1114}
1115
reed@google.com5fdc9832013-07-24 15:47:52 +00001116static int lpaint_getShader(lua_State* L) {
1117 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1118 SkShader* shader = paint->getShader();
1119 if (shader) {
1120 push_ref(L, shader);
1121 return 1;
1122 }
1123 return 0;
1124}
1125
reed9fbc3f32014-10-21 07:12:58 -07001126static int lpaint_setShader(lua_State* L) {
1127 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedfe630452016-03-25 09:08:00 -07001128 paint->setShader(sk_ref_sp(get_ref<SkShader>(L, 2)));
reed9fbc3f32014-10-21 07:12:58 -07001129 return 0;
1130}
1131
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001132static int lpaint_getPathEffect(lua_State* L) {
1133 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1134 SkPathEffect* pe = paint->getPathEffect();
1135 if (pe) {
1136 push_ref(L, pe);
1137 return 1;
1138 }
1139 return 0;
1140}
1141
hstern0b401ce2016-08-02 09:17:59 -07001142static int lpaint_getFillPath(lua_State* L) {
1143 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1144 const SkPath* path = get_obj<SkPath>(L, 2);
1145
1146 SkPath fillpath;
1147 paint->getFillPath(*path, &fillpath);
1148
1149 SkLua lua(L);
1150 lua.pushPath(fillpath);
1151
1152 return 1;
1153}
1154
reed@google.com74ce6f02013-05-22 15:13:18 +00001155static int lpaint_gc(lua_State* L) {
1156 get_obj<SkPaint>(L, 1)->~SkPaint();
1157 return 0;
1158}
1159
1160static const struct luaL_Reg gSkPaint_Methods[] = {
1161 { "isAntiAlias", lpaint_isAntiAlias },
1162 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001163 { "isDither", lpaint_isDither },
reedbb8a0ab2014-11-03 22:32:07 -08001164 { "setDither", lpaint_setDither },
reed93a12152015-03-16 10:08:34 -07001165 { "getFilterQuality", lpaint_getFilterQuality },
1166 { "setFilterQuality", lpaint_setFilterQuality },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001167 { "isUnderlineText", lpaint_isUnderlineText },
1168 { "isStrikeThruText", lpaint_isStrikeThruText },
1169 { "isFakeBoldText", lpaint_isFakeBoldText },
1170 { "isLinearText", lpaint_isLinearText },
1171 { "isSubpixelText", lpaint_isSubpixelText },
reed09a1d672014-10-11 13:13:11 -07001172 { "setSubpixelText", lpaint_setSubpixelText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001173 { "isDevKernText", lpaint_isDevKernText },
1174 { "isLCDRenderText", lpaint_isLCDRenderText },
reed36c9c112014-11-04 10:58:42 -08001175 { "setLCDRenderText", lpaint_setLCDRenderText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001176 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
1177 { "isAutohinted", lpaint_isAutohinted },
1178 { "isVerticalText", lpaint_isVerticalText },
reed468b1812014-10-19 11:42:54 -07001179 { "getAlpha", lpaint_getAlpha },
1180 { "setAlpha", lpaint_setAlpha },
reed@google.com74ce6f02013-05-22 15:13:18 +00001181 { "getColor", lpaint_getColor },
1182 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +00001183 { "getTextSize", lpaint_getTextSize },
1184 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001185 { "getTextScaleX", lpaint_getTextScaleX },
1186 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001187 { "getTypeface", lpaint_getTypeface },
1188 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001189 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +00001190 { "getFontID", lpaint_getFontID },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001191 { "getTextAlign", lpaint_getTextAlign },
1192 { "setTextAlign", lpaint_setTextAlign },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001193 { "getStroke", lpaint_getStroke },
1194 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001195 { "getStrokeCap", lpaint_getStrokeCap },
1196 { "getStrokeJoin", lpaint_getStrokeJoin },
1197 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001198 { "getStrokeWidth", lpaint_getStrokeWidth },
1199 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001200 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001201 { "measureText", lpaint_measureText },
1202 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +00001203 { "getEffects", lpaint_getEffects },
reed22a517f2015-12-04 20:45:59 -08001204 { "getColorFilter", lpaint_getColorFilter },
1205 { "setColorFilter", lpaint_setColorFilter },
reed468b1812014-10-19 11:42:54 -07001206 { "getImageFilter", lpaint_getImageFilter },
1207 { "setImageFilter", lpaint_setImageFilter },
reed@google.com5fdc9832013-07-24 15:47:52 +00001208 { "getShader", lpaint_getShader },
reed9fbc3f32014-10-21 07:12:58 -07001209 { "setShader", lpaint_setShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001210 { "getPathEffect", lpaint_getPathEffect },
hstern0b401ce2016-08-02 09:17:59 -07001211 { "getFillPath", lpaint_getFillPath },
reed@google.com74ce6f02013-05-22 15:13:18 +00001212 { "__gc", lpaint_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001213 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001214};
1215
1216///////////////////////////////////////////////////////////////////////////////
1217
reed@google.com5fdc9832013-07-24 15:47:52 +00001218static const char* mode2string(SkShader::TileMode mode) {
1219 static const char* gNames[] = { "clamp", "repeat", "mirror" };
1220 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
1221 return gNames[mode];
1222}
1223
1224static const char* gradtype2string(SkShader::GradientType t) {
1225 static const char* gNames[] = {
1226 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
1227 };
1228 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
1229 return gNames[t];
1230}
1231
1232static int lshader_isOpaque(lua_State* L) {
1233 SkShader* shader = get_ref<SkShader>(L, 1);
1234 return shader && shader->isOpaque();
1235}
1236
Mike Reed627778d2016-09-28 17:13:38 -04001237static int lshader_isAImage(lua_State* L) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001238 SkShader* shader = get_ref<SkShader>(L, 1);
1239 if (shader) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001240 SkMatrix matrix;
1241 SkShader::TileMode modes[2];
Mike Reed627778d2016-09-28 17:13:38 -04001242 if (SkImage* image = shader->isAImage(&matrix, modes)) {
reedf5822822015-08-19 11:46:38 -07001243 lua_newtable(L);
Mike Reed627778d2016-09-28 17:13:38 -04001244 setfield_number(L, "id", image->uniqueID());
1245 setfield_number(L, "width", image->width());
1246 setfield_number(L, "height", image->height());
reedf5822822015-08-19 11:46:38 -07001247 setfield_string(L, "tileX", mode2string(modes[0]));
1248 setfield_string(L, "tileY", mode2string(modes[1]));
1249 return 1;
reed@google.com5fdc9832013-07-24 15:47:52 +00001250 }
1251 }
1252 return 0;
1253}
1254
1255static int lshader_asAGradient(lua_State* L) {
1256 SkShader* shader = get_ref<SkShader>(L, 1);
1257 if (shader) {
1258 SkShader::GradientInfo info;
1259 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001260
reed@google.com5fdc9832013-07-24 15:47:52 +00001261 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001262
reed@google.com5fdc9832013-07-24 15:47:52 +00001263 if (SkShader::kNone_GradientType != t) {
fmenozzib4f254e2016-06-28 14:03:03 -07001264 SkAutoTArray<SkScalar> pos(info.fColorCount);
1265 info.fColorOffsets = pos.get();
1266 shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001267
fmenozzib4f254e2016-06-28 14:03:03 -07001268 lua_newtable(L);
fmenozzi7f2c85e2016-07-12 09:17:39 -07001269 setfield_string(L, "type", gradtype2string(t));
1270 setfield_string(L, "tile", mode2string(info.fTileMode));
1271 setfield_number(L, "colorCount", info.fColorCount);
fmenozzib4f254e2016-06-28 14:03:03 -07001272
1273 lua_newtable(L);
1274 for (int i = 0; i < info.fColorCount; i++) {
1275 // Lua uses 1-based indexing
1276 setarray_scalar(L, i+1, pos[i]);
1277 }
1278 lua_setfield(L, -2, "positions");
1279
reed@google.com5fdc9832013-07-24 15:47:52 +00001280 return 1;
1281 }
1282 }
1283 return 0;
1284}
1285
1286static int lshader_gc(lua_State* L) {
1287 get_ref<SkShader>(L, 1)->unref();
1288 return 0;
1289}
1290
1291static const struct luaL_Reg gSkShader_Methods[] = {
1292 { "isOpaque", lshader_isOpaque },
Mike Reed627778d2016-09-28 17:13:38 -04001293 { "isAImage", lshader_isAImage },
reed@google.com5fdc9832013-07-24 15:47:52 +00001294 { "asAGradient", lshader_asAGradient },
1295 { "__gc", lshader_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001296 { nullptr, nullptr }
reed@google.com5fdc9832013-07-24 15:47:52 +00001297};
1298
1299///////////////////////////////////////////////////////////////////////////////
1300
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001301static int lpatheffect_asADash(lua_State* L) {
1302 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1303 if (pe) {
1304 SkPathEffect::DashInfo info;
1305 SkPathEffect::DashType dashType = pe->asADash(&info);
1306 if (SkPathEffect::kDash_DashType == dashType) {
1307 SkAutoTArray<SkScalar> intervals(info.fCount);
1308 info.fIntervals = intervals.get();
1309 pe->asADash(&info);
1310 SkLua(L).pushDash(info);
1311 return 1;
1312 }
1313 }
1314 return 0;
1315}
1316
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001317static int lpatheffect_gc(lua_State* L) {
1318 get_ref<SkPathEffect>(L, 1)->unref();
1319 return 0;
1320}
1321
1322static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001323 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001324 { "__gc", lpatheffect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001325 { nullptr, nullptr }
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001326};
1327
1328///////////////////////////////////////////////////////////////////////////////
1329
reed22a517f2015-12-04 20:45:59 -08001330static int lpcolorfilter_gc(lua_State* L) {
1331 get_ref<SkColorFilter>(L, 1)->unref();
1332 return 0;
1333}
1334
1335static const struct luaL_Reg gSkColorFilter_Methods[] = {
1336 { "__gc", lpcolorfilter_gc },
1337 { nullptr, nullptr }
1338};
1339
1340///////////////////////////////////////////////////////////////////////////////
1341
reed468b1812014-10-19 11:42:54 -07001342static int lpimagefilter_gc(lua_State* L) {
1343 get_ref<SkImageFilter>(L, 1)->unref();
1344 return 0;
1345}
1346
1347static const struct luaL_Reg gSkImageFilter_Methods[] = {
1348 { "__gc", lpimagefilter_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001349 { nullptr, nullptr }
reed468b1812014-10-19 11:42:54 -07001350};
1351
1352///////////////////////////////////////////////////////////////////////////////
1353
humper@google.com2815c192013-07-10 22:42:30 +00001354static int lmatrix_getType(lua_State* L) {
1355 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001356
humper@google.com2815c192013-07-10 22:42:30 +00001357 lua_newtable(L);
1358 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1359 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1360 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1361 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1362 return 1;
1363}
1364
humper@google.com0f48ee02013-07-26 15:23:43 +00001365static int lmatrix_getScaleX(lua_State* L) {
1366 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1367 return 1;
1368}
1369
1370static int lmatrix_getScaleY(lua_State* L) {
1371 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1372 return 1;
1373}
1374
1375static int lmatrix_getTranslateX(lua_State* L) {
1376 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1377 return 1;
1378}
1379
1380static int lmatrix_getTranslateY(lua_State* L) {
1381 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1382 return 1;
1383}
1384
reed7a72c672014-11-07 10:23:55 -08001385static int lmatrix_invert(lua_State* L) {
1386 lua_pushboolean(L, get_obj<SkMatrix>(L, 1)->invert(get_obj<SkMatrix>(L, 2)));
1387 return 1;
1388}
1389
1390static int lmatrix_mapXY(lua_State* L) {
1391 SkPoint pt = { lua2scalar(L, 2), lua2scalar(L, 3) };
1392 get_obj<SkMatrix>(L, 1)->mapPoints(&pt, &pt, 1);
1393 lua_pushnumber(L, pt.x());
1394 lua_pushnumber(L, pt.y());
1395 return 2;
1396}
1397
reedbdc49ae2014-10-14 09:34:52 -07001398static int lmatrix_setRectToRect(lua_State* L) {
1399 SkMatrix* matrix = get_obj<SkMatrix>(L, 1);
1400 SkRect srcR, dstR;
1401 lua2rect(L, 2, &srcR);
1402 lua2rect(L, 3, &dstR);
1403 const char* scaleToFitStr = lua_tostring(L, 4);
1404 SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit;
1405
1406 if (scaleToFitStr) {
1407 const struct {
1408 const char* fName;
1409 SkMatrix::ScaleToFit fScaleToFit;
1410 } rec[] = {
1411 { "fill", SkMatrix::kFill_ScaleToFit },
1412 { "start", SkMatrix::kStart_ScaleToFit },
1413 { "center", SkMatrix::kCenter_ScaleToFit },
1414 { "end", SkMatrix::kEnd_ScaleToFit },
1415 };
1416
1417 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
1418 if (strcmp(rec[i].fName, scaleToFitStr) == 0) {
1419 scaleToFit = rec[i].fScaleToFit;
1420 break;
1421 }
1422 }
1423 }
1424
1425 matrix->setRectToRect(srcR, dstR, scaleToFit);
1426 return 0;
1427}
1428
humper@google.com2815c192013-07-10 22:42:30 +00001429static const struct luaL_Reg gSkMatrix_Methods[] = {
1430 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001431 { "getScaleX", lmatrix_getScaleX },
1432 { "getScaleY", lmatrix_getScaleY },
1433 { "getTranslateX", lmatrix_getTranslateX },
1434 { "getTranslateY", lmatrix_getTranslateY },
reedbdc49ae2014-10-14 09:34:52 -07001435 { "setRectToRect", lmatrix_setRectToRect },
reed7a72c672014-11-07 10:23:55 -08001436 { "invert", lmatrix_invert },
1437 { "mapXY", lmatrix_mapXY },
halcanary96fcdcc2015-08-27 07:41:13 -07001438 { nullptr, nullptr }
humper@google.com2815c192013-07-10 22:42:30 +00001439};
1440
1441///////////////////////////////////////////////////////////////////////////////
1442
reed@google.com74ce6f02013-05-22 15:13:18 +00001443static int lpath_getBounds(lua_State* L) {
1444 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1445 return 1;
1446}
1447
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001448static const char* fill_type_to_str(SkPath::FillType fill) {
1449 switch (fill) {
1450 case SkPath::kEvenOdd_FillType:
1451 return "even-odd";
1452 case SkPath::kWinding_FillType:
1453 return "winding";
1454 case SkPath::kInverseEvenOdd_FillType:
1455 return "inverse-even-odd";
1456 case SkPath::kInverseWinding_FillType:
1457 return "inverse-winding";
1458 }
1459 return "unknown";
1460}
1461
1462static int lpath_getFillType(lua_State* L) {
1463 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1464 SkLua(L).pushString(fill_type_to_str(fill));
1465 return 1;
1466}
1467
1468static SkString segment_masks_to_str(uint32_t segmentMasks) {
1469 SkString result;
1470 bool first = true;
1471 if (SkPath::kLine_SegmentMask & segmentMasks) {
1472 result.append("line");
1473 first = false;
1474 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1475 }
1476 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1477 if (!first) {
1478 result.append(" ");
1479 }
1480 result.append("quad");
1481 first = false;
1482 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1483 }
1484 if (SkPath::kConic_SegmentMask & segmentMasks) {
1485 if (!first) {
1486 result.append(" ");
1487 }
1488 result.append("conic");
1489 first = false;
1490 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1491 }
1492 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1493 if (!first) {
1494 result.append(" ");
1495 }
1496 result.append("cubic");
1497 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1498 }
1499 SkASSERT(0 == segmentMasks);
1500 return result;
1501}
1502
krajcevski95498ed2014-08-18 08:02:33 -07001503static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001504 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1505 SkLua(L).pushString(segment_masks_to_str(segMasks));
1506 return 1;
1507}
1508
1509static int lpath_isConvex(lua_State* L) {
1510 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1511 SkLua(L).pushBool(isConvex);
1512 return 1;
1513}
1514
reed@google.com74ce6f02013-05-22 15:13:18 +00001515static int lpath_isEmpty(lua_State* L) {
1516 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1517 return 1;
1518}
1519
1520static int lpath_isRect(lua_State* L) {
1521 SkRect r;
1522 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1523 int ret_count = 1;
1524 lua_pushboolean(L, pred);
1525 if (pred) {
1526 SkLua(L).pushRect(r);
1527 ret_count += 1;
1528 }
1529 return ret_count;
1530}
1531
1532static const char* dir2string(SkPath::Direction dir) {
1533 static const char* gStr[] = {
1534 "unknown", "cw", "ccw"
1535 };
1536 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1537 return gStr[dir];
1538}
1539
caryclark95bc5f32015-04-08 08:34:15 -07001540static int lpath_isNestedFillRects(lua_State* L) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001541 SkRect rects[2];
1542 SkPath::Direction dirs[2];
caryclark95bc5f32015-04-08 08:34:15 -07001543 bool pred = get_obj<SkPath>(L, 1)->isNestedFillRects(rects, dirs);
reed@google.com74ce6f02013-05-22 15:13:18 +00001544 int ret_count = 1;
1545 lua_pushboolean(L, pred);
1546 if (pred) {
1547 SkLua lua(L);
1548 lua.pushRect(rects[0]);
1549 lua.pushRect(rects[1]);
1550 lua_pushstring(L, dir2string(dirs[0]));
1551 lua_pushstring(L, dir2string(dirs[0]));
1552 ret_count += 4;
1553 }
1554 return ret_count;
1555}
1556
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001557static int lpath_countPoints(lua_State* L) {
1558 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1559 return 1;
1560}
1561
hstern0b401ce2016-08-02 09:17:59 -07001562static int lpath_getVerbs(lua_State* L) {
1563 const SkPath* path = get_obj<SkPath>(L, 1);
1564 SkPath::Iter iter(*path, false);
1565 SkPoint pts[4];
1566
1567 lua_newtable(L);
1568
1569 bool done = false;
1570 int i = 0;
1571 do {
1572 switch (iter.next(pts, true)) {
1573 case SkPath::kMove_Verb:
1574 setarray_string(L, ++i, "move");
1575 break;
1576 case SkPath::kClose_Verb:
1577 setarray_string(L, ++i, "close");
1578 break;
1579 case SkPath::kLine_Verb:
1580 setarray_string(L, ++i, "line");
1581 break;
1582 case SkPath::kQuad_Verb:
1583 setarray_string(L, ++i, "quad");
1584 break;
1585 case SkPath::kConic_Verb:
1586 setarray_string(L, ++i, "conic");
1587 break;
1588 case SkPath::kCubic_Verb:
1589 setarray_string(L, ++i, "cubic");
1590 break;
1591 case SkPath::kDone_Verb:
1592 setarray_string(L, ++i, "done");
1593 done = true;
1594 break;
1595 }
1596 } while (!done);
1597
1598 return 1;
1599}
1600
reed@google.com74ce6f02013-05-22 15:13:18 +00001601static int lpath_reset(lua_State* L) {
1602 get_obj<SkPath>(L, 1)->reset();
1603 return 0;
1604}
1605
1606static int lpath_moveTo(lua_State* L) {
1607 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1608 return 0;
1609}
1610
1611static int lpath_lineTo(lua_State* L) {
1612 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1613 return 0;
1614}
1615
1616static int lpath_quadTo(lua_State* L) {
1617 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1618 lua2scalar(L, 4), lua2scalar(L, 5));
1619 return 0;
1620}
1621
1622static int lpath_cubicTo(lua_State* L) {
1623 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1624 lua2scalar(L, 4), lua2scalar(L, 5),
1625 lua2scalar(L, 6), lua2scalar(L, 7));
1626 return 0;
1627}
1628
1629static int lpath_close(lua_State* L) {
1630 get_obj<SkPath>(L, 1)->close();
1631 return 0;
1632}
1633
1634static int lpath_gc(lua_State* L) {
1635 get_obj<SkPath>(L, 1)->~SkPath();
1636 return 0;
1637}
1638
1639static const struct luaL_Reg gSkPath_Methods[] = {
1640 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001641 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001642 { "getSegmentTypes", lpath_getSegmentTypes },
hstern0b401ce2016-08-02 09:17:59 -07001643 { "getVerbs", lpath_getVerbs },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001644 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001645 { "isEmpty", lpath_isEmpty },
1646 { "isRect", lpath_isRect },
caryclark95bc5f32015-04-08 08:34:15 -07001647 { "isNestedFillRects", lpath_isNestedFillRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001648 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001649 { "reset", lpath_reset },
1650 { "moveTo", lpath_moveTo },
1651 { "lineTo", lpath_lineTo },
1652 { "quadTo", lpath_quadTo },
1653 { "cubicTo", lpath_cubicTo },
1654 { "close", lpath_close },
1655 { "__gc", lpath_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001656 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001657};
1658
1659///////////////////////////////////////////////////////////////////////////////
1660
1661static const char* rrect_type(const SkRRect& rr) {
1662 switch (rr.getType()) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001663 case SkRRect::kEmpty_Type: return "empty";
1664 case SkRRect::kRect_Type: return "rect";
1665 case SkRRect::kOval_Type: return "oval";
1666 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001667 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001668 case SkRRect::kComplex_Type: return "complex";
1669 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001670 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001671 return "";
1672}
1673
1674static int lrrect_rect(lua_State* L) {
1675 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1676 return 1;
1677}
1678
1679static int lrrect_type(lua_State* L) {
1680 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1681 return 1;
1682}
1683
1684static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001685 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001686 SkVector v;
1687 if (corner < 0 || corner > 3) {
1688 SkDebugf("bad corner index %d", corner);
1689 v.set(0, 0);
1690 } else {
1691 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1692 }
1693 lua_pushnumber(L, v.fX);
1694 lua_pushnumber(L, v.fY);
1695 return 2;
1696}
1697
1698static int lrrect_gc(lua_State* L) {
1699 get_obj<SkRRect>(L, 1)->~SkRRect();
1700 return 0;
1701}
1702
1703static const struct luaL_Reg gSkRRect_Methods[] = {
1704 { "rect", lrrect_rect },
1705 { "type", lrrect_type },
1706 { "radii", lrrect_radii },
1707 { "__gc", lrrect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001708 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001709};
1710
1711///////////////////////////////////////////////////////////////////////////////
1712
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001713static int limage_width(lua_State* L) {
1714 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1715 return 1;
1716}
1717
1718static int limage_height(lua_State* L) {
1719 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1720 return 1;
1721}
1722
reed7a72c672014-11-07 10:23:55 -08001723static int limage_newShader(lua_State* L) {
1724 SkShader::TileMode tmode = SkShader::kClamp_TileMode;
halcanary96fcdcc2015-08-27 07:41:13 -07001725 const SkMatrix* localM = nullptr;
reed5671c5b2016-03-09 14:47:34 -08001726 push_ref(L, get_ref<SkImage>(L, 1)->makeShader(tmode, tmode, localM));
reed7a72c672014-11-07 10:23:55 -08001727 return 1;
1728}
1729
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001730static int limage_gc(lua_State* L) {
1731 get_ref<SkImage>(L, 1)->unref();
1732 return 0;
1733}
1734
1735static const struct luaL_Reg gSkImage_Methods[] = {
1736 { "width", limage_width },
1737 { "height", limage_height },
reed7a72c672014-11-07 10:23:55 -08001738 { "newShader", limage_newShader },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001739 { "__gc", limage_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001740 { nullptr, nullptr }
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001741};
1742
1743///////////////////////////////////////////////////////////////////////////////
1744
reed485557f2014-10-12 10:36:47 -07001745static int lsurface_width(lua_State* L) {
1746 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1747 return 1;
1748}
1749
1750static int lsurface_height(lua_State* L) {
1751 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1752 return 1;
1753}
1754
1755static int lsurface_getCanvas(lua_State* L) {
1756 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001757 if (nullptr == canvas) {
reed485557f2014-10-12 10:36:47 -07001758 lua_pushnil(L);
1759 } else {
Mike Reed5df49342016-11-12 08:06:55 -06001760 push_ptr(L, canvas);
reed485557f2014-10-12 10:36:47 -07001761 // note: we don't unref canvas, since getCanvas did not ref it.
1762 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1763 // the real owner (the surface) go away, but still hold onto the canvas?
1764 // *really* we want to sort of ref the surface again, but have the native object
1765 // know that it is supposed to be treated as a canvas...
1766 }
1767 return 1;
1768}
1769
1770static int lsurface_newImageSnapshot(lua_State* L) {
reed9ce9d672016-03-17 10:51:11 -07001771 sk_sp<SkImage> image = get_ref<SkSurface>(L, 1)->makeImageSnapshot();
1772 if (!image) {
reed485557f2014-10-12 10:36:47 -07001773 lua_pushnil(L);
1774 } else {
reed9ce9d672016-03-17 10:51:11 -07001775 push_ref(L, image);
reed485557f2014-10-12 10:36:47 -07001776 }
1777 return 1;
1778}
1779
1780static int lsurface_newSurface(lua_State* L) {
1781 int width = lua2int_def(L, 2, 0);
reed96affcd2014-10-13 12:38:04 -07001782 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -07001783 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -07001784 auto surface = get_ref<SkSurface>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -07001785 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07001786 lua_pushnil(L);
1787 } else {
reede8f30622016-03-23 18:59:25 -07001788 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07001789 }
1790 return 1;
1791}
1792
1793static int lsurface_gc(lua_State* L) {
1794 get_ref<SkSurface>(L, 1)->unref();
1795 return 0;
1796}
1797
1798static const struct luaL_Reg gSkSurface_Methods[] = {
1799 { "width", lsurface_width },
1800 { "height", lsurface_height },
1801 { "getCanvas", lsurface_getCanvas },
1802 { "newImageSnapshot", lsurface_newImageSnapshot },
1803 { "newSurface", lsurface_newSurface },
1804 { "__gc", lsurface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001805 { nullptr, nullptr }
reed485557f2014-10-12 10:36:47 -07001806};
1807
1808///////////////////////////////////////////////////////////////////////////////
1809
reed96affcd2014-10-13 12:38:04 -07001810static int lpicturerecorder_beginRecording(lua_State* L) {
1811 const SkScalar w = lua2scalar_def(L, 2, -1);
1812 const SkScalar h = lua2scalar_def(L, 3, -1);
1813 if (w <= 0 || h <= 0) {
1814 lua_pushnil(L);
1815 return 1;
1816 }
1817
1818 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
halcanary96fcdcc2015-08-27 07:41:13 -07001819 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001820 lua_pushnil(L);
1821 return 1;
1822 }
1823
Mike Reed5df49342016-11-12 08:06:55 -06001824 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001825 return 1;
1826}
1827
1828static int lpicturerecorder_getCanvas(lua_State* L) {
1829 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001830 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001831 lua_pushnil(L);
1832 return 1;
1833 }
Mike Reed5df49342016-11-12 08:06:55 -06001834 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001835 return 1;
1836}
1837
1838static int lpicturerecorder_endRecording(lua_State* L) {
reedca2622b2016-03-18 07:25:55 -07001839 sk_sp<SkPicture> pic = get_obj<SkPictureRecorder>(L, 1)->finishRecordingAsPicture();
1840 if (!pic) {
reed96affcd2014-10-13 12:38:04 -07001841 lua_pushnil(L);
1842 return 1;
1843 }
reedca2622b2016-03-18 07:25:55 -07001844 push_ref(L, std::move(pic));
reed96affcd2014-10-13 12:38:04 -07001845 return 1;
1846}
1847
1848static int lpicturerecorder_gc(lua_State* L) {
1849 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1850 return 0;
1851}
1852
1853static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1854 { "beginRecording", lpicturerecorder_beginRecording },
1855 { "getCanvas", lpicturerecorder_getCanvas },
1856 { "endRecording", lpicturerecorder_endRecording },
1857 { "__gc", lpicturerecorder_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001858 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001859};
1860
1861///////////////////////////////////////////////////////////////////////////////
1862
1863static int lpicture_width(lua_State* L) {
1864 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1865 return 1;
1866}
1867
1868static int lpicture_height(lua_State* L) {
1869 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1870 return 1;
1871}
1872
1873static int lpicture_gc(lua_State* L) {
1874 get_ref<SkPicture>(L, 1)->unref();
1875 return 0;
1876}
1877
1878static const struct luaL_Reg gSkPicture_Methods[] = {
1879 { "width", lpicture_width },
1880 { "height", lpicture_height },
1881 { "__gc", lpicture_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001882 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001883};
1884
1885///////////////////////////////////////////////////////////////////////////////
1886
reed1b6ab442014-11-03 19:55:41 -08001887static int ltextblob_bounds(lua_State* L) {
1888 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
1889 return 1;
1890}
1891
1892static int ltextblob_gc(lua_State* L) {
1893 SkSafeUnref(get_ref<SkTextBlob>(L, 1));
1894 return 0;
1895}
1896
1897static const struct luaL_Reg gSkTextBlob_Methods[] = {
1898 { "bounds", ltextblob_bounds },
1899 { "__gc", ltextblob_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001900 { nullptr, nullptr }
reed1b6ab442014-11-03 19:55:41 -08001901};
1902
1903///////////////////////////////////////////////////////////////////////////////
1904
reed36c9c112014-11-04 10:58:42 -08001905static int ltypeface_getFamilyName(lua_State* L) {
1906 SkString str;
1907 get_ref<SkTypeface>(L, 1)->getFamilyName(&str);
1908 lua_pushstring(L, str.c_str());
1909 return 1;
1910}
1911
1912static int ltypeface_getStyle(lua_State* L) {
1913 lua_pushnumber(L, (double)get_ref<SkTypeface>(L, 1)->style());
1914 return 1;
1915}
1916
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001917static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001918 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001919 return 0;
1920}
1921
1922static const struct luaL_Reg gSkTypeface_Methods[] = {
reed36c9c112014-11-04 10:58:42 -08001923 { "getFamilyName", ltypeface_getFamilyName },
1924 { "getStyle", ltypeface_getStyle },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001925 { "__gc", ltypeface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001926 { nullptr, nullptr }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001927};
1928
1929///////////////////////////////////////////////////////////////////////////////
1930
reed@google.com74ce6f02013-05-22 15:13:18 +00001931class AutoCallLua {
1932public:
1933 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1934 lua_getglobal(L, func);
1935 if (!lua_isfunction(L, -1)) {
1936 int t = lua_type(L, -1);
1937 SkDebugf("--- expected function %d\n", t);
1938 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001939
reed@google.com74ce6f02013-05-22 15:13:18 +00001940 lua_newtable(L);
1941 setfield_string(L, "verb", verb);
1942 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001943
reed@google.com74ce6f02013-05-22 15:13:18 +00001944 ~AutoCallLua() {
1945 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1946 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1947 }
1948 lua_settop(fL, -1);
1949 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001950
reed@google.com74ce6f02013-05-22 15:13:18 +00001951private:
1952 lua_State* fL;
1953};
1954
1955#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1956
1957///////////////////////////////////////////////////////////////////////////////
1958
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001959static int lsk_newDocumentPDF(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001960 const char* file = nullptr;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001961 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001962 file = lua_tolstring(L, 1, nullptr);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001963 }
1964
halcanary676ab682016-05-03 12:10:04 -07001965 sk_sp<SkDocument> doc = SkDocument::MakePDF(file);
halcanary96fcdcc2015-08-27 07:41:13 -07001966 if (nullptr == doc) {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001967 // do I need to push a nil on the stack and return 1?
1968 return 0;
1969 } else {
halcanary676ab682016-05-03 12:10:04 -07001970 push_ref(L, std::move(doc));
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001971 return 1;
1972 }
1973}
1974
reed468b1812014-10-19 11:42:54 -07001975static int lsk_newBlurImageFilter(lua_State* L) {
1976 SkScalar sigmaX = lua2scalar_def(L, 1, 0);
1977 SkScalar sigmaY = lua2scalar_def(L, 2, 0);
robertphillips6e7025a2016-04-04 04:31:25 -07001978 sk_sp<SkImageFilter> imf(SkBlurImageFilter::Make(sigmaX, sigmaY, nullptr));
1979 if (!imf) {
reed468b1812014-10-19 11:42:54 -07001980 lua_pushnil(L);
1981 } else {
robertphillips6e7025a2016-04-04 04:31:25 -07001982 push_ref(L, std::move(imf));
reed9fbc3f32014-10-21 07:12:58 -07001983 }
1984 return 1;
1985}
1986
1987static int lsk_newLinearGradient(lua_State* L) {
1988 SkScalar x0 = lua2scalar_def(L, 1, 0);
1989 SkScalar y0 = lua2scalar_def(L, 2, 0);
1990 SkColor c0 = lua2color(L, 3);
1991 SkScalar x1 = lua2scalar_def(L, 4, 0);
1992 SkScalar y1 = lua2scalar_def(L, 5, 0);
1993 SkColor c1 = lua2color(L, 6);
1994
1995 SkPoint pts[] = { { x0, y0 }, { x1, y1 } };
1996 SkColor colors[] = { c0, c1 };
robertphillips6e7025a2016-04-04 04:31:25 -07001997 sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
1998 SkShader::kClamp_TileMode));
reed2ad1aa62016-03-09 09:50:50 -08001999 if (!s) {
reed9fbc3f32014-10-21 07:12:58 -07002000 lua_pushnil(L);
2001 } else {
reed2ad1aa62016-03-09 09:50:50 -08002002 push_ref(L, std::move(s));
reed468b1812014-10-19 11:42:54 -07002003 }
2004 return 1;
2005}
2006
reedbdc49ae2014-10-14 09:34:52 -07002007static int lsk_newMatrix(lua_State* L) {
2008 push_new<SkMatrix>(L)->reset();
2009 return 1;
2010}
2011
reed@google.com3597b732013-05-22 20:12:50 +00002012static int lsk_newPaint(lua_State* L) {
2013 push_new<SkPaint>(L);
2014 return 1;
2015}
2016
2017static int lsk_newPath(lua_State* L) {
2018 push_new<SkPath>(L);
2019 return 1;
2020}
2021
reed96affcd2014-10-13 12:38:04 -07002022static int lsk_newPictureRecorder(lua_State* L) {
2023 push_new<SkPictureRecorder>(L);
2024 return 1;
2025}
2026
reed@google.com3597b732013-05-22 20:12:50 +00002027static int lsk_newRRect(lua_State* L) {
reedbdc49ae2014-10-14 09:34:52 -07002028 push_new<SkRRect>(L)->setEmpty();
reed@google.com3597b732013-05-22 20:12:50 +00002029 return 1;
2030}
2031
reed1b6ab442014-11-03 19:55:41 -08002032#include "SkTextBox.h"
2033// Sk.newTextBlob(text, rect, paint)
2034static int lsk_newTextBlob(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07002035 const char* text = lua_tolstring(L, 1, nullptr);
reed1b6ab442014-11-03 19:55:41 -08002036 SkRect bounds;
2037 lua2rect(L, 2, &bounds);
2038 const SkPaint& paint = *get_obj<SkPaint>(L, 3);
2039
2040 SkTextBox box;
2041 box.setMode(SkTextBox::kLineBreak_Mode);
2042 box.setBox(bounds);
2043 box.setText(text, strlen(text), paint);
2044
2045 SkScalar newBottom;
fmalita37283c22016-09-13 10:00:23 -07002046 push_ref<SkTextBlob>(L, box.snapshotTextBlob(&newBottom));
reed1b6ab442014-11-03 19:55:41 -08002047 SkLua(L).pushScalar(newBottom);
2048 return 2;
2049}
2050
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002051static int lsk_newTypeface(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07002052 const char* name = nullptr;
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002053 int style = SkTypeface::kNormal;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00002054
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002055 int count = lua_gettop(L);
2056 if (count > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002057 name = lua_tolstring(L, 1, nullptr);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002058 if (count > 1 && lua_isnumber(L, 2)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002059 style = lua_tointegerx(L, 2, nullptr) & SkTypeface::kBoldItalic;
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002060 }
2061 }
2062
mbocee6a9912016-05-31 11:42:36 -07002063 sk_sp<SkTypeface> face(SkTypeface::MakeFromName(name, SkFontStyle::FromOldStyle(style)));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002064// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
halcanary96fcdcc2015-08-27 07:41:13 -07002065 if (nullptr == face) {
bungeman13b9c952016-05-12 10:09:30 -07002066 face = SkTypeface::MakeDefault();
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002067 }
bungeman13b9c952016-05-12 10:09:30 -07002068 push_ref(L, std::move(face));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002069 return 1;
2070}
reed@google.com3597b732013-05-22 20:12:50 +00002071
reed485557f2014-10-12 10:36:47 -07002072static int lsk_newRasterSurface(lua_State* L) {
reed7b864662014-11-04 13:24:47 -08002073 int width = lua2int_def(L, 1, 0);
reed485557f2014-10-12 10:36:47 -07002074 int height = lua2int_def(L, 2, 0);
2075 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
robertphillips702edbd2015-06-23 06:26:08 -07002076 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
reede8f30622016-03-23 18:59:25 -07002077 auto surface = SkSurface::MakeRaster(info, &props);
halcanary96fcdcc2015-08-27 07:41:13 -07002078 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07002079 lua_pushnil(L);
2080 } else {
reede8f30622016-03-23 18:59:25 -07002081 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07002082 }
2083 return 1;
2084}
2085
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002086static int lsk_loadImage(lua_State* L) {
2087 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002088 const char* name = lua_tolstring(L, 1, nullptr);
reed9ce9d672016-03-17 10:51:11 -07002089 sk_sp<SkData> data(SkData::MakeFromFileName(name));
2090 if (data) {
2091 auto image = SkImage::MakeFromEncoded(std::move(data));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002092 if (image) {
reed9ce9d672016-03-17 10:51:11 -07002093 push_ref(L, std::move(image));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002094 return 1;
2095 }
2096 }
2097 }
2098 return 0;
2099}
2100
reed@google.com3597b732013-05-22 20:12:50 +00002101static void register_Sk(lua_State* L) {
2102 lua_newtable(L);
2103 lua_pushvalue(L, -1);
2104 lua_setglobal(L, "Sk");
2105 // the Sk table is still on top
2106
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00002107 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002108 setfield_function(L, "loadImage", lsk_loadImage);
reed468b1812014-10-19 11:42:54 -07002109 setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
reed9fbc3f32014-10-21 07:12:58 -07002110 setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
reedbdc49ae2014-10-14 09:34:52 -07002111 setfield_function(L, "newMatrix", lsk_newMatrix);
reed@google.com3597b732013-05-22 20:12:50 +00002112 setfield_function(L, "newPaint", lsk_newPaint);
2113 setfield_function(L, "newPath", lsk_newPath);
reed96affcd2014-10-13 12:38:04 -07002114 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
reed@google.com3597b732013-05-22 20:12:50 +00002115 setfield_function(L, "newRRect", lsk_newRRect);
reed485557f2014-10-12 10:36:47 -07002116 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
reed1b6ab442014-11-03 19:55:41 -08002117 setfield_function(L, "newTextBlob", lsk_newTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002118 setfield_function(L, "newTypeface", lsk_newTypeface);
reed@google.com3597b732013-05-22 20:12:50 +00002119 lua_pop(L, 1); // pop off the Sk table
2120}
2121
reed@google.com74ce6f02013-05-22 15:13:18 +00002122#define REG_CLASS(L, C) \
2123 do { \
reed@google.com3597b732013-05-22 20:12:50 +00002124 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00002125 lua_pushvalue(L, -1); \
2126 lua_setfield(L, -2, "__index"); \
2127 luaL_setfuncs(L, g##C##_Methods, 0); \
2128 lua_pop(L, 1); /* pop off the meta-table */ \
2129 } while (0)
2130
2131void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00002132 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00002133 REG_CLASS(L, SkCanvas);
reed22a517f2015-12-04 20:45:59 -08002134 REG_CLASS(L, SkColorFilter);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00002135 REG_CLASS(L, SkDocument);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002136 REG_CLASS(L, SkImage);
reed468b1812014-10-19 11:42:54 -07002137 REG_CLASS(L, SkImageFilter);
reed1b6ab442014-11-03 19:55:41 -08002138 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00002139 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00002140 REG_CLASS(L, SkPath);
2141 REG_CLASS(L, SkPathEffect);
reed96affcd2014-10-13 12:38:04 -07002142 REG_CLASS(L, SkPicture);
2143 REG_CLASS(L, SkPictureRecorder);
reed@google.com74ce6f02013-05-22 15:13:18 +00002144 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00002145 REG_CLASS(L, SkShader);
reed485557f2014-10-12 10:36:47 -07002146 REG_CLASS(L, SkSurface);
reed1b6ab442014-11-03 19:55:41 -08002147 REG_CLASS(L, SkTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002148 REG_CLASS(L, SkTypeface);
reed@google.com74ce6f02013-05-22 15:13:18 +00002149}
zachr@google.com28c27c82013-06-20 17:15:05 +00002150
reed@google.com7bce9982013-06-20 17:40:21 +00002151extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00002152extern "C" int luaopen_skia(lua_State* L) {
2153 SkLua::Load(L);
2154 return 0;
2155}