blob: 074493ce266b8e04a7e5fca362c996f3a0776461 [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
Mike Reed4f364fd2017-01-19 14:34:51 -050011//#include "GrReducedClip.h"
bsalomon@google.com4ebe3822014-02-26 20:22:32 +000012#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"
Ben Wagnerc6c10b42017-08-07 09:56:21 -040018#include "SkFontStyle.h"
reed9fbc3f32014-10-21 07:12:58 -070019#include "SkGradientShader.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000020#include "SkImage.h"
Mike Reed7ff6ca52018-01-08 14:45:31 -050021#include "SkMakeUnique.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000022#include "SkMatrix.h"
Hal Canary23564b92018-09-07 14:33:14 -040023#include "SkPDFDocument.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000024#include "SkPaint.h"
25#include "SkPath.h"
reed96affcd2014-10-13 12:38:04 -070026#include "SkPictureRecorder.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000027#include "SkRRect.h"
Herb Derby1724db12018-05-22 12:01:50 -040028#include "SkShaper.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000029#include "SkString.h"
reed485557f2014-10-12 10:36:47 -070030#include "SkSurface.h"
fmalitab7425172014-08-26 07:56:44 -070031#include "SkTextBlob.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040032#include "SkTo.h"
reed@google.come3823fd2013-05-30 18:55:14 +000033#include "SkTypeface.h"
Mike Klein79aea6a2018-06-11 10:45:26 -040034#include <new>
reed@google.com74ce6f02013-05-22 15:13:18 +000035
36extern "C" {
reed@google.com3597b732013-05-22 20:12:50 +000037 #include "lua.h"
38 #include "lualib.h"
39 #include "lauxlib.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000040}
41
Mike Reed7ff6ca52018-01-08 14:45:31 -050042struct DocHolder {
43 sk_sp<SkDocument> fDoc;
44 std::unique_ptr<SkWStream> fStream;
45};
46
reed@google.comfd345872013-05-22 20:53:42 +000047// return the metatable name for a given class
reed@google.com3597b732013-05-22 20:12:50 +000048template <typename T> const char* get_mtname();
reed@google.comfd345872013-05-22 20:53:42 +000049#define DEF_MTNAME(T) \
50 template <> const char* get_mtname<T>() { \
51 return #T "_LuaMetaTableName"; \
52 }
53
54DEF_MTNAME(SkCanvas)
reed22a517f2015-12-04 20:45:59 -080055DEF_MTNAME(SkColorFilter)
Mike Reed7ff6ca52018-01-08 14:45:31 -050056DEF_MTNAME(DocHolder)
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000057DEF_MTNAME(SkImage)
reed468b1812014-10-19 11:42:54 -070058DEF_MTNAME(SkImageFilter)
reed@google.comfd345872013-05-22 20:53:42 +000059DEF_MTNAME(SkMatrix)
60DEF_MTNAME(SkRRect)
61DEF_MTNAME(SkPath)
62DEF_MTNAME(SkPaint)
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +000063DEF_MTNAME(SkPathEffect)
reed96affcd2014-10-13 12:38:04 -070064DEF_MTNAME(SkPicture)
65DEF_MTNAME(SkPictureRecorder)
reed@google.com5fdc9832013-07-24 15:47:52 +000066DEF_MTNAME(SkShader)
reed485557f2014-10-12 10:36:47 -070067DEF_MTNAME(SkSurface)
fmalitab7425172014-08-26 07:56:44 -070068DEF_MTNAME(SkTextBlob)
mike@reedtribe.orge6469f12013-06-08 03:15:47 +000069DEF_MTNAME(SkTypeface)
Ben Wagnerc6c10b42017-08-07 09:56:21 -040070DEF_MTNAME(SkFontStyle)
reed@google.com74ce6f02013-05-22 15:13:18 +000071
Ben Wagnerc6c10b42017-08-07 09:56:21 -040072template <typename T, typename... Args> T* push_new(lua_State* L, Args&&... args) {
reed@google.com3597b732013-05-22 20:12:50 +000073 T* addr = (T*)lua_newuserdata(L, sizeof(T));
Ben Wagnerc6c10b42017-08-07 09:56:21 -040074 new (addr) T(std::forward<Args>(args)...);
reed@google.com3597b732013-05-22 20:12:50 +000075 luaL_getmetatable(L, get_mtname<T>());
76 lua_setmetatable(L, -2);
77 return addr;
78}
reed@google.com74ce6f02013-05-22 15:13:18 +000079
80template <typename T> void push_obj(lua_State* L, const T& obj) {
81 new (lua_newuserdata(L, sizeof(T))) T(obj);
reed@google.com3597b732013-05-22 20:12:50 +000082 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000083 lua_setmetatable(L, -2);
84}
85
Mike Reed5df49342016-11-12 08:06:55 -060086template <typename T> T* push_ptr(lua_State* L, T* ptr) {
87 *(T**)lua_newuserdata(L, sizeof(T*)) = ptr;
88 luaL_getmetatable(L, get_mtname<T>());
89 lua_setmetatable(L, -2);
90 return ptr;
91}
92
reed9fbc3f32014-10-21 07:12:58 -070093template <typename T> T* push_ref(lua_State* L, T* ref) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +000094 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
reed@google.com3597b732013-05-22 20:12:50 +000095 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000096 lua_setmetatable(L, -2);
reed9fbc3f32014-10-21 07:12:58 -070097 return ref;
reed@google.com74ce6f02013-05-22 15:13:18 +000098}
99
reed2ad1aa62016-03-09 09:50:50 -0800100template <typename T> void push_ref(lua_State* L, sk_sp<T> sp) {
101 *(T**)lua_newuserdata(L, sizeof(T*)) = sp.release();
102 luaL_getmetatable(L, get_mtname<T>());
103 lua_setmetatable(L, -2);
104}
105
reed@google.com74ce6f02013-05-22 15:13:18 +0000106template <typename T> T* get_ref(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +0000107 return *(T**)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +0000108}
109
110template <typename T> T* get_obj(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +0000111 return (T*)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +0000112}
113
reed@google.com88c9ec92013-05-22 15:43:21 +0000114static bool lua2bool(lua_State* L, int index) {
115 return !!lua_toboolean(L, index);
116}
117
reed@google.com74ce6f02013-05-22 15:13:18 +0000118///////////////////////////////////////////////////////////////////////////////
119
reed@google.com3597b732013-05-22 20:12:50 +0000120SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
121 fL = luaL_newstate();
122 luaL_openlibs(fL);
123 SkLua::Load(fL);
124}
125
126SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
127
128SkLua::~SkLua() {
129 if (fWeOwnL) {
130 if (fTermCode.size() > 0) {
131 lua_getglobal(fL, fTermCode.c_str());
132 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
133 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
134 }
135 }
136 lua_close(fL);
137 }
138}
139
140bool SkLua::runCode(const char code[]) {
141 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
142 if (err) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000143 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
reed@google.com3597b732013-05-22 20:12:50 +0000144 return false;
145 }
146 return true;
147}
148
149bool SkLua::runCode(const void* code, size_t size) {
150 SkString str((const char*)code, size);
151 return this->runCode(str.c_str());
152}
153
154///////////////////////////////////////////////////////////////////////////////
155
156#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
157
reed@google.com29563872013-07-10 21:23:49 +0000158static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
159 if (pred) {
160 lua_pushboolean(L, true);
161 lua_setfield(L, -2, key);
162 }
163}
164
reed@google.com74ce6f02013-05-22 15:13:18 +0000165static void setfield_string(lua_State* L, const char key[], const char value[]) {
166 lua_pushstring(L, value);
167 lua_setfield(L, -2, key);
168}
169
170static void setfield_number(lua_State* L, const char key[], double value) {
171 lua_pushnumber(L, value);
172 lua_setfield(L, -2, key);
173}
174
humper@google.com2815c192013-07-10 22:42:30 +0000175static void setfield_boolean(lua_State* L, const char key[], bool value) {
176 lua_pushboolean(L, value);
177 lua_setfield(L, -2, key);
178}
179
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000180static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
181 setfield_number(L, key, SkScalarToLua(value));
182}
183
reed@google.com3597b732013-05-22 20:12:50 +0000184static void setfield_function(lua_State* L,
185 const char key[], lua_CFunction value) {
186 lua_pushcfunction(L, value);
187 lua_setfield(L, -2, key);
reed@google.com74ce6f02013-05-22 15:13:18 +0000188}
189
reed7a72c672014-11-07 10:23:55 -0800190static int lua2int_def(lua_State* L, int index, int defaultValue) {
191 if (lua_isnumber(L, index)) {
192 return (int)lua_tonumber(L, index);
193 } else {
194 return defaultValue;
195 }
196}
197
198static SkScalar lua2scalar(lua_State* L, int index) {
199 SkASSERT(lua_isnumber(L, index));
200 return SkLuaToScalar(lua_tonumber(L, index));
201}
202
203static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
204 if (lua_isnumber(L, index)) {
205 return SkLuaToScalar(lua_tonumber(L, index));
206 } else {
207 return defaultValue;
208 }
209}
210
211static SkScalar getarray_scalar(lua_State* L, int stackIndex, int arrayIndex) {
212 SkASSERT(lua_istable(L, stackIndex));
213 lua_rawgeti(L, stackIndex, arrayIndex);
mtklein8aacf202014-12-18 13:29:54 -0800214
reed7a72c672014-11-07 10:23:55 -0800215 SkScalar value = lua2scalar(L, -1);
216 lua_pop(L, 1);
217 return value;
218}
219
220static void getarray_scalars(lua_State* L, int stackIndex, SkScalar dst[], int count) {
221 for (int i = 0; i < count; ++i) {
222 dst[i] = getarray_scalar(L, stackIndex, i + 1);
223 }
224}
225
226static void getarray_points(lua_State* L, int stackIndex, SkPoint pts[], int count) {
227 getarray_scalars(L, stackIndex, &pts[0].fX, count * 2);
228}
229
reed@google.come3823fd2013-05-30 18:55:14 +0000230static void setarray_number(lua_State* L, int index, double value) {
231 lua_pushnumber(L, value);
232 lua_rawseti(L, -2, index);
233}
234
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000235static void setarray_scalar(lua_State* L, int index, SkScalar value) {
236 setarray_number(L, index, SkScalarToLua(value));
237}
238
hstern0b401ce2016-08-02 09:17:59 -0700239static void setarray_string(lua_State* L, int index, const char str[]) {
240 lua_pushstring(L, str);
241 lua_rawseti(L, -2, index);
242}
243
reed@google.com74ce6f02013-05-22 15:13:18 +0000244void SkLua::pushBool(bool value, const char key[]) {
245 lua_pushboolean(fL, value);
246 CHECK_SETFIELD(key);
247}
248
249void SkLua::pushString(const char str[], const char key[]) {
250 lua_pushstring(fL, str);
251 CHECK_SETFIELD(key);
252}
253
reed@google.come3823fd2013-05-30 18:55:14 +0000254void SkLua::pushString(const char str[], size_t length, const char key[]) {
255 // TODO: how to do this w/o making a copy?
256 SkString s(str, length);
257 lua_pushstring(fL, s.c_str());
258 CHECK_SETFIELD(key);
259}
260
reed@google.com74ce6f02013-05-22 15:13:18 +0000261void SkLua::pushString(const SkString& str, const char key[]) {
262 lua_pushstring(fL, str.c_str());
263 CHECK_SETFIELD(key);
264}
265
266void SkLua::pushColor(SkColor color, const char key[]) {
267 lua_newtable(fL);
268 setfield_number(fL, "a", SkColorGetA(color) / 255.0);
269 setfield_number(fL, "r", SkColorGetR(color) / 255.0);
270 setfield_number(fL, "g", SkColorGetG(color) / 255.0);
271 setfield_number(fL, "b", SkColorGetB(color) / 255.0);
272 CHECK_SETFIELD(key);
273}
274
reed@google.come3823fd2013-05-30 18:55:14 +0000275void SkLua::pushU32(uint32_t value, const char key[]) {
276 lua_pushnumber(fL, (double)value);
277 CHECK_SETFIELD(key);
278}
279
reed@google.com74ce6f02013-05-22 15:13:18 +0000280void SkLua::pushScalar(SkScalar value, const char key[]) {
281 lua_pushnumber(fL, SkScalarToLua(value));
282 CHECK_SETFIELD(key);
283}
284
reed@google.come3823fd2013-05-30 18:55:14 +0000285void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
286 lua_newtable(fL);
287 for (int i = 0; i < count; ++i) {
288 // make it base-1 to match lua convention
289 setarray_number(fL, i + 1, (double)array[i]);
290 }
291 CHECK_SETFIELD(key);
292}
293
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000294void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
295 lua_newtable(fL);
296 for (int i = 0; i < count; ++i) {
297 // make it base-1 to match lua convention
298 lua_newtable(fL);
299 this->pushScalar(array[i].fX, "x");
300 this->pushScalar(array[i].fY, "y");
301 lua_rawseti(fL, -2, i + 1);
302 }
303 CHECK_SETFIELD(key);
304}
305
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000306void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
307 lua_newtable(fL);
308 for (int i = 0; i < count; ++i) {
309 // make it base-1 to match lua convention
310 setarray_scalar(fL, i + 1, array[i]);
311 }
312 CHECK_SETFIELD(key);
313}
314
reed@google.com74ce6f02013-05-22 15:13:18 +0000315void SkLua::pushRect(const SkRect& r, const char key[]) {
316 lua_newtable(fL);
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000317 setfield_scalar(fL, "left", r.fLeft);
318 setfield_scalar(fL, "top", r.fTop);
319 setfield_scalar(fL, "right", r.fRight);
320 setfield_scalar(fL, "bottom", r.fBottom);
reed@google.com74ce6f02013-05-22 15:13:18 +0000321 CHECK_SETFIELD(key);
322}
323
324void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
325 push_obj(fL, rr);
326 CHECK_SETFIELD(key);
327}
328
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000329void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
330 lua_newtable(fL);
331 setfield_scalar(fL, "phase", info.fPhase);
332 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
333 CHECK_SETFIELD(key);
334}
335
336
reed@google.com74ce6f02013-05-22 15:13:18 +0000337void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
338 push_obj(fL, matrix);
339 CHECK_SETFIELD(key);
340}
341
342void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
343 push_obj(fL, paint);
344 CHECK_SETFIELD(key);
345}
346
347void SkLua::pushPath(const SkPath& path, const char key[]) {
348 push_obj(fL, path);
349 CHECK_SETFIELD(key);
350}
351
352void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
Mike Reed5df49342016-11-12 08:06:55 -0600353 push_ptr(fL, canvas);
reed@google.com74ce6f02013-05-22 15:13:18 +0000354 CHECK_SETFIELD(key);
355}
356
fmalitab7425172014-08-26 07:56:44 -0700357void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
358 push_ref(fL, const_cast<SkTextBlob*>(blob));
359 CHECK_SETFIELD(key);
360}
361
reed@google.com74ce6f02013-05-22 15:13:18 +0000362///////////////////////////////////////////////////////////////////////////////
363///////////////////////////////////////////////////////////////////////////////
364
reed@google.com74ce6f02013-05-22 15:13:18 +0000365static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
366 SkASSERT(lua_istable(L, index));
367 lua_pushstring(L, key);
368 lua_gettable(L, index);
mtklein8aacf202014-12-18 13:29:54 -0800369
reed@google.com74ce6f02013-05-22 15:13:18 +0000370 SkScalar value = lua2scalar(L, -1);
371 lua_pop(L, 1);
372 return value;
373}
374
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000375static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
376 SkASSERT(lua_istable(L, index));
377 lua_pushstring(L, key);
378 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000379
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000380 SkScalar value;
381 if (lua_isnil(L, -1)) {
382 value = def;
383 } else {
384 value = lua2scalar(L, -1);
385 }
386 lua_pop(L, 1);
387 return value;
388}
389
reed468b1812014-10-19 11:42:54 -0700390static SkScalar byte2unit(U8CPU byte) {
391 return byte / 255.0f;
392}
393
reed@google.com74ce6f02013-05-22 15:13:18 +0000394static U8CPU unit2byte(SkScalar x) {
395 if (x <= 0) {
396 return 0;
397 } else if (x >= 1) {
398 return 255;
399 } else {
400 return SkScalarRoundToInt(x * 255);
401 }
402}
403
404static SkColor lua2color(lua_State* L, int index) {
reed485557f2014-10-12 10:36:47 -0700405 return SkColorSetARGB(unit2byte(getfield_scalar_default(L, index, "a", 1)),
406 unit2byte(getfield_scalar_default(L, index, "r", 0)),
407 unit2byte(getfield_scalar_default(L, index, "g", 0)),
408 unit2byte(getfield_scalar_default(L, index, "b", 0)));
reed@google.com74ce6f02013-05-22 15:13:18 +0000409}
410
411static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000412 rect->set(getfield_scalar_default(L, index, "left", 0),
413 getfield_scalar_default(L, index, "top", 0),
reed@google.com74ce6f02013-05-22 15:13:18 +0000414 getfield_scalar(L, index, "right"),
415 getfield_scalar(L, index, "bottom"));
416 return rect;
417}
418
reedf355df52014-10-12 12:18:40 -0700419static int lcanvas_clear(lua_State* L) {
420 get_ref<SkCanvas>(L, 1)->clear(0);
421 return 0;
422}
423
reed@google.com74ce6f02013-05-22 15:13:18 +0000424static int lcanvas_drawColor(lua_State* L) {
425 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
426 return 0;
427}
428
reed9fbc3f32014-10-21 07:12:58 -0700429static int lcanvas_drawPaint(lua_State* L) {
430 get_ref<SkCanvas>(L, 1)->drawPaint(*get_obj<SkPaint>(L, 2));
431 return 0;
432}
433
reed@google.com74ce6f02013-05-22 15:13:18 +0000434static int lcanvas_drawRect(lua_State* L) {
435 SkRect rect;
reed7a72c672014-11-07 10:23:55 -0800436 lua2rect(L, 2, &rect);
437 const SkPaint* paint = get_obj<SkPaint>(L, 3);
438 get_ref<SkCanvas>(L, 1)->drawRect(rect, *paint);
reed@google.com74ce6f02013-05-22 15:13:18 +0000439 return 0;
440}
441
442static int lcanvas_drawOval(lua_State* L) {
443 SkRect rect;
444 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
445 *get_obj<SkPaint>(L, 3));
446 return 0;
447}
448
449static int lcanvas_drawCircle(lua_State* L) {
450 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
451 lua2scalar(L, 3),
452 lua2scalar(L, 4),
453 *get_obj<SkPaint>(L, 5));
454 return 0;
455}
456
reed485557f2014-10-12 10:36:47 -0700457static SkPaint* lua2OptionalPaint(lua_State* L, int index, SkPaint* paint) {
458 if (lua_isnumber(L, index)) {
459 paint->setAlpha(SkScalarRoundToInt(lua2scalar(L, index) * 255));
460 return paint;
reedf355df52014-10-12 12:18:40 -0700461 } else if (lua_isuserdata(L, index)) {
reed485557f2014-10-12 10:36:47 -0700462 const SkPaint* ptr = get_obj<SkPaint>(L, index);
463 if (ptr) {
464 *paint = *ptr;
465 return paint;
466 }
467 }
halcanary96fcdcc2015-08-27 07:41:13 -0700468 return nullptr;
reed485557f2014-10-12 10:36:47 -0700469}
470
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000471static int lcanvas_drawImage(lua_State* L) {
472 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
473 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700474 if (nullptr == image) {
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000475 return 0;
476 }
477 SkScalar x = lua2scalar(L, 3);
478 SkScalar y = lua2scalar(L, 4);
479
480 SkPaint paint;
reed485557f2014-10-12 10:36:47 -0700481 canvas->drawImage(image, x, y, lua2OptionalPaint(L, 5, &paint));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000482 return 0;
483}
484
reedba5fb932014-10-10 15:28:19 -0700485static int lcanvas_drawImageRect(lua_State* L) {
486 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
487 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700488 if (nullptr == image) {
reedba5fb932014-10-10 15:28:19 -0700489 return 0;
490 }
491
492 SkRect srcR, dstR;
halcanary96fcdcc2015-08-27 07:41:13 -0700493 SkRect* srcRPtr = nullptr;
reedba5fb932014-10-10 15:28:19 -0700494 if (!lua_isnil(L, 3)) {
495 srcRPtr = lua2rect(L, 3, &srcR);
496 }
497 lua2rect(L, 4, &dstR);
mtklein8aacf202014-12-18 13:29:54 -0800498
reedba5fb932014-10-10 15:28:19 -0700499 SkPaint paint;
reede47829b2015-08-06 10:02:53 -0700500 canvas->legacy_drawImageRect(image, srcRPtr, dstR, lua2OptionalPaint(L, 5, &paint));
reedba5fb932014-10-10 15:28:19 -0700501 return 0;
502}
503
reed7a72c672014-11-07 10:23:55 -0800504static int lcanvas_drawPatch(lua_State* L) {
505 SkPoint cubics[12];
506 SkColor colorStorage[4];
507 SkPoint texStorage[4];
508
halcanary96fcdcc2015-08-27 07:41:13 -0700509 const SkColor* colors = nullptr;
510 const SkPoint* texs = nullptr;
reed7a72c672014-11-07 10:23:55 -0800511
512 getarray_points(L, 2, cubics, 12);
513
514 colorStorage[0] = SK_ColorRED;
515 colorStorage[1] = SK_ColorGREEN;
516 colorStorage[2] = SK_ColorBLUE;
517 colorStorage[3] = SK_ColorGRAY;
518
519 if (lua_isnil(L, 4)) {
520 colors = colorStorage;
521 } else {
522 getarray_points(L, 4, texStorage, 4);
523 texs = texStorage;
524 }
525
Mike Reed7d954ad2016-10-28 15:42:34 -0400526 get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, *get_obj<SkPaint>(L, 5));
reed7a72c672014-11-07 10:23:55 -0800527 return 0;
528}
529
reed@google.comfd345872013-05-22 20:53:42 +0000530static int lcanvas_drawPath(lua_State* L) {
531 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
532 *get_obj<SkPaint>(L, 3));
533 return 0;
534}
535
reed96affcd2014-10-13 12:38:04 -0700536// drawPicture(pic, x, y, paint)
537static int lcanvas_drawPicture(lua_State* L) {
538 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
539 SkPicture* picture = get_ref<SkPicture>(L, 2);
540 SkScalar x = lua2scalar_def(L, 3, 0);
541 SkScalar y = lua2scalar_def(L, 4, 0);
halcanary96fcdcc2015-08-27 07:41:13 -0700542 SkMatrix matrix, *matrixPtr = nullptr;
reed96affcd2014-10-13 12:38:04 -0700543 if (x || y) {
544 matrix.setTranslate(x, y);
545 matrixPtr = &matrix;
546 }
547 SkPaint paint;
548 canvas->drawPicture(picture, matrixPtr, lua2OptionalPaint(L, 5, &paint));
549 return 0;
550}
551
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000552static int lcanvas_drawText(lua_State* L) {
553 if (lua_gettop(L) < 5) {
554 return 0;
555 }
556
557 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
558 size_t len;
559 const char* text = lua_tolstring(L, 2, &len);
560 get_ref<SkCanvas>(L, 1)->drawText(text, len,
561 lua2scalar(L, 3), lua2scalar(L, 4),
562 *get_obj<SkPaint>(L, 5));
563 }
564 return 0;
565}
566
reed1b6ab442014-11-03 19:55:41 -0800567static int lcanvas_drawTextBlob(lua_State* L) {
568 const SkTextBlob* blob = get_ref<SkTextBlob>(L, 2);
569 SkScalar x = lua2scalar(L, 3);
570 SkScalar y = lua2scalar(L, 4);
571 const SkPaint& paint = *get_obj<SkPaint>(L, 5);
572 get_ref<SkCanvas>(L, 1)->drawTextBlob(blob, x, y, paint);
573 return 0;
574}
575
reed@google.com74ce6f02013-05-22 15:13:18 +0000576static int lcanvas_getSaveCount(lua_State* L) {
577 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
578 return 1;
579}
580
581static int lcanvas_getTotalMatrix(lua_State* L) {
582 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
583 return 1;
584}
585
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000586static int lcanvas_save(lua_State* L) {
587 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
588 return 1;
589}
590
reed86217d82014-10-25 20:44:40 -0700591static int lcanvas_saveLayer(lua_State* L) {
592 SkPaint paint;
halcanary96fcdcc2015-08-27 07:41:13 -0700593 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->saveLayer(nullptr, lua2OptionalPaint(L, 2, &paint)));
reed86217d82014-10-25 20:44:40 -0700594 return 1;
595}
596
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000597static int lcanvas_restore(lua_State* L) {
598 get_ref<SkCanvas>(L, 1)->restore();
599 return 0;
600}
601
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000602static int lcanvas_scale(lua_State* L) {
603 SkScalar sx = lua2scalar_def(L, 2, 1);
604 SkScalar sy = lua2scalar_def(L, 3, sx);
605 get_ref<SkCanvas>(L, 1)->scale(sx, sy);
606 return 0;
607}
608
reed@google.com3597b732013-05-22 20:12:50 +0000609static int lcanvas_translate(lua_State* L) {
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000610 SkScalar tx = lua2scalar_def(L, 2, 0);
611 SkScalar ty = lua2scalar_def(L, 3, 0);
612 get_ref<SkCanvas>(L, 1)->translate(tx, ty);
613 return 0;
614}
615
616static int lcanvas_rotate(lua_State* L) {
617 SkScalar degrees = lua2scalar_def(L, 2, 0);
618 get_ref<SkCanvas>(L, 1)->rotate(degrees);
reed@google.com3597b732013-05-22 20:12:50 +0000619 return 0;
620}
621
reedbdc49ae2014-10-14 09:34:52 -0700622static int lcanvas_concat(lua_State* L) {
623 get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2));
624 return 0;
625}
626
reed485557f2014-10-12 10:36:47 -0700627static int lcanvas_newSurface(lua_State* L) {
628 int width = lua2int_def(L, 2, 0);
reed7a72c672014-11-07 10:23:55 -0800629 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -0700630 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -0700631 auto surface = get_ref<SkCanvas>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -0700632 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -0700633 lua_pushnil(L);
634 } else {
reede8f30622016-03-23 18:59:25 -0700635 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -0700636 }
637 return 1;
638}
639
reed@google.com74ce6f02013-05-22 15:13:18 +0000640static int lcanvas_gc(lua_State* L) {
Mike Reed5df49342016-11-12 08:06:55 -0600641 // don't know how to track a ptr...
reed@google.com74ce6f02013-05-22 15:13:18 +0000642 return 0;
643}
644
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000645const struct luaL_Reg gSkCanvas_Methods[] = {
reedf355df52014-10-12 12:18:40 -0700646 { "clear", lcanvas_clear },
reed@google.com74ce6f02013-05-22 15:13:18 +0000647 { "drawColor", lcanvas_drawColor },
reed9fbc3f32014-10-21 07:12:58 -0700648 { "drawPaint", lcanvas_drawPaint },
reed@google.com74ce6f02013-05-22 15:13:18 +0000649 { "drawRect", lcanvas_drawRect },
650 { "drawOval", lcanvas_drawOval },
651 { "drawCircle", lcanvas_drawCircle },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000652 { "drawImage", lcanvas_drawImage },
reedba5fb932014-10-10 15:28:19 -0700653 { "drawImageRect", lcanvas_drawImageRect },
reed7a72c672014-11-07 10:23:55 -0800654 { "drawPatch", lcanvas_drawPatch },
reed@google.comfd345872013-05-22 20:53:42 +0000655 { "drawPath", lcanvas_drawPath },
reed96affcd2014-10-13 12:38:04 -0700656 { "drawPicture", lcanvas_drawPicture },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000657 { "drawText", lcanvas_drawText },
reed1b6ab442014-11-03 19:55:41 -0800658 { "drawTextBlob", lcanvas_drawTextBlob },
reed@google.com74ce6f02013-05-22 15:13:18 +0000659 { "getSaveCount", lcanvas_getSaveCount },
660 { "getTotalMatrix", lcanvas_getTotalMatrix },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000661 { "save", lcanvas_save },
reed86217d82014-10-25 20:44:40 -0700662 { "saveLayer", lcanvas_saveLayer },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000663 { "restore", lcanvas_restore },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000664 { "scale", lcanvas_scale },
reed@google.com3597b732013-05-22 20:12:50 +0000665 { "translate", lcanvas_translate },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000666 { "rotate", lcanvas_rotate },
reedbdc49ae2014-10-14 09:34:52 -0700667 { "concat", lcanvas_concat },
reed485557f2014-10-12 10:36:47 -0700668
669 { "newSurface", lcanvas_newSurface },
670
reed@google.com74ce6f02013-05-22 15:13:18 +0000671 { "__gc", lcanvas_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700672 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +0000673};
674
675///////////////////////////////////////////////////////////////////////////////
676
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000677static int ldocument_beginPage(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -0700678 const SkRect* contentPtr = nullptr;
Mike Reed7ff6ca52018-01-08 14:45:31 -0500679 push_ptr(L, get_obj<DocHolder>(L, 1)->fDoc->beginPage(lua2scalar(L, 2),
680 lua2scalar(L, 3),
681 contentPtr));
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000682 return 1;
683}
684
685static int ldocument_endPage(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500686 get_obj<DocHolder>(L, 1)->fDoc->endPage();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000687 return 0;
688}
689
690static int ldocument_close(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500691 get_obj<DocHolder>(L, 1)->fDoc->close();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000692 return 0;
693}
694
695static int ldocument_gc(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500696 get_obj<DocHolder>(L, 1)->~DocHolder();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000697 return 0;
698}
699
Mike Reed7ff6ca52018-01-08 14:45:31 -0500700static const struct luaL_Reg gDocHolder_Methods[] = {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000701 { "beginPage", ldocument_beginPage },
702 { "endPage", ldocument_endPage },
703 { "close", ldocument_close },
704 { "__gc", ldocument_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700705 { nullptr, nullptr }
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000706};
707
708///////////////////////////////////////////////////////////////////////////////
709
reed@google.com74ce6f02013-05-22 15:13:18 +0000710static int lpaint_isAntiAlias(lua_State* L) {
711 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
712 return 1;
713}
714
715static int lpaint_setAntiAlias(lua_State* L) {
reed@google.com88c9ec92013-05-22 15:43:21 +0000716 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +0000717 return 0;
718}
719
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000720static int lpaint_isDither(lua_State* L) {
721 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
722 return 1;
723}
724
reedbb8a0ab2014-11-03 22:32:07 -0800725static int lpaint_setDither(lua_State* L) {
726 get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2));
727 return 0;
728}
729
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000730static int lpaint_isFakeBoldText(lua_State* L) {
731 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
732 return 1;
733}
734
735static int lpaint_isLinearText(lua_State* L) {
736 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
737 return 1;
738}
739
740static int lpaint_isSubpixelText(lua_State* L) {
741 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
742 return 1;
743}
744
reed09a1d672014-10-11 13:13:11 -0700745static int lpaint_setSubpixelText(lua_State* L) {
746 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
747 return 1;
748}
749
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000750static int lpaint_isLCDRenderText(lua_State* L) {
751 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
752 return 1;
753}
754
reed36c9c112014-11-04 10:58:42 -0800755static int lpaint_setLCDRenderText(lua_State* L) {
756 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2));
757 return 1;
758}
759
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000760static int lpaint_isEmbeddedBitmapText(lua_State* L) {
761 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
762 return 1;
763}
764
765static int lpaint_isAutohinted(lua_State* L) {
766 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
767 return 1;
768}
769
reed468b1812014-10-19 11:42:54 -0700770static int lpaint_getAlpha(lua_State* L) {
771 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha()));
772 return 1;
773}
774
775static int lpaint_setAlpha(lua_State* L) {
776 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2)));
777 return 0;
778}
779
reed@google.com74ce6f02013-05-22 15:13:18 +0000780static int lpaint_getColor(lua_State* L) {
781 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
782 return 1;
783}
784
785static int lpaint_setColor(lua_State* L) {
786 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
787 return 0;
788}
789
reed@google.come3823fd2013-05-30 18:55:14 +0000790static int lpaint_getTextSize(lua_State* L) {
791 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
792 return 1;
793}
794
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000795static int lpaint_getTextScaleX(lua_State* L) {
796 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
797 return 1;
798}
799
800static int lpaint_getTextSkewX(lua_State* L) {
801 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
802 return 1;
803}
804
reed@google.come3823fd2013-05-30 18:55:14 +0000805static int lpaint_setTextSize(lua_State* L) {
806 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
807 return 0;
808}
809
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000810static int lpaint_getTypeface(lua_State* L) {
811 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
812 return 1;
813}
814
815static int lpaint_setTypeface(lua_State* L) {
bungeman13b9c952016-05-12 10:09:30 -0700816 get_obj<SkPaint>(L, 1)->setTypeface(sk_ref_sp(get_ref<SkTypeface>(L, 2)));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000817 return 0;
818}
819
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000820static int lpaint_getHinting(lua_State* L) {
Mike Reed9edbf422018-11-07 19:54:33 -0500821 SkLua(L).pushU32((unsigned)get_obj<SkPaint>(L, 1)->getHinting());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000822 return 1;
823}
824
reed93a12152015-03-16 10:08:34 -0700825static int lpaint_getFilterQuality(lua_State* L) {
826 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality());
reed7a72c672014-11-07 10:23:55 -0800827 return 1;
828}
829
reed93a12152015-03-16 10:08:34 -0700830static int lpaint_setFilterQuality(lua_State* L) {
reed7a72c672014-11-07 10:23:55 -0800831 int level = lua2int_def(L, 2, -1);
832 if (level >= 0 && level <= 3) {
reed93a12152015-03-16 10:08:34 -0700833 get_obj<SkPaint>(L, 1)->setFilterQuality((SkFilterQuality)level);
reed7a72c672014-11-07 10:23:55 -0800834 }
835 return 0;
836}
837
reed@google.come3823fd2013-05-30 18:55:14 +0000838static int lpaint_getFontID(lua_State* L) {
839 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
840 SkLua(L).pushU32(SkTypeface::UniqueID(face));
841 return 1;
842}
843
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000844static int lpaint_getStroke(lua_State* L) {
845 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
846 return 1;
847}
848
849static int lpaint_setStroke(lua_State* L) {
850 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000851
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000852 if (lua_toboolean(L, 2)) {
853 style = SkPaint::kStroke_Style;
854 } else {
855 style = SkPaint::kFill_Style;
856 }
857 get_obj<SkPaint>(L, 1)->setStyle(style);
858 return 0;
859}
860
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000861static int lpaint_getStrokeCap(lua_State* L) {
862 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
863 return 1;
864}
865
866static int lpaint_getStrokeJoin(lua_State* L) {
867 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
868 return 1;
869}
870
871static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +0000872 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000873 return 1;
874}
875
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000876static int lpaint_getStrokeWidth(lua_State* L) {
877 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
878 return 1;
879}
880
881static int lpaint_setStrokeWidth(lua_State* L) {
882 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
883 return 0;
884}
885
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000886static int lpaint_getStrokeMiter(lua_State* L) {
887 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
888 return 1;
889}
890
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000891static int lpaint_measureText(lua_State* L) {
892 if (lua_isstring(L, 2)) {
893 size_t len;
894 const char* text = lua_tolstring(L, 2, &len);
895 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
896 return 1;
897 }
898 return 0;
899}
900
901struct FontMetrics {
902 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
903 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
904 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
905 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
906 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
907 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
908 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
909 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
910 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
911};
912
913static int lpaint_getFontMetrics(lua_State* L) {
Mike Reedb5784ac2018-11-12 09:35:15 -0500914 SkFontMetrics fm;
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000915 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000916
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000917 lua_newtable(L);
918 setfield_scalar(L, "top", fm.fTop);
919 setfield_scalar(L, "ascent", fm.fAscent);
920 setfield_scalar(L, "descent", fm.fDescent);
921 setfield_scalar(L, "bottom", fm.fBottom);
922 setfield_scalar(L, "leading", fm.fLeading);
923 SkLua(L).pushScalar(height);
924 return 2;
925}
926
reed@google.com29563872013-07-10 21:23:49 +0000927static int lpaint_getEffects(lua_State* L) {
928 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000929
reed@google.com29563872013-07-10 21:23:49 +0000930 lua_newtable(L);
reed468b1812014-10-19 11:42:54 -0700931 setfield_bool_if(L, "looper", !!paint->getLooper());
932 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
reed468b1812014-10-19 11:42:54 -0700933 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
934 setfield_bool_if(L, "shader", !!paint->getShader());
reed@google.com29563872013-07-10 21:23:49 +0000935 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
936 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
reed@google.com29563872013-07-10 21:23:49 +0000937 return 1;
938}
939
reed22a517f2015-12-04 20:45:59 -0800940static int lpaint_getColorFilter(lua_State* L) {
941 const SkPaint* paint = get_obj<SkPaint>(L, 1);
942 SkColorFilter* cf = paint->getColorFilter();
943 if (cf) {
944 push_ref(L, cf);
945 return 1;
946 }
947 return 0;
948}
949
950static int lpaint_setColorFilter(lua_State* L) {
951 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedd053ce92016-03-22 10:17:23 -0700952 paint->setColorFilter(sk_ref_sp(get_ref<SkColorFilter>(L, 2)));
reed22a517f2015-12-04 20:45:59 -0800953 return 0;
954}
955
reed468b1812014-10-19 11:42:54 -0700956static int lpaint_getImageFilter(lua_State* L) {
957 const SkPaint* paint = get_obj<SkPaint>(L, 1);
958 SkImageFilter* imf = paint->getImageFilter();
959 if (imf) {
960 push_ref(L, imf);
961 return 1;
962 }
963 return 0;
964}
965
966static int lpaint_setImageFilter(lua_State* L) {
967 SkPaint* paint = get_obj<SkPaint>(L, 1);
Mike Reed5e257172016-11-01 11:22:05 -0400968 paint->setImageFilter(sk_ref_sp(get_ref<SkImageFilter>(L, 2)));
reed468b1812014-10-19 11:42:54 -0700969 return 0;
970}
971
reed@google.com5fdc9832013-07-24 15:47:52 +0000972static int lpaint_getShader(lua_State* L) {
973 const SkPaint* paint = get_obj<SkPaint>(L, 1);
974 SkShader* shader = paint->getShader();
975 if (shader) {
976 push_ref(L, shader);
977 return 1;
978 }
979 return 0;
980}
981
reed9fbc3f32014-10-21 07:12:58 -0700982static int lpaint_setShader(lua_State* L) {
983 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedfe630452016-03-25 09:08:00 -0700984 paint->setShader(sk_ref_sp(get_ref<SkShader>(L, 2)));
reed9fbc3f32014-10-21 07:12:58 -0700985 return 0;
986}
987
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000988static int lpaint_getPathEffect(lua_State* L) {
989 const SkPaint* paint = get_obj<SkPaint>(L, 1);
990 SkPathEffect* pe = paint->getPathEffect();
991 if (pe) {
992 push_ref(L, pe);
993 return 1;
994 }
995 return 0;
996}
997
hstern0b401ce2016-08-02 09:17:59 -0700998static int lpaint_getFillPath(lua_State* L) {
999 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1000 const SkPath* path = get_obj<SkPath>(L, 2);
1001
1002 SkPath fillpath;
1003 paint->getFillPath(*path, &fillpath);
1004
1005 SkLua lua(L);
1006 lua.pushPath(fillpath);
1007
1008 return 1;
1009}
1010
reed@google.com74ce6f02013-05-22 15:13:18 +00001011static int lpaint_gc(lua_State* L) {
1012 get_obj<SkPaint>(L, 1)->~SkPaint();
1013 return 0;
1014}
1015
1016static const struct luaL_Reg gSkPaint_Methods[] = {
1017 { "isAntiAlias", lpaint_isAntiAlias },
1018 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001019 { "isDither", lpaint_isDither },
reedbb8a0ab2014-11-03 22:32:07 -08001020 { "setDither", lpaint_setDither },
reed93a12152015-03-16 10:08:34 -07001021 { "getFilterQuality", lpaint_getFilterQuality },
1022 { "setFilterQuality", lpaint_setFilterQuality },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001023 { "isFakeBoldText", lpaint_isFakeBoldText },
1024 { "isLinearText", lpaint_isLinearText },
1025 { "isSubpixelText", lpaint_isSubpixelText },
reed09a1d672014-10-11 13:13:11 -07001026 { "setSubpixelText", lpaint_setSubpixelText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001027 { "isLCDRenderText", lpaint_isLCDRenderText },
reed36c9c112014-11-04 10:58:42 -08001028 { "setLCDRenderText", lpaint_setLCDRenderText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001029 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
1030 { "isAutohinted", lpaint_isAutohinted },
reed468b1812014-10-19 11:42:54 -07001031 { "getAlpha", lpaint_getAlpha },
1032 { "setAlpha", lpaint_setAlpha },
reed@google.com74ce6f02013-05-22 15:13:18 +00001033 { "getColor", lpaint_getColor },
1034 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +00001035 { "getTextSize", lpaint_getTextSize },
1036 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001037 { "getTextScaleX", lpaint_getTextScaleX },
1038 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001039 { "getTypeface", lpaint_getTypeface },
1040 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001041 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +00001042 { "getFontID", lpaint_getFontID },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001043 { "getStroke", lpaint_getStroke },
1044 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001045 { "getStrokeCap", lpaint_getStrokeCap },
1046 { "getStrokeJoin", lpaint_getStrokeJoin },
1047 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001048 { "getStrokeWidth", lpaint_getStrokeWidth },
1049 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001050 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001051 { "measureText", lpaint_measureText },
1052 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +00001053 { "getEffects", lpaint_getEffects },
reed22a517f2015-12-04 20:45:59 -08001054 { "getColorFilter", lpaint_getColorFilter },
1055 { "setColorFilter", lpaint_setColorFilter },
reed468b1812014-10-19 11:42:54 -07001056 { "getImageFilter", lpaint_getImageFilter },
1057 { "setImageFilter", lpaint_setImageFilter },
reed@google.com5fdc9832013-07-24 15:47:52 +00001058 { "getShader", lpaint_getShader },
reed9fbc3f32014-10-21 07:12:58 -07001059 { "setShader", lpaint_setShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001060 { "getPathEffect", lpaint_getPathEffect },
hstern0b401ce2016-08-02 09:17:59 -07001061 { "getFillPath", lpaint_getFillPath },
reed@google.com74ce6f02013-05-22 15:13:18 +00001062 { "__gc", lpaint_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001063 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001064};
1065
1066///////////////////////////////////////////////////////////////////////////////
1067
reed@google.com5fdc9832013-07-24 15:47:52 +00001068static const char* mode2string(SkShader::TileMode mode) {
1069 static const char* gNames[] = { "clamp", "repeat", "mirror" };
1070 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
1071 return gNames[mode];
1072}
1073
1074static const char* gradtype2string(SkShader::GradientType t) {
1075 static const char* gNames[] = {
1076 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
1077 };
1078 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
1079 return gNames[t];
1080}
1081
1082static int lshader_isOpaque(lua_State* L) {
1083 SkShader* shader = get_ref<SkShader>(L, 1);
1084 return shader && shader->isOpaque();
1085}
1086
Mike Reed627778d2016-09-28 17:13:38 -04001087static int lshader_isAImage(lua_State* L) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001088 SkShader* shader = get_ref<SkShader>(L, 1);
1089 if (shader) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001090 SkMatrix matrix;
1091 SkShader::TileMode modes[2];
Mike Reed627778d2016-09-28 17:13:38 -04001092 if (SkImage* image = shader->isAImage(&matrix, modes)) {
reedf5822822015-08-19 11:46:38 -07001093 lua_newtable(L);
Mike Reed627778d2016-09-28 17:13:38 -04001094 setfield_number(L, "id", image->uniqueID());
1095 setfield_number(L, "width", image->width());
1096 setfield_number(L, "height", image->height());
reedf5822822015-08-19 11:46:38 -07001097 setfield_string(L, "tileX", mode2string(modes[0]));
1098 setfield_string(L, "tileY", mode2string(modes[1]));
1099 return 1;
reed@google.com5fdc9832013-07-24 15:47:52 +00001100 }
1101 }
1102 return 0;
1103}
1104
1105static int lshader_asAGradient(lua_State* L) {
1106 SkShader* shader = get_ref<SkShader>(L, 1);
1107 if (shader) {
1108 SkShader::GradientInfo info;
1109 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001110
reed@google.com5fdc9832013-07-24 15:47:52 +00001111 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001112
reed@google.com5fdc9832013-07-24 15:47:52 +00001113 if (SkShader::kNone_GradientType != t) {
fmenozzib4f254e2016-06-28 14:03:03 -07001114 SkAutoTArray<SkScalar> pos(info.fColorCount);
1115 info.fColorOffsets = pos.get();
1116 shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001117
fmenozzib4f254e2016-06-28 14:03:03 -07001118 lua_newtable(L);
fmenozzi7f2c85e2016-07-12 09:17:39 -07001119 setfield_string(L, "type", gradtype2string(t));
1120 setfield_string(L, "tile", mode2string(info.fTileMode));
1121 setfield_number(L, "colorCount", info.fColorCount);
fmenozzib4f254e2016-06-28 14:03:03 -07001122
1123 lua_newtable(L);
1124 for (int i = 0; i < info.fColorCount; i++) {
1125 // Lua uses 1-based indexing
1126 setarray_scalar(L, i+1, pos[i]);
1127 }
1128 lua_setfield(L, -2, "positions");
1129
reed@google.com5fdc9832013-07-24 15:47:52 +00001130 return 1;
1131 }
1132 }
1133 return 0;
1134}
1135
1136static int lshader_gc(lua_State* L) {
1137 get_ref<SkShader>(L, 1)->unref();
1138 return 0;
1139}
1140
1141static const struct luaL_Reg gSkShader_Methods[] = {
1142 { "isOpaque", lshader_isOpaque },
Mike Reed627778d2016-09-28 17:13:38 -04001143 { "isAImage", lshader_isAImage },
reed@google.com5fdc9832013-07-24 15:47:52 +00001144 { "asAGradient", lshader_asAGradient },
1145 { "__gc", lshader_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001146 { nullptr, nullptr }
reed@google.com5fdc9832013-07-24 15:47:52 +00001147};
1148
1149///////////////////////////////////////////////////////////////////////////////
1150
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001151static int lpatheffect_asADash(lua_State* L) {
1152 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1153 if (pe) {
1154 SkPathEffect::DashInfo info;
1155 SkPathEffect::DashType dashType = pe->asADash(&info);
1156 if (SkPathEffect::kDash_DashType == dashType) {
1157 SkAutoTArray<SkScalar> intervals(info.fCount);
1158 info.fIntervals = intervals.get();
1159 pe->asADash(&info);
1160 SkLua(L).pushDash(info);
1161 return 1;
1162 }
1163 }
1164 return 0;
1165}
1166
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001167static int lpatheffect_gc(lua_State* L) {
1168 get_ref<SkPathEffect>(L, 1)->unref();
1169 return 0;
1170}
1171
1172static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001173 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001174 { "__gc", lpatheffect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001175 { nullptr, nullptr }
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001176};
1177
1178///////////////////////////////////////////////////////////////////////////////
1179
reed22a517f2015-12-04 20:45:59 -08001180static int lpcolorfilter_gc(lua_State* L) {
1181 get_ref<SkColorFilter>(L, 1)->unref();
1182 return 0;
1183}
1184
1185static const struct luaL_Reg gSkColorFilter_Methods[] = {
1186 { "__gc", lpcolorfilter_gc },
1187 { nullptr, nullptr }
1188};
1189
1190///////////////////////////////////////////////////////////////////////////////
1191
reed468b1812014-10-19 11:42:54 -07001192static int lpimagefilter_gc(lua_State* L) {
1193 get_ref<SkImageFilter>(L, 1)->unref();
1194 return 0;
1195}
1196
1197static const struct luaL_Reg gSkImageFilter_Methods[] = {
1198 { "__gc", lpimagefilter_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001199 { nullptr, nullptr }
reed468b1812014-10-19 11:42:54 -07001200};
1201
1202///////////////////////////////////////////////////////////////////////////////
1203
humper@google.com2815c192013-07-10 22:42:30 +00001204static int lmatrix_getType(lua_State* L) {
1205 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001206
humper@google.com2815c192013-07-10 22:42:30 +00001207 lua_newtable(L);
1208 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1209 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1210 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1211 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1212 return 1;
1213}
1214
humper@google.com0f48ee02013-07-26 15:23:43 +00001215static int lmatrix_getScaleX(lua_State* L) {
1216 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1217 return 1;
1218}
1219
1220static int lmatrix_getScaleY(lua_State* L) {
1221 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1222 return 1;
1223}
1224
1225static int lmatrix_getTranslateX(lua_State* L) {
1226 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1227 return 1;
1228}
1229
1230static int lmatrix_getTranslateY(lua_State* L) {
1231 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1232 return 1;
1233}
1234
reed7a72c672014-11-07 10:23:55 -08001235static int lmatrix_invert(lua_State* L) {
1236 lua_pushboolean(L, get_obj<SkMatrix>(L, 1)->invert(get_obj<SkMatrix>(L, 2)));
1237 return 1;
1238}
1239
1240static int lmatrix_mapXY(lua_State* L) {
1241 SkPoint pt = { lua2scalar(L, 2), lua2scalar(L, 3) };
1242 get_obj<SkMatrix>(L, 1)->mapPoints(&pt, &pt, 1);
1243 lua_pushnumber(L, pt.x());
1244 lua_pushnumber(L, pt.y());
1245 return 2;
1246}
1247
reedbdc49ae2014-10-14 09:34:52 -07001248static int lmatrix_setRectToRect(lua_State* L) {
1249 SkMatrix* matrix = get_obj<SkMatrix>(L, 1);
1250 SkRect srcR, dstR;
1251 lua2rect(L, 2, &srcR);
1252 lua2rect(L, 3, &dstR);
1253 const char* scaleToFitStr = lua_tostring(L, 4);
1254 SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit;
1255
1256 if (scaleToFitStr) {
1257 const struct {
1258 const char* fName;
1259 SkMatrix::ScaleToFit fScaleToFit;
1260 } rec[] = {
1261 { "fill", SkMatrix::kFill_ScaleToFit },
1262 { "start", SkMatrix::kStart_ScaleToFit },
1263 { "center", SkMatrix::kCenter_ScaleToFit },
1264 { "end", SkMatrix::kEnd_ScaleToFit },
1265 };
1266
1267 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
1268 if (strcmp(rec[i].fName, scaleToFitStr) == 0) {
1269 scaleToFit = rec[i].fScaleToFit;
1270 break;
1271 }
1272 }
1273 }
1274
1275 matrix->setRectToRect(srcR, dstR, scaleToFit);
1276 return 0;
1277}
1278
humper@google.com2815c192013-07-10 22:42:30 +00001279static const struct luaL_Reg gSkMatrix_Methods[] = {
1280 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001281 { "getScaleX", lmatrix_getScaleX },
1282 { "getScaleY", lmatrix_getScaleY },
1283 { "getTranslateX", lmatrix_getTranslateX },
1284 { "getTranslateY", lmatrix_getTranslateY },
reedbdc49ae2014-10-14 09:34:52 -07001285 { "setRectToRect", lmatrix_setRectToRect },
reed7a72c672014-11-07 10:23:55 -08001286 { "invert", lmatrix_invert },
1287 { "mapXY", lmatrix_mapXY },
halcanary96fcdcc2015-08-27 07:41:13 -07001288 { nullptr, nullptr }
humper@google.com2815c192013-07-10 22:42:30 +00001289};
1290
1291///////////////////////////////////////////////////////////////////////////////
1292
reed@google.com74ce6f02013-05-22 15:13:18 +00001293static int lpath_getBounds(lua_State* L) {
1294 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1295 return 1;
1296}
1297
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001298static const char* fill_type_to_str(SkPath::FillType fill) {
1299 switch (fill) {
1300 case SkPath::kEvenOdd_FillType:
1301 return "even-odd";
1302 case SkPath::kWinding_FillType:
1303 return "winding";
1304 case SkPath::kInverseEvenOdd_FillType:
1305 return "inverse-even-odd";
1306 case SkPath::kInverseWinding_FillType:
1307 return "inverse-winding";
1308 }
1309 return "unknown";
1310}
1311
1312static int lpath_getFillType(lua_State* L) {
1313 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1314 SkLua(L).pushString(fill_type_to_str(fill));
1315 return 1;
1316}
1317
1318static SkString segment_masks_to_str(uint32_t segmentMasks) {
1319 SkString result;
1320 bool first = true;
1321 if (SkPath::kLine_SegmentMask & segmentMasks) {
1322 result.append("line");
1323 first = false;
1324 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1325 }
1326 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1327 if (!first) {
1328 result.append(" ");
1329 }
1330 result.append("quad");
1331 first = false;
1332 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1333 }
1334 if (SkPath::kConic_SegmentMask & segmentMasks) {
1335 if (!first) {
1336 result.append(" ");
1337 }
1338 result.append("conic");
1339 first = false;
1340 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1341 }
1342 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1343 if (!first) {
1344 result.append(" ");
1345 }
1346 result.append("cubic");
1347 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1348 }
1349 SkASSERT(0 == segmentMasks);
1350 return result;
1351}
1352
krajcevski95498ed2014-08-18 08:02:33 -07001353static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001354 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1355 SkLua(L).pushString(segment_masks_to_str(segMasks));
1356 return 1;
1357}
1358
1359static int lpath_isConvex(lua_State* L) {
1360 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1361 SkLua(L).pushBool(isConvex);
1362 return 1;
1363}
1364
reed@google.com74ce6f02013-05-22 15:13:18 +00001365static int lpath_isEmpty(lua_State* L) {
1366 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1367 return 1;
1368}
1369
1370static int lpath_isRect(lua_State* L) {
1371 SkRect r;
1372 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1373 int ret_count = 1;
1374 lua_pushboolean(L, pred);
1375 if (pred) {
1376 SkLua(L).pushRect(r);
1377 ret_count += 1;
1378 }
1379 return ret_count;
1380}
1381
1382static const char* dir2string(SkPath::Direction dir) {
1383 static const char* gStr[] = {
1384 "unknown", "cw", "ccw"
1385 };
1386 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1387 return gStr[dir];
1388}
1389
caryclark95bc5f32015-04-08 08:34:15 -07001390static int lpath_isNestedFillRects(lua_State* L) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001391 SkRect rects[2];
1392 SkPath::Direction dirs[2];
caryclark95bc5f32015-04-08 08:34:15 -07001393 bool pred = get_obj<SkPath>(L, 1)->isNestedFillRects(rects, dirs);
reed@google.com74ce6f02013-05-22 15:13:18 +00001394 int ret_count = 1;
1395 lua_pushboolean(L, pred);
1396 if (pred) {
1397 SkLua lua(L);
1398 lua.pushRect(rects[0]);
1399 lua.pushRect(rects[1]);
1400 lua_pushstring(L, dir2string(dirs[0]));
1401 lua_pushstring(L, dir2string(dirs[0]));
1402 ret_count += 4;
1403 }
1404 return ret_count;
1405}
1406
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001407static int lpath_countPoints(lua_State* L) {
1408 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1409 return 1;
1410}
1411
hstern0b401ce2016-08-02 09:17:59 -07001412static int lpath_getVerbs(lua_State* L) {
1413 const SkPath* path = get_obj<SkPath>(L, 1);
1414 SkPath::Iter iter(*path, false);
1415 SkPoint pts[4];
1416
1417 lua_newtable(L);
1418
1419 bool done = false;
1420 int i = 0;
1421 do {
1422 switch (iter.next(pts, true)) {
1423 case SkPath::kMove_Verb:
1424 setarray_string(L, ++i, "move");
1425 break;
1426 case SkPath::kClose_Verb:
1427 setarray_string(L, ++i, "close");
1428 break;
1429 case SkPath::kLine_Verb:
1430 setarray_string(L, ++i, "line");
1431 break;
1432 case SkPath::kQuad_Verb:
1433 setarray_string(L, ++i, "quad");
1434 break;
1435 case SkPath::kConic_Verb:
1436 setarray_string(L, ++i, "conic");
1437 break;
1438 case SkPath::kCubic_Verb:
1439 setarray_string(L, ++i, "cubic");
1440 break;
1441 case SkPath::kDone_Verb:
1442 setarray_string(L, ++i, "done");
1443 done = true;
1444 break;
1445 }
1446 } while (!done);
1447
1448 return 1;
1449}
1450
reed@google.com74ce6f02013-05-22 15:13:18 +00001451static int lpath_reset(lua_State* L) {
1452 get_obj<SkPath>(L, 1)->reset();
1453 return 0;
1454}
1455
1456static int lpath_moveTo(lua_State* L) {
1457 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1458 return 0;
1459}
1460
1461static int lpath_lineTo(lua_State* L) {
1462 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1463 return 0;
1464}
1465
1466static int lpath_quadTo(lua_State* L) {
1467 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1468 lua2scalar(L, 4), lua2scalar(L, 5));
1469 return 0;
1470}
1471
1472static int lpath_cubicTo(lua_State* L) {
1473 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1474 lua2scalar(L, 4), lua2scalar(L, 5),
1475 lua2scalar(L, 6), lua2scalar(L, 7));
1476 return 0;
1477}
1478
1479static int lpath_close(lua_State* L) {
1480 get_obj<SkPath>(L, 1)->close();
1481 return 0;
1482}
1483
1484static int lpath_gc(lua_State* L) {
1485 get_obj<SkPath>(L, 1)->~SkPath();
1486 return 0;
1487}
1488
1489static const struct luaL_Reg gSkPath_Methods[] = {
1490 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001491 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001492 { "getSegmentTypes", lpath_getSegmentTypes },
hstern0b401ce2016-08-02 09:17:59 -07001493 { "getVerbs", lpath_getVerbs },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001494 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001495 { "isEmpty", lpath_isEmpty },
1496 { "isRect", lpath_isRect },
caryclark95bc5f32015-04-08 08:34:15 -07001497 { "isNestedFillRects", lpath_isNestedFillRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001498 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001499 { "reset", lpath_reset },
1500 { "moveTo", lpath_moveTo },
1501 { "lineTo", lpath_lineTo },
1502 { "quadTo", lpath_quadTo },
1503 { "cubicTo", lpath_cubicTo },
1504 { "close", lpath_close },
1505 { "__gc", lpath_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001506 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001507};
1508
1509///////////////////////////////////////////////////////////////////////////////
1510
1511static const char* rrect_type(const SkRRect& rr) {
1512 switch (rr.getType()) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001513 case SkRRect::kEmpty_Type: return "empty";
1514 case SkRRect::kRect_Type: return "rect";
1515 case SkRRect::kOval_Type: return "oval";
1516 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001517 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001518 case SkRRect::kComplex_Type: return "complex";
1519 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001520 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001521 return "";
1522}
1523
1524static int lrrect_rect(lua_State* L) {
1525 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1526 return 1;
1527}
1528
1529static int lrrect_type(lua_State* L) {
1530 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1531 return 1;
1532}
1533
1534static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001535 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001536 SkVector v;
1537 if (corner < 0 || corner > 3) {
1538 SkDebugf("bad corner index %d", corner);
1539 v.set(0, 0);
1540 } else {
1541 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1542 }
1543 lua_pushnumber(L, v.fX);
1544 lua_pushnumber(L, v.fY);
1545 return 2;
1546}
1547
1548static int lrrect_gc(lua_State* L) {
1549 get_obj<SkRRect>(L, 1)->~SkRRect();
1550 return 0;
1551}
1552
1553static const struct luaL_Reg gSkRRect_Methods[] = {
1554 { "rect", lrrect_rect },
1555 { "type", lrrect_type },
1556 { "radii", lrrect_radii },
1557 { "__gc", lrrect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001558 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001559};
1560
1561///////////////////////////////////////////////////////////////////////////////
1562
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001563static int limage_width(lua_State* L) {
1564 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1565 return 1;
1566}
1567
1568static int limage_height(lua_State* L) {
1569 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1570 return 1;
1571}
1572
reed7a72c672014-11-07 10:23:55 -08001573static int limage_newShader(lua_State* L) {
1574 SkShader::TileMode tmode = SkShader::kClamp_TileMode;
halcanary96fcdcc2015-08-27 07:41:13 -07001575 const SkMatrix* localM = nullptr;
reed5671c5b2016-03-09 14:47:34 -08001576 push_ref(L, get_ref<SkImage>(L, 1)->makeShader(tmode, tmode, localM));
reed7a72c672014-11-07 10:23:55 -08001577 return 1;
1578}
1579
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001580static int limage_gc(lua_State* L) {
1581 get_ref<SkImage>(L, 1)->unref();
1582 return 0;
1583}
1584
1585static const struct luaL_Reg gSkImage_Methods[] = {
1586 { "width", limage_width },
1587 { "height", limage_height },
reed7a72c672014-11-07 10:23:55 -08001588 { "newShader", limage_newShader },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001589 { "__gc", limage_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001590 { nullptr, nullptr }
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001591};
1592
1593///////////////////////////////////////////////////////////////////////////////
1594
reed485557f2014-10-12 10:36:47 -07001595static int lsurface_width(lua_State* L) {
1596 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1597 return 1;
1598}
1599
1600static int lsurface_height(lua_State* L) {
1601 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1602 return 1;
1603}
1604
1605static int lsurface_getCanvas(lua_State* L) {
1606 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001607 if (nullptr == canvas) {
reed485557f2014-10-12 10:36:47 -07001608 lua_pushnil(L);
1609 } else {
Mike Reed5df49342016-11-12 08:06:55 -06001610 push_ptr(L, canvas);
reed485557f2014-10-12 10:36:47 -07001611 // note: we don't unref canvas, since getCanvas did not ref it.
1612 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1613 // the real owner (the surface) go away, but still hold onto the canvas?
1614 // *really* we want to sort of ref the surface again, but have the native object
1615 // know that it is supposed to be treated as a canvas...
1616 }
1617 return 1;
1618}
1619
1620static int lsurface_newImageSnapshot(lua_State* L) {
reed9ce9d672016-03-17 10:51:11 -07001621 sk_sp<SkImage> image = get_ref<SkSurface>(L, 1)->makeImageSnapshot();
1622 if (!image) {
reed485557f2014-10-12 10:36:47 -07001623 lua_pushnil(L);
1624 } else {
reed9ce9d672016-03-17 10:51:11 -07001625 push_ref(L, image);
reed485557f2014-10-12 10:36:47 -07001626 }
1627 return 1;
1628}
1629
1630static int lsurface_newSurface(lua_State* L) {
1631 int width = lua2int_def(L, 2, 0);
reed96affcd2014-10-13 12:38:04 -07001632 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -07001633 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -07001634 auto surface = get_ref<SkSurface>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -07001635 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07001636 lua_pushnil(L);
1637 } else {
reede8f30622016-03-23 18:59:25 -07001638 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07001639 }
1640 return 1;
1641}
1642
1643static int lsurface_gc(lua_State* L) {
1644 get_ref<SkSurface>(L, 1)->unref();
1645 return 0;
1646}
1647
1648static const struct luaL_Reg gSkSurface_Methods[] = {
1649 { "width", lsurface_width },
1650 { "height", lsurface_height },
1651 { "getCanvas", lsurface_getCanvas },
1652 { "newImageSnapshot", lsurface_newImageSnapshot },
1653 { "newSurface", lsurface_newSurface },
1654 { "__gc", lsurface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001655 { nullptr, nullptr }
reed485557f2014-10-12 10:36:47 -07001656};
1657
1658///////////////////////////////////////////////////////////////////////////////
1659
reed96affcd2014-10-13 12:38:04 -07001660static int lpicturerecorder_beginRecording(lua_State* L) {
1661 const SkScalar w = lua2scalar_def(L, 2, -1);
1662 const SkScalar h = lua2scalar_def(L, 3, -1);
1663 if (w <= 0 || h <= 0) {
1664 lua_pushnil(L);
1665 return 1;
1666 }
1667
1668 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
halcanary96fcdcc2015-08-27 07:41:13 -07001669 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001670 lua_pushnil(L);
1671 return 1;
1672 }
1673
Mike Reed5df49342016-11-12 08:06:55 -06001674 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001675 return 1;
1676}
1677
1678static int lpicturerecorder_getCanvas(lua_State* L) {
1679 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001680 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001681 lua_pushnil(L);
1682 return 1;
1683 }
Mike Reed5df49342016-11-12 08:06:55 -06001684 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001685 return 1;
1686}
1687
1688static int lpicturerecorder_endRecording(lua_State* L) {
reedca2622b2016-03-18 07:25:55 -07001689 sk_sp<SkPicture> pic = get_obj<SkPictureRecorder>(L, 1)->finishRecordingAsPicture();
1690 if (!pic) {
reed96affcd2014-10-13 12:38:04 -07001691 lua_pushnil(L);
1692 return 1;
1693 }
reedca2622b2016-03-18 07:25:55 -07001694 push_ref(L, std::move(pic));
reed96affcd2014-10-13 12:38:04 -07001695 return 1;
1696}
1697
1698static int lpicturerecorder_gc(lua_State* L) {
1699 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1700 return 0;
1701}
1702
1703static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1704 { "beginRecording", lpicturerecorder_beginRecording },
1705 { "getCanvas", lpicturerecorder_getCanvas },
1706 { "endRecording", lpicturerecorder_endRecording },
1707 { "__gc", lpicturerecorder_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001708 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001709};
1710
1711///////////////////////////////////////////////////////////////////////////////
1712
1713static int lpicture_width(lua_State* L) {
1714 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1715 return 1;
1716}
1717
1718static int lpicture_height(lua_State* L) {
1719 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1720 return 1;
1721}
1722
1723static int lpicture_gc(lua_State* L) {
1724 get_ref<SkPicture>(L, 1)->unref();
1725 return 0;
1726}
1727
1728static const struct luaL_Reg gSkPicture_Methods[] = {
1729 { "width", lpicture_width },
1730 { "height", lpicture_height },
1731 { "__gc", lpicture_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001732 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001733};
1734
1735///////////////////////////////////////////////////////////////////////////////
1736
reed1b6ab442014-11-03 19:55:41 -08001737static int ltextblob_bounds(lua_State* L) {
1738 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
1739 return 1;
1740}
1741
1742static int ltextblob_gc(lua_State* L) {
1743 SkSafeUnref(get_ref<SkTextBlob>(L, 1));
1744 return 0;
1745}
1746
1747static const struct luaL_Reg gSkTextBlob_Methods[] = {
1748 { "bounds", ltextblob_bounds },
1749 { "__gc", ltextblob_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001750 { nullptr, nullptr }
reed1b6ab442014-11-03 19:55:41 -08001751};
1752
1753///////////////////////////////////////////////////////////////////////////////
1754
reed36c9c112014-11-04 10:58:42 -08001755static int ltypeface_getFamilyName(lua_State* L) {
1756 SkString str;
1757 get_ref<SkTypeface>(L, 1)->getFamilyName(&str);
1758 lua_pushstring(L, str.c_str());
1759 return 1;
1760}
1761
1762static int ltypeface_getStyle(lua_State* L) {
Ben Wagner26308e12017-08-08 15:23:47 -04001763 push_obj(L, get_ref<SkTypeface>(L, 1)->fontStyle());
reed36c9c112014-11-04 10:58:42 -08001764 return 1;
1765}
1766
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001767static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001768 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001769 return 0;
1770}
1771
1772static const struct luaL_Reg gSkTypeface_Methods[] = {
reed36c9c112014-11-04 10:58:42 -08001773 { "getFamilyName", ltypeface_getFamilyName },
1774 { "getStyle", ltypeface_getStyle },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001775 { "__gc", ltypeface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001776 { nullptr, nullptr }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001777};
1778
1779///////////////////////////////////////////////////////////////////////////////
1780
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001781static int lfontstyle_weight(lua_State* L) {
1782 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->weight());
1783 return 1;
1784}
1785
1786static int lfontstyle_width(lua_State* L) {
1787 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->width());
1788 return 1;
1789}
1790
1791static int lfontstyle_slant(lua_State* L) {
1792 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->slant());
1793 return 1;
1794}
1795
1796static int lfontstyle_gc(lua_State* L) {
1797 get_obj<SkFontStyle>(L, 1)->~SkFontStyle();
1798 return 0;
1799}
1800
1801static const struct luaL_Reg gSkFontStyle_Methods[] = {
1802 { "weight", lfontstyle_weight },
1803 { "width", lfontstyle_width },
1804 { "slant", lfontstyle_slant },
1805 { "__gc", lfontstyle_gc },
1806 { nullptr, nullptr }
1807};
1808
1809///////////////////////////////////////////////////////////////////////////////
1810
reed@google.com74ce6f02013-05-22 15:13:18 +00001811class AutoCallLua {
1812public:
1813 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1814 lua_getglobal(L, func);
1815 if (!lua_isfunction(L, -1)) {
1816 int t = lua_type(L, -1);
1817 SkDebugf("--- expected function %d\n", t);
1818 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001819
reed@google.com74ce6f02013-05-22 15:13:18 +00001820 lua_newtable(L);
1821 setfield_string(L, "verb", verb);
1822 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001823
reed@google.com74ce6f02013-05-22 15:13:18 +00001824 ~AutoCallLua() {
1825 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1826 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1827 }
1828 lua_settop(fL, -1);
1829 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001830
reed@google.com74ce6f02013-05-22 15:13:18 +00001831private:
1832 lua_State* fL;
1833};
1834
1835#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1836
1837///////////////////////////////////////////////////////////////////////////////
1838
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001839static int lsk_newDocumentPDF(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -05001840 const char* filename = nullptr;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001841 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
Mike Reed7ff6ca52018-01-08 14:45:31 -05001842 filename = lua_tolstring(L, 1, nullptr);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001843 }
Mike Reed7ff6ca52018-01-08 14:45:31 -05001844 if (!filename) {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001845 return 0;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001846 }
Mike Reed7ff6ca52018-01-08 14:45:31 -05001847 auto file = skstd::make_unique<SkFILEWStream>(filename);
1848 if (!file->isValid()) {
1849 return 0;
1850 }
Hal Canary23564b92018-09-07 14:33:14 -04001851 sk_sp<SkDocument> doc = SkPDF::MakeDocument(file.get());
Mike Reed7ff6ca52018-01-08 14:45:31 -05001852 if (!doc) {
1853 return 0;
1854 }
1855 push_ptr(L, new DocHolder{std::move(doc), std::move(file)});
1856 return 1;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001857}
1858
reed468b1812014-10-19 11:42:54 -07001859static int lsk_newBlurImageFilter(lua_State* L) {
1860 SkScalar sigmaX = lua2scalar_def(L, 1, 0);
1861 SkScalar sigmaY = lua2scalar_def(L, 2, 0);
robertphillips6e7025a2016-04-04 04:31:25 -07001862 sk_sp<SkImageFilter> imf(SkBlurImageFilter::Make(sigmaX, sigmaY, nullptr));
1863 if (!imf) {
reed468b1812014-10-19 11:42:54 -07001864 lua_pushnil(L);
1865 } else {
robertphillips6e7025a2016-04-04 04:31:25 -07001866 push_ref(L, std::move(imf));
reed9fbc3f32014-10-21 07:12:58 -07001867 }
1868 return 1;
1869}
1870
1871static int lsk_newLinearGradient(lua_State* L) {
1872 SkScalar x0 = lua2scalar_def(L, 1, 0);
1873 SkScalar y0 = lua2scalar_def(L, 2, 0);
1874 SkColor c0 = lua2color(L, 3);
1875 SkScalar x1 = lua2scalar_def(L, 4, 0);
1876 SkScalar y1 = lua2scalar_def(L, 5, 0);
1877 SkColor c1 = lua2color(L, 6);
1878
1879 SkPoint pts[] = { { x0, y0 }, { x1, y1 } };
1880 SkColor colors[] = { c0, c1 };
robertphillips6e7025a2016-04-04 04:31:25 -07001881 sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
1882 SkShader::kClamp_TileMode));
reed2ad1aa62016-03-09 09:50:50 -08001883 if (!s) {
reed9fbc3f32014-10-21 07:12:58 -07001884 lua_pushnil(L);
1885 } else {
reed2ad1aa62016-03-09 09:50:50 -08001886 push_ref(L, std::move(s));
reed468b1812014-10-19 11:42:54 -07001887 }
1888 return 1;
1889}
1890
reedbdc49ae2014-10-14 09:34:52 -07001891static int lsk_newMatrix(lua_State* L) {
1892 push_new<SkMatrix>(L)->reset();
1893 return 1;
1894}
1895
reed@google.com3597b732013-05-22 20:12:50 +00001896static int lsk_newPaint(lua_State* L) {
1897 push_new<SkPaint>(L);
1898 return 1;
1899}
1900
1901static int lsk_newPath(lua_State* L) {
1902 push_new<SkPath>(L);
1903 return 1;
1904}
1905
reed96affcd2014-10-13 12:38:04 -07001906static int lsk_newPictureRecorder(lua_State* L) {
1907 push_new<SkPictureRecorder>(L);
1908 return 1;
1909}
1910
reed@google.com3597b732013-05-22 20:12:50 +00001911static int lsk_newRRect(lua_State* L) {
reedbdc49ae2014-10-14 09:34:52 -07001912 push_new<SkRRect>(L)->setEmpty();
reed@google.com3597b732013-05-22 20:12:50 +00001913 return 1;
1914}
1915
reed1b6ab442014-11-03 19:55:41 -08001916// Sk.newTextBlob(text, rect, paint)
1917static int lsk_newTextBlob(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001918 const char* text = lua_tolstring(L, 1, nullptr);
reed1b6ab442014-11-03 19:55:41 -08001919 SkRect bounds;
1920 lua2rect(L, 2, &bounds);
1921 const SkPaint& paint = *get_obj<SkPaint>(L, 3);
1922
Herb Derby1724db12018-05-22 12:01:50 -04001923 SkShaper shaper(nullptr);
reed1b6ab442014-11-03 19:55:41 -08001924
Hal Canary2a1848d2018-11-26 17:23:24 -05001925 SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
Herb Derby1724db12018-05-22 12:01:50 -04001926 SkTextBlobBuilder builder;
Hal Canary2a1848d2018-11-26 17:23:24 -05001927 SkPoint end = shaper.shape(&builder, font, text, strlen(text), true,
Herb Derby1724db12018-05-22 12:01:50 -04001928 { bounds.left(), bounds.top() }, bounds.width());
1929
1930 push_ref<SkTextBlob>(L, builder.make());
1931 SkLua(L).pushScalar(end.fY);
reed1b6ab442014-11-03 19:55:41 -08001932 return 2;
1933}
1934
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001935static int lsk_newTypeface(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001936 const char* name = nullptr;
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001937 SkFontStyle style;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00001938
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001939 int count = lua_gettop(L);
1940 if (count > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001941 name = lua_tolstring(L, 1, nullptr);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001942 if (count > 1) {
1943 SkFontStyle* passedStyle = get_obj<SkFontStyle>(L, 2);
1944 if (passedStyle) {
1945 style = *passedStyle;
1946 }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001947 }
1948 }
1949
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001950 sk_sp<SkTypeface> face(SkTypeface::MakeFromName(name, style));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001951// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
halcanary96fcdcc2015-08-27 07:41:13 -07001952 if (nullptr == face) {
bungeman13b9c952016-05-12 10:09:30 -07001953 face = SkTypeface::MakeDefault();
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001954 }
bungeman13b9c952016-05-12 10:09:30 -07001955 push_ref(L, std::move(face));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001956 return 1;
1957}
reed@google.com3597b732013-05-22 20:12:50 +00001958
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001959static int lsk_newFontStyle(lua_State* L) {
1960 int count = lua_gettop(L);
1961 int weight = SkFontStyle::kNormal_Weight;
1962 int width = SkFontStyle::kNormal_Width;
1963 SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
1964 if (count >= 1 && lua_isnumber(L, 1)) {
1965 weight = lua_tointegerx(L, 1, nullptr);
1966 }
1967 if (count >= 2 && lua_isnumber(L, 2)) {
1968 width = lua_tointegerx(L, 2, nullptr);
1969 }
1970 if (count >= 3 && lua_isnumber(L, 3)) {
1971 slant = static_cast<SkFontStyle::Slant>(lua_tointegerx(L, 3, nullptr));
1972 }
1973 push_new<SkFontStyle>(L, weight, width, slant);
1974 return 1;
1975}
1976
reed485557f2014-10-12 10:36:47 -07001977static int lsk_newRasterSurface(lua_State* L) {
reed7b864662014-11-04 13:24:47 -08001978 int width = lua2int_def(L, 1, 0);
reed485557f2014-10-12 10:36:47 -07001979 int height = lua2int_def(L, 2, 0);
1980 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
robertphillips702edbd2015-06-23 06:26:08 -07001981 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
reede8f30622016-03-23 18:59:25 -07001982 auto surface = SkSurface::MakeRaster(info, &props);
halcanary96fcdcc2015-08-27 07:41:13 -07001983 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07001984 lua_pushnil(L);
1985 } else {
reede8f30622016-03-23 18:59:25 -07001986 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07001987 }
1988 return 1;
1989}
1990
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001991static int lsk_loadImage(lua_State* L) {
1992 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001993 const char* name = lua_tolstring(L, 1, nullptr);
reed9ce9d672016-03-17 10:51:11 -07001994 sk_sp<SkData> data(SkData::MakeFromFileName(name));
1995 if (data) {
1996 auto image = SkImage::MakeFromEncoded(std::move(data));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001997 if (image) {
reed9ce9d672016-03-17 10:51:11 -07001998 push_ref(L, std::move(image));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001999 return 1;
2000 }
2001 }
2002 }
2003 return 0;
2004}
2005
reed@google.com3597b732013-05-22 20:12:50 +00002006static void register_Sk(lua_State* L) {
2007 lua_newtable(L);
2008 lua_pushvalue(L, -1);
2009 lua_setglobal(L, "Sk");
2010 // the Sk table is still on top
2011
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00002012 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002013 setfield_function(L, "loadImage", lsk_loadImage);
reed468b1812014-10-19 11:42:54 -07002014 setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
reed9fbc3f32014-10-21 07:12:58 -07002015 setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
reedbdc49ae2014-10-14 09:34:52 -07002016 setfield_function(L, "newMatrix", lsk_newMatrix);
reed@google.com3597b732013-05-22 20:12:50 +00002017 setfield_function(L, "newPaint", lsk_newPaint);
2018 setfield_function(L, "newPath", lsk_newPath);
reed96affcd2014-10-13 12:38:04 -07002019 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
reed@google.com3597b732013-05-22 20:12:50 +00002020 setfield_function(L, "newRRect", lsk_newRRect);
reed485557f2014-10-12 10:36:47 -07002021 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
reed1b6ab442014-11-03 19:55:41 -08002022 setfield_function(L, "newTextBlob", lsk_newTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002023 setfield_function(L, "newTypeface", lsk_newTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002024 setfield_function(L, "newFontStyle", lsk_newFontStyle);
reed@google.com3597b732013-05-22 20:12:50 +00002025 lua_pop(L, 1); // pop off the Sk table
2026}
2027
reed@google.com74ce6f02013-05-22 15:13:18 +00002028#define REG_CLASS(L, C) \
2029 do { \
reed@google.com3597b732013-05-22 20:12:50 +00002030 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00002031 lua_pushvalue(L, -1); \
2032 lua_setfield(L, -2, "__index"); \
2033 luaL_setfuncs(L, g##C##_Methods, 0); \
2034 lua_pop(L, 1); /* pop off the meta-table */ \
2035 } while (0)
2036
2037void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00002038 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00002039 REG_CLASS(L, SkCanvas);
reed22a517f2015-12-04 20:45:59 -08002040 REG_CLASS(L, SkColorFilter);
Mike Reed7ff6ca52018-01-08 14:45:31 -05002041 REG_CLASS(L, DocHolder);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002042 REG_CLASS(L, SkImage);
reed468b1812014-10-19 11:42:54 -07002043 REG_CLASS(L, SkImageFilter);
reed1b6ab442014-11-03 19:55:41 -08002044 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00002045 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00002046 REG_CLASS(L, SkPath);
2047 REG_CLASS(L, SkPathEffect);
reed96affcd2014-10-13 12:38:04 -07002048 REG_CLASS(L, SkPicture);
2049 REG_CLASS(L, SkPictureRecorder);
reed@google.com74ce6f02013-05-22 15:13:18 +00002050 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00002051 REG_CLASS(L, SkShader);
reed485557f2014-10-12 10:36:47 -07002052 REG_CLASS(L, SkSurface);
reed1b6ab442014-11-03 19:55:41 -08002053 REG_CLASS(L, SkTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002054 REG_CLASS(L, SkTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002055 REG_CLASS(L, SkFontStyle);
reed@google.com74ce6f02013-05-22 15:13:18 +00002056}
zachr@google.com28c27c82013-06-20 17:15:05 +00002057
reed@google.com7bce9982013-06-20 17:40:21 +00002058extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00002059extern "C" int luaopen_skia(lua_State* L) {
2060 SkLua::Load(L);
2061 return 0;
2062}