
// DashingState.hpp - state maintained while dashing a stroked path

#ifndef __DashingState_hpp__
#define __DashingState_hpp__

#pragma once

#include <cstddef>
#include <vector>

class DashingState {
    bool dashing;               // are we dashing strokes?
    bool dash_on;               // true if currently inside an "on" dash segment
    size_t current_segment;     // within dash array
    double distance_into_pattern;             // (modulo) distance into dash pattern
    double accumulated_length;  // length accumulated in prior dash segments

public:
    inline bool Dashing() const {
        if (!dashing) {
            assert(dash_on);
        }
        return dashing;
    }
    inline bool DashOn() const {
        return dash_on;
    }
    inline void copyDashOnState(const DashingState& src) {
        dash_on = src.dash_on;
    }
    inline void advanceDistance(double distance) {
        distance_into_pattern += distance;
    }
    inline double distanceIntoPattern() const {
        return distance_into_pattern - accumulated_length;
    }
    inline size_t CurrentSegment() const {
        return current_segment;
    }

    // Constructors
    DashingState(std::vector<float> dash_array, float dash_offset);
    DashingState(const DashingState &src);

    bool operator ==(const DashingState &rhs) {
        return
            dashing == rhs.dashing &&
            dash_on == rhs.dash_on &&
            current_segment == rhs.current_segment &&
            distance_into_pattern == rhs.distance_into_pattern &&
            accumulated_length == rhs.accumulated_length;
    }

    void advancePatternElement(const std::vector<float> &dash_array);
};

// Version of DashingState that also tracks when the hull_seam can be shared.
// Dashing is the primary reason the hull_seam would be ignored.
class SeamDashingState : public DashingState {
    bool use_hull_seam;         // next hull should use prior hull's seam (false when starting a new dash)

public:
    inline void useHullSeam() {
        use_hull_seam = true;
    }
    inline void ignoreHullSeam() {
        use_hull_seam = false;
    }
    inline bool UseHullSeam() const {
        return use_hull_seam;
    }

    // Constructors
    SeamDashingState(std::vector<float> dash_array, float dash_offset);
    SeamDashingState(const SeamDashingState &src);

    bool operator ==(const SeamDashingState &rhs) {
        return DashingState::operator ==(rhs) && (use_hull_seam == rhs.use_hull_seam);
    }
};

#endif // __DashingState_hpp__
