blob: 36bd0b228b66b3a4c86d8f61c4f6d75f8b80ffdc [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"
reed@google.com74ce6f02013-05-22 15:13:18 +000034
35extern "C" {
reed@google.com3597b732013-05-22 20:12:50 +000036 #include "lua.h"
37 #include "lualib.h"
38 #include "lauxlib.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000039}
40
Mike Reed7ff6ca52018-01-08 14:45:31 -050041struct DocHolder {
42 sk_sp<SkDocument> fDoc;
43 std::unique_ptr<SkWStream> fStream;
44};
45
reed@google.comfd345872013-05-22 20:53:42 +000046// return the metatable name for a given class
reed@google.com3597b732013-05-22 20:12:50 +000047template <typename T> const char* get_mtname();
reed@google.comfd345872013-05-22 20:53:42 +000048#define DEF_MTNAME(T) \
49 template <> const char* get_mtname<T>() { \
50 return #T "_LuaMetaTableName"; \
51 }
52
53DEF_MTNAME(SkCanvas)
reed22a517f2015-12-04 20:45:59 -080054DEF_MTNAME(SkColorFilter)
Mike Reed7ff6ca52018-01-08 14:45:31 -050055DEF_MTNAME(DocHolder)
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000056DEF_MTNAME(SkImage)
reed468b1812014-10-19 11:42:54 -070057DEF_MTNAME(SkImageFilter)
reed@google.comfd345872013-05-22 20:53:42 +000058DEF_MTNAME(SkMatrix)
59DEF_MTNAME(SkRRect)
60DEF_MTNAME(SkPath)
61DEF_MTNAME(SkPaint)
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +000062DEF_MTNAME(SkPathEffect)
reed96affcd2014-10-13 12:38:04 -070063DEF_MTNAME(SkPicture)
64DEF_MTNAME(SkPictureRecorder)
reed@google.com5fdc9832013-07-24 15:47:52 +000065DEF_MTNAME(SkShader)
reed485557f2014-10-12 10:36:47 -070066DEF_MTNAME(SkSurface)
fmalitab7425172014-08-26 07:56:44 -070067DEF_MTNAME(SkTextBlob)
mike@reedtribe.orge6469f12013-06-08 03:15:47 +000068DEF_MTNAME(SkTypeface)
Ben Wagnerc6c10b42017-08-07 09:56:21 -040069DEF_MTNAME(SkFontStyle)
reed@google.com74ce6f02013-05-22 15:13:18 +000070
Ben Wagnerc6c10b42017-08-07 09:56:21 -040071template <typename T, typename... Args> T* push_new(lua_State* L, Args&&... args) {
reed@google.com3597b732013-05-22 20:12:50 +000072 T* addr = (T*)lua_newuserdata(L, sizeof(T));
Ben Wagnerc6c10b42017-08-07 09:56:21 -040073 new (addr) T(std::forward<Args>(args)...);
reed@google.com3597b732013-05-22 20:12:50 +000074 luaL_getmetatable(L, get_mtname<T>());
75 lua_setmetatable(L, -2);
76 return addr;
77}
reed@google.com74ce6f02013-05-22 15:13:18 +000078
79template <typename T> void push_obj(lua_State* L, const T& obj) {
80 new (lua_newuserdata(L, sizeof(T))) T(obj);
reed@google.com3597b732013-05-22 20:12:50 +000081 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000082 lua_setmetatable(L, -2);
83}
84
Mike Reed5df49342016-11-12 08:06:55 -060085template <typename T> T* push_ptr(lua_State* L, T* ptr) {
86 *(T**)lua_newuserdata(L, sizeof(T*)) = ptr;
87 luaL_getmetatable(L, get_mtname<T>());
88 lua_setmetatable(L, -2);
89 return ptr;
90}
91
reed9fbc3f32014-10-21 07:12:58 -070092template <typename T> T* push_ref(lua_State* L, T* ref) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +000093 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
reed@google.com3597b732013-05-22 20:12:50 +000094 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000095 lua_setmetatable(L, -2);
reed9fbc3f32014-10-21 07:12:58 -070096 return ref;
reed@google.com74ce6f02013-05-22 15:13:18 +000097}
98
reed2ad1aa62016-03-09 09:50:50 -080099template <typename T> void push_ref(lua_State* L, sk_sp<T> sp) {
100 *(T**)lua_newuserdata(L, sizeof(T*)) = sp.release();
101 luaL_getmetatable(L, get_mtname<T>());
102 lua_setmetatable(L, -2);
103}
104
reed@google.com74ce6f02013-05-22 15:13:18 +0000105template <typename T> T* get_ref(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +0000106 return *(T**)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +0000107}
108
109template <typename T> T* get_obj(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +0000110 return (T*)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +0000111}
112
reed@google.com88c9ec92013-05-22 15:43:21 +0000113static bool lua2bool(lua_State* L, int index) {
114 return !!lua_toboolean(L, index);
115}
116
reed@google.com74ce6f02013-05-22 15:13:18 +0000117///////////////////////////////////////////////////////////////////////////////
118
reed@google.com3597b732013-05-22 20:12:50 +0000119SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
120 fL = luaL_newstate();
121 luaL_openlibs(fL);
122 SkLua::Load(fL);
123}
124
125SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
126
127SkLua::~SkLua() {
128 if (fWeOwnL) {
129 if (fTermCode.size() > 0) {
130 lua_getglobal(fL, fTermCode.c_str());
131 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
132 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
133 }
134 }
135 lua_close(fL);
136 }
137}
138
139bool SkLua::runCode(const char code[]) {
140 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
141 if (err) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000142 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
reed@google.com3597b732013-05-22 20:12:50 +0000143 return false;
144 }
145 return true;
146}
147
148bool SkLua::runCode(const void* code, size_t size) {
149 SkString str((const char*)code, size);
150 return this->runCode(str.c_str());
151}
152
153///////////////////////////////////////////////////////////////////////////////
154
155#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
156
reed@google.com29563872013-07-10 21:23:49 +0000157static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
158 if (pred) {
159 lua_pushboolean(L, true);
160 lua_setfield(L, -2, key);
161 }
162}
163
reed@google.com74ce6f02013-05-22 15:13:18 +0000164static void setfield_string(lua_State* L, const char key[], const char value[]) {
165 lua_pushstring(L, value);
166 lua_setfield(L, -2, key);
167}
168
169static void setfield_number(lua_State* L, const char key[], double value) {
170 lua_pushnumber(L, value);
171 lua_setfield(L, -2, key);
172}
173
humper@google.com2815c192013-07-10 22:42:30 +0000174static void setfield_boolean(lua_State* L, const char key[], bool value) {
175 lua_pushboolean(L, value);
176 lua_setfield(L, -2, key);
177}
178
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000179static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
180 setfield_number(L, key, SkScalarToLua(value));
181}
182
reed@google.com3597b732013-05-22 20:12:50 +0000183static void setfield_function(lua_State* L,
184 const char key[], lua_CFunction value) {
185 lua_pushcfunction(L, value);
186 lua_setfield(L, -2, key);
reed@google.com74ce6f02013-05-22 15:13:18 +0000187}
188
reed7a72c672014-11-07 10:23:55 -0800189static int lua2int_def(lua_State* L, int index, int defaultValue) {
190 if (lua_isnumber(L, index)) {
191 return (int)lua_tonumber(L, index);
192 } else {
193 return defaultValue;
194 }
195}
196
197static SkScalar lua2scalar(lua_State* L, int index) {
198 SkASSERT(lua_isnumber(L, index));
199 return SkLuaToScalar(lua_tonumber(L, index));
200}
201
202static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
203 if (lua_isnumber(L, index)) {
204 return SkLuaToScalar(lua_tonumber(L, index));
205 } else {
206 return defaultValue;
207 }
208}
209
210static SkScalar getarray_scalar(lua_State* L, int stackIndex, int arrayIndex) {
211 SkASSERT(lua_istable(L, stackIndex));
212 lua_rawgeti(L, stackIndex, arrayIndex);
mtklein8aacf202014-12-18 13:29:54 -0800213
reed7a72c672014-11-07 10:23:55 -0800214 SkScalar value = lua2scalar(L, -1);
215 lua_pop(L, 1);
216 return value;
217}
218
219static void getarray_scalars(lua_State* L, int stackIndex, SkScalar dst[], int count) {
220 for (int i = 0; i < count; ++i) {
221 dst[i] = getarray_scalar(L, stackIndex, i + 1);
222 }
223}
224
225static void getarray_points(lua_State* L, int stackIndex, SkPoint pts[], int count) {
226 getarray_scalars(L, stackIndex, &pts[0].fX, count * 2);
227}
228
reed@google.come3823fd2013-05-30 18:55:14 +0000229static void setarray_number(lua_State* L, int index, double value) {
230 lua_pushnumber(L, value);
231 lua_rawseti(L, -2, index);
232}
233
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000234static void setarray_scalar(lua_State* L, int index, SkScalar value) {
235 setarray_number(L, index, SkScalarToLua(value));
236}
237
hstern0b401ce2016-08-02 09:17:59 -0700238static void setarray_string(lua_State* L, int index, const char str[]) {
239 lua_pushstring(L, str);
240 lua_rawseti(L, -2, index);
241}
242
reed@google.com74ce6f02013-05-22 15:13:18 +0000243void SkLua::pushBool(bool value, const char key[]) {
244 lua_pushboolean(fL, value);
245 CHECK_SETFIELD(key);
246}
247
248void SkLua::pushString(const char str[], const char key[]) {
249 lua_pushstring(fL, str);
250 CHECK_SETFIELD(key);
251}
252
reed@google.come3823fd2013-05-30 18:55:14 +0000253void SkLua::pushString(const char str[], size_t length, const char key[]) {
254 // TODO: how to do this w/o making a copy?
255 SkString s(str, length);
256 lua_pushstring(fL, s.c_str());
257 CHECK_SETFIELD(key);
258}
259
reed@google.com74ce6f02013-05-22 15:13:18 +0000260void SkLua::pushString(const SkString& str, const char key[]) {
261 lua_pushstring(fL, str.c_str());
262 CHECK_SETFIELD(key);
263}
264
265void SkLua::pushColor(SkColor color, const char key[]) {
266 lua_newtable(fL);
267 setfield_number(fL, "a", SkColorGetA(color) / 255.0);
268 setfield_number(fL, "r", SkColorGetR(color) / 255.0);
269 setfield_number(fL, "g", SkColorGetG(color) / 255.0);
270 setfield_number(fL, "b", SkColorGetB(color) / 255.0);
271 CHECK_SETFIELD(key);
272}
273
reed@google.come3823fd2013-05-30 18:55:14 +0000274void SkLua::pushU32(uint32_t value, const char key[]) {
275 lua_pushnumber(fL, (double)value);
276 CHECK_SETFIELD(key);
277}
278
reed@google.com74ce6f02013-05-22 15:13:18 +0000279void SkLua::pushScalar(SkScalar value, const char key[]) {
280 lua_pushnumber(fL, SkScalarToLua(value));
281 CHECK_SETFIELD(key);
282}
283
reed@google.come3823fd2013-05-30 18:55:14 +0000284void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
285 lua_newtable(fL);
286 for (int i = 0; i < count; ++i) {
287 // make it base-1 to match lua convention
288 setarray_number(fL, i + 1, (double)array[i]);
289 }
290 CHECK_SETFIELD(key);
291}
292
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000293void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
294 lua_newtable(fL);
295 for (int i = 0; i < count; ++i) {
296 // make it base-1 to match lua convention
297 lua_newtable(fL);
298 this->pushScalar(array[i].fX, "x");
299 this->pushScalar(array[i].fY, "y");
300 lua_rawseti(fL, -2, i + 1);
301 }
302 CHECK_SETFIELD(key);
303}
304
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000305void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
306 lua_newtable(fL);
307 for (int i = 0; i < count; ++i) {
308 // make it base-1 to match lua convention
309 setarray_scalar(fL, i + 1, array[i]);
310 }
311 CHECK_SETFIELD(key);
312}
313
reed@google.com74ce6f02013-05-22 15:13:18 +0000314void SkLua::pushRect(const SkRect& r, const char key[]) {
315 lua_newtable(fL);
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000316 setfield_scalar(fL, "left", r.fLeft);
317 setfield_scalar(fL, "top", r.fTop);
318 setfield_scalar(fL, "right", r.fRight);
319 setfield_scalar(fL, "bottom", r.fBottom);
reed@google.com74ce6f02013-05-22 15:13:18 +0000320 CHECK_SETFIELD(key);
321}
322
323void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
324 push_obj(fL, rr);
325 CHECK_SETFIELD(key);
326}
327
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000328void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
329 lua_newtable(fL);
330 setfield_scalar(fL, "phase", info.fPhase);
331 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
332 CHECK_SETFIELD(key);
333}
334
335
reed@google.com74ce6f02013-05-22 15:13:18 +0000336void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
337 push_obj(fL, matrix);
338 CHECK_SETFIELD(key);
339}
340
341void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
342 push_obj(fL, paint);
343 CHECK_SETFIELD(key);
344}
345
346void SkLua::pushPath(const SkPath& path, const char key[]) {
347 push_obj(fL, path);
348 CHECK_SETFIELD(key);
349}
350
351void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
Mike Reed5df49342016-11-12 08:06:55 -0600352 push_ptr(fL, canvas);
reed@google.com74ce6f02013-05-22 15:13:18 +0000353 CHECK_SETFIELD(key);
354}
355
fmalitab7425172014-08-26 07:56:44 -0700356void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
357 push_ref(fL, const_cast<SkTextBlob*>(blob));
358 CHECK_SETFIELD(key);
359}
360
reed@google.com74ce6f02013-05-22 15:13:18 +0000361///////////////////////////////////////////////////////////////////////////////
362///////////////////////////////////////////////////////////////////////////////
363
reed@google.com74ce6f02013-05-22 15:13:18 +0000364static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
365 SkASSERT(lua_istable(L, index));
366 lua_pushstring(L, key);
367 lua_gettable(L, index);
mtklein8aacf202014-12-18 13:29:54 -0800368
reed@google.com74ce6f02013-05-22 15:13:18 +0000369 SkScalar value = lua2scalar(L, -1);
370 lua_pop(L, 1);
371 return value;
372}
373
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000374static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
375 SkASSERT(lua_istable(L, index));
376 lua_pushstring(L, key);
377 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000378
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000379 SkScalar value;
380 if (lua_isnil(L, -1)) {
381 value = def;
382 } else {
383 value = lua2scalar(L, -1);
384 }
385 lua_pop(L, 1);
386 return value;
387}
388
reed468b1812014-10-19 11:42:54 -0700389static SkScalar byte2unit(U8CPU byte) {
390 return byte / 255.0f;
391}
392
reed@google.com74ce6f02013-05-22 15:13:18 +0000393static U8CPU unit2byte(SkScalar x) {
394 if (x <= 0) {
395 return 0;
396 } else if (x >= 1) {
397 return 255;
398 } else {
399 return SkScalarRoundToInt(x * 255);
400 }
401}
402
403static SkColor lua2color(lua_State* L, int index) {
reed485557f2014-10-12 10:36:47 -0700404 return SkColorSetARGB(unit2byte(getfield_scalar_default(L, index, "a", 1)),
405 unit2byte(getfield_scalar_default(L, index, "r", 0)),
406 unit2byte(getfield_scalar_default(L, index, "g", 0)),
407 unit2byte(getfield_scalar_default(L, index, "b", 0)));
reed@google.com74ce6f02013-05-22 15:13:18 +0000408}
409
410static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000411 rect->set(getfield_scalar_default(L, index, "left", 0),
412 getfield_scalar_default(L, index, "top", 0),
reed@google.com74ce6f02013-05-22 15:13:18 +0000413 getfield_scalar(L, index, "right"),
414 getfield_scalar(L, index, "bottom"));
415 return rect;
416}
417
reedf355df52014-10-12 12:18:40 -0700418static int lcanvas_clear(lua_State* L) {
419 get_ref<SkCanvas>(L, 1)->clear(0);
420 return 0;
421}
422
reed@google.com74ce6f02013-05-22 15:13:18 +0000423static int lcanvas_drawColor(lua_State* L) {
424 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
425 return 0;
426}
427
reed9fbc3f32014-10-21 07:12:58 -0700428static int lcanvas_drawPaint(lua_State* L) {
429 get_ref<SkCanvas>(L, 1)->drawPaint(*get_obj<SkPaint>(L, 2));
430 return 0;
431}
432
reed@google.com74ce6f02013-05-22 15:13:18 +0000433static int lcanvas_drawRect(lua_State* L) {
434 SkRect rect;
reed7a72c672014-11-07 10:23:55 -0800435 lua2rect(L, 2, &rect);
436 const SkPaint* paint = get_obj<SkPaint>(L, 3);
437 get_ref<SkCanvas>(L, 1)->drawRect(rect, *paint);
reed@google.com74ce6f02013-05-22 15:13:18 +0000438 return 0;
439}
440
441static int lcanvas_drawOval(lua_State* L) {
442 SkRect rect;
443 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
444 *get_obj<SkPaint>(L, 3));
445 return 0;
446}
447
448static int lcanvas_drawCircle(lua_State* L) {
449 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
450 lua2scalar(L, 3),
451 lua2scalar(L, 4),
452 *get_obj<SkPaint>(L, 5));
453 return 0;
454}
455
reed485557f2014-10-12 10:36:47 -0700456static SkPaint* lua2OptionalPaint(lua_State* L, int index, SkPaint* paint) {
457 if (lua_isnumber(L, index)) {
458 paint->setAlpha(SkScalarRoundToInt(lua2scalar(L, index) * 255));
459 return paint;
reedf355df52014-10-12 12:18:40 -0700460 } else if (lua_isuserdata(L, index)) {
reed485557f2014-10-12 10:36:47 -0700461 const SkPaint* ptr = get_obj<SkPaint>(L, index);
462 if (ptr) {
463 *paint = *ptr;
464 return paint;
465 }
466 }
halcanary96fcdcc2015-08-27 07:41:13 -0700467 return nullptr;
reed485557f2014-10-12 10:36:47 -0700468}
469
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000470static int lcanvas_drawImage(lua_State* L) {
471 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
472 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700473 if (nullptr == image) {
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000474 return 0;
475 }
476 SkScalar x = lua2scalar(L, 3);
477 SkScalar y = lua2scalar(L, 4);
478
479 SkPaint paint;
reed485557f2014-10-12 10:36:47 -0700480 canvas->drawImage(image, x, y, lua2OptionalPaint(L, 5, &paint));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000481 return 0;
482}
483
reedba5fb932014-10-10 15:28:19 -0700484static int lcanvas_drawImageRect(lua_State* L) {
485 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
486 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700487 if (nullptr == image) {
reedba5fb932014-10-10 15:28:19 -0700488 return 0;
489 }
490
491 SkRect srcR, dstR;
halcanary96fcdcc2015-08-27 07:41:13 -0700492 SkRect* srcRPtr = nullptr;
reedba5fb932014-10-10 15:28:19 -0700493 if (!lua_isnil(L, 3)) {
494 srcRPtr = lua2rect(L, 3, &srcR);
495 }
496 lua2rect(L, 4, &dstR);
mtklein8aacf202014-12-18 13:29:54 -0800497
reedba5fb932014-10-10 15:28:19 -0700498 SkPaint paint;
reede47829b2015-08-06 10:02:53 -0700499 canvas->legacy_drawImageRect(image, srcRPtr, dstR, lua2OptionalPaint(L, 5, &paint));
reedba5fb932014-10-10 15:28:19 -0700500 return 0;
501}
502
reed7a72c672014-11-07 10:23:55 -0800503static int lcanvas_drawPatch(lua_State* L) {
504 SkPoint cubics[12];
505 SkColor colorStorage[4];
506 SkPoint texStorage[4];
507
halcanary96fcdcc2015-08-27 07:41:13 -0700508 const SkColor* colors = nullptr;
509 const SkPoint* texs = nullptr;
reed7a72c672014-11-07 10:23:55 -0800510
511 getarray_points(L, 2, cubics, 12);
512
513 colorStorage[0] = SK_ColorRED;
514 colorStorage[1] = SK_ColorGREEN;
515 colorStorage[2] = SK_ColorBLUE;
516 colorStorage[3] = SK_ColorGRAY;
517
518 if (lua_isnil(L, 4)) {
519 colors = colorStorage;
520 } else {
521 getarray_points(L, 4, texStorage, 4);
522 texs = texStorage;
523 }
524
Mike Reed7d954ad2016-10-28 15:42:34 -0400525 get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, *get_obj<SkPaint>(L, 5));
reed7a72c672014-11-07 10:23:55 -0800526 return 0;
527}
528
reed@google.comfd345872013-05-22 20:53:42 +0000529static int lcanvas_drawPath(lua_State* L) {
530 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
531 *get_obj<SkPaint>(L, 3));
532 return 0;
533}
534
reed96affcd2014-10-13 12:38:04 -0700535// drawPicture(pic, x, y, paint)
536static int lcanvas_drawPicture(lua_State* L) {
537 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
538 SkPicture* picture = get_ref<SkPicture>(L, 2);
539 SkScalar x = lua2scalar_def(L, 3, 0);
540 SkScalar y = lua2scalar_def(L, 4, 0);
halcanary96fcdcc2015-08-27 07:41:13 -0700541 SkMatrix matrix, *matrixPtr = nullptr;
reed96affcd2014-10-13 12:38:04 -0700542 if (x || y) {
543 matrix.setTranslate(x, y);
544 matrixPtr = &matrix;
545 }
546 SkPaint paint;
547 canvas->drawPicture(picture, matrixPtr, lua2OptionalPaint(L, 5, &paint));
548 return 0;
549}
550
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000551static int lcanvas_drawText(lua_State* L) {
552 if (lua_gettop(L) < 5) {
553 return 0;
554 }
555
556 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
557 size_t len;
558 const char* text = lua_tolstring(L, 2, &len);
559 get_ref<SkCanvas>(L, 1)->drawText(text, len,
560 lua2scalar(L, 3), lua2scalar(L, 4),
561 *get_obj<SkPaint>(L, 5));
562 }
563 return 0;
564}
565
reed1b6ab442014-11-03 19:55:41 -0800566static int lcanvas_drawTextBlob(lua_State* L) {
567 const SkTextBlob* blob = get_ref<SkTextBlob>(L, 2);
568 SkScalar x = lua2scalar(L, 3);
569 SkScalar y = lua2scalar(L, 4);
570 const SkPaint& paint = *get_obj<SkPaint>(L, 5);
571 get_ref<SkCanvas>(L, 1)->drawTextBlob(blob, x, y, paint);
572 return 0;
573}
574
reed@google.com74ce6f02013-05-22 15:13:18 +0000575static int lcanvas_getSaveCount(lua_State* L) {
576 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
577 return 1;
578}
579
580static int lcanvas_getTotalMatrix(lua_State* L) {
581 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
582 return 1;
583}
584
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000585static int lcanvas_save(lua_State* L) {
586 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
587 return 1;
588}
589
reed86217d82014-10-25 20:44:40 -0700590static int lcanvas_saveLayer(lua_State* L) {
591 SkPaint paint;
halcanary96fcdcc2015-08-27 07:41:13 -0700592 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->saveLayer(nullptr, lua2OptionalPaint(L, 2, &paint)));
reed86217d82014-10-25 20:44:40 -0700593 return 1;
594}
595
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000596static int lcanvas_restore(lua_State* L) {
597 get_ref<SkCanvas>(L, 1)->restore();
598 return 0;
599}
600
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000601static int lcanvas_scale(lua_State* L) {
602 SkScalar sx = lua2scalar_def(L, 2, 1);
603 SkScalar sy = lua2scalar_def(L, 3, sx);
604 get_ref<SkCanvas>(L, 1)->scale(sx, sy);
605 return 0;
606}
607
reed@google.com3597b732013-05-22 20:12:50 +0000608static int lcanvas_translate(lua_State* L) {
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000609 SkScalar tx = lua2scalar_def(L, 2, 0);
610 SkScalar ty = lua2scalar_def(L, 3, 0);
611 get_ref<SkCanvas>(L, 1)->translate(tx, ty);
612 return 0;
613}
614
615static int lcanvas_rotate(lua_State* L) {
616 SkScalar degrees = lua2scalar_def(L, 2, 0);
617 get_ref<SkCanvas>(L, 1)->rotate(degrees);
reed@google.com3597b732013-05-22 20:12:50 +0000618 return 0;
619}
620
reedbdc49ae2014-10-14 09:34:52 -0700621static int lcanvas_concat(lua_State* L) {
622 get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2));
623 return 0;
624}
625
reed485557f2014-10-12 10:36:47 -0700626static int lcanvas_newSurface(lua_State* L) {
627 int width = lua2int_def(L, 2, 0);
reed7a72c672014-11-07 10:23:55 -0800628 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -0700629 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -0700630 auto surface = get_ref<SkCanvas>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -0700631 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -0700632 lua_pushnil(L);
633 } else {
reede8f30622016-03-23 18:59:25 -0700634 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -0700635 }
636 return 1;
637}
638
reed@google.com74ce6f02013-05-22 15:13:18 +0000639static int lcanvas_gc(lua_State* L) {
Mike Reed5df49342016-11-12 08:06:55 -0600640 // don't know how to track a ptr...
reed@google.com74ce6f02013-05-22 15:13:18 +0000641 return 0;
642}
643
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000644const struct luaL_Reg gSkCanvas_Methods[] = {
reedf355df52014-10-12 12:18:40 -0700645 { "clear", lcanvas_clear },
reed@google.com74ce6f02013-05-22 15:13:18 +0000646 { "drawColor", lcanvas_drawColor },
reed9fbc3f32014-10-21 07:12:58 -0700647 { "drawPaint", lcanvas_drawPaint },
reed@google.com74ce6f02013-05-22 15:13:18 +0000648 { "drawRect", lcanvas_drawRect },
649 { "drawOval", lcanvas_drawOval },
650 { "drawCircle", lcanvas_drawCircle },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000651 { "drawImage", lcanvas_drawImage },
reedba5fb932014-10-10 15:28:19 -0700652 { "drawImageRect", lcanvas_drawImageRect },
reed7a72c672014-11-07 10:23:55 -0800653 { "drawPatch", lcanvas_drawPatch },
reed@google.comfd345872013-05-22 20:53:42 +0000654 { "drawPath", lcanvas_drawPath },
reed96affcd2014-10-13 12:38:04 -0700655 { "drawPicture", lcanvas_drawPicture },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000656 { "drawText", lcanvas_drawText },
reed1b6ab442014-11-03 19:55:41 -0800657 { "drawTextBlob", lcanvas_drawTextBlob },
reed@google.com74ce6f02013-05-22 15:13:18 +0000658 { "getSaveCount", lcanvas_getSaveCount },
659 { "getTotalMatrix", lcanvas_getTotalMatrix },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000660 { "save", lcanvas_save },
reed86217d82014-10-25 20:44:40 -0700661 { "saveLayer", lcanvas_saveLayer },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000662 { "restore", lcanvas_restore },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000663 { "scale", lcanvas_scale },
reed@google.com3597b732013-05-22 20:12:50 +0000664 { "translate", lcanvas_translate },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000665 { "rotate", lcanvas_rotate },
reedbdc49ae2014-10-14 09:34:52 -0700666 { "concat", lcanvas_concat },
reed485557f2014-10-12 10:36:47 -0700667
668 { "newSurface", lcanvas_newSurface },
669
reed@google.com74ce6f02013-05-22 15:13:18 +0000670 { "__gc", lcanvas_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700671 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +0000672};
673
674///////////////////////////////////////////////////////////////////////////////
675
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000676static int ldocument_beginPage(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -0700677 const SkRect* contentPtr = nullptr;
Mike Reed7ff6ca52018-01-08 14:45:31 -0500678 push_ptr(L, get_obj<DocHolder>(L, 1)->fDoc->beginPage(lua2scalar(L, 2),
679 lua2scalar(L, 3),
680 contentPtr));
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000681 return 1;
682}
683
684static int ldocument_endPage(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500685 get_obj<DocHolder>(L, 1)->fDoc->endPage();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000686 return 0;
687}
688
689static int ldocument_close(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500690 get_obj<DocHolder>(L, 1)->fDoc->close();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000691 return 0;
692}
693
694static int ldocument_gc(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500695 get_obj<DocHolder>(L, 1)->~DocHolder();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000696 return 0;
697}
698
Mike Reed7ff6ca52018-01-08 14:45:31 -0500699static const struct luaL_Reg gDocHolder_Methods[] = {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000700 { "beginPage", ldocument_beginPage },
701 { "endPage", ldocument_endPage },
702 { "close", ldocument_close },
703 { "__gc", ldocument_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700704 { nullptr, nullptr }
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000705};
706
707///////////////////////////////////////////////////////////////////////////////
708
reed@google.com74ce6f02013-05-22 15:13:18 +0000709static int lpaint_isAntiAlias(lua_State* L) {
710 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
711 return 1;
712}
713
714static int lpaint_setAntiAlias(lua_State* L) {
reed@google.com88c9ec92013-05-22 15:43:21 +0000715 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +0000716 return 0;
717}
718
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000719static int lpaint_isDither(lua_State* L) {
720 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
721 return 1;
722}
723
reedbb8a0ab2014-11-03 22:32:07 -0800724static int lpaint_setDither(lua_State* L) {
725 get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2));
726 return 0;
727}
728
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000729static int lpaint_isFakeBoldText(lua_State* L) {
730 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
731 return 1;
732}
733
734static int lpaint_isLinearText(lua_State* L) {
735 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
736 return 1;
737}
738
739static int lpaint_isSubpixelText(lua_State* L) {
740 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
741 return 1;
742}
743
reed09a1d672014-10-11 13:13:11 -0700744static int lpaint_setSubpixelText(lua_State* L) {
745 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
746 return 1;
747}
748
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000749static int lpaint_isDevKernText(lua_State* L) {
750 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
751 return 1;
752}
753
754static int lpaint_isLCDRenderText(lua_State* L) {
755 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
756 return 1;
757}
758
reed36c9c112014-11-04 10:58:42 -0800759static int lpaint_setLCDRenderText(lua_State* L) {
760 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2));
761 return 1;
762}
763
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000764static int lpaint_isEmbeddedBitmapText(lua_State* L) {
765 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
766 return 1;
767}
768
769static int lpaint_isAutohinted(lua_State* L) {
770 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
771 return 1;
772}
773
774static int lpaint_isVerticalText(lua_State* L) {
775 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
776 return 1;
777}
778
reed468b1812014-10-19 11:42:54 -0700779static int lpaint_getAlpha(lua_State* L) {
780 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha()));
781 return 1;
782}
783
784static int lpaint_setAlpha(lua_State* L) {
785 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2)));
786 return 0;
787}
788
reed@google.com74ce6f02013-05-22 15:13:18 +0000789static int lpaint_getColor(lua_State* L) {
790 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
791 return 1;
792}
793
794static int lpaint_setColor(lua_State* L) {
795 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
796 return 0;
797}
798
reed@google.come3823fd2013-05-30 18:55:14 +0000799static int lpaint_getTextSize(lua_State* L) {
800 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
801 return 1;
802}
803
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000804static int lpaint_getTextScaleX(lua_State* L) {
805 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
806 return 1;
807}
808
809static int lpaint_getTextSkewX(lua_State* L) {
810 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
811 return 1;
812}
813
reed@google.come3823fd2013-05-30 18:55:14 +0000814static int lpaint_setTextSize(lua_State* L) {
815 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
816 return 0;
817}
818
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000819static int lpaint_getTypeface(lua_State* L) {
820 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
821 return 1;
822}
823
824static int lpaint_setTypeface(lua_State* L) {
bungeman13b9c952016-05-12 10:09:30 -0700825 get_obj<SkPaint>(L, 1)->setTypeface(sk_ref_sp(get_ref<SkTypeface>(L, 2)));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000826 return 0;
827}
828
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000829static int lpaint_getHinting(lua_State* L) {
830 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
831 return 1;
832}
833
reed93a12152015-03-16 10:08:34 -0700834static int lpaint_getFilterQuality(lua_State* L) {
835 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality());
reed7a72c672014-11-07 10:23:55 -0800836 return 1;
837}
838
reed93a12152015-03-16 10:08:34 -0700839static int lpaint_setFilterQuality(lua_State* L) {
reed7a72c672014-11-07 10:23:55 -0800840 int level = lua2int_def(L, 2, -1);
841 if (level >= 0 && level <= 3) {
reed93a12152015-03-16 10:08:34 -0700842 get_obj<SkPaint>(L, 1)->setFilterQuality((SkFilterQuality)level);
reed7a72c672014-11-07 10:23:55 -0800843 }
844 return 0;
845}
846
reed@google.come3823fd2013-05-30 18:55:14 +0000847static int lpaint_getFontID(lua_State* L) {
848 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
849 SkLua(L).pushU32(SkTypeface::UniqueID(face));
850 return 1;
851}
852
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000853static const struct {
854 const char* fLabel;
855 SkPaint::Align fAlign;
856} gAlignRec[] = {
857 { "left", SkPaint::kLeft_Align },
858 { "center", SkPaint::kCenter_Align },
859 { "right", SkPaint::kRight_Align },
860};
861
862static int lpaint_getTextAlign(lua_State* L) {
863 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
864 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
865 if (gAlignRec[i].fAlign == align) {
866 lua_pushstring(L, gAlignRec[i].fLabel);
867 return 1;
868 }
869 }
870 return 0;
871}
872
873static int lpaint_setTextAlign(lua_State* L) {
874 if (lua_isstring(L, 2)) {
875 size_t len;
876 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000877
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000878 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
879 if (!strcmp(gAlignRec[i].fLabel, label)) {
880 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
881 break;
882 }
883 }
884 }
885 return 0;
886}
887
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000888static int lpaint_getStroke(lua_State* L) {
889 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
890 return 1;
891}
892
893static int lpaint_setStroke(lua_State* L) {
894 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000895
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000896 if (lua_toboolean(L, 2)) {
897 style = SkPaint::kStroke_Style;
898 } else {
899 style = SkPaint::kFill_Style;
900 }
901 get_obj<SkPaint>(L, 1)->setStyle(style);
902 return 0;
903}
904
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000905static int lpaint_getStrokeCap(lua_State* L) {
906 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
907 return 1;
908}
909
910static int lpaint_getStrokeJoin(lua_State* L) {
911 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
912 return 1;
913}
914
915static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +0000916 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000917 return 1;
918}
919
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000920static int lpaint_getStrokeWidth(lua_State* L) {
921 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
922 return 1;
923}
924
925static int lpaint_setStrokeWidth(lua_State* L) {
926 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
927 return 0;
928}
929
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000930static int lpaint_getStrokeMiter(lua_State* L) {
931 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
932 return 1;
933}
934
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000935static int lpaint_measureText(lua_State* L) {
936 if (lua_isstring(L, 2)) {
937 size_t len;
938 const char* text = lua_tolstring(L, 2, &len);
939 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
940 return 1;
941 }
942 return 0;
943}
944
945struct FontMetrics {
946 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
947 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
948 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
949 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
950 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
951 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
952 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
953 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
954 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
955};
956
957static int lpaint_getFontMetrics(lua_State* L) {
958 SkPaint::FontMetrics fm;
959 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000960
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000961 lua_newtable(L);
962 setfield_scalar(L, "top", fm.fTop);
963 setfield_scalar(L, "ascent", fm.fAscent);
964 setfield_scalar(L, "descent", fm.fDescent);
965 setfield_scalar(L, "bottom", fm.fBottom);
966 setfield_scalar(L, "leading", fm.fLeading);
967 SkLua(L).pushScalar(height);
968 return 2;
969}
970
reed@google.com29563872013-07-10 21:23:49 +0000971static int lpaint_getEffects(lua_State* L) {
972 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000973
reed@google.com29563872013-07-10 21:23:49 +0000974 lua_newtable(L);
reed468b1812014-10-19 11:42:54 -0700975 setfield_bool_if(L, "looper", !!paint->getLooper());
976 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
reed468b1812014-10-19 11:42:54 -0700977 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
978 setfield_bool_if(L, "shader", !!paint->getShader());
reed@google.com29563872013-07-10 21:23:49 +0000979 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
980 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
reed@google.com29563872013-07-10 21:23:49 +0000981 return 1;
982}
983
reed22a517f2015-12-04 20:45:59 -0800984static int lpaint_getColorFilter(lua_State* L) {
985 const SkPaint* paint = get_obj<SkPaint>(L, 1);
986 SkColorFilter* cf = paint->getColorFilter();
987 if (cf) {
988 push_ref(L, cf);
989 return 1;
990 }
991 return 0;
992}
993
994static int lpaint_setColorFilter(lua_State* L) {
995 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedd053ce92016-03-22 10:17:23 -0700996 paint->setColorFilter(sk_ref_sp(get_ref<SkColorFilter>(L, 2)));
reed22a517f2015-12-04 20:45:59 -0800997 return 0;
998}
999
reed468b1812014-10-19 11:42:54 -07001000static int lpaint_getImageFilter(lua_State* L) {
1001 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1002 SkImageFilter* imf = paint->getImageFilter();
1003 if (imf) {
1004 push_ref(L, imf);
1005 return 1;
1006 }
1007 return 0;
1008}
1009
1010static int lpaint_setImageFilter(lua_State* L) {
1011 SkPaint* paint = get_obj<SkPaint>(L, 1);
Mike Reed5e257172016-11-01 11:22:05 -04001012 paint->setImageFilter(sk_ref_sp(get_ref<SkImageFilter>(L, 2)));
reed468b1812014-10-19 11:42:54 -07001013 return 0;
1014}
1015
reed@google.com5fdc9832013-07-24 15:47:52 +00001016static int lpaint_getShader(lua_State* L) {
1017 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1018 SkShader* shader = paint->getShader();
1019 if (shader) {
1020 push_ref(L, shader);
1021 return 1;
1022 }
1023 return 0;
1024}
1025
reed9fbc3f32014-10-21 07:12:58 -07001026static int lpaint_setShader(lua_State* L) {
1027 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedfe630452016-03-25 09:08:00 -07001028 paint->setShader(sk_ref_sp(get_ref<SkShader>(L, 2)));
reed9fbc3f32014-10-21 07:12:58 -07001029 return 0;
1030}
1031
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001032static int lpaint_getPathEffect(lua_State* L) {
1033 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1034 SkPathEffect* pe = paint->getPathEffect();
1035 if (pe) {
1036 push_ref(L, pe);
1037 return 1;
1038 }
1039 return 0;
1040}
1041
hstern0b401ce2016-08-02 09:17:59 -07001042static int lpaint_getFillPath(lua_State* L) {
1043 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1044 const SkPath* path = get_obj<SkPath>(L, 2);
1045
1046 SkPath fillpath;
1047 paint->getFillPath(*path, &fillpath);
1048
1049 SkLua lua(L);
1050 lua.pushPath(fillpath);
1051
1052 return 1;
1053}
1054
reed@google.com74ce6f02013-05-22 15:13:18 +00001055static int lpaint_gc(lua_State* L) {
1056 get_obj<SkPaint>(L, 1)->~SkPaint();
1057 return 0;
1058}
1059
1060static const struct luaL_Reg gSkPaint_Methods[] = {
1061 { "isAntiAlias", lpaint_isAntiAlias },
1062 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001063 { "isDither", lpaint_isDither },
reedbb8a0ab2014-11-03 22:32:07 -08001064 { "setDither", lpaint_setDither },
reed93a12152015-03-16 10:08:34 -07001065 { "getFilterQuality", lpaint_getFilterQuality },
1066 { "setFilterQuality", lpaint_setFilterQuality },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001067 { "isFakeBoldText", lpaint_isFakeBoldText },
1068 { "isLinearText", lpaint_isLinearText },
1069 { "isSubpixelText", lpaint_isSubpixelText },
reed09a1d672014-10-11 13:13:11 -07001070 { "setSubpixelText", lpaint_setSubpixelText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001071 { "isDevKernText", lpaint_isDevKernText },
1072 { "isLCDRenderText", lpaint_isLCDRenderText },
reed36c9c112014-11-04 10:58:42 -08001073 { "setLCDRenderText", lpaint_setLCDRenderText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001074 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
1075 { "isAutohinted", lpaint_isAutohinted },
1076 { "isVerticalText", lpaint_isVerticalText },
reed468b1812014-10-19 11:42:54 -07001077 { "getAlpha", lpaint_getAlpha },
1078 { "setAlpha", lpaint_setAlpha },
reed@google.com74ce6f02013-05-22 15:13:18 +00001079 { "getColor", lpaint_getColor },
1080 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +00001081 { "getTextSize", lpaint_getTextSize },
1082 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001083 { "getTextScaleX", lpaint_getTextScaleX },
1084 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001085 { "getTypeface", lpaint_getTypeface },
1086 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001087 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +00001088 { "getFontID", lpaint_getFontID },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001089 { "getTextAlign", lpaint_getTextAlign },
1090 { "setTextAlign", lpaint_setTextAlign },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001091 { "getStroke", lpaint_getStroke },
1092 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001093 { "getStrokeCap", lpaint_getStrokeCap },
1094 { "getStrokeJoin", lpaint_getStrokeJoin },
1095 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001096 { "getStrokeWidth", lpaint_getStrokeWidth },
1097 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001098 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001099 { "measureText", lpaint_measureText },
1100 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +00001101 { "getEffects", lpaint_getEffects },
reed22a517f2015-12-04 20:45:59 -08001102 { "getColorFilter", lpaint_getColorFilter },
1103 { "setColorFilter", lpaint_setColorFilter },
reed468b1812014-10-19 11:42:54 -07001104 { "getImageFilter", lpaint_getImageFilter },
1105 { "setImageFilter", lpaint_setImageFilter },
reed@google.com5fdc9832013-07-24 15:47:52 +00001106 { "getShader", lpaint_getShader },
reed9fbc3f32014-10-21 07:12:58 -07001107 { "setShader", lpaint_setShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001108 { "getPathEffect", lpaint_getPathEffect },
hstern0b401ce2016-08-02 09:17:59 -07001109 { "getFillPath", lpaint_getFillPath },
reed@google.com74ce6f02013-05-22 15:13:18 +00001110 { "__gc", lpaint_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001111 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001112};
1113
1114///////////////////////////////////////////////////////////////////////////////
1115
reed@google.com5fdc9832013-07-24 15:47:52 +00001116static const char* mode2string(SkShader::TileMode mode) {
1117 static const char* gNames[] = { "clamp", "repeat", "mirror" };
1118 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
1119 return gNames[mode];
1120}
1121
1122static const char* gradtype2string(SkShader::GradientType t) {
1123 static const char* gNames[] = {
1124 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
1125 };
1126 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
1127 return gNames[t];
1128}
1129
1130static int lshader_isOpaque(lua_State* L) {
1131 SkShader* shader = get_ref<SkShader>(L, 1);
1132 return shader && shader->isOpaque();
1133}
1134
Mike Reed627778d2016-09-28 17:13:38 -04001135static int lshader_isAImage(lua_State* L) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001136 SkShader* shader = get_ref<SkShader>(L, 1);
1137 if (shader) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001138 SkMatrix matrix;
1139 SkShader::TileMode modes[2];
Mike Reed627778d2016-09-28 17:13:38 -04001140 if (SkImage* image = shader->isAImage(&matrix, modes)) {
reedf5822822015-08-19 11:46:38 -07001141 lua_newtable(L);
Mike Reed627778d2016-09-28 17:13:38 -04001142 setfield_number(L, "id", image->uniqueID());
1143 setfield_number(L, "width", image->width());
1144 setfield_number(L, "height", image->height());
reedf5822822015-08-19 11:46:38 -07001145 setfield_string(L, "tileX", mode2string(modes[0]));
1146 setfield_string(L, "tileY", mode2string(modes[1]));
1147 return 1;
reed@google.com5fdc9832013-07-24 15:47:52 +00001148 }
1149 }
1150 return 0;
1151}
1152
1153static int lshader_asAGradient(lua_State* L) {
1154 SkShader* shader = get_ref<SkShader>(L, 1);
1155 if (shader) {
1156 SkShader::GradientInfo info;
1157 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001158
reed@google.com5fdc9832013-07-24 15:47:52 +00001159 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001160
reed@google.com5fdc9832013-07-24 15:47:52 +00001161 if (SkShader::kNone_GradientType != t) {
fmenozzib4f254e2016-06-28 14:03:03 -07001162 SkAutoTArray<SkScalar> pos(info.fColorCount);
1163 info.fColorOffsets = pos.get();
1164 shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001165
fmenozzib4f254e2016-06-28 14:03:03 -07001166 lua_newtable(L);
fmenozzi7f2c85e2016-07-12 09:17:39 -07001167 setfield_string(L, "type", gradtype2string(t));
1168 setfield_string(L, "tile", mode2string(info.fTileMode));
1169 setfield_number(L, "colorCount", info.fColorCount);
fmenozzib4f254e2016-06-28 14:03:03 -07001170
1171 lua_newtable(L);
1172 for (int i = 0; i < info.fColorCount; i++) {
1173 // Lua uses 1-based indexing
1174 setarray_scalar(L, i+1, pos[i]);
1175 }
1176 lua_setfield(L, -2, "positions");
1177
reed@google.com5fdc9832013-07-24 15:47:52 +00001178 return 1;
1179 }
1180 }
1181 return 0;
1182}
1183
1184static int lshader_gc(lua_State* L) {
1185 get_ref<SkShader>(L, 1)->unref();
1186 return 0;
1187}
1188
1189static const struct luaL_Reg gSkShader_Methods[] = {
1190 { "isOpaque", lshader_isOpaque },
Mike Reed627778d2016-09-28 17:13:38 -04001191 { "isAImage", lshader_isAImage },
reed@google.com5fdc9832013-07-24 15:47:52 +00001192 { "asAGradient", lshader_asAGradient },
1193 { "__gc", lshader_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001194 { nullptr, nullptr }
reed@google.com5fdc9832013-07-24 15:47:52 +00001195};
1196
1197///////////////////////////////////////////////////////////////////////////////
1198
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001199static int lpatheffect_asADash(lua_State* L) {
1200 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1201 if (pe) {
1202 SkPathEffect::DashInfo info;
1203 SkPathEffect::DashType dashType = pe->asADash(&info);
1204 if (SkPathEffect::kDash_DashType == dashType) {
1205 SkAutoTArray<SkScalar> intervals(info.fCount);
1206 info.fIntervals = intervals.get();
1207 pe->asADash(&info);
1208 SkLua(L).pushDash(info);
1209 return 1;
1210 }
1211 }
1212 return 0;
1213}
1214
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001215static int lpatheffect_gc(lua_State* L) {
1216 get_ref<SkPathEffect>(L, 1)->unref();
1217 return 0;
1218}
1219
1220static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001221 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001222 { "__gc", lpatheffect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001223 { nullptr, nullptr }
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001224};
1225
1226///////////////////////////////////////////////////////////////////////////////
1227
reed22a517f2015-12-04 20:45:59 -08001228static int lpcolorfilter_gc(lua_State* L) {
1229 get_ref<SkColorFilter>(L, 1)->unref();
1230 return 0;
1231}
1232
1233static const struct luaL_Reg gSkColorFilter_Methods[] = {
1234 { "__gc", lpcolorfilter_gc },
1235 { nullptr, nullptr }
1236};
1237
1238///////////////////////////////////////////////////////////////////////////////
1239
reed468b1812014-10-19 11:42:54 -07001240static int lpimagefilter_gc(lua_State* L) {
1241 get_ref<SkImageFilter>(L, 1)->unref();
1242 return 0;
1243}
1244
1245static const struct luaL_Reg gSkImageFilter_Methods[] = {
1246 { "__gc", lpimagefilter_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001247 { nullptr, nullptr }
reed468b1812014-10-19 11:42:54 -07001248};
1249
1250///////////////////////////////////////////////////////////////////////////////
1251
humper@google.com2815c192013-07-10 22:42:30 +00001252static int lmatrix_getType(lua_State* L) {
1253 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001254
humper@google.com2815c192013-07-10 22:42:30 +00001255 lua_newtable(L);
1256 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1257 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1258 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1259 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1260 return 1;
1261}
1262
humper@google.com0f48ee02013-07-26 15:23:43 +00001263static int lmatrix_getScaleX(lua_State* L) {
1264 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1265 return 1;
1266}
1267
1268static int lmatrix_getScaleY(lua_State* L) {
1269 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1270 return 1;
1271}
1272
1273static int lmatrix_getTranslateX(lua_State* L) {
1274 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1275 return 1;
1276}
1277
1278static int lmatrix_getTranslateY(lua_State* L) {
1279 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1280 return 1;
1281}
1282
reed7a72c672014-11-07 10:23:55 -08001283static int lmatrix_invert(lua_State* L) {
1284 lua_pushboolean(L, get_obj<SkMatrix>(L, 1)->invert(get_obj<SkMatrix>(L, 2)));
1285 return 1;
1286}
1287
1288static int lmatrix_mapXY(lua_State* L) {
1289 SkPoint pt = { lua2scalar(L, 2), lua2scalar(L, 3) };
1290 get_obj<SkMatrix>(L, 1)->mapPoints(&pt, &pt, 1);
1291 lua_pushnumber(L, pt.x());
1292 lua_pushnumber(L, pt.y());
1293 return 2;
1294}
1295
reedbdc49ae2014-10-14 09:34:52 -07001296static int lmatrix_setRectToRect(lua_State* L) {
1297 SkMatrix* matrix = get_obj<SkMatrix>(L, 1);
1298 SkRect srcR, dstR;
1299 lua2rect(L, 2, &srcR);
1300 lua2rect(L, 3, &dstR);
1301 const char* scaleToFitStr = lua_tostring(L, 4);
1302 SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit;
1303
1304 if (scaleToFitStr) {
1305 const struct {
1306 const char* fName;
1307 SkMatrix::ScaleToFit fScaleToFit;
1308 } rec[] = {
1309 { "fill", SkMatrix::kFill_ScaleToFit },
1310 { "start", SkMatrix::kStart_ScaleToFit },
1311 { "center", SkMatrix::kCenter_ScaleToFit },
1312 { "end", SkMatrix::kEnd_ScaleToFit },
1313 };
1314
1315 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
1316 if (strcmp(rec[i].fName, scaleToFitStr) == 0) {
1317 scaleToFit = rec[i].fScaleToFit;
1318 break;
1319 }
1320 }
1321 }
1322
1323 matrix->setRectToRect(srcR, dstR, scaleToFit);
1324 return 0;
1325}
1326
humper@google.com2815c192013-07-10 22:42:30 +00001327static const struct luaL_Reg gSkMatrix_Methods[] = {
1328 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001329 { "getScaleX", lmatrix_getScaleX },
1330 { "getScaleY", lmatrix_getScaleY },
1331 { "getTranslateX", lmatrix_getTranslateX },
1332 { "getTranslateY", lmatrix_getTranslateY },
reedbdc49ae2014-10-14 09:34:52 -07001333 { "setRectToRect", lmatrix_setRectToRect },
reed7a72c672014-11-07 10:23:55 -08001334 { "invert", lmatrix_invert },
1335 { "mapXY", lmatrix_mapXY },
halcanary96fcdcc2015-08-27 07:41:13 -07001336 { nullptr, nullptr }
humper@google.com2815c192013-07-10 22:42:30 +00001337};
1338
1339///////////////////////////////////////////////////////////////////////////////
1340
reed@google.com74ce6f02013-05-22 15:13:18 +00001341static int lpath_getBounds(lua_State* L) {
1342 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1343 return 1;
1344}
1345
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001346static const char* fill_type_to_str(SkPath::FillType fill) {
1347 switch (fill) {
1348 case SkPath::kEvenOdd_FillType:
1349 return "even-odd";
1350 case SkPath::kWinding_FillType:
1351 return "winding";
1352 case SkPath::kInverseEvenOdd_FillType:
1353 return "inverse-even-odd";
1354 case SkPath::kInverseWinding_FillType:
1355 return "inverse-winding";
1356 }
1357 return "unknown";
1358}
1359
1360static int lpath_getFillType(lua_State* L) {
1361 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1362 SkLua(L).pushString(fill_type_to_str(fill));
1363 return 1;
1364}
1365
1366static SkString segment_masks_to_str(uint32_t segmentMasks) {
1367 SkString result;
1368 bool first = true;
1369 if (SkPath::kLine_SegmentMask & segmentMasks) {
1370 result.append("line");
1371 first = false;
1372 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1373 }
1374 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1375 if (!first) {
1376 result.append(" ");
1377 }
1378 result.append("quad");
1379 first = false;
1380 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1381 }
1382 if (SkPath::kConic_SegmentMask & segmentMasks) {
1383 if (!first) {
1384 result.append(" ");
1385 }
1386 result.append("conic");
1387 first = false;
1388 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1389 }
1390 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1391 if (!first) {
1392 result.append(" ");
1393 }
1394 result.append("cubic");
1395 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1396 }
1397 SkASSERT(0 == segmentMasks);
1398 return result;
1399}
1400
krajcevski95498ed2014-08-18 08:02:33 -07001401static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001402 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1403 SkLua(L).pushString(segment_masks_to_str(segMasks));
1404 return 1;
1405}
1406
1407static int lpath_isConvex(lua_State* L) {
1408 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1409 SkLua(L).pushBool(isConvex);
1410 return 1;
1411}
1412
reed@google.com74ce6f02013-05-22 15:13:18 +00001413static int lpath_isEmpty(lua_State* L) {
1414 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1415 return 1;
1416}
1417
1418static int lpath_isRect(lua_State* L) {
1419 SkRect r;
1420 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1421 int ret_count = 1;
1422 lua_pushboolean(L, pred);
1423 if (pred) {
1424 SkLua(L).pushRect(r);
1425 ret_count += 1;
1426 }
1427 return ret_count;
1428}
1429
1430static const char* dir2string(SkPath::Direction dir) {
1431 static const char* gStr[] = {
1432 "unknown", "cw", "ccw"
1433 };
1434 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1435 return gStr[dir];
1436}
1437
caryclark95bc5f32015-04-08 08:34:15 -07001438static int lpath_isNestedFillRects(lua_State* L) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001439 SkRect rects[2];
1440 SkPath::Direction dirs[2];
caryclark95bc5f32015-04-08 08:34:15 -07001441 bool pred = get_obj<SkPath>(L, 1)->isNestedFillRects(rects, dirs);
reed@google.com74ce6f02013-05-22 15:13:18 +00001442 int ret_count = 1;
1443 lua_pushboolean(L, pred);
1444 if (pred) {
1445 SkLua lua(L);
1446 lua.pushRect(rects[0]);
1447 lua.pushRect(rects[1]);
1448 lua_pushstring(L, dir2string(dirs[0]));
1449 lua_pushstring(L, dir2string(dirs[0]));
1450 ret_count += 4;
1451 }
1452 return ret_count;
1453}
1454
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001455static int lpath_countPoints(lua_State* L) {
1456 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1457 return 1;
1458}
1459
hstern0b401ce2016-08-02 09:17:59 -07001460static int lpath_getVerbs(lua_State* L) {
1461 const SkPath* path = get_obj<SkPath>(L, 1);
1462 SkPath::Iter iter(*path, false);
1463 SkPoint pts[4];
1464
1465 lua_newtable(L);
1466
1467 bool done = false;
1468 int i = 0;
1469 do {
1470 switch (iter.next(pts, true)) {
1471 case SkPath::kMove_Verb:
1472 setarray_string(L, ++i, "move");
1473 break;
1474 case SkPath::kClose_Verb:
1475 setarray_string(L, ++i, "close");
1476 break;
1477 case SkPath::kLine_Verb:
1478 setarray_string(L, ++i, "line");
1479 break;
1480 case SkPath::kQuad_Verb:
1481 setarray_string(L, ++i, "quad");
1482 break;
1483 case SkPath::kConic_Verb:
1484 setarray_string(L, ++i, "conic");
1485 break;
1486 case SkPath::kCubic_Verb:
1487 setarray_string(L, ++i, "cubic");
1488 break;
1489 case SkPath::kDone_Verb:
1490 setarray_string(L, ++i, "done");
1491 done = true;
1492 break;
1493 }
1494 } while (!done);
1495
1496 return 1;
1497}
1498
reed@google.com74ce6f02013-05-22 15:13:18 +00001499static int lpath_reset(lua_State* L) {
1500 get_obj<SkPath>(L, 1)->reset();
1501 return 0;
1502}
1503
1504static int lpath_moveTo(lua_State* L) {
1505 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1506 return 0;
1507}
1508
1509static int lpath_lineTo(lua_State* L) {
1510 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1511 return 0;
1512}
1513
1514static int lpath_quadTo(lua_State* L) {
1515 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1516 lua2scalar(L, 4), lua2scalar(L, 5));
1517 return 0;
1518}
1519
1520static int lpath_cubicTo(lua_State* L) {
1521 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1522 lua2scalar(L, 4), lua2scalar(L, 5),
1523 lua2scalar(L, 6), lua2scalar(L, 7));
1524 return 0;
1525}
1526
1527static int lpath_close(lua_State* L) {
1528 get_obj<SkPath>(L, 1)->close();
1529 return 0;
1530}
1531
1532static int lpath_gc(lua_State* L) {
1533 get_obj<SkPath>(L, 1)->~SkPath();
1534 return 0;
1535}
1536
1537static const struct luaL_Reg gSkPath_Methods[] = {
1538 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001539 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001540 { "getSegmentTypes", lpath_getSegmentTypes },
hstern0b401ce2016-08-02 09:17:59 -07001541 { "getVerbs", lpath_getVerbs },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001542 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001543 { "isEmpty", lpath_isEmpty },
1544 { "isRect", lpath_isRect },
caryclark95bc5f32015-04-08 08:34:15 -07001545 { "isNestedFillRects", lpath_isNestedFillRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001546 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001547 { "reset", lpath_reset },
1548 { "moveTo", lpath_moveTo },
1549 { "lineTo", lpath_lineTo },
1550 { "quadTo", lpath_quadTo },
1551 { "cubicTo", lpath_cubicTo },
1552 { "close", lpath_close },
1553 { "__gc", lpath_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001554 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001555};
1556
1557///////////////////////////////////////////////////////////////////////////////
1558
1559static const char* rrect_type(const SkRRect& rr) {
1560 switch (rr.getType()) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001561 case SkRRect::kEmpty_Type: return "empty";
1562 case SkRRect::kRect_Type: return "rect";
1563 case SkRRect::kOval_Type: return "oval";
1564 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001565 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001566 case SkRRect::kComplex_Type: return "complex";
1567 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001568 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001569 return "";
1570}
1571
1572static int lrrect_rect(lua_State* L) {
1573 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1574 return 1;
1575}
1576
1577static int lrrect_type(lua_State* L) {
1578 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1579 return 1;
1580}
1581
1582static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001583 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001584 SkVector v;
1585 if (corner < 0 || corner > 3) {
1586 SkDebugf("bad corner index %d", corner);
1587 v.set(0, 0);
1588 } else {
1589 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1590 }
1591 lua_pushnumber(L, v.fX);
1592 lua_pushnumber(L, v.fY);
1593 return 2;
1594}
1595
1596static int lrrect_gc(lua_State* L) {
1597 get_obj<SkRRect>(L, 1)->~SkRRect();
1598 return 0;
1599}
1600
1601static const struct luaL_Reg gSkRRect_Methods[] = {
1602 { "rect", lrrect_rect },
1603 { "type", lrrect_type },
1604 { "radii", lrrect_radii },
1605 { "__gc", lrrect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001606 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001607};
1608
1609///////////////////////////////////////////////////////////////////////////////
1610
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001611static int limage_width(lua_State* L) {
1612 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1613 return 1;
1614}
1615
1616static int limage_height(lua_State* L) {
1617 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1618 return 1;
1619}
1620
reed7a72c672014-11-07 10:23:55 -08001621static int limage_newShader(lua_State* L) {
1622 SkShader::TileMode tmode = SkShader::kClamp_TileMode;
halcanary96fcdcc2015-08-27 07:41:13 -07001623 const SkMatrix* localM = nullptr;
reed5671c5b2016-03-09 14:47:34 -08001624 push_ref(L, get_ref<SkImage>(L, 1)->makeShader(tmode, tmode, localM));
reed7a72c672014-11-07 10:23:55 -08001625 return 1;
1626}
1627
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001628static int limage_gc(lua_State* L) {
1629 get_ref<SkImage>(L, 1)->unref();
1630 return 0;
1631}
1632
1633static const struct luaL_Reg gSkImage_Methods[] = {
1634 { "width", limage_width },
1635 { "height", limage_height },
reed7a72c672014-11-07 10:23:55 -08001636 { "newShader", limage_newShader },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001637 { "__gc", limage_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001638 { nullptr, nullptr }
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001639};
1640
1641///////////////////////////////////////////////////////////////////////////////
1642
reed485557f2014-10-12 10:36:47 -07001643static int lsurface_width(lua_State* L) {
1644 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1645 return 1;
1646}
1647
1648static int lsurface_height(lua_State* L) {
1649 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1650 return 1;
1651}
1652
1653static int lsurface_getCanvas(lua_State* L) {
1654 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001655 if (nullptr == canvas) {
reed485557f2014-10-12 10:36:47 -07001656 lua_pushnil(L);
1657 } else {
Mike Reed5df49342016-11-12 08:06:55 -06001658 push_ptr(L, canvas);
reed485557f2014-10-12 10:36:47 -07001659 // note: we don't unref canvas, since getCanvas did not ref it.
1660 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1661 // the real owner (the surface) go away, but still hold onto the canvas?
1662 // *really* we want to sort of ref the surface again, but have the native object
1663 // know that it is supposed to be treated as a canvas...
1664 }
1665 return 1;
1666}
1667
1668static int lsurface_newImageSnapshot(lua_State* L) {
reed9ce9d672016-03-17 10:51:11 -07001669 sk_sp<SkImage> image = get_ref<SkSurface>(L, 1)->makeImageSnapshot();
1670 if (!image) {
reed485557f2014-10-12 10:36:47 -07001671 lua_pushnil(L);
1672 } else {
reed9ce9d672016-03-17 10:51:11 -07001673 push_ref(L, image);
reed485557f2014-10-12 10:36:47 -07001674 }
1675 return 1;
1676}
1677
1678static int lsurface_newSurface(lua_State* L) {
1679 int width = lua2int_def(L, 2, 0);
reed96affcd2014-10-13 12:38:04 -07001680 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -07001681 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -07001682 auto surface = get_ref<SkSurface>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -07001683 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07001684 lua_pushnil(L);
1685 } else {
reede8f30622016-03-23 18:59:25 -07001686 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07001687 }
1688 return 1;
1689}
1690
1691static int lsurface_gc(lua_State* L) {
1692 get_ref<SkSurface>(L, 1)->unref();
1693 return 0;
1694}
1695
1696static const struct luaL_Reg gSkSurface_Methods[] = {
1697 { "width", lsurface_width },
1698 { "height", lsurface_height },
1699 { "getCanvas", lsurface_getCanvas },
1700 { "newImageSnapshot", lsurface_newImageSnapshot },
1701 { "newSurface", lsurface_newSurface },
1702 { "__gc", lsurface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001703 { nullptr, nullptr }
reed485557f2014-10-12 10:36:47 -07001704};
1705
1706///////////////////////////////////////////////////////////////////////////////
1707
reed96affcd2014-10-13 12:38:04 -07001708static int lpicturerecorder_beginRecording(lua_State* L) {
1709 const SkScalar w = lua2scalar_def(L, 2, -1);
1710 const SkScalar h = lua2scalar_def(L, 3, -1);
1711 if (w <= 0 || h <= 0) {
1712 lua_pushnil(L);
1713 return 1;
1714 }
1715
1716 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
halcanary96fcdcc2015-08-27 07:41:13 -07001717 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001718 lua_pushnil(L);
1719 return 1;
1720 }
1721
Mike Reed5df49342016-11-12 08:06:55 -06001722 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001723 return 1;
1724}
1725
1726static int lpicturerecorder_getCanvas(lua_State* L) {
1727 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001728 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001729 lua_pushnil(L);
1730 return 1;
1731 }
Mike Reed5df49342016-11-12 08:06:55 -06001732 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001733 return 1;
1734}
1735
1736static int lpicturerecorder_endRecording(lua_State* L) {
reedca2622b2016-03-18 07:25:55 -07001737 sk_sp<SkPicture> pic = get_obj<SkPictureRecorder>(L, 1)->finishRecordingAsPicture();
1738 if (!pic) {
reed96affcd2014-10-13 12:38:04 -07001739 lua_pushnil(L);
1740 return 1;
1741 }
reedca2622b2016-03-18 07:25:55 -07001742 push_ref(L, std::move(pic));
reed96affcd2014-10-13 12:38:04 -07001743 return 1;
1744}
1745
1746static int lpicturerecorder_gc(lua_State* L) {
1747 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1748 return 0;
1749}
1750
1751static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1752 { "beginRecording", lpicturerecorder_beginRecording },
1753 { "getCanvas", lpicturerecorder_getCanvas },
1754 { "endRecording", lpicturerecorder_endRecording },
1755 { "__gc", lpicturerecorder_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001756 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001757};
1758
1759///////////////////////////////////////////////////////////////////////////////
1760
1761static int lpicture_width(lua_State* L) {
1762 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1763 return 1;
1764}
1765
1766static int lpicture_height(lua_State* L) {
1767 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1768 return 1;
1769}
1770
1771static int lpicture_gc(lua_State* L) {
1772 get_ref<SkPicture>(L, 1)->unref();
1773 return 0;
1774}
1775
1776static const struct luaL_Reg gSkPicture_Methods[] = {
1777 { "width", lpicture_width },
1778 { "height", lpicture_height },
1779 { "__gc", lpicture_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001780 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001781};
1782
1783///////////////////////////////////////////////////////////////////////////////
1784
reed1b6ab442014-11-03 19:55:41 -08001785static int ltextblob_bounds(lua_State* L) {
1786 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
1787 return 1;
1788}
1789
1790static int ltextblob_gc(lua_State* L) {
1791 SkSafeUnref(get_ref<SkTextBlob>(L, 1));
1792 return 0;
1793}
1794
1795static const struct luaL_Reg gSkTextBlob_Methods[] = {
1796 { "bounds", ltextblob_bounds },
1797 { "__gc", ltextblob_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001798 { nullptr, nullptr }
reed1b6ab442014-11-03 19:55:41 -08001799};
1800
1801///////////////////////////////////////////////////////////////////////////////
1802
reed36c9c112014-11-04 10:58:42 -08001803static int ltypeface_getFamilyName(lua_State* L) {
1804 SkString str;
1805 get_ref<SkTypeface>(L, 1)->getFamilyName(&str);
1806 lua_pushstring(L, str.c_str());
1807 return 1;
1808}
1809
1810static int ltypeface_getStyle(lua_State* L) {
Ben Wagner26308e12017-08-08 15:23:47 -04001811 push_obj(L, get_ref<SkTypeface>(L, 1)->fontStyle());
reed36c9c112014-11-04 10:58:42 -08001812 return 1;
1813}
1814
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001815static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001816 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001817 return 0;
1818}
1819
1820static const struct luaL_Reg gSkTypeface_Methods[] = {
reed36c9c112014-11-04 10:58:42 -08001821 { "getFamilyName", ltypeface_getFamilyName },
1822 { "getStyle", ltypeface_getStyle },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001823 { "__gc", ltypeface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001824 { nullptr, nullptr }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001825};
1826
1827///////////////////////////////////////////////////////////////////////////////
1828
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001829static int lfontstyle_weight(lua_State* L) {
1830 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->weight());
1831 return 1;
1832}
1833
1834static int lfontstyle_width(lua_State* L) {
1835 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->width());
1836 return 1;
1837}
1838
1839static int lfontstyle_slant(lua_State* L) {
1840 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->slant());
1841 return 1;
1842}
1843
1844static int lfontstyle_gc(lua_State* L) {
1845 get_obj<SkFontStyle>(L, 1)->~SkFontStyle();
1846 return 0;
1847}
1848
1849static const struct luaL_Reg gSkFontStyle_Methods[] = {
1850 { "weight", lfontstyle_weight },
1851 { "width", lfontstyle_width },
1852 { "slant", lfontstyle_slant },
1853 { "__gc", lfontstyle_gc },
1854 { nullptr, nullptr }
1855};
1856
1857///////////////////////////////////////////////////////////////////////////////
1858
reed@google.com74ce6f02013-05-22 15:13:18 +00001859class AutoCallLua {
1860public:
1861 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1862 lua_getglobal(L, func);
1863 if (!lua_isfunction(L, -1)) {
1864 int t = lua_type(L, -1);
1865 SkDebugf("--- expected function %d\n", t);
1866 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001867
reed@google.com74ce6f02013-05-22 15:13:18 +00001868 lua_newtable(L);
1869 setfield_string(L, "verb", verb);
1870 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001871
reed@google.com74ce6f02013-05-22 15:13:18 +00001872 ~AutoCallLua() {
1873 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1874 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1875 }
1876 lua_settop(fL, -1);
1877 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001878
reed@google.com74ce6f02013-05-22 15:13:18 +00001879private:
1880 lua_State* fL;
1881};
1882
1883#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1884
1885///////////////////////////////////////////////////////////////////////////////
1886
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001887static int lsk_newDocumentPDF(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -05001888 const char* filename = nullptr;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001889 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
Mike Reed7ff6ca52018-01-08 14:45:31 -05001890 filename = lua_tolstring(L, 1, nullptr);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001891 }
Mike Reed7ff6ca52018-01-08 14:45:31 -05001892 if (!filename) {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001893 return 0;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001894 }
Mike Reed7ff6ca52018-01-08 14:45:31 -05001895 auto file = skstd::make_unique<SkFILEWStream>(filename);
1896 if (!file->isValid()) {
1897 return 0;
1898 }
1899 sk_sp<SkDocument> doc = SkDocument::MakePDF(file.get());
1900 if (!doc) {
1901 return 0;
1902 }
1903 push_ptr(L, new DocHolder{std::move(doc), std::move(file)});
1904 return 1;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001905}
1906
reed468b1812014-10-19 11:42:54 -07001907static int lsk_newBlurImageFilter(lua_State* L) {
1908 SkScalar sigmaX = lua2scalar_def(L, 1, 0);
1909 SkScalar sigmaY = lua2scalar_def(L, 2, 0);
robertphillips6e7025a2016-04-04 04:31:25 -07001910 sk_sp<SkImageFilter> imf(SkBlurImageFilter::Make(sigmaX, sigmaY, nullptr));
1911 if (!imf) {
reed468b1812014-10-19 11:42:54 -07001912 lua_pushnil(L);
1913 } else {
robertphillips6e7025a2016-04-04 04:31:25 -07001914 push_ref(L, std::move(imf));
reed9fbc3f32014-10-21 07:12:58 -07001915 }
1916 return 1;
1917}
1918
1919static int lsk_newLinearGradient(lua_State* L) {
1920 SkScalar x0 = lua2scalar_def(L, 1, 0);
1921 SkScalar y0 = lua2scalar_def(L, 2, 0);
1922 SkColor c0 = lua2color(L, 3);
1923 SkScalar x1 = lua2scalar_def(L, 4, 0);
1924 SkScalar y1 = lua2scalar_def(L, 5, 0);
1925 SkColor c1 = lua2color(L, 6);
1926
1927 SkPoint pts[] = { { x0, y0 }, { x1, y1 } };
1928 SkColor colors[] = { c0, c1 };
robertphillips6e7025a2016-04-04 04:31:25 -07001929 sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
1930 SkShader::kClamp_TileMode));
reed2ad1aa62016-03-09 09:50:50 -08001931 if (!s) {
reed9fbc3f32014-10-21 07:12:58 -07001932 lua_pushnil(L);
1933 } else {
reed2ad1aa62016-03-09 09:50:50 -08001934 push_ref(L, std::move(s));
reed468b1812014-10-19 11:42:54 -07001935 }
1936 return 1;
1937}
1938
reedbdc49ae2014-10-14 09:34:52 -07001939static int lsk_newMatrix(lua_State* L) {
1940 push_new<SkMatrix>(L)->reset();
1941 return 1;
1942}
1943
reed@google.com3597b732013-05-22 20:12:50 +00001944static int lsk_newPaint(lua_State* L) {
1945 push_new<SkPaint>(L);
1946 return 1;
1947}
1948
1949static int lsk_newPath(lua_State* L) {
1950 push_new<SkPath>(L);
1951 return 1;
1952}
1953
reed96affcd2014-10-13 12:38:04 -07001954static int lsk_newPictureRecorder(lua_State* L) {
1955 push_new<SkPictureRecorder>(L);
1956 return 1;
1957}
1958
reed@google.com3597b732013-05-22 20:12:50 +00001959static int lsk_newRRect(lua_State* L) {
reedbdc49ae2014-10-14 09:34:52 -07001960 push_new<SkRRect>(L)->setEmpty();
reed@google.com3597b732013-05-22 20:12:50 +00001961 return 1;
1962}
1963
reed1b6ab442014-11-03 19:55:41 -08001964// Sk.newTextBlob(text, rect, paint)
1965static int lsk_newTextBlob(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001966 const char* text = lua_tolstring(L, 1, nullptr);
reed1b6ab442014-11-03 19:55:41 -08001967 SkRect bounds;
1968 lua2rect(L, 2, &bounds);
1969 const SkPaint& paint = *get_obj<SkPaint>(L, 3);
1970
Herb Derby1724db12018-05-22 12:01:50 -04001971 SkShaper shaper(nullptr);
reed1b6ab442014-11-03 19:55:41 -08001972
Herb Derby1724db12018-05-22 12:01:50 -04001973 SkTextBlobBuilder builder;
1974 SkPoint end = shaper.shape(&builder, paint, text, strlen(text), true,
1975 { bounds.left(), bounds.top() }, bounds.width());
1976
1977 push_ref<SkTextBlob>(L, builder.make());
1978 SkLua(L).pushScalar(end.fY);
reed1b6ab442014-11-03 19:55:41 -08001979 return 2;
1980}
1981
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001982static int lsk_newTypeface(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001983 const char* name = nullptr;
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001984 SkFontStyle style;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00001985
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001986 int count = lua_gettop(L);
1987 if (count > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001988 name = lua_tolstring(L, 1, nullptr);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001989 if (count > 1) {
1990 SkFontStyle* passedStyle = get_obj<SkFontStyle>(L, 2);
1991 if (passedStyle) {
1992 style = *passedStyle;
1993 }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001994 }
1995 }
1996
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001997 sk_sp<SkTypeface> face(SkTypeface::MakeFromName(name, style));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001998// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
halcanary96fcdcc2015-08-27 07:41:13 -07001999 if (nullptr == face) {
bungeman13b9c952016-05-12 10:09:30 -07002000 face = SkTypeface::MakeDefault();
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002001 }
bungeman13b9c952016-05-12 10:09:30 -07002002 push_ref(L, std::move(face));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002003 return 1;
2004}
reed@google.com3597b732013-05-22 20:12:50 +00002005
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002006static int lsk_newFontStyle(lua_State* L) {
2007 int count = lua_gettop(L);
2008 int weight = SkFontStyle::kNormal_Weight;
2009 int width = SkFontStyle::kNormal_Width;
2010 SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
2011 if (count >= 1 && lua_isnumber(L, 1)) {
2012 weight = lua_tointegerx(L, 1, nullptr);
2013 }
2014 if (count >= 2 && lua_isnumber(L, 2)) {
2015 width = lua_tointegerx(L, 2, nullptr);
2016 }
2017 if (count >= 3 && lua_isnumber(L, 3)) {
2018 slant = static_cast<SkFontStyle::Slant>(lua_tointegerx(L, 3, nullptr));
2019 }
2020 push_new<SkFontStyle>(L, weight, width, slant);
2021 return 1;
2022}
2023
reed485557f2014-10-12 10:36:47 -07002024static int lsk_newRasterSurface(lua_State* L) {
reed7b864662014-11-04 13:24:47 -08002025 int width = lua2int_def(L, 1, 0);
reed485557f2014-10-12 10:36:47 -07002026 int height = lua2int_def(L, 2, 0);
2027 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
robertphillips702edbd2015-06-23 06:26:08 -07002028 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
reede8f30622016-03-23 18:59:25 -07002029 auto surface = SkSurface::MakeRaster(info, &props);
halcanary96fcdcc2015-08-27 07:41:13 -07002030 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07002031 lua_pushnil(L);
2032 } else {
reede8f30622016-03-23 18:59:25 -07002033 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07002034 }
2035 return 1;
2036}
2037
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002038static int lsk_loadImage(lua_State* L) {
2039 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002040 const char* name = lua_tolstring(L, 1, nullptr);
reed9ce9d672016-03-17 10:51:11 -07002041 sk_sp<SkData> data(SkData::MakeFromFileName(name));
2042 if (data) {
2043 auto image = SkImage::MakeFromEncoded(std::move(data));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002044 if (image) {
reed9ce9d672016-03-17 10:51:11 -07002045 push_ref(L, std::move(image));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002046 return 1;
2047 }
2048 }
2049 }
2050 return 0;
2051}
2052
reed@google.com3597b732013-05-22 20:12:50 +00002053static void register_Sk(lua_State* L) {
2054 lua_newtable(L);
2055 lua_pushvalue(L, -1);
2056 lua_setglobal(L, "Sk");
2057 // the Sk table is still on top
2058
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00002059 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002060 setfield_function(L, "loadImage", lsk_loadImage);
reed468b1812014-10-19 11:42:54 -07002061 setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
reed9fbc3f32014-10-21 07:12:58 -07002062 setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
reedbdc49ae2014-10-14 09:34:52 -07002063 setfield_function(L, "newMatrix", lsk_newMatrix);
reed@google.com3597b732013-05-22 20:12:50 +00002064 setfield_function(L, "newPaint", lsk_newPaint);
2065 setfield_function(L, "newPath", lsk_newPath);
reed96affcd2014-10-13 12:38:04 -07002066 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
reed@google.com3597b732013-05-22 20:12:50 +00002067 setfield_function(L, "newRRect", lsk_newRRect);
reed485557f2014-10-12 10:36:47 -07002068 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
reed1b6ab442014-11-03 19:55:41 -08002069 setfield_function(L, "newTextBlob", lsk_newTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002070 setfield_function(L, "newTypeface", lsk_newTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002071 setfield_function(L, "newFontStyle", lsk_newFontStyle);
reed@google.com3597b732013-05-22 20:12:50 +00002072 lua_pop(L, 1); // pop off the Sk table
2073}
2074
reed@google.com74ce6f02013-05-22 15:13:18 +00002075#define REG_CLASS(L, C) \
2076 do { \
reed@google.com3597b732013-05-22 20:12:50 +00002077 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00002078 lua_pushvalue(L, -1); \
2079 lua_setfield(L, -2, "__index"); \
2080 luaL_setfuncs(L, g##C##_Methods, 0); \
2081 lua_pop(L, 1); /* pop off the meta-table */ \
2082 } while (0)
2083
2084void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00002085 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00002086 REG_CLASS(L, SkCanvas);
reed22a517f2015-12-04 20:45:59 -08002087 REG_CLASS(L, SkColorFilter);
Mike Reed7ff6ca52018-01-08 14:45:31 -05002088 REG_CLASS(L, DocHolder);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002089 REG_CLASS(L, SkImage);
reed468b1812014-10-19 11:42:54 -07002090 REG_CLASS(L, SkImageFilter);
reed1b6ab442014-11-03 19:55:41 -08002091 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00002092 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00002093 REG_CLASS(L, SkPath);
2094 REG_CLASS(L, SkPathEffect);
reed96affcd2014-10-13 12:38:04 -07002095 REG_CLASS(L, SkPicture);
2096 REG_CLASS(L, SkPictureRecorder);
reed@google.com74ce6f02013-05-22 15:13:18 +00002097 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00002098 REG_CLASS(L, SkShader);
reed485557f2014-10-12 10:36:47 -07002099 REG_CLASS(L, SkSurface);
reed1b6ab442014-11-03 19:55:41 -08002100 REG_CLASS(L, SkTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002101 REG_CLASS(L, SkTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002102 REG_CLASS(L, SkFontStyle);
reed@google.com74ce6f02013-05-22 15:13:18 +00002103}
zachr@google.com28c27c82013-06-20 17:15:05 +00002104
reed@google.com7bce9982013-06-20 17:40:21 +00002105extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00002106extern "C" int luaopen_skia(lua_State* L) {
2107 SkLua::Load(L);
2108 return 0;
2109}