Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrAARectRenderer.cpp
index ee7c024..eebda01 100644 (file)
@@ -13,8 +13,6 @@
 #include "SkColorPriv.h"
 #include "effects/GrVertexEffect.h"
 
-SK_DEFINE_INST_COUNT(GrAARectRenderer)
-
 ///////////////////////////////////////////////////////////////////////////////
 class GrGLAlignedRectEffect;
 
@@ -263,12 +261,12 @@ namespace {
 
 extern const GrVertexAttrib gAARectCoverageAttribs[] = {
     {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
-    {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
+    {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding},
 };
 
 extern const GrVertexAttrib gAARectColorAttribs[] = {
     {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
-    {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
+    {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
 };
 
 static void set_aa_rect_vertex_attributes(GrDrawState* drawState, bool useCoverage) {
@@ -279,7 +277,7 @@ static void set_aa_rect_vertex_attributes(GrDrawState* drawState, bool useCovera
     }
 }
 
-static void set_inset_fan(GrPoint* pts, size_t stride,
+static void set_inset_fan(SkPoint* pts, size_t stride,
                           const SkRect& r, SkScalar dx, SkScalar dy) {
     pts->setRectFan(r.fLeft + dx, r.fTop + dy,
                     r.fRight - dx, r.fBottom - dy, stride);
@@ -289,7 +287,8 @@ static void set_inset_fan(GrPoint* pts, size_t stride,
 
 void GrAARectRenderer::reset() {
     SkSafeSetNull(fAAFillRectIndexBuffer);
-    SkSafeSetNull(fAAStrokeRectIndexBuffer);
+    SkSafeSetNull(fAAMiterStrokeRectIndexBuffer);
+    SkSafeSetNull(fAABevelStrokeRectIndexBuffer);
 }
 
 static const uint16_t gFillAARectIdx[] = {
@@ -300,7 +299,7 @@ static const uint16_t gFillAARectIdx[] = {
     4, 5, 6, 6, 7, 4,
 };
 
-static const int kIndicesPerAAFillRect = GR_ARRAY_COUNT(gFillAARectIdx);
+static const int kIndicesPerAAFillRect = SK_ARRAY_COUNT(gFillAARectIdx);
 static const int kVertsPerAAFillRect = 8;
 static const int kNumAAFillRectsInIndexBuffer = 256;
 
@@ -328,7 +327,7 @@ GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
             }
             if (useTempData) {
                 if (!fAAFillRectIndexBuffer->updateData(data, kAAFillRectIndexBufferSize)) {
-                    GrCrash("Can't get AA Fill Rect indices into buffer!");
+                    SkFAIL("Can't get AA Fill Rect indices into buffer!");
                 }
                 SkDELETE_ARRAY(data);
             } else {
@@ -340,7 +339,7 @@ GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
     return fAAFillRectIndexBuffer;
 }
 
-static const uint16_t gStrokeAARectIdx[] = {
+static const uint16_t gMiterStrokeAARectIdx[] = {
     0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
     1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
     2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
@@ -357,24 +356,98 @@ static const uint16_t gStrokeAARectIdx[] = {
     3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
 };
 
-int GrAARectRenderer::aaStrokeRectIndexCount() {
-    return GR_ARRAY_COUNT(gStrokeAARectIdx);
+/**
+ * As in miter-stroke, index = a + b, and a is the current index, b is the shift
+ * from the first index. The index layout:
+ * outer AA line: 0~3, 4~7
+ * outer edge:    8~11, 12~15
+ * inner edge:    16~19
+ * inner AA line: 20~23
+ * Following comes a bevel-stroke rect and its indices:
+ *
+ *           4                                 7
+ *            *********************************
+ *          *   ______________________________  *
+ *         *  / 12                          15 \  *
+ *        *  /                                  \  *
+ *     0 *  |8     16_____________________19  11 |  * 3
+ *       *  |       |                    |       |  *
+ *       *  |       |  ****************  |       |  *
+ *       *  |       |  * 20        23 *  |       |  *
+ *       *  |       |  *              *  |       |  *
+ *       *  |       |  * 21        22 *  |       |  *
+ *       *  |       |  ****************  |       |  *
+ *       *  |       |____________________|       |  *
+ *     1 *  |9    17                      18   10|  * 2
+ *        *  \                                  /  *
+ *         *  \13 __________________________14/  *
+ *          *                                   *
+ *           **********************************
+ *          5                                  6
+ */
+static const uint16_t gBevelStrokeAARectIdx[] = {
+    // Draw outer AA, from outer AA line to outer edge, shift is 0.
+    0 + 0, 1 + 0, 9 + 0, 9 + 0, 8 + 0, 0 + 0,
+    1 + 0, 5 + 0, 13 + 0, 13 + 0, 9 + 0, 1 + 0,
+    5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0,
+    6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0,
+    2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0,
+    3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0,
+    7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0,
+    4 + 0, 0 + 0, 8 + 0, 8 + 0, 12 + 0, 4 + 0,
+
+    // Draw the stroke, from outer edge to inner edge, shift is 8.
+    0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8,
+    1 + 8, 5 + 8, 9 + 8,
+    5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8,
+    6 + 8, 2 + 8, 10 + 8,
+    2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8,
+    3 + 8, 7 + 8, 11 + 8,
+    7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8,
+    4 + 8, 0 + 8, 8 + 8,
+
+    // Draw the inner AA, from inner edge to inner AA line, shift is 16.
+    0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16,
+    1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16,
+    2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16,
+    3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16,
+};
+
+int GrAARectRenderer::aaStrokeRectIndexCount(bool miterStroke) {
+    return miterStroke ? SK_ARRAY_COUNT(gMiterStrokeAARectIdx) :
+                         SK_ARRAY_COUNT(gBevelStrokeAARectIdx);
 }
 
-GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu) {
-    if (NULL == fAAStrokeRectIndexBuffer) {
-        fAAStrokeRectIndexBuffer =
-                  gpu->createIndexBuffer(sizeof(gStrokeAARectIdx), false);
-        if (NULL != fAAStrokeRectIndexBuffer) {
+GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu, bool miterStroke) {
+    if (miterStroke) {
+        if (NULL == fAAMiterStrokeRectIndexBuffer) {
+            fAAMiterStrokeRectIndexBuffer =
+                gpu->createIndexBuffer(sizeof(gMiterStrokeAARectIdx), false);
+            if (NULL != fAAMiterStrokeRectIndexBuffer) {
 #ifdef SK_DEBUG
-            bool updated =
+                bool updated =
 #endif
-            fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
-                                                 sizeof(gStrokeAARectIdx));
-            GR_DEBUGASSERT(updated);
+                fAAMiterStrokeRectIndexBuffer->updateData(gMiterStrokeAARectIdx,
+                                                          sizeof(gMiterStrokeAARectIdx));
+                GR_DEBUGASSERT(updated);
+            }
         }
+        return fAAMiterStrokeRectIndexBuffer;
+    } else {
+        if (NULL == fAABevelStrokeRectIndexBuffer) {
+            fAABevelStrokeRectIndexBuffer =
+                gpu->createIndexBuffer(sizeof(gBevelStrokeAARectIdx), false);
+            if (NULL != fAABevelStrokeRectIndexBuffer) {
+#ifdef SK_DEBUG
+                bool updated =
+#endif
+                fAABevelStrokeRectIndexBuffer->updateData(gBevelStrokeAARectIdx,
+                                                          sizeof(gBevelStrokeAARectIdx));
+                GR_DEBUGASSERT(updated);
+            }
+        }
+        return fAABevelStrokeRectIndexBuffer;
     }
-    return fAAStrokeRectIndexBuffer;
 }
 
 void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
@@ -401,10 +474,10 @@ void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
 
     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
     size_t vsize = drawState->getVertexSize();
-    SkASSERT(sizeof(GrPoint) + sizeof(GrColor) == vsize);
+    SkASSERT(sizeof(SkPoint) + sizeof(GrColor) == vsize);
 
-    GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
-    GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
+    SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
+    SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vsize);
 
     SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1);
     inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
@@ -458,7 +531,7 @@ void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
         *((SkPoint*)((intptr_t)fan0Pos + 3 * vsize)) += vec[0] - vec[1];
     }
 
-    verts += sizeof(GrPoint);
+    verts += sizeof(SkPoint);
     for (int i = 0; i < 4; ++i) {
         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
     }
@@ -498,30 +571,30 @@ namespace {
 
 // Rotated
 struct RectVertex {
-    GrPoint fPos;
-    GrPoint fCenter;
-    GrPoint fDir;
-    GrPoint fWidthHeight;
+    SkPoint fPos;
+    SkPoint fCenter;
+    SkPoint fDir;
+    SkPoint fWidthHeight;
 };
 
 // Rotated
 extern const GrVertexAttrib gAARectVertexAttribs[] = {
     { kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding },
-    { kVec4f_GrVertexAttribType, sizeof(GrPoint),   kEffect_GrVertexAttribBinding },
-    { kVec2f_GrVertexAttribType, 3*sizeof(GrPoint), kEffect_GrVertexAttribBinding }
+    { kVec4f_GrVertexAttribType, sizeof(SkPoint),   kEffect_GrVertexAttribBinding },
+    { kVec2f_GrVertexAttribType, 3*sizeof(SkPoint), kEffect_GrVertexAttribBinding }
 };
 
 // Axis Aligned
 struct AARectVertex {
-    GrPoint fPos;
-    GrPoint fOffset;
-    GrPoint fWidthHeight;
+    SkPoint fPos;
+    SkPoint fOffset;
+    SkPoint fWidthHeight;
 };
 
 // Axis Aligned
 extern const GrVertexAttrib gAAAARectVertexAttribs[] = {
     { kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding },
-    { kVec4f_GrVertexAttribType, sizeof(GrPoint),   kEffect_GrVertexAttribBinding },
+    { kVec4f_GrVertexAttribType, sizeof(SkPoint),   kEffect_GrVertexAttribBinding },
 };
 
 };
@@ -622,7 +695,7 @@ void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu,
         devRect.fBottom + SK_ScalarHalf
     };
 
-    GrPoint widthHeight = {
+    SkPoint widthHeight = {
         SkScalarHalf(devRect.width()) + SK_ScalarHalf,
         SkScalarHalf(devRect.height()) + SK_ScalarHalf
     };
@@ -653,9 +726,10 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
                                     const SkRect& rect,
                                     const SkMatrix& combinedMatrix,
                                     const SkRect& devRect,
-                                    SkScalar width,
+                                    const SkStrokeRec* stroke,
                                     bool useVertexCoverage) {
-    GrVec devStrokeSize;
+    SkVector devStrokeSize;
+    SkScalar width = stroke->getWidth();
     if (width > 0) {
         devStrokeSize.set(width, width);
         combinedMatrix.mapVectors(&devStrokeSize, 1);
@@ -681,13 +755,19 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
     {
         SkScalar w = devRect.width() - dx;
         SkScalar h = devRect.height() - dy;
-        spare = GrMin(w, h);
+        spare = SkTMin(w, h);
     }
 
     SkRect devOutside(devRect);
     devOutside.outset(rx, ry);
 
-    if (spare <= 0) {
+    bool miterStroke = true;
+    // small miter limit means right angles show bevel...
+    if (stroke->getJoin() != SkPaint::kMiter_Join || stroke->getMiter() < SK_ScalarSqrt2) {
+        miterStroke = false;
+    }
+
+    if (spare <= 0 && miterStroke) {
         this->fillAARect(gpu, target, devOutside, SkMatrix::I(),
                          devOutside, useVertexCoverage);
         return;
@@ -696,24 +776,41 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
     SkRect devInside(devRect);
     devInside.inset(rx, ry);
 
-    this->geometryStrokeAARect(gpu, target, devOutside, devInside, useVertexCoverage);
+    SkRect devOutsideAssist(devRect);
+
+    // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist)
+    // to draw the outer of the rect. Because there are 8 vertices on the outer
+    // edge, while vertex number of inner edge is 4, the same as miter-stroke.
+    if (!miterStroke) {
+        devOutside.inset(0, ry);
+        devOutsideAssist.outset(0, ry);
+    }
+
+    this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist,
+                               devInside, useVertexCoverage, miterStroke);
 }
 
 void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
                                             GrDrawTarget* target,
                                             const SkRect& devOutside,
+                                            const SkRect& devOutsideAssist,
                                             const SkRect& devInside,
-                                            bool useVertexCoverage) {
+                                            bool useVertexCoverage,
+                                            bool miterStroke) {
     GrDrawState* drawState = target->drawState();
 
     set_aa_rect_vertex_attributes(drawState, useVertexCoverage);
 
-    GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
+    int innerVertexNum = 4;
+    int outerVertexNum = miterStroke ? 4 : 8;
+    int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
+
+    GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, 0);
     if (!geo.succeeded()) {
         GrPrintf("Failed to get space for vertices!\n");
         return;
     }
-    GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu);
+    GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu, miterStroke);
     if (NULL == indexBuffer) {
         GrPrintf("Failed to create index buffer!\n");
         return;
@@ -721,15 +818,15 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
 
     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
     size_t vsize = drawState->getVertexSize();
-    SkASSERT(sizeof(GrPoint) + sizeof(GrColor) == vsize);
+    SkASSERT(sizeof(SkPoint) + sizeof(GrColor) == vsize);
 
     // We create vertices for four nested rectangles. There are two ramps from 0 to full
     // coverage, one on the exterior of the stroke and the other on the interior.
     // The following pointers refer to the four rects, from outermost to innermost.
-    GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
-    GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
-    GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
-    GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
+    SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
+    SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vsize);
+    SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vsize);
+    SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vsize);
 
 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
     // TODO: this only really works if the X & Y margins are the same all around
@@ -737,23 +834,42 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
     SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRight);
     inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft);
     inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop);
-    inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom);
+    if (miterStroke) {
+        inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom);
+    } else {
+        inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - devInside.fBottom);
+    }
     SkASSERT(inset >= 0);
 #else
     SkScalar inset = SK_ScalarHalf;
 #endif
 
