|  | /* | 
|  | * Copyright 2013 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "SkLuaCanvas.h" | 
|  |  | 
|  | #include "SkLua.h" | 
|  | #include "SkStringUtils.h" | 
|  | #include "SkTo.h" | 
|  |  | 
|  | extern "C" { | 
|  | #include "lua.h" | 
|  | #include "lauxlib.h" | 
|  | } | 
|  |  | 
|  | class AutoCallLua : public SkLua { | 
|  | public: | 
|  | AutoCallLua(lua_State* L, const char func[], const char verb[]) : INHERITED(L) { | 
|  | lua_getglobal(L, func); | 
|  | if (!lua_isfunction(L, -1)) { | 
|  | int t = lua_type(L, -1); | 
|  | SkDebugf("--- expected function %d\n", t); | 
|  | } | 
|  |  | 
|  | lua_newtable(L); | 
|  | this->pushString(verb, "verb"); | 
|  | } | 
|  |  | 
|  | ~AutoCallLua() { | 
|  | lua_State* L = this->get(); | 
|  | if (lua_pcall(L, 1, 0, 0) != LUA_OK) { | 
|  | SkDebugf("lua err: %s\n", lua_tostring(L, -1)); | 
|  | } | 
|  | lua_settop(L, -1); | 
|  | } | 
|  |  | 
|  | void pushEncodedText(SkTextEncoding, const void*, size_t); | 
|  |  | 
|  | private: | 
|  | typedef SkLua INHERITED; | 
|  | }; | 
|  |  | 
|  | #define AUTO_LUA(verb)  AutoCallLua lua(fL, fFunc.c_str(), verb) | 
|  |  | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | void AutoCallLua::pushEncodedText(SkTextEncoding enc, const void* text, size_t length) { | 
|  | switch (enc) { | 
|  | case kUTF8_SkTextEncoding: | 
|  | this->pushString((const char*)text, length, "text"); | 
|  | break; | 
|  | case kUTF16_SkTextEncoding: | 
|  | this->pushString(SkStringFromUTF16((const uint16_t*)text, length), "text"); | 
|  | break; | 
|  | case kGlyphID_SkTextEncoding: | 
|  | this->pushArrayU16((const uint16_t*)text, SkToInt(length >> 1), | 
|  | "glyphs"); | 
|  | break; | 
|  | case kUTF32_SkTextEncoding: | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | void SkLuaCanvas::pushThis() { | 
|  | SkLua(fL).pushCanvas(this); | 
|  | } | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | SkLuaCanvas::SkLuaCanvas(int width, int height, lua_State* L, const char func[]) | 
|  | : INHERITED(width, height) | 
|  | , fL(L) | 
|  | , fFunc(func) { | 
|  | } | 
|  |  | 
|  | SkLuaCanvas::~SkLuaCanvas() {} | 
|  |  | 
|  | void SkLuaCanvas::willSave() { | 
|  | AUTO_LUA("save"); | 
|  | this->INHERITED::willSave(); | 
|  | } | 
|  |  | 
|  | SkCanvas::SaveLayerStrategy SkLuaCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) { | 
|  | AUTO_LUA("saveLayer"); | 
|  | if (rec.fBounds) { | 
|  | lua.pushRect(*rec.fBounds, "bounds"); | 
|  | } | 
|  | if (rec.fPaint) { | 
|  | lua.pushPaint(*rec.fPaint, "paint"); | 
|  | } | 
|  |  | 
|  | (void)this->INHERITED::getSaveLayerStrategy(rec); | 
|  | // No need for a layer. | 
|  | return kNoLayer_SaveLayerStrategy; | 
|  | } | 
|  |  | 
|  | bool SkLuaCanvas::onDoSaveBehind(const SkRect*) { | 
|  | // TODO | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::willRestore() { | 
|  | AUTO_LUA("restore"); | 
|  | this->INHERITED::willRestore(); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::didConcat(const SkMatrix& matrix) { | 
|  | switch (matrix.getType()) { | 
|  | case SkMatrix::kTranslate_Mask: { | 
|  | AUTO_LUA("translate"); | 
|  | lua.pushScalar(matrix.getTranslateX(), "dx"); | 
|  | lua.pushScalar(matrix.getTranslateY(), "dy"); | 
|  | break; | 
|  | } | 
|  | case SkMatrix::kScale_Mask: { | 
|  | AUTO_LUA("scale"); | 
|  | lua.pushScalar(matrix.getScaleX(), "sx"); | 
|  | lua.pushScalar(matrix.getScaleY(), "sy"); | 
|  | break; | 
|  | } | 
|  | default: { | 
|  | AUTO_LUA("concat"); | 
|  | // pushMatrix added in https://codereview.chromium.org/203203004/ | 
|  | // Doesn't seem to have ever been working correctly since added | 
|  | // lua.pushMatrix(matrix); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | this->INHERITED::didConcat(matrix); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::didSetMatrix(const SkMatrix& matrix) { | 
|  | this->INHERITED::didSetMatrix(matrix); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onClipRect(const SkRect& r, SkClipOp op, ClipEdgeStyle edgeStyle) { | 
|  | AUTO_LUA("clipRect"); | 
|  | lua.pushRect(r, "rect"); | 
|  | lua.pushBool(kSoft_ClipEdgeStyle == edgeStyle, "aa"); | 
|  | this->INHERITED::onClipRect(r, op, edgeStyle); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) { | 
|  | AUTO_LUA("clipRRect"); | 
|  | lua.pushRRect(rrect, "rrect"); | 
|  | lua.pushBool(kSoft_ClipEdgeStyle == edgeStyle, "aa"); | 
|  | this->INHERITED::onClipRRect(rrect, op, edgeStyle); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) { | 
|  | AUTO_LUA("clipPath"); | 
|  | lua.pushPath(path, "path"); | 
|  | lua.pushBool(kSoft_ClipEdgeStyle == edgeStyle, "aa"); | 
|  | this->INHERITED::onClipPath(path, op, edgeStyle); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) { | 
|  | AUTO_LUA("clipRegion"); | 
|  | this->INHERITED::onClipRegion(deviceRgn, op); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawPaint(const SkPaint& paint) { | 
|  | AUTO_LUA("drawPaint"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawPoints(PointMode mode, size_t count, | 
|  | const SkPoint pts[], const SkPaint& paint) { | 
|  | AUTO_LUA("drawPoints"); | 
|  | lua.pushArrayPoint(pts, SkToInt(count), "points"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) { | 
|  | AUTO_LUA("drawOval"); | 
|  | lua.pushRect(rect, "rect"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle, | 
|  | bool useCenter, const SkPaint& paint) { | 
|  | AUTO_LUA("drawArc"); | 
|  | lua.pushRect(rect, "rect"); | 
|  | lua.pushScalar(startAngle, "startAngle"); | 
|  | lua.pushScalar(sweepAngle, "sweepAngle"); | 
|  | lua.pushBool(useCenter, "useCenter"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { | 
|  | AUTO_LUA("drawRect"); | 
|  | lua.pushRect(rect, "rect"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { | 
|  | AUTO_LUA("drawRRect"); | 
|  | lua.pushRRect(rrect, "rrect"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, | 
|  | const SkPaint& paint) { | 
|  | AUTO_LUA("drawDRRect"); | 
|  | lua.pushRRect(outer, "outer"); | 
|  | lua.pushRRect(inner, "inner"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { | 
|  | AUTO_LUA("drawPath"); | 
|  | lua.pushPath(path, "path"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, | 
|  | const SkPaint* paint) { | 
|  | AUTO_LUA("drawBitmap"); | 
|  | if (paint) { | 
|  | lua.pushPaint(*paint, "paint"); | 
|  | } | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, | 
|  | const SkPaint* paint, SrcRectConstraint) { | 
|  | AUTO_LUA("drawBitmapRect"); | 
|  | if (paint) { | 
|  | lua.pushPaint(*paint, "paint"); | 
|  | } | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, | 
|  | const SkPaint* paint) { | 
|  | AUTO_LUA("drawBitmapNine"); | 
|  | if (paint) { | 
|  | lua.pushPaint(*paint, "paint"); | 
|  | } | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { | 
|  | AUTO_LUA("drawImage"); | 
|  | if (paint) { | 
|  | lua.pushPaint(*paint, "paint"); | 
|  | } | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, | 
|  | const SkPaint* paint, SrcRectConstraint) { | 
|  | AUTO_LUA("drawImageRect"); | 
|  | if (paint) { | 
|  | lua.pushPaint(*paint, "paint"); | 
|  | } | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, | 
|  | const SkPaint &paint) { | 
|  | AUTO_LUA("drawTextBlob"); | 
|  | lua.pushTextBlob(blob, "blob"); | 
|  | lua.pushScalar(x, "x"); | 
|  | lua.pushScalar(y, "y"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, | 
|  | const SkPaint* paint) { | 
|  | AUTO_LUA("drawPicture"); | 
|  | // call through so we can see the nested picture ops | 
|  | this->INHERITED::onDrawPicture(picture, matrix, paint); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { | 
|  | AUTO_LUA("drawDrawable"); | 
|  | // call through so we can see the nested ops | 
|  | this->INHERITED::onDrawDrawable(drawable, matrix); | 
|  | } | 
|  |  | 
|  | void SkLuaCanvas::onDrawVerticesObject(const SkVertices*, const SkVertices::Bone[], int, | 
|  | SkBlendMode, const SkPaint& paint) { | 
|  | AUTO_LUA("drawVertices"); | 
|  | lua.pushPaint(paint, "paint"); | 
|  | } |