// curve_tessellate.h — the staged envelope's TRACE: envelope_overlay's node vertices joined by
// the curve each stage's exponent defines. Split from that module on the axis the two already
// have — envelope_overlay decides where a node LANDS, this strokes the span BETWEEN two of
// them over phi, so a re-scaled time axis changes nothing here.

#pragma once

#include <vector>

#include "core/instrument/ui/envelope_overlay.h"
#include "core/ui/stroke_aa.h"  // StrokePoint — the stroker's own vertex type

namespace reasampler::instrument::ui {

// The exponent governing the segment that ENDS at `node`: attack, decay and release are the
// three sloped stages. Every other node ends a plateau, whose straightness comes from its own
// zero level span rather than from an exponent, so neutral is returned and no caller needs a
// second rule to recognize one.
double segmentCurve(const StageEnvelope& env, EnvNode endNode);

// Replaces `out` with the polyline the shell strokes. Knot vertices are handles, not line
// vertices, and are skipped; node vertices keep their exact INTEGER coordinates (clamped to
// [xLo, xHi]) because those are the positions their draggable handles are drawn at. Only the
// interior samples are sub-pixel, one per pixel column, which is what makes the density follow
// the canvas width instead of a fixed count.
//
// A segment's level runs start + (end - start) * curveMap(phi, exponent) — the composition
// envelopes.h's four evaluators use, so the trace cannot diverge from the sound. A neutral
// exponent or a zero level span emits the two endpoints and nothing between: the straight
// stroke, vertex for vertex.
void buildEnvelopeTrace(const std::vector<EnvVertex>& poly, const StageEnvelope& env, int xLo,
                        int xHi, std::vector<reasampler::ui::StrokePoint>& out);

}  // namespace reasampler::instrument::ui
