/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/GrStyle.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/gl/GrGLPath.h"
#include "src/gpu/gl/GrGLPathRendering.h"

namespace {
inline GrGLubyte verb_to_gl_path_cmd(SkPath::Verb verb) {
    static const GrGLubyte gTable[] = {
        GR_GL_MOVE_TO,
        GR_GL_LINE_TO,
        GR_GL_QUADRATIC_CURVE_TO,
        GR_GL_CONIC_CURVE_TO,
        GR_GL_CUBIC_CURVE_TO,
        GR_GL_CLOSE_PATH,
    };
    GR_STATIC_ASSERT(0 == SkPath::kMove_Verb);
    GR_STATIC_ASSERT(1 == SkPath::kLine_Verb);
    GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb);
    GR_STATIC_ASSERT(3 == SkPath::kConic_Verb);
    GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb);
    GR_STATIC_ASSERT(5 == SkPath::kClose_Verb);

    SkASSERT(verb >= 0 && (size_t)verb < SK_ARRAY_COUNT(gTable));
    return gTable[verb];
}

#ifdef SK_DEBUG
inline int num_coords(SkPath::Verb verb) {
    static const int gTable[] = {
        2, // move
        2, // line
        4, // quad
        5, // conic
        6, // cubic
        0, // close
    };
    GR_STATIC_ASSERT(0 == SkPath::kMove_Verb);
    GR_STATIC_ASSERT(1 == SkPath::kLine_Verb);
    GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb);
    GR_STATIC_ASSERT(3 == SkPath::kConic_Verb);
    GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb);
    GR_STATIC_ASSERT(5 == SkPath::kClose_Verb);

    SkASSERT(verb >= 0 && (size_t)verb < SK_ARRAY_COUNT(gTable));
    return gTable[verb];
}
#endif

inline GrGLenum join_to_gl_join(SkPaint::Join join) {
    static GrGLenum gSkJoinsToGrGLJoins[] = {
        GR_GL_MITER_REVERT,
        GR_GL_ROUND,
        GR_GL_BEVEL
    };
    return gSkJoinsToGrGLJoins[join];
    GR_STATIC_ASSERT(0 == SkPaint::kMiter_Join);
    GR_STATIC_ASSERT(1 == SkPaint::kRound_Join);
    GR_STATIC_ASSERT(2 == SkPaint::kBevel_Join);
    GR_STATIC_ASSERT(SK_ARRAY_COUNT(gSkJoinsToGrGLJoins) == SkPaint::kJoinCount);
}

inline GrGLenum cap_to_gl_cap(SkPaint::Cap cap) {
    static GrGLenum gSkCapsToGrGLCaps[] = {
        GR_GL_FLAT,
        GR_GL_ROUND,
        GR_GL_SQUARE
    };
    return gSkCapsToGrGLCaps[cap];
    GR_STATIC_ASSERT(0 == SkPaint::kButt_Cap);
    GR_STATIC_ASSERT(1 == SkPaint::kRound_Cap);
    GR_STATIC_ASSERT(2 == SkPaint::kSquare_Cap);
    GR_STATIC_ASSERT(SK_ARRAY_COUNT(gSkCapsToGrGLCaps) == SkPaint::kCapCount);
}

#ifdef SK_DEBUG
inline void verify_floats(const float* floats, int count) {
    for (int i = 0; i < count; ++i) {
        SkASSERT(!SkScalarIsNaN(SkFloatToScalar(floats[i])));
    }
}
#endif

inline void points_to_coords(const SkPoint points[], size_t first_point, size_t amount,
                             GrGLfloat coords[]) {
    for (size_t i = 0;  i < amount; ++i) {
        coords[i * 2] =  SkScalarToFloat(points[first_point + i].fX);
        coords[i * 2 + 1] = SkScalarToFloat(points[first_point + i].fY);
    }
}

