/*
 * 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/core/SkPathPriv.h"
#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,
    };
    static_assert(0 == SkPath::kMove_Verb);
    static_assert(1 == SkPath::kLine_Verb);
    static_assert(2 == SkPath::kQuad_Verb);
    static_assert(3 == SkPath::kConic_Verb);
    static_assert(4 == SkPath::kCubic_Verb);
    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
    };
    static_assert(0 == SkPath::kMove_Verb);
    static_assert(1 == SkPath::kLine_Verb);
    static_assert(2 == SkPath::kQuad_Verb);
    static_assert(3 == SkPath::kConic_Verb);
    static_assert(4 == SkPath::kCubic_Verb);
    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];
    static_assert(0 == SkPaint::kMiter_Join);
    static_assert(1 == SkPaint::kRound_Join);
    static_assert(2 == SkPaint::kBevel_Join);
    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];
    static_assert(0 == SkPaint::kButt_Cap);
    static_assert(1 == SkPaint::kRound_Cap);
    static_assert(2 == SkPaint::kSquare_Cap);
    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;"
    for (auto [verb, points, w] : SkPathPriv::Iterate(skPath)) {
        pathCommands.push_back(verb_to_gl_path_cmd((SkPath::Verb)verb));
        GrGLfloat coords[6];
        int coordsForVerb;
        switch (verb) {
            case SkPathVerb::kMove:
                if (checkForDegenerates) {
                    lastVerbWasMove = true;
                }
                points_to_coords(points, 0, 1, coords);
                coordsForVerb = 2;
                break;
            case SkPathVerb::kLine:
                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 SkPathVerb::kConic:
                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(*w);
                coordsForVerb = 5;
                break;
            case SkPathVerb::kQuad:
                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 SkPathVerb::kCubic:
                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 SkPathVerb::kClose:
                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;
        }
        SkDEBUGCODE(numCoords += num_coords((SkPath::Verb)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();
}
