blob: 38f9c910f057b8123f20c474ba15888e5f44f23d [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"
29#include "SkString.h"
reed485557f2014-10-12 10:36:47 -070030#include "SkSurface.h"
fmalitab7425172014-08-26 07:56:44 -070031#include "SkTextBlob.h"
reed@google.come3823fd2013-05-30 18:55:14 +000032#include "SkTypeface.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000033
34extern "C" {
reed@google.com3597b732013-05-22 20:12:50 +000035 #include "lua.h"
36 #include "lualib.h"
37 #include "lauxlib.h"
reed@google.com74ce6f02013-05-22 15:13:18 +000038}
39
Mike Reed7ff6ca52018-01-08 14:45:31 -050040struct DocHolder {
41 sk_sp<SkDocument> fDoc;
42 std::unique_ptr<SkWStream> fStream;
43};
44
reed@google.comfd345872013-05-22 20:53:42 +000045// return the metatable name for a given class
reed@google.com3597b732013-05-22 20:12:50 +000046template <typename T> const char* get_mtname();
reed@google.comfd345872013-05-22 20:53:42 +000047#define DEF_MTNAME(T) \
48 template <> const char* get_mtname<T>() { \
49 return #T "_LuaMetaTableName"; \
50 }
51
52DEF_MTNAME(SkCanvas)
reed22a517f2015-12-04 20:45:59 -080053DEF_MTNAME(SkColorFilter)
Mike Reed7ff6ca52018-01-08 14:45:31 -050054DEF_MTNAME(DocHolder)
mike@reedtribe.org792bbd12013-06-11 02:20:28 +000055DEF_MTNAME(SkImage)
reed468b1812014-10-19 11:42:54 -070056DEF_MTNAME(SkImageFilter)
reed@google.comfd345872013-05-22 20:53:42 +000057DEF_MTNAME(SkMatrix)
58DEF_MTNAME(SkRRect)
59DEF_MTNAME(SkPath)
60DEF_MTNAME(SkPaint)
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +000061DEF_MTNAME(SkPathEffect)
reed96affcd2014-10-13 12:38:04 -070062DEF_MTNAME(SkPicture)
63DEF_MTNAME(SkPictureRecorder)
reed@google.com5fdc9832013-07-24 15:47:52 +000064DEF_MTNAME(SkShader)
reed485557f2014-10-12 10:36:47 -070065DEF_MTNAME(SkSurface)
fmalitab7425172014-08-26 07:56:44 -070066DEF_MTNAME(SkTextBlob)
mike@reedtribe.orge6469f12013-06-08 03:15:47 +000067DEF_MTNAME(SkTypeface)
Ben Wagnerc6c10b42017-08-07 09:56:21 -040068DEF_MTNAME(SkFontStyle)
reed@google.com74ce6f02013-05-22 15:13:18 +000069
Ben Wagnerc6c10b42017-08-07 09:56:21 -040070template <typename T, typename... Args> T* push_new(lua_State* L, Args&&... args) {
reed@google.com3597b732013-05-22 20:12:50 +000071 T* addr = (T*)lua_newuserdata(L, sizeof(T));
Ben Wagnerc6c10b42017-08-07 09:56:21 -040072 new (addr) T(std::forward<Args>(args)...);
reed@google.com3597b732013-05-22 20:12:50 +000073 luaL_getmetatable(L, get_mtname<T>());
74 lua_setmetatable(L, -2);
75 return addr;
76}
reed@google.com74ce6f02013-05-22 15:13:18 +000077
78template <typename T> void push_obj(lua_State* L, const T& obj) {
79 new (lua_newuserdata(L, sizeof(T))) T(obj);
reed@google.com3597b732013-05-22 20:12:50 +000080 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000081 lua_setmetatable(L, -2);
82}
83
Mike Reed5df49342016-11-12 08:06:55 -060084template <typename T> T* push_ptr(lua_State* L, T* ptr) {
85 *(T**)lua_newuserdata(L, sizeof(T*)) = ptr;
86 luaL_getmetatable(L, get_mtname<T>());
87 lua_setmetatable(L, -2);
88 return ptr;
89}
90
reed9fbc3f32014-10-21 07:12:58 -070091template <typename T> T* push_ref(lua_State* L, T* ref) {
commit-bot@chromium.org77887af2013-12-17 14:28:19 +000092 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
reed@google.com3597b732013-05-22 20:12:50 +000093 luaL_getmetatable(L, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +000094 lua_setmetatable(L, -2);
reed9fbc3f32014-10-21 07:12:58 -070095 return ref;
reed@google.com74ce6f02013-05-22 15:13:18 +000096}
97
reed2ad1aa62016-03-09 09:50:50 -080098template <typename T> void push_ref(lua_State* L, sk_sp<T> sp) {
99 *(T**)lua_newuserdata(L, sizeof(T*)) = sp.release();
100 luaL_getmetatable(L, get_mtname<T>());
101 lua_setmetatable(L, -2);
102}
103
reed@google.com74ce6f02013-05-22 15:13:18 +0000104template <typename T> T* get_ref(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +0000105 return *(T**)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +0000106}
107
108template <typename T> T* get_obj(lua_State* L, int index) {
reed@google.com3597b732013-05-22 20:12:50 +0000109 return (T*)luaL_checkudata(L, index, get_mtname<T>());
reed@google.com74ce6f02013-05-22 15:13:18 +0000110}
111
reed@google.com88c9ec92013-05-22 15:43:21 +0000112static bool lua2bool(lua_State* L, int index) {
113 return !!lua_toboolean(L, index);
114}
115
reed@google.com74ce6f02013-05-22 15:13:18 +0000116///////////////////////////////////////////////////////////////////////////////
117
reed@google.com3597b732013-05-22 20:12:50 +0000118SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) {
119 fL = luaL_newstate();
120 luaL_openlibs(fL);
121 SkLua::Load(fL);
122}
123
124SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {}
125
126SkLua::~SkLua() {
127 if (fWeOwnL) {
128 if (fTermCode.size() > 0) {
129 lua_getglobal(fL, fTermCode.c_str());
130 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) {
131 SkDebugf("lua err: %s\n", lua_tostring(fL, -1));
132 }
133 }
134 lua_close(fL);
135 }
136}
137
138bool SkLua::runCode(const char code[]) {
139 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0);
140 if (err) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000141 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1));
reed@google.com3597b732013-05-22 20:12:50 +0000142 return false;
143 }
144 return true;
145}
146
147bool SkLua::runCode(const void* code, size_t size) {
148 SkString str((const char*)code, size);
149 return this->runCode(str.c_str());
150}
151
152///////////////////////////////////////////////////////////////////////////////
153
154#define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0)
155
reed@google.com29563872013-07-10 21:23:49 +0000156static void setfield_bool_if(lua_State* L, const char key[], bool pred) {
157 if (pred) {
158 lua_pushboolean(L, true);
159 lua_setfield(L, -2, key);
160 }
161}
162
reed@google.com74ce6f02013-05-22 15:13:18 +0000163static void setfield_string(lua_State* L, const char key[], const char value[]) {
164 lua_pushstring(L, value);
165 lua_setfield(L, -2, key);
166}
167
168static void setfield_number(lua_State* L, const char key[], double value) {
169 lua_pushnumber(L, value);
170 lua_setfield(L, -2, key);
171}
172
humper@google.com2815c192013-07-10 22:42:30 +0000173static void setfield_boolean(lua_State* L, const char key[], bool value) {
174 lua_pushboolean(L, value);
175 lua_setfield(L, -2, key);
176}
177
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000178static void setfield_scalar(lua_State* L, const char key[], SkScalar value) {
179 setfield_number(L, key, SkScalarToLua(value));
180}
181
reed@google.com3597b732013-05-22 20:12:50 +0000182static void setfield_function(lua_State* L,
183 const char key[], lua_CFunction value) {
184 lua_pushcfunction(L, value);
185 lua_setfield(L, -2, key);
reed@google.com74ce6f02013-05-22 15:13:18 +0000186}
187
reed7a72c672014-11-07 10:23:55 -0800188static int lua2int_def(lua_State* L, int index, int defaultValue) {
189 if (lua_isnumber(L, index)) {
190 return (int)lua_tonumber(L, index);
191 } else {
192 return defaultValue;
193 }
194}
195
196static SkScalar lua2scalar(lua_State* L, int index) {
197 SkASSERT(lua_isnumber(L, index));
198 return SkLuaToScalar(lua_tonumber(L, index));
199}
200
201static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) {
202 if (lua_isnumber(L, index)) {
203 return SkLuaToScalar(lua_tonumber(L, index));
204 } else {
205 return defaultValue;
206 }
207}
208
209static SkScalar getarray_scalar(lua_State* L, int stackIndex, int arrayIndex) {
210 SkASSERT(lua_istable(L, stackIndex));
211 lua_rawgeti(L, stackIndex, arrayIndex);
mtklein8aacf202014-12-18 13:29:54 -0800212
reed7a72c672014-11-07 10:23:55 -0800213 SkScalar value = lua2scalar(L, -1);
214 lua_pop(L, 1);
215 return value;
216}
217
218static void getarray_scalars(lua_State* L, int stackIndex, SkScalar dst[], int count) {
219 for (int i = 0; i < count; ++i) {
220 dst[i] = getarray_scalar(L, stackIndex, i + 1);
221 }
222}
223
224static void getarray_points(lua_State* L, int stackIndex, SkPoint pts[], int count) {
225 getarray_scalars(L, stackIndex, &pts[0].fX, count * 2);
226}
227
reed@google.come3823fd2013-05-30 18:55:14 +0000228static void setarray_number(lua_State* L, int index, double value) {
229 lua_pushnumber(L, value);
230 lua_rawseti(L, -2, index);
231}
232
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000233static void setarray_scalar(lua_State* L, int index, SkScalar value) {
234 setarray_number(L, index, SkScalarToLua(value));
235}
236
hstern0b401ce2016-08-02 09:17:59 -0700237static void setarray_string(lua_State* L, int index, const char str[]) {
238 lua_pushstring(L, str);
239 lua_rawseti(L, -2, index);
240}
241
reed@google.com74ce6f02013-05-22 15:13:18 +0000242void SkLua::pushBool(bool value, const char key[]) {
243 lua_pushboolean(fL, value);
244 CHECK_SETFIELD(key);
245}
246
247void SkLua::pushString(const char str[], const char key[]) {
248 lua_pushstring(fL, str);
249 CHECK_SETFIELD(key);
250}
251
reed@google.come3823fd2013-05-30 18:55:14 +0000252void SkLua::pushString(const char str[], size_t length, const char key[]) {
253 // TODO: how to do this w/o making a copy?
254 SkString s(str, length);
255 lua_pushstring(fL, s.c_str());
256 CHECK_SETFIELD(key);
257}
258
reed@google.com74ce6f02013-05-22 15:13:18 +0000259void SkLua::pushString(const SkString& str, const char key[]) {
260 lua_pushstring(fL, str.c_str());
261 CHECK_SETFIELD(key);
262}
263
264void SkLua::pushColor(SkColor color, const char key[]) {
265 lua_newtable(fL);
266 setfield_number(fL, "a", SkColorGetA(color) / 255.0);
267 setfield_number(fL, "r", SkColorGetR(color) / 255.0);
268 setfield_number(fL, "g", SkColorGetG(color) / 255.0);
269 setfield_number(fL, "b", SkColorGetB(color) / 255.0);
270 CHECK_SETFIELD(key);
271}
272
reed@google.come3823fd2013-05-30 18:55:14 +0000273void SkLua::pushU32(uint32_t value, const char key[]) {
274 lua_pushnumber(fL, (double)value);
275 CHECK_SETFIELD(key);
276}
277
reed@google.com74ce6f02013-05-22 15:13:18 +0000278void SkLua::pushScalar(SkScalar value, const char key[]) {
279 lua_pushnumber(fL, SkScalarToLua(value));
280 CHECK_SETFIELD(key);
281}
282
reed@google.come3823fd2013-05-30 18:55:14 +0000283void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
284 lua_newtable(fL);
285 for (int i = 0; i < count; ++i) {
286 // make it base-1 to match lua convention
287 setarray_number(fL, i + 1, (double)array[i]);
288 }
289 CHECK_SETFIELD(key);
290}
291
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +0000292void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
293 lua_newtable(fL);
294 for (int i = 0; i < count; ++i) {
295 // make it base-1 to match lua convention
296 lua_newtable(fL);
297 this->pushScalar(array[i].fX, "x");
298 this->pushScalar(array[i].fY, "y");
299 lua_rawseti(fL, -2, i + 1);
300 }
301 CHECK_SETFIELD(key);
302}
303
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000304void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
305 lua_newtable(fL);
306 for (int i = 0; i < count; ++i) {
307 // make it base-1 to match lua convention
308 setarray_scalar(fL, i + 1, array[i]);
309 }
310 CHECK_SETFIELD(key);
311}
312
reed@google.com74ce6f02013-05-22 15:13:18 +0000313void SkLua::pushRect(const SkRect& r, const char key[]) {
314 lua_newtable(fL);
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000315 setfield_scalar(fL, "left", r.fLeft);
316 setfield_scalar(fL, "top", r.fTop);
317 setfield_scalar(fL, "right", r.fRight);
318 setfield_scalar(fL, "bottom", r.fBottom);
reed@google.com74ce6f02013-05-22 15:13:18 +0000319 CHECK_SETFIELD(key);
320}
321
322void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
323 push_obj(fL, rr);
324 CHECK_SETFIELD(key);
325}
326
commit-bot@chromium.org4d803a92014-05-14 16:03:14 +0000327void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
328 lua_newtable(fL);
329 setfield_scalar(fL, "phase", info.fPhase);
330 this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
331 CHECK_SETFIELD(key);
332}
333
334
reed@google.com74ce6f02013-05-22 15:13:18 +0000335void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
336 push_obj(fL, matrix);
337 CHECK_SETFIELD(key);
338}
339
340void SkLua::pushPaint(const SkPaint& paint, const char key[]) {
341 push_obj(fL, paint);
342 CHECK_SETFIELD(key);
343}
344
345void SkLua::pushPath(const SkPath& path, const char key[]) {
346 push_obj(fL, path);
347 CHECK_SETFIELD(key);
348}
349
350void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
Mike Reed5df49342016-11-12 08:06:55 -0600351 push_ptr(fL, canvas);
reed@google.com74ce6f02013-05-22 15:13:18 +0000352 CHECK_SETFIELD(key);
353}
354
fmalitab7425172014-08-26 07:56:44 -0700355void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
356 push_ref(fL, const_cast<SkTextBlob*>(blob));
357 CHECK_SETFIELD(key);
358}
359
reed@google.com74ce6f02013-05-22 15:13:18 +0000360///////////////////////////////////////////////////////////////////////////////
361///////////////////////////////////////////////////////////////////////////////
362
reed@google.com74ce6f02013-05-22 15:13:18 +0000363static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) {
364 SkASSERT(lua_istable(L, index));
365 lua_pushstring(L, key);
366 lua_gettable(L, index);
mtklein8aacf202014-12-18 13:29:54 -0800367
reed@google.com74ce6f02013-05-22 15:13:18 +0000368 SkScalar value = lua2scalar(L, -1);
369 lua_pop(L, 1);
370 return value;
371}
372
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000373static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) {
374 SkASSERT(lua_istable(L, index));
375 lua_pushstring(L, key);
376 lua_gettable(L, index);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000377
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000378 SkScalar value;
379 if (lua_isnil(L, -1)) {
380 value = def;
381 } else {
382 value = lua2scalar(L, -1);
383 }
384 lua_pop(L, 1);
385 return value;
386}
387
reed468b1812014-10-19 11:42:54 -0700388static SkScalar byte2unit(U8CPU byte) {
389 return byte / 255.0f;
390}
391
reed@google.com74ce6f02013-05-22 15:13:18 +0000392static U8CPU unit2byte(SkScalar x) {
393 if (x <= 0) {
394 return 0;
395 } else if (x >= 1) {
396 return 255;
397 } else {
398 return SkScalarRoundToInt(x * 255);
399 }
400}
401
402static SkColor lua2color(lua_State* L, int index) {
reed485557f2014-10-12 10:36:47 -0700403 return SkColorSetARGB(unit2byte(getfield_scalar_default(L, index, "a", 1)),
404 unit2byte(getfield_scalar_default(L, index, "r", 0)),
405 unit2byte(getfield_scalar_default(L, index, "g", 0)),
406 unit2byte(getfield_scalar_default(L, index, "b", 0)));
reed@google.com74ce6f02013-05-22 15:13:18 +0000407}
408
409static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) {
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000410 rect->set(getfield_scalar_default(L, index, "left", 0),
411 getfield_scalar_default(L, index, "top", 0),
reed@google.com74ce6f02013-05-22 15:13:18 +0000412 getfield_scalar(L, index, "right"),
413 getfield_scalar(L, index, "bottom"));
414 return rect;
415}
416
reedf355df52014-10-12 12:18:40 -0700417static int lcanvas_clear(lua_State* L) {
418 get_ref<SkCanvas>(L, 1)->clear(0);
419 return 0;
420}
421
reed@google.com74ce6f02013-05-22 15:13:18 +0000422static int lcanvas_drawColor(lua_State* L) {
423 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2));
424 return 0;
425}
426
reed9fbc3f32014-10-21 07:12:58 -0700427static int lcanvas_drawPaint(lua_State* L) {
428 get_ref<SkCanvas>(L, 1)->drawPaint(*get_obj<SkPaint>(L, 2));
429 return 0;
430}
431
reed@google.com74ce6f02013-05-22 15:13:18 +0000432static int lcanvas_drawRect(lua_State* L) {
433 SkRect rect;
reed7a72c672014-11-07 10:23:55 -0800434 lua2rect(L, 2, &rect);
435 const SkPaint* paint = get_obj<SkPaint>(L, 3);
436 get_ref<SkCanvas>(L, 1)->drawRect(rect, *paint);
reed@google.com74ce6f02013-05-22 15:13:18 +0000437 return 0;
438}
439
440static int lcanvas_drawOval(lua_State* L) {
441 SkRect rect;
442 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect),
443 *get_obj<SkPaint>(L, 3));
444 return 0;
445}
446
447static int lcanvas_drawCircle(lua_State* L) {
448 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2),
449 lua2scalar(L, 3),
450 lua2scalar(L, 4),
451 *get_obj<SkPaint>(L, 5));
452 return 0;
453}
454
reed485557f2014-10-12 10:36:47 -0700455static SkPaint* lua2OptionalPaint(lua_State* L, int index, SkPaint* paint) {
456 if (lua_isnumber(L, index)) {
457 paint->setAlpha(SkScalarRoundToInt(lua2scalar(L, index) * 255));
458 return paint;
reedf355df52014-10-12 12:18:40 -0700459 } else if (lua_isuserdata(L, index)) {
reed485557f2014-10-12 10:36:47 -0700460 const SkPaint* ptr = get_obj<SkPaint>(L, index);
461 if (ptr) {
462 *paint = *ptr;
463 return paint;
464 }
465 }
halcanary96fcdcc2015-08-27 07:41:13 -0700466 return nullptr;
reed485557f2014-10-12 10:36:47 -0700467}
468
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000469static int lcanvas_drawImage(lua_State* L) {
470 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
471 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700472 if (nullptr == image) {
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000473 return 0;
474 }
475 SkScalar x = lua2scalar(L, 3);
476 SkScalar y = lua2scalar(L, 4);
477
478 SkPaint paint;
reed485557f2014-10-12 10:36:47 -0700479 canvas->drawImage(image, x, y, lua2OptionalPaint(L, 5, &paint));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000480 return 0;
481}
482
reedba5fb932014-10-10 15:28:19 -0700483static int lcanvas_drawImageRect(lua_State* L) {
484 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
485 SkImage* image = get_ref<SkImage>(L, 2);
halcanary96fcdcc2015-08-27 07:41:13 -0700486 if (nullptr == image) {
reedba5fb932014-10-10 15:28:19 -0700487 return 0;
488 }
489
490 SkRect srcR, dstR;
halcanary96fcdcc2015-08-27 07:41:13 -0700491 SkRect* srcRPtr = nullptr;
reedba5fb932014-10-10 15:28:19 -0700492 if (!lua_isnil(L, 3)) {
493 srcRPtr = lua2rect(L, 3, &srcR);
494 }
495 lua2rect(L, 4, &dstR);
mtklein8aacf202014-12-18 13:29:54 -0800496
reedba5fb932014-10-10 15:28:19 -0700497 SkPaint paint;
reede47829b2015-08-06 10:02:53 -0700498 canvas->legacy_drawImageRect(image, srcRPtr, dstR, lua2OptionalPaint(L, 5, &paint));
reedba5fb932014-10-10 15:28:19 -0700499 return 0;
500}
501
reed7a72c672014-11-07 10:23:55 -0800502static int lcanvas_drawPatch(lua_State* L) {
503 SkPoint cubics[12];
504 SkColor colorStorage[4];
505 SkPoint texStorage[4];
506
halcanary96fcdcc2015-08-27 07:41:13 -0700507 const SkColor* colors = nullptr;
508 const SkPoint* texs = nullptr;
reed7a72c672014-11-07 10:23:55 -0800509
510 getarray_points(L, 2, cubics, 12);
511
512 colorStorage[0] = SK_ColorRED;
513 colorStorage[1] = SK_ColorGREEN;
514 colorStorage[2] = SK_ColorBLUE;
515 colorStorage[3] = SK_ColorGRAY;
516
517 if (lua_isnil(L, 4)) {
518 colors = colorStorage;
519 } else {
520 getarray_points(L, 4, texStorage, 4);
521 texs = texStorage;
522 }
523
Mike Reed7d954ad2016-10-28 15:42:34 -0400524 get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, *get_obj<SkPaint>(L, 5));
reed7a72c672014-11-07 10:23:55 -0800525 return 0;
526}
527
reed@google.comfd345872013-05-22 20:53:42 +0000528static int lcanvas_drawPath(lua_State* L) {
529 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2),
530 *get_obj<SkPaint>(L, 3));
531 return 0;
532}
533
reed96affcd2014-10-13 12:38:04 -0700534// drawPicture(pic, x, y, paint)
535static int lcanvas_drawPicture(lua_State* L) {
536 SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
537 SkPicture* picture = get_ref<SkPicture>(L, 2);
538 SkScalar x = lua2scalar_def(L, 3, 0);
539 SkScalar y = lua2scalar_def(L, 4, 0);
halcanary96fcdcc2015-08-27 07:41:13 -0700540 SkMatrix matrix, *matrixPtr = nullptr;
reed96affcd2014-10-13 12:38:04 -0700541 if (x || y) {
542 matrix.setTranslate(x, y);
543 matrixPtr = &matrix;
544 }
545 SkPaint paint;
546 canvas->drawPicture(picture, matrixPtr, lua2OptionalPaint(L, 5, &paint));
547 return 0;
548}
549
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000550static int lcanvas_drawText(lua_State* L) {
551 if (lua_gettop(L) < 5) {
552 return 0;
553 }
554
555 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
556 size_t len;
557 const char* text = lua_tolstring(L, 2, &len);
558 get_ref<SkCanvas>(L, 1)->drawText(text, len,
559 lua2scalar(L, 3), lua2scalar(L, 4),
560 *get_obj<SkPaint>(L, 5));
561 }
562 return 0;
563}
564
reed1b6ab442014-11-03 19:55:41 -0800565static int lcanvas_drawTextBlob(lua_State* L) {
566 const SkTextBlob* blob = get_ref<SkTextBlob>(L, 2);
567 SkScalar x = lua2scalar(L, 3);
568 SkScalar y = lua2scalar(L, 4);
569 const SkPaint& paint = *get_obj<SkPaint>(L, 5);
570 get_ref<SkCanvas>(L, 1)->drawTextBlob(blob, x, y, paint);
571 return 0;
572}
573
reed@google.com74ce6f02013-05-22 15:13:18 +0000574static int lcanvas_getSaveCount(lua_State* L) {
575 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
576 return 1;
577}
578
579static int lcanvas_getTotalMatrix(lua_State* L) {
580 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix());
581 return 1;
582}
583
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000584static int lcanvas_save(lua_State* L) {
585 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
586 return 1;
587}
588
reed86217d82014-10-25 20:44:40 -0700589static int lcanvas_saveLayer(lua_State* L) {
590 SkPaint paint;
halcanary96fcdcc2015-08-27 07:41:13 -0700591 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->saveLayer(nullptr, lua2OptionalPaint(L, 2, &paint)));
reed86217d82014-10-25 20:44:40 -0700592 return 1;
593}
594
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000595static int lcanvas_restore(lua_State* L) {
596 get_ref<SkCanvas>(L, 1)->restore();
597 return 0;
598}
599
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000600static int lcanvas_scale(lua_State* L) {
601 SkScalar sx = lua2scalar_def(L, 2, 1);
602 SkScalar sy = lua2scalar_def(L, 3, sx);
603 get_ref<SkCanvas>(L, 1)->scale(sx, sy);
604 return 0;
605}
606
reed@google.com3597b732013-05-22 20:12:50 +0000607static int lcanvas_translate(lua_State* L) {
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000608 SkScalar tx = lua2scalar_def(L, 2, 0);
609 SkScalar ty = lua2scalar_def(L, 3, 0);
610 get_ref<SkCanvas>(L, 1)->translate(tx, ty);
611 return 0;
612}
613
614static int lcanvas_rotate(lua_State* L) {
615 SkScalar degrees = lua2scalar_def(L, 2, 0);
616 get_ref<SkCanvas>(L, 1)->rotate(degrees);
reed@google.com3597b732013-05-22 20:12:50 +0000617 return 0;
618}
619
reedbdc49ae2014-10-14 09:34:52 -0700620static int lcanvas_concat(lua_State* L) {
621 get_ref<SkCanvas>(L, 1)->concat(*get_obj<SkMatrix>(L, 2));
622 return 0;
623}
624
reed485557f2014-10-12 10:36:47 -0700625static int lcanvas_newSurface(lua_State* L) {
626 int width = lua2int_def(L, 2, 0);
reed7a72c672014-11-07 10:23:55 -0800627 int height = lua2int_def(L, 3, 0);
reed485557f2014-10-12 10:36:47 -0700628 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
reede8f30622016-03-23 18:59:25 -0700629 auto surface = get_ref<SkCanvas>(L, 1)->makeSurface(info);
halcanary96fcdcc2015-08-27 07:41:13 -0700630 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -0700631 lua_pushnil(L);
632 } else {
reede8f30622016-03-23 18:59:25 -0700633 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -0700634 }
635 return 1;
636}
637
reed@google.com74ce6f02013-05-22 15:13:18 +0000638static int lcanvas_gc(lua_State* L) {
Mike Reed5df49342016-11-12 08:06:55 -0600639 // don't know how to track a ptr...
reed@google.com74ce6f02013-05-22 15:13:18 +0000640 return 0;
641}
642
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000643const struct luaL_Reg gSkCanvas_Methods[] = {
reedf355df52014-10-12 12:18:40 -0700644 { "clear", lcanvas_clear },
reed@google.com74ce6f02013-05-22 15:13:18 +0000645 { "drawColor", lcanvas_drawColor },
reed9fbc3f32014-10-21 07:12:58 -0700646 { "drawPaint", lcanvas_drawPaint },
reed@google.com74ce6f02013-05-22 15:13:18 +0000647 { "drawRect", lcanvas_drawRect },
648 { "drawOval", lcanvas_drawOval },
649 { "drawCircle", lcanvas_drawCircle },
mike@reedtribe.org792bbd12013-06-11 02:20:28 +0000650 { "drawImage", lcanvas_drawImage },
reedba5fb932014-10-10 15:28:19 -0700651 { "drawImageRect", lcanvas_drawImageRect },
reed7a72c672014-11-07 10:23:55 -0800652 { "drawPatch", lcanvas_drawPatch },
reed@google.comfd345872013-05-22 20:53:42 +0000653 { "drawPath", lcanvas_drawPath },
reed96affcd2014-10-13 12:38:04 -0700654 { "drawPicture", lcanvas_drawPicture },
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000655 { "drawText", lcanvas_drawText },
reed1b6ab442014-11-03 19:55:41 -0800656 { "drawTextBlob", lcanvas_drawTextBlob },
reed@google.com74ce6f02013-05-22 15:13:18 +0000657 { "getSaveCount", lcanvas_getSaveCount },
658 { "getTotalMatrix", lcanvas_getTotalMatrix },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000659 { "save", lcanvas_save },
reed86217d82014-10-25 20:44:40 -0700660 { "saveLayer", lcanvas_saveLayer },
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000661 { "restore", lcanvas_restore },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000662 { "scale", lcanvas_scale },
reed@google.com3597b732013-05-22 20:12:50 +0000663 { "translate", lcanvas_translate },
mike@reedtribe.org1d32cc62013-06-13 01:28:56 +0000664 { "rotate", lcanvas_rotate },
reedbdc49ae2014-10-14 09:34:52 -0700665 { "concat", lcanvas_concat },
reed485557f2014-10-12 10:36:47 -0700666
667 { "newSurface", lcanvas_newSurface },
668
reed@google.com74ce6f02013-05-22 15:13:18 +0000669 { "__gc", lcanvas_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700670 { nullptr, nullptr }
reed@google.com74ce6f02013-05-22 15:13:18 +0000671};
672
673///////////////////////////////////////////////////////////////////////////////
674
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000675static int ldocument_beginPage(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -0700676 const SkRect* contentPtr = nullptr;
Mike Reed7ff6ca52018-01-08 14:45:31 -0500677 push_ptr(L, get_obj<DocHolder>(L, 1)->fDoc->beginPage(lua2scalar(L, 2),
678 lua2scalar(L, 3),
679 contentPtr));
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000680 return 1;
681}
682
683static int ldocument_endPage(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500684 get_obj<DocHolder>(L, 1)->fDoc->endPage();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000685 return 0;
686}
687
688static int ldocument_close(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500689 get_obj<DocHolder>(L, 1)->fDoc->close();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000690 return 0;
691}
692
693static int ldocument_gc(lua_State* L) {
Mike Reed7ff6ca52018-01-08 14:45:31 -0500694 get_obj<DocHolder>(L, 1)->~DocHolder();
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000695 return 0;
696}
697
Mike Reed7ff6ca52018-01-08 14:45:31 -0500698static const struct luaL_Reg gDocHolder_Methods[] = {
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000699 { "beginPage", ldocument_beginPage },
700 { "endPage", ldocument_endPage },
701 { "close", ldocument_close },
702 { "__gc", ldocument_gc },
halcanary96fcdcc2015-08-27 07:41:13 -0700703 { nullptr, nullptr }
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000704};
705
706///////////////////////////////////////////////////////////////////////////////
707
reed@google.com74ce6f02013-05-22 15:13:18 +0000708static int lpaint_isAntiAlias(lua_State* L) {
709 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias());
710 return 1;
711}
712
713static int lpaint_setAntiAlias(lua_State* L) {
reed@google.com88c9ec92013-05-22 15:43:21 +0000714 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2));
reed@google.com74ce6f02013-05-22 15:13:18 +0000715 return 0;
716}
717
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000718static int lpaint_isDither(lua_State* L) {
719 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
720 return 1;
721}
722
reedbb8a0ab2014-11-03 22:32:07 -0800723static int lpaint_setDither(lua_State* L) {
724 get_obj<SkPaint>(L, 1)->setDither(lua2bool(L, 2));
725 return 0;
726}
727
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000728static int lpaint_isFakeBoldText(lua_State* L) {
729 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
730 return 1;
731}
732
733static int lpaint_isLinearText(lua_State* L) {
734 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
735 return 1;
736}
737
738static int lpaint_isSubpixelText(lua_State* L) {
739 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
740 return 1;
741}
742
reed09a1d672014-10-11 13:13:11 -0700743static int lpaint_setSubpixelText(lua_State* L) {
744 get_obj<SkPaint>(L, 1)->setSubpixelText(lua2bool(L, 2));
745 return 1;
746}
747
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000748static int lpaint_isDevKernText(lua_State* L) {
749 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
750 return 1;
751}
752
753static int lpaint_isLCDRenderText(lua_State* L) {
754 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
755 return 1;
756}
757
reed36c9c112014-11-04 10:58:42 -0800758static int lpaint_setLCDRenderText(lua_State* L) {
759 get_obj<SkPaint>(L, 1)->setLCDRenderText(lua2bool(L, 2));
760 return 1;
761}
762
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000763static int lpaint_isEmbeddedBitmapText(lua_State* L) {
764 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
765 return 1;
766}
767
768static int lpaint_isAutohinted(lua_State* L) {
769 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
770 return 1;
771}
772
773static int lpaint_isVerticalText(lua_State* L) {
774 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
775 return 1;
776}
777
reed468b1812014-10-19 11:42:54 -0700778static int lpaint_getAlpha(lua_State* L) {
779 SkLua(L).pushScalar(byte2unit(get_obj<SkPaint>(L, 1)->getAlpha()));
780 return 1;
781}
782
783static int lpaint_setAlpha(lua_State* L) {
784 get_obj<SkPaint>(L, 1)->setAlpha(unit2byte(lua2scalar(L, 2)));
785 return 0;
786}
787
reed@google.com74ce6f02013-05-22 15:13:18 +0000788static int lpaint_getColor(lua_State* L) {
789 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
790 return 1;
791}
792
793static int lpaint_setColor(lua_State* L) {
794 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2));
795 return 0;
796}
797
reed@google.come3823fd2013-05-30 18:55:14 +0000798static int lpaint_getTextSize(lua_State* L) {
799 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
800 return 1;
801}
802
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000803static int lpaint_getTextScaleX(lua_State* L) {
804 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
805 return 1;
806}
807
808static int lpaint_getTextSkewX(lua_State* L) {
809 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
810 return 1;
811}
812
reed@google.come3823fd2013-05-30 18:55:14 +0000813static int lpaint_setTextSize(lua_State* L) {
814 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
815 return 0;
816}
817
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000818static int lpaint_getTypeface(lua_State* L) {
819 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface());
820 return 1;
821}
822
823static int lpaint_setTypeface(lua_State* L) {
bungeman13b9c952016-05-12 10:09:30 -0700824 get_obj<SkPaint>(L, 1)->setTypeface(sk_ref_sp(get_ref<SkTypeface>(L, 2)));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +0000825 return 0;
826}
827
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000828static int lpaint_getHinting(lua_State* L) {
829 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
830 return 1;
831}
832
reed93a12152015-03-16 10:08:34 -0700833static int lpaint_getFilterQuality(lua_State* L) {
834 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getFilterQuality());
reed7a72c672014-11-07 10:23:55 -0800835 return 1;
836}
837
reed93a12152015-03-16 10:08:34 -0700838static int lpaint_setFilterQuality(lua_State* L) {
reed7a72c672014-11-07 10:23:55 -0800839 int level = lua2int_def(L, 2, -1);
840 if (level >= 0 && level <= 3) {
reed93a12152015-03-16 10:08:34 -0700841 get_obj<SkPaint>(L, 1)->setFilterQuality((SkFilterQuality)level);
reed7a72c672014-11-07 10:23:55 -0800842 }
843 return 0;
844}
845
reed@google.come3823fd2013-05-30 18:55:14 +0000846static int lpaint_getFontID(lua_State* L) {
847 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
848 SkLua(L).pushU32(SkTypeface::UniqueID(face));
849 return 1;
850}
851
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000852static const struct {
853 const char* fLabel;
854 SkPaint::Align fAlign;
855} gAlignRec[] = {
856 { "left", SkPaint::kLeft_Align },
857 { "center", SkPaint::kCenter_Align },
858 { "right", SkPaint::kRight_Align },
859};
860
861static int lpaint_getTextAlign(lua_State* L) {
862 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign();
863 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
864 if (gAlignRec[i].fAlign == align) {
865 lua_pushstring(L, gAlignRec[i].fLabel);
866 return 1;
867 }
868 }
869 return 0;
870}
871
872static int lpaint_setTextAlign(lua_State* L) {
873 if (lua_isstring(L, 2)) {
874 size_t len;
875 const char* label = lua_tolstring(L, 2, &len);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000876
mike@reedtribe.orgfb858242013-06-08 16:39:44 +0000877 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) {
878 if (!strcmp(gAlignRec[i].fLabel, label)) {
879 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign);
880 break;
881 }
882 }
883 }
884 return 0;
885}
886
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000887static int lpaint_getStroke(lua_State* L) {
888 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle());
889 return 1;
890}
891
892static int lpaint_setStroke(lua_State* L) {
893 SkPaint::Style style;
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000894
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000895 if (lua_toboolean(L, 2)) {
896 style = SkPaint::kStroke_Style;
897 } else {
898 style = SkPaint::kFill_Style;
899 }
900 get_obj<SkPaint>(L, 1)->setStyle(style);
901 return 0;
902}
903
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000904static int lpaint_getStrokeCap(lua_State* L) {
905 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
906 return 1;
907}
908
909static int lpaint_getStrokeJoin(lua_State* L) {
910 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
911 return 1;
912}
913
914static int lpaint_getTextEncoding(lua_State* L) {
commit-bot@chromium.org641bcc32013-12-19 10:39:59 +0000915 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000916 return 1;
917}
918
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000919static int lpaint_getStrokeWidth(lua_State* L) {
920 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
921 return 1;
922}
923
924static int lpaint_setStrokeWidth(lua_State* L) {
925 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2));
926 return 0;
927}
928
commit-bot@chromium.org1cd71fb2013-12-18 18:28:07 +0000929static int lpaint_getStrokeMiter(lua_State* L) {
930 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
931 return 1;
932}
933
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000934static int lpaint_measureText(lua_State* L) {
935 if (lua_isstring(L, 2)) {
936 size_t len;
937 const char* text = lua_tolstring(L, 2, &len);
938 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len));
939 return 1;
940 }
941 return 0;
942}
943
944struct FontMetrics {
945 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
946 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
947 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
948 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
949 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
950 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
951 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
952 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
953 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
954};
955
956static int lpaint_getFontMetrics(lua_State* L) {
957 SkPaint::FontMetrics fm;
958 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm);
skia.committer@gmail.com370c5342013-06-09 07:01:05 +0000959
mike@reedtribe.org73d9f1c2013-06-09 01:54:56 +0000960 lua_newtable(L);
961 setfield_scalar(L, "top", fm.fTop);
962 setfield_scalar(L, "ascent", fm.fAscent);
963 setfield_scalar(L, "descent", fm.fDescent);
964 setfield_scalar(L, "bottom", fm.fBottom);
965 setfield_scalar(L, "leading", fm.fLeading);
966 SkLua(L).pushScalar(height);
967 return 2;
968}
969
reed@google.com29563872013-07-10 21:23:49 +0000970static int lpaint_getEffects(lua_State* L) {
971 const SkPaint* paint = get_obj<SkPaint>(L, 1);
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000972
reed@google.com29563872013-07-10 21:23:49 +0000973 lua_newtable(L);
reed468b1812014-10-19 11:42:54 -0700974 setfield_bool_if(L, "looper", !!paint->getLooper());
975 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
976 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer());
977 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#include "SkTextBox.h"
1965// Sk.newTextBlob(text, rect, paint)
1966static int lsk_newTextBlob(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001967 const char* text = lua_tolstring(L, 1, nullptr);
reed1b6ab442014-11-03 19:55:41 -08001968 SkRect bounds;
1969 lua2rect(L, 2, &bounds);
1970 const SkPaint& paint = *get_obj<SkPaint>(L, 3);
1971
1972 SkTextBox box;
1973 box.setMode(SkTextBox::kLineBreak_Mode);
1974 box.setBox(bounds);
1975 box.setText(text, strlen(text), paint);
1976
1977 SkScalar newBottom;
fmalita37283c22016-09-13 10:00:23 -07001978 push_ref<SkTextBlob>(L, box.snapshotTextBlob(&newBottom));
reed1b6ab442014-11-03 19:55:41 -08001979 SkLua(L).pushScalar(newBottom);
1980 return 2;
1981}
1982
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001983static int lsk_newTypeface(lua_State* L) {
halcanary96fcdcc2015-08-27 07:41:13 -07001984 const char* name = nullptr;
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001985 SkFontStyle style;
skia.committer@gmail.com63193672013-06-08 07:01:13 +00001986
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001987 int count = lua_gettop(L);
1988 if (count > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001989 name = lua_tolstring(L, 1, nullptr);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001990 if (count > 1) {
1991 SkFontStyle* passedStyle = get_obj<SkFontStyle>(L, 2);
1992 if (passedStyle) {
1993 style = *passedStyle;
1994 }
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001995 }
1996 }
1997
Ben Wagnerc6c10b42017-08-07 09:56:21 -04001998 sk_sp<SkTypeface> face(SkTypeface::MakeFromName(name, style));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00001999// SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt());
halcanary96fcdcc2015-08-27 07:41:13 -07002000 if (nullptr == face) {
bungeman13b9c952016-05-12 10:09:30 -07002001 face = SkTypeface::MakeDefault();
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002002 }
bungeman13b9c952016-05-12 10:09:30 -07002003 push_ref(L, std::move(face));
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002004 return 1;
2005}
reed@google.com3597b732013-05-22 20:12:50 +00002006
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002007static int lsk_newFontStyle(lua_State* L) {
2008 int count = lua_gettop(L);
2009 int weight = SkFontStyle::kNormal_Weight;
2010 int width = SkFontStyle::kNormal_Width;
2011 SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
2012 if (count >= 1 && lua_isnumber(L, 1)) {
2013 weight = lua_tointegerx(L, 1, nullptr);
2014 }
2015 if (count >= 2 && lua_isnumber(L, 2)) {
2016 width = lua_tointegerx(L, 2, nullptr);
2017 }
2018 if (count >= 3 && lua_isnumber(L, 3)) {
2019 slant = static_cast<SkFontStyle::Slant>(lua_tointegerx(L, 3, nullptr));
2020 }
2021 push_new<SkFontStyle>(L, weight, width, slant);
2022 return 1;
2023}
2024
reed485557f2014-10-12 10:36:47 -07002025static int lsk_newRasterSurface(lua_State* L) {
reed7b864662014-11-04 13:24:47 -08002026 int width = lua2int_def(L, 1, 0);
reed485557f2014-10-12 10:36:47 -07002027 int height = lua2int_def(L, 2, 0);
2028 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
robertphillips702edbd2015-06-23 06:26:08 -07002029 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
reede8f30622016-03-23 18:59:25 -07002030 auto surface = SkSurface::MakeRaster(info, &props);
halcanary96fcdcc2015-08-27 07:41:13 -07002031 if (nullptr == surface) {
reed485557f2014-10-12 10:36:47 -07002032 lua_pushnil(L);
2033 } else {
reede8f30622016-03-23 18:59:25 -07002034 push_ref(L, surface);
reed485557f2014-10-12 10:36:47 -07002035 }
2036 return 1;
2037}
2038
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002039static int lsk_loadImage(lua_State* L) {
2040 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) {
halcanary96fcdcc2015-08-27 07:41:13 -07002041 const char* name = lua_tolstring(L, 1, nullptr);
reed9ce9d672016-03-17 10:51:11 -07002042 sk_sp<SkData> data(SkData::MakeFromFileName(name));
2043 if (data) {
2044 auto image = SkImage::MakeFromEncoded(std::move(data));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002045 if (image) {
reed9ce9d672016-03-17 10:51:11 -07002046 push_ref(L, std::move(image));
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002047 return 1;
2048 }
2049 }
2050 }
2051 return 0;
2052}
2053
reed@google.com3597b732013-05-22 20:12:50 +00002054static void register_Sk(lua_State* L) {
2055 lua_newtable(L);
2056 lua_pushvalue(L, -1);
2057 lua_setglobal(L, "Sk");
2058 // the Sk table is still on top
2059
mike@reedtribe.orgfb858242013-06-08 16:39:44 +00002060 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002061 setfield_function(L, "loadImage", lsk_loadImage);
reed468b1812014-10-19 11:42:54 -07002062 setfield_function(L, "newBlurImageFilter", lsk_newBlurImageFilter);
reed9fbc3f32014-10-21 07:12:58 -07002063 setfield_function(L, "newLinearGradient", lsk_newLinearGradient);
reedbdc49ae2014-10-14 09:34:52 -07002064 setfield_function(L, "newMatrix", lsk_newMatrix);
reed@google.com3597b732013-05-22 20:12:50 +00002065 setfield_function(L, "newPaint", lsk_newPaint);
2066 setfield_function(L, "newPath", lsk_newPath);
reed96affcd2014-10-13 12:38:04 -07002067 setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
reed@google.com3597b732013-05-22 20:12:50 +00002068 setfield_function(L, "newRRect", lsk_newRRect);
reed485557f2014-10-12 10:36:47 -07002069 setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
reed1b6ab442014-11-03 19:55:41 -08002070 setfield_function(L, "newTextBlob", lsk_newTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002071 setfield_function(L, "newTypeface", lsk_newTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002072 setfield_function(L, "newFontStyle", lsk_newFontStyle);
reed@google.com3597b732013-05-22 20:12:50 +00002073 lua_pop(L, 1); // pop off the Sk table
2074}
2075
reed@google.com74ce6f02013-05-22 15:13:18 +00002076#define REG_CLASS(L, C) \
2077 do { \
reed@google.com3597b732013-05-22 20:12:50 +00002078 luaL_newmetatable(L, get_mtname<C>()); \
reed@google.com74ce6f02013-05-22 15:13:18 +00002079 lua_pushvalue(L, -1); \
2080 lua_setfield(L, -2, "__index"); \
2081 luaL_setfuncs(L, g##C##_Methods, 0); \
2082 lua_pop(L, 1); /* pop off the meta-table */ \
2083 } while (0)
2084
2085void SkLua::Load(lua_State* L) {
reed@google.com3597b732013-05-22 20:12:50 +00002086 register_Sk(L);
reed@google.com74ce6f02013-05-22 15:13:18 +00002087 REG_CLASS(L, SkCanvas);
reed22a517f2015-12-04 20:45:59 -08002088 REG_CLASS(L, SkColorFilter);
Mike Reed7ff6ca52018-01-08 14:45:31 -05002089 REG_CLASS(L, DocHolder);
mike@reedtribe.org792bbd12013-06-11 02:20:28 +00002090 REG_CLASS(L, SkImage);
reed468b1812014-10-19 11:42:54 -07002091 REG_CLASS(L, SkImageFilter);
reed1b6ab442014-11-03 19:55:41 -08002092 REG_CLASS(L, SkMatrix);
reed@google.com74ce6f02013-05-22 15:13:18 +00002093 REG_CLASS(L, SkPaint);
commit-bot@chromium.org1301bf32014-03-17 23:09:47 +00002094 REG_CLASS(L, SkPath);
2095 REG_CLASS(L, SkPathEffect);
reed96affcd2014-10-13 12:38:04 -07002096 REG_CLASS(L, SkPicture);
2097 REG_CLASS(L, SkPictureRecorder);
reed@google.com74ce6f02013-05-22 15:13:18 +00002098 REG_CLASS(L, SkRRect);
reed@google.com5fdc9832013-07-24 15:47:52 +00002099 REG_CLASS(L, SkShader);
reed485557f2014-10-12 10:36:47 -07002100 REG_CLASS(L, SkSurface);
reed1b6ab442014-11-03 19:55:41 -08002101 REG_CLASS(L, SkTextBlob);
mike@reedtribe.orge6469f12013-06-08 03:15:47 +00002102 REG_CLASS(L, SkTypeface);
Ben Wagnerc6c10b42017-08-07 09:56:21 -04002103 REG_CLASS(L, SkFontStyle);
reed@google.com74ce6f02013-05-22 15:13:18 +00002104}
zachr@google.com28c27c82013-06-20 17:15:05 +00002105
reed@google.com7bce9982013-06-20 17:40:21 +00002106extern "C" int luaopen_skia(lua_State* L);
zachr@google.com28c27c82013-06-20 17:15:05 +00002107extern "C" int luaopen_skia(lua_State* L) {
2108 SkLua::Load(L);
2109 return 0;
2110}