template<bool checkForDegenerates>
inline bool init_path_object_for_general_path(GrGLGpu* gpu, GrGLuint pathID,
                                              const SkPath& skPath) {
    SkDEBUGCODE(int numCoords = 0);
    int verbCnt = skPath.countVerbs();
    int pointCnt = skPath.countPoints();
    int minCoordCnt = pointCnt * 2;

    SkSTArray<16, GrGLubyte, true> pathCommands(verbCnt);
    SkSTArray<16, GrGLfloat, true> pathCoords(minCoordCnt);
    bool lastVerbWasMove = true; // A path with just "close;" means "moveto(0,0); close;"
    SkPoint points[4];
    SkPath::RawIter iter(skPath);
    SkPath::Verb verb;
    while ((verb = iter.next(points)) != SkPath::kDone_Verb) {
        pathCommands.push_back(verb_to_gl_path_cmd(verb));
        GrGLfloat coords[6];
        int coordsForVerb;
        switch (verb) {
            case SkPath::kMove_Verb:
                if (checkForDegenerates) {
                    lastVerbWasMove = true;
                }
                points_to_coords(points, 0, 1, coords);
                coordsForVerb = 2;
                break;
            case SkPath::kLine_Verb:
                if (checkForDegenerates) {
                    if (SkPath::IsLineDegenerate(points[0], points[1], true)) {
                        return false;
                    }
                    lastVerbWasMove = false;
                }

                points_to_coords(points, 1, 1, coords);
                coordsForVerb = 2;
                break;
            case SkPath::kConic_Verb:
                if (checkForDegenerates) {
                    if (SkPath::IsQuadDegenerate(points[0], points[1], points[2], true)) {
                        return false;
                    }
                    lastVerbWasMove = false;
                }
                points_to_coords(points, 1, 2, coords);
                coords[4] = SkScalarToFloat(iter.conicWeight());
                coordsForVerb = 5;
                break;
            case SkPath::kQuad_Verb:
                if (checkForDegenerates) {
                    if (SkPath::IsQuadDegenerate(points[0], points[1], points[2], true)) {
                        return false;
                    }
                    lastVerbWasMove = false;
                }
                points_to_coords(points, 1, 2, coords);
                coordsForVerb = 4;
                break;
            case SkPath::kCubic_Verb:
                if (checkForDegenerates) {
                    if (SkPath::IsCubicDegenerate(points[0], points[1], points[2], points[3],
                                                  true)) {
                        return false;
                    }
                    lastVerbWasMove = false;
                }
                points_to_coords(points, 1, 3, coords);
                coordsForVerb = 6;
                break;
            case SkPath::kClose_Verb:
                if (checkForDegenerates) {
                    if (lastVerbWasMove) {
                        // Interpret "move(x,y);close;" as "move(x,y);lineto(x,y);close;".
                        // which produces a degenerate segment.
                        return false;
                    }
                }
                continue;
            default:
                SkASSERT(false);  // Not reached.
                continue;
        }
        SkDEBUGCODE(numCoords += num_coords(verb));
        SkDEBUGCODE(verify_floats(coords, coordsForVerb));
        pathCoords.push_back_n(coordsForVerb, coords);
    }
    SkASSERT(verbCnt == pathCommands.count());
    SkASSERT(numCoords == pathCoords.count());

    GR_GL_CALL(gpu->glInterface(),
               PathCommands(pathID, pathCommands.count(), pathCommands.begin(),
                            pathCoords.count(), GR_GL_FLOAT, pathCoords.begin()));
    return true;
}

/*
 * For now paths only natively support winding and even odd fill types
 */
static GrPathRendering::FillType convert_skpath_filltype(SkPathFillType fill) {
    switch (fill) {
        default:
            SK_ABORT("Incomplete Switch\n");
        case SkPathFillType::kWinding:
        case SkPathFillType::kInverseWinding:
            return GrPathRendering::kWinding_FillType;
        case SkPathFillType::kEvenOdd:
        case SkPathFillType::kInverseEvenOdd:
            return GrPathRendering::kEvenOdd_FillType;
    }
}

} // namespace

bool GrGLPath::InitPathObjectPathDataCheckingDegenerates(GrGLGpu* gpu, GrGLuint pathID,
                                                         const SkPath& skPath) {
    return init_path_object_for_general_path<true>(gpu, pathID, skPath);
}

void GrGLPath::InitPathObjectPathData(GrGLGpu* gpu,
                                      GrGLuint pathID,
                                      const SkPath& skPath) {
    SkASSERT(!skPath.isEmpty());

#if 1  //  SK_SCALAR_IS_FLOAT
    // This branch does type punning, converting SkPoint* to GrGLfloat*.
    if ((skPath.getSegmentMasks() & SkPath::kConic_SegmentMask) == 0) {
        int verbCnt = skPath.countVerbs();
        int pointCnt = skPath.countPoints();
        int coordCnt = pointCnt * 2;
        SkAutoSTArray<16, GrGLubyte> pathCommands(verbCnt);
        SkAutoSTArray<16, GrGLfloat> pathCoords(coordCnt);

        static_assert(sizeof(SkPoint) == sizeof(GrGLfloat) * 2, "sk_point_not_two_floats");

        skPath.getPoints(reinterpret_cast<SkPoint*>(&pathCoords[0]), pointCnt);
        skPath.getVerbs(&pathCommands[0], verbCnt);

        SkDEBUGCODE(int verbCoordCnt = 0);
        for (int i = 0; i < verbCnt; ++i) {
            SkPath::Verb v = static_cast<SkPath::Verb>(pathCommands[i]);
            pathCommands[i] = verb_to_gl_path_cmd(v);
            SkDEBUGCODE(verbCoordCnt += num_coords(v));
        }
        SkASSERT(verbCnt == pathCommands.count());
        SkASSERT(verbCoordCnt == pathCoords.count());
        SkDEBUGCODE(verify_floats(&pathCoords[0], pathCoords.count()));
        GR_GL_CALL(gpu->glInterface(), PathCommands(pathID, pathCommands.count(), &pathCommands[0],
                                                    pathCoords.count(), GR_GL_FLOAT,
                                                    &pathCoords[0]));
        return;
    }
#endif
    SkAssertResult(init_path_object_for_general_path<false>(gpu, pathID, skPath));
}

