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 "SkLuaCanvas.h"
9#include "SkLua.h"
10
11extern "C" {
12    #include "lua.h"
13    #include "lauxlib.h"
14}
15
16class AutoCallLua : public SkLua {
17public:
18    AutoCallLua(lua_State* L, const char func[], const char verb[]) : INHERITED(L) {
19        lua_getglobal(L, func);
20        if (!lua_isfunction(L, -1)) {
21            int t = lua_type(L, -1);
22            SkDebugf("--- expected function %d\n", t);
23        }
24
25        lua_newtable(L);
26        this->pushString(verb, "verb");
27    }
28
29    ~AutoCallLua() {
30        lua_State* L = this->get();
31        if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
32            SkDebugf("lua err: %s\n", lua_tostring(L, -1));
33        }
34        lua_settop(L, -1);
35    }
36
37    void pushEncodedText(SkPaint::TextEncoding, const void*, size_t);
38
39private:
40    typedef SkLua INHERITED;
41};
42
43#define AUTO_LUA(verb)  AutoCallLua lua(fL, fFunc.c_str(), verb)
44
45
46///////////////////////////////////////////////////////////////////////////////
47
48void AutoCallLua::pushEncodedText(SkPaint::TextEncoding enc, const void* text,
49                                  size_t length) {
50    switch (enc) {
51        case SkPaint::kUTF8_TextEncoding:
52            this->pushString((const char*)text, length, "text");
53            break;
54        case SkPaint::kUTF16_TextEncoding: {
55            SkString str;
56            str.setUTF16((const uint16_t*)text, length);
57            this->pushString(str, "text");
58        } break;
59        case SkPaint::kGlyphID_TextEncoding:
60            this->pushArrayU16((const uint16_t*)text, length >> 1, "glyphs");
61            break;
62        case SkPaint::kUTF32_TextEncoding:
63            break;
64    }
65}
66
67///////////////////////////////////////////////////////////////////////////////
68
69void SkLuaCanvas::pushThis() {
70    SkLua(fL).pushCanvas(this);
71}
72
73///////////////////////////////////////////////////////////////////////////////
74
75static SkBitmap make_bm(int width, int height) {
76    SkBitmap bm;
77    bm.setConfig(SkBitmap::kNo_Config, width, height);
78    return bm;
79}
80
81SkLuaCanvas::SkLuaCanvas(int width, int height, lua_State* L, const char func[])
82    : INHERITED(make_bm(width, height))
83    , fL(L)
84    , fFunc(func) {
85}
86
87SkLuaCanvas::~SkLuaCanvas() {}
88
89int SkLuaCanvas::save(SaveFlags flags) {
90    AUTO_LUA("save");
91    return this->INHERITED::save(flags);
92}
93
94int SkLuaCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
95                             SaveFlags flags) {
96    AUTO_LUA("saveLayer");
97    if (bounds) {
98        lua.pushRect(*bounds, "bounds");
99    }
100    if (paint) {
101        lua.pushPaint(*paint, "paint");
102    }
103    return this->INHERITED::save(flags);
104}
105
106void SkLuaCanvas::restore() {
107    AUTO_LUA("restore");
108    this->INHERITED::restore();
109}
110
111bool SkLuaCanvas::translate(SkScalar dx, SkScalar dy) {
112    AUTO_LUA("translate");
113    lua.pushScalar(dx, "dx");
114    lua.pushScalar(dy, "dy");
115    return this->INHERITED::translate(dx, dy);
116}
117
118bool SkLuaCanvas::scale(SkScalar sx, SkScalar sy) {
119    AUTO_LUA("scale");
120    lua.pushScalar(sx, "sx");
121    lua.pushScalar(sy, "sy");
122    return this->INHERITED::scale(sx, sy);
123}
124
125bool SkLuaCanvas::rotate(SkScalar degrees) {
126    AUTO_LUA("rotate");
127    lua.pushScalar(degrees, "degrees");
128    return this->INHERITED::rotate(degrees);
129}
130
131bool SkLuaCanvas::skew(SkScalar kx, SkScalar ky) {
132    AUTO_LUA("skew");
133    lua.pushScalar(kx, "kx");
134    lua.pushScalar(ky, "ky");
135    return this->INHERITED::skew(kx, ky);
136}
137
138bool SkLuaCanvas::concat(const SkMatrix& matrix) {
139    AUTO_LUA("concat");
140    return this->INHERITED::concat(matrix);
141}
142
143void SkLuaCanvas::setMatrix(const SkMatrix& matrix) {
144    this->INHERITED::setMatrix(matrix);
145}
146
147bool SkLuaCanvas::clipRect(const SkRect& r, SkRegion::Op op, bool doAA) {
148    AUTO_LUA("clipRect");
149    lua.pushRect(r, "rect");
150    lua.pushBool(doAA, "aa");
151    return this->INHERITED::clipRect(r, op, doAA);
152}
153
154bool SkLuaCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
155    AUTO_LUA("clipRRect");
156    lua.pushRRect(rrect, "rrect");
157    lua.pushBool(doAA, "aa");
158    return this->INHERITED::clipRRect(rrect, op, doAA);
159}
160
161bool SkLuaCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
162    AUTO_LUA("clipPath");
163    lua.pushPath(path, "path");
164    lua.pushBool(doAA, "aa");
165    return this->INHERITED::clipPath(path, op, doAA);
166}
167
168bool SkLuaCanvas::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
169    AUTO_LUA("clipRegion");
170    return this->INHERITED::clipRegion(deviceRgn, op);
171}
172
173void SkLuaCanvas::drawPaint(const SkPaint& paint) {
174    AUTO_LUA("drawPaint");
175    lua.pushPaint(paint, "paint");
176}
177
178void SkLuaCanvas::drawPoints(PointMode mode, size_t count,
179                               const SkPoint pts[], const SkPaint& paint) {
180    AUTO_LUA("drawPoints");
181    lua.pushPaint(paint, "paint");
182}
183
184void SkLuaCanvas::drawOval(const SkRect& rect, const SkPaint& paint) {
185    AUTO_LUA("drawOval");
186    lua.pushRect(rect, "rect");
187    lua.pushPaint(paint, "paint");
188}
189
190void SkLuaCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
191    AUTO_LUA("drawRect");
192    lua.pushRect(rect, "rect");
193    lua.pushPaint(paint, "paint");
194}
195
196void SkLuaCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
197    AUTO_LUA("drawRRect");
198    lua.pushRRect(rrect, "rrect");
199    lua.pushPaint(paint, "paint");
200}
201
202void SkLuaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
203    AUTO_LUA("drawPath");
204    lua.pushPath(path, "path");
205    lua.pushPaint(paint, "paint");
206}
207
208void SkLuaCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
209                             const SkPaint* paint) {
210    AUTO_LUA("drawBitmap");
211    if (paint) {
212        lua.pushPaint(*paint, "paint");
213    }
214}
215
216void SkLuaCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
217                                       const SkRect& dst, const SkPaint* paint,
218                                       DrawBitmapRectFlags flags) {
219    AUTO_LUA("drawBitmapRectToRect");
220    if (paint) {
221        lua.pushPaint(*paint, "paint");
222    }
223}
224
225void SkLuaCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
226                                   const SkPaint* paint) {
227    AUTO_LUA("drawBitmapMatrix");
228    if (paint) {
229        lua.pushPaint(*paint, "paint");
230    }
231}
232
233void SkLuaCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
234                               const SkPaint* paint) {
235    AUTO_LUA("drawSprite");
236    if (paint) {
237        lua.pushPaint(*paint, "paint");
238    }
239}
240
241void SkLuaCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
242                             SkScalar y, const SkPaint& paint) {
243    AUTO_LUA("drawText");
244    lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
245    lua.pushPaint(paint, "paint");
246}
247
248void SkLuaCanvas::drawPosText(const void* text, size_t byteLength,
249                                const SkPoint pos[], const SkPaint& paint) {
250    AUTO_LUA("drawPosText");
251    lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
252    lua.pushPaint(paint, "paint");
253}
254
255void SkLuaCanvas::drawPosTextH(const void* text, size_t byteLength,
256                                 const SkScalar xpos[], SkScalar constY,
257                                 const SkPaint& paint) {
258    AUTO_LUA("drawPosTextH");
259    lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
260    lua.pushPaint(paint, "paint");
261}
262
263void SkLuaCanvas::drawTextOnPath(const void* text, size_t byteLength,
264                                   const SkPath& path, const SkMatrix* matrix,
265                                   const SkPaint& paint) {
266    AUTO_LUA("drawTextOnPath");
267    lua.pushPath(path, "path");
268    lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
269    lua.pushPaint(paint, "paint");
270}
271
272void SkLuaCanvas::drawPicture(SkPicture& picture) {
273    AUTO_LUA("drawPicture");
274    // call through so we can see the nested picture ops
275    this->INHERITED::drawPicture(picture);
276}
277
278void SkLuaCanvas::drawVertices(VertexMode vmode, int vertexCount,
279                                 const SkPoint vertices[], const SkPoint texs[],
280                                 const SkColor colors[], SkXfermode* xmode,
281                                 const uint16_t indices[], int indexCount,
282                                 const SkPaint& paint) {
283    AUTO_LUA("drawVertices");
284    lua.pushPaint(paint, "paint");
285}
286
287void SkLuaCanvas::drawData(const void* data, size_t length) {
288    AUTO_LUA("drawData");
289}
290