blob: 887e251ff23913ed3799af907297c077e8d0971d [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"
Hal Canaryc640d0d2018-06-13 09:59:02 -040033#include "SkTo.h"
reed@google.come3823fd2013-05-30 18:55:14 +000034#include "SkTypeface.h"
Mike Klein79aea6a2018-06-11 10:45:26 -040035#include <new>
reed@google.com74ce6f02013-05-22 15:13:18 +000036
37extern "C" {
reed@google.com3597b732013-05-22 20:12:50 +000038 #include "lua.h"
39 #include "lualib.h"
40 #include "lauxlib.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000041}
42
Mike Reed7ff6ca52018-01-08 14:45:31 -050043struct DocHolder {
44 sk_sp<SkDocument> fDoc;
45 std::unique_ptr<SkWStream> fStream;
46};
47
reed@google.comfd345872013-05-22 20:53:42 +000048// return the metatable name for a given class
reed@google.com3597b732013-05-22 20:12:50 +000049template <typename T> const char* get_mtname();
reed@google.comfd345872013-05-22 20:53:42 +000050#define DEF_MTNAME(T) \
51 template <> const char* get_mtname<T>() { \
52 return #T "_LuaMetaTableName"; \
53 }
54
55DEF_MTNAME(SkCanvas)
reed22a517f2015-12-04 20:45:59 -080056DEF_MTNAME(SkColorFilter)
Mike Reed7ff6ca52018-01-08 14:45:31 -050057DEF_MTNAME(DocHolder)
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000058DEF_MTNAME(SkImage)
reed468b1812014-10-19 11:42:54 -070059DEF_MTNAME(SkImageFilter)
reed@google.comfd345872013-05-22 20:53:42 +000060DEF_MTNAME(SkMatrix)
61DEF_MTNAME(SkRRect)
62DEF_MTNAME(SkPath)
63DEF_MTNAME(SkPaint)
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +000064DEF_MTNAME(SkPathEffect)
reed96affcd2014-10-13 12:38:04 -070065DEF_MTNAME(SkPicture)
66DEF_MTNAME(SkPictureRecorder)
reed@google.com5fdc9832013-07-24 15:47:52 +000067DEF_MTNAME(SkShader)
reed485557f2014-10-12 10:36:47 -070068DEF_MTNAME(SkSurface)
fmalitab7425172014-08-26 07:56:44 -070069DEF_MTNAME(SkTextBlob)
mike@reedtribe.orge6469f12013-06-08 03:15:47 +000070DEF_MTNAME(SkTypeface)
Ben Wagnerc6c10b42017-08-07 09:56:21 -040071DEF_MTNAME(SkFontStyle)
reed@google.com74ce6f02013-05-22 15:13:18 +000072
Ben Wagnerc6c10b42017-08-07 09:56:21 -040073template <typename T, typename... Args> T* push_new(lua_State* L, Args&&... args) {
reed@google.com3597b732013-05-22 20:12:50 +000074 T* addr = (T*)lua_newuserdata(L, sizeof(T));
Ben Wagnerc6c10b42017-08-07 09:56:21 -040075 new (addr) T(std::forward<Args>(args)...);
reed@google.com3597b732013-05-22 20:12:50 +000076 luaL_getmetatable(L, get_mtname<T>());
77 lua_setmetatable(L, -2);
78 return addr;
79}
reed@google.com74ce6f02013-05-22 15:13:18 +000080
81template <typename T> void push_obj(lua_State* L, const T& obj) {
82 new (lua_newuserdata(L, sizeof(T))) T(obj);
reed@google.com3597b732013-05-22 20:12:50 +000083 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000084 lua_setmetatable(L, -2);
85}
86
Mike Reed5df49342016-11-12 08:06:55 -060087template <typename T> T* push_ptr(lua_State* L, T* ptr) {
88 *(T**)lua_newuserdata(L, sizeof(T*)) = ptr;
89 luaL_getmetatable(L, get_mtname<T>());
90 lua_setmetatable(L, -2);
91 return ptr;
92}
93
reed9fbc3f32014-10-21 07:12:58 -070094template <typename T> T* push_ref(lua_State* L, T* ref) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +000095 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
reed@google.com3597b732013-05-22 20:12:50 +000096 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000097 lua_setmetatable(L, -2);
reed9fbc3f32014-10-21 07:12:58 -070098 return ref;
reed@google.com74ce6f02013-05-22 15:13:18 +000099}
100
reed2ad1aa62016-03-09 09:50:50 -0800101template <typename T> void push_ref(lua_State* L, sk_sp<T> sp) {
102 *(T**)lua_newuserdata(L, sizeof(T*)) = sp.release();
103 luaL_getmetatable(L, get_mtname<T>());
104 lua_setmetatable(L, -2);
105}
106
reed@google.com74ce6f02013-05-22 15:13:18 +0000107template <typename T> T* get_ref(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +0000108 return *(T**)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +0000109}
110
111template <typename T> T* get_obj(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +0000112 return (T*)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +0000113}
114
reed@google.com88c9ec92013-05-22 15:43:21 +0000115static bool lua2bool(lua_State* L, int index) {
116 return !!lua_toboolean(L, index);
117}
118
reed@google.com74ce6f02013-05-22 15:13:18 +0000119///////////////////////////////////////////////////////////////////////////////
120
reed@google.com3597b732013-05-22 20:12:50 +0000121SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
122 fL = luaL_newstate();
123 luaL_openlibs(fL);
124 SkLua::Load(fL);
125}
126
127SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
128
129SkLua::~SkLua() {
130 if (fWeOwnL) {
131 if (fTermCode.size() > 0) {
132 lua_getglobal(fL, fTermCode.c_str());
133 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
134 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
135 }
136 }
137 lua_close(fL);
138 }
139}
140
141bool SkLua::runCode(const char code[]) {
142 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
143 if (err) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000144 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
reed@google.com3597b732013-05-22 20:12:50 +0000145 return false;
146 }
147 return true;
148}
149
150bool SkLua::runCode(const void* code, size_t size) {
151 SkString str((const char*)code, size);
152 return this->runCode(str.c_str());
153}
154
155///////////////////////////////////////////////////////////////////////////////
156
157#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
158
reed@google.com29563872013-07-10 21:23:49 +0000159static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
160 if (pred) {
161 lua_pushboolean(L, true);
162 lua_setfield(L, -2, key);
163 }
164}
165
reed@google.com74ce6f02013-05-22 15:13:18 +0000166static void setfield_string(lua_State* L, const char key[], const char value[]) {
167 lua_pushstring(L, value);
168 lua_setfield(L, -2, key);
169}
170
171static void setfield_number(lua_State* L, const char key[], double value) {
172 lua_pushnumber(L, value);
173 lua_setfield(L, -2, key);
174}
175
humper@google.com2815c192013-07-10 22:42:30 +0000176static void setfield_boolean(lua_State* L, const char key[], bool value) {
177 lua_pushboolean(L, value);
178 lua_setfield(L, -2, key);
179}
180
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000181static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
182 setfield_number(L, key, SkScalarToLua(value));
183}
184
reed@google.com3597b732013-05-22 20:12:50 +0000185static void setfield_function(lua_State* L,
186 const char key[], lua_CFunction value) {
187 lua_pushcfunction(L, value);
188 lua_setfield(L, -2, key);
reed@google.com74ce6f02013-05-22 15:13:18 +0000189}
190
reed7a72c672014-11-07 10:23:55 -0800191static int lua2int_def(lua_State* L, int index, int defaultValue) {
192 if (lua_isnumber(L, index)) {
193 return (int)lua_tonumber(L, index);
194 } else {
195 return defaultValue;
196 }
197}
198
199static SkScalar lua2scalar(lua_State* L, int index) {
200 SkASSERT(lua_isnumber(L, index));
201 return SkLuaToScalar(lua_tonumber(L, index));
202}
203
204static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
205 if (lua_isnumber(L, index)) {
206 return SkLuaToScalar(lua_tonumber(L, index));
207 } else {
208 return defaultValue;
209 }
210}
211
212static SkScalar getarray_scalar(lua_State* L, int stackIndex, int arrayIndex) {
213 SkASSERT(lua_istable(L, stackIndex));
214 lua_rawgeti(L, stackIndex, arrayIndex);
mtklein8aacf202014-12-18 13:29:54 -0800215
reed7a72c672014-11-07 10:23:55 -0800216 SkScalar value = lua2scalar(L, -1);
217 lua_pop(L, 1);
218 return value;
219}
220
221static void getarray_scalars(lua_State* L, int stackIndex, SkScalar dst[], int count) {
222 for (int i = 0; i < count; ++i) {
223 dst[i] = getarray_scalar(L, stackIndex, i + 1);
224 }
225}
226
227static void getarray_points(lua_State* L, int stackIndex, SkPoint pts[], int count) {
228 getarray_scalars(L, stackIndex, &pts[0].fX, count * 2);
229}
230
reed@google.come3823fd2013-05-30 18:55:14 +0000231static void setarray_number(lua_State* L, int index, double value) {
232 lua_pushnumber(L, value);
233 lua_rawseti(L, -2, index);
234}
235
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000236static void setarray_scalar(lua_State* L, int index, SkScalar value) {
237 setarray_number(L, index, SkScalarToLua(value));
238}
239
hstern0b401ce2016-08-02 09:17:59 -0700240static void setarray_string(lua_State* L, int index, const char str[]) {
241 lua_pushstring(L, str);
242 lua_rawseti(L, -2, index);
243}
244
reed@google.com74ce6f02013-05-22 15:13:18 +0000245void SkLua::pushBool(bool value, const char key[]) {
246 lua_pushboolean(fL, value);
247 CHECK_SETFIELD(key);
248}
249
250void SkLua::pushString(const char str[], const char key[]) {
251 lua_pushstring(fL, str);
252 CHECK_SETFIELD(key);
253}
254
reed@google.come3823fd2013-05-30 18:55:14 +0000255void SkLua::pushString(const char str[], size_t length, const char key[]) {
256 // TODO: how to do this w/o making a copy?
257 SkString s(str, length);
258 lua_pushstring(fL, s.c_str());
259 CHECK_SETFIELD(key);
260}
261
reed@google.com74ce6f02013-05-22 15:13:18 +0000262void SkLua::pushString(const SkString& str, const char key[]) {
263 lua_pushstring(fL, str.c_str());
264 CHECK_SETFIELD(key);
265}
266
267void SkLua::pushColor(SkColor color, const char key[]) {
268 lua_newtable(fL);
269 setfield_number(fL, "a", SkColorGetA(color) / 255.0);
270 setfield_number(fL, "r", SkColorGetR(color) / 255.0);
271 setfield_number(fL, "g", SkColorGetG(color) / 255.0);
272 setfield_number(fL, "b", SkColorGetB(color) / 255.0);
273 CHECK_SETFIELD(key);
274}
275
reed@google.come3823fd2013-05-30 18:55:14 +0000276void SkLua::pushU32(uint32_t value, const char key[]) {
277 lua_pushnumber(fL, (double)value);
278 CHECK_SETFIELD(key);
279}
280
reed@google.com74ce6f02013-05-22 15:13:18 +0000281void SkLua::pushScalar(SkScalar value, const char key[]) {
282 lua_pushnumber(fL, SkScalarToLua(value));
283 CHECK_SETFIELD(key);
284}
285
reed@google.come3823fd2013-05-30 18:55:14 +0000286void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
287 lua_newtable(fL);
288 for (int i = 0; i < count; ++i) {
289 // make it base-1 to match lua convention
290 setarray_number(fL, i + 1, (double)array[i]);
291 }
292 CHECK_SETFIELD(key);
293}
294
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000295void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
296 lua_newtable(fL);
297 for (int i = 0; i < count; ++i) {
298 // make it base-1 to match lua convention
299 lua_newtable(fL);
300 this->pushScalar(array[i].fX, "x");
301 this->pushScalar(array[i].fY, "y");
302 lua_rawseti(fL, -2, i + 1);
303 }
304 CHECK_SETFIELD(key);
305}
306
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000307void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
308 lua_newtable(fL);
309 for (int i = 0; i < count; ++i) {
310 // make it base-1 to match lua convention
311 setarray_scalar(fL, i + 1, array[i]);
312 }
313 CHECK_SETFIELD(key);
314}
315
reed@google.com74ce6f02013-05-22 15:13:18 +0000316void SkLua::pushRect(const SkRect& r, const char key[]) {
317 lua_newtable(fL);
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000318 setfield_scalar(fL, "left", r.fLeft);
319 setfield_scalar(fL, "top", r.fTop);
320 setfield_scalar(fL, "right", r.fRight);
321 setfield_scalar(fL, "bottom", r.fBottom);
reed@google.com74ce6f02013-05-22 15:13:18 +0000322 CHECK_SETFIELD(key);
323}
324
325void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
326 push_obj(fL, rr);
327 CHECK_SETFIELD(key);
328}
329
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000330void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
331 lua_newtable(fL);
332 setfield_scalar(fL, "phase", info.fPhase);
333 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
334 CHECK_SETFIELD(key);
335}
336
337
reed@google.com74ce6f02013-05-22 15:13:18 +0000338void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
339 push_obj(fL, matrix);
340 CHECK_SETFIELD(key);
341}
342
343void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
344 push_obj(fL, paint);
345 CHECK_SETFIELD(key);
346}
347
348void SkLua::pushPath(const SkPath& path, const char key[]) {
349 push_obj(fL, path);
350 CHECK_SETFIELD(key);
351}
352
353void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
Mike Reed5df49342016-11-12 08:06:55 -0600354 push_ptr(fL, canvas);
reed@google.com74ce6f02013-05-22 15:13:18 +0000355 CHECK_SETFIELD(key);
356}
357
fmalitab7425172014-08-26 07:56:44 -0700358void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
359 push_ref(fL, const_cast<SkTextBlob*>(blob));
360 CHECK_SETFIELD(key);
361}
362
reed@google.com74ce6f02013-05-22 15:13:18 +0000363///////////////////////////////////////////////////////////////////////////////
364///////////////////////////////////////////////////////////////////////////////
365
reed@google.com74ce6f02013-05-22 15:13:18 +0000366static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
367 SkASSERT(lua_istable(L, index));
368 lua_pushstring(L, key);
369 lua_gettable(L, index);
mtklein8aacf202014-12-18 13:29:54 -0800370
reed@google.com74ce6f02013-05-22 15:13:18 +0000371 SkScalar value = lua2scalar(L, -1);
372 lua_pop(L, 1);
373 return value;
374}
375
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000376static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
377 SkASSERT(lua_istable(L, index));
378 lua_pushstring(L, key);
379 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000380
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000381 SkScalar value;
382 if (lua_isnil(L, -1)) {
383 value = def;
384 } else {
385 value = lua2scalar(L, -1);
386 }
387 lua_pop(L, 1);
388 return value;
389}
390
reed468b1812014-10-19 11:42:54 -0700391static SkScalar byte2unit(U8CPU byte) {
392 return byte / 255.0f;
393}
394
reed@google.com74ce6f02013-05-22 15:13:18 +0000395static U8CPU unit2byte(SkScalar x) {
396 if (x <= 0) {
397 return 0;
398 } else if (x >= 1) {
399 return 255;
400 } else {
401 return SkScalarRoundToInt(x * 255);
402 }
403}
404
405static SkColor lua2color(lua_State* L, int index) {
reed485557f2014-10-12 10:36:47 -0700406 return SkColorSetARGB(unit2byte(getfield_scalar_default(L, index, "a", 1)),
407 unit2byte(getfield_scalar_default(L, index, "r", 0)),
408 unit2byte(getfield_scalar_default(L, index, "g", 0)),
409 unit2byte(getfield_scalar_default(L, index, "b", 0)));
reed@google.com74ce6f02013-05-22 15:13:18 +0000410}
411
412static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000413 rect->set(getfield_scalar_default(L, index, "left", 0),
414 getfield_scalar_default(L, index, "top", 0),
reed@google.com74ce6f02013-05-22 15:13:18 +0000415 getfield_scalar(L, index, "right"),
416 getfield_scalar(L, index, "bottom"));
417 return rect;
418}
419
reedf355df52014-10-12 12:18:40 -0700420static int lcanvas_clear(lua_State* L) {
421 get_ref<SkCanvas>(L, 1)->clear(0);
422 return 0;
423}
424
reed@google.com74ce6f02013-05-22 15:13:18 +0000425static int lcanvas_drawColor(lua_State* L) {
426 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
427 return 0;
428}
429
reed9fbc3f32014-10-21 07:12:58 -0700430static int lcanvas_drawPaint(lua_State* L) {
431 get_ref<SkCanvas>(L, 1)->drawPaint(*get_obj<SkPaint>(L, 2));
432 return 0;
433}
434
reed@google.com74ce6f02013-05-22 15:13:18 +0000435static int lcanvas_drawRect(lua_State* L) {
436 SkRect rect;
reed7a72c672014-11-07 10:23:55 -0800437 lua2rect(L, 2, &rect);
438 const SkPaint* paint = get_obj<SkPaint>(L, 3);
439 get_ref<SkCanvas>(L, 1)->drawRect(rect, *paint);
reed@google.com74ce6f02013-05-22 15:13:18 +0000440 return 0;
441}
442
443static int lcanvas_drawOval(lua_State* L) {
444 SkRect rect;
445 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
446 *get_obj<SkPaint>(L, 3));
447 return 0;
448}
449
450static int lcanvas_drawCircle(lua_State* L) {
451 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
452 lua2scalar(L, 3),
453 lua2scalar(L, 4),
454 *get_obj<SkPaint>(L, 5));
455 return 0;
456}
457
reed485557f2014-10-12 10:36:47 -0700458static SkPaint* lua2OptionalPaint(lua_State* L, int index, SkPaint* paint) {
459 if (lua_isnumber(L, index)) {
460 paint->setAlpha(SkScalarRoundToInt(lua2scalar(L, index) * 255));
461 return paint;
reedf355df52014-10-12 12:18:40 -0700462 } else if (lua_isuserdata(L, index)) {
reed485557f2014-10-12 10:36:47 -0700463 const SkPaint* ptr = get_obj<SkPaint>(L, index);
464 if (ptr) {
465 *paint = *ptr;
466 return paint;
467 }
468 }
halcanary96fcdcc2015-08-27 07:41:13 -0700469 return nullptr;
reed485557f2014-10-12 10:36:47 -0700470}
471
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000472static int lcanvas_drawImage(lua_State* L) {
473 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
474 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700475 if (nullptr == image) {
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000476 return 0;
477 }
478 SkScalar x = lua2scalar(L, 3);
479 SkScalar y = lua2scalar(L, 4);
480
481 SkPaint paint;
reed485557f2014-10-12 10:36:47 -0700482 canvas->drawImage(image, x, y, lua2OptionalPaint(L, 5, &paint));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000483 return 0;
484}
485
reedba5fb932014-10-10 15:28:19 -0700486static int lcanvas_drawImageRect(lua_State* L) {
487 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
488 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700489 if (nullptr == image) {
reedba5fb932014-10-10 15:28:19 -0700490 return 0;
491 }
492
493 SkRect srcR, dstR;
halcanary96fcdcc2015-08-27 07:41:13 -0700494 SkRect* srcRPtr = nullptr;
reedba5fb932014-10-10 15:28:19 -0700495 if (!lua_isnil(L, 3)) {
496 srcRPtr = lua2rect(L, 3, &srcR);
497 }
498 lua2rect(L, 4, &dstR);
mtklein8aacf202014-12-18 13:29:54 -0800499
reedba5fb932014-10-10 15:28:19 -0700500 SkPaint paint;
reede47829b2015-08-06 10:02:53 -0700501 canvas->legacy_drawImageRect(image, srcRPtr, dstR, lua2OptionalPaint(L, 5, &paint));
reedba5fb932014-10-10 15:28:19 -0700502 return 0;
503}
504
reed7a72c672014-11-07 10:23:55 -0800505static int lcanvas_drawPatch(lua_State* L) {
506 SkPoint cubics[12];
507 SkColor colorStorage[4];
508 SkPoint texStorage[4];
509
halcanary96fcdcc2015-08-27 07:41:13 -0700510 const SkColor* colors = nullptr;
511 const SkPoint* texs = nullptr;
reed7a72c672014-11-07 10:23:55 -0800512
513 getarray_points(L, 2, cubics, 12);
514
515 colorStorage[0] = SK_ColorRED;
516 colorStorage[1] = SK_ColorGREEN;
517 colorStorage[2] = SK_ColorBLUE;
518 colorStorage[3] = SK_ColorGRAY;
519
520 if (lua_isnil(L, 4)) {
521 colors = colorStorage;
522 } else {
523 getarray_points(L, 4, texStorage, 4);
524 texs = texStorage;
525 }
526
Mike Reed7d954ad2016-10-28 15:42:34 -0400527 get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, *get_obj<SkPaint>(L, 5));
reed7a72c672014-11-07 10:23:55 -0800528 return 0;
529}
530
reed@google.comfd345872013-05-22 20:53:42 +0000531static int lcanvas_drawPath(lua_State* L) {
532 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
533 *get_obj<SkPaint>(L, 3));
534 return 0;
535}
536
reed96affcd2014-10-13 12:38:04 -0700537// drawPicture(pic, x, y, paint)
538static int lcanvas_drawPicture(lua_State* L) {
539 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
540 SkPicture* picture = get_ref<SkPicture>(L, 2);
541 SkScalar x = lua2scalar_def(L, 3, 0);
542 SkScalar y = lua2scalar_def(L, 4, 0);
halcanary96fcdcc2015-08-27 07:41:13 -0700543 SkMatrix matrix, *matrixPtr = nullptr;
reed96affcd2014-10-13 12:38:04 -0700544 if (x || y) {
545 matrix.setTranslate(x, y);
546 matrixPtr = &matrix;
547 }
548 SkPaint paint;
549 canvas->drawPicture(picture, matrixPtr, lua2OptionalPaint(L, 5, &paint));
550 return 0;
551}
552
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000553static int lcanvas_drawText(lua_State* L) {
554 if (lua_gettop(L) < 5) {
555 return 0;
556 }
557
558 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
559 size_t len;
560 const char* text = lua_tolstring(L, 2, &len);
561 get_ref<SkCanvas>(L, 1)->drawText(text, len,
562 lua2scalar(L, 3), lua2scalar(L, 4),
563 *get_obj<SkPaint>(L, 5));
564 }
565 return 0;
566}
567
reed1b6ab442014-11-03 19:55:41 -0800568static int lcanvas_drawTextBlob(lua_State* L) {
569 const SkTextBlob* blob = get_ref<SkTextBlob>(L, 2);
570 SkScalar x = lua2scalar(L, 3);
571 SkScalar y = lua2scalar(L, 4);
572 const SkPaint& paint = *get_obj<SkPaint>(L, 5);
573 get_ref<SkCanvas>(L, 1)->drawTextBlob(blob, x, y, paint);
574 return 0;
575}
576
reed@google.com74ce6f02013-05-22 15:13:18 +0000577static int lcanvas_getSaveCount(lua_State* L) {
578 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
579 return 1;
580}
581
582static int lcanvas_getTotalMatrix(lua_State* L) {
583 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
584 return 1;
585}
586
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000587static int lcanvas_save(lua_State* L) {
588 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
589 return 1;
590}
591
reed86217d82014-10-25 20:44:40 -0700592static int lcanvas_saveLayer(lua_State* L) {
593 SkPaint paint;
halcanary96fcdcc2015-08-27 07:41:13 -0700594 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->saveLayer(nullptr, lua2OptionalPaint(L, 2, &paint)));
reed86217d82014-10-25 20:44:40 -0700595 return 1;
596}
597
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000598static int lcanvas_restore(lua_State* L) {
599 get_ref<SkCanvas>(L, 1)->restore();
600 return 0;
601}
602
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000603static int lcanvas_scale(lua_State* L) {
604 SkScalar sx = lua2scalar_def(L, 2, 1);
605 SkScalar sy = lua2scalar_def(L, 3, sx);
606 get_ref<SkCanvas>(L, 1)->scale(sx, sy);
607 return 0;
608}
609
reed@google.com3597b732013-05-22 20:12:50 +0000610static int lcanvas_translate(lua_State* L) {
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000611 SkScalar tx = lua2scalar_def(L, 2, 0);
612 SkScalar ty = lua2scalar_def(L, 3, 0);
613 get_ref<SkCanvas>(L, 1)->translate(tx, ty);
614 return 0;
615}
616
617static int lcanvas_rotate(lua_State* L) {
618 SkScalar degrees = lua2scalar_def(L, 2, 0);
619 get_ref<SkCanvas>(L, 1)->rotate(degrees);
reed@google.com3597b732013-05-22 20:12:50 +0000620 return 0;
621}
622
reedbdc49ae2014-10-14 09:34:52 -0700623static int lcanvas_concat(lua_State* L) {
624 get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2));
625 return 0;
626}
627
reed485557f2014-10-12 10:36:47 -0700628static int lcanvas_newSurface(lua_State* L) {
629 int width = lua2int_def(L, 2, 0);
reed7a72c672014-11-07 10:23:55 -0800630 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -0700631 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -0700632 auto surface = get_ref<SkCanvas>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -0700633 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -0700634 lua_pushnil(L);
635 } else {
reede8f30622016-03-23 18:59:25 -0700636 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -0700637 }
638 return 1;
639}
640
reed@google.com74ce6f02013-05-22 15:13:18 +0000641static int lcanvas_gc(lua_State* L) {
Mike Reed5df49342016-11-12 08:06:55 -0600642 // don't know how to track a ptr...
reed@google.com74ce6f02013-05-22 15:13:18 +0000643 return 0;
644}
645
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000646const struct luaL_Reg gSkCanvas_Methods[] = {
reedf355df52014-10-12 12:18:40 -0700647 { "clear", lcanvas_clear },
reed@google.com74ce6f02013-05-22 15:13:18 +0000648 { "drawColor", lcanvas_drawColor },
reed9fbc3f32014-10-21 07:12:58 -0700649 { "drawPaint", lcanvas_drawPaint },
reed@google.com74ce6f02013-05-22 15:13:18 +0000650 { "drawRect", lcanvas_drawRect },
651 { "drawOval", lcanvas_drawOval },
652 { "drawCircle", lcanvas_drawCircle },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000653 { "drawImage", lcanvas_drawImage },
reedba5fb932014-10-10 15:28:19 -0700654 { "drawImageRect", lcanvas_drawImageRect },
reed7a72c672014-11-07 10:23:55 -0800655 { "drawPatch", lcanvas_drawPatch },
reed@google.comfd345872013-05-22 20:53:42 +0000656 { "drawPath", lcanvas_drawPath },
reed96affcd2014-10-13 12:38:04 -0700657 { "drawPicture", lcanvas_drawPicture },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000658 { "drawText", lcanvas_drawText },
reed1b6ab442014-11-03 19:55:41 -0800659 { "drawTextBlob", lcanvas_drawTextBlob },
reed@google.com74ce6f02013-05-22 15:13:18 +0000660 { "getSaveCount", lcanvas_getSaveCount },
661 { "getTotalMatrix", lcanvas_getTotalMatrix },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000662 { "save", lcanvas_save },
reed86217d82014-10-25 20:44:40 -0700663 { "saveLayer", lcanvas_saveLayer },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000664 { "restore", lcanvas_restore },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000665 { "scale", lcanvas_scale },
reed@google.com3597b732013-05-22 20:12:50 +0000666 { "translate", lcanvas_translate },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000667 { "rotate", lcanvas_rotate },
reedbdc49ae2014-10-14 09:34:52 -0700668 { "concat", lcanvas_concat },
reed485557f2014-10-12 10:36:47 -0700669
670 { "newSurface", lcanvas_newSurface },
671
reed@google.com74ce6f02013-05-22 15:13:18 +0000672 { "__gc", lcanvas_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700673 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +0000674};
675
676///////////////////////////////////////////////////////////////////////////////
677
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000678static int ldocument_beginPage(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -0700679 const SkRect* contentPtr = nullptr;
Mike Reed7ff6ca52018-01-08 14:45:31 -0500680 push_ptr(L, get_obj<DocHolder>(L, 1)->fDoc->beginPage(lua2scalar(L, 2),
681 lua2scalar(L, 3),
682 contentPtr));
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000683 return 1;
684}
685
686static int ldocument_endPage(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500687 get_obj<DocHolder>(L, 1)->fDoc->endPage();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000688 return 0;
689}
690
691static int ldocument_close(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500692 get_obj<DocHolder>(L, 1)->fDoc->close();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000693 return 0;
694}
695
696static int ldocument_gc(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500697 get_obj<DocHolder>(L, 1)->~DocHolder();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000698 return 0;
699}
700
Mike Reed7ff6ca52018-01-08 14:45:31 -0500701static const struct luaL_Reg gDocHolder_Methods[] = {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000702 { "beginPage", ldocument_beginPage },
703 { "endPage", ldocument_endPage },
704 { "close", ldocument_close },
705 { "__gc", ldocument_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700706 { nullptr, nullptr }
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000707};
708
709///////////////////////////////////////////////////////////////////////////////
710
reed@google.com74ce6f02013-05-22 15:13:18 +0000711static int lpaint_isAntiAlias(lua_State* L) {
712 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
713 return 1;
714}
715
716static int lpaint_setAntiAlias(lua_State* L) {
reed@google.com88c9ec92013-05-22 15:43:21 +0000717 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +0000718 return 0;
719}
720
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000721static int lpaint_isDither(lua_State* L) {
722 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
723 return 1;
724}
725
reedbb8a0ab2014-11-03 22:32:07 -0800726static int lpaint_setDither(lua_State* L) {
727 get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2));
728 return 0;
729}
730
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000731static int lpaint_isFakeBoldText(lua_State* L) {
732 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
733 return 1;
734}
735
736static int lpaint_isLinearText(lua_State* L) {
737 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
738 return 1;
739}
740
741static int lpaint_isSubpixelText(lua_State* L) {
742 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
743 return 1;
744}
745
reed09a1d672014-10-11 13:13:11 -0700746static int lpaint_setSubpixelText(lua_State* L) {
747 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
748 return 1;
749}
750
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000751static int lpaint_isDevKernText(lua_State* L) {
752 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
753 return 1;
754}
755
756static int lpaint_isLCDRenderText(lua_State* L) {
757 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
758 return 1;
759}
760
reed36c9c112014-11-04 10:58:42 -0800761static int lpaint_setLCDRenderText(lua_State* L) {
762 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2));
763 return 1;
764}
765
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000766static int lpaint_isEmbeddedBitmapText(lua_State* L) {
767 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
768 return 1;
769}
770
771static int lpaint_isAutohinted(lua_State* L) {
772 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
773 return 1;
774}
775
776static int lpaint_isVerticalText(lua_State* L) {
777 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
778 return 1;
779}
780
reed468b1812014-10-19 11:42:54 -0700781static int lpaint_getAlpha(lua_State* L) {
782 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha()));
783 return 1;
784}
785
786static int lpaint_setAlpha(lua_State* L) {
787 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2)));
788 return 0;
789}
790
reed@google.com74ce6f02013-05-22 15:13:18 +0000791static int lpaint_getColor(lua_State* L) {
792 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
793 return 1;
794}
795
796static int lpaint_setColor(lua_State* L) {
797 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
798 return 0;
799}
800
reed@google.come3823fd2013-05-30 18:55:14 +0000801static int lpaint_getTextSize(lua_State* L) {
802 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
803 return 1;
804}
805
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000806static int lpaint_getTextScaleX(lua_State* L) {
807 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
808 return 1;
809}
810
811static int lpaint_getTextSkewX(lua_State* L) {
812 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
813 return 1;
814}
815
reed@google.come3823fd2013-05-30 18:55:14 +0000816static int lpaint_setTextSize(lua_State* L) {
817 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
818 return 0;
819}
820
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000821static int lpaint_getTypeface(lua_State* L) {
822 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
823 return 1;
824}
825
826static int lpaint_setTypeface(lua_State* L) {
bungeman13b9c952016-05-12 10:09:30 -0700827 get_obj<SkPaint>(L, 1)->setTypeface(sk_ref_sp(get_ref<SkTypeface>(L, 2)));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000828 return 0;
829}
830
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000831static int lpaint_getHinting(lua_State* L) {
832 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
833 return 1;
834}
835
reed93a12152015-03-16 10:08:34 -0700836static int lpaint_getFilterQuality(lua_State* L) {
837 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality());
reed7a72c672014-11-07 10:23:55 -0800838 return 1;
839}
840
reed93a12152015-03-16 10:08:34 -0700841static int lpaint_setFilterQuality(lua_State* L) {
reed7a72c672014-11-07 10:23:55 -0800842 int level = lua2int_def(L, 2, -1);
843 if (level >= 0 && level <= 3) {
reed93a12152015-03-16 10:08:34 -0700844 get_obj<SkPaint>(L, 1)->setFilterQuality((SkFilterQuality)level);
reed7a72c672014-11-07 10:23:55 -0800845 }
846 return 0;
847}
848
reed@google.come3823fd2013-05-30 18:55:14 +0000849static int lpaint_getFontID(lua_State* L) {
850 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
851 SkLua(L).pushU32(SkTypeface::UniqueID(face));
852 return 1;
853}
854
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000855static const struct {
856 const char* fLabel;
857 SkPaint::Align fAlign;
858} gAlignRec[] = {
859 { "left", SkPaint::kLeft_Align },
860 { "center", SkPaint::kCenter_Align },
861 { "right", SkPaint::kRight_Align },
862};
863
864static int lpaint_getTextAlign(lua_State* L) {
865 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
866 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
867 if (gAlignRec[i].fAlign == align) {
868 lua_pushstring(L, gAlignRec[i].fLabel);
869 return 1;
870 }
871 }
872 return 0;
873}
874
875static int lpaint_setTextAlign(lua_State* L) {
876 if (lua_isstring(L, 2)) {
877 size_t len;
878 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000879
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000880 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
881 if (!strcmp(gAlignRec[i].fLabel, label)) {
882 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
883 break;
884 }
885 }
886 }
887 return 0;
888}
889
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000890static int lpaint_getStroke(lua_State* L) {
891 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
892 return 1;
893}
894
895static int lpaint_setStroke(lua_State* L) {
896 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000897
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000898 if (lua_toboolean(L, 2)) {
899 style = SkPaint::kStroke_Style;
900 } else {
901 style = SkPaint::kFill_Style;
902 }
903 get_obj<SkPaint>(L, 1)->setStyle(style);
904 return 0;
905}
906
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000907static int lpaint_getStrokeCap(lua_State* L) {
908 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
909 return 1;
910}
911
912static int lpaint_getStrokeJoin(lua_State* L) {
913 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
914 return 1;
915}
916
917static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +0000918 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000919 return 1;
920}
921
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000922static int lpaint_getStrokeWidth(lua_State* L) {
923 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
924 return 1;
925}
926
927static int lpaint_setStrokeWidth(lua_State* L) {
928 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
929 return 0;
930}
931
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000932static int lpaint_getStrokeMiter(lua_State* L) {
933 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
934 return 1;
935}
936
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000937static int lpaint_measureText(lua_State* L) {
938 if (lua_isstring(L, 2)) {
939 size_t len;
940 const char* text = lua_tolstring(L, 2, &len);
941 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
942 return 1;
943 }
944 return 0;
945}
946
947struct FontMetrics {
948 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
949 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
950 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
951 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
952 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
953 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
954 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
955 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
956 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
957};
958
959static int lpaint_getFontMetrics(lua_State* L) {
960 SkPaint::FontMetrics fm;
961 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000962
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000963 lua_newtable(L);
964 setfield_scalar(L, "top", fm.fTop);
965 setfield_scalar(L, "ascent", fm.fAscent);
966 setfield_scalar(L, "descent", fm.fDescent);
967 setfield_scalar(L, "bottom", fm.fBottom);
968 setfield_scalar(L, "leading", fm.fLeading);
969 SkLua(L).pushScalar(height);
970 return 2;
971}
972
reed@google.com29563872013-07-10 21:23:49 +0000973static int lpaint_getEffects(lua_State* L) {
974 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000975
reed@google.com29563872013-07-10 21:23:49 +0000976 lua_newtable(L);
reed468b1812014-10-19 11:42:54 -0700977 setfield_bool_if(L, "looper", !!paint->getLooper());
978 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
reed468b1812014-10-19 11:42:54 -0700979 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
980 setfield_bool_if(L, "shader", !!paint->getShader());
reed@google.com29563872013-07-10 21:23:49 +0000981 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
982 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
reed@google.com29563872013-07-10 21:23:49 +0000983 return 1;
984}
985
reed22a517f2015-12-04 20:45:59 -0800986static int lpaint_getColorFilter(lua_State* L) {
987 const SkPaint* paint = get_obj<SkPaint>(L, 1);
988 SkColorFilter* cf = paint->getColorFilter();
989 if (cf) {
990 push_ref(L, cf);
991 return 1;
992 }
993 return 0;
994}
995
996static int lpaint_setColorFilter(lua_State* L) {
997 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedd053ce92016-03-22 10:17:23 -0700998 paint->setColorFilter(sk_ref_sp(get_ref<SkColorFilter>(L, 2)));
reed22a517f2015-12-04 20:45:59 -0800999 return 0;
1000}
1001
reed468b1812014-10-19 11:42:54 -07001002static int lpaint_getImageFilter(lua_State* L) {
1003 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1004 SkImageFilter* imf = paint->getImageFilter();
1005 if (imf) {
1006 push_ref(L, imf);
1007 return 1;
1008 }
1009 return 0;
1010}
1011
1012static int lpaint_setImageFilter(lua_State* L) {
1013 SkPaint* paint = get_obj<SkPaint>(L, 1);
Mike Reed5e257172016-11-01 11:22:05 -04001014 paint->setImageFilter(sk_ref_sp(get_ref<SkImageFilter>(L, 2)));
reed468b1812014-10-19 11:42:54 -07001015 return 0;
1016}
1017
reed@google.com5fdc9832013-07-24 15:47:52 +00001018static int lpaint_getShader(lua_State* L) {
1019 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1020 SkShader* shader = paint->getShader();
1021 if (shader) {
1022 push_ref(L, shader);
1023 return 1;
1024 }
1025 return 0;
1026}
1027
reed9fbc3f32014-10-21 07:12:58 -07001028static int lpaint_setShader(lua_State* L) {
1029 SkPaint* paint = get_obj<SkPaint>(L, 1);
reedfe630452016-03-25 09:08:00 -07001030 paint->setShader(sk_ref_sp(get_ref<SkShader>(L, 2)));
reed9fbc3f32014-10-21 07:12:58 -07001031 return 0;
1032}
1033
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001034static int lpaint_getPathEffect(lua_State* L) {
1035 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1036 SkPathEffect* pe = paint->getPathEffect();
1037 if (pe) {
1038 push_ref(L, pe);
1039 return 1;
1040 }
1041 return 0;
1042}
1043
hstern0b401ce2016-08-02 09:17:59 -07001044static int lpaint_getFillPath(lua_State* L) {
1045 const SkPaint* paint = get_obj<SkPaint>(L, 1);
1046 const SkPath* path = get_obj<SkPath>(L, 2);
1047
1048 SkPath fillpath;
1049 paint->getFillPath(*path, &fillpath);
1050
1051 SkLua lua(L);
1052 lua.pushPath(fillpath);
1053
1054 return 1;
1055}
1056
reed@google.com74ce6f02013-05-22 15:13:18 +00001057static int lpaint_gc(lua_State* L) {
1058 get_obj<SkPaint>(L, 1)->~SkPaint();
1059 return 0;
1060}
1061
1062static const struct luaL_Reg gSkPaint_Methods[] = {
1063 { "isAntiAlias", lpaint_isAntiAlias },
1064 { "setAntiAlias", lpaint_setAntiAlias },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001065 { "isDither", lpaint_isDither },
reedbb8a0ab2014-11-03 22:32:07 -08001066 { "setDither", lpaint_setDither },
reed93a12152015-03-16 10:08:34 -07001067 { "getFilterQuality", lpaint_getFilterQuality },
1068 { "setFilterQuality", lpaint_setFilterQuality },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001069 { "isFakeBoldText", lpaint_isFakeBoldText },
1070 { "isLinearText", lpaint_isLinearText },
1071 { "isSubpixelText", lpaint_isSubpixelText },
reed09a1d672014-10-11 13:13:11 -07001072 { "setSubpixelText", lpaint_setSubpixelText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001073 { "isDevKernText", lpaint_isDevKernText },
1074 { "isLCDRenderText", lpaint_isLCDRenderText },
reed36c9c112014-11-04 10:58:42 -08001075 { "setLCDRenderText", lpaint_setLCDRenderText },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001076 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
1077 { "isAutohinted", lpaint_isAutohinted },
1078 { "isVerticalText", lpaint_isVerticalText },
reed468b1812014-10-19 11:42:54 -07001079 { "getAlpha", lpaint_getAlpha },
1080 { "setAlpha", lpaint_setAlpha },
reed@google.com74ce6f02013-05-22 15:13:18 +00001081 { "getColor", lpaint_getColor },
1082 { "setColor", lpaint_setColor },
reed@google.come3823fd2013-05-30 18:55:14 +00001083 { "getTextSize", lpaint_getTextSize },
1084 { "setTextSize", lpaint_setTextSize },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001085 { "getTextScaleX", lpaint_getTextScaleX },
1086 { "getTextSkewX", lpaint_getTextSkewX },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001087 { "getTypeface", lpaint_getTypeface },
1088 { "setTypeface", lpaint_setTypeface },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001089 { "getHinting", lpaint_getHinting },
reed@google.come3823fd2013-05-30 18:55:14 +00001090 { "getFontID", lpaint_getFontID },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001091 { "getTextAlign", lpaint_getTextAlign },
1092 { "setTextAlign", lpaint_setTextAlign },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001093 { "getStroke", lpaint_getStroke },
1094 { "setStroke", lpaint_setStroke },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001095 { "getStrokeCap", lpaint_getStrokeCap },
1096 { "getStrokeJoin", lpaint_getStrokeJoin },
1097 { "getTextEncoding", lpaint_getTextEncoding },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001098 { "getStrokeWidth", lpaint_getStrokeWidth },
1099 { "setStrokeWidth", lpaint_setStrokeWidth },
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +00001100 { "getStrokeMiter", lpaint_getStrokeMiter },
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +00001101 { "measureText", lpaint_measureText },
1102 { "getFontMetrics", lpaint_getFontMetrics },
reed@google.com29563872013-07-10 21:23:49 +00001103 { "getEffects", lpaint_getEffects },
reed22a517f2015-12-04 20:45:59 -08001104 { "getColorFilter", lpaint_getColorFilter },
1105 { "setColorFilter", lpaint_setColorFilter },
reed468b1812014-10-19 11:42:54 -07001106 { "getImageFilter", lpaint_getImageFilter },
1107 { "setImageFilter", lpaint_setImageFilter },
reed@google.com5fdc9832013-07-24 15:47:52 +00001108 { "getShader", lpaint_getShader },
reed9fbc3f32014-10-21 07:12:58 -07001109 { "setShader", lpaint_setShader },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001110 { "getPathEffect", lpaint_getPathEffect },
hstern0b401ce2016-08-02 09:17:59 -07001111 { "getFillPath", lpaint_getFillPath },
reed@google.com74ce6f02013-05-22 15:13:18 +00001112 { "__gc", lpaint_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001113 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001114};
1115
1116///////////////////////////////////////////////////////////////////////////////
1117
reed@google.com5fdc9832013-07-24 15:47:52 +00001118static const char* mode2string(SkShader::TileMode mode) {
1119 static const char* gNames[] = { "clamp", "repeat", "mirror" };
1120 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames));
1121 return gNames[mode];
1122}
1123
1124static const char* gradtype2string(SkShader::GradientType t) {
1125 static const char* gNames[] = {
1126 "none", "color", "linear", "radial", "radial2", "sweep", "conical"
1127 };
1128 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames));
1129 return gNames[t];
1130}
1131
1132static int lshader_isOpaque(lua_State* L) {
1133 SkShader* shader = get_ref<SkShader>(L, 1);
1134 return shader && shader->isOpaque();
1135}
1136
Mike Reed627778d2016-09-28 17:13:38 -04001137static int lshader_isAImage(lua_State* L) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001138 SkShader* shader = get_ref<SkShader>(L, 1);
1139 if (shader) {
reed@google.com5fdc9832013-07-24 15:47:52 +00001140 SkMatrix matrix;
1141 SkShader::TileMode modes[2];
Mike Reed627778d2016-09-28 17:13:38 -04001142 if (SkImage* image = shader->isAImage(&matrix, modes)) {
reedf5822822015-08-19 11:46:38 -07001143 lua_newtable(L);
Mike Reed627778d2016-09-28 17:13:38 -04001144 setfield_number(L, "id", image->uniqueID());
1145 setfield_number(L, "width", image->width());
1146 setfield_number(L, "height", image->height());
reedf5822822015-08-19 11:46:38 -07001147 setfield_string(L, "tileX", mode2string(modes[0]));
1148 setfield_string(L, "tileY", mode2string(modes[1]));
1149 return 1;
reed@google.com5fdc9832013-07-24 15:47:52 +00001150 }
1151 }
1152 return 0;
1153}
1154
1155static int lshader_asAGradient(lua_State* L) {
1156 SkShader* shader = get_ref<SkShader>(L, 1);
1157 if (shader) {
1158 SkShader::GradientInfo info;
1159 sk_bzero(&info, sizeof(info));
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001160
reed@google.com5fdc9832013-07-24 15:47:52 +00001161 SkShader::GradientType t = shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001162
reed@google.com5fdc9832013-07-24 15:47:52 +00001163 if (SkShader::kNone_GradientType != t) {
fmenozzib4f254e2016-06-28 14:03:03 -07001164 SkAutoTArray<SkScalar> pos(info.fColorCount);
1165 info.fColorOffsets = pos.get();
1166 shader->asAGradient(&info);
commit-bot@chromium.org74f96b92013-08-01 17:32:56 +00001167
fmenozzib4f254e2016-06-28 14:03:03 -07001168 lua_newtable(L);
fmenozzi7f2c85e2016-07-12 09:17:39 -07001169 setfield_string(L, "type", gradtype2string(t));
1170 setfield_string(L, "tile", mode2string(info.fTileMode));
1171 setfield_number(L, "colorCount", info.fColorCount);
fmenozzib4f254e2016-06-28 14:03:03 -07001172
1173 lua_newtable(L);
1174 for (int i = 0; i < info.fColorCount; i++) {
1175 // Lua uses 1-based indexing
1176 setarray_scalar(L, i+1, pos[i]);
1177 }
1178 lua_setfield(L, -2, "positions");
1179
reed@google.com5fdc9832013-07-24 15:47:52 +00001180 return 1;
1181 }
1182 }
1183 return 0;
1184}
1185
1186static int lshader_gc(lua_State* L) {
1187 get_ref<SkShader>(L, 1)->unref();
1188 return 0;
1189}
1190
1191static const struct luaL_Reg gSkShader_Methods[] = {
1192 { "isOpaque", lshader_isOpaque },
Mike Reed627778d2016-09-28 17:13:38 -04001193 { "isAImage", lshader_isAImage },
reed@google.com5fdc9832013-07-24 15:47:52 +00001194 { "asAGradient", lshader_asAGradient },
1195 { "__gc", lshader_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001196 { nullptr, nullptr }
reed@google.com5fdc9832013-07-24 15:47:52 +00001197};
1198
1199///////////////////////////////////////////////////////////////////////////////
1200
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001201static int lpatheffect_asADash(lua_State* L) {
1202 SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
1203 if (pe) {
1204 SkPathEffect::DashInfo info;
1205 SkPathEffect::DashType dashType = pe->asADash(&info);
1206 if (SkPathEffect::kDash_DashType == dashType) {
1207 SkAutoTArray<SkScalar> intervals(info.fCount);
1208 info.fIntervals = intervals.get();
1209 pe->asADash(&info);
1210 SkLua(L).pushDash(info);
1211 return 1;
1212 }
1213 }
1214 return 0;
1215}
1216
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001217static int lpatheffect_gc(lua_State* L) {
1218 get_ref<SkPathEffect>(L, 1)->unref();
1219 return 0;
1220}
1221
1222static const struct luaL_Reg gSkPathEffect_Methods[] = {
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +00001223 { "asADash", lpatheffect_asADash },
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001224 { "__gc", lpatheffect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001225 { nullptr, nullptr }
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00001226};
1227
1228///////////////////////////////////////////////////////////////////////////////
1229
reed22a517f2015-12-04 20:45:59 -08001230static int lpcolorfilter_gc(lua_State* L) {
1231 get_ref<SkColorFilter>(L, 1)->unref();
1232 return 0;
1233}
1234
1235static const struct luaL_Reg gSkColorFilter_Methods[] = {
1236 { "__gc", lpcolorfilter_gc },
1237 { nullptr, nullptr }
1238};
1239
1240///////////////////////////////////////////////////////////////////////////////
1241
reed468b1812014-10-19 11:42:54 -07001242static int lpimagefilter_gc(lua_State* L) {
1243 get_ref<SkImageFilter>(L, 1)->unref();
1244 return 0;
1245}
1246
1247static const struct luaL_Reg gSkImageFilter_Methods[] = {
1248 { "__gc", lpimagefilter_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001249 { nullptr, nullptr }
reed468b1812014-10-19 11:42:54 -07001250};
1251
1252///////////////////////////////////////////////////////////////////////////////
1253
humper@google.com2815c192013-07-10 22:42:30 +00001254static int lmatrix_getType(lua_State* L) {
1255 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +00001256
humper@google.com2815c192013-07-10 22:42:30 +00001257 lua_newtable(L);
1258 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask));
1259 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask));
1260 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask));
1261 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask));
1262 return 1;
1263}
1264
humper@google.com0f48ee02013-07-26 15:23:43 +00001265static int lmatrix_getScaleX(lua_State* L) {
1266 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX());
1267 return 1;
1268}
1269
1270static int lmatrix_getScaleY(lua_State* L) {
1271 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY());
1272 return 1;
1273}
1274
1275static int lmatrix_getTranslateX(lua_State* L) {
1276 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX());
1277 return 1;
1278}
1279
1280static int lmatrix_getTranslateY(lua_State* L) {
1281 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY());
1282 return 1;
1283}
1284
reed7a72c672014-11-07 10:23:55 -08001285static int lmatrix_invert(lua_State* L) {
1286 lua_pushboolean(L, get_obj<SkMatrix>(L, 1)->invert(get_obj<SkMatrix>(L, 2)));
1287 return 1;
1288}
1289
1290static int lmatrix_mapXY(lua_State* L) {
1291 SkPoint pt = { lua2scalar(L, 2), lua2scalar(L, 3) };
1292 get_obj<SkMatrix>(L, 1)->mapPoints(&pt, &pt, 1);
1293 lua_pushnumber(L, pt.x());
1294 lua_pushnumber(L, pt.y());
1295 return 2;
1296}
1297
reedbdc49ae2014-10-14 09:34:52 -07001298static int lmatrix_setRectToRect(lua_State* L) {
1299 SkMatrix* matrix = get_obj<SkMatrix>(L, 1);
1300 SkRect srcR, dstR;
1301 lua2rect(L, 2, &srcR);
1302 lua2rect(L, 3, &dstR);
1303 const char* scaleToFitStr = lua_tostring(L, 4);
1304 SkMatrix::ScaleToFit scaleToFit = SkMatrix::kFill_ScaleToFit;
1305
1306 if (scaleToFitStr) {
1307 const struct {
1308 const char* fName;
1309 SkMatrix::ScaleToFit fScaleToFit;
1310 } rec[] = {
1311 { "fill", SkMatrix::kFill_ScaleToFit },
1312 { "start", SkMatrix::kStart_ScaleToFit },
1313 { "center", SkMatrix::kCenter_ScaleToFit },
1314 { "end", SkMatrix::kEnd_ScaleToFit },
1315 };
1316
1317 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
1318 if (strcmp(rec[i].fName, scaleToFitStr) == 0) {
1319 scaleToFit = rec[i].fScaleToFit;
1320 break;
1321 }
1322 }
1323 }
1324
1325 matrix->setRectToRect(srcR, dstR, scaleToFit);
1326 return 0;
1327}
1328
humper@google.com2815c192013-07-10 22:42:30 +00001329static const struct luaL_Reg gSkMatrix_Methods[] = {
1330 { "getType", lmatrix_getType },
humper@google.com0f48ee02013-07-26 15:23:43 +00001331 { "getScaleX", lmatrix_getScaleX },
1332 { "getScaleY", lmatrix_getScaleY },
1333 { "getTranslateX", lmatrix_getTranslateX },
1334 { "getTranslateY", lmatrix_getTranslateY },
reedbdc49ae2014-10-14 09:34:52 -07001335 { "setRectToRect", lmatrix_setRectToRect },
reed7a72c672014-11-07 10:23:55 -08001336 { "invert", lmatrix_invert },
1337 { "mapXY", lmatrix_mapXY },
halcanary96fcdcc2015-08-27 07:41:13 -07001338 { nullptr, nullptr }
humper@google.com2815c192013-07-10 22:42:30 +00001339};
1340
1341///////////////////////////////////////////////////////////////////////////////
1342
reed@google.com74ce6f02013-05-22 15:13:18 +00001343static int lpath_getBounds(lua_State* L) {
1344 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds());
1345 return 1;
1346}
1347
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001348static const char* fill_type_to_str(SkPath::FillType fill) {
1349 switch (fill) {
1350 case SkPath::kEvenOdd_FillType:
1351 return "even-odd";
1352 case SkPath::kWinding_FillType:
1353 return "winding";
1354 case SkPath::kInverseEvenOdd_FillType:
1355 return "inverse-even-odd";
1356 case SkPath::kInverseWinding_FillType:
1357 return "inverse-winding";
1358 }
1359 return "unknown";
1360}
1361
1362static int lpath_getFillType(lua_State* L) {
1363 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
1364 SkLua(L).pushString(fill_type_to_str(fill));
1365 return 1;
1366}
1367
1368static SkString segment_masks_to_str(uint32_t segmentMasks) {
1369 SkString result;
1370 bool first = true;
1371 if (SkPath::kLine_SegmentMask & segmentMasks) {
1372 result.append("line");
1373 first = false;
1374 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
1375 }
1376 if (SkPath::kQuad_SegmentMask & segmentMasks) {
1377 if (!first) {
1378 result.append(" ");
1379 }
1380 result.append("quad");
1381 first = false;
1382 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
1383 }
1384 if (SkPath::kConic_SegmentMask & segmentMasks) {
1385 if (!first) {
1386 result.append(" ");
1387 }
1388 result.append("conic");
1389 first = false;
1390 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
1391 }
1392 if (SkPath::kCubic_SegmentMask & segmentMasks) {
1393 if (!first) {
1394 result.append(" ");
1395 }
1396 result.append("cubic");
1397 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
1398 }
1399 SkASSERT(0 == segmentMasks);
1400 return result;
1401}
1402
krajcevski95498ed2014-08-18 08:02:33 -07001403static int lpath_getSegmentTypes(lua_State* L) {
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001404 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
1405 SkLua(L).pushString(segment_masks_to_str(segMasks));
1406 return 1;
1407}
1408
1409static int lpath_isConvex(lua_State* L) {
1410 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
1411 SkLua(L).pushBool(isConvex);
1412 return 1;
1413}
1414
reed@google.com74ce6f02013-05-22 15:13:18 +00001415static int lpath_isEmpty(lua_State* L) {
1416 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
1417 return 1;
1418}
1419
1420static int lpath_isRect(lua_State* L) {
1421 SkRect r;
1422 bool pred = get_obj<SkPath>(L, 1)->isRect(&r);
1423 int ret_count = 1;
1424 lua_pushboolean(L, pred);
1425 if (pred) {
1426 SkLua(L).pushRect(r);
1427 ret_count += 1;
1428 }
1429 return ret_count;
1430}
1431
1432static const char* dir2string(SkPath::Direction dir) {
1433 static const char* gStr[] = {
1434 "unknown", "cw", "ccw"
1435 };
1436 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr));
1437 return gStr[dir];
1438}
1439
caryclark95bc5f32015-04-08 08:34:15 -07001440static int lpath_isNestedFillRects(lua_State* L) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001441 SkRect rects[2];
1442 SkPath::Direction dirs[2];
caryclark95bc5f32015-04-08 08:34:15 -07001443 bool pred = get_obj<SkPath>(L, 1)->isNestedFillRects(rects, dirs);
reed@google.com74ce6f02013-05-22 15:13:18 +00001444 int ret_count = 1;
1445 lua_pushboolean(L, pred);
1446 if (pred) {
1447 SkLua lua(L);
1448 lua.pushRect(rects[0]);
1449 lua.pushRect(rects[1]);
1450 lua_pushstring(L, dir2string(dirs[0]));
1451 lua_pushstring(L, dir2string(dirs[0]));
1452 ret_count += 4;
1453 }
1454 return ret_count;
1455}
1456
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001457static int lpath_countPoints(lua_State* L) {
1458 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
1459 return 1;
1460}
1461
hstern0b401ce2016-08-02 09:17:59 -07001462static int lpath_getVerbs(lua_State* L) {
1463 const SkPath* path = get_obj<SkPath>(L, 1);
1464 SkPath::Iter iter(*path, false);
1465 SkPoint pts[4];
1466
1467 lua_newtable(L);
1468
1469 bool done = false;
1470 int i = 0;
1471 do {
1472 switch (iter.next(pts, true)) {
1473 case SkPath::kMove_Verb:
1474 setarray_string(L, ++i, "move");
1475 break;
1476 case SkPath::kClose_Verb:
1477 setarray_string(L, ++i, "close");
1478 break;
1479 case SkPath::kLine_Verb:
1480 setarray_string(L, ++i, "line");
1481 break;
1482 case SkPath::kQuad_Verb:
1483 setarray_string(L, ++i, "quad");
1484 break;
1485 case SkPath::kConic_Verb:
1486 setarray_string(L, ++i, "conic");
1487 break;
1488 case SkPath::kCubic_Verb:
1489 setarray_string(L, ++i, "cubic");
1490 break;
1491 case SkPath::kDone_Verb:
1492 setarray_string(L, ++i, "done");
1493 done = true;
1494 break;
1495 }
1496 } while (!done);
1497
1498 return 1;
1499}
1500
reed@google.com74ce6f02013-05-22 15:13:18 +00001501static int lpath_reset(lua_State* L) {
1502 get_obj<SkPath>(L, 1)->reset();
1503 return 0;
1504}
1505
1506static int lpath_moveTo(lua_State* L) {
1507 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3));
1508 return 0;
1509}
1510
1511static int lpath_lineTo(lua_State* L) {
1512 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3));
1513 return 0;
1514}
1515
1516static int lpath_quadTo(lua_State* L) {
1517 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3),
1518 lua2scalar(L, 4), lua2scalar(L, 5));
1519 return 0;
1520}
1521
1522static int lpath_cubicTo(lua_State* L) {
1523 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3),
1524 lua2scalar(L, 4), lua2scalar(L, 5),
1525 lua2scalar(L, 6), lua2scalar(L, 7));
1526 return 0;
1527}
1528
1529static int lpath_close(lua_State* L) {
1530 get_obj<SkPath>(L, 1)->close();
1531 return 0;
1532}
1533
1534static int lpath_gc(lua_State* L) {
1535 get_obj<SkPath>(L, 1)->~SkPath();
1536 return 0;
1537}
1538
1539static const struct luaL_Reg gSkPath_Methods[] = {
1540 { "getBounds", lpath_getBounds },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001541 { "getFillType", lpath_getFillType },
krajcevski95498ed2014-08-18 08:02:33 -07001542 { "getSegmentTypes", lpath_getSegmentTypes },
hstern0b401ce2016-08-02 09:17:59 -07001543 { "getVerbs", lpath_getVerbs },
commit-bot@chromium.orgd85b8222014-02-24 21:59:29 +00001544 { "isConvex", lpath_isConvex },
reed@google.com74ce6f02013-05-22 15:13:18 +00001545 { "isEmpty", lpath_isEmpty },
1546 { "isRect", lpath_isRect },
caryclark95bc5f32015-04-08 08:34:15 -07001547 { "isNestedFillRects", lpath_isNestedFillRects },
commit-bot@chromium.orgc5302082014-02-26 21:38:47 +00001548 { "countPoints", lpath_countPoints },
reed@google.com74ce6f02013-05-22 15:13:18 +00001549 { "reset", lpath_reset },
1550 { "moveTo", lpath_moveTo },
1551 { "lineTo", lpath_lineTo },
1552 { "quadTo", lpath_quadTo },
1553 { "cubicTo", lpath_cubicTo },
1554 { "close", lpath_close },
1555 { "__gc", lpath_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001556 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001557};
1558
1559///////////////////////////////////////////////////////////////////////////////
1560
1561static const char* rrect_type(const SkRRect& rr) {
1562 switch (rr.getType()) {
reed@google.com74ce6f02013-05-22 15:13:18 +00001563 case SkRRect::kEmpty_Type: return "empty";
1564 case SkRRect::kRect_Type: return "rect";
1565 case SkRRect::kOval_Type: return "oval";
1566 case SkRRect::kSimple_Type: return "simple";
commit-bot@chromium.orgf338d7c2014-03-17 21:17:30 +00001567 case SkRRect::kNinePatch_Type: return "nine-patch";
reed@google.com74ce6f02013-05-22 15:13:18 +00001568 case SkRRect::kComplex_Type: return "complex";
1569 }
mtklein@google.com330313a2013-08-22 15:37:26 +00001570 SkDEBUGFAIL("never get here");
reed@google.com74ce6f02013-05-22 15:13:18 +00001571 return "";
1572}
1573
1574static int lrrect_rect(lua_State* L) {
1575 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect());
1576 return 1;
1577}
1578
1579static int lrrect_type(lua_State* L) {
1580 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1)));
1581 return 1;
1582}
1583
1584static int lrrect_radii(lua_State* L) {
reed@google.com7fa2a652014-01-27 13:42:58 +00001585 int corner = SkToInt(lua_tointeger(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +00001586 SkVector v;
1587 if (corner < 0 || corner > 3) {
1588 SkDebugf("bad corner index %d", corner);
1589 v.set(0, 0);
1590 } else {
1591 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner);
1592 }
1593 lua_pushnumber(L, v.fX);
1594 lua_pushnumber(L, v.fY);
1595 return 2;
1596}
1597
1598static int lrrect_gc(lua_State* L) {
1599 get_obj<SkRRect>(L, 1)->~SkRRect();
1600 return 0;
1601}
1602
1603static const struct luaL_Reg gSkRRect_Methods[] = {
1604 { "rect", lrrect_rect },
1605 { "type", lrrect_type },
1606 { "radii", lrrect_radii },
1607 { "__gc", lrrect_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001608 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +00001609};
1610
1611///////////////////////////////////////////////////////////////////////////////
1612
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001613static int limage_width(lua_State* L) {
1614 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width());
1615 return 1;
1616}
1617
1618static int limage_height(lua_State* L) {
1619 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height());
1620 return 1;
1621}
1622
reed7a72c672014-11-07 10:23:55 -08001623static int limage_newShader(lua_State* L) {
1624 SkShader::TileMode tmode = SkShader::kClamp_TileMode;
halcanary96fcdcc2015-08-27 07:41:13 -07001625 const SkMatrix* localM = nullptr;
reed5671c5b2016-03-09 14:47:34 -08001626 push_ref(L, get_ref<SkImage>(L, 1)->makeShader(tmode, tmode, localM));
reed7a72c672014-11-07 10:23:55 -08001627 return 1;
1628}
1629
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001630static int limage_gc(lua_State* L) {
1631 get_ref<SkImage>(L, 1)->unref();
1632 return 0;
1633}
1634
1635static const struct luaL_Reg gSkImage_Methods[] = {
1636 { "width", limage_width },
1637 { "height", limage_height },
reed7a72c672014-11-07 10:23:55 -08001638 { "newShader", limage_newShader },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001639 { "__gc", limage_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001640 { nullptr, nullptr }
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00001641};
1642
1643///////////////////////////////////////////////////////////////////////////////
1644
reed485557f2014-10-12 10:36:47 -07001645static int lsurface_width(lua_State* L) {
1646 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->width());
1647 return 1;
1648}
1649
1650static int lsurface_height(lua_State* L) {
1651 lua_pushinteger(L, get_ref<SkSurface>(L, 1)->height());
1652 return 1;
1653}
1654
1655static int lsurface_getCanvas(lua_State* L) {
1656 SkCanvas* canvas = get_ref<SkSurface>(L, 1)->getCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001657 if (nullptr == canvas) {
reed485557f2014-10-12 10:36:47 -07001658 lua_pushnil(L);
1659 } else {
Mike Reed5df49342016-11-12 08:06:55 -06001660 push_ptr(L, canvas);
reed485557f2014-10-12 10:36:47 -07001661 // note: we don't unref canvas, since getCanvas did not ref it.
1662 // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
1663 // the real owner (the surface) go away, but still hold onto the canvas?
1664 // *really* we want to sort of ref the surface again, but have the native object
1665 // know that it is supposed to be treated as a canvas...
1666 }
1667 return 1;
1668}
1669
1670static int lsurface_newImageSnapshot(lua_State* L) {
reed9ce9d672016-03-17 10:51:11 -07001671 sk_sp<SkImage> image = get_ref<SkSurface>(L, 1)->makeImageSnapshot();
1672 if (!image) {
reed485557f2014-10-12 10:36:47 -07001673 lua_pushnil(L);
1674 } else {
reed9ce9d672016-03-17 10:51:11 -07001675 push_ref(L, image);
reed485557f2014-10-12 10:36:47 -07001676 }
1677 return 1;
1678}
1679
1680static int lsurface_newSurface(lua_State* L) {
1681 int width = lua2int_def(L, 2, 0);
reed96affcd2014-10-13 12:38:04 -07001682 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -07001683 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -07001684 auto surface = get_ref<SkSurface>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -07001685 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07001686 lua_pushnil(L);
1687 } else {
reede8f30622016-03-23 18:59:25 -07001688 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07001689 }
1690 return 1;
1691}
1692
1693static int lsurface_gc(lua_State* L) {
1694 get_ref<SkSurface>(L, 1)->unref();
1695 return 0;
1696}
1697
1698static const struct luaL_Reg gSkSurface_Methods[] = {
1699 { "width", lsurface_width },
1700 { "height", lsurface_height },
1701 { "getCanvas", lsurface_getCanvas },
1702 { "newImageSnapshot", lsurface_newImageSnapshot },
1703 { "newSurface", lsurface_newSurface },
1704 { "__gc", lsurface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001705 { nullptr, nullptr }
reed485557f2014-10-12 10:36:47 -07001706};
1707
1708///////////////////////////////////////////////////////////////////////////////
1709
reed96affcd2014-10-13 12:38:04 -07001710static int lpicturerecorder_beginRecording(lua_State* L) {
1711 const SkScalar w = lua2scalar_def(L, 2, -1);
1712 const SkScalar h = lua2scalar_def(L, 3, -1);
1713 if (w <= 0 || h <= 0) {
1714 lua_pushnil(L);
1715 return 1;
1716 }
1717
1718 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->beginRecording(w, h);
halcanary96fcdcc2015-08-27 07:41:13 -07001719 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001720 lua_pushnil(L);
1721 return 1;
1722 }
1723
Mike Reed5df49342016-11-12 08:06:55 -06001724 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001725 return 1;
1726}
1727
1728static int lpicturerecorder_getCanvas(lua_State* L) {
1729 SkCanvas* canvas = get_obj<SkPictureRecorder>(L, 1)->getRecordingCanvas();
halcanary96fcdcc2015-08-27 07:41:13 -07001730 if (nullptr == canvas) {
reed96affcd2014-10-13 12:38:04 -07001731 lua_pushnil(L);
1732 return 1;
1733 }
Mike Reed5df49342016-11-12 08:06:55 -06001734 push_ptr(L, canvas);
reed96affcd2014-10-13 12:38:04 -07001735 return 1;
1736}
1737
1738static int lpicturerecorder_endRecording(lua_State* L) {
reedca2622b2016-03-18 07:25:55 -07001739 sk_sp<SkPicture> pic = get_obj<SkPictureRecorder>(L, 1)->finishRecordingAsPicture();
1740 if (!pic) {
reed96affcd2014-10-13 12:38:04 -07001741 lua_pushnil(L);
1742 return 1;
1743 }
reedca2622b2016-03-18 07:25:55 -07001744 push_ref(L, std::move(pic));
reed96affcd2014-10-13 12:38:04 -07001745 return 1;
1746}
1747
1748static int lpicturerecorder_gc(lua_State* L) {
1749 get_obj<SkPictureRecorder>(L, 1)->~SkPictureRecorder();
1750 return 0;
1751}
1752
1753static const struct luaL_Reg gSkPictureRecorder_Methods[] = {
1754 { "beginRecording", lpicturerecorder_beginRecording },
1755 { "getCanvas", lpicturerecorder_getCanvas },
1756 { "endRecording", lpicturerecorder_endRecording },
1757 { "__gc", lpicturerecorder_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001758 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001759};
1760
1761///////////////////////////////////////////////////////////////////////////////
1762
1763static int lpicture_width(lua_State* L) {
1764 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().width());
1765 return 1;
1766}
1767
1768static int lpicture_height(lua_State* L) {
1769 lua_pushnumber(L, get_ref<SkPicture>(L, 1)->cullRect().height());
1770 return 1;
1771}
1772
1773static int lpicture_gc(lua_State* L) {
1774 get_ref<SkPicture>(L, 1)->unref();
1775 return 0;
1776}
1777
1778static const struct luaL_Reg gSkPicture_Methods[] = {
1779 { "width", lpicture_width },
1780 { "height", lpicture_height },
1781 { "__gc", lpicture_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001782 { nullptr, nullptr }
reed96affcd2014-10-13 12:38:04 -07001783};
1784
1785///////////////////////////////////////////////////////////////////////////////
1786
reed1b6ab442014-11-03 19:55:41 -08001787static int ltextblob_bounds(lua_State* L) {
1788 SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
1789 return 1;
1790}
1791
1792static int ltextblob_gc(lua_State* L) {
1793 SkSafeUnref(get_ref<SkTextBlob>(L, 1));
1794 return 0;
1795}
1796
1797static const struct luaL_Reg gSkTextBlob_Methods[] = {
1798 { "bounds", ltextblob_bounds },
1799 { "__gc", ltextblob_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001800 { nullptr, nullptr }
reed1b6ab442014-11-03 19:55:41 -08001801};
1802
1803///////////////////////////////////////////////////////////////////////////////
1804
reed36c9c112014-11-04 10:58:42 -08001805static int ltypeface_getFamilyName(lua_State* L) {
1806 SkString str;
1807 get_ref<SkTypeface>(L, 1)->getFamilyName(&str);
1808 lua_pushstring(L, str.c_str());
1809 return 1;
1810}
1811
1812static int ltypeface_getStyle(lua_State* L) {
Ben Wagner26308e12017-08-08 15:23:47 -04001813 push_obj(L, get_ref<SkTypeface>(L, 1)->fontStyle());
reed36c9c112014-11-04 10:58:42 -08001814 return 1;
1815}
1816
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001817static int ltypeface_gc(lua_State* L) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +00001818 SkSafeUnref(get_ref<SkTypeface>(L, 1));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001819 return 0;
1820}
1821
1822static const struct luaL_Reg gSkTypeface_Methods[] = {
reed36c9c112014-11-04 10:58:42 -08001823 { "getFamilyName", ltypeface_getFamilyName },
1824 { "getStyle", ltypeface_getStyle },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001825 { "__gc", ltypeface_gc },
halcanary96fcdcc2015-08-27 07:41:13 -07001826 { nullptr, nullptr }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001827};
1828
1829///////////////////////////////////////////////////////////////////////////////
1830
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001831static int lfontstyle_weight(lua_State* L) {
1832 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->weight());
1833 return 1;
1834}
1835
1836static int lfontstyle_width(lua_State* L) {
1837 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->width());
1838 return 1;
1839}
1840
1841static int lfontstyle_slant(lua_State* L) {
1842 lua_pushnumber(L, get_ref<SkFontStyle>(L, 1)->slant());
1843 return 1;
1844}
1845
1846static int lfontstyle_gc(lua_State* L) {
1847 get_obj<SkFontStyle>(L, 1)->~SkFontStyle();
1848 return 0;
1849}
1850
1851static const struct luaL_Reg gSkFontStyle_Methods[] = {
1852 { "weight", lfontstyle_weight },
1853 { "width", lfontstyle_width },
1854 { "slant", lfontstyle_slant },
1855 { "__gc", lfontstyle_gc },
1856 { nullptr, nullptr }
1857};
1858
1859///////////////////////////////////////////////////////////////////////////////
1860
reed@google.com74ce6f02013-05-22 15:13:18 +00001861class AutoCallLua {
1862public:
1863 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) {
1864 lua_getglobal(L, func);
1865 if (!lua_isfunction(L, -1)) {
1866 int t = lua_type(L, -1);
1867 SkDebugf("--- expected function %d\n", t);
1868 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001869
reed@google.com74ce6f02013-05-22 15:13:18 +00001870 lua_newtable(L);
1871 setfield_string(L, "verb", verb);
1872 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001873
reed@google.com74ce6f02013-05-22 15:13:18 +00001874 ~AutoCallLua() {
1875 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) {
1876 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
1877 }
1878 lua_settop(fL, -1);
1879 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +00001880
reed@google.com74ce6f02013-05-22 15:13:18 +00001881private:
1882 lua_State* fL;
1883};
1884
1885#define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb)
1886
1887///////////////////////////////////////////////////////////////////////////////
1888
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001889static int lsk_newDocumentPDF(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -05001890 const char* filename = nullptr;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001891 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
Mike Reed7ff6ca52018-01-08 14:45:31 -05001892 filename = lua_tolstring(L, 1, nullptr);
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001893 }
Mike Reed7ff6ca52018-01-08 14:45:31 -05001894 if (!filename) {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001895 return 0;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001896 }
Mike Reed7ff6ca52018-01-08 14:45:31 -05001897 auto file = skstd::make_unique<SkFILEWStream>(filename);
1898 if (!file->isValid()) {
1899 return 0;
1900 }
1901 sk_sp<SkDocument> doc = SkDocument::MakePDF(file.get());
1902 if (!doc) {
1903 return 0;
1904 }
1905 push_ptr(L, new DocHolder{std::move(doc), std::move(file)});
1906 return 1;
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00001907}
1908
reed468b1812014-10-19 11:42:54 -07001909static int lsk_newBlurImageFilter(lua_State* L) {
1910 SkScalar sigmaX = lua2scalar_def(L, 1, 0);
1911 SkScalar sigmaY = lua2scalar_def(L, 2, 0);
robertphillips6e7025a2016-04-04 04:31:25 -07001912 sk_sp<SkImageFilter> imf(SkBlurImageFilter::Make(sigmaX, sigmaY, nullptr));
1913 if (!imf) {
reed468b1812014-10-19 11:42:54 -07001914 lua_pushnil(L);
1915 } else {
robertphillips6e7025a2016-04-04 04:31:25 -07001916 push_ref(L, std::move(imf));
reed9fbc3f32014-10-21 07:12:58 -07001917 }
1918 return 1;
1919}
1920
1921static int lsk_newLinearGradient(lua_State* L) {
1922 SkScalar x0 = lua2scalar_def(L, 1, 0);
1923 SkScalar y0 = lua2scalar_def(L, 2, 0);
1924 SkColor c0 = lua2color(L, 3);
1925 SkScalar x1 = lua2scalar_def(L, 4, 0);
1926 SkScalar y1 = lua2scalar_def(L, 5, 0);
1927 SkColor c1 = lua2color(L, 6);
1928
1929 SkPoint pts[] = { { x0, y0 }, { x1, y1 } };
1930 SkColor colors[] = { c0, c1 };
robertphillips6e7025a2016-04-04 04:31:25 -07001931 sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
1932 SkShader::kClamp_TileMode));
reed2ad1aa62016-03-09 09:50:50 -08001933 if (!s) {
reed9fbc3f32014-10-21 07:12:58 -07001934 lua_pushnil(L);
1935 } else {
reed2ad1aa62016-03-09 09:50:50 -08001936 push_ref(L, std::move(s));
reed468b1812014-10-19 11:42:54 -07001937 }
1938 return 1;
1939}
1940
reedbdc49ae2014-10-14 09:34:52 -07001941static int lsk_newMatrix(lua_State* L) {
1942 push_new<SkMatrix>(L)->reset();
1943 return 1;
1944}
1945
reed@google.com3597b732013-05-22 20:12:50 +00001946static int lsk_newPaint(lua_State* L) {
1947 push_new<SkPaint>(L);
1948 return 1;
1949}
1950
1951static int lsk_newPath(lua_State* L) {
1952 push_new<SkPath>(L);
1953 return 1;
1954}
1955
reed96affcd2014-10-13 12:38:04 -07001956static int lsk_newPictureRecorder(lua_State* L) {
1957 push_new<SkPictureRecorder>(L);
1958 return 1;
1959}
1960
reed@google.com3597b732013-05-22 20:12:50 +00001961static int lsk_newRRect(lua_State* L) {
reedbdc49ae2014-10-14 09:34:52 -07001962 push_new<SkRRect>(L)->setEmpty();
reed@google.com3597b732013-05-22 20:12:50 +00001963 return 1;
1964}
1965
reed1b6ab442014-11-03 19:55:41 -08001966// Sk.newTextBlob(text, rect, paint)
1967static int lsk_newTextBlob(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001968 const char* text = lua_tolstring(L, 1, nullptr);
reed1b6ab442014-11-03 19:55:41 -08001969 SkRect bounds;
1970 lua2rect(L, 2, &bounds);
1971 const SkPaint& paint = *get_obj<SkPaint>(L, 3);
1972
Herb Derby1724db12018-05-22 12:01:50 -04001973 SkShaper shaper(nullptr);
reed1b6ab442014-11-03 19:55:41 -08001974
Herb Derby1724db12018-05-22 12:01:50 -04001975 SkTextBlobBuilder builder;
1976 SkPoint end = shaper.shape(&builder, paint, text, strlen(text), true,
1977 { bounds.left(), bounds.top() }, bounds.width());
1978
1979 push_ref<SkTextBlob>(L, builder.make());
1980 SkLua(L).pushScalar(end.fY);
reed1b6ab442014-11-03 19:55:41 -08001981 return 2;
1982}
1983
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001984static int lsk_newTypeface(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001985 const char* name = nullptr;
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001986 SkFontStyle style;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00001987
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001988 int count = lua_gettop(L);
1989 if (count > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001990 name = lua_tolstring(L, 1, nullptr);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001991 if (count > 1) {
1992 SkFontStyle* passedStyle = get_obj<SkFontStyle>(L, 2);
1993 if (passedStyle) {
1994 style = *passedStyle;
1995 }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001996 }
1997 }
1998
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001999 sk_sp<SkTypeface> face(SkTypeface::MakeFromName(name, style));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002000// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
halcanary96fcdcc2015-08-27 07:41:13 -07002001 if (nullptr == face) {
bungeman13b9c952016-05-12 10:09:30 -07002002 face = SkTypeface::MakeDefault();
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002003 }
bungeman13b9c952016-05-12 10:09:30 -07002004 push_ref(L, std::move(face));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002005 return 1;
2006}
reed@google.com3597b732013-05-22 20:12:50 +00002007
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002008static int lsk_newFontStyle(lua_State* L) {
2009 int count = lua_gettop(L);
2010 int weight = SkFontStyle::kNormal_Weight;
2011 int width = SkFontStyle::kNormal_Width;
2012 SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
2013 if (count >= 1 && lua_isnumber(L, 1)) {
2014 weight = lua_tointegerx(L, 1, nullptr);
2015 }
2016 if (count >= 2 && lua_isnumber(L, 2)) {
2017 width = lua_tointegerx(L, 2, nullptr);
2018 }
2019 if (count >= 3 && lua_isnumber(L, 3)) {
2020 slant = static_cast<SkFontStyle::Slant>(lua_tointegerx(L, 3, nullptr));
2021 }
2022 push_new<SkFontStyle>(L, weight, width, slant);
2023 return 1;
2024}
2025
reed485557f2014-10-12 10:36:47 -07002026static int lsk_newRasterSurface(lua_State* L) {
reed7b864662014-11-04 13:24:47 -08002027 int width = lua2int_def(L, 1, 0);
reed485557f2014-10-12 10:36:47 -07002028 int height = lua2int_def(L, 2, 0);
2029 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
robertphillips702edbd2015-06-23 06:26:08 -07002030 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
reede8f30622016-03-23 18:59:25 -07002031 auto surface = SkSurface::MakeRaster(info, &props);
halcanary96fcdcc2015-08-27 07:41:13 -07002032 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07002033 lua_pushnil(L);
2034 } else {
reede8f30622016-03-23 18:59:25 -07002035 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07002036 }
2037 return 1;
2038}
2039
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002040static int lsk_loadImage(lua_State* L) {
2041 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002042 const char* name = lua_tolstring(L, 1, nullptr);
reed9ce9d672016-03-17 10:51:11 -07002043 sk_sp<SkData> data(SkData::MakeFromFileName(name));
2044 if (data) {
2045 auto image = SkImage::MakeFromEncoded(std::move(data));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002046 if (image) {
reed9ce9d672016-03-17 10:51:11 -07002047 push_ref(L, std::move(image));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002048 return 1;
2049 }
2050 }
2051 }
2052 return 0;
2053}
2054
reed@google.com3597b732013-05-22 20:12:50 +00002055static void register_Sk(lua_State* L) {
2056 lua_newtable(L);
2057 lua_pushvalue(L, -1);
2058 lua_setglobal(L, "Sk");
2059 // the Sk table is still on top
2060
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00002061 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002062 setfield_function(L, "loadImage", lsk_loadImage);
reed468b1812014-10-19 11:42:54 -07002063 setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
reed9fbc3f32014-10-21 07:12:58 -07002064 setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
reedbdc49ae2014-10-14 09:34:52 -07002065 setfield_function(L, "newMatrix", lsk_newMatrix);
reed@google.com3597b732013-05-22 20:12:50 +00002066 setfield_function(L, "newPaint", lsk_newPaint);
2067 setfield_function(L, "newPath", lsk_newPath);
reed96affcd2014-10-13 12:38:04 -07002068 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
reed@google.com3597b732013-05-22 20:12:50 +00002069 setfield_function(L, "newRRect", lsk_newRRect);
reed485557f2014-10-12 10:36:47 -07002070 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
reed1b6ab442014-11-03 19:55:41 -08002071 setfield_function(L, "newTextBlob", lsk_newTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002072 setfield_function(L, "newTypeface", lsk_newTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002073 setfield_function(L, "newFontStyle", lsk_newFontStyle);
reed@google.com3597b732013-05-22 20:12:50 +00002074 lua_pop(L, 1); // pop off the Sk table
2075}
2076
reed@google.com74ce6f02013-05-22 15:13:18 +00002077#define REG_CLASS(L, C) \
2078 do { \
reed@google.com3597b732013-05-22 20:12:50 +00002079 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00002080 lua_pushvalue(L, -1); \
2081 lua_setfield(L, -2, "__index"); \
2082 luaL_setfuncs(L, g##C##_Methods, 0); \
2083 lua_pop(L, 1); /* pop off the meta-table */ \
2084 } while (0)
2085
2086void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00002087 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00002088 REG_CLASS(L, SkCanvas);
reed22a517f2015-12-04 20:45:59 -08002089 REG_CLASS(L, SkColorFilter);
Mike Reed7ff6ca52018-01-08 14:45:31 -05002090 REG_CLASS(L, DocHolder);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002091 REG_CLASS(L, SkImage);
reed468b1812014-10-19 11:42:54 -07002092 REG_CLASS(L, SkImageFilter);
reed1b6ab442014-11-03 19:55:41 -08002093 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00002094 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00002095 REG_CLASS(L, SkPath);
2096 REG_CLASS(L, SkPathEffect);
reed96affcd2014-10-13 12:38:04 -07002097 REG_CLASS(L, SkPicture);
2098 REG_CLASS(L, SkPictureRecorder);
reed@google.com74ce6f02013-05-22 15:13:18 +00002099 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00002100 REG_CLASS(L, SkShader);
reed485557f2014-10-12 10:36:47 -07002101 REG_CLASS(L, SkSurface);
reed1b6ab442014-11-03 19:55:41 -08002102 REG_CLASS(L, SkTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002103 REG_CLASS(L, SkTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002104 REG_CLASS(L, SkFontStyle);
reed@google.com74ce6f02013-05-22 15:13:18 +00002105}
zachr@google.com28c27c82013-06-20 17:15:05 +00002106
reed@google.com7bce9982013-06-20 17:40:21 +00002107extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00002108extern "C" int luaopen_skia(lua_State* L) {
2109 SkLua::Load(L);
2110 return 0;
2111}