blob: 53e8bb33a5c120e8cc2698ebe6fdb5ebf4c4f1d8 [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"
mike@reedtribe.orgfb858242013-06-08 16:39:44 +000018#include "SkDocument.h"
Ben Wagnerc6c10b42017-08-07 09:56:21 -040019#include "SkFontStyle.h"
reed9fbc3f32014-10-21 07:12:58 -070020#include "SkGradientShader.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000021#include "SkImage.h"
Mike Reed7ff6ca52018-01-08 14:45:31 -050022#include "SkMakeUnique.h"
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000023#include "SkMatrix.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.com5fdc9832013-07-24 15:47:52 +000027#include "SkPixelRef.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000028#include "SkRRect.h"
Herb Derby1724db12018-05-22 12:01:50 -040029#include "SkShaper.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000030#include "SkString.h"
reed485557f2014-10-12 10:36:47 -070031#include "SkSurface.h"
fmalitab7425172014-08-26 07:56:44 -070032#include "SkTextBlob.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_isDevKernText(lua_State* L) {
751 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
752 return 1;
753}
754
755static int lpaint_isLCDRenderText(lua_State* L) {
756 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
757 return 1;
758}
759
reed36c9c112014-11-04 10:58:42 -0800760static int lpaint_setLCDRenderText(lua_State* L) {
761 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2));
762 return 1;
763}
764
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000765static int lpaint_isEmbeddedBitmapText(lua_State* L) {
766 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
767 return 1;
768}
769
770static int lpaint_isAutohinted(lua_State* L) {
771 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
772 return 1;
773}
774
775static int lpaint_isVerticalText(lua_State* L) {
776 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
777 return 1;
778}
779
reed468b1812014-10-19 11:42:54 -0700780static int lpaint_getAlpha(lua_State* L) {
781 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha()));
782 return 1;
783}
784
785static int lpaint_setAlpha(lua_State* L) {
786 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2)));
787 return 0;
788}
789
reed@google.com74ce6f02013-05-22 15:13:18 +0000790static int lpaint_getColor(lua_State* L) {
791 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
792 return 1;
793}
794
795static int lpaint_setColor(lua_State* L) {
796 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
797 return 0;
798}
799
reed@google.come3823fd2013-05-30 18:55:14 +0000800static int lpaint_getTextSize(lua_State* L) {
801 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
802 return 1;
803}
804
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000805static int lpaint_getTextScaleX(lua_State* L) {
806 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
807 return 1;
808}
809
810static int lpaint_getTextSkewX(lua_State* L) {
811 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
812 return 1;
813}
814
reed@google.come3823fd2013-05-30 18:55:14 +0000815static int lpaint_setTextSize(lua_State* L) {
816 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
817 return 0;
818}
819
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000820static int lpaint_getTypeface(lua_State* L) {
821 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
822 return 1;
823}
824
825static int lpaint_setTypeface(lua_State* L) {
bungeman13b9c952016-05-12 10:09:30 -0700826 get_obj<SkPaint>(L, 1)->setTypeface(sk_ref_sp(get_ref<SkTypeface>(L, 2)));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000827 return 0;
828}
829
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000830static int lpaint_getHinting(lua_State* L) {
831 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
832 return 1;
833}
834
reed93a12152015-03-16 10:08:34 -0700835static int lpaint_getFilterQuality(lua_State* L) {
836 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality());
reed7a72c672014-11-07 10:23:55 -0800837 return 1;
838}
839
reed93a12152015-03-16 10:08:34 -0700840static int lpaint_setFilterQuality(lua_State* L) {
reed7a72c672014-11-07 10:23:55 -0800841 int level = lua2int_def(L, 2, -1);
842 if (level >= 0 && level <= 3) {
reed93a12152015-03-16 10:08:34 -0700843 get_obj<SkPaint>(L, 1)->setFilterQuality((SkFilterQuality)level);
reed7a72c672014-11-07 10:23:55 -0800844 }
845 return 0;
846}
847
reed@google.come3823fd2013-05-30 18:55:14 +0000848static int lpaint_getFontID(lua_State* L) {
849 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
850 SkLua(L).pushU32(SkTypeface::UniqueID(face));
851 return 1;
852}
853
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000854static const struct {
855 const char* fLabel;
856 SkPaint::Align fAlign;
857} gAlignRec[] = {
858 { "left", SkPaint::kLeft_Align },
859 { "center", SkPaint::kCenter_Align },
860 { "right", SkPaint::kRight_Align },
861};
862
863static int lpaint_getTextAlign(lua_State* L) {
864 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
865 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
866 if (gAlignRec[i].fAlign == align) {
867 lua_pushstring(L, gAlignRec[i].fLabel);
868 return 1;
869 }
870 }
871 return 0;
872}
873
874static int lpaint_setTextAlign(lua_State* L) {
875 if (lua_isstring(L, 2)) {
876 size_t len;
877 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000878
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000879 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
880 if (!strcmp(gAlignRec[i].fLabel, label)) {
881 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
882 break;
883 }
884 }
885 }
886 return 0;
887}
888
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000889static int lpaint_getStroke(lua_State* L) {
890 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
891 return 1;
892}
893
894static int lpaint_setStroke(lua_State* L) {
895 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000896
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000897 if (lua_toboolean(L, 2)) {
898 style = SkPaint::kStroke_Style;
899 } else {
900 style = SkPaint::kFill_Style;
901 }
902 get_obj<SkPaint>(L, 1)->setStyle(style);
903 return 0;
904}
905
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000906static int lpaint_getStrokeCap(lua_State* L) {
907 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
908 return 1;
909}
910
911static int lpaint_getStrokeJoin(lua_State* L) {
912 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
913 return 1;
914}
915
916static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +0000917 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000918 return 1;
919}
920
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000921static int lpaint_getStrokeWidth(lua_State* L) {
922 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
923 return 1;
924}
925
926static int lpaint_setStrokeWidth(lua_State* L) {
927 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
928 return 0;
929}
930
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000931static int lpaint_getStrokeMiter(lua_State* L) {
932 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
933 return 1;
934}
935
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000936static int lpaint_measureText(lua_State* L) {
937 if (lua_isstring(L, 2)) {
938 size_t len;
939 const char* text = lua_tolstring(L, 2, &len);
940 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
941 return 1;
942 }
943 return 0;
944}
945
946struct FontMetrics {
947 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
948 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
949 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
950 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
951 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
952 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
953 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
954 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
955 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
956};
957
958static int lpaint_getFontMetrics(lua_State* L) {
959 SkPaint::FontMetrics fm;
960 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000961
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000962 lua_newtable(L);
963 setfield_scalar(L, "top", fm.fTop);
964 setfield_scalar(L, "ascent", fm.fAscent);
965 setfield_scalar(L, "descent", fm.fDescent);
966 setfield_scalar(L, "bottom", fm.fBottom);
967 setfield_scalar(L, "leading", fm.fLeading);
968 SkLua(L).pushScalar(height);
969 return 2;
970}
971
reed@google.com29563872013-07-10 21:23:49 +0000972static int lpaint_getEffects(lua_State* L) {
973 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000974
reed@google.com29563872013-07-10 21:23:49 +0000975 lua_newtable(L);
reed468b1812014-10-19 11:42:54 -0700976 setfield_bool_if(L, "looper", !!paint->getLooper());
977 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
reed468b1812014-10-19 11:42:54 -0700978 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
979 setfield_bool_if(L, "shader", !!paint->getShader());
reed@google.com29563872013-07-10 21:23:49 +0000980 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
981 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
reed@google.com29563872013-07-10 21:23:49 +0000982 return 1;
983}
984
reed22a517f2015-12-04 20:45:59 -0800985static int lpaint_getColorFilter(lua_State* L) {
986 const SkPaint* paint = get_obj<SkPaint>(L, 1);
987 SkColorFilter* cf = paint->getColorFilter();
988 if (cf) {
989 push_ref(L, cf);
990 return 1;
991 }
992 return 0;
993}
994
995static int lpaint_setColorFilter(lua_State* L) {
996 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedd053ce92016-03-22 10:17:23 -0700997 paint->setColorFilter(sk_ref_sp(get_ref<SkColorFilter>(L, 2)));
reed22a517f2015-12-04 20:45:59 -0800998 return 0;
999}
1000
reed468b1812014-10-19 11:42:54 -07001001static int lpaint_getImageFilter(lua_State* L) {
1002 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1003 SkImageFilter* imf = paint->getImageFilter();
1004 if (imf) {
1005 push_ref(L, imf);
1006 return 1;
1007 }
1008 return 0;
1009}
1010
1011static int lpaint_setImageFilter(lua_State* L) {
1012 SkPaint* paint = get_obj<SkPaint>(L, 1);
Mike Reed5e257172016-11-01 11:22:05 -04001013 paint->setImageFilter(sk_ref_sp(get_ref<SkImageFilter>(L, 2)));
reed468b1812014-10-19 11:42:54 -07001014 return 0;
1015}
1016
reed@google.com5fdc9832013-07-24 15:47:52 +00001017static int lpaint_getShader(lua_State* L) {
1018 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1019 SkShader* shader = paint->getShader();
1020 if (shader) {
1021 push_ref(L, shader);
1022 return 1;
1023 }
1024 return 0;
1025}
1026
reed9fbc3f32014-10-21 07:12:58 -07001027static int lpaint_setShader(lua_State* L) {
1028 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedfe630452016-03-25 09:08:00 -07001029 paint->setShader(sk_ref_sp(get_ref<SkShader>(L, 2)));
reed9fbc3f32014-10-21 07:12:58 -07001030 return 0;
1031}
1032
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001033static int lpaint_getPathEffect(lua_State* L) {
1034 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1035 SkPathEffect* pe = paint->getPathEffect();
1036 if (pe) {
1037 push_ref(L, pe);
1038 return 1;
1039 }
1040 return 0;
1041}
1042
hstern0b401ce2016-08-02 09:17:59 -07001043static int lpaint_getFillPath(lua_State* L) {
1044 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1045 const SkPath* path = get_obj<SkPath>(L, 2);
1046
1047 SkPath fillpath;
1048 paint->getFillPath(*path, &fillpath);
1049
1050 SkLua lua(L);
1051 lua.pushPath(fillpath);
1052
1053 return 1;
1054}
1055
reed@google.com74ce6f02013-05-22 15:13:18 +00001056static int lpaint_gc(lua_State* L) {
1057 get_obj<SkPaint>(L, 1)->~SkPaint();
1058 return 0;
1059}
1060
1061static const struct luaL_Reg gSkPaint_Methods[] = {
1062 { "isAntiAlias", lpaint_isAntiAlias },
1063 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001064 { "isDither", lpaint_isDither },
reedbb8a0ab2014-11-03 22:32:07 -08001065 { "setDither", lpaint_setDither },
reed93a12152015-03-16 10:08:34 -07001066 { "getFilterQuality", lpaint_getFilterQuality },
1067 { "setFilterQuality", lpaint_setFilterQuality },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001068 { "isFakeBoldText", lpaint_isFakeBoldText },
1069 { "isLinearText", lpaint_isLinearText },
1070 { "isSubpixelText", lpaint_isSubpixelText },
reed09a1d672014-10-11 13:13:11 -07001071 { "setSubpixelText", lpaint_setSubpixelText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001072 { "isDevKernText", lpaint_isDevKernText },
1073 { "isLCDRenderText", lpaint_isLCDRenderText },
reed36c9c112014-11-04 10:58:42 -08001074 { "setLCDRenderText", lpaint_setLCDRenderText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001075 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
1076 { "isAutohinted", lpaint_isAutohinted },
1077 { "isVerticalText", lpaint_isVerticalText },
reed468b1812014-10-19 11:42:54 -07001078 { "getAlpha", lpaint_getAlpha },
1079 { "setAlpha", lpaint_setAlpha },
reed@google.com74ce6f02013-05-22 15:13:18 +00001080 { "getColor", lpaint_getColor },
1081 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +00001082 { "getTextSize", lpaint_getTextSize },
1083 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001084 { "getTextScaleX", lpaint_getTextScaleX },
1085 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001086 { "getTypeface", lpaint_getTypeface },
1087 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001088 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +00001089 { "getFontID", lpaint_getFontID },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001090 { "getTextAlign", lpaint_getTextAlign },
1091 { "setTextAlign", lpaint_setTextAlign },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001092 { "getStroke", lpaint_getStroke },
1093 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001094 { "getStrokeCap", lpaint_getStrokeCap },
1095 { "getStrokeJoin", lpaint_getStrokeJoin },
1096 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001097 { "getStrokeWidth", lpaint_getStrokeWidth },
1098 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001099 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001100 { "measureText", lpaint_measureText },
1101 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +00001102 { "getEffects", lpaint_getEffects },
reed22a517f2015-12-04 20:45:59 -08001103 { "getColorFilter", lpaint_getColorFilter },
1104 { "setColorFilter", lpaint_setColorFilter },
reed468b1812014-10-19 11:42:54 -07001105 { "getImageFilter", lpaint_getImageFilter },
1106 { "setImageFilter", lpaint_setImageFilter },
reed@google.com5fdc9832013-07-24 15:47:52 +00001107 { "getShader", lpaint_getShader },
reed9fbc3f32014-10-21 07:12:58 -07001108 { "setShader", lpaint_setShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001109 { "getPathEffect", lpaint_getPathEffect },
hstern0b401ce2016-08-02 09:17:59 -07001110 { "getFillPath", lpaint_getFillPath },
reed@google.com74ce6f02013-05-22 15:13:18 +00001111 { "__gc", lpaint_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001112 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001113};
1114
1115///////////////////////////////////////////////////////////////////////////////
1116
reed@google.com5fdc9832013-07-24 15:47:52 +00001117static const char* mode2string(SkShader::TileMode mode) {
1118 static const char* gNames[] = { "clamp", "repeat", "mirror" };
1119 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
1120 return gNames[mode];
1121}
1122
1123static const char* gradtype2string(SkShader::GradientType t) {
1124 static const char* gNames[] = {
1125 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
1126 };
1127 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
1128 return gNames[t];
1129}
1130
1131static int lshader_isOpaque(lua_State* L) {
1132 SkShader* shader = get_ref<SkShader>(L, 1);
1133 return shader && shader->isOpaque();
1134}
1135
Mike Reed627778d2016-09-28 17:13:38 -04001136static int lshader_isAImage(lua_State* L) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001137 SkShader* shader = get_ref<SkShader>(L, 1);
1138 if (shader) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001139 SkMatrix matrix;
1140 SkShader::TileMode modes[2];
Mike Reed627778d2016-09-28 17:13:38 -04001141 if (SkImage* image = shader->isAImage(&matrix, modes)) {
reedf5822822015-08-19 11:46:38 -07001142 lua_newtable(L);
Mike Reed627778d2016-09-28 17:13:38 -04001143 setfield_number(L, "id", image->uniqueID());
1144 setfield_number(L, "width", image->width());
1145 setfield_number(L, "height", image->height());
reedf5822822015-08-19 11:46:38 -07001146 setfield_string(L, "tileX", mode2string(modes[0]));
1147 setfield_string(L, "tileY", mode2string(modes[1]));
1148 return 1;
reed@google.com5fdc9832013-07-24 15:47:52 +00001149 }
1150 }
1151 return 0;
1152}
1153
1154static int lshader_asAGradient(lua_State* L) {
1155 SkShader* shader = get_ref<SkShader>(L, 1);
1156 if (shader) {
1157 SkShader::GradientInfo info;
1158 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001159
reed@google.com5fdc9832013-07-24 15:47:52 +00001160 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001161
reed@google.com5fdc9832013-07-24 15:47:52 +00001162 if (SkShader::kNone_GradientType != t) {
fmenozzib4f254e2016-06-28 14:03:03 -07001163 SkAutoTArray<SkScalar> pos(info.fColorCount);
1164 info.fColorOffsets = pos.get();
1165 shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001166
fmenozzib4f254e2016-06-28 14:03:03 -07001167 lua_newtable(L);
fmenozzi7f2c85e2016-07-12 09:17:39 -07001168 setfield_string(L, "type", gradtype2string(t));
1169 setfield_string(L, "tile", mode2string(info.fTileMode));
1170 setfield_number(L, "colorCount", info.fColorCount);
fmenozzib4f254e2016-06-28 14:03:03 -07001171
1172 lua_newtable(L);
1173 for (int i = 0; i < info.fColorCount; i++) {
1174 // Lua uses 1-based indexing
1175 setarray_scalar(L, i+1, pos[i]);
1176 }
1177 lua_setfield(L, -2, "positions");
1178
reed@google.com5fdc9832013-07-24 15:47:52 +00001179 return 1;
1180 }
1181 }
1182 return 0;
1183}
1184
1185static int lshader_gc(lua_State* L) {
1186 get_ref<SkShader>(L, 1)->unref();
1187 return 0;
1188}
1189
1190static const struct luaL_Reg gSkShader_Methods[] = {
1191 { "isOpaque", lshader_isOpaque },
Mike Reed627778d2016-09-28 17:13:38 -04001192 { "isAImage", lshader_isAImage },
reed@google.com5fdc9832013-07-24 15:47:52 +00001193 { "asAGradient", lshader_asAGradient },
1194 { "__gc", lshader_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001195 { nullptr, nullptr }
reed@google.com5fdc9832013-07-24 15:47:52 +00001196};
1197
1198///////////////////////////////////////////////////////////////////////////////
1199
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001200static int lpatheffect_asADash(lua_State* L) {
1201 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1202 if (pe) {
1203 SkPathEffect::DashInfo info;
1204 SkPathEffect::DashType dashType = pe->asADash(&info);
1205 if (SkPathEffect::kDash_DashType == dashType) {
1206 SkAutoTArray<SkScalar> intervals(info.fCount);
1207 info.fIntervals = intervals.get();
1208 pe->asADash(&info);
1209 SkLua(L).pushDash(info);
1210 return 1;
1211 }
1212 }
1213 return 0;
1214}
1215
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001216static int lpatheffect_gc(lua_State* L) {
1217 get_ref<SkPathEffect>(L, 1)->unref();
1218 return 0;
1219}
1220
1221static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001222 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001223 { "__gc", lpatheffect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001224 { nullptr, nullptr }
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001225};
1226
1227///////////////////////////////////////////////////////////////////////////////
1228
reed22a517f2015-12-04 20:45:59 -08001229static int lpcolorfilter_gc(lua_State* L) {
1230 get_ref<SkColorFilter>(L, 1)->unref();
1231 return 0;
1232}
1233
1234static const struct luaL_Reg gSkColorFilter_Methods[] = {
1235 { "__gc", lpcolorfilter_gc },
1236 { nullptr, nullptr }
1237};
1238
1239///////////////////////////////////////////////////////////////////////////////
1240
reed468b1812014-10-19 11:42:54 -07001241static int lpimagefilter_gc(lua_State* L) {
1242 get_ref<SkImageFilter>(L, 1)->unref();
1243 return 0;
1244}
1245
1246static const struct luaL_Reg gSkImageFilter_Methods[] = {
1247 { "__gc", lpimagefilter_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001248 { nullptr, nullptr }
reed468b1812014-10-19 11:42:54 -07001249};
1250
1251///////////////////////////////////////////////////////////////////////////////
1252
humper@google.com2815c192013-07-10 22:42:30 +00001253static int lmatrix_getType(lua_State* L) {
1254 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001255
humper@google.com2815c192013-07-10 22:42:30 +00001256 lua_newtable(L);
1257 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1258 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1259 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1260 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1261 return 1;
1262}
1263
humper@google.com0f48ee02013-07-26 15:23:43 +00001264static int lmatrix_getScaleX(lua_State* L) {
1265 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1266 return 1;
1267}
1268
1269static int lmatrix_getScaleY(lua_State* L) {
1270 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1271 return 1;
1272}
1273
1274static int lmatrix_getTranslateX(lua_State* L) {
1275 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1276 return 1;
1277}
1278
1279static int lmatrix_getTranslateY(lua_State* L) {
1280 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1281 return 1;
1282}
1283
reed7a72c672014-11-07 10:23:55 -08001284static int lmatrix_invert(lua_State* L) {
1285 lua_pushboolean(L, get_obj<SkMatrix>(L, 1)->invert(get_obj<SkMatrix>(L, 2)));
1286 return 1;
1287}
1288
1289static int lmatrix_mapXY(lua_State* L) {
1290 SkPoint pt = { lua2scalar(L, 2), lua2scalar(L, 3) };
1291 get_obj<SkMatrix>(L, 1)->mapPoints(&pt, &pt, 1);
1292 lua_pushnumber(L, pt.x());
1293 lua_pushnumber(L, pt.y());
1294 return 2;
1295}
1296
reedbdc49ae2014-10-14 09:34:52 -07001297static int lmatrix_setRectToRect(lua_State* L) {
1298 SkMatrix* matrix = get_obj<SkMatrix>(L, 1);
1299 SkRect srcR, dstR;
1300 lua2rect(L, 2, &srcR);
1301 lua2rect(L, 3, &dstR);
1302 const char* scaleToFitStr = lua_tostring(L, 4);
1303 SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit;
1304
1305 if (scaleToFitStr) {
1306 const struct {
1307 const char* fName;
1308 SkMatrix::ScaleToFit fScaleToFit;
1309 } rec[] = {
1310 { "fill", SkMatrix::kFill_ScaleToFit },
1311 { "start", SkMatrix::kStart_ScaleToFit },
1312 { "center", SkMatrix::kCenter_ScaleToFit },
1313 { "end", SkMatrix::kEnd_ScaleToFit },
1314 };
1315
1316 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
1317 if (strcmp(rec[i].fName, scaleToFitStr) == 0) {
1318 scaleToFit = rec[i].fScaleToFit;
1319 break;
1320 }
1321 }
1322 }
1323
1324 matrix->setRectToRect(srcR, dstR, scaleToFit);
1325 return 0;
1326}
1327
humper@google.com2815c192013-07-10 22:42:30 +00001328static const struct luaL_Reg gSkMatrix_Methods[] = {
1329 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001330 { "getScaleX", lmatrix_getScaleX },
1331 { "getScaleY", lmatrix_getScaleY },
1332 { "getTranslateX", lmatrix_getTranslateX },
1333 { "getTranslateY", lmatrix_getTranslateY },
reedbdc49ae2014-10-14 09:34:52 -07001334 { "setRectToRect", lmatrix_setRectToRect },
reed7a72c672014-11-07 10:23:55 -08001335 { "invert", lmatrix_invert },
1336 { "mapXY", lmatrix_mapXY },
halcanary96fcdcc2015-08-27 07:41:13 -07001337 { nullptr, nullptr }
humper@google.com2815c192013-07-10 22:42:30 +00001338};
1339
1340///////////////////////////////////////////////////////////////////////////////
1341
reed@google.com74ce6f02013-05-22 15:13:18 +00001342static int lpath_getBounds(lua_State* L) {
1343 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1344 return 1;
1345}
1346
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001347static const char* fill_type_to_str(SkPath::FillType fill) {
1348 switch (fill) {
1349 case SkPath::kEvenOdd_FillType:
1350 return "even-odd";
1351 case SkPath::kWinding_FillType:
1352 return "winding";
1353 case SkPath::kInverseEvenOdd_FillType:
1354 return "inverse-even-odd";
1355 case SkPath::kInverseWinding_FillType:
1356 return "inverse-winding";
1357 }
1358 return "unknown";
1359}
1360
1361static int lpath_getFillType(lua_State* L) {
1362 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1363 SkLua(L).pushString(fill_type_to_str(fill));
1364 return 1;
1365}
1366
1367static SkString segment_masks_to_str(uint32_t segmentMasks) {
1368 SkString result;
1369 bool first = true;
1370 if (SkPath::kLine_SegmentMask & segmentMasks) {
1371 result.append("line");
1372 first = false;
1373 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1374 }
1375 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1376 if (!first) {
1377 result.append(" ");
1378 }
1379 result.append("quad");
1380 first = false;
1381 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1382 }
1383 if (SkPath::kConic_SegmentMask & segmentMasks) {
1384 if (!first) {
1385 result.append(" ");
1386 }
1387 result.append("conic");
1388 first = false;
1389 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1390 }
1391 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1392 if (!first) {
1393 result.append(" ");
1394 }
1395 result.append("cubic");
1396 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1397 }
1398 SkASSERT(0 == segmentMasks);
1399 return result;
1400}
1401
krajcevski95498ed2014-08-18 08:02:33 -07001402static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001403 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1404 SkLua(L).pushString(segment_masks_to_str(segMasks));
1405 return 1;
1406}
1407
1408static int lpath_isConvex(lua_State* L) {
1409 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1410 SkLua(L).pushBool(isConvex);
1411 return 1;
1412}
1413
reed@google.com74ce6f02013-05-22 15:13:18 +00001414static int lpath_isEmpty(lua_State* L) {
1415 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1416 return 1;
1417}
1418
1419static int lpath_isRect(lua_State* L) {
1420 SkRect r;
1421 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1422 int ret_count = 1;
1423 lua_pushboolean(L, pred);
1424 if (pred) {
1425 SkLua(L).pushRect(r);
1426 ret_count += 1;
1427 }
1428 return ret_count;
1429}
1430
1431static const char* dir2string(SkPath::Direction dir) {
1432 static const char* gStr[] = {
1433 "unknown", "cw", "ccw"
1434 };
1435 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1436 return gStr[dir];
1437}
1438
caryclark95bc5f32015-04-08 08:34:15 -07001439static int lpath_isNestedFillRects(lua_State* L) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001440 SkRect rects[2];
1441 SkPath::Direction dirs[2];
caryclark95bc5f32015-04-08 08:34:15 -07001442 bool pred = get_obj<SkPath>(L, 1)->isNestedFillRects(rects, dirs);
reed@google.com74ce6f02013-05-22 15:13:18 +00001443 int ret_count = 1;
1444 lua_pushboolean(L, pred);
1445 if (pred) {
1446 SkLua lua(L);
1447 lua.pushRect(rects[0]);
1448 lua.pushRect(rects[1]);
1449 lua_pushstring(L, dir2string(dirs[0]));
1450 lua_pushstring(L, dir2string(dirs[0]));
1451 ret_count += 4;
1452 }
1453 return ret_count;
1454}
1455
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001456static int lpath_countPoints(lua_State* L) {
1457 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1458 return 1;
1459}
1460
hstern0b401ce2016-08-02 09:17:59 -07001461static int lpath_getVerbs(lua_State* L) {
1462 const SkPath* path = get_obj<SkPath>(L, 1);
1463 SkPath::Iter iter(*path, false);
1464 SkPoint pts[4];
1465
1466 lua_newtable(L);
1467
1468 bool done = false;
1469 int i = 0;
1470 do {
1471 switch (iter.next(pts, true)) {
1472 case SkPath::kMove_Verb:
1473 setarray_string(L, ++i, "move");
1474 break;
1475 case SkPath::kClose_Verb:
1476 setarray_string(L, ++i, "close");
1477 break;
1478 case SkPath::kLine_Verb:
1479 setarray_string(L, ++i, "line");
1480 break;
1481 case SkPath::kQuad_Verb:
1482 setarray_string(L, ++i, "quad");
1483 break;
1484 case SkPath::kConic_Verb:
1485 setarray_string(L, ++i, "conic");
1486 break;
1487 case SkPath::kCubic_Verb:
1488 setarray_string(L, ++i, "cubic");
1489 break;
1490 case SkPath::kDone_Verb:
1491 setarray_string(L, ++i, "done");
1492 done = true;
1493 break;
1494 }
1495 } while (!done);
1496
1497 return 1;
1498}
1499
reed@google.com74ce6f02013-05-22 15:13:18 +00001500static int lpath_reset(lua_State* L) {
1501 get_obj<SkPath>(L, 1)->reset();
1502 return 0;
1503}
1504
1505static int lpath_moveTo(lua_State* L) {
1506 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1507 return 0;
1508}
1509
1510static int lpath_lineTo(lua_State* L) {
1511 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1512 return 0;
1513}
1514
1515static int lpath_quadTo(lua_State* L) {
1516 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1517 lua2scalar(L, 4), lua2scalar(L, 5));
1518 return 0;
1519}
1520
1521static int lpath_cubicTo(lua_State* L) {
1522 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1523 lua2scalar(L, 4), lua2scalar(L, 5),
1524 lua2scalar(L, 6), lua2scalar(L, 7));
1525 return 0;
1526}
1527
1528static int lpath_close(lua_State* L) {
1529 get_obj<SkPath>(L, 1)->close();
1530 return 0;
1531}
1532
1533static int lpath_gc(lua_State* L) {
1534 get_obj<SkPath>(L, 1)->~SkPath();
1535 return 0;
1536}
1537
1538static const struct luaL_Reg gSkPath_Methods[] = {
1539 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001540 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001541 { "getSegmentTypes", lpath_getSegmentTypes },
hstern0b401ce2016-08-02 09:17:59 -07001542 { "getVerbs", lpath_getVerbs },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001543 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001544 { "isEmpty", lpath_isEmpty },
1545 { "isRect", lpath_isRect },
caryclark95bc5f32015-04-08 08:34:15 -07001546 { "isNestedFillRects", lpath_isNestedFillRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001547 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001548 { "reset", lpath_reset },
1549 { "moveTo", lpath_moveTo },
1550 { "lineTo", lpath_lineTo },
1551 { "quadTo", lpath_quadTo },
1552 { "cubicTo", lpath_cubicTo },
1553 { "close", lpath_close },
1554 { "__gc", lpath_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001555 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001556};
1557
1558///////////////////////////////////////////////////////////////////////////////
1559
1560static const char* rrect_type(const SkRRect& rr) {
1561 switch (rr.getType()) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001562 case SkRRect::kEmpty_Type: return "empty";
1563 case SkRRect::kRect_Type: return "rect";
1564 case SkRRect::kOval_Type: return "oval";
1565 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001566 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001567 case SkRRect::kComplex_Type: return "complex";
1568 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001569 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001570 return "";
1571}
1572
1573static int lrrect_rect(lua_State* L) {
1574 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1575 return 1;
1576}
1577
1578static int lrrect_type(lua_State* L) {
1579 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1580 return 1;
1581}
1582
1583static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001584 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001585 SkVector v;
1586 if (corner < 0 || corner > 3) {
1587 SkDebugf("bad corner index %d", corner);
1588 v.set(0, 0);
1589 } else {
1590 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1591 }
1592 lua_pushnumber(L, v.fX);
1593 lua_pushnumber(L, v.fY);
1594 return 2;
1595}
1596
1597static int lrrect_gc(lua_State* L) {
1598 get_obj<SkRRect>(L, 1)->~SkRRect();
1599 return 0;
1600}
1601
1602static const struct luaL_Reg gSkRRect_Methods[] = {
1603 { "rect", lrrect_rect },
1604 { "type", lrrect_type },
1605 { "radii", lrrect_radii },
1606 { "__gc", lrrect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001607 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001608};
1609
1610///////////////////////////////////////////////////////////////////////////////
1611
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001612static int limage_width(lua_State* L) {
1613 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1614 return 1;
1615}
1616
1617static int limage_height(lua_State* L) {
1618 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1619 return 1;
1620}
1621
reed7a72c672014-11-07 10:23:55 -08001622static int limage_newShader(lua_State* L) {
1623 SkShader::TileMode tmode = SkShader::kClamp_TileMode;
halcanary96fcdcc2015-08-27 07:41:13 -07001624 const SkMatrix* localM = nullptr;
reed5671c5b2016-03-09 14:47:34 -08001625 push_ref(L, get_ref<SkImage>(L, 1)->makeShader(tmode, tmode, localM));
reed7a72c672014-11-07 10:23:55 -08001626 return 1;
1627}
1628
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001629static int limage_gc(lua_State* L) {
1630 get_ref<SkImage>(L, 1)->unref();
1631 return 0;
1632}
1633
1634static const struct luaL_Reg gSkImage_Methods[] = {
1635 { "width", limage_width },
1636 { "height", limage_height },
reed7a72c672014-11-07 10:23:55 -08001637 { "newShader", limage_newShader },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001638 { "__gc", limage_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001639 { nullptr, nullptr }
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001640};
1641
1642///////////////////////////////////////////////////////////////////////////////
1643
reed485557f2014-10-12 10:36:47 -07001644static int lsurface_width(lua_State* L) {
1645 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1646 return 1;
1647}
1648
1649static int lsurface_height(lua_State* L) {
1650 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1651 return 1;
1652}
1653
1654static int lsurface_getCanvas(lua_State* L) {
1655 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001656 if (nullptr == canvas) {
reed485557f2014-10-12 10:36:47 -07001657 lua_pushnil(L);
1658 } else {
Mike Reed5df49342016-11-12 08:06:55 -06001659 push_ptr(L, canvas);
reed485557f2014-10-12 10:36:47 -07001660 // note: we don't unref canvas, since getCanvas did not ref it.
1661 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1662 // the real owner (the surface) go away, but still hold onto the canvas?
1663 // *really* we want to sort of ref the surface again, but have the native object
1664 // know that it is supposed to be treated as a canvas...
1665 }
1666 return 1;
1667}
1668
1669static int lsurface_newImageSnapshot(lua_State* L) {
reed9ce9d672016-03-17 10:51:11 -07001670 sk_sp<SkImage> image = get_ref<SkSurface>(L, 1)->makeImageSnapshot();
1671 if (!image) {
reed485557f2014-10-12 10:36:47 -07001672 lua_pushnil(L);
1673 } else {
reed9ce9d672016-03-17 10:51:11 -07001674 push_ref(L, image);
reed485557f2014-10-12 10:36:47 -07001675 }
1676 return 1;
1677}
1678
1679static int lsurface_newSurface(lua_State* L) {
1680 int width = lua2int_def(L, 2, 0);
reed96affcd2014-10-13 12:38:04 -07001681 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -07001682 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -07001683 auto surface = get_ref<SkSurface>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -07001684 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07001685 lua_pushnil(L);
1686 } else {
reede8f30622016-03-23 18:59:25 -07001687 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07001688 }
1689 return 1;
1690}
1691
1692static int lsurface_gc(lua_State* L) {
1693 get_ref<SkSurface>(L, 1)->unref();
1694 return 0;
1695}
1696
1697static const struct luaL_Reg gSkSurface_Methods[] = {
1698 { "width", lsurface_width },
1699 { "height", lsurface_height },
1700 { "getCanvas", lsurface_getCanvas },
1701 { "newImageSnapshot", lsurface_newImageSnapshot },
1702 { "newSurface", lsurface_newSurface },
1703 { "__gc", lsurface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001704 { nullptr, nullptr }
reed485557f2014-10-12 10:36:47 -07001705};
1706
1707///////////////////////////////////////////////////////////////////////////////
1708
reed96affcd2014-10-13 12:38:04 -07001709static int lpicturerecorder_beginRecording(lua_State* L) {
1710 const SkScalar w = lua2scalar_def(L, 2, -1);
1711 const SkScalar h = lua2scalar_def(L, 3, -1);
1712 if (w <= 0 || h <= 0) {
1713 lua_pushnil(L);
1714 return 1;
1715 }
1716
1717 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
halcanary96fcdcc2015-08-27 07:41:13 -07001718 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001719 lua_pushnil(L);
1720 return 1;
1721 }
1722
Mike Reed5df49342016-11-12 08:06:55 -06001723 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001724 return 1;
1725}
1726
1727static int lpicturerecorder_getCanvas(lua_State* L) {
1728 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001729 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001730 lua_pushnil(L);
1731 return 1;
1732 }
Mike Reed5df49342016-11-12 08:06:55 -06001733 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001734 return 1;
1735}
1736
1737static int lpicturerecorder_endRecording(lua_State* L) {
reedca2622b2016-03-18 07:25:55 -07001738 sk_sp<SkPicture> pic = get_obj<SkPictureRecorder>(L, 1)->finishRecordingAsPicture();
1739 if (!pic) {
reed96affcd2014-10-13 12:38:04 -07001740 lua_pushnil(L);
1741 return 1;
1742 }
reedca2622b2016-03-18 07:25:55 -07001743 push_ref(L, std::move(pic));
reed96affcd2014-10-13 12:38:04 -07001744 return 1;
1745}
1746
1747static int lpicturerecorder_gc(lua_State* L) {
1748 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1749 return 0;
1750}
1751
1752static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1753 { "beginRecording", lpicturerecorder_beginRecording },
1754 { "getCanvas", lpicturerecorder_getCanvas },
1755 { "endRecording", lpicturerecorder_endRecording },
1756 { "__gc", lpicturerecorder_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001757 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001758};
1759
1760///////////////////////////////////////////////////////////////////////////////
1761
1762static int lpicture_width(lua_State* L) {
1763 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1764 return 1;
1765}
1766
1767static int lpicture_height(lua_State* L) {
1768 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1769 return 1;
1770}
1771
1772static int lpicture_gc(lua_State* L) {
1773 get_ref<SkPicture>(L, 1)->unref();
1774 return 0;
1775}
1776
1777static const struct luaL_Reg gSkPicture_Methods[] = {
1778 { "width", lpicture_width },
1779 { "height", lpicture_height },
1780 { "__gc", lpicture_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001781 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001782};
1783
1784///////////////////////////////////////////////////////////////////////////////
1785
reed1b6ab442014-11-03 19:55:41 -08001786static int ltextblob_bounds(lua_State* L) {
1787 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
1788 return 1;
1789}
1790
1791static int ltextblob_gc(lua_State* L) {
1792 SkSafeUnref(get_ref<SkTextBlob>(L, 1));
1793 return 0;
1794}
1795
1796static const struct luaL_Reg gSkTextBlob_Methods[] = {
1797 { "bounds", ltextblob_bounds },
1798 { "__gc", ltextblob_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001799 { nullptr, nullptr }
reed1b6ab442014-11-03 19:55:41 -08001800};
1801
1802///////////////////////////////////////////////////////////////////////////////
1803
reed36c9c112014-11-04 10:58:42 -08001804static int ltypeface_getFamilyName(lua_State* L) {
1805 SkString str;
1806 get_ref<SkTypeface>(L, 1)->getFamilyName(&str);
1807 lua_pushstring(L, str.c_str());
1808 return 1;
1809}
1810
1811static int ltypeface_getStyle(lua_State* L) {
Ben Wagner26308e12017-08-08 15:23:47 -04001812 push_obj(L, get_ref<SkTypeface>(L, 1)->fontStyle());
reed36c9c112014-11-04 10:58:42 -08001813 return 1;
1814}
1815
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001816static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001817 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001818 return 0;
1819}
1820
1821static const struct luaL_Reg gSkTypeface_Methods[] = {
reed36c9c112014-11-04 10:58:42 -08001822 { "getFamilyName", ltypeface_getFamilyName },
1823 { "getStyle", ltypeface_getStyle },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001824 { "__gc", ltypeface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001825 { nullptr, nullptr }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001826};
1827
1828///////////////////////////////////////////////////////////////////////////////
1829
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001830static int lfontstyle_weight(lua_State* L) {
1831 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->weight());
1832 return 1;
1833}
1834
1835static int lfontstyle_width(lua_State* L) {
1836 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->width());
1837 return 1;
1838}
1839
1840static int lfontstyle_slant(lua_State* L) {
1841 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->slant());
1842 return 1;
1843}
1844
1845static int lfontstyle_gc(lua_State* L) {
1846 get_obj<SkFontStyle>(L, 1)->~SkFontStyle();
1847 return 0;
1848}
1849
1850static const struct luaL_Reg gSkFontStyle_Methods[] = {
1851 { "weight", lfontstyle_weight },
1852 { "width", lfontstyle_width },
1853 { "slant", lfontstyle_slant },
1854 { "__gc", lfontstyle_gc },
1855 { nullptr, nullptr }
1856};
1857
1858///////////////////////////////////////////////////////////////////////////////
1859
reed@google.com74ce6f02013-05-22 15:13:18 +00001860class AutoCallLua {
1861public:
1862 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1863 lua_getglobal(L, func);
1864 if (!lua_isfunction(L, -1)) {
1865 int t = lua_type(L, -1);
1866 SkDebugf("--- expected function %d\n", t);
1867 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001868
reed@google.com74ce6f02013-05-22 15:13:18 +00001869 lua_newtable(L);
1870 setfield_string(L, "verb", verb);
1871 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001872
reed@google.com74ce6f02013-05-22 15:13:18 +00001873 ~AutoCallLua() {
1874 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1875 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1876 }
1877 lua_settop(fL, -1);
1878 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001879
reed@google.com74ce6f02013-05-22 15:13:18 +00001880private:
1881 lua_State* fL;
1882};
1883
1884#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1885
1886///////////////////////////////////////////////////////////////////////////////
1887
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001888static int lsk_newDocumentPDF(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -05001889 const char* filename = nullptr;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001890 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
Mike Reed7ff6ca52018-01-08 14:45:31 -05001891 filename = lua_tolstring(L, 1, nullptr);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001892 }
Mike Reed7ff6ca52018-01-08 14:45:31 -05001893 if (!filename) {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001894 return 0;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001895 }
Mike Reed7ff6ca52018-01-08 14:45:31 -05001896 auto file = skstd::make_unique<SkFILEWStream>(filename);
1897 if (!file->isValid()) {
1898 return 0;
1899 }
1900 sk_sp<SkDocument> doc = SkDocument::MakePDF(file.get());
1901 if (!doc) {
1902 return 0;
1903 }
1904 push_ptr(L, new DocHolder{std::move(doc), std::move(file)});
1905 return 1;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001906}
1907
reed468b1812014-10-19 11:42:54 -07001908static int lsk_newBlurImageFilter(lua_State* L) {
1909 SkScalar sigmaX = lua2scalar_def(L, 1, 0);
1910 SkScalar sigmaY = lua2scalar_def(L, 2, 0);
robertphillips6e7025a2016-04-04 04:31:25 -07001911 sk_sp<SkImageFilter> imf(SkBlurImageFilter::Make(sigmaX, sigmaY, nullptr));
1912 if (!imf) {
reed468b1812014-10-19 11:42:54 -07001913 lua_pushnil(L);
1914 } else {
robertphillips6e7025a2016-04-04 04:31:25 -07001915 push_ref(L, std::move(imf));
reed9fbc3f32014-10-21 07:12:58 -07001916 }
1917 return 1;
1918}
1919
1920static int lsk_newLinearGradient(lua_State* L) {
1921 SkScalar x0 = lua2scalar_def(L, 1, 0);
1922 SkScalar y0 = lua2scalar_def(L, 2, 0);
1923 SkColor c0 = lua2color(L, 3);
1924 SkScalar x1 = lua2scalar_def(L, 4, 0);
1925 SkScalar y1 = lua2scalar_def(L, 5, 0);
1926 SkColor c1 = lua2color(L, 6);
1927
1928 SkPoint pts[] = { { x0, y0 }, { x1, y1 } };
1929 SkColor colors[] = { c0, c1 };
robertphillips6e7025a2016-04-04 04:31:25 -07001930 sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
1931 SkShader::kClamp_TileMode));
reed2ad1aa62016-03-09 09:50:50 -08001932 if (!s) {
reed9fbc3f32014-10-21 07:12:58 -07001933 lua_pushnil(L);
1934 } else {
reed2ad1aa62016-03-09 09:50:50 -08001935 push_ref(L, std::move(s));
reed468b1812014-10-19 11:42:54 -07001936 }
1937 return 1;
1938}
1939
reedbdc49ae2014-10-14 09:34:52 -07001940static int lsk_newMatrix(lua_State* L) {
1941 push_new<SkMatrix>(L)->reset();
1942 return 1;
1943}
1944
reed@google.com3597b732013-05-22 20:12:50 +00001945static int lsk_newPaint(lua_State* L) {
1946 push_new<SkPaint>(L);
1947 return 1;
1948}
1949
1950static int lsk_newPath(lua_State* L) {
1951 push_new<SkPath>(L);
1952 return 1;
1953}
1954
reed96affcd2014-10-13 12:38:04 -07001955static int lsk_newPictureRecorder(lua_State* L) {
1956 push_new<SkPictureRecorder>(L);
1957 return 1;
1958}
1959
reed@google.com3597b732013-05-22 20:12:50 +00001960static int lsk_newRRect(lua_State* L) {
reedbdc49ae2014-10-14 09:34:52 -07001961 push_new<SkRRect>(L)->setEmpty();
reed@google.com3597b732013-05-22 20:12:50 +00001962 return 1;
1963}
1964
reed1b6ab442014-11-03 19:55:41 -08001965// Sk.newTextBlob(text, rect, paint)
1966static int lsk_newTextBlob(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001967 const char* text = lua_tolstring(L, 1, nullptr);
reed1b6ab442014-11-03 19:55:41 -08001968 SkRect bounds;
1969 lua2rect(L, 2, &bounds);
1970 const SkPaint& paint = *get_obj<SkPaint>(L, 3);
1971
Herb Derby1724db12018-05-22 12:01:50 -04001972 SkShaper shaper(nullptr);
reed1b6ab442014-11-03 19:55:41 -08001973
Herb Derby1724db12018-05-22 12:01:50 -04001974 SkTextBlobBuilder builder;
1975 SkPoint end = shaper.shape(&builder, paint, text, strlen(text), true,
1976 { bounds.left(), bounds.top() }, bounds.width());
1977
1978 push_ref<SkTextBlob>(L, builder.make());
1979 SkLua(L).pushScalar(end.fY);
reed1b6ab442014-11-03 19:55:41 -08001980 return 2;
1981}
1982
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001983static int lsk_newTypeface(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001984 const char* name = nullptr;
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001985 SkFontStyle style;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00001986
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001987 int count = lua_gettop(L);
1988 if (count > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001989 name = lua_tolstring(L, 1, nullptr);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001990 if (count > 1) {
1991 SkFontStyle* passedStyle = get_obj<SkFontStyle>(L, 2);
1992 if (passedStyle) {
1993 style = *passedStyle;
1994 }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001995 }
1996 }
1997
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001998 sk_sp<SkTypeface> face(SkTypeface::MakeFromName(name, style));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001999// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
halcanary96fcdcc2015-08-27 07:41:13 -07002000 if (nullptr == face) {
bungeman13b9c952016-05-12 10:09:30 -07002001 face = SkTypeface::MakeDefault();
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002002 }
bungeman13b9c952016-05-12 10:09:30 -07002003 push_ref(L, std::move(face));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002004 return 1;
2005}
reed@google.com3597b732013-05-22 20:12:50 +00002006
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002007static int lsk_newFontStyle(lua_State* L) {
2008 int count = lua_gettop(L);
2009 int weight = SkFontStyle::kNormal_Weight;
2010 int width = SkFontStyle::kNormal_Width;
2011 SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
2012 if (count >= 1 && lua_isnumber(L, 1)) {
2013 weight = lua_tointegerx(L, 1, nullptr);
2014 }
2015 if (count >= 2 && lua_isnumber(L, 2)) {
2016 width = lua_tointegerx(L, 2, nullptr);
2017 }
2018 if (count >= 3 && lua_isnumber(L, 3)) {
2019 slant = static_cast<SkFontStyle::Slant>(lua_tointegerx(L, 3, nullptr));
2020 }
2021 push_new<SkFontStyle>(L, weight, width, slant);
2022 return 1;
2023}
2024
reed485557f2014-10-12 10:36:47 -07002025static int lsk_newRasterSurface(lua_State* L) {
reed7b864662014-11-04 13:24:47 -08002026 int width = lua2int_def(L, 1, 0);
reed485557f2014-10-12 10:36:47 -07002027 int height = lua2int_def(L, 2, 0);
2028 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
robertphillips702edbd2015-06-23 06:26:08 -07002029 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
reede8f30622016-03-23 18:59:25 -07002030 auto surface = SkSurface::MakeRaster(info, &props);
halcanary96fcdcc2015-08-27 07:41:13 -07002031 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07002032 lua_pushnil(L);
2033 } else {
reede8f30622016-03-23 18:59:25 -07002034 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07002035 }
2036 return 1;
2037}
2038
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002039static int lsk_loadImage(lua_State* L) {
2040 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002041 const char* name = lua_tolstring(L, 1, nullptr);
reed9ce9d672016-03-17 10:51:11 -07002042 sk_sp<SkData> data(SkData::MakeFromFileName(name));
2043 if (data) {
2044 auto image = SkImage::MakeFromEncoded(std::move(data));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002045 if (image) {
reed9ce9d672016-03-17 10:51:11 -07002046 push_ref(L, std::move(image));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002047 return 1;
2048 }
2049 }
2050 }
2051 return 0;
2052}
2053
reed@google.com3597b732013-05-22 20:12:50 +00002054static void register_Sk(lua_State* L) {
2055 lua_newtable(L);
2056 lua_pushvalue(L, -1);
2057 lua_setglobal(L, "Sk");
2058 // the Sk table is still on top
2059
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00002060 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002061 setfield_function(L, "loadImage", lsk_loadImage);
reed468b1812014-10-19 11:42:54 -07002062 setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
reed9fbc3f32014-10-21 07:12:58 -07002063 setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
reedbdc49ae2014-10-14 09:34:52 -07002064 setfield_function(L, "newMatrix", lsk_newMatrix);
reed@google.com3597b732013-05-22 20:12:50 +00002065 setfield_function(L, "newPaint", lsk_newPaint);
2066 setfield_function(L, "newPath", lsk_newPath);
reed96affcd2014-10-13 12:38:04 -07002067 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
reed@google.com3597b732013-05-22 20:12:50 +00002068 setfield_function(L, "newRRect", lsk_newRRect);
reed485557f2014-10-12 10:36:47 -07002069 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
reed1b6ab442014-11-03 19:55:41 -08002070 setfield_function(L, "newTextBlob", lsk_newTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002071 setfield_function(L, "newTypeface", lsk_newTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002072 setfield_function(L, "newFontStyle", lsk_newFontStyle);
reed@google.com3597b732013-05-22 20:12:50 +00002073 lua_pop(L, 1); // pop off the Sk table
2074}
2075
reed@google.com74ce6f02013-05-22 15:13:18 +00002076#define REG_CLASS(L, C) \
2077 do { \
reed@google.com3597b732013-05-22 20:12:50 +00002078 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00002079 lua_pushvalue(L, -1); \
2080 lua_setfield(L, -2, "__index"); \
2081 luaL_setfuncs(L, g##C##_Methods, 0); \
2082 lua_pop(L, 1); /* pop off the meta-table */ \
2083 } while (0)
2084
2085void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00002086 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00002087 REG_CLASS(L, SkCanvas);
reed22a517f2015-12-04 20:45:59 -08002088 REG_CLASS(L, SkColorFilter);
Mike Reed7ff6ca52018-01-08 14:45:31 -05002089 REG_CLASS(L, DocHolder);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002090 REG_CLASS(L, SkImage);
reed468b1812014-10-19 11:42:54 -07002091 REG_CLASS(L, SkImageFilter);
reed1b6ab442014-11-03 19:55:41 -08002092 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00002093 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00002094 REG_CLASS(L, SkPath);
2095 REG_CLASS(L, SkPathEffect);
reed96affcd2014-10-13 12:38:04 -07002096 REG_CLASS(L, SkPicture);
2097 REG_CLASS(L, SkPictureRecorder);
reed@google.com74ce6f02013-05-22 15:13:18 +00002098 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00002099 REG_CLASS(L, SkShader);
reed485557f2014-10-12 10:36:47 -07002100 REG_CLASS(L, SkSurface);
reed1b6ab442014-11-03 19:55:41 -08002101 REG_CLASS(L, SkTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002102 REG_CLASS(L, SkTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002103 REG_CLASS(L, SkFontStyle);
reed@google.com74ce6f02013-05-22 15:13:18 +00002104}
zachr@google.com28c27c82013-06-20 17:15:05 +00002105
reed@google.com7bce9982013-06-20 17:40:21 +00002106extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00002107extern "C" int luaopen_skia(lua_State* L) {
2108 SkLua::Load(L);
2109 return 0;
2110}