
// StrokerProgram.cpp - GLSL programs for stroking

#include "StrokerProgram.hpp"
#include "global_polar_settings.hpp"

#ifdef _WIN32
#define snprintf _snprintf  // Workaround Win32's deprecated POSIX name nonsense.
#endif

void StrokerProgram::updateUniformsOfProgramVariant(const StrokerShaderConfig& config, const float viewport_scale[4])
{
    const float epsilon = StrokeTessellator::InitialAlmostZeroEpsilon();

#if SUPPORT_POLAR_VISUALIZE
    if (config.getDrawingMode() == RAW_GRID) {
        // Configure corners for raw grid visualization
        static const float corners[4] = { 530, 250, 780, 500 };
        set4fv("corners", corners);
    } else
#endif
    {
        if (config.hasGradientCoeffs()) {
            set3f("coeff[0]", 0, 0, 0);
        }
        if (config.isConstantColor()) {
            set4f("stroke_color", 0,0,0,1);  // XXX why is this needed? driver issue?
        }
    }

#if SUPPORT_POLAR_VISUALIZE
    if (config.getParameterization() != POLAR) {
        assert(config.getParameterization() == UNIFORM);
        set1i("uniform_segments", stroke_tessellator_settings.UniformSegments());
    } else 
#endif
    {
        set1f("almost_zero_epsilon", epsilon);
        if (shadingModeNeedsArcLength(config.getShadingMode())) {
            set1i("trivial_culling", false);
        } else {
            set1i("trivial_culling", stroke_tessellator_settings.TrivialCulling());
        }
        set1i("draw_inside_of_round_joins", config.DrawInsideOfRoundJoins());
#if SUPPORT_POLAR_VISUALIZE
        set1i("extra_steps", stroke_tessellator_settings.ExtraSteps());
        if (config.getDrawingMode() != RAW_GRID) {
            if (getUniformLocation("show_joins") >= 0) {
                set1i("show_joins", stroke_tessellator_settings.ShowJoins());
            }
        }
#endif
        set1f("max_turning_angle_delta", stroke_tessellator_settings.MaxTurningAngleDelta());

        const GLint min_window_stroke_radius_ndx = getUniformLocation("min_window_stroke_radius");
        if (min_window_stroke_radius_ndx >= 0) {
            if (stroke_tessellator_settings.MinWindowStrokeRadiusClamp()) {
                set1f("min_window_stroke_radius",
                    stroke_tessellator_settings.MinWindowStrokeRadius());
            } else {
                set1f("min_window_stroke_radius", 0);
            }
        }
    }

    const GLint viewport_scale_ndx = getUniformLocation("viewport_scale");
    if (viewport_scale_ndx >= 0) {
        set4fv("viewport_scale", viewport_scale);
    }
}

#if SUPPORT_POLAR_VISUALIZE
void StrokerProgram::configRawGridProgramJoinStyle(StrokeTessellator::JoinEnum join_style)
{
    set1i("max_join_steps", StrokeTessellator::JoinEnumToMaxJoinSteps(join_style));
}

void StrokerProgram::configRawGridProgramEffectiveMiterLimit(float effective_miter_limit)
{
    set1f("effective_miter_limit", effective_miter_limit);
}

void StrokerProgram::configRawGridProgramCapMask(StrokeTessellator::CapEnum initial_cap,
                                                 StrokeTessellator::CapEnum terminal_cap, 
                                                 StrokeTessellator::CapEnum initial_dash_cap,
                                                 StrokeTessellator::CapEnum terminal_dash_cap)
{
    unsigned int cap_mask = StrokeTessellator::CapStateToCapMask(initial_cap, terminal_cap, initial_dash_cap, terminal_dash_cap);
    set1ui("cap_placement_to_type", cap_mask);
}

void StrokerProgram::configRawGridProgramCutOut(bool cut_out)
{
    set1i("cut_out", cut_out);
}

void StrokerProgram::updateUniformSegments(int ribs)
{
    if (getProgId()) {
        set1i("uniform_segments", ribs);
    }
}
#endif
