Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / utils / SkLua.cpp
index 8bc646f..9880fe4 100644 (file)
@@ -6,8 +6,14 @@
  */
 
 #include "SkLua.h"
+
+#if SK_SUPPORT_GPU
+#include "GrReducedClip.h"
+#endif
+
 #include "SkCanvas.h"
 #include "SkData.h"
+#include "SkDecodingImageGenerator.h"
 #include "SkDocument.h"
 #include "SkImage.h"
 #include "SkMatrix.h"
@@ -16,6 +22,7 @@
 #include "SkPixelRef.h"
 #include "SkRRect.h"
 #include "SkString.h"
+#include "SkTextBlob.h"
 #include "SkTypeface.h"
 
 extern "C" {
@@ -38,7 +45,9 @@ DEF_MTNAME(SkMatrix)
 DEF_MTNAME(SkRRect)
 DEF_MTNAME(SkPath)
 DEF_MTNAME(SkPaint)
+DEF_MTNAME(SkPathEffect)
 DEF_MTNAME(SkShader)
+DEF_MTNAME(SkTextBlob)
 DEF_MTNAME(SkTypeface)
 
 template <typename T> T* push_new(lua_State* L) {
@@ -150,6 +159,10 @@ static void setarray_number(lua_State* L, int index, double value) {
     lua_rawseti(L, -2, index);
 }
 
+static void setarray_scalar(lua_State* L, int index, SkScalar value) {
+    setarray_number(L, index, SkScalarToLua(value));
+}
+
 void SkLua::pushBool(bool value, const char key[]) {
     lua_pushboolean(fL, value);
     CHECK_SETFIELD(key);
@@ -200,6 +213,27 @@ void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
     CHECK_SETFIELD(key);
 }
 
+void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
+    lua_newtable(fL);
+    for (int i = 0; i < count; ++i) {
+        // make it base-1 to match lua convention
+        lua_newtable(fL);
+        this->pushScalar(array[i].fX, "x");
+        this->pushScalar(array[i].fY, "y");
+        lua_rawseti(fL, -2, i + 1);
+    }
+    CHECK_SETFIELD(key);
+}
+
+void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
+    lua_newtable(fL);
+    for (int i = 0; i < count; ++i) {
+        // make it base-1 to match lua convention
+        setarray_scalar(fL, i + 1, array[i]);
+    }
+    CHECK_SETFIELD(key);
+}
+
 void SkLua::pushRect(const SkRect& r, const char key[]) {
     lua_newtable(fL);
     setfield_scalar(fL, "left", r.fLeft);
@@ -214,6 +248,14 @@ void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
     CHECK_SETFIELD(key);
 }
 
+void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
+    lua_newtable(fL);
+    setfield_scalar(fL, "phase", info.fPhase);
+    this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
+    CHECK_SETFIELD(key);
+}
+
+
 void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
     push_obj(fL, matrix);
     CHECK_SETFIELD(key);
@@ -234,6 +276,78 @@ void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
     CHECK_SETFIELD(key);
 }
 
+void SkLua::pushTextBlob(const SkTextBlob* blob, const char key[]) {
+    push_ref(fL, const_cast<SkTextBlob*>(blob));
+    CHECK_SETFIELD(key);
+}
+
+static const char* element_type(SkClipStack::Element::Type type) {
+    switch (type) {
+        case SkClipStack::Element::kEmpty_Type:
+            return "empty";
+        case SkClipStack::Element::kRect_Type:
+            return "rect";
+        case SkClipStack::Element::kRRect_Type:
+            return "rrect";
+        case SkClipStack::Element::kPath_Type:
+            return "path";
+    }
+    return "unknown";
+}
+
+static const char* region_op(SkRegion::Op op) {
+    switch (op) {
+        case SkRegion::kDifference_Op:
+            return "difference";
+        case SkRegion::kIntersect_Op:
+            return "intersect";
+        case SkRegion::kUnion_Op:
+            return "union";
+        case SkRegion::kXOR_Op:
+            return "xor";
+        case SkRegion::kReverseDifference_Op:
+            return "reverse-difference";
+        case SkRegion::kReplace_Op:
+            return "replace";
+    }
+    return "unknown";
+}
+
+void SkLua::pushClipStack(const SkClipStack& stack, const char* key) {
+    lua_newtable(fL);
+    SkClipStack::B2TIter iter(stack);
+    const SkClipStack::Element* element;
+    int i = 0;
+    while ((element = iter.next())) {
+        this->pushClipStackElement(*element);
+        lua_rawseti(fL, -2, ++i);
+    }
+    CHECK_SETFIELD(key);
+}
+
+void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) {
+    lua_newtable(fL);
+    SkClipStack::Element::Type type = element.getType();
+    this->pushString(element_type(type), "type");
+    switch (type) {
+        case SkClipStack::Element::kEmpty_Type:
+            break;
+        case SkClipStack::Element::kRect_Type:
+            this->pushRect(element.getRect(), "rect");
+            break;
+        case SkClipStack::Element::kRRect_Type:
+            this->pushRRect(element.getRRect(), "rrect");
+            break;
+        case SkClipStack::Element::kPath_Type:
+            this->pushPath(element.getPath(), "path");
+            break;
+    }
+    this->pushString(region_op(element.getOp()), "op");
+    this->pushBool(element.isAA(), "aa");
+    CHECK_SETFIELD(key);
+}
+
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -342,7 +456,7 @@ static int lcanvas_drawImage(lua_State* L) {
         paint.setAlpha(SkScalarRoundToInt(lua2scalar(L, 5) * 255));
         paintPtr = &paint;
     }
