agg/src/ctrl/agg_gamma_ctrl.cpp

434 lines
13 KiB
C++

//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class gamma_ctrl_impl
//
//----------------------------------------------------------------------------
#include <stdio.h>
#include "agg_math.h"
#include "ctrl/agg_gamma_ctrl.h"
namespace agg
{
//------------------------------------------------------------------------
gamma_ctrl_impl::gamma_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y) :
ctrl(x1, y1, x2, y2, flip_y),
m_border_width(2.0),
m_border_extra(0.0),
m_curve_width(2.0),
m_grid_width(0.2),
m_text_thickness(1.5),
m_point_size(5.0),
m_text_height(9.0),
m_text_width(0.0),
m_xc1(x1),
m_yc1(y1),
m_xc2(x2),
m_yc2(y2 - m_text_height * 2.0),
m_xt1(x1),
m_yt1(y2 - m_text_height * 2.0),
m_xt2(x2),
m_yt2(y2),
m_curve_poly(m_gamma_spline),
m_text_poly(m_text),
m_idx(0),
m_vertex(0),
m_p1_active(true),
m_mouse_point(0),
m_pdx(0.0),
m_pdy(0.0)
{
calc_spline_box();
}
//------------------------------------------------------------------------
void gamma_ctrl_impl::calc_spline_box()
{
m_xs1 = m_xc1 + m_border_width;
m_ys1 = m_yc1 + m_border_width;
m_xs2 = m_xc2 - m_border_width;
m_ys2 = m_yc2 - m_border_width * 0.5;
}
//------------------------------------------------------------------------
void gamma_ctrl_impl::calc_points()
{
double kx1, ky1, kx2, ky2;
m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2);
m_xp1 = m_xs1 + (m_xs2 - m_xs1) * kx1 * 0.25;
m_yp1 = m_ys1 + (m_ys2 - m_ys1) * ky1 * 0.25;
m_xp2 = m_xs2 - (m_xs2 - m_xs1) * kx2 * 0.25;
m_yp2 = m_ys2 - (m_ys2 - m_ys1) * ky2 * 0.25;
}
//------------------------------------------------------------------------
void gamma_ctrl_impl::calc_values()
{
double kx1, ky1, kx2, ky2;
kx1 = (m_xp1 - m_xs1) * 4.0 / (m_xs2 - m_xs1);
ky1 = (m_yp1 - m_ys1) * 4.0 / (m_ys2 - m_ys1);
kx2 = (m_xs2 - m_xp2) * 4.0 / (m_xs2 - m_xs1);
ky2 = (m_ys2 - m_yp2) * 4.0 / (m_ys2 - m_ys1);
m_gamma_spline.values(kx1, ky1, kx2, ky2);
}
//------------------------------------------------------------------------
void gamma_ctrl_impl::text_size(double h, double w)
{
m_text_width = w;
m_text_height = h;
m_yc2 = m_y2 - m_text_height * 2.0;
m_yt1 = m_y2 - m_text_height * 2.0;
calc_spline_box();
}
//------------------------------------------------------------------------
void gamma_ctrl_impl::border_width(double t, double extra)
{
m_border_width = t;
m_border_extra = extra;
calc_spline_box();
}
//------------------------------------------------------------------------
void gamma_ctrl_impl::values(double kx1, double ky1, double kx2, double ky2)
{
m_gamma_spline.values(kx1, ky1, kx2, ky2);
}
//------------------------------------------------------------------------
void gamma_ctrl_impl::values(double* kx1, double* ky1, double* kx2, double* ky2) const
{
m_gamma_spline.values(kx1, ky1, kx2, ky2);
}
//------------------------------------------------------------------------
void gamma_ctrl_impl::rewind(unsigned idx)
{
double kx1, ky1, kx2, ky2;
char tbuf[32];
m_idx = idx;
switch(idx)
{
default:
case 0: // Background
m_vertex = 0;
m_vx[0] = m_x1 - m_border_extra;
m_vy[0] = m_y1 - m_border_extra;
m_vx[1] = m_x2 + m_border_extra;
m_vy[1] = m_y1 - m_border_extra;
m_vx[2] = m_x2 + m_border_extra;
m_vy[2] = m_y2 + m_border_extra;
m_vx[3] = m_x1 - m_border_extra;
m_vy[3] = m_y2 + m_border_extra;
break;
case 1: // Border
m_vertex = 0;
m_vx[0] = m_x1;
m_vy[0] = m_y1;
m_vx[1] = m_x2;
m_vy[1] = m_y1;
m_vx[2] = m_x2;
m_vy[2] = m_y2;
m_vx[3] = m_x1;
m_vy[3] = m_y2;
m_vx[4] = m_x1 + m_border_width;
m_vy[4] = m_y1 + m_border_width;
m_vx[5] = m_x1 + m_border_width;
m_vy[5] = m_y2 - m_border_width;
m_vx[6] = m_x2 - m_border_width;
m_vy[6] = m_y2 - m_border_width;
m_vx[7] = m_x2 - m_border_width;
m_vy[7] = m_y1 + m_border_width;
m_vx[8] = m_xc1 + m_border_width;
m_vy[8] = m_yc2 - m_border_width * 0.5;
m_vx[9] = m_xc2 - m_border_width;
m_vy[9] = m_yc2 - m_border_width * 0.5;
m_vx[10] = m_xc2 - m_border_width;
m_vy[10] = m_yc2 + m_border_width * 0.5;
m_vx[11] = m_xc1 + m_border_width;
m_vy[11] = m_yc2 + m_border_width * 0.5;
break;
case 2: // Curve
m_gamma_spline.box(m_xs1, m_ys1, m_xs2, m_ys2);
m_curve_poly.width(m_curve_width);
m_curve_poly.rewind(0);
break;
case 3: // Grid
m_vertex = 0;
m_vx[0] = m_xs1;
m_vy[0] = (m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5;
m_vx[1] = m_xs2;
m_vy[1] = (m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5;
m_vx[2] = m_xs2;
m_vy[2] = (m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5;
m_vx[3] = m_xs1;
m_vy[3] = (m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5;
m_vx[4] = (m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5;
m_vy[4] = m_ys1;
m_vx[5] = (m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5;
m_vy[5] = m_ys2;
m_vx[6] = (m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5;
m_vy[6] = m_ys2;
m_vx[7] = (m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5;
m_vy[7] = m_ys1;
calc_points();
m_vx[8] = m_xs1;
m_vy[8] = m_yp1 - m_grid_width * 0.5;
m_vx[9] = m_xp1 - m_grid_width * 0.5;
m_vy[9] = m_yp1 - m_grid_width * 0.5;
m_vx[10] = m_xp1 - m_grid_width * 0.5;
m_vy[10] = m_ys1;
m_vx[11] = m_xp1 + m_grid_width * 0.5;
m_vy[11] = m_ys1;
m_vx[12] = m_xp1 + m_grid_width * 0.5;
m_vy[12] = m_yp1 + m_grid_width * 0.5;
m_vx[13] = m_xs1;
m_vy[13] = m_yp1 + m_grid_width * 0.5;
m_vx[14] = m_xs2;
m_vy[14] = m_yp2 + m_grid_width * 0.5;
m_vx[15] = m_xp2 + m_grid_width * 0.5;
m_vy[15] = m_yp2 + m_grid_width * 0.5;
m_vx[16] = m_xp2 + m_grid_width * 0.5;
m_vy[16] = m_ys2;
m_vx[17] = m_xp2 - m_grid_width * 0.5;
m_vy[17] = m_ys2;
m_vx[18] = m_xp2 - m_grid_width * 0.5;
m_vy[18] = m_yp2 - m_grid_width * 0.5;
m_vx[19] = m_xs2;
m_vy[19] = m_yp2 - m_grid_width * 0.5;
break;
case 4: // Point1
calc_points();
if(m_p1_active) m_ellipse.init(m_xp2, m_yp2, m_point_size, m_point_size, 32);
else m_ellipse.init(m_xp1, m_yp1, m_point_size, m_point_size, 32);
break;
case 5: // Point2
calc_points();
if(m_p1_active) m_ellipse.init(m_xp1, m_yp1, m_point_size, m_point_size, 32);
else m_ellipse.init(m_xp2, m_yp2, m_point_size, m_point_size, 32);
break;
case 6: // Text
m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2);
sprintf(tbuf, "%5.3f %5.3f %5.3f %5.3f", kx1, ky1, kx2, ky2);
m_text.text(tbuf);
m_text.size(m_text_height, m_text_width);
m_text.start_point(m_xt1 + m_border_width * 2.0, (m_yt1 + m_yt2) * 0.5 - m_text_height * 0.5);
m_text_poly.width(m_text_thickness);
m_text_poly.line_join(round_join);
m_text_poly.line_cap(round_cap);
m_text_poly.rewind(0);
break;
}
}
//------------------------------------------------------------------------
unsigned gamma_ctrl_impl::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_line_to;
switch(m_idx)
{
case 0:
if(m_vertex == 0) cmd = path_cmd_move_to;
if(m_vertex >= 4) cmd = path_cmd_stop;
*x = m_vx[m_vertex];
*y = m_vy[m_vertex];
m_vertex++;
break;
case 1:
if(m_vertex == 0 || m_vertex == 4 || m_vertex == 8) cmd = path_cmd_move_to;
if(m_vertex >= 12) cmd = path_cmd_stop;
*x = m_vx[m_vertex];
*y = m_vy[m_vertex];
m_vertex++;
break;
case 2:
cmd = m_curve_poly.vertex(x, y);
break;
case 3:
if(m_vertex == 0 ||
m_vertex == 4 ||
m_vertex == 8 ||
m_vertex == 14) cmd = path_cmd_move_to;
if(m_vertex >= 20) cmd = path_cmd_stop;
*x = m_vx[m_vertex];
*y = m_vy[m_vertex];
m_vertex++;
break;
case 4: // Point1
case 5: // Point2
cmd = m_ellipse.vertex(x, y);
break;
case 6:
cmd = m_text_poly.vertex(x, y);
break;
default:
cmd = path_cmd_stop;
break;
}
if(!is_stop(cmd))
{
transform_xy(x, y);
}
return cmd;
}
//------------------------------------------------------------------------
bool gamma_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
{
double kx1, ky1, kx2, ky2;
bool ret = false;
m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2);
if(m_p1_active)
{
if(left) { kx1 -= 0.005; ret = true; }
if(right) { kx1 += 0.005; ret = true; }
if(down) { ky1 -= 0.005; ret = true; }
if(up) { ky1 += 0.005; ret = true; }
}
else
{
if(left) { kx2 += 0.005; ret = true; }
if(right) { kx2 -= 0.005; ret = true; }
if(down) { ky2 += 0.005; ret = true; }
if(up) { ky2 -= 0.005; ret = true; }
}
if(ret)
{
m_gamma_spline.values(kx1, ky1, kx2, ky2);
}
return ret;
}
//------------------------------------------------------------------------
void gamma_ctrl_impl::change_active_point()
{
m_p1_active = m_p1_active ? false : true;
}
//------------------------------------------------------------------------
bool gamma_ctrl_impl::in_rect(double x, double y) const
{
inverse_transform_xy(&x, &y);
return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2;
}
//------------------------------------------------------------------------
bool gamma_ctrl_impl::on_mouse_button_down(double x, double y)
{
inverse_transform_xy(&x, &y);
calc_points();
if(calc_distance(x, y, m_xp1, m_yp1) <= m_point_size + 1)
{
m_mouse_point = 1;
m_pdx = m_xp1 - x;
m_pdy = m_yp1 - y;
m_p1_active = true;
return true;
}
if(calc_distance(x, y, m_xp2, m_yp2) <= m_point_size + 1)
{
m_mouse_point = 2;
m_pdx = m_xp2 - x;
m_pdy = m_yp2 - y;
m_p1_active = false;
return true;
}
return false;
}
//------------------------------------------------------------------------
bool gamma_ctrl_impl::on_mouse_button_up(double, double)
{
if(m_mouse_point)
{
m_mouse_point = 0;
return true;
}
return false;
}
//------------------------------------------------------------------------
bool gamma_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
{
inverse_transform_xy(&x, &y);
if(!button_flag)
{
return on_mouse_button_up(x, y);
}
if(m_mouse_point == 1)
{
m_xp1 = x + m_pdx;
m_yp1 = y + m_pdy;
calc_values();
return true;
}
if(m_mouse_point == 2)
{
m_xp2 = x + m_pdx;
m_yp2 = y + m_pdy;
calc_values();
return true;
}
return false;
}
}