
// StrokeTessellator.hpp - interface for common stroke tessellator functionality

#ifndef __StrokeTessellator_hpp__
#define __StrokeTessellator_hpp__

// Functionality here is assumed useful to both CPU- and GPU-based stroke tessellators.

// CPUStrokeTessellator subclasses from this common functionality

// The stroke tessellator generates a sequence of connected "ribs" to tessellate the stroke.
// Each rib has a mid position, positive edge position, and negative edge position.  The
// "step" between each adjacent pair of ribs is a quadrilateral (that might bowtie).

class StrokeTessellator {
protected:
    // Technically these are GPU limits.
    static const unsigned int max_steps_per_strip = 62;   // Maximum value is 62!  Because 2 steps are part of 64's inner/outer stitching.
    static const unsigned int max_strips = 21;   // Maximum value is 21!  floor(64/3).
    // max_strips*max_steps_per_strip is the maximum steps allowed.
    // More than 1,302 (21*62) steps would overflow the GPU's maximum patch tessellation.
    static const unsigned int max_steps = max_strips*max_steps_per_strip;
    float almost_zero_epsilon;

public:
    enum CapEnum {
        // This order is important to tessellation control shader!
        NO_CAP,  // same as butt cap
        ROUND_CAP,
        TRIANGULAR_CAP,
        SQUARE_CAP,
        CAP_ENUM_COUNT
    };
    enum JoinEnum {
        // XXX ideally this would identity map to PathStyle::LineJoin but does not currently.
        ROUND_JOIN,
        BEVEL,
        TRIANGULAR_JOIN,
        MITER_REVERT,
        MITER_TRUNCATE,
        NO_JOIN,
        JOIN_ENUM_COUNT
    };

    static int JoinEnumToMaxJoinSteps(JoinEnum join_style);
    static unsigned int CapStateToCapMask(CapEnum initial_cap,
                                          CapEnum terminal_cap,
                                          CapEnum initial_dash_cap,
                                          CapEnum terminal_dash_cap);
    static unsigned int CapStateToCapMask(CapEnum identical_cap);

    static float InitialAlmostZeroEpsilon();
    StrokeTessellator();
};

#endif // __StrokeTessellator_hpp__