-    image->draw(canvas, x, y, paintPtr);
+    canvas->drawImage(image, x, y, paintPtr);
     return 0;
 }
 
@@ -377,6 +491,50 @@ static int lcanvas_getTotalMatrix(lua_State* L) {
     return 1;
 }
 
+static int lcanvas_getClipStack(lua_State* L) {
+    SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack());
+    return 1;
+}
+
+int SkLua::lcanvas_getReducedClipStack(lua_State* L) {
+#if SK_SUPPORT_GPU
+    const SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
+    SkISize layerSize = canvas->getTopLayerSize();
+    SkIPoint layerOrigin = canvas->getTopLayerOrigin();
+    SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY,
+                                            layerSize.fWidth, layerSize.fHeight);
+
+    GrReducedClip::ElementList elements;
+    GrReducedClip::InitialState initialState;
+    int32_t genID;
+    SkIRect resultBounds;
+
+    const SkClipStack& stack = *canvas->getClipStack();
+
+    GrReducedClip::ReduceClipStack(stack,
+                                   queryBounds,
+                                   &elements,
+                                   &genID,
+                                   &initialState,
+                                   &resultBounds,
+                                   NULL);
+
+    GrReducedClip::ElementList::Iter iter(elements);
+    int i = 0;
+    lua_newtable(L);
+    while(iter.get()) {
+        SkLua(L).pushClipStackElement(*iter.get());
+        iter.next();
+        lua_rawseti(L, -2, ++i);
+    }
+    // Currently this only returns the element list to lua, not the initial state or result bounds.
+    // It could return these as additional items on the lua stack.
+    return 1;
+#else
+    return 0;
+#endif
+}
+
 static int lcanvas_save(lua_State* L) {
     lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
     return 1;
@@ -412,7 +570,7 @@ static int lcanvas_gc(lua_State* L) {
     return 0;
 }
 
-static const struct luaL_Reg gSkCanvas_Methods[] = {
+const struct luaL_Reg gSkCanvas_Methods[] = {
     { "drawColor", lcanvas_drawColor },
     { "drawRect", lcanvas_drawRect },
     { "drawOval", lcanvas_drawOval },
@@ -422,6 +580,10 @@ static const struct luaL_Reg gSkCanvas_Methods[] = {
     { "drawText", lcanvas_drawText },
     { "getSaveCount", lcanvas_getSaveCount },
     { "getTotalMatrix", lcanvas_getTotalMatrix },
+    { "getClipStack", lcanvas_getClipStack },
+#if SK_SUPPORT_GPU
+    { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
+#endif
     { "save", lcanvas_save },
     { "restore", lcanvas_restore },
     { "scale", lcanvas_scale },
@@ -725,6 +887,16 @@ static int lpaint_getShader(lua_State* L) {
     return 0;
 }
 
+static int lpaint_getPathEffect(lua_State* L) {
+    const SkPaint* paint = get_obj<SkPaint>(L, 1);
+    SkPathEffect* pe = paint->getPathEffect();
+    if (pe) {
+        push_ref(L, pe);
+        return 1;
+    }
+    return 0;
+}
+
 static int lpaint_gc(lua_State* L) {
     get_obj<SkPaint>(L, 1)->~SkPaint();
     return 0;
@@ -768,6 +940,7 @@ static const struct luaL_Reg gSkPaint_Methods[] = {
     { "getFontMetrics", lpaint_getFontMetrics },
     { "getEffects", lpaint_getEffects },
     { "getShader", lpaint_getShader },
+    { "getPathEffect", lpaint_getPathEffect },
     { "__gc", lpaint_gc },
     { NULL, NULL }
 };
@@ -861,6 +1034,35 @@ static const struct luaL_Reg gSkShader_Methods[] = {
 
 ///////////////////////////////////////////////////////////////////////////////
 
+static int lpatheffect_asADash(lua_State* L) {
+    SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
+    if (pe) {
+        SkPathEffect::DashInfo info;
+        SkPathEffect::DashType dashType = pe->asADash(&info);
+        if (SkPathEffect::kDash_DashType == dashType) {
+            SkAutoTArray<SkScalar> intervals(info.fCount);
+            info.fIntervals = intervals.get();
+            pe->asADash(&info);
+            SkLua(L).pushDash(info);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static int lpatheffect_gc(lua_State* L) {
+    get_ref<SkPathEffect>(L, 1)->unref();
+    return 0;
+}
+
+static const struct luaL_Reg gSkPathEffect_Methods[] = {
+    { "asADash",        lpatheffect_asADash },
+    { "__gc",           lpatheffect_gc },
+    { NULL, NULL }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
 static int lmatrix_getType(lua_State* L) {
     SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
 
@@ -908,6 +1110,73 @@ static int lpath_getBounds(lua_State* L) {
     return 1;
 }
 
+static const char* fill_type_to_str(SkPath::FillType fill) {
+    switch (fill) {
+        case SkPath::kEvenOdd_FillType:
+            return "even-odd";
+        case SkPath::kWinding_FillType:
+            return "winding";
+        case SkPath::kInverseEvenOdd_FillType:
+            return "inverse-even-odd";
+        case SkPath::kInverseWinding_FillType:
+            return "inverse-winding";
+    }
+    return "unknown";
+}
+
+static int lpath_getFillType(lua_State* L) {
+    SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
+    SkLua(L).pushString(fill_type_to_str(fill));
+    return 1;
+}
+
+static SkString segment_masks_to_str(uint32_t segmentMasks) {
+    SkString result;
+    bool first = true;
+    if (SkPath::kLine_SegmentMask & segmentMasks) {
+        result.append("line");
+        first = false;
+        SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
+    }
+    if (SkPath::kQuad_SegmentMask & segmentMasks) {
+        if (!first) {
+            result.append(" ");
+        }
+        result.append("quad");
+        first = false;
+        SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
+    }
+    if (SkPath::kConic_SegmentMask & segmentMasks) {
+        if (!first) {
+            result.append(" ");
+        }
+        result.append("conic");
+        first = false;
+        SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
+    }
+    if (SkPath::kCubic_SegmentMask & segmentMasks) {
+        if (!first) {
+            result.append(" ");
+        }
+        result.append("cubic");
+        SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
+    }
+    SkASSERT(0 == segmentMasks);
+    return result;
+}
+
+static int lpath_getSegmentTypes(lua_State* L) {
+    uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
+    SkLua(L).pushString(segment_masks_to_str(segMasks));
+    return 1;
+}
+
+static int lpath_isConvex(lua_State* L) {
+    bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
+    SkLua(L).pushBool(isConvex);
+    return 1;
+}
+
 static int lpath_isEmpty(lua_State* L) {
     lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
     return 1;
@@ -950,6 +1219,11 @@ static int lpath_isNestedRects(lua_State* L) {
     return ret_count;
 }
 
+static int lpath_countPoints(lua_State* L) {
+    lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
+    return 1;
+}
+
 static int lpath_reset(lua_State* L) {
     get_obj<SkPath>(L, 1)->reset();
     return 0;
@@ -990,9 +1264,13 @@ static int lpath_gc(lua_State* L) {
 
 static const struct luaL_Reg gSkPath_Methods[] = {
     { "getBounds", lpath_getBounds },
+    { "getFillType", lpath_getFillType },
+    { "getSegmentTypes", lpath_getSegmentTypes },
+    { "isConvex", lpath_isConvex },
     { "isEmpty", lpath_isEmpty },
     { "isRect", lpath_isRect },
     { "isNestedRects", lpath_isNestedRects },
+    { "countPoints", lpath_countPoints },
     { "reset", lpath_reset },
     { "moveTo", lpath_moveTo },
     { "lineTo", lpath_lineTo },
@@ -1012,6 +1290,7 @@ static const char* rrect_type(const SkRRect& rr) {
         case SkRRect::kRect_Type: return "rect";
         case SkRRect::kOval_Type: return "oval";
         case SkRRect::kSimple_Type: return "simple";
+        case SkRRect::kNinePatch_Type: return "nine-patch";
         case SkRRect::kComplex_Type: return "complex";
     }
     SkDEBUGFAIL("never get here");
@@ -1029,7 +1308,7 @@ static int lrrect_type(lua_State* L) {
 }
 
 static int lrrect_radii(lua_State* L) {
-    int corner = lua_tointeger(L, 2);
+    int corner = SkToInt(lua_tointeger(L, 2));
     SkVector v;
     if (corner < 0 || corner > 3) {
         SkDebugf("bad corner index %d", corner);
@@ -1182,7 +1461,9 @@ static int lsk_loadImage(lua_State* L) {
         const char* name = lua_tolstring(L, 1, NULL);
         SkAutoDataUnref data(SkData::NewFromFileName(name));
         if (data.get()) {
-            SkImage* image = SkImage::NewEncodedData(data.get());
+            SkImage* image = SkImage::NewFromGenerator(
+                SkDecodingImageGenerator::Create(data, SkDecodingImageGenerator::Options()));
+
             if (image) {
                 push_ref(L, image);
                 image->unref();
@@ -1222,8 +1503,9 @@ void SkLua::Load(lua_State* L) {
     REG_CLASS(L, SkCanvas);
     REG_CLASS(L, SkDocument);
     REG_CLASS(L, SkImage);
-    REG_CLASS(L, SkPath);
     REG_CLASS(L, SkPaint);
+    REG_CLASS(L, SkPath);
+    REG_CLASS(L, SkPathEffect);
     REG_CLASS(L, SkRRect);
     REG_CLASS(L, SkShader);
     REG_CLASS(L, SkTypeface);