|
1 /* |
|
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" |
|
9 |
|
10 #if SK_SUPPORT_GPU |
|
11 #include "GrReducedClip.h" |
|
12 #endif |
|
13 |
|
14 #include "SkCanvas.h" |
|
15 #include "SkData.h" |
|
16 #include "SkDocument.h" |
|
17 #include "SkImage.h" |
|
18 #include "SkMatrix.h" |
|
19 #include "SkPaint.h" |
|
20 #include "SkPath.h" |
|
21 #include "SkPixelRef.h" |
|
22 #include "SkRRect.h" |
|
23 #include "SkString.h" |
|
24 #include "SkTypeface.h" |
|
25 |
|
26 extern "C" { |
|
27 #include "lua.h" |
|
28 #include "lualib.h" |
|
29 #include "lauxlib.h" |
|
30 } |
|
31 |
|
32 // return the metatable name for a given class |
|
33 template <typename T> const char* get_mtname(); |
|
34 #define DEF_MTNAME(T) \ |
|
35 template <> const char* get_mtname<T>() { \ |
|
36 return #T "_LuaMetaTableName"; \ |
|
37 } |
|
38 |
|
39 DEF_MTNAME(SkCanvas) |
|
40 DEF_MTNAME(SkDocument) |
|
41 DEF_MTNAME(SkImage) |
|
42 DEF_MTNAME(SkMatrix) |
|
43 DEF_MTNAME(SkRRect) |
|
44 DEF_MTNAME(SkPath) |
|
45 DEF_MTNAME(SkPaint) |
|
46 DEF_MTNAME(SkShader) |
|
47 DEF_MTNAME(SkTypeface) |
|
48 |
|
49 template <typename T> T* push_new(lua_State* L) { |
|
50 T* addr = (T*)lua_newuserdata(L, sizeof(T)); |
|
51 new (addr) T; |
|
52 luaL_getmetatable(L, get_mtname<T>()); |
|
53 lua_setmetatable(L, -2); |
|
54 return addr; |
|
55 } |
|
56 |
|
57 template <typename T> void push_obj(lua_State* L, const T& obj) { |
|
58 new (lua_newuserdata(L, sizeof(T))) T(obj); |
|
59 luaL_getmetatable(L, get_mtname<T>()); |
|
60 lua_setmetatable(L, -2); |
|
61 } |
|
62 |
|
63 template <typename T> void push_ref(lua_State* L, T* ref) { |
|
64 *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref); |
|
65 luaL_getmetatable(L, get_mtname<T>()); |
|
66 lua_setmetatable(L, -2); |
|
67 } |
|
68 |
|
69 template <typename T> T* get_ref(lua_State* L, int index) { |
|
70 return *(T**)luaL_checkudata(L, index, get_mtname<T>()); |
|
71 } |
|
72 |
|
73 template <typename T> T* get_obj(lua_State* L, int index) { |
|
74 return (T*)luaL_checkudata(L, index, get_mtname<T>()); |
|
75 } |
|
76 |
|
77 static bool lua2bool(lua_State* L, int index) { |
|
78 return !!lua_toboolean(L, index); |
|
79 } |
|
80 |
|
81 /////////////////////////////////////////////////////////////////////////////// |
|
82 |
|
83 SkLua::SkLua(const char termCode[]) : fTermCode(termCode), fWeOwnL(true) { |
|
84 fL = luaL_newstate(); |
|
85 luaL_openlibs(fL); |
|
86 SkLua::Load(fL); |
|
87 } |
|
88 |
|
89 SkLua::SkLua(lua_State* L) : fL(L), fWeOwnL(false) {} |
|
90 |
|
91 SkLua::~SkLua() { |
|
92 if (fWeOwnL) { |
|
93 if (fTermCode.size() > 0) { |
|
94 lua_getglobal(fL, fTermCode.c_str()); |
|
95 if (lua_pcall(fL, 0, 0, 0) != LUA_OK) { |
|
96 SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); |
|
97 } |
|
98 } |
|
99 lua_close(fL); |
|
100 } |
|
101 } |
|
102 |
|
103 bool SkLua::runCode(const char code[]) { |
|
104 int err = luaL_loadstring(fL, code) || lua_pcall(fL, 0, 0, 0); |
|
105 if (err) { |
|
106 SkDebugf("--- lua failed: %s\n", lua_tostring(fL, -1)); |
|
107 return false; |
|
108 } |
|
109 return true; |
|
110 } |
|
111 |
|
112 bool SkLua::runCode(const void* code, size_t size) { |
|
113 SkString str((const char*)code, size); |
|
114 return this->runCode(str.c_str()); |
|
115 } |
|
116 |
|
117 /////////////////////////////////////////////////////////////////////////////// |
|
118 |
|
119 #define CHECK_SETFIELD(key) do if (key) lua_setfield(fL, -2, key); while (0) |
|
120 |
|
121 static void setfield_bool_if(lua_State* L, const char key[], bool pred) { |
|
122 if (pred) { |
|
123 lua_pushboolean(L, true); |
|
124 lua_setfield(L, -2, key); |
|
125 } |
|
126 } |
|
127 |
|
128 static void setfield_string(lua_State* L, const char key[], const char value[]) { |
|
129 lua_pushstring(L, value); |
|
130 lua_setfield(L, -2, key); |
|
131 } |
|
132 |
|
133 static void setfield_number(lua_State* L, const char key[], double value) { |
|
134 lua_pushnumber(L, value); |
|
135 lua_setfield(L, -2, key); |
|
136 } |
|
137 |
|
138 static void setfield_boolean(lua_State* L, const char key[], bool value) { |
|
139 lua_pushboolean(L, value); |
|
140 lua_setfield(L, -2, key); |
|
141 } |
|
142 |
|
143 static void setfield_scalar(lua_State* L, const char key[], SkScalar value) { |
|
144 setfield_number(L, key, SkScalarToLua(value)); |
|
145 } |
|
146 |
|
147 static void setfield_function(lua_State* L, |
|
148 const char key[], lua_CFunction value) { |
|
149 lua_pushcfunction(L, value); |
|
150 lua_setfield(L, -2, key); |
|
151 } |
|
152 |
|
153 static void setarray_number(lua_State* L, int index, double value) { |
|
154 lua_pushnumber(L, value); |
|
155 lua_rawseti(L, -2, index); |
|
156 } |
|
157 |
|
158 void SkLua::pushBool(bool value, const char key[]) { |
|
159 lua_pushboolean(fL, value); |
|
160 CHECK_SETFIELD(key); |
|
161 } |
|
162 |
|
163 void SkLua::pushString(const char str[], const char key[]) { |
|
164 lua_pushstring(fL, str); |
|
165 CHECK_SETFIELD(key); |
|
166 } |
|
167 |
|
168 void SkLua::pushString(const char str[], size_t length, const char key[]) { |
|
169 // TODO: how to do this w/o making a copy? |
|
170 SkString s(str, length); |
|
171 lua_pushstring(fL, s.c_str()); |
|
172 CHECK_SETFIELD(key); |
|
173 } |
|
174 |
|
175 void SkLua::pushString(const SkString& str, const char key[]) { |
|
176 lua_pushstring(fL, str.c_str()); |
|
177 CHECK_SETFIELD(key); |
|
178 } |
|
179 |
|
180 void SkLua::pushColor(SkColor color, const char key[]) { |
|
181 lua_newtable(fL); |
|
182 setfield_number(fL, "a", SkColorGetA(color) / 255.0); |
|
183 setfield_number(fL, "r", SkColorGetR(color) / 255.0); |
|
184 setfield_number(fL, "g", SkColorGetG(color) / 255.0); |
|
185 setfield_number(fL, "b", SkColorGetB(color) / 255.0); |
|
186 CHECK_SETFIELD(key); |
|
187 } |
|
188 |
|
189 void SkLua::pushU32(uint32_t value, const char key[]) { |
|
190 lua_pushnumber(fL, (double)value); |
|
191 CHECK_SETFIELD(key); |
|
192 } |
|
193 |
|
194 void SkLua::pushScalar(SkScalar value, const char key[]) { |
|
195 lua_pushnumber(fL, SkScalarToLua(value)); |
|
196 CHECK_SETFIELD(key); |
|
197 } |
|
198 |
|
199 void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) { |
|
200 lua_newtable(fL); |
|
201 for (int i = 0; i < count; ++i) { |
|
202 // make it base-1 to match lua convention |
|
203 setarray_number(fL, i + 1, (double)array[i]); |
|
204 } |
|
205 CHECK_SETFIELD(key); |
|
206 } |
|
207 |
|
208 void SkLua::pushRect(const SkRect& r, const char key[]) { |
|
209 lua_newtable(fL); |
|
210 setfield_scalar(fL, "left", r.fLeft); |
|
211 setfield_scalar(fL, "top", r.fTop); |
|
212 setfield_scalar(fL, "right", r.fRight); |
|
213 setfield_scalar(fL, "bottom", r.fBottom); |
|
214 CHECK_SETFIELD(key); |
|
215 } |
|
216 |
|
217 void SkLua::pushRRect(const SkRRect& rr, const char key[]) { |
|
218 push_obj(fL, rr); |
|
219 CHECK_SETFIELD(key); |
|
220 } |
|
221 |
|
222 void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) { |
|
223 push_obj(fL, matrix); |
|
224 CHECK_SETFIELD(key); |
|
225 } |
|
226 |
|
227 void SkLua::pushPaint(const SkPaint& paint, const char key[]) { |
|
228 push_obj(fL, paint); |
|
229 CHECK_SETFIELD(key); |
|
230 } |
|
231 |
|
232 void SkLua::pushPath(const SkPath& path, const char key[]) { |
|
233 push_obj(fL, path); |
|
234 CHECK_SETFIELD(key); |
|
235 } |
|
236 |
|
237 void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) { |
|
238 push_ref(fL, canvas); |
|
239 CHECK_SETFIELD(key); |
|
240 } |
|
241 |
|
242 static const char* element_type(SkClipStack::Element::Type type) { |
|
243 switch (type) { |
|
244 case SkClipStack::Element::kEmpty_Type: |
|
245 return "empty"; |
|
246 case SkClipStack::Element::kRect_Type: |
|
247 return "rect"; |
|
248 case SkClipStack::Element::kRRect_Type: |
|
249 return "rrect"; |
|
250 case SkClipStack::Element::kPath_Type: |
|
251 return "path"; |
|
252 } |
|
253 return "unknown"; |
|
254 } |
|
255 |
|
256 static const char* region_op(SkRegion::Op op) { |
|
257 switch (op) { |
|
258 case SkRegion::kDifference_Op: |
|
259 return "difference"; |
|
260 case SkRegion::kIntersect_Op: |
|
261 return "intersect"; |
|
262 case SkRegion::kUnion_Op: |
|
263 return "union"; |
|
264 case SkRegion::kXOR_Op: |
|
265 return "xor"; |
|
266 case SkRegion::kReverseDifference_Op: |
|
267 return "reverse-difference"; |
|
268 case SkRegion::kReplace_Op: |
|
269 return "replace"; |
|
270 } |
|
271 return "unknown"; |
|
272 } |
|
273 |
|
274 void SkLua::pushClipStack(const SkClipStack& stack, const char* key) { |
|
275 lua_newtable(fL); |
|
276 SkClipStack::B2TIter iter(stack); |
|
277 const SkClipStack::Element* element; |
|
278 int i = 0; |
|
279 while (NULL != (element = iter.next())) { |
|
280 this->pushClipStackElement(*element); |
|
281 lua_rawseti(fL, -2, ++i); |
|
282 } |
|
283 CHECK_SETFIELD(key); |
|
284 } |
|
285 |
|
286 void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) { |
|
287 lua_newtable(fL); |
|
288 SkClipStack::Element::Type type = element.getType(); |
|
289 this->pushString(element_type(type), "type"); |
|
290 switch (type) { |
|
291 case SkClipStack::Element::kEmpty_Type: |
|
292 break; |
|
293 case SkClipStack::Element::kRect_Type: |
|
294 this->pushRect(element.getRect(), "rect"); |
|
295 break; |
|
296 case SkClipStack::Element::kRRect_Type: |
|
297 this->pushRRect(element.getRRect(), "rrect"); |
|
298 break; |
|
299 case SkClipStack::Element::kPath_Type: |
|
300 this->pushPath(element.getPath(), "path"); |
|
301 break; |
|
302 } |
|
303 this->pushString(region_op(element.getOp()), "op"); |
|
304 this->pushBool(element.isAA(), "aa"); |
|
305 CHECK_SETFIELD(key); |
|
306 } |
|
307 |
|
308 |
|
309 /////////////////////////////////////////////////////////////////////////////// |
|
310 /////////////////////////////////////////////////////////////////////////////// |
|
311 |
|
312 static SkScalar lua2scalar(lua_State* L, int index) { |
|
313 SkASSERT(lua_isnumber(L, index)); |
|
314 return SkLuaToScalar(lua_tonumber(L, index)); |
|
315 } |
|
316 |
|
317 static SkScalar lua2scalar_def(lua_State* L, int index, SkScalar defaultValue) { |
|
318 if (lua_isnumber(L, index)) { |
|
319 return SkLuaToScalar(lua_tonumber(L, index)); |
|
320 } else { |
|
321 return defaultValue; |
|
322 } |
|
323 } |
|
324 |
|
325 static SkScalar getfield_scalar(lua_State* L, int index, const char key[]) { |
|
326 SkASSERT(lua_istable(L, index)); |
|
327 lua_pushstring(L, key); |
|
328 lua_gettable(L, index); |
|
329 |
|
330 SkScalar value = lua2scalar(L, -1); |
|
331 lua_pop(L, 1); |
|
332 return value; |
|
333 } |
|
334 |
|
335 static SkScalar getfield_scalar_default(lua_State* L, int index, const char key[], SkScalar def) { |
|
336 SkASSERT(lua_istable(L, index)); |
|
337 lua_pushstring(L, key); |
|
338 lua_gettable(L, index); |
|
339 |
|
340 SkScalar value; |
|
341 if (lua_isnil(L, -1)) { |
|
342 value = def; |
|
343 } else { |
|
344 value = lua2scalar(L, -1); |
|
345 } |
|
346 lua_pop(L, 1); |
|
347 return value; |
|
348 } |
|
349 |
|
350 static U8CPU unit2byte(SkScalar x) { |
|
351 if (x <= 0) { |
|
352 return 0; |
|
353 } else if (x >= 1) { |
|
354 return 255; |
|
355 } else { |
|
356 return SkScalarRoundToInt(x * 255); |
|
357 } |
|
358 } |
|
359 |
|
360 static SkColor lua2color(lua_State* L, int index) { |
|
361 return SkColorSetARGB(unit2byte(getfield_scalar(L, index, "a")), |
|
362 unit2byte(getfield_scalar(L, index, "r")), |
|
363 unit2byte(getfield_scalar(L, index, "g")), |
|
364 unit2byte(getfield_scalar(L, index, "b"))); |
|
365 } |
|
366 |
|
367 static SkRect* lua2rect(lua_State* L, int index, SkRect* rect) { |
|
368 rect->set(getfield_scalar_default(L, index, "left", 0), |
|
369 getfield_scalar_default(L, index, "top", 0), |
|
370 getfield_scalar(L, index, "right"), |
|
371 getfield_scalar(L, index, "bottom")); |
|
372 return rect; |
|
373 } |
|
374 |
|
375 static int lcanvas_drawColor(lua_State* L) { |
|
376 get_ref<SkCanvas>(L, 1)->drawColor(lua2color(L, 2)); |
|
377 return 0; |
|
378 } |
|
379 |
|
380 static int lcanvas_drawRect(lua_State* L) { |
|
381 SkRect rect; |
|
382 get_ref<SkCanvas>(L, 1)->drawRect(*lua2rect(L, 2, &rect), |
|
383 *get_obj<SkPaint>(L, 3)); |
|
384 return 0; |
|
385 } |
|
386 |
|
387 static int lcanvas_drawOval(lua_State* L) { |
|
388 SkRect rect; |
|
389 get_ref<SkCanvas>(L, 1)->drawOval(*lua2rect(L, 2, &rect), |
|
390 *get_obj<SkPaint>(L, 3)); |
|
391 return 0; |
|
392 } |
|
393 |
|
394 static int lcanvas_drawCircle(lua_State* L) { |
|
395 get_ref<SkCanvas>(L, 1)->drawCircle(lua2scalar(L, 2), |
|
396 lua2scalar(L, 3), |
|
397 lua2scalar(L, 4), |
|
398 *get_obj<SkPaint>(L, 5)); |
|
399 return 0; |
|
400 } |
|
401 |
|
402 static int lcanvas_drawImage(lua_State* L) { |
|
403 SkCanvas* canvas = get_ref<SkCanvas>(L, 1); |
|
404 SkImage* image = get_ref<SkImage>(L, 2); |
|
405 if (NULL == image) { |
|
406 return 0; |
|
407 } |
|
408 SkScalar x = lua2scalar(L, 3); |
|
409 SkScalar y = lua2scalar(L, 4); |
|
410 |
|
411 SkPaint paint; |
|
412 const SkPaint* paintPtr = NULL; |
|
413 if (lua_isnumber(L, 5)) { |
|
414 paint.setAlpha(SkScalarRoundToInt(lua2scalar(L, 5) * 255)); |
|
415 paintPtr = &paint; |
|
416 } |
|
417 image->draw(canvas, x, y, paintPtr); |
|
418 return 0; |
|
419 } |
|
420 |
|
421 static int lcanvas_drawPath(lua_State* L) { |
|
422 get_ref<SkCanvas>(L, 1)->drawPath(*get_obj<SkPath>(L, 2), |
|
423 *get_obj<SkPaint>(L, 3)); |
|
424 return 0; |
|
425 } |
|
426 |
|
427 static int lcanvas_drawText(lua_State* L) { |
|
428 if (lua_gettop(L) < 5) { |
|
429 return 0; |
|
430 } |
|
431 |
|
432 if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) { |
|
433 size_t len; |
|
434 const char* text = lua_tolstring(L, 2, &len); |
|
435 get_ref<SkCanvas>(L, 1)->drawText(text, len, |
|
436 lua2scalar(L, 3), lua2scalar(L, 4), |
|
437 *get_obj<SkPaint>(L, 5)); |
|
438 } |
|
439 return 0; |
|
440 } |
|
441 |
|
442 static int lcanvas_getSaveCount(lua_State* L) { |
|
443 lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount()); |
|
444 return 1; |
|
445 } |
|
446 |
|
447 static int lcanvas_getTotalMatrix(lua_State* L) { |
|
448 SkLua(L).pushMatrix(get_ref<SkCanvas>(L, 1)->getTotalMatrix()); |
|
449 return 1; |
|
450 } |
|
451 |
|
452 static int lcanvas_getClipStack(lua_State* L) { |
|
453 SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack()); |
|
454 return 1; |
|
455 } |
|
456 |
|
457 int SkLua::lcanvas_getReducedClipStack(lua_State* L) { |
|
458 #if SK_SUPPORT_GPU |
|
459 const SkCanvas* canvas = get_ref<SkCanvas>(L, 1); |
|
460 SkISize layerSize = canvas->getTopLayerSize(); |
|
461 SkIPoint layerOrigin = canvas->getTopLayerOrigin(); |
|
462 SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY, |
|
463 layerSize.fWidth, layerSize.fHeight); |
|
464 |
|
465 GrReducedClip::ElementList elements; |
|
466 GrReducedClip::InitialState initialState; |
|
467 int32_t genID; |
|
468 SkIRect resultBounds; |
|
469 |
|
470 const SkClipStack& stack = *canvas->getClipStack(); |
|
471 |
|
472 GrReducedClip::ReduceClipStack(stack, |
|
473 queryBounds, |
|
474 &elements, |
|
475 &genID, |
|
476 &initialState, |
|
477 &resultBounds, |
|
478 NULL); |
|
479 |
|
480 GrReducedClip::ElementList::Iter iter(elements); |
|
481 int i = 0; |
|
482 lua_newtable(L); |
|
483 while(NULL != iter.get()) { |
|
484 SkLua(L).pushClipStackElement(*iter.get()); |
|
485 iter.next(); |
|
486 lua_rawseti(L, -2, ++i); |
|
487 } |
|
488 // Currently this only returns the element list to lua, not the initial state or result bounds. |
|
489 // It could return these as additional items on the lua stack. |
|
490 return 1; |
|
491 #else |
|
492 return 0; |
|
493 #endif |
|
494 } |
|
495 |
|
496 static int lcanvas_save(lua_State* L) { |
|
497 lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save()); |
|
498 return 1; |
|
499 } |
|
500 |
|
501 static int lcanvas_restore(lua_State* L) { |
|
502 get_ref<SkCanvas>(L, 1)->restore(); |
|
503 return 0; |
|
504 } |
|
505 |
|
506 static int lcanvas_scale(lua_State* L) { |
|
507 SkScalar sx = lua2scalar_def(L, 2, 1); |
|
508 SkScalar sy = lua2scalar_def(L, 3, sx); |
|
509 get_ref<SkCanvas>(L, 1)->scale(sx, sy); |
|
510 return 0; |
|
511 } |
|
512 |
|
513 static int lcanvas_translate(lua_State* L) { |
|
514 SkScalar tx = lua2scalar_def(L, 2, 0); |
|
515 SkScalar ty = lua2scalar_def(L, 3, 0); |
|
516 get_ref<SkCanvas>(L, 1)->translate(tx, ty); |
|
517 return 0; |
|
518 } |
|
519 |
|
520 static int lcanvas_rotate(lua_State* L) { |
|
521 SkScalar degrees = lua2scalar_def(L, 2, 0); |
|
522 get_ref<SkCanvas>(L, 1)->rotate(degrees); |
|
523 return 0; |
|
524 } |
|
525 |
|
526 static int lcanvas_gc(lua_State* L) { |
|
527 get_ref<SkCanvas>(L, 1)->unref(); |
|
528 return 0; |
|
529 } |
|
530 |
|
531 const struct luaL_Reg gSkCanvas_Methods[] = { |
|
532 { "drawColor", lcanvas_drawColor }, |
|
533 { "drawRect", lcanvas_drawRect }, |
|
534 { "drawOval", lcanvas_drawOval }, |
|
535 { "drawCircle", lcanvas_drawCircle }, |
|
536 { "drawImage", lcanvas_drawImage }, |
|
537 { "drawPath", lcanvas_drawPath }, |
|
538 { "drawText", lcanvas_drawText }, |
|
539 { "getSaveCount", lcanvas_getSaveCount }, |
|
540 { "getTotalMatrix", lcanvas_getTotalMatrix }, |
|
541 { "getClipStack", lcanvas_getClipStack }, |
|
542 #if SK_SUPPORT_GPU |
|
543 { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack }, |
|
544 #endif |
|
545 { "save", lcanvas_save }, |
|
546 { "restore", lcanvas_restore }, |
|
547 { "scale", lcanvas_scale }, |
|
548 { "translate", lcanvas_translate }, |
|
549 { "rotate", lcanvas_rotate }, |
|
550 { "__gc", lcanvas_gc }, |
|
551 { NULL, NULL } |
|
552 }; |
|
553 |
|
554 /////////////////////////////////////////////////////////////////////////////// |
|
555 |
|
556 static int ldocument_beginPage(lua_State* L) { |
|
557 const SkRect* contentPtr = NULL; |
|
558 push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2), |
|
559 lua2scalar(L, 3), |
|
560 contentPtr)); |
|
561 return 1; |
|
562 } |
|
563 |
|
564 static int ldocument_endPage(lua_State* L) { |
|
565 get_ref<SkDocument>(L, 1)->endPage(); |
|
566 return 0; |
|
567 } |
|
568 |
|
569 static int ldocument_close(lua_State* L) { |
|
570 get_ref<SkDocument>(L, 1)->close(); |
|
571 return 0; |
|
572 } |
|
573 |
|
574 static int ldocument_gc(lua_State* L) { |
|
575 get_ref<SkDocument>(L, 1)->unref(); |
|
576 return 0; |
|
577 } |
|
578 |
|
579 static const struct luaL_Reg gSkDocument_Methods[] = { |
|
580 { "beginPage", ldocument_beginPage }, |
|
581 { "endPage", ldocument_endPage }, |
|
582 { "close", ldocument_close }, |
|
583 { "__gc", ldocument_gc }, |
|
584 { NULL, NULL } |
|
585 }; |
|
586 |
|
587 /////////////////////////////////////////////////////////////////////////////// |
|
588 |
|
589 static int lpaint_isAntiAlias(lua_State* L) { |
|
590 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAntiAlias()); |
|
591 return 1; |
|
592 } |
|
593 |
|
594 static int lpaint_setAntiAlias(lua_State* L) { |
|
595 get_obj<SkPaint>(L, 1)->setAntiAlias(lua2bool(L, 2)); |
|
596 return 0; |
|
597 } |
|
598 |
|
599 static int lpaint_isDither(lua_State* L) { |
|
600 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither()); |
|
601 return 1; |
|
602 } |
|
603 |
|
604 static int lpaint_isUnderlineText(lua_State* L) { |
|
605 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText()); |
|
606 return 1; |
|
607 } |
|
608 |
|
609 static int lpaint_isStrikeThruText(lua_State* L) { |
|
610 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText()); |
|
611 return 1; |
|
612 } |
|
613 |
|
614 static int lpaint_isFakeBoldText(lua_State* L) { |
|
615 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText()); |
|
616 return 1; |
|
617 } |
|
618 |
|
619 static int lpaint_isLinearText(lua_State* L) { |
|
620 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText()); |
|
621 return 1; |
|
622 } |
|
623 |
|
624 static int lpaint_isSubpixelText(lua_State* L) { |
|
625 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText()); |
|
626 return 1; |
|
627 } |
|
628 |
|
629 static int lpaint_isDevKernText(lua_State* L) { |
|
630 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText()); |
|
631 return 1; |
|
632 } |
|
633 |
|
634 static int lpaint_isLCDRenderText(lua_State* L) { |
|
635 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText()); |
|
636 return 1; |
|
637 } |
|
638 |
|
639 static int lpaint_isEmbeddedBitmapText(lua_State* L) { |
|
640 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText()); |
|
641 return 1; |
|
642 } |
|
643 |
|
644 static int lpaint_isAutohinted(lua_State* L) { |
|
645 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted()); |
|
646 return 1; |
|
647 } |
|
648 |
|
649 static int lpaint_isVerticalText(lua_State* L) { |
|
650 lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText()); |
|
651 return 1; |
|
652 } |
|
653 |
|
654 static int lpaint_getColor(lua_State* L) { |
|
655 SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor()); |
|
656 return 1; |
|
657 } |
|
658 |
|
659 static int lpaint_setColor(lua_State* L) { |
|
660 get_obj<SkPaint>(L, 1)->setColor(lua2color(L, 2)); |
|
661 return 0; |
|
662 } |
|
663 |
|
664 static int lpaint_getTextSize(lua_State* L) { |
|
665 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize()); |
|
666 return 1; |
|
667 } |
|
668 |
|
669 static int lpaint_getTextScaleX(lua_State* L) { |
|
670 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX()); |
|
671 return 1; |
|
672 } |
|
673 |
|
674 static int lpaint_getTextSkewX(lua_State* L) { |
|
675 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX()); |
|
676 return 1; |
|
677 } |
|
678 |
|
679 static int lpaint_setTextSize(lua_State* L) { |
|
680 get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2)); |
|
681 return 0; |
|
682 } |
|
683 |
|
684 static int lpaint_getTypeface(lua_State* L) { |
|
685 push_ref(L, get_obj<SkPaint>(L, 1)->getTypeface()); |
|
686 return 1; |
|
687 } |
|
688 |
|
689 static int lpaint_setTypeface(lua_State* L) { |
|
690 get_obj<SkPaint>(L, 1)->setTypeface(get_ref<SkTypeface>(L, 2)); |
|
691 return 0; |
|
692 } |
|
693 |
|
694 static int lpaint_getHinting(lua_State* L) { |
|
695 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting()); |
|
696 return 1; |
|
697 } |
|
698 |
|
699 static int lpaint_getFontID(lua_State* L) { |
|
700 SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface(); |
|
701 SkLua(L).pushU32(SkTypeface::UniqueID(face)); |
|
702 return 1; |
|
703 } |
|
704 |
|
705 static const struct { |
|
706 const char* fLabel; |
|
707 SkPaint::Align fAlign; |
|
708 } gAlignRec[] = { |
|
709 { "left", SkPaint::kLeft_Align }, |
|
710 { "center", SkPaint::kCenter_Align }, |
|
711 { "right", SkPaint::kRight_Align }, |
|
712 }; |
|
713 |
|
714 static int lpaint_getTextAlign(lua_State* L) { |
|
715 SkPaint::Align align = get_obj<SkPaint>(L, 1)->getTextAlign(); |
|
716 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { |
|
717 if (gAlignRec[i].fAlign == align) { |
|
718 lua_pushstring(L, gAlignRec[i].fLabel); |
|
719 return 1; |
|
720 } |
|
721 } |
|
722 return 0; |
|
723 } |
|
724 |
|
725 static int lpaint_setTextAlign(lua_State* L) { |
|
726 if (lua_isstring(L, 2)) { |
|
727 size_t len; |
|
728 const char* label = lua_tolstring(L, 2, &len); |
|
729 |
|
730 for (size_t i = 0; i < SK_ARRAY_COUNT(gAlignRec); ++i) { |
|
731 if (!strcmp(gAlignRec[i].fLabel, label)) { |
|
732 get_obj<SkPaint>(L, 1)->setTextAlign(gAlignRec[i].fAlign); |
|
733 break; |
|
734 } |
|
735 } |
|
736 } |
|
737 return 0; |
|
738 } |
|
739 |
|
740 static int lpaint_getStroke(lua_State* L) { |
|
741 lua_pushboolean(L, SkPaint::kStroke_Style == get_obj<SkPaint>(L, 1)->getStyle()); |
|
742 return 1; |
|
743 } |
|
744 |
|
745 static int lpaint_setStroke(lua_State* L) { |
|
746 SkPaint::Style style; |
|
747 |
|
748 if (lua_toboolean(L, 2)) { |
|
749 style = SkPaint::kStroke_Style; |
|
750 } else { |
|
751 style = SkPaint::kFill_Style; |
|
752 } |
|
753 get_obj<SkPaint>(L, 1)->setStyle(style); |
|
754 return 0; |
|
755 } |
|
756 |
|
757 static int lpaint_getStrokeCap(lua_State* L) { |
|
758 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap()); |
|
759 return 1; |
|
760 } |
|
761 |
|
762 static int lpaint_getStrokeJoin(lua_State* L) { |
|
763 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin()); |
|
764 return 1; |
|
765 } |
|
766 |
|
767 static int lpaint_getTextEncoding(lua_State* L) { |
|
768 SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding()); |
|
769 return 1; |
|
770 } |
|
771 |
|
772 static int lpaint_getStrokeWidth(lua_State* L) { |
|
773 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth()); |
|
774 return 1; |
|
775 } |
|
776 |
|
777 static int lpaint_setStrokeWidth(lua_State* L) { |
|
778 get_obj<SkPaint>(L, 1)->setStrokeWidth(lua2scalar(L, 2)); |
|
779 return 0; |
|
780 } |
|
781 |
|
782 static int lpaint_getStrokeMiter(lua_State* L) { |
|
783 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter()); |
|
784 return 1; |
|
785 } |
|
786 |
|
787 static int lpaint_measureText(lua_State* L) { |
|
788 if (lua_isstring(L, 2)) { |
|
789 size_t len; |
|
790 const char* text = lua_tolstring(L, 2, &len); |
|
791 SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->measureText(text, len)); |
|
792 return 1; |
|
793 } |
|
794 return 0; |
|
795 } |
|
796 |
|
797 struct FontMetrics { |
|
798 SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0) |
|
799 SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0) |
|
800 SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0) |
|
801 SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0) |
|
802 SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0) |
|
803 SkScalar fAvgCharWidth; //!< the average charactor width (>= 0) |
|
804 SkScalar fXMin; //!< The minimum bounding box x value for all glyphs |
|
805 SkScalar fXMax; //!< The maximum bounding box x value for all glyphs |
|
806 SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face |
|
807 }; |
|
808 |
|
809 static int lpaint_getFontMetrics(lua_State* L) { |
|
810 SkPaint::FontMetrics fm; |
|
811 SkScalar height = get_obj<SkPaint>(L, 1)->getFontMetrics(&fm); |
|
812 |
|
813 lua_newtable(L); |
|
814 setfield_scalar(L, "top", fm.fTop); |
|
815 setfield_scalar(L, "ascent", fm.fAscent); |
|
816 setfield_scalar(L, "descent", fm.fDescent); |
|
817 setfield_scalar(L, "bottom", fm.fBottom); |
|
818 setfield_scalar(L, "leading", fm.fLeading); |
|
819 SkLua(L).pushScalar(height); |
|
820 return 2; |
|
821 } |
|
822 |
|
823 static int lpaint_getEffects(lua_State* L) { |
|
824 const SkPaint* paint = get_obj<SkPaint>(L, 1); |
|
825 |
|
826 lua_newtable(L); |
|
827 setfield_bool_if(L, "looper", !!paint->getLooper()); |
|
828 setfield_bool_if(L, "pathEffect", !!paint->getPathEffect()); |
|
829 setfield_bool_if(L, "rasterizer", !!paint->getRasterizer()); |
|
830 setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter()); |
|
831 setfield_bool_if(L, "shader", !!paint->getShader()); |
|
832 setfield_bool_if(L, "colorFilter", !!paint->getColorFilter()); |
|
833 setfield_bool_if(L, "imageFilter", !!paint->getImageFilter()); |
|
834 setfield_bool_if(L, "xfermode", !!paint->getXfermode()); |
|
835 return 1; |
|
836 } |
|
837 |
|
838 static int lpaint_getShader(lua_State* L) { |
|
839 const SkPaint* paint = get_obj<SkPaint>(L, 1); |
|
840 SkShader* shader = paint->getShader(); |
|
841 if (shader) { |
|
842 push_ref(L, shader); |
|
843 return 1; |
|
844 } |
|
845 return 0; |
|
846 } |
|
847 |
|
848 static int lpaint_gc(lua_State* L) { |
|
849 get_obj<SkPaint>(L, 1)->~SkPaint(); |
|
850 return 0; |
|
851 } |
|
852 |
|
853 static const struct luaL_Reg gSkPaint_Methods[] = { |
|
854 { "isAntiAlias", lpaint_isAntiAlias }, |
|
855 { "setAntiAlias", lpaint_setAntiAlias }, |
|
856 { "isDither", lpaint_isDither }, |
|
857 { "isUnderlineText", lpaint_isUnderlineText }, |
|
858 { "isStrikeThruText", lpaint_isStrikeThruText }, |
|
859 { "isFakeBoldText", lpaint_isFakeBoldText }, |
|
860 { "isLinearText", lpaint_isLinearText }, |
|
861 { "isSubpixelText", lpaint_isSubpixelText }, |
|
862 { "isDevKernText", lpaint_isDevKernText }, |
|
863 { "isLCDRenderText", lpaint_isLCDRenderText }, |
|
864 { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText }, |
|
865 { "isAutohinted", lpaint_isAutohinted }, |
|
866 { "isVerticalText", lpaint_isVerticalText }, |
|
867 { "getColor", lpaint_getColor }, |
|
868 { "setColor", lpaint_setColor }, |
|
869 { "getTextSize", lpaint_getTextSize }, |
|
870 { "setTextSize", lpaint_setTextSize }, |
|
871 { "getTextScaleX", lpaint_getTextScaleX }, |
|
872 { "getTextSkewX", lpaint_getTextSkewX }, |
|
873 { "getTypeface", lpaint_getTypeface }, |
|
874 { "setTypeface", lpaint_setTypeface }, |
|
875 { "getHinting", lpaint_getHinting }, |
|
876 { "getFontID", lpaint_getFontID }, |
|
877 { "getTextAlign", lpaint_getTextAlign }, |
|
878 { "setTextAlign", lpaint_setTextAlign }, |
|
879 { "getStroke", lpaint_getStroke }, |
|
880 { "setStroke", lpaint_setStroke }, |
|
881 { "getStrokeCap", lpaint_getStrokeCap }, |
|
882 { "getStrokeJoin", lpaint_getStrokeJoin }, |
|
883 { "getTextEncoding", lpaint_getTextEncoding }, |
|
884 { "getStrokeWidth", lpaint_getStrokeWidth }, |
|
885 { "setStrokeWidth", lpaint_setStrokeWidth }, |
|
886 { "getStrokeMiter", lpaint_getStrokeMiter }, |
|
887 { "measureText", lpaint_measureText }, |
|
888 { "getFontMetrics", lpaint_getFontMetrics }, |
|
889 { "getEffects", lpaint_getEffects }, |
|
890 { "getShader", lpaint_getShader }, |
|
891 { "__gc", lpaint_gc }, |
|
892 { NULL, NULL } |
|
893 }; |
|
894 |
|
895 /////////////////////////////////////////////////////////////////////////////// |
|
896 |
|
897 static const char* mode2string(SkShader::TileMode mode) { |
|
898 static const char* gNames[] = { "clamp", "repeat", "mirror" }; |
|
899 SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gNames)); |
|
900 return gNames[mode]; |
|
901 } |
|
902 |
|
903 static const char* gradtype2string(SkShader::GradientType t) { |
|
904 static const char* gNames[] = { |
|
905 "none", "color", "linear", "radial", "radial2", "sweep", "conical" |
|
906 }; |
|
907 SkASSERT((unsigned)t < SK_ARRAY_COUNT(gNames)); |
|
908 return gNames[t]; |
|
909 } |
|
910 |
|
911 static int lshader_isOpaque(lua_State* L) { |
|
912 SkShader* shader = get_ref<SkShader>(L, 1); |
|
913 return shader && shader->isOpaque(); |
|
914 } |
|
915 |
|
916 static int lshader_asABitmap(lua_State* L) { |
|
917 SkShader* shader = get_ref<SkShader>(L, 1); |
|
918 if (shader) { |
|
919 SkBitmap bm; |
|
920 SkMatrix matrix; |
|
921 SkShader::TileMode modes[2]; |
|
922 switch (shader->asABitmap(&bm, &matrix, modes)) { |
|
923 case SkShader::kDefault_BitmapType: |
|
924 lua_newtable(L); |
|
925 setfield_number(L, "genID", bm.pixelRef() ? bm.pixelRef()->getGenerationID() : 0); |
|
926 setfield_number(L, "width", bm.width()); |
|
927 setfield_number(L, "height", bm.height()); |
|
928 setfield_string(L, "tileX", mode2string(modes[0])); |
|
929 setfield_string(L, "tileY", mode2string(modes[1])); |
|
930 return 1; |
|
931 default: |
|
932 break; |
|
933 } |
|
934 } |
|
935 return 0; |
|
936 } |
|
937 |
|
938 static int lshader_asAGradient(lua_State* L) { |
|
939 SkShader* shader = get_ref<SkShader>(L, 1); |
|
940 if (shader) { |
|
941 SkShader::GradientInfo info; |
|
942 sk_bzero(&info, sizeof(info)); |
|
943 |
|
944 SkColor colors[3]; // hacked in for extracting info on 3 color case. |
|
945 SkScalar pos[3]; |
|
946 |
|
947 info.fColorCount = 3; |
|
948 info.fColors = &colors[0]; |
|
949 info.fColorOffsets = &pos[0]; |
|
950 |
|
951 SkShader::GradientType t = shader->asAGradient(&info); |
|
952 |
|
953 if (SkShader::kNone_GradientType != t) { |
|
954 lua_newtable(L); |
|
955 setfield_string(L, "type", gradtype2string(t)); |
|
956 setfield_number(L, "colorCount", info.fColorCount); |
|
957 setfield_string(L, "tile", mode2string(info.fTileMode)); |
|
958 |
|
959 if (info.fColorCount == 3){ |
|
960 setfield_number(L, "midPos", pos[1]); |
|
961 } |
|
962 |
|
963 return 1; |
|
964 } |
|
965 } |
|
966 return 0; |
|
967 } |
|
968 |
|
969 static int lshader_gc(lua_State* L) { |
|
970 get_ref<SkShader>(L, 1)->unref(); |
|
971 return 0; |
|
972 } |
|
973 |
|
974 static const struct luaL_Reg gSkShader_Methods[] = { |
|
975 { "isOpaque", lshader_isOpaque }, |
|
976 { "asABitmap", lshader_asABitmap }, |
|
977 { "asAGradient", lshader_asAGradient }, |
|
978 { "__gc", lshader_gc }, |
|
979 { NULL, NULL } |
|
980 }; |
|
981 |
|
982 /////////////////////////////////////////////////////////////////////////////// |
|
983 |
|
984 static int lmatrix_getType(lua_State* L) { |
|
985 SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType(); |
|
986 |
|
987 lua_newtable(L); |
|
988 setfield_boolean(L, "translate", SkToBool(mask & SkMatrix::kTranslate_Mask)); |
|
989 setfield_boolean(L, "scale", SkToBool(mask & SkMatrix::kScale_Mask)); |
|
990 setfield_boolean(L, "affine", SkToBool(mask & SkMatrix::kAffine_Mask)); |
|
991 setfield_boolean(L, "perspective", SkToBool(mask & SkMatrix::kPerspective_Mask)); |
|
992 return 1; |
|
993 } |
|
994 |
|
995 static int lmatrix_getScaleX(lua_State* L) { |
|
996 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleX()); |
|
997 return 1; |
|
998 } |
|
999 |
|
1000 static int lmatrix_getScaleY(lua_State* L) { |
|
1001 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getScaleY()); |
|
1002 return 1; |
|
1003 } |
|
1004 |
|
1005 static int lmatrix_getTranslateX(lua_State* L) { |
|
1006 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateX()); |
|
1007 return 1; |
|
1008 } |
|
1009 |
|
1010 static int lmatrix_getTranslateY(lua_State* L) { |
|
1011 lua_pushnumber(L, get_obj<SkMatrix>(L,1)->getTranslateY()); |
|
1012 return 1; |
|
1013 } |
|
1014 |
|
1015 static const struct luaL_Reg gSkMatrix_Methods[] = { |
|
1016 { "getType", lmatrix_getType }, |
|
1017 { "getScaleX", lmatrix_getScaleX }, |
|
1018 { "getScaleY", lmatrix_getScaleY }, |
|
1019 { "getTranslateX", lmatrix_getTranslateX }, |
|
1020 { "getTranslateY", lmatrix_getTranslateY }, |
|
1021 { NULL, NULL } |
|
1022 }; |
|
1023 |
|
1024 /////////////////////////////////////////////////////////////////////////////// |
|
1025 |
|
1026 static int lpath_getBounds(lua_State* L) { |
|
1027 SkLua(L).pushRect(get_obj<SkPath>(L, 1)->getBounds()); |
|
1028 return 1; |
|
1029 } |
|
1030 |
|
1031 static const char* fill_type_to_str(SkPath::FillType fill) { |
|
1032 switch (fill) { |
|
1033 case SkPath::kEvenOdd_FillType: |
|
1034 return "even-odd"; |
|
1035 case SkPath::kWinding_FillType: |
|
1036 return "winding"; |
|
1037 case SkPath::kInverseEvenOdd_FillType: |
|
1038 return "inverse-even-odd"; |
|
1039 case SkPath::kInverseWinding_FillType: |
|
1040 return "inverse-winding"; |
|
1041 } |
|
1042 return "unknown"; |
|
1043 } |
|
1044 |
|
1045 static int lpath_getFillType(lua_State* L) { |
|
1046 SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType(); |
|
1047 SkLua(L).pushString(fill_type_to_str(fill)); |
|
1048 return 1; |
|
1049 } |
|
1050 |
|
1051 static SkString segment_masks_to_str(uint32_t segmentMasks) { |
|
1052 SkString result; |
|
1053 bool first = true; |
|
1054 if (SkPath::kLine_SegmentMask & segmentMasks) { |
|
1055 result.append("line"); |
|
1056 first = false; |
|
1057 SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;) |
|
1058 } |
|
1059 if (SkPath::kQuad_SegmentMask & segmentMasks) { |
|
1060 if (!first) { |
|
1061 result.append(" "); |
|
1062 } |
|
1063 result.append("quad"); |
|
1064 first = false; |
|
1065 SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;) |
|
1066 } |
|
1067 if (SkPath::kConic_SegmentMask & segmentMasks) { |
|
1068 if (!first) { |
|
1069 result.append(" "); |
|
1070 } |
|
1071 result.append("conic"); |
|
1072 first = false; |
|
1073 SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;) |
|
1074 } |
|
1075 if (SkPath::kCubic_SegmentMask & segmentMasks) { |
|
1076 if (!first) { |
|
1077 result.append(" "); |
|
1078 } |
|
1079 result.append("cubic"); |
|
1080 SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;) |
|
1081 } |
|
1082 SkASSERT(0 == segmentMasks); |
|
1083 return result; |
|
1084 } |
|
1085 |
|
1086 static int lpath_getSegementTypes(lua_State* L) { |
|
1087 uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks(); |
|
1088 SkLua(L).pushString(segment_masks_to_str(segMasks)); |
|
1089 return 1; |
|
1090 } |
|
1091 |
|
1092 static int lpath_isConvex(lua_State* L) { |
|
1093 bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity(); |
|
1094 SkLua(L).pushBool(isConvex); |
|
1095 return 1; |
|
1096 } |
|
1097 |
|
1098 static int lpath_isEmpty(lua_State* L) { |
|
1099 lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty()); |
|
1100 return 1; |
|
1101 } |
|
1102 |
|
1103 static int lpath_isRect(lua_State* L) { |
|
1104 SkRect r; |
|
1105 bool pred = get_obj<SkPath>(L, 1)->isRect(&r); |
|
1106 int ret_count = 1; |
|
1107 lua_pushboolean(L, pred); |
|
1108 if (pred) { |
|
1109 SkLua(L).pushRect(r); |
|
1110 ret_count += 1; |
|
1111 } |
|
1112 return ret_count; |
|
1113 } |
|
1114 |
|
1115 static const char* dir2string(SkPath::Direction dir) { |
|
1116 static const char* gStr[] = { |
|
1117 "unknown", "cw", "ccw" |
|
1118 }; |
|
1119 SkASSERT((unsigned)dir < SK_ARRAY_COUNT(gStr)); |
|
1120 return gStr[dir]; |
|
1121 } |
|
1122 |
|
1123 static int lpath_isNestedRects(lua_State* L) { |
|
1124 SkRect rects[2]; |
|
1125 SkPath::Direction dirs[2]; |
|
1126 bool pred = get_obj<SkPath>(L, 1)->isNestedRects(rects, dirs); |
|
1127 int ret_count = 1; |
|
1128 lua_pushboolean(L, pred); |
|
1129 if (pred) { |
|
1130 SkLua lua(L); |
|
1131 lua.pushRect(rects[0]); |
|
1132 lua.pushRect(rects[1]); |
|
1133 lua_pushstring(L, dir2string(dirs[0])); |
|
1134 lua_pushstring(L, dir2string(dirs[0])); |
|
1135 ret_count += 4; |
|
1136 } |
|
1137 return ret_count; |
|
1138 } |
|
1139 |
|
1140 static int lpath_countPoints(lua_State* L) { |
|
1141 lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints()); |
|
1142 return 1; |
|
1143 } |
|
1144 |
|
1145 static int lpath_reset(lua_State* L) { |
|
1146 get_obj<SkPath>(L, 1)->reset(); |
|
1147 return 0; |
|
1148 } |
|
1149 |
|
1150 static int lpath_moveTo(lua_State* L) { |
|
1151 get_obj<SkPath>(L, 1)->moveTo(lua2scalar(L, 2), lua2scalar(L, 3)); |
|
1152 return 0; |
|
1153 } |
|
1154 |
|
1155 static int lpath_lineTo(lua_State* L) { |
|
1156 get_obj<SkPath>(L, 1)->lineTo(lua2scalar(L, 2), lua2scalar(L, 3)); |
|
1157 return 0; |
|
1158 } |
|
1159 |
|
1160 static int lpath_quadTo(lua_State* L) { |
|
1161 get_obj<SkPath>(L, 1)->quadTo(lua2scalar(L, 2), lua2scalar(L, 3), |
|
1162 lua2scalar(L, 4), lua2scalar(L, 5)); |
|
1163 return 0; |
|
1164 } |
|
1165 |
|
1166 static int lpath_cubicTo(lua_State* L) { |
|
1167 get_obj<SkPath>(L, 1)->cubicTo(lua2scalar(L, 2), lua2scalar(L, 3), |
|
1168 lua2scalar(L, 4), lua2scalar(L, 5), |
|
1169 lua2scalar(L, 6), lua2scalar(L, 7)); |
|
1170 return 0; |
|
1171 } |
|
1172 |
|
1173 static int lpath_close(lua_State* L) { |
|
1174 get_obj<SkPath>(L, 1)->close(); |
|
1175 return 0; |
|
1176 } |
|
1177 |
|
1178 static int lpath_gc(lua_State* L) { |
|
1179 get_obj<SkPath>(L, 1)->~SkPath(); |
|
1180 return 0; |
|
1181 } |
|
1182 |
|
1183 static const struct luaL_Reg gSkPath_Methods[] = { |
|
1184 { "getBounds", lpath_getBounds }, |
|
1185 { "getFillType", lpath_getFillType }, |
|
1186 { "getSegmentTypes", lpath_getSegementTypes }, |
|
1187 { "isConvex", lpath_isConvex }, |
|
1188 { "isEmpty", lpath_isEmpty }, |
|
1189 { "isRect", lpath_isRect }, |
|
1190 { "isNestedRects", lpath_isNestedRects }, |
|
1191 { "countPoints", lpath_countPoints }, |
|
1192 { "reset", lpath_reset }, |
|
1193 { "moveTo", lpath_moveTo }, |
|
1194 { "lineTo", lpath_lineTo }, |
|
1195 { "quadTo", lpath_quadTo }, |
|
1196 { "cubicTo", lpath_cubicTo }, |
|
1197 { "close", lpath_close }, |
|
1198 { "__gc", lpath_gc }, |
|
1199 { NULL, NULL } |
|
1200 }; |
|
1201 |
|
1202 /////////////////////////////////////////////////////////////////////////////// |
|
1203 |
|
1204 static const char* rrect_type(const SkRRect& rr) { |
|
1205 switch (rr.getType()) { |
|
1206 case SkRRect::kUnknown_Type: return "unknown"; |
|
1207 case SkRRect::kEmpty_Type: return "empty"; |
|
1208 case SkRRect::kRect_Type: return "rect"; |
|
1209 case SkRRect::kOval_Type: return "oval"; |
|
1210 case SkRRect::kSimple_Type: return "simple"; |
|
1211 case SkRRect::kComplex_Type: return "complex"; |
|
1212 } |
|
1213 SkDEBUGFAIL("never get here"); |
|
1214 return ""; |
|
1215 } |
|
1216 |
|
1217 static int lrrect_rect(lua_State* L) { |
|
1218 SkLua(L).pushRect(get_obj<SkRRect>(L, 1)->rect()); |
|
1219 return 1; |
|
1220 } |
|
1221 |
|
1222 static int lrrect_type(lua_State* L) { |
|
1223 lua_pushstring(L, rrect_type(*get_obj<SkRRect>(L, 1))); |
|
1224 return 1; |
|
1225 } |
|
1226 |
|
1227 static int lrrect_radii(lua_State* L) { |
|
1228 int corner = SkToInt(lua_tointeger(L, 2)); |
|
1229 SkVector v; |
|
1230 if (corner < 0 || corner > 3) { |
|
1231 SkDebugf("bad corner index %d", corner); |
|
1232 v.set(0, 0); |
|
1233 } else { |
|
1234 v = get_obj<SkRRect>(L, 1)->radii((SkRRect::Corner)corner); |
|
1235 } |
|
1236 lua_pushnumber(L, v.fX); |
|
1237 lua_pushnumber(L, v.fY); |
|
1238 return 2; |
|
1239 } |
|
1240 |
|
1241 static int lrrect_gc(lua_State* L) { |
|
1242 get_obj<SkRRect>(L, 1)->~SkRRect(); |
|
1243 return 0; |
|
1244 } |
|
1245 |
|
1246 static const struct luaL_Reg gSkRRect_Methods[] = { |
|
1247 { "rect", lrrect_rect }, |
|
1248 { "type", lrrect_type }, |
|
1249 { "radii", lrrect_radii }, |
|
1250 { "__gc", lrrect_gc }, |
|
1251 { NULL, NULL } |
|
1252 }; |
|
1253 |
|
1254 /////////////////////////////////////////////////////////////////////////////// |
|
1255 |
|
1256 static int limage_width(lua_State* L) { |
|
1257 lua_pushinteger(L, get_ref<SkImage>(L, 1)->width()); |
|
1258 return 1; |
|
1259 } |
|
1260 |
|
1261 static int limage_height(lua_State* L) { |
|
1262 lua_pushinteger(L, get_ref<SkImage>(L, 1)->height()); |
|
1263 return 1; |
|
1264 } |
|
1265 |
|
1266 static int limage_gc(lua_State* L) { |
|
1267 get_ref<SkImage>(L, 1)->unref(); |
|
1268 return 0; |
|
1269 } |
|
1270 |
|
1271 static const struct luaL_Reg gSkImage_Methods[] = { |
|
1272 { "width", limage_width }, |
|
1273 { "height", limage_height }, |
|
1274 { "__gc", limage_gc }, |
|
1275 { NULL, NULL } |
|
1276 }; |
|
1277 |
|
1278 /////////////////////////////////////////////////////////////////////////////// |
|
1279 |
|
1280 static int ltypeface_gc(lua_State* L) { |
|
1281 SkSafeUnref(get_ref<SkTypeface>(L, 1)); |
|
1282 return 0; |
|
1283 } |
|
1284 |
|
1285 static const struct luaL_Reg gSkTypeface_Methods[] = { |
|
1286 { "__gc", ltypeface_gc }, |
|
1287 { NULL, NULL } |
|
1288 }; |
|
1289 |
|
1290 /////////////////////////////////////////////////////////////////////////////// |
|
1291 |
|
1292 class AutoCallLua { |
|
1293 public: |
|
1294 AutoCallLua(lua_State* L, const char func[], const char verb[]) : fL(L) { |
|
1295 lua_getglobal(L, func); |
|
1296 if (!lua_isfunction(L, -1)) { |
|
1297 int t = lua_type(L, -1); |
|
1298 SkDebugf("--- expected function %d\n", t); |
|
1299 } |
|
1300 |
|
1301 lua_newtable(L); |
|
1302 setfield_string(L, "verb", verb); |
|
1303 } |
|
1304 |
|
1305 ~AutoCallLua() { |
|
1306 if (lua_pcall(fL, 1, 0, 0) != LUA_OK) { |
|
1307 SkDebugf("lua err: %s\n", lua_tostring(fL, -1)); |
|
1308 } |
|
1309 lua_settop(fL, -1); |
|
1310 } |
|
1311 |
|
1312 private: |
|
1313 lua_State* fL; |
|
1314 }; |
|
1315 |
|
1316 #define AUTO_LUA(verb) AutoCallLua acl(fL, fFunc.c_str(), verb) |
|
1317 |
|
1318 /////////////////////////////////////////////////////////////////////////////// |
|
1319 |
|
1320 static int lsk_newDocumentPDF(lua_State* L) { |
|
1321 const char* file = NULL; |
|
1322 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { |
|
1323 file = lua_tolstring(L, 1, NULL); |
|
1324 } |
|
1325 |
|
1326 SkDocument* doc = SkDocument::CreatePDF(file); |
|
1327 if (NULL == doc) { |
|
1328 // do I need to push a nil on the stack and return 1? |
|
1329 return 0; |
|
1330 } else { |
|
1331 push_ref(L, doc); |
|
1332 doc->unref(); |
|
1333 return 1; |
|
1334 } |
|
1335 } |
|
1336 |
|
1337 static int lsk_newPaint(lua_State* L) { |
|
1338 push_new<SkPaint>(L); |
|
1339 return 1; |
|
1340 } |
|
1341 |
|
1342 static int lsk_newPath(lua_State* L) { |
|
1343 push_new<SkPath>(L); |
|
1344 return 1; |
|
1345 } |
|
1346 |
|
1347 static int lsk_newRRect(lua_State* L) { |
|
1348 SkRRect* rr = push_new<SkRRect>(L); |
|
1349 rr->setEmpty(); |
|
1350 return 1; |
|
1351 } |
|
1352 |
|
1353 static int lsk_newTypeface(lua_State* L) { |
|
1354 const char* name = NULL; |
|
1355 int style = SkTypeface::kNormal; |
|
1356 |
|
1357 int count = lua_gettop(L); |
|
1358 if (count > 0 && lua_isstring(L, 1)) { |
|
1359 name = lua_tolstring(L, 1, NULL); |
|
1360 if (count > 1 && lua_isnumber(L, 2)) { |
|
1361 style = lua_tointegerx(L, 2, NULL) & SkTypeface::kBoldItalic; |
|
1362 } |
|
1363 } |
|
1364 |
|
1365 SkTypeface* face = SkTypeface::CreateFromName(name, |
|
1366 (SkTypeface::Style)style); |
|
1367 // SkDebugf("---- name <%s> style=%d, face=%p ref=%d\n", name, style, face, face->getRefCnt()); |
|
1368 if (NULL == face) { |
|
1369 face = SkTypeface::RefDefault(); |
|
1370 } |
|
1371 push_ref(L, face); |
|
1372 face->unref(); |
|
1373 return 1; |
|
1374 } |
|
1375 |
|
1376 static int lsk_loadImage(lua_State* L) { |
|
1377 if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { |
|
1378 const char* name = lua_tolstring(L, 1, NULL); |
|
1379 SkAutoDataUnref data(SkData::NewFromFileName(name)); |
|
1380 if (data.get()) { |
|
1381 SkImage* image = SkImage::NewEncodedData(data.get()); |
|
1382 if (image) { |
|
1383 push_ref(L, image); |
|
1384 image->unref(); |
|
1385 return 1; |
|
1386 } |
|
1387 } |
|
1388 } |
|
1389 return 0; |
|
1390 } |
|
1391 |
|
1392 static void register_Sk(lua_State* L) { |
|
1393 lua_newtable(L); |
|
1394 lua_pushvalue(L, -1); |
|
1395 lua_setglobal(L, "Sk"); |
|
1396 // the Sk table is still on top |
|
1397 |
|
1398 setfield_function(L, "newDocumentPDF", lsk_newDocumentPDF); |
|
1399 setfield_function(L, "loadImage", lsk_loadImage); |
|
1400 setfield_function(L, "newPaint", lsk_newPaint); |
|
1401 setfield_function(L, "newPath", lsk_newPath); |
|
1402 setfield_function(L, "newRRect", lsk_newRRect); |
|
1403 setfield_function(L, "newTypeface", lsk_newTypeface); |
|
1404 lua_pop(L, 1); // pop off the Sk table |
|
1405 } |
|
1406 |
|
1407 #define REG_CLASS(L, C) \ |
|
1408 do { \ |
|
1409 luaL_newmetatable(L, get_mtname<C>()); \ |
|
1410 lua_pushvalue(L, -1); \ |
|
1411 lua_setfield(L, -2, "__index"); \ |
|
1412 luaL_setfuncs(L, g##C##_Methods, 0); \ |
|
1413 lua_pop(L, 1); /* pop off the meta-table */ \ |
|
1414 } while (0) |
|
1415 |
|
1416 void SkLua::Load(lua_State* L) { |
|
1417 register_Sk(L); |
|
1418 REG_CLASS(L, SkCanvas); |
|
1419 REG_CLASS(L, SkDocument); |
|
1420 REG_CLASS(L, SkImage); |
|
1421 REG_CLASS(L, SkPath); |
|
1422 REG_CLASS(L, SkPaint); |
|
1423 REG_CLASS(L, SkRRect); |
|
1424 REG_CLASS(L, SkShader); |
|
1425 REG_CLASS(L, SkTypeface); |
|
1426 REG_CLASS(L, SkMatrix); |
|
1427 } |
|
1428 |
|
1429 extern "C" int luaopen_skia(lua_State* L); |
|
1430 extern "C" int luaopen_skia(lua_State* L) { |
|
1431 SkLua::Load(L); |
|
1432 return 0; |
|
1433 } |