-    // outermost
-    set_inset_fan(fan0Pos, vsize, devOutside, -SK_ScalarHalf, -SK_ScalarHalf);
-    // inner two
-    set_inset_fan(fan1Pos, vsize, devOutside,  inset,  inset);
-    set_inset_fan(fan2Pos, vsize, devInside,  -inset, -inset);
-    // innermost
-    set_inset_fan(fan3Pos, vsize, devInside,   SK_ScalarHalf,  SK_ScalarHalf);
+    if (miterStroke) {
+        // outermost
+        set_inset_fan(fan0Pos, vsize, devOutside, -SK_ScalarHalf, -SK_ScalarHalf);
+        // inner two
+        set_inset_fan(fan1Pos, vsize, devOutside,  inset,  inset);
+        set_inset_fan(fan2Pos, vsize, devInside,  -inset, -inset);
+        // innermost
+        set_inset_fan(fan3Pos, vsize, devInside,   SK_ScalarHalf,  SK_ScalarHalf);
+    } else {
+        SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vsize);
+        SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertexNum + 4) * vsize);
+        // outermost
+        set_inset_fan(fan0Pos, vsize, devOutside, -SK_ScalarHalf, -SK_ScalarHalf);
+        set_inset_fan(fan0AssistPos, vsize, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf);
+        // outer one of the inner two
+        set_inset_fan(fan1Pos, vsize, devOutside,  inset,  inset);
+        set_inset_fan(fan1AssistPos, vsize, devOutsideAssist,  inset,  inset);
+        // inner one of the inner two
+        set_inset_fan(fan2Pos, vsize, devInside,  -inset, -inset);
+        // innermost
+        set_inset_fan(fan3Pos, vsize, devInside,   SK_ScalarHalf,  SK_ScalarHalf);
+    }
 
     // The outermost rect has 0 coverage
