290 lines
8.3 KiB
C++
290 lines
8.3 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
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// classes dda_line_interpolator, dda2_line_interpolator
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef AGG_DDA_LINE_INCLUDED
|
|
#define AGG_DDA_LINE_INCLUDED
|
|
|
|
#include <cstdlib>
|
|
#include "agg_basics.h"
|
|
|
|
namespace agg
|
|
{
|
|
|
|
//===================================================dda_line_interpolator
|
|
template<int FractionShift, int YShift = 0> class dda_line_interpolator
|
|
{
|
|
static constexpr int factor = 2 << (FractionShift - 1);
|
|
public:
|
|
//--------------------------------------------------------------------
|
|
dda_line_interpolator() {}
|
|
|
|
//--------------------------------------------------------------------
|
|
dda_line_interpolator(int y1, int y2, unsigned count) :
|
|
m_y(y1),
|
|
m_inc(((y2 - y1) * factor) / static_cast<int>(count)),
|
|
m_dy(0)
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void operator ++ ()
|
|
{
|
|
m_dy += m_inc;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void operator -- ()
|
|
{
|
|
m_dy -= m_inc;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void operator += (unsigned n)
|
|
{
|
|
m_dy += m_inc * n;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void operator -= (unsigned n)
|
|
{
|
|
m_dy -= m_inc * n;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
int y() const { return m_y + (m_dy >> (FractionShift - YShift)); }
|
|
int dy() const { return m_dy; }
|
|
|
|
private:
|
|
int m_y;
|
|
int m_inc;
|
|
int m_dy;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//=================================================dda2_line_interpolator
|
|
class dda2_line_interpolator
|
|
{
|
|
public:
|
|
typedef int save_data_type;
|
|
enum save_size_e { save_size = 2 };
|
|
|
|
//--------------------------------------------------------------------
|
|
dda2_line_interpolator() {}
|
|
|
|
//-------------------------------------------- Forward-adjusted line
|
|
dda2_line_interpolator(int y1, int y2, int count) :
|
|
m_cnt(count <= 0 ? 1 : count),
|
|
m_lft((y2 - y1) / m_cnt),
|
|
m_rem((y2 - y1) % m_cnt),
|
|
m_mod(m_rem),
|
|
m_y(y1)
|
|
{
|
|
if(m_mod <= 0)
|
|
{
|
|
m_mod += count;
|
|
m_rem += count;
|
|
m_lft--;
|
|
}
|
|
m_mod -= count;
|
|
}
|
|
|
|
//-------------------------------------------- Backward-adjusted line
|
|
dda2_line_interpolator(int y1, int y2, int count, int) :
|
|
m_cnt(count <= 0 ? 1 : count),
|
|
m_lft((y2 - y1) / m_cnt),
|
|
m_rem((y2 - y1) % m_cnt),
|
|
m_mod(m_rem),
|
|
m_y(y1)
|
|
{
|
|
if(m_mod <= 0)
|
|
{
|
|
m_mod += count;
|
|
m_rem += count;
|
|
m_lft--;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------- Backward-adjusted line
|
|
dda2_line_interpolator(int y, int count) :
|
|
m_cnt(count <= 0 ? 1 : count),
|
|
m_lft(y / m_cnt),
|
|
m_rem(y % m_cnt),
|
|
m_mod(m_rem),
|
|
m_y(0)
|
|
{
|
|
if(m_mod <= 0)
|
|
{
|
|
m_mod += count;
|
|
m_rem += count;
|
|
m_lft--;
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
void save(save_data_type* data) const
|
|
{
|
|
data[0] = m_mod;
|
|
data[1] = m_y;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void load(const save_data_type* data)
|
|
{
|
|
m_mod = data[0];
|
|
m_y = data[1];
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void operator++()
|
|
{
|
|
m_mod += m_rem;
|
|
m_y += m_lft;
|
|
if(m_mod > 0)
|
|
{
|
|
m_mod -= m_cnt;
|
|
m_y++;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void operator--()
|
|
{
|
|
if(m_mod <= m_rem)
|
|
{
|
|
m_mod += m_cnt;
|
|
m_y--;
|
|
}
|
|
m_mod -= m_rem;
|
|
m_y -= m_lft;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void adjust_forward()
|
|
{
|
|
m_mod -= m_cnt;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void adjust_backward()
|
|
{
|
|
m_mod += m_cnt;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
int mod() const { return m_mod; }
|
|
int rem() const { return m_rem; }
|
|
int lft() const { return m_lft; }
|
|
|
|
//--------------------------------------------------------------------
|
|
int y() const { return m_y; }
|
|
|
|
private:
|
|
int m_cnt;
|
|
int m_lft;
|
|
int m_rem;
|
|
int m_mod;
|
|
int m_y;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------line_bresenham_interpolator
|
|
class line_bresenham_interpolator
|
|
{
|
|
public:
|
|
enum subpixel_scale_e
|
|
{
|
|
subpixel_shift = 8,
|
|
subpixel_scale = 1 << subpixel_shift,
|
|
subpixel_mask = subpixel_scale - 1
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
static int line_lr(int v) { return v >> subpixel_shift; }
|
|
|
|
//--------------------------------------------------------------------
|
|
line_bresenham_interpolator(int x1, int y1, int x2, int y2) :
|
|
m_x1_lr(line_lr(x1)),
|
|
m_y1_lr(line_lr(y1)),
|
|
m_x2_lr(line_lr(x2)),
|
|
m_y2_lr(line_lr(y2)),
|
|
m_ver(std::abs(m_x2_lr - m_x1_lr) < std::abs(m_y2_lr - m_y1_lr)),
|
|
m_len(m_ver ? std::abs(m_y2_lr - m_y1_lr) :
|
|
std::abs(m_x2_lr - m_x1_lr)),
|
|
m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)),
|
|
m_interpolator(m_ver ? x1 : y1,
|
|
m_ver ? x2 : y2,
|
|
m_len)
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
bool is_ver() const { return m_ver; }
|
|
unsigned len() const { return m_len; }
|
|
int inc() const { return m_inc; }
|
|
|
|
//--------------------------------------------------------------------
|
|
void hstep()
|
|
{
|
|
++m_interpolator;
|
|
m_x1_lr += m_inc;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void vstep()
|
|
{
|
|
++m_interpolator;
|
|
m_y1_lr += m_inc;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
int x1() const { return m_x1_lr; }
|
|
int y1() const { return m_y1_lr; }
|
|
int x2() const { return line_lr(m_interpolator.y()); }
|
|
int y2() const { return line_lr(m_interpolator.y()); }
|
|
int x2_hr() const { return m_interpolator.y(); }
|
|
int y2_hr() const { return m_interpolator.y(); }
|
|
|
|
private:
|
|
int m_x1_lr;
|
|
int m_y1_lr;
|
|
int m_x2_lr;
|
|
int m_y2_lr;
|
|
bool m_ver;
|
|
unsigned m_len;
|
|
int m_inc;
|
|
dda2_line_interpolator m_interpolator;
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|