
// Paint.hpp - interface for paint

#ifndef __Paint_hpp__
#define __Paint_hpp__

#include <GL/glew.h>

#include <Cg/double.hpp>
#include <Cg/vector/xyzw.hpp>
#include <Cg/vector.hpp>

using namespace Cg;

#include "polar/cpu/CPUStrokeTessellator.hpp"  // for StrokeTessellator::JoinEnum & CapEnum conversions

class Paint {
public:
    enum CapEnum {
        // This order is important to tessellation control shader!
        NO_CAP,
        ROUND_CAP,
        TRIANGULAR_CAP,
        SQUARE_CAP,
        CAP_ENUM_COUNT
    };
    enum JoinEnum {
        ROUND_JOIN,
        BEVEL,
        TRIANGULAR_JOIN,
        MITER_REVERT,
        MITER_TRUNCATE,
        NO_JOIN,
        JOIN_ENUM_COUNT
    };
private:
    static GLenum CapEnumToGLenum(CapEnum cap) {
        static const GLenum cap_enum_to_glenum[4] = {
            GL_FLAT,
            GL_ROUND_NV,
            GL_TRIANGULAR_NV,
            GL_SQUARE_NV
        };
        assert(cap < CAP_ENUM_COUNT);
        return cap_enum_to_glenum[cap];
    }
    float stroke_width;
    float arc_length_extension;
    CapEnum initial_end_cap;
    CapEnum terminal_end_cap;
    CapEnum initial_dash_cap;
    CapEnum terminal_dash_cap;
    JoinEnum join_style;
    float miter_limit;
    float3 fill_color;  // perceptually linear RGB
    float3 stroke_color;  // perceptually linear RGB
    float fill_opacity;
    float stroke_opacity;

public:
    Paint();
    Paint(const Paint& from);
    void resetToDefault();
    void setJoinStyle(JoinEnum js);
    void setStrokeWidth(float sw);
    void increaseStrokeWidth(float delta);
    void decreaseStrokeWidth(float delta);
    float ArcLengthExtension() const;
    void setArcLengthExtension(float ale);
    void increaseArcLengthExtension(float delta);
    void decreaseArcLengthExtension(float delta);
    void setMiterLimit(float ml);
    void increaseMiterLimit(float delta);
    void decreaseMiterLimit(float delta);
    JoinEnum JoinStyle() const;
    StrokeTessellator::JoinEnum StrokeTessellatorJoinStyle() const;
    static StrokeTessellator::CapEnum StrokeTessellatorCapEnum(Paint::CapEnum cap);
    unsigned int StrokeTessellatorCapMask() const;
    float StrokeWidth() const;
    float StrokeRadius() const;
    float MiterLimit() const;
    float EffectiveMiterLimit() const;
    CapEnum InitialEndCap() const;
    CapEnum TerminalEndCap() const;
    CapEnum InitialDashCap() const;
    CapEnum TerminalDashCap() const;

    GLenum GLInitialEndCap() const;
    GLenum GLTerminalEndCap() const;
    GLenum GLInitialDashCap() const;
    GLenum GLTerminalDashCap() const;

    void setInitialEndCap(CapEnum cap);
    void setTerminalEndCap(CapEnum cap);
    void setInitialDashCap(CapEnum cap);
    void setTerminalDashCap(CapEnum cap);
    void setCapsIdentical(CapEnum cap);
    float StrokeOpacity() const;
    float FillOpacity() const;
    float3 StrokeColor() const;
    float3 FillColor() const;
    void setStrokeColor(const float3 &c);
    void setStrokeOpacity(float v);
    void setFillColor(const float3 &c);
    void setFillOpacity(float v);
    void forceNoCaps();
};

#endif // __Paint_hpp__