-    verts += sizeof(GrPoint);
-    for (int i = 0; i < 4; ++i) {
+    verts += sizeof(SkPoint);
+    for (int i = 0; i < outerVertexNum; ++i) {
         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
     }
 
@@ -777,20 +893,20 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
         }
     }
 
-    verts += 4 * vsize;
-    for (int i = 0; i < 8; ++i) {
+    verts += outerVertexNum * vsize;
+    for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
     }
 
     // The innermost rect has 0 coverage
-    verts += 8 * vsize;
-    for (int i = 0; i < 4; ++i) {
+    verts += (outerVertexNum + innerVertexNum) * vsize;
+    for (int i = 0; i < innerVertexNum; ++i) {
         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
     }
 
     target->setIndexSourceToBuffer(indexBuffer);
-    target->drawIndexed(kTriangles_GrPrimitiveType,
-                        0, 0, 16, aaStrokeRectIndexCount());
+    target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0,
+                        totalVertexNum, aaStrokeRectIndexCount(miterStroke));
 }
 
 void GrAARectRenderer::fillAANestedRects(GrGpu* gpu,
@@ -801,7 +917,7 @@ void GrAARectRenderer::fillAANestedRects(GrGpu* gpu,
     SkASSERT(combinedMatrix.rectStaysRect());
     SkASSERT(!rects[1].isEmpty());
 
-    SkRect devOutside, devInside;
+    SkRect devOutside, devOutsideAssist, devInside;
     combinedMatrix.mapRect(&devOutside, rects[0]);
     // can't call mapRect for devInside since it calls sort
     combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);
@@ -811,5 +927,6 @@ void GrAARectRenderer::fillAANestedRects(GrGpu* gpu,
         return;
     }
 
-    this->geometryStrokeAARect(gpu, target, devOutside, devInside, useVertexCoverage);
+    this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist,
+                               devInside, useVertexCoverage, true);
 }