void GrGLPath::InitPathObjectStroke(GrGLGpu* gpu, GrGLuint pathID, const SkStrokeRec& stroke) {
    SkASSERT(!stroke.isHairlineStyle());
    GR_GL_CALL(gpu->glInterface(),
               PathParameterf(pathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth())));
    GR_GL_CALL(gpu->glInterface(),
               PathParameterf(pathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter())));
    GrGLenum join = join_to_gl_join(stroke.getJoin());
    GR_GL_CALL(gpu->glInterface(), PathParameteri(pathID, GR_GL_PATH_JOIN_STYLE, join));
    GrGLenum cap = cap_to_gl_cap(stroke.getCap());
    GR_GL_CALL(gpu->glInterface(), PathParameteri(pathID, GR_GL_PATH_END_CAPS, cap));
    GR_GL_CALL(gpu->glInterface(), PathParameterf(pathID, GR_GL_PATH_STROKE_BOUND, 0.02f));
}

void GrGLPath::InitPathObjectEmptyPath(GrGLGpu* gpu, GrGLuint pathID) {
    GR_GL_CALL(gpu->glInterface(), PathCommands(pathID, 0, nullptr, 0, GR_GL_FLOAT, nullptr));
}

GrGLPath::GrGLPath(GrGLGpu* gpu, const SkPath& origSkPath, const GrStyle& style)
    : INHERITED(gpu, origSkPath, style),
      fPathID(gpu->glPathRendering()->genPaths(1)) {

    if (origSkPath.isEmpty()) {
        InitPathObjectEmptyPath(gpu, fPathID);
        fShouldStroke = false;
        fShouldFill = false;
    } else {
        const SkPath* skPath = &origSkPath;
        SkTLazy<SkPath> tmpPath;
        SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);

        if (style.pathEffect()) {
            // Skia stroking and NVPR stroking differ with respect to dashing
            // pattern.
            // Convert a dashing (or other path effect) to either a stroke or a fill.
            if (style.applyPathEffectToPath(tmpPath.init(), &stroke, *skPath, SK_Scalar1)) {
                skPath = tmpPath.get();
            }
        } else {
            stroke = style.strokeRec();
        }

        bool didInit = false;
        if (stroke.needToApply() && stroke.getCap() != SkPaint::kButt_Cap) {
            // Skia stroking and NVPR stroking differ with respect to stroking
            // end caps of empty subpaths.
            // Convert stroke to fill if path contains empty subpaths.
            didInit = InitPathObjectPathDataCheckingDegenerates(gpu, fPathID, *skPath);
            if (!didInit) {
                if (!tmpPath.isValid()) {
                    tmpPath.init();
                }
                SkAssertResult(stroke.applyToPath(tmpPath.get(), *skPath));
                skPath = tmpPath.get();
                stroke.setFillStyle();
            }
        }

        if (!didInit) {
            InitPathObjectPathData(gpu, fPathID, *skPath);
        }

        fShouldStroke = stroke.needToApply();
        fShouldFill = stroke.isFillStyle() ||
                stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style;

        fFillType = convert_skpath_filltype(skPath->getFillType());
        fBounds = skPath->getBounds();
        SkScalar radius = stroke.getInflationRadius();
        fBounds.outset(radius, radius);
        if (fShouldStroke) {
            InitPathObjectStroke(gpu, fPathID, stroke);
        }
    }

    this->registerWithCache(SkBudgeted::kYes);
}

void GrGLPath::onRelease() {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);

    if (0 != fPathID) {
        static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fPathID, 1);
        fPathID = 0;
    }

    INHERITED::onRelease();
}

void GrGLPath::onAbandon() {
    fPathID = 0;

    INHERITED::onAbandon();
}
