new build system
This commit is contained in:
parent
c97fb0bf57
commit
d8dc53bcf4
330 changed files with 80727 additions and 155 deletions
166
INSTALL
166
INSTALL
|
@ -1,26 +1,164 @@
|
|||
# $Id$
|
||||
|
||||
INSTALLATION INSTRUCTIONS
|
||||
|
||||
Prerequisites
|
||||
First of all you will have to install 'scons'. See scons user guide on how to get started.
|
||||
-------------
|
||||
|
||||
Mapnik is relying on a number of boost libraries (filesystem, python, regex, spirit etc). You can download the latest release (1.32.0) or grab a CVS snapshot from http://boost.org. You don't need to build anything, just unzip the source into read/write location on your disk.
|
||||
First, here is a quick list of the software dependencies:
|
||||
|
||||
The same requirements apply for AGG library (available from http://www.antigrain.com)
|
||||
- Linux/UNIX with g++ compiler
|
||||
|
||||
- libboost 1.32.0 or greater with the following libraries included:
|
||||
- thread
|
||||
- wserialization
|
||||
- filesystem
|
||||
- regex
|
||||
- (Optional) program_options
|
||||
- (Optional) python
|
||||
|
||||
- libpng
|
||||
- libjpeg
|
||||
- libtiff
|
||||
- libz
|
||||
- libfreetype2
|
||||
- (Optional) PostgreSQL libraries
|
||||
|
||||
- Python 1.5.2 or greater to build Mapnik
|
||||
- (Optional) Python 2.2 or greater for the Python language bindings
|
||||
|
||||
All of these will normally come with any modern Linux distribution.
|
||||
|
||||
If your system does NOT have one of these installed, you will need to install the mandatory ones at the very least before proceeding further. Instructions on how to do this will come with each individual package.
|
||||
|
||||
Other dependencies include:
|
||||
1. libltdl (dynamic linking)
|
||||
2. libz
|
||||
3. libpng
|
||||
4. libjpeg
|
||||
5. freetype2
|
||||
6. postgresql (+postgis) - if you want to build postgis datasource
|
||||
|
||||
Building
|
||||
Once you satisfy all dependencies you can build mapnik by issuing the following command:
|
||||
--------
|
||||
|
||||
:/> scons DATASOURCES=all PREFIX=/where/to/install install
|
||||
Once you've installed the required software packages, the simplest way to build mapnik is to run "scons" (The software builder) without any options:
|
||||
|
||||
This should compile, link and install all relevant libraries/headers in PREFIX.
|
||||
$ cd /path/to/mapnik-sourcecode
|
||||
$ /path/to/python scons/scons.py
|
||||
|
||||
By default release versions are built, but you can specify "debug=yes" to build debug versions. At this time only GCC toolkit is supported and you'll have to modify SConstruct/SConscript files if you're planning to use something else.
|
||||
This should compile and link the mapnik library, the input plugins and the python language binding (if possible). If any mandatory dependencies are not found the build will fail, and you will need to specify custom paths to your libraries and include files (see below).
|
||||
|
||||
Note that the python used to run "scons" does NOT have to be the same as the one used for the python bindings.
|
||||
|
||||
"scons" accepts a variety of options to customize your build. This allows you to specify which components are compiled, where to find dependencies, where to install mapnik, and so on.
|
||||
|
||||
To see the list of available options, from the root of the source distribution, run:
|
||||
|
||||
$ /path/to/python scons/scons.py -h
|
||||
|
||||
You will get:
|
||||
|
||||
PREFIX: The install path "prefix"
|
||||
default: /usr/local
|
||||
actual: /usr/local
|
||||
|
||||
BOOST_INCLUDES: Search path for boost include files ( /path/to/BOOST_INCLUDES )
|
||||
default: /usr/include
|
||||
actual: /usr/include
|
||||
|
||||
BOOST_LIBS: Search path for boost library files ( /path/to/BOOST_LIBS )
|
||||
default: /usr/lib
|
||||
actual: /usr/lib
|
||||
|
||||
FREETYPE_INCLUDES: Search path for FreeType include files ( /path/to/FREETYPE_INCLUDES )
|
||||
default: /usr/include
|
||||
actual: /usr/include
|
||||
|
||||
FREETYPE_LIBS: Search path for FreeType library files ( /path/to/FREETYPE_LIBS )
|
||||
default: /usr/lib
|
||||
actual: /usr/lib
|
||||
|
||||
PNG_INCLUDES: Search path for libpng include files ( /path/to/PNG_INCLUDES )
|
||||
default: /usr/include
|
||||
actual: /usr/include
|
||||
|
||||
PNG_LIBS: Search path for libpng include files ( /path/to/PNG_LIBS )
|
||||
default: /usr/lib
|
||||
actual: /usr/lib
|
||||
|
||||
JPEG_INCLUDES: Search path for libjpeg include files ( /path/to/JPEG_INCLUDES )
|
||||
default: /usr/include
|
||||
actual: /usr/include
|
||||
|
||||
JPEG_LIBS: Search path for libjpeg library files ( /path/to/JPEG_LIBS )
|
||||
default: /usr/lib
|
||||
actual: /usr/lib
|
||||
|
||||
TIFF_INCLUDES: Search path for libtiff include files ( /path/to/TIFF_INCLUDES )
|
||||
default: /usr/include
|
||||
actual: /usr/include
|
||||
|
||||
TIFF_LIBS: Search path for libtiff library files ( /path/to/TIFF_LIBS )
|
||||
default: /usr/lib
|
||||
actual: /usr/lib
|
||||
|
||||
PGSQL_INCLUDES: Search path for PostgreSQL include files ( /path/to/PGSQL_INCLUDES )
|
||||
default: /usr/include
|
||||
actual: /usr/include
|
||||
|
||||
PGSQL_LIBS: Search path for PostgreSQL library files ( /path/to/PGSQL_LIBS )
|
||||
default: /usr/lib
|
||||
actual: /usr/lib
|
||||
|
||||
PYTHON: Python executable ( /path/to/PYTHON )
|
||||
default: /usr/local/bin/python2.4
|
||||
actual: /usr/local/bin/python2.4
|
||||
|
||||
INPUT_PLUGINS: Input drivers to include
|
||||
(all|none|comma-separated list of names)
|
||||
allowed names: postgis shape raster
|
||||
default: all
|
||||
actual: postgis shape raster
|
||||
|
||||
BINDINGS: Language bindings to build
|
||||
(all|none|comma-separated list of names)
|
||||
allowed names: python
|
||||
default: all
|
||||
actual: python
|
||||
|
||||
This help should be self-explanatory!
|
||||
|
||||
For example, if you compiled your own set of Boost libraries, you might use:
|
||||
|
||||
$ /path/to/python scons/scons.py BOOST_INCLUDES=/usr/local/include/boost-1_33_1 BOOST_LIBS=/usr/local/lib
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Once the build has successfully completed, you can install the various files on your system by executing:
|
||||
|
||||
$ /path/to/python scons/scons.py install
|
||||
|
||||
By default, everything will be installed under the PREFIX '/usr/local' as such:
|
||||
|
||||
$PREFIX/lib: libmapnik.so
|
||||
$PREFIX/lib/mapnik/input: input plug-ins
|
||||
$PREFIX/include: mapnik include files
|
||||
$PREFIX/bin: shapeindex utility
|
||||
$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages/mapnik: Python bindings
|
||||
|
||||
If you're using the default PREFIX, you will most likely need to be root to perform the install.
|
||||
|
||||
|
||||
Test
|
||||
----
|
||||
|
||||
There currently are no easy way to test your setup, other than write some code to generate a map.
|
||||
|
||||
One simple thing you can do is try to load the Python module, and make sure it does so without errors:
|
||||
|
||||
$ /path/to/python
|
||||
Python 2.4.2 (#1, Jan 11 2006, 10:59:28)
|
||||
[GCC 3.4.4 20050721 (Red Hat 3.4.4-2)] on linux2
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> from mapnik import *
|
||||
registered datasource : shape
|
||||
registered datasource : raster
|
||||
registered datasource : postgis
|
||||
>>>
|
||||
|
||||
|
|
499
agg/include/agg_alpha_mask_u8.h
Normal file
499
agg/include/agg_alpha_mask_u8.h
Normal file
|
@ -0,0 +1,499 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// scanline_u8 class
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_ALPHA_MASK_U8_INCLUDED
|
||||
#define AGG_ALPHA_MASK_U8_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//===================================================one_component_mask_u8
|
||||
struct one_component_mask_u8
|
||||
{
|
||||
static unsigned calculate(const int8u* p) { return *p; }
|
||||
};
|
||||
|
||||
|
||||
//=====================================================rgb_to_gray_mask_u8
|
||||
template<unsigned R, unsigned G, unsigned B>
|
||||
struct rgb_to_gray_mask_u8
|
||||
{
|
||||
static unsigned calculate(const int8u* p)
|
||||
{
|
||||
return (p[R]*77 + p[G]*150 + p[B]*29) >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================alpha_mask_u8
|
||||
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
|
||||
class alpha_mask_u8
|
||||
{
|
||||
public:
|
||||
typedef int8u cover_type;
|
||||
typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
|
||||
enum cover_scale_e
|
||||
{
|
||||
cover_shift = 8,
|
||||
cover_none = 0,
|
||||
cover_full = 255
|
||||
};
|
||||
|
||||
alpha_mask_u8() : m_rbuf(0) {}
|
||||
alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
|
||||
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||
|
||||
MaskF& mask_function() { return m_mask_function; }
|
||||
const MaskF& mask_function() const { return m_mask_function; }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type pixel(int x, int y) const
|
||||
{
|
||||
if(x >= 0 && y >= 0 &&
|
||||
x < (int)m_rbuf->width() &&
|
||||
y <= (int)m_rbuf->height())
|
||||
{
|
||||
return (cover_type)m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type combine_pixel(int x, int y, cover_type val) const
|
||||
{
|
||||
if(x >= 0 && y >= 0 &&
|
||||
x < (int)m_rbuf->width() &&
|
||||
y <= (int)m_rbuf->height())
|
||||
{
|
||||
return (cover_type)((cover_full + val *
|
||||
m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset)) >>
|
||||
cover_shift);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(y < 0 || y > ymax)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
count += x;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers, 0, -x * sizeof(cover_type));
|
||||
covers -= x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if(x + count > xmax)
|
||||
{
|
||||
int rest = x + count - xmax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += Step;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(y < 0 || y > ymax)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
count += x;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers, 0, -x * sizeof(cover_type));
|
||||
covers -= x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if(x + count > xmax)
|
||||
{
|
||||
int rest = x + count - xmax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers = (cover_type)((cover_full + (*covers) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++covers;
|
||||
mask += Step;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(x < 0 || x > xmax)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(y < 0)
|
||||
{
|
||||
count += y;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers, 0, -y * sizeof(cover_type));
|
||||
covers -= y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if(y + count > ymax)
|
||||
{
|
||||
int rest = y + count - ymax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(x < 0 || x > xmax)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(y < 0)
|
||||
{
|
||||
count += y;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers, 0, -y * sizeof(cover_type));
|
||||
covers -= y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if(y + count > ymax)
|
||||
{
|
||||
int rest = y + count - ymax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers = (cover_type)((cover_full + (*covers) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++covers;
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
alpha_mask_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
rendering_buffer* m_rbuf;
|
||||
MaskF m_mask_function;
|
||||
};
|
||||
|
||||
|
||||
typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8
|
||||
|
||||
typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r
|
||||
typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g
|
||||
typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b
|
||||
|
||||
typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r
|
||||
typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g
|
||||
typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b
|
||||
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
|
||||
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
|
||||
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
|
||||
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
|
||||
|
||||
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray
|
||||
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray
|
||||
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
|
||||
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
|
||||
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
|
||||
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
|
||||
|
||||
|
||||
|
||||
//==========================================================amask_no_clip_u8
|
||||
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
|
||||
class amask_no_clip_u8
|
||||
{
|
||||
public:
|
||||
typedef int8u cover_type;
|
||||
typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
|
||||
enum cover_scale_e
|
||||
{
|
||||
cover_shift = 8,
|
||||
cover_none = 0,
|
||||
cover_full = 255
|
||||
};
|
||||
|
||||
amask_no_clip_u8() : m_rbuf(0) {}
|
||||
amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
|
||||
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||
|
||||
MaskF& mask_function() { return m_mask_function; }
|
||||
const MaskF& mask_function() const { return m_mask_function; }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type pixel(int x, int y) const
|
||||
{
|
||||
return (cover_type)m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type combine_pixel(int x, int y, cover_type val) const
|
||||
{
|
||||
return (cover_type)((cover_full + val *
|
||||
m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset)) >>
|
||||
cover_shift);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += Step;
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst = (cover_type)((cover_full + (*dst) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++dst;
|
||||
mask += Step;
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst = (cover_type)((cover_full + (*dst) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++dst;
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
private:
|
||||
amask_no_clip_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
rendering_buffer* m_rbuf;
|
||||
MaskF m_mask_function;
|
||||
};
|
||||
|
||||
|
||||
typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8
|
||||
|
||||
typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r
|
||||
typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g
|
||||
typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b
|
||||
|
||||
typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r
|
||||
typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g
|
||||
typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b
|
||||
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a
|
||||
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a
|
||||
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
|
||||
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
|
||||
|
||||
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray
|
||||
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray
|
||||
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray
|
||||
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray
|
||||
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray
|
||||
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
74
agg/include/agg_arc.h
Normal file
74
agg/include/agg_arc.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Arc vertex generator
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ARC_INCLUDED
|
||||
#define AGG_ARC_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=====================================================================arc
|
||||
//
|
||||
// See Implementation agg_arc.cpp
|
||||
//
|
||||
class arc
|
||||
{
|
||||
public:
|
||||
arc() : m_scale(1.0), m_initialized(false) {}
|
||||
arc(double x, double y,
|
||||
double rx, double ry,
|
||||
double a1, double a2,
|
||||
bool ccw=true);
|
||||
|
||||
void init(double x, double y,
|
||||
double rx, double ry,
|
||||
double a1, double a2,
|
||||
bool ccw=true);
|
||||
|
||||
void approximation_scale(double s);
|
||||
double approximation_scale() const { return m_scale; }
|
||||
|
||||
void rewind(unsigned);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
void normalize(double a1, double a2, bool ccw);
|
||||
|
||||
double m_x;
|
||||
double m_y;
|
||||
double m_rx;
|
||||
double m_ry;
|
||||
double m_angle;
|
||||
double m_start;
|
||||
double m_end;
|
||||
double m_scale;
|
||||
double m_da;
|
||||
bool m_ccw;
|
||||
bool m_initialized;
|
||||
unsigned m_path_cmd;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
1057
agg/include/agg_array.h
Normal file
1057
agg/include/agg_array.h
Normal file
File diff suppressed because it is too large
Load diff
82
agg/include/agg_arrowhead.h
Normal file
82
agg/include/agg_arrowhead.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Simple arrowhead/arrowtail generator
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_ARROWHEAD_INCLUDED
|
||||
#define AGG_ARROWHEAD_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===============================================================arrowhead
|
||||
//
|
||||
// See implementation agg_arrowhead.cpp
|
||||
//
|
||||
class arrowhead
|
||||
{
|
||||
public:
|
||||
arrowhead();
|
||||
|
||||
void head(double d1, double d2, double d3, double d4)
|
||||
{
|
||||
m_head_d1 = d1;
|
||||
m_head_d2 = d2;
|
||||
m_head_d3 = d3;
|
||||
m_head_d4 = d4;
|
||||
m_head_flag = true;
|
||||
}
|
||||
|
||||
void head() { m_head_flag = true; }
|
||||
void no_head() { m_head_flag = false; }
|
||||
|
||||
void tail(double d1, double d2, double d3, double d4)
|
||||
{
|
||||
m_tail_d1 = d1;
|
||||
m_tail_d2 = d2;
|
||||
m_tail_d3 = d3;
|
||||
m_tail_d4 = d4;
|
||||
m_tail_flag = true;
|
||||
}
|
||||
|
||||
void tail() { m_tail_flag = true; }
|
||||
void no_tail() { m_tail_flag = false; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
double m_head_d1;
|
||||
double m_head_d2;
|
||||
double m_head_d3;
|
||||
double m_head_d4;
|
||||
double m_tail_d1;
|
||||
double m_tail_d2;
|
||||
double m_tail_d3;
|
||||
double m_tail_d4;
|
||||
bool m_head_flag;
|
||||
bool m_tail_flag;
|
||||
double m_coord[16];
|
||||
unsigned m_cmd[8];
|
||||
unsigned m_curr_id;
|
||||
unsigned m_curr_coord;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
451
agg/include/agg_basics.h
Normal file
451
agg/include/agg_basics.h
Normal file
|
@ -0,0 +1,451 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BASICS_INCLUDED
|
||||
#define AGG_BASICS_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_config.h"
|
||||
|
||||
//-------------------------------------------------------- Default basic types
|
||||
//
|
||||
// If the compiler has different capacity of the basic types you can redefine
|
||||
// them via the compiler command line or by generating agg_config.h that is
|
||||
// empty by default.
|
||||
//
|
||||
#ifndef AGG_INT8
|
||||
#define AGG_INT8 signed char
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT8U
|
||||
#define AGG_INT8U unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT16
|
||||
#define AGG_INT16 short
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT16U
|
||||
#define AGG_INT16U unsigned short
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT32
|
||||
#define AGG_INT32 int
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT32U
|
||||
#define AGG_INT32U unsigned
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT64
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#define AGG_INT64 signed __int64
|
||||
#else
|
||||
#define AGG_INT64 signed long long
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT64U
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#define AGG_INT64U unsigned __int64
|
||||
#else
|
||||
#define AGG_INT64U unsigned long long
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//------------------------------------------------ Some fixes for MS Visual C++
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4786) // Identifier was truncated...
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define AGG_INLINE __forceinline
|
||||
#else
|
||||
#define AGG_INLINE inline
|
||||
#endif
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-------------------------------------------------------------------------
|
||||
typedef AGG_INT8 int8; //----int8
|
||||
typedef AGG_INT8U int8u; //----int8u
|
||||
typedef AGG_INT16 int16; //----int16
|
||||
typedef AGG_INT16U int16u; //----int16u
|
||||
typedef AGG_INT32 int32; //----int32
|
||||
typedef AGG_INT32U int32u; //----int32u
|
||||
typedef AGG_INT64 int64; //----int64
|
||||
typedef AGG_INT64U int64u; //----int64u
|
||||
|
||||
#if defined(AGG_FISTP)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4035) //Disable warning "no return value"
|
||||
AGG_INLINE int iround(double v) //-------iround
|
||||
{
|
||||
__asm fld qword ptr [v]
|
||||
__asm fistp dword ptr [ebp-8]
|
||||
__asm mov eax, dword ptr [ebp-8]
|
||||
}
|
||||
AGG_INLINE unsigned uround(double v) //-------uround
|
||||
{
|
||||
__asm fld qword ptr [v]
|
||||
__asm fistp dword ptr [ebp-8]
|
||||
__asm mov eax, dword ptr [ebp-8]
|
||||
}
|
||||
#pragma warning(pop)
|
||||
AGG_INLINE unsigned ufloor(double v) //-------ufloor
|
||||
{
|
||||
return unsigned(floor(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v) //--------uceil
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
}
|
||||
#elif defined(AGG_QIFIST)
|
||||
AGG_INLINE int iround(double v)
|
||||
{
|
||||
return int(v);
|
||||
}
|
||||
AGG_INLINE int uround(double v)
|
||||
{
|
||||
return unsigned(v);
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v)
|
||||
{
|
||||
return unsigned(floor(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v)
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
}
|
||||
#else
|
||||
AGG_INLINE int iround(double v)
|
||||
{
|
||||
return int((v < 0.0) ? v - 0.5 : v + 0.5);
|
||||
}
|
||||
AGG_INLINE int uround(double v)
|
||||
{
|
||||
return unsigned(v + 0.5);
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v)
|
||||
{
|
||||
return unsigned(v);
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v)
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
}
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------saturation
|
||||
template<int Limit> struct saturation
|
||||
{
|
||||
AGG_INLINE static int iround(double v)
|
||||
{
|
||||
if(v < double(-Limit)) return -Limit;
|
||||
if(v > double( Limit)) return Limit;
|
||||
return agg::iround(v);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------mul_one
|
||||
template<unsigned Shift> struct mul_one
|
||||
{
|
||||
AGG_INLINE static unsigned mul(unsigned a, unsigned b)
|
||||
{
|
||||
register unsigned q = a * b + (1 << (Shift-1));
|
||||
return (q + (q >> Shift)) >> Shift;
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
typedef unsigned char cover_type; //----cover_type
|
||||
enum cover_scale_e
|
||||
{
|
||||
cover_shift = 8, //----cover_shift
|
||||
cover_size = 1 << cover_shift, //----cover_size
|
||||
cover_mask = cover_size - 1, //----cover_mask
|
||||
cover_none = 0, //----cover_none
|
||||
cover_full = cover_mask //----cover_full
|
||||
};
|
||||
|
||||
//----------------------------------------------------poly_subpixel_scale_e
|
||||
// These constants determine the subpixel accuracy, to be more precise,
|
||||
// the number of bits of the fractional part of the coordinates.
|
||||
// The possible coordinate capacity in bits can be calculated by formula:
|
||||
// sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
|
||||
// 8-bits fractional part the capacity is 24 bits.
|
||||
enum poly_subpixel_scale_e
|
||||
{
|
||||
poly_subpixel_shift = 8, //----poly_subpixel_shift
|
||||
poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale
|
||||
poly_subpixel_mask = poly_subpixel_scale-1, //----poly_subpixel_mask
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------pi
|
||||
const double pi = 3.14159265358979323846;
|
||||
|
||||
//------------------------------------------------------------------deg2rad
|
||||
inline double deg2rad(double deg)
|
||||
{
|
||||
return deg * pi / 180.0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------rad2deg
|
||||
inline double rad2deg(double rad)
|
||||
{
|
||||
return rad * 180.0 / pi;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------rect_base
|
||||
template<class T> struct rect_base
|
||||
{
|
||||
typedef rect_base<T> self_type;
|
||||
T x1;
|
||||
T y1;
|
||||
T x2;
|
||||
T y2;
|
||||
|
||||
rect_base() {}
|
||||
rect_base(T x1_, T y1_, T x2_, T y2_) :
|
||||
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
|
||||
|
||||
const self_type& normalize()
|
||||
{
|
||||
T t;
|
||||
if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
|
||||
if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool clip(const self_type& r)
|
||||
{
|
||||
if(x2 > r.x2) x2 = r.x2;
|
||||
if(y2 > r.y2) y2 = r.y2;
|
||||
if(x1 < r.x1) x1 = r.x1;
|
||||
if(y1 < r.y1) y1 = r.y1;
|
||||
return x1 <= x2 && y1 <= y2;
|
||||
}
|
||||
|
||||
bool is_valid() const
|
||||
{
|
||||
return x1 <= x2 && y1 <= y2;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------intersect_rectangles
|
||||
template<class Rect>
|
||||
inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
|
||||
{
|
||||
Rect r = r1;
|
||||
|
||||
// First process x2,y2 because the other order
|
||||
// results in Internal Compiler Error under
|
||||
// Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in
|
||||
// case of "Maximize Speed" optimization option.
|
||||
//-----------------
|
||||
if(r.x2 > r2.x2) r.x2 = r2.x2;
|
||||
if(r.y2 > r2.y2) r.y2 = r2.y2;
|
||||
if(r.x1 < r2.x1) r.x1 = r2.x1;
|
||||
if(r.y1 < r2.y1) r.y1 = r2.y1;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------unite_rectangles
|
||||
template<class Rect>
|
||||
inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
|
||||
{
|
||||
Rect r = r1;
|
||||
if(r.x2 < r2.x2) r.x2 = r2.x2;
|
||||
if(r.y2 < r2.y2) r.y2 = r2.y2;
|
||||
if(r.x1 > r2.x1) r.x1 = r2.x1;
|
||||
if(r.y1 > r2.y1) r.y1 = r2.y1;
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef rect_base<int> rect_i; //----rect_i
|
||||
typedef rect_base<float> rect_f; //----rect_f
|
||||
typedef rect_base<double> rect_d; //----rect_d
|
||||
|
||||
//---------------------------------------------------------path_commands_e
|
||||
enum path_commands_e
|
||||
{
|
||||
path_cmd_stop = 0, //----path_cmd_stop
|
||||
path_cmd_move_to = 1, //----path_cmd_move_to
|
||||
path_cmd_line_to = 2, //----path_cmd_line_to
|
||||
path_cmd_curve3 = 3, //----path_cmd_curve3
|
||||
path_cmd_curve4 = 4, //----path_cmd_curve4
|
||||
path_cmd_curveN = 5, //----path_cmd_curveN
|
||||
path_cmd_catrom = 6, //----path_cmd_catrom
|
||||
path_cmd_ubspline = 7, //----path_cmd_ubspline
|
||||
path_cmd_end_poly = 0x0F, //----path_cmd_end_poly
|
||||
path_cmd_mask = 0x0F //----path_cmd_mask
|
||||
};
|
||||
|
||||
//------------------------------------------------------------path_flags_e
|
||||
enum path_flags_e
|
||||
{
|
||||
path_flags_none = 0, //----path_flags_none
|
||||
path_flags_ccw = 0x10, //----path_flags_ccw
|
||||
path_flags_cw = 0x20, //----path_flags_cw
|
||||
path_flags_close = 0x40, //----path_flags_close
|
||||
path_flags_mask = 0xF0 //----path_flags_mask
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------is_vertex
|
||||
inline bool is_vertex(unsigned c)
|
||||
{
|
||||
return c >= path_cmd_move_to && c < path_cmd_end_poly;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------is_drawing
|
||||
inline bool is_drawing(unsigned c)
|
||||
{
|
||||
return c >= path_cmd_line_to && c < path_cmd_end_poly;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------is_stop
|
||||
inline bool is_stop(unsigned c)
|
||||
{
|
||||
return c == path_cmd_stop;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------is_move_to
|
||||
inline bool is_move_to(unsigned c)
|
||||
{
|
||||
return c == path_cmd_move_to;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------is_line_to
|
||||
inline bool is_line_to(unsigned c)
|
||||
{
|
||||
return c == path_cmd_line_to;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------is_curve
|
||||
inline bool is_curve(unsigned c)
|
||||
{
|
||||
return c == path_cmd_curve3 || c == path_cmd_curve4;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------is_curve3
|
||||
inline bool is_curve3(unsigned c)
|
||||
{
|
||||
return c == path_cmd_curve3;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------is_curve4
|
||||
inline bool is_curve4(unsigned c)
|
||||
{
|
||||
return c == path_cmd_curve4;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------is_end_poly
|
||||
inline bool is_end_poly(unsigned c)
|
||||
{
|
||||
return (c & path_cmd_mask) == path_cmd_end_poly;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------is_close
|
||||
inline bool is_close(unsigned c)
|
||||
{
|
||||
return (c & ~(path_flags_cw | path_flags_ccw)) ==
|
||||
(path_cmd_end_poly | path_flags_close);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------is_next_poly
|
||||
inline bool is_next_poly(unsigned c)
|
||||
{
|
||||
return is_stop(c) || is_move_to(c) || is_end_poly(c);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------is_cw
|
||||
inline bool is_cw(unsigned c)
|
||||
{
|
||||
return (c & path_flags_cw) != 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------is_ccw
|
||||
inline bool is_ccw(unsigned c)
|
||||
{
|
||||
return (c & path_flags_ccw) != 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------is_oriented
|
||||
inline bool is_oriented(unsigned c)
|
||||
{
|
||||
return (c & (path_flags_cw | path_flags_ccw)) != 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------is_closed
|
||||
inline bool is_closed(unsigned c)
|
||||
{
|
||||
return (c & path_flags_close) != 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------get_close_flag
|
||||
inline unsigned get_close_flag(unsigned c)
|
||||
{
|
||||
return c & path_flags_close;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------clear_orientation
|
||||
inline unsigned clear_orientation(unsigned c)
|
||||
{
|
||||
return c & ~(path_flags_cw | path_flags_ccw);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------get_orientation
|
||||
inline unsigned get_orientation(unsigned c)
|
||||
{
|
||||
return c & (path_flags_cw | path_flags_ccw);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------set_orientation
|
||||
inline unsigned set_orientation(unsigned c, unsigned o)
|
||||
{
|
||||
return clear_orientation(c) | o;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------point_base
|
||||
template<class T> struct point_base
|
||||
{
|
||||
typedef T value_type;
|
||||
T x,y;
|
||||
point_base() {}
|
||||
point_base(T x_, T y_) : x(x_), y(y_) {}
|
||||
};
|
||||
typedef point_base<int> point_i; //-----point_i
|
||||
typedef point_base<float> point_f; //-----point_f
|
||||
typedef point_base<double> point_d; //-----point_d
|
||||
|
||||
//-------------------------------------------------------------vertex_base
|
||||
template<class T> struct vertex_base
|
||||
{
|
||||
typedef T value_type;
|
||||
T x,y;
|
||||
unsigned cmd;
|
||||
vertex_base() {}
|
||||
vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {}
|
||||
};
|
||||
typedef vertex_base<int> vertex_i; //-----vertex_i
|
||||
typedef vertex_base<float> vertex_f; //-----vertex_f
|
||||
typedef vertex_base<double> vertex_d; //-----vertex_d
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
159
agg/include/agg_bezier_arc.h
Normal file
159
agg/include/agg_bezier_arc.h
Normal file
|
@ -0,0 +1,159 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
|
||||
// 4, 7, 10, or 13 vertices.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BEZIER_ARC_INCLUDED
|
||||
#define AGG_BEZIER_ARC_INCLUDED
|
||||
|
||||
#include "agg_conv_transform.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void arc_to_bezier(double cx, double cy, double rx, double ry,
|
||||
double start_angle, double sweep_angle,
|
||||
double* curve);
|
||||
|
||||
|
||||
//==============================================================bezier_arc
|
||||
//
|
||||
// See implemantaion agg_bezier_arc.cpp
|
||||
//
|
||||
class bezier_arc
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {}
|
||||
bezier_arc(double x, double y,
|
||||
double rx, double ry,
|
||||
double start_angle,
|
||||
double sweep_angle)
|
||||
{
|
||||
init(x, y, rx, ry, start_angle, sweep_angle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(double x, double y,
|
||||
double rx, double ry,
|
||||
double start_angle,
|
||||
double sweep_angle);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_vertex = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_vertex >= m_num_vertices) return path_cmd_stop;
|
||||
*x = m_vertices[m_vertex];
|
||||
*y = m_vertices[m_vertex + 1];
|
||||
m_vertex += 2;
|
||||
return (m_vertex == 2) ? path_cmd_move_to : m_cmd;
|
||||
}
|
||||
|
||||
// Supplemantary functions. num_vertices() actually returns doubled
|
||||
// number of vertices. That is, for 1 vertex it returns 2.
|
||||
//--------------------------------------------------------------------
|
||||
unsigned num_vertices() const { return m_num_vertices; }
|
||||
const double* vertices() const { return m_vertices; }
|
||||
double* vertices() { return m_vertices; }
|
||||
|
||||
private:
|
||||
unsigned m_vertex;
|
||||
unsigned m_num_vertices;
|
||||
double m_vertices[26];
|
||||
unsigned m_cmd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==========================================================bezier_arc_svg
|
||||
// Compute an SVG-style bezier arc.
|
||||
//
|
||||
// Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
|
||||
// orientation of the ellipse are defined by two radii (rx, ry)
|
||||
// and an x-axis-rotation, which indicates how the ellipse as a whole
|
||||
// is rotated relative to the current coordinate system. The center
|
||||
// (cx, cy) of the ellipse is calculated automatically to satisfy the
|
||||
// constraints imposed by the other parameters.
|
||||
// large-arc-flag and sweep-flag contribute to the automatic calculations
|
||||
// and help determine how the arc is drawn.
|
||||
class bezier_arc_svg
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
|
||||
|
||||
bezier_arc_svg(double x1, double y1,
|
||||
double rx, double ry,
|
||||
double angle,
|
||||
bool large_arc_flag,
|
||||
bool sweep_flag,
|
||||
double x2, double y2) :
|
||||
m_arc(), m_radii_ok(false)
|
||||
{
|
||||
init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(double x1, double y1,
|
||||
double rx, double ry,
|
||||
double angle,
|
||||
bool large_arc_flag,
|
||||
bool sweep_flag,
|
||||
double x2, double y2);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool radii_ok() const { return m_radii_ok; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_arc.rewind(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
return m_arc.vertex(x, y);
|
||||
}
|
||||
|
||||
// Supplemantary functions. num_vertices() actually returns doubled
|
||||
// number of vertices. That is, for 1 vertex it returns 2.
|
||||
//--------------------------------------------------------------------
|
||||
unsigned num_vertices() const { return m_arc.num_vertices(); }
|
||||
const double* vertices() const { return m_arc.vertices(); }
|
||||
double* vertices() { return m_arc.vertices(); }
|
||||
|
||||
private:
|
||||
bezier_arc m_arc;
|
||||
bool m_radii_ok;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
54
agg/include/agg_bitset_iterator.h
Normal file
54
agg/include/agg_bitset_iterator.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BITSET_ITERATOR_INCLUDED
|
||||
#define AGG_BITSET_ITERATOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
class bitset_iterator
|
||||
{
|
||||
public:
|
||||
bitset_iterator(const int8u* bits, unsigned offset = 0) :
|
||||
m_bits(bits + (offset >> 3)),
|
||||
m_mask(0x80 >> (offset & 7))
|
||||
{}
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
m_mask >>= 1;
|
||||
if(m_mask == 0)
|
||||
{
|
||||
++m_bits;
|
||||
m_mask = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned bit() const
|
||||
{
|
||||
return (*m_bits) & m_mask;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_bits;
|
||||
int8u m_mask;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
116
agg/include/agg_bounding_rect.h
Normal file
116
agg/include/agg_bounding_rect.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// bounding_rect function template
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_BOUNDING_RECT_INCLUDED
|
||||
#define AGG_BOUNDING_RECT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------bounding_rect
|
||||
template<class VertexSource, class GetId, class CoordT>
|
||||
bool bounding_rect(VertexSource& vs, GetId& gi,
|
||||
unsigned start, unsigned num,
|
||||
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||
{
|
||||
unsigned i;
|
||||
double x;
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
vs.rewind(gi[start + i]);
|
||||
unsigned cmd;
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
*x1 = CoordT(x);
|
||||
*y1 = CoordT(y);
|
||||
*x2 = CoordT(x);
|
||||
*y2 = CoordT(y);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return *x1 <= *x2 && *y1 <= *y2;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------bounding_rect_single
|
||||
template<class VertexSource, class CoordT>
|
||||
bool bounding_rect_single(VertexSource& vs, unsigned path_id,
|
||||
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
vs.rewind(path_id);
|
||||
unsigned cmd;
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
*x1 = CoordT(x);
|
||||
*y1 = CoordT(y);
|
||||
*x2 = CoordT(x);
|
||||
*y2 = CoordT(y);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return *x1 <= *x2 && *y1 <= *y2;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
77
agg/include/agg_bspline.h
Normal file
77
agg/include/agg_bspline.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 bspline
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BSPLINE_INCLUDED
|
||||
#define AGG_BSPLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//----------------------------------------------------------------bspline
|
||||
// A very simple class of Bi-cubic Spline interpolation.
|
||||
// First call init(num, x[], y[]) where num - number of source points,
|
||||
// x, y - arrays of X and Y values respectively. Here Y must be a function
|
||||
// of X. It means that all the X-coordinates must be arranged in the ascending
|
||||
// order.
|
||||
// Then call get(x) that calculates a value Y for the respective X.
|
||||
// The class supports extrapolation, i.e. you can call get(x) where x is
|
||||
// outside the given with init() X-range. Extrapolation is a simple linear
|
||||
// function.
|
||||
//
|
||||
// See Implementation agg_bspline.cpp
|
||||
//------------------------------------------------------------------------
|
||||
class bspline
|
||||
{
|
||||
public:
|
||||
~bspline();
|
||||
bspline();
|
||||
bspline(int num);
|
||||
bspline(int num, const double* x, const double* y);
|
||||
|
||||
void init(int num);
|
||||
void add_point(double x, double y);
|
||||
void prepare();
|
||||
|
||||
void init(int num, const double* x, const double* y);
|
||||
|
||||
double get(double x) const;
|
||||
double get_stateful(double x) const;
|
||||
|
||||
private:
|
||||
bspline(const bspline&);
|
||||
const bspline& operator = (const bspline&);
|
||||
|
||||
static void bsearch(int n, const double *x, double x0, int *i);
|
||||
double extrapolation_left(double x) const;
|
||||
double extrapolation_right(double x) const;
|
||||
double interpolation(double x, int i) const;
|
||||
|
||||
int m_max;
|
||||
int m_num;
|
||||
double* m_x;
|
||||
double* m_y;
|
||||
double* m_am;
|
||||
mutable int m_last_idx;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
333
agg/include/agg_clip_liang_barsky.h
Normal file
333
agg/include/agg_clip_liang_barsky.h
Normal file
|
@ -0,0 +1,333 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Liang-Barsky clipping
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum clipping_flags_e
|
||||
{
|
||||
clipping_flags_x1_clipped = 4,
|
||||
clipping_flags_x2_clipped = 1,
|
||||
clipping_flags_y1_clipped = 8,
|
||||
clipping_flags_y2_clipped = 2,
|
||||
clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
|
||||
clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
|
||||
};
|
||||
|
||||
//----------------------------------------------------------clipping_flags
|
||||
// Determine the clipping code of the vertex according to the
|
||||
// Cyrus-Beck line clipping algorithm
|
||||
//
|
||||
// | |
|
||||
// 0110 | 0010 | 0011
|
||||
// | |
|
||||
// -------+--------+-------- clip_box.y2
|
||||
// | |
|
||||
// 0100 | 0000 | 0001
|
||||
// | |
|
||||
// -------+--------+-------- clip_box.y1
|
||||
// | |
|
||||
// 1100 | 1000 | 1001
|
||||
// | |
|
||||
// clip_box.x1 clip_box.x2
|
||||
//
|
||||
//
|
||||
template<class T>
|
||||
inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
|
||||
{
|
||||
return (x > clip_box.x2) |
|
||||
((y > clip_box.y2) << 1) |
|
||||
((x < clip_box.x1) << 2) |
|
||||
((y < clip_box.y1) << 3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------clipping_flags_x
|
||||
template<class T>
|
||||
inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
|
||||
{
|
||||
return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------clipping_flags_y
|
||||
template<class T>
|
||||
inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
|
||||
{
|
||||
return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------clip_liang_barsky
|
||||
template<class T>
|
||||
inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
|
||||
const rect_base<T>& clip_box,
|
||||
T* x, T* y)
|
||||
{
|
||||
const double nearzero = 1e-30;
|
||||
|
||||
double deltax = x2 - x1;
|
||||
double deltay = y2 - y1;
|
||||
double xin;
|
||||
double xout;
|
||||
double yin;
|
||||
double yout;
|
||||
double tinx;
|
||||
double tiny;
|
||||
double toutx;
|
||||
double touty;
|
||||
double tin1;
|
||||
double tin2;
|
||||
double tout1;
|
||||
unsigned np = 0;
|
||||
|
||||
if(deltax == 0.0)
|
||||
{
|
||||
// bump off of the vertical
|
||||
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
|
||||
}
|
||||
|
||||
if(deltay == 0.0)
|
||||
{
|
||||
// bump off of the horizontal
|
||||
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
|
||||
}
|
||||
|
||||
if(deltax > 0.0)
|
||||
{
|
||||
// points to right
|
||||
xin = clip_box.x1;
|
||||
xout = clip_box.x2;
|
||||
}
|
||||
else
|
||||
{
|
||||
xin = clip_box.x2;
|
||||
xout = clip_box.x1;
|
||||
}
|
||||
|
||||
if(deltay > 0.0)
|
||||
{
|
||||
// points up
|
||||
yin = clip_box.y1;
|
||||
yout = clip_box.y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
yin = clip_box.y2;
|
||||
yout = clip_box.y1;
|
||||
}
|
||||
|
||||
tinx = (xin - x1) / deltax;
|
||||
tiny = (yin - y1) / deltay;
|
||||
|
||||
if (tinx < tiny)
|
||||
{
|
||||
// hits x first
|
||||
tin1 = tinx;
|
||||
tin2 = tiny;
|
||||
}
|
||||
else
|
||||
{
|
||||
// hits y first
|
||||
tin1 = tiny;
|
||||
tin2 = tinx;
|
||||
}
|
||||
|
||||
if(tin1 <= 1.0)
|
||||
{
|
||||
if(0.0 < tin1)
|
||||
{
|
||||
*x++ = (T)xin;
|
||||
*y++ = (T)yin;
|
||||
++np;
|
||||
}
|
||||
|
||||
if(tin2 <= 1.0)
|
||||
{
|
||||
toutx = (xout - x1) / deltax;
|
||||
touty = (yout - y1) / deltay;
|
||||
|
||||
tout1 = (toutx < touty) ? toutx : touty;
|
||||
|
||||
if(tin2 > 0.0 || tout1 > 0.0)
|
||||
{
|
||||
if(tin2 <= tout1)
|
||||
{
|
||||
if(tin2 > 0.0)
|
||||
{
|
||||
if(tinx > tiny)
|
||||
{
|
||||
*x++ = (T)xin;
|
||||
*y++ = (T)(y1 + tinx * deltay);
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = (T)(x1 + tiny * deltax);
|
||||
*y++ = (T)yin;
|
||||
}
|
||||
++np;
|
||||
}
|
||||
|
||||
if(tout1 < 1.0)
|
||||
{
|
||||
if(toutx < touty)
|
||||
{
|
||||
*x++ = (T)xout;
|
||||
*y++ = (T)(y1 + toutx * deltay);
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = (T)(x1 + touty * deltax);
|
||||
*y++ = (T)yout;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = x2;
|
||||
*y++ = y2;
|
||||
}
|
||||
++np;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tinx > tiny)
|
||||
{
|
||||
*x++ = (T)xin;
|
||||
*y++ = (T)yout;
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = (T)xout;
|
||||
*y++ = (T)yin;
|
||||
}
|
||||
++np;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class T>
|
||||
bool clip_move_point(T x1, T y1, T x2, T y2,
|
||||
const rect_base<T>& clip_box,
|
||||
T* x, T* y, unsigned flags)
|
||||
{
|
||||
T bound;
|
||||
|
||||
if(flags & clipping_flags_x_clipped)
|
||||
{
|
||||
if(x1 == x2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
|
||||
*y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
|
||||
*x = bound;
|
||||
}
|
||||
|
||||
flags = clipping_flags_y(*y, clip_box);
|
||||
if(flags & clipping_flags_y_clipped)
|
||||
{
|
||||
if(y1 == y2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
|
||||
*x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
|
||||
*y = bound;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------clip_line_segment
|
||||
// Returns: ret >= 4 - Fully clipped
|
||||
// (ret & 1) != 0 - First point has been moved
|
||||
// (ret & 2) != 0 - Second point has been moved
|
||||
//
|
||||
template<class T>
|
||||
unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2,
|
||||
const rect_base<T>& clip_box)
|
||||
{
|
||||
unsigned f1 = clipping_flags(*x1, *y1, clip_box);
|
||||
unsigned f2 = clipping_flags(*x2, *y2, clip_box);
|
||||
unsigned ret = 0;
|
||||
|
||||
if((f2 | f1) == 0)
|
||||
{
|
||||
// Fully visible
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((f1 & clipping_flags_x_clipped) != 0 &&
|
||||
(f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
|
||||
{
|
||||
// Fully clipped
|
||||
return 4;
|
||||
}
|
||||
|
||||
if((f1 & clipping_flags_y_clipped) != 0 &&
|
||||
(f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
|
||||
{
|
||||
// Fully clipped
|
||||
return 4;
|
||||
}
|
||||
|
||||
T tx1 = *x1;
|
||||
T ty1 = *y1;
|
||||
T tx2 = *x2;
|
||||
T ty2 = *y2;
|
||||
if(f1)
|
||||
{
|
||||
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
if(*x1 == *x2 && *y1 == *y2)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
ret |= 1;
|
||||
}
|
||||
if(f2)
|
||||
{
|
||||
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
if(*x1 == *x2 && *y1 == *y2)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
ret |= 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
364
agg/include/agg_color_gray.h
Normal file
364
agg/include/agg_color_gray.h
Normal file
|
@ -0,0 +1,364 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// color types gray8, gray16
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_COLOR_GRAY_INCLUDED
|
||||
#define AGG_COLOR_GRAY_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===================================================================gray8
|
||||
struct gray8
|
||||
{
|
||||
typedef int8u value_type;
|
||||
typedef int32u calc_type;
|
||||
typedef int32 long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = 8,
|
||||
base_scale = 1 << base_shift,
|
||||
base_mask = base_scale - 1
|
||||
};
|
||||
typedef gray8 self_type;
|
||||
|
||||
value_type v;
|
||||
value_type a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(unsigned v_, unsigned a_=base_mask) :
|
||||
v(int8u(v_)), a(int8u(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const self_type& c, unsigned a_) :
|
||||
v(c.v), a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const rgba& c) :
|
||||
v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
|
||||
a((value_type)uround(c.a * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const rgba& c, double a_) :
|
||||
v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
|
||||
a((value_type)uround(a_ * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const rgba8& c) :
|
||||
v((c.r*77 + c.g*150 + c.b*29) >> 8),
|
||||
a(c.a) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const rgba8& c, unsigned a_) :
|
||||
v((c.r*77 + c.g*150 + c.b*29) >> 8),
|
||||
a(a_) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
v = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& transparent()
|
||||
{
|
||||
a = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = (value_type)uround(a_ * double(base_mask));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return double(a) / double(base_mask);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
v = value_type((calc_type(v) * a) >> base_shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply(unsigned a_)
|
||||
{
|
||||
if(a == base_mask && a_ >= base_mask) return *this;
|
||||
if(a == 0 || a_ == 0)
|
||||
{
|
||||
v = a = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * a_) / a;
|
||||
v = value_type((v_ > a_) ? a_ : v_);
|
||||
a = value_type(a_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& demultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * base_mask) / a;
|
||||
v = value_type((v_ > base_mask) ? base_mask : v_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
self_type gradient(self_type c, double k) const
|
||||
{
|
||||
self_type ret;
|
||||
calc_type ik = uround(k * base_scale);
|
||||
ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift));
|
||||
ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0); }
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------gray8_pre
|
||||
inline gray8 gray8_pre(unsigned v, unsigned a = gray8::base_mask)
|
||||
{
|
||||
return gray8(v,a).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const gray8& c, unsigned a)
|
||||
{
|
||||
return gray8(c,a).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const rgba& c)
|
||||
{
|
||||
return gray8(c).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const rgba& c, double a)
|
||||
{
|
||||
return gray8(c,a).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const rgba8& c)
|
||||
{
|
||||
return gray8(c).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const rgba8& c, unsigned a)
|
||||
{
|
||||
return gray8(c,a).premultiply();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==================================================================gray16
|
||||
struct gray16
|
||||
{
|
||||
typedef int16u value_type;
|
||||
typedef int32u calc_type;
|
||||
typedef int64 long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = 16,
|
||||
base_scale = 1 << base_shift,
|
||||
base_mask = base_scale - 1
|
||||
};
|
||||
typedef gray16 self_type;
|
||||
|
||||
value_type v;
|
||||
value_type a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(unsigned v_, unsigned a_=base_mask) :
|
||||
v(int16u(v_)), a(int16u(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const self_type& c, unsigned a_) :
|
||||
v(c.v), a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const rgba& c) :
|
||||
v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
|
||||
a((value_type)uround(c.a * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const rgba& c, double a_) :
|
||||
v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
|
||||
a((value_type)uround(a_ * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const rgba8& c) :
|
||||
v(c.r*77 + c.g*150 + c.b*29),
|
||||
a((value_type(c.a) << 8) | c.a) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const rgba8& c, unsigned a_) :
|
||||
v(c.r*77 + c.g*150 + c.b*29),
|
||||
a((value_type(a_) << 8) | c.a) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
v = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& transparent()
|
||||
{
|
||||
a = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = (value_type)uround(a_ * double(base_mask));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return double(a) / double(base_mask);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
v = value_type((calc_type(v) * a) >> base_shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply(unsigned a_)
|
||||
{
|
||||
if(a == base_mask && a_ >= base_mask) return *this;
|
||||
if(a == 0 || a_ == 0)
|
||||
{
|
||||
v = a = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * a_) / a;
|
||||
v = value_type((v_ > a_) ? a_ : v_);
|
||||
a = value_type(a_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& demultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * base_mask) / a;
|
||||
v = value_type((v_ > base_mask) ? base_mask : v_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
self_type gradient(self_type c, double k) const
|
||||
{
|
||||
self_type ret;
|
||||
calc_type ik = uround(k * base_scale);
|
||||
ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift));
|
||||
ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0); }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------gray16_pre
|
||||
inline gray16 gray16_pre(unsigned v, unsigned a = gray16::base_mask)
|
||||
{
|
||||
return gray16(v,a).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const gray16& c, unsigned a)
|
||||
{
|
||||
return gray16(c,a).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const rgba& c)
|
||||
{
|
||||
return gray16(c).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const rgba& c, double a)
|
||||
{
|
||||
return gray16(c,a).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const rgba8& c)
|
||||
{
|
||||
return gray16(c).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const rgba8& c, unsigned a)
|
||||
{
|
||||
return gray16(c,a).premultiply();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
716
agg/include/agg_color_rgba.h
Normal file
716
agg/include/agg_color_rgba.h
Normal file
|
@ -0,0 +1,716 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_COLOR_RGBA_INCLUDED
|
||||
#define AGG_COLOR_RGBA_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
// Supported byte orders for RGB and RGBA pixel formats
|
||||
//=======================================================================
|
||||
struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb
|
||||
struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr
|
||||
struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba
|
||||
struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb
|
||||
struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr
|
||||
struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra
|
||||
|
||||
//====================================================================rgba
|
||||
struct rgba
|
||||
{
|
||||
typedef double value_type;
|
||||
|
||||
double r;
|
||||
double g;
|
||||
double b;
|
||||
double a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba(double r_, double g_, double b_, double a_=1.0) :
|
||||
r(r_), g(g_), b(b_), a(a_) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& transparent()
|
||||
{
|
||||
a = 0.0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = a_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& premultiply()
|
||||
{
|
||||
r *= a;
|
||||
g *= a;
|
||||
b *= a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& premultiply(double a_)
|
||||
{
|
||||
if(a <= 0.0 || a_ <= 0.0)
|
||||
{
|
||||
r = g = b = a = 0.0;
|
||||
return *this;
|
||||
}
|
||||
a_ /= a;
|
||||
r *= a_;
|
||||
g *= a_;
|
||||
b *= a_;
|
||||
a = a_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& demultiply()
|
||||
{
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
double a_ = 1.0 / a;
|
||||
r *= a_;
|
||||
g *= a_;
|
||||
b *= a_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba gradient(rgba c, double k) const
|
||||
{
|
||||
rgba ret;
|
||||
ret.r = r + (c.r - r) * k;
|
||||
ret.g = g + (c.g - g) * k;
|
||||
ret.b = b + (c.b - b) * k;
|
||||
ret.a = a + (c.a - a) * k;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static rgba no_color() { return rgba(0,0,0,0); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static rgba from_wavelength(double wl, double gamma = 1.0);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
explicit rgba(double wavelen, double gamma=1.0)
|
||||
{
|
||||
*this = from_wavelength(wavelen, gamma);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------rgba_pre
|
||||
inline rgba rgba_pre(double r, double g, double b, double a=1.0)
|
||||
{
|
||||
return rgba(r, g, b, a).premultiply();
|
||||
}
|
||||
inline rgba rgba_pre(const rgba& c)
|
||||
{
|
||||
return rgba(c).premultiply();
|
||||
}
|
||||
inline rgba rgba_pre(const rgba& c, double a)
|
||||
{
|
||||
return rgba(c, a).premultiply();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline rgba rgba::from_wavelength(double wl, double gamma)
|
||||
{
|
||||
rgba t(0.0, 0.0, 0.0);
|
||||
|
||||
if(wl >= 380.0 && wl <= 440.0)
|
||||
{
|
||||
t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
|
||||
t.b = 1.0;
|
||||
}
|
||||
else
|
||||
if(wl >= 440.0 && wl <= 490.0)
|
||||
{
|
||||
t.g = (wl - 440.0) / (490.0 - 440.0);
|
||||
t.b = 1.0;
|
||||
}
|
||||
else
|
||||
if(wl >= 490.0 && wl <= 510.0)
|
||||
{
|
||||
t.g = 1.0;
|
||||
t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
|
||||
}
|
||||
else
|
||||
if(wl >= 510.0 && wl <= 580.0)
|
||||
{
|
||||
t.r = (wl - 510.0) / (580.0 - 510.0);
|
||||
t.g = 1.0;
|
||||
}
|
||||
else
|
||||
if(wl >= 580.0 && wl <= 645.0)
|
||||
{
|
||||
t.r = 1.0;
|
||||
t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
|
||||
}
|
||||
else
|
||||
if(wl >= 645.0 && wl <= 780.0)
|
||||
{
|
||||
t.r = 1.0;
|
||||
}
|
||||
|
||||
double s = 1.0;
|
||||
if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
|
||||
else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
|
||||
|
||||
t.r = pow(t.r * s, gamma);
|
||||
t.g = pow(t.g * s, gamma);
|
||||
t.b = pow(t.b * s, gamma);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===================================================================rgba8
|
||||
struct rgba8
|
||||
{
|
||||
typedef int8u value_type;
|
||||
typedef int32u calc_type;
|
||||
typedef int32 long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = 8,
|
||||
base_scale = 1 << base_shift,
|
||||
base_mask = base_scale - 1
|
||||
};
|
||||
typedef rgba8 self_type;
|
||||
|
||||
|
||||
value_type r;
|
||||
value_type g;
|
||||
value_type b;
|
||||
value_type a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
|
||||
r(value_type(r_)),
|
||||
g(value_type(g_)),
|
||||
b(value_type(b_)),
|
||||
a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8(const rgba& c, double a_) :
|
||||
r((value_type)uround(c.r * double(base_mask))),
|
||||
g((value_type)uround(c.g * double(base_mask))),
|
||||
b((value_type)uround(c.b * double(base_mask))),
|
||||
a((value_type)uround(a_ * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8(const self_type& c, unsigned a_) :
|
||||
r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8(const rgba& c) :
|
||||
r((value_type)uround(c.r * double(base_mask))),
|
||||
g((value_type)uround(c.g * double(base_mask))),
|
||||
b((value_type)uround(c.b * double(base_mask))),
|
||||
a((value_type)uround(c.a * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& transparent()
|
||||
{
|
||||
a = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = (value_type)uround(a_ * double(base_mask));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return double(a) / double(base_mask);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& premultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
r = value_type((calc_type(r) * a) >> base_shift);
|
||||
g = value_type((calc_type(g) * a) >> base_shift);
|
||||
b = value_type((calc_type(b) * a) >> base_shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& premultiply(unsigned a_)
|
||||
{
|
||||
if(a == base_mask && a_ >= base_mask) return *this;
|
||||
if(a == 0 || a_ == 0)
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type r_ = (calc_type(r) * a_) / a;
|
||||
calc_type g_ = (calc_type(g) * a_) / a;
|
||||
calc_type b_ = (calc_type(b) * a_) / a;
|
||||
r = value_type((r_ > a_) ? a_ : r_);
|
||||
g = value_type((g_ > a_) ? a_ : g_);
|
||||
b = value_type((b_ > a_) ? a_ : b_);
|
||||
a = value_type(a_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& demultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type r_ = (calc_type(r) * base_mask) / a;
|
||||
calc_type g_ = (calc_type(g) * base_mask) / a;
|
||||
calc_type b_ = (calc_type(b) * base_mask) / a;
|
||||
r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
|
||||
g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
|
||||
b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE self_type gradient(const self_type& c, double k) const
|
||||
{
|
||||
self_type ret;
|
||||
calc_type ik = uround(k * base_scale);
|
||||
ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
|
||||
ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
|
||||
ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
|
||||
ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void add(const self_type& c, unsigned cover)
|
||||
{
|
||||
calc_type cr, cg, cb, ca;
|
||||
if(cover == cover_mask)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*this = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
|
||||
cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
|
||||
cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
|
||||
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = r + ((c.r * cover + cover_mask/2) >> cover_shift);
|
||||
cg = g + ((c.g * cover + cover_mask/2) >> cover_shift);
|
||||
cb = b + ((c.b * cover + cover_mask/2) >> cover_shift);
|
||||
ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
|
||||
r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
|
||||
g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
|
||||
b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
|
||||
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLUT>
|
||||
AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
|
||||
{
|
||||
r = gamma.dir(r);
|
||||
g = gamma.dir(g);
|
||||
b = gamma.dir(b);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLUT>
|
||||
AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
|
||||
{
|
||||
r = gamma.inv(r);
|
||||
g = gamma.inv(g);
|
||||
b = gamma.inv(b);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0,0,0); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type from_wavelength(double wl, double gamma = 1.0)
|
||||
{
|
||||
return self_type(rgba::from_wavelength(wl, gamma));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------rgba8_pre
|
||||
inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b,
|
||||
unsigned a = rgba8::base_mask)
|
||||
{
|
||||
return rgba8(r,g,b,a).premultiply();
|
||||
}
|
||||
inline rgba8 rgba8_pre(const rgba8& c)
|
||||
{
|
||||
return rgba8(c).premultiply();
|
||||
}
|
||||
inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
|
||||
{
|
||||
return rgba8(c,a).premultiply();
|
||||
}
|
||||
inline rgba8 rgba8_pre(const rgba& c)
|
||||
{
|
||||
return rgba8(c).premultiply();
|
||||
}
|
||||
inline rgba8 rgba8_pre(const rgba& c, double a)
|
||||
{
|
||||
return rgba8(c,a).premultiply();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------rgb8_packed
|
||||
inline rgba8 rgb8_packed(unsigned v)
|
||||
{
|
||||
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------bgr8_packed
|
||||
inline rgba8 bgr8_packed(unsigned v)
|
||||
{
|
||||
return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------argb8_packed
|
||||
inline rgba8 argb8_packed(unsigned v)
|
||||
{
|
||||
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=================================================================rgba16
|
||||
struct rgba16
|
||||
{
|
||||
typedef int16u value_type;
|
||||
typedef int32u calc_type;
|
||||
typedef int64 long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = 16,
|
||||
base_scale = 1 << base_shift,
|
||||
base_mask = base_scale - 1
|
||||
};
|
||||
typedef rgba16 self_type;
|
||||
|
||||
value_type r;
|
||||
value_type g;
|
||||
value_type b;
|
||||
value_type a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
|
||||
r(value_type(r_)),
|
||||
g(value_type(g_)),
|
||||
b(value_type(b_)),
|
||||
a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const self_type& c, unsigned a_) :
|
||||
r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const rgba& c) :
|
||||
r((value_type)uround(c.r * double(base_mask))),
|
||||
g((value_type)uround(c.g * double(base_mask))),
|
||||
b((value_type)uround(c.b * double(base_mask))),
|
||||
a((value_type)uround(c.a * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const rgba& c, double a_) :
|
||||
r((value_type)uround(c.r * double(base_mask))),
|
||||
g((value_type)uround(c.g * double(base_mask))),
|
||||
b((value_type)uround(c.b * double(base_mask))),
|
||||
a((value_type)uround(a_ * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const rgba8& c) :
|
||||
r(value_type((value_type(c.r) << 8) | c.r)),
|
||||
g(value_type((value_type(c.g) << 8) | c.g)),
|
||||
b(value_type((value_type(c.b) << 8) | c.b)),
|
||||
a(value_type((value_type(c.a) << 8) | c.a)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const rgba8& c, unsigned a_) :
|
||||
r(value_type((value_type(c.r) << 8) | c.r)),
|
||||
g(value_type((value_type(c.g) << 8) | c.g)),
|
||||
b(value_type((value_type(c.b) << 8) | c.b)),
|
||||
a(value_type(( a_ << 8) | c.a)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& transparent()
|
||||
{
|
||||
a = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = (value_type)uround(a_ * double(base_mask));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return double(a) / double(base_mask);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& premultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
r = value_type((calc_type(r) * a) >> base_shift);
|
||||
g = value_type((calc_type(g) * a) >> base_shift);
|
||||
b = value_type((calc_type(b) * a) >> base_shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& premultiply(unsigned a_)
|
||||
{
|
||||
if(a == base_mask && a_ >= base_mask) return *this;
|
||||
if(a == 0 || a_ == 0)
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type r_ = (calc_type(r) * a_) / a;
|
||||
calc_type g_ = (calc_type(g) * a_) / a;
|
||||
calc_type b_ = (calc_type(b) * a_) / a;
|
||||
r = value_type((r_ > a_) ? a_ : r_);
|
||||
g = value_type((g_ > a_) ? a_ : g_);
|
||||
b = value_type((b_ > a_) ? a_ : b_);
|
||||
a = value_type(a_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& demultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type r_ = (calc_type(r) * base_mask) / a;
|
||||
calc_type g_ = (calc_type(g) * base_mask) / a;
|
||||
calc_type b_ = (calc_type(b) * base_mask) / a;
|
||||
r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
|
||||
g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
|
||||
b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE self_type gradient(const self_type& c, double k) const
|
||||
{
|
||||
self_type ret;
|
||||
calc_type ik = uround(k * base_scale);
|
||||
ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
|
||||
ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
|
||||
ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
|
||||
ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void add(const self_type& c, unsigned cover)
|
||||
{
|
||||
calc_type cr, cg, cb, ca;
|
||||
if(cover == cover_mask)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*this = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
|
||||
cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
|
||||
cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
|
||||
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = r + ((c.r * cover + cover_mask) >> cover_shift);
|
||||
cg = g + ((c.g * cover + cover_mask) >> cover_shift);
|
||||
cb = b + ((c.b * cover + cover_mask) >> cover_shift);
|
||||
ca = a + ((c.a * cover + cover_mask) >> cover_shift);
|
||||
r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
|
||||
g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
|
||||
b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
|
||||
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLUT>
|
||||
AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
|
||||
{
|
||||
r = gamma.dir(r);
|
||||
g = gamma.dir(g);
|
||||
b = gamma.dir(b);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLUT>
|
||||
AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
|
||||
{
|
||||
r = gamma.inv(r);
|
||||
g = gamma.inv(g);
|
||||
b = gamma.inv(b);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0,0,0); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type from_wavelength(double wl, double gamma = 1.0)
|
||||
{
|
||||
return self_type(rgba::from_wavelength(wl, gamma));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------rgba16_pre
|
||||
inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b,
|
||||
unsigned a = rgba16::base_mask)
|
||||
{
|
||||
return rgba16(r,g,b,a).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba16& c, unsigned a)
|
||||
{
|
||||
return rgba16(c,a).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba& c)
|
||||
{
|
||||
return rgba16(c).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba& c, double a)
|
||||
{
|
||||
return rgba16(c,a).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba8& c)
|
||||
{
|
||||
return rgba16(c).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba8& c, unsigned a)
|
||||
{
|
||||
return rgba16(c,a).premultiply();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
26
agg/include/agg_config.h
Normal file
26
agg/include/agg_config.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef AGG_CONFIG_INCLUDED
|
||||
#define AGG_CONFIG_INCLUDED
|
||||
|
||||
// This file can be used to redefine the default basic types such as:
|
||||
//
|
||||
// AGG_INT8
|
||||
// AGG_INT8U
|
||||
// AGG_INT16
|
||||
// AGG_INT16U
|
||||
// AGG_INT32
|
||||
// AGG_INT32U
|
||||
// AGG_INT64
|
||||
// AGG_INT64U
|
||||
//
|
||||
// Just replace this file with new defines if necessary.
|
||||
// For example, if your compiler doesn't have a 64 bit integer type
|
||||
// you can still use AGG if you define the follows:
|
||||
//
|
||||
// #define AGG_INT64 int
|
||||
// #define AGG_INT64U unsigned
|
||||
//
|
||||
// It will result in overflow in 16 bit-per-component image/pattern resampling
|
||||
// but it won't result any crash and the rest of the library will remain
|
||||
// fully functional.
|
||||
|
||||
#endif
|
158
agg/include/agg_conv_adaptor_vcgen.h
Normal file
158
agg/include/agg_conv_adaptor_vcgen.h
Normal file
|
@ -0,0 +1,158 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||
#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//------------------------------------------------------------null_markers
|
||||
struct null_markers
|
||||
{
|
||||
void remove_all() {}
|
||||
void add_vertex(double, double, unsigned) {}
|
||||
void prepare_src() {}
|
||||
|
||||
void rewind(unsigned) {}
|
||||
unsigned vertex(double*, double*) { return path_cmd_stop; }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------conv_adaptor_vcgen
|
||||
template<class VertexSource,
|
||||
class Generator,
|
||||
class Markers=null_markers> class conv_adaptor_vcgen
|
||||
{
|
||||
enum status
|
||||
{
|
||||
initial,
|
||||
accumulate,
|
||||
generate
|
||||
};
|
||||
|
||||
public:
|
||||
conv_adaptor_vcgen(VertexSource& source) :
|
||||
m_source(&source),
|
||||
m_status(initial)
|
||||
{}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
|
||||
Generator& generator() { return m_generator; }
|
||||
const Generator& generator() const { return m_generator; }
|
||||
|
||||
Markers& markers() { return m_markers; }
|
||||
const Markers& markers() const { return m_markers; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_status = initial;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
// Prohibit copying
|
||||
conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||
const conv_adaptor_vcgen<VertexSource, Generator, Markers>&
|
||||
operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
Generator m_generator;
|
||||
Markers m_markers;
|
||||
status m_status;
|
||||
unsigned m_last_cmd;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Generator, class Markers>
|
||||
unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
bool done = false;
|
||||
while(!done)
|
||||
{
|
||||
switch(m_status)
|
||||
{
|
||||
case initial:
|
||||
m_markers.remove_all();
|
||||
m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
|
||||
m_status = accumulate;
|
||||
|
||||
case accumulate:
|
||||
if(is_stop(m_last_cmd)) return path_cmd_stop;
|
||||
|
||||
m_generator.remove_all();
|
||||
m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||
m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
cmd = m_source->vertex(x, y);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_last_cmd = cmd;
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
m_start_x = *x;
|
||||
m_start_y = *y;
|
||||
break;
|
||||
}
|
||||
m_generator.add_vertex(*x, *y, cmd);
|
||||
m_markers.add_vertex(*x, *y, path_cmd_line_to);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
m_last_cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
m_generator.add_vertex(*x, *y, cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_generator.rewind(0);
|
||||
m_status = generate;
|
||||
|
||||
case generate:
|
||||
cmd = m_generator.vertex(x, y);
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
m_status = accumulate;
|
||||
break;
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
160
agg/include/agg_conv_adaptor_vpgen.h
Normal file
160
agg/include/agg_conv_adaptor_vpgen.h
Normal file
|
@ -0,0 +1,160 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED
|
||||
#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//======================================================conv_adaptor_vpgen
|
||||
template<class VertexSource, class VPGen> class conv_adaptor_vpgen
|
||||
{
|
||||
public:
|
||||
conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
|
||||
VPGen& vpgen() { return m_vpgen; }
|
||||
const VPGen& vpgen() const { return m_vpgen; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
|
||||
const conv_adaptor_vpgen<VertexSource, VPGen>&
|
||||
operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
VPGen m_vpgen;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
unsigned m_poly_flags;
|
||||
int m_vertices;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class VPGen>
|
||||
void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_vpgen.reset();
|
||||
m_start_x = 0;
|
||||
m_start_y = 0;
|
||||
m_poly_flags = 0;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class VPGen>
|
||||
unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
for(;;)
|
||||
{
|
||||
cmd = m_vpgen.vertex(x, y);
|
||||
if(!is_stop(cmd)) break;
|
||||
|
||||
if(m_poly_flags && !m_vpgen.auto_unclose())
|
||||
{
|
||||
*x = 0.0;
|
||||
*y = 0.0;
|
||||
cmd = m_poly_flags;
|
||||
m_poly_flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_vertices < 0)
|
||||
{
|
||||
if(m_vertices < -1)
|
||||
{
|
||||
m_vertices = 0;
|
||||
return path_cmd_stop;
|
||||
}
|
||||
m_vpgen.move_to(m_start_x, m_start_y);
|
||||
m_vertices = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
double tx, ty;
|
||||
cmd = m_source->vertex(&tx, &ty);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
if(m_vpgen.auto_close() && m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
m_poly_flags = path_cmd_end_poly | path_flags_close;
|
||||
m_start_x = tx;
|
||||
m_start_y = ty;
|
||||
m_vertices = -1;
|
||||
continue;
|
||||
}
|
||||
m_vpgen.move_to(tx, ty);
|
||||
m_start_x = tx;
|
||||
m_start_y = ty;
|
||||
m_vertices = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vpgen.line_to(tx, ty);
|
||||
++m_vertices;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
m_poly_flags = cmd;
|
||||
if(is_closed(cmd) || m_vpgen.auto_close())
|
||||
{
|
||||
if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
|
||||
if(m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
}
|
||||
m_vertices = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// path_cmd_stop
|
||||
if(m_vpgen.auto_close() && m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
m_poly_flags = path_cmd_end_poly | path_flags_close;
|
||||
m_vertices = -2;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
48
agg/include/agg_conv_bspline.h
Normal file
48
agg/include/agg_conv_bspline.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_BSPLINE_INCLUDED
|
||||
#define AGG_CONV_BSPLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_bspline.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//---------------------------------------------------------conv_bspline
|
||||
template<class VertexSource>
|
||||
struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
|
||||
{
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
|
||||
|
||||
conv_bspline(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {}
|
||||
|
||||
void interpolation_step(double v) { base_type::generator().interpolation_step(v); }
|
||||
double interpolation_step() const { return base_type::generator().interpolation_step(); }
|
||||
|
||||
private:
|
||||
conv_bspline(const conv_bspline<VertexSource>&);
|
||||
const conv_bspline<VertexSource>&
|
||||
operator = (const conv_bspline<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
63
agg/include/agg_conv_clip_polygon.h
Normal file
63
agg/include/agg_conv_clip_polygon.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Polygon clipping converter
|
||||
// There an optimized Liang-Basky algorithm is used.
|
||||
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
|
||||
// break a closed polygon into two or more ones, instead, there will be
|
||||
// degenerate edges coinciding with the respective clipping boundaries.
|
||||
// This is a sub-optimal solution, because that optimization would require
|
||||
// extra, rather expensive math while the rasterizer tolerates it quite well,
|
||||
// without any considerable overhead.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED
|
||||
#define AGG_CONV_CLIP_POLYGON_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vpgen.h"
|
||||
#include "agg_vpgen_clip_polygon.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================conv_clip_polygon
|
||||
template<class VertexSource>
|
||||
struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>
|
||||
{
|
||||
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type;
|
||||
|
||||
conv_clip_polygon(VertexSource& vs) :
|
||||
conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
|
||||
|
||||
void clip_box(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
base_type::vpgen().clip_box(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
double x1() const { return base_type::vpgen().x1(); }
|
||||
double y1() const { return base_type::vpgen().y1(); }
|
||||
double x2() const { return base_type::vpgen().x2(); }
|
||||
double y2() const { return base_type::vpgen().y2(); }
|
||||
|
||||
private:
|
||||
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
|
||||
const conv_clip_polygon<VertexSource>&
|
||||
operator = (const conv_clip_polygon<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
63
agg/include/agg_conv_clip_polyline.h
Normal file
63
agg/include/agg_conv_clip_polyline.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// polyline clipping converter
|
||||
// There an optimized Liang-Basky algorithm is used.
|
||||
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
|
||||
// break a closed polyline into two or more ones, instead, there will be
|
||||
// degenerate edges coinciding with the respective clipping boundaries.
|
||||
// This is a sub-optimal solution, because that optimization would require
|
||||
// extra, rather expensive math while the rasterizer tolerates it quite well,
|
||||
// without any considerable overhead.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_CLIP_polyline_INCLUDED
|
||||
#define AGG_CONV_CLIP_polyline_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vpgen.h"
|
||||
#include "agg_vpgen_clip_polyline.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================conv_clip_polyline
|
||||
template<class VertexSource>
|
||||
struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>
|
||||
{
|
||||
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type;
|
||||
|
||||
conv_clip_polyline(VertexSource& vs) :
|
||||
conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {}
|
||||
|
||||
void clip_box(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
base_type::vpgen().clip_box(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
double x1() const { return base_type::vpgen().x1(); }
|
||||
double y1() const { return base_type::vpgen().y1(); }
|
||||
double x2() const { return base_type::vpgen().x2(); }
|
||||
double y2() const { return base_type::vpgen().y2(); }
|
||||
|
||||
private:
|
||||
conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
|
||||
const conv_clip_polyline<VertexSource>&
|
||||
operator = (const conv_clip_polyline<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
126
agg/include/agg_conv_close_polygon.h
Normal file
126
agg/include/agg_conv_close_polygon.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED
|
||||
#define AGG_CONV_CLOSE_POLYGON_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//======================================================conv_close_polygon
|
||||
template<class VertexSource> class conv_close_polygon
|
||||
{
|
||||
public:
|
||||
conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_close_polygon(const conv_close_polygon<VertexSource>&);
|
||||
const conv_close_polygon<VertexSource>&
|
||||
operator = (const conv_close_polygon<VertexSource>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
unsigned m_cmd[2];
|
||||
double m_x[2];
|
||||
double m_y[2];
|
||||
unsigned m_vertex;
|
||||
bool m_line_to;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_vertex = 2;
|
||||
m_line_to = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
for(;;)
|
||||
{
|
||||
if(m_vertex < 2)
|
||||
{
|
||||
*x = m_x[m_vertex];
|
||||
*y = m_y[m_vertex];
|
||||
cmd = m_cmd[m_vertex];
|
||||
++m_vertex;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd = m_source->vertex(x, y);
|
||||
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
cmd |= path_flags_close;
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
if(m_line_to)
|
||||
{
|
||||
m_cmd[0] = path_cmd_end_poly | path_flags_close;
|
||||
m_cmd[1] = path_cmd_stop;
|
||||
m_vertex = 0;
|
||||
m_line_to = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
if(m_line_to)
|
||||
{
|
||||
m_x[0] = 0.0;
|
||||
m_y[0] = 0.0;
|
||||
m_cmd[0] = path_cmd_end_poly | path_flags_close;
|
||||
m_x[1] = *x;
|
||||
m_y[1] = *y;
|
||||
m_cmd[1] = cmd;
|
||||
m_vertex = 0;
|
||||
m_line_to = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_line_to = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
74
agg/include/agg_conv_concat.h
Normal file
74
agg/include/agg_conv_concat.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CONCAT_INCLUDED
|
||||
#define AGG_CONV_CONCAT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//=============================================================conv_concat
|
||||
// Concatenation of two paths. Usually used to combine lines or curves
|
||||
// with markers such as arrowheads
|
||||
template<class VS1, class VS2> class conv_concat
|
||||
{
|
||||
public:
|
||||
conv_concat(VS1& source1, VS2& source2) :
|
||||
m_source1(&source1), m_source2(&source2), m_status(2) {}
|
||||
|
||||
void set_source1(VS1& source) { m_source1 = &source; }
|
||||
void set_source2(VS2& source) { m_source2 = &source; }
|
||||
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source1->rewind(path_id);
|
||||
m_source2->rewind(0);
|
||||
m_status = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd;
|
||||
if(m_status == 0)
|
||||
{
|
||||
cmd = m_source1->vertex(x, y);
|
||||
if(!is_stop(cmd)) return cmd;
|
||||
m_status = 1;
|
||||
}
|
||||
if(m_status == 1)
|
||||
{
|
||||
cmd = m_source2->vertex(x, y);
|
||||
if(!is_stop(cmd)) return cmd;
|
||||
m_status = 2;
|
||||
}
|
||||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
private:
|
||||
conv_concat(const conv_concat<VS1, VS2>&);
|
||||
const conv_concat<VS1, VS2>&
|
||||
operator = (const conv_concat<VS1, VS2>&);
|
||||
|
||||
VS1* m_source1;
|
||||
VS2* m_source2;
|
||||
int m_status;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
65
agg/include/agg_conv_contour.h
Normal file
65
agg/include/agg_conv_contour.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// conv_stroke
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_CONTOUR_INCLUDED
|
||||
#define AGG_CONV_CONTOUR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_contour.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------conv_contour
|
||||
template<class VertexSource>
|
||||
struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour>
|
||||
{
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
|
||||
|
||||
conv_contour(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
|
||||
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
|
||||
void width(double w) { base_type::generator().width(w); }
|
||||
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
|
||||
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
|
||||
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
|
||||
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
|
||||
|
||||
line_join_e line_join() const { return base_type::generator().line_join(); }
|
||||
inner_join_e inner_join() const { return base_type::generator().inner_join(); }
|
||||
double width() const { return base_type::generator().width(); }
|
||||
double miter_limit() const { return base_type::generator().miter_limit(); }
|
||||
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
|
||||
double approximation_scale() const { return base_type::generator().approximation_scale(); }
|
||||
bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
|
||||
|
||||
private:
|
||||
conv_contour(const conv_contour<VertexSource>&);
|
||||
const conv_contour<VertexSource>&
|
||||
operator = (const conv_contour<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
202
agg/include/agg_conv_curve.h
Normal file
202
agg/include/agg_conv_curve.h
Normal file
|
@ -0,0 +1,202 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 conv_curve
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CURVE_INCLUDED
|
||||
#define AGG_CONV_CURVE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_curves.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//---------------------------------------------------------------conv_curve
|
||||
// Curve converter class. Any path storage can have Bezier curves defined
|
||||
// by their control points. There're two types of curves supported: curve3
|
||||
// and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control
|
||||
// point. Curve4 has 2 control points (4 points in total) and can be used
|
||||
// to interpolate more complicated curves. Curve4, unlike curve3 can be used
|
||||
// to approximate arcs, both circular and elliptical. Curves are approximated
|
||||
// with straight lines and one of the approaches is just to store the whole
|
||||
// sequence of vertices that approximate our curve. It takes additional
|
||||
// memory, and at the same time the consecutive vertices can be calculated
|
||||
// on demand.
|
||||
//
|
||||
// Initially, path storages are not suppose to keep all the vertices of the
|
||||
// curves (although, nothing prevents us from doing so). Instead, path_storage
|
||||
// keeps only vertices, needed to calculate a curve on demand. Those vertices
|
||||
// are marked with special commands. So, if the path_storage contains curves
|
||||
// (which are not real curves yet), and we render this storage directly,
|
||||
// all we will see is only 2 or 3 straight line segments (for curve3 and
|
||||
// curve4 respectively). If we need to see real curves drawn we need to
|
||||
// include this class into the conversion pipeline.
|
||||
//
|
||||
// Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4
|
||||
// and converts these vertices into a move_to/line_to sequence.
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VertexSource,
|
||||
class Curve3=curve3,
|
||||
class Curve4=curve4> class conv_curve
|
||||
{
|
||||
public:
|
||||
typedef Curve3 curve3_type;
|
||||
typedef Curve4 curve4_type;
|
||||
typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
|
||||
|
||||
conv_curve(VertexSource& source) :
|
||||
m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
m_curve3.approximation_method(v);
|
||||
m_curve4.approximation_method(v);
|
||||
}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return m_curve4.approximation_method();
|
||||
}
|
||||
|
||||
void approximation_scale(double s)
|
||||
{
|
||||
m_curve3.approximation_scale(s);
|
||||
m_curve4.approximation_scale(s);
|
||||
}
|
||||
|
||||
double approximation_scale() const
|
||||
{
|
||||
return m_curve4.approximation_scale();
|
||||
}
|
||||
|
||||
void angle_tolerance(double v)
|
||||
{
|
||||
m_curve3.angle_tolerance(v);
|
||||
m_curve4.angle_tolerance(v);
|
||||
}
|
||||
|
||||
double angle_tolerance() const
|
||||
{
|
||||
return m_curve4.angle_tolerance();
|
||||
}
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_curve3.cusp_limit(v);
|
||||
m_curve4.cusp_limit(v);
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return m_curve4.cusp_limit();
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_curve(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
VertexSource* m_source;
|
||||
double m_last_x;
|
||||
double m_last_y;
|
||||
curve3_type m_curve3;
|
||||
curve4_type m_curve4;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Curve3, class Curve4>
|
||||
void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_last_x = 0.0;
|
||||
m_last_y = 0.0;
|
||||
m_curve3.reset();
|
||||
m_curve4.reset();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Curve3, class Curve4>
|
||||
unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
|
||||
{
|
||||
if(!is_stop(m_curve3.vertex(x, y)))
|
||||
{
|
||||
m_last_x = *x;
|
||||
m_last_y = *y;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
if(!is_stop(m_curve4.vertex(x, y)))
|
||||
{
|
||||
m_last_x = *x;
|
||||
m_last_y = *y;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
double ct2_x;
|
||||
double ct2_y;
|
||||
double end_x;
|
||||
double end_y;
|
||||
|
||||
unsigned cmd = m_source->vertex(x, y);
|
||||
switch(cmd)
|
||||
{
|
||||
case path_cmd_curve3:
|
||||
m_source->vertex(&end_x, &end_y);
|
||||
|
||||
m_curve3.init(m_last_x, m_last_y,
|
||||
*x, *y,
|
||||
end_x, end_y);
|
||||
|
||||
m_curve3.vertex(x, y); // First call returns path_cmd_move_to
|
||||
m_curve3.vertex(x, y); // This is the first vertex of the curve
|
||||
cmd = path_cmd_line_to;
|
||||
break;
|
||||
|
||||
case path_cmd_curve4:
|
||||
m_source->vertex(&ct2_x, &ct2_y);
|
||||
m_source->vertex(&end_x, &end_y);
|
||||
|
||||
m_curve4.init(m_last_x, m_last_y,
|
||||
*x, *y,
|
||||
ct2_x, ct2_y,
|
||||
end_x, end_y);
|
||||
|
||||
m_curve4.vertex(x, y); // First call returns path_cmd_move_to
|
||||
m_curve4.vertex(x, y); // This is the first vertex of the curve
|
||||
cmd = path_cmd_line_to;
|
||||
break;
|
||||
}
|
||||
m_last_x = *x;
|
||||
m_last_y = *y;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
68
agg/include/agg_conv_dash.h
Normal file
68
agg/include/agg_conv_dash.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// conv_dash
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_DASH_INCLUDED
|
||||
#define AGG_CONV_DASH_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_dash.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------conv_dash
|
||||
template<class VertexSource, class Markers=null_markers>
|
||||
struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>
|
||||
{
|
||||
typedef Markers marker_type;
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type;
|
||||
|
||||
conv_dash(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void remove_all_dashes()
|
||||
{
|
||||
base_type::generator().remove_all_dashes();
|
||||
}
|
||||
|
||||
void add_dash(double dash_len, double gap_len)
|
||||
{
|
||||
base_type::generator().add_dash(dash_len, gap_len);
|
||||
}
|
||||
|
||||
void dash_start(double ds)
|
||||
{
|
||||
base_type::generator().dash_start(ds);
|
||||
}
|
||||
|
||||
void shorten(double s) { base_type::generator().shorten(s); }
|
||||
double shorten() const { return base_type::generator().shorten(); }
|
||||
|
||||
private:
|
||||
conv_dash(const conv_dash<VertexSource, Markers>&);
|
||||
const conv_dash<VertexSource, Markers>&
|
||||
operator = (const conv_dash<VertexSource, Markers>&);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
437
agg/include/agg_conv_gpc.h
Normal file
437
agg/include/agg_conv_gpc.h
Normal file
|
@ -0,0 +1,437 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// General Polygon Clipper based on the GPC library by Alan Murta
|
||||
// Union, Intersection, XOR, A-B, B-A
|
||||
// Contact the author if you intend to use it in commercial applications!
|
||||
// http://www.cs.man.ac.uk/aig/staff/alan/software/
|
||||
// Alan Murta (email: gpc@cs.man.ac.uk)
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_GPC_INCLUDED
|
||||
#define AGG_CONV_GPC_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "gpc.h"
|
||||
}
|
||||
|
||||
namespace agg
|
||||
{
|
||||
enum gpc_op_e
|
||||
{
|
||||
gpc_or,
|
||||
gpc_and,
|
||||
gpc_xor,
|
||||
gpc_a_minus_b,
|
||||
gpc_b_minus_a
|
||||
};
|
||||
|
||||
|
||||
//================================================================conv_gpc
|
||||
template<class VSA, class VSB> class conv_gpc
|
||||
{
|
||||
enum status
|
||||
{
|
||||
status_move_to,
|
||||
status_line_to,
|
||||
status_stop
|
||||
};
|
||||
|
||||
struct contour_header_type
|
||||
{
|
||||
int num_vertices;
|
||||
int hole_flag;
|
||||
gpc_vertex* vertices;
|
||||
};
|
||||
|
||||
typedef pod_bvector<gpc_vertex, 8> vertex_array_type;
|
||||
typedef pod_bvector<contour_header_type, 6> contour_header_array_type;
|
||||
|
||||
|
||||
public:
|
||||
typedef VSA source_a_type;
|
||||
typedef VSB source_b_type;
|
||||
typedef conv_gpc<source_a_type, source_b_type> self_type;
|
||||
|
||||
~conv_gpc()
|
||||
{
|
||||
free_gpc_data();
|
||||
}
|
||||
|
||||
conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :
|
||||
m_src_a(&a),
|
||||
m_src_b(&b),
|
||||
m_status(status_move_to),
|
||||
m_vertex(-1),
|
||||
m_contour(-1),
|
||||
m_operation(op)
|
||||
{
|
||||
memset(&m_poly_a, 0, sizeof(m_poly_a));
|
||||
memset(&m_poly_b, 0, sizeof(m_poly_b));
|
||||
memset(&m_result, 0, sizeof(m_result));
|
||||
}
|
||||
|
||||
void set_source1(VSA& source) { m_src_a = &source; }
|
||||
void set_source2(VSB& source) { m_src_b = &source; }
|
||||
|
||||
void operation(gpc_op_e v) { m_operation = v; }
|
||||
|
||||
// Vertex Source Interface
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_gpc(const conv_gpc<VSA, VSB>&);
|
||||
const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void free_polygon(gpc_polygon& p);
|
||||
void free_result();
|
||||
void free_gpc_data();
|
||||
void start_contour();
|
||||
void add_vertex(double x, double y);
|
||||
void end_contour(unsigned orientation);
|
||||
void make_polygon(gpc_polygon& p);
|
||||
void start_extracting();
|
||||
bool next_contour();
|
||||
bool next_vertex(double* x, double* y);
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class VS> void add(VS& src, gpc_polygon& p)
|
||||
{
|
||||
unsigned cmd;
|
||||
double x, y;
|
||||
double start_x = 0.0;
|
||||
double start_y = 0.0;
|
||||
bool line_to = false;
|
||||
unsigned orientation = 0;
|
||||
|
||||
m_contour_accumulator.remove_all();
|
||||
|
||||
while(!is_stop(cmd = src.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
if(line_to)
|
||||
{
|
||||
end_contour(orientation);
|
||||
orientation = 0;
|
||||
}
|
||||
start_contour();
|
||||
start_x = x;
|
||||
start_y = y;
|
||||
}
|
||||
add_vertex(x, y);
|
||||
line_to = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
orientation = get_orientation(cmd);
|
||||
if(line_to && is_closed(cmd))
|
||||
{
|
||||
add_vertex(start_x, start_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(line_to)
|
||||
{
|
||||
end_contour(orientation);
|
||||
}
|
||||
make_polygon(p);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
source_a_type* m_src_a;
|
||||
source_b_type* m_src_b;
|
||||
status m_status;
|
||||
int m_vertex;
|
||||
int m_contour;
|
||||
gpc_op_e m_operation;
|
||||
vertex_array_type m_vertex_accumulator;
|
||||
contour_header_array_type m_contour_accumulator;
|
||||
gpc_polygon m_poly_a;
|
||||
gpc_polygon m_poly_b;
|
||||
gpc_polygon m_result;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < p.num_contours; i++)
|
||||
{
|
||||
delete [] p.contour[i].vertex;
|
||||
}
|
||||
delete [] p.hole;
|
||||
delete [] p.contour;
|
||||
memset(&p, 0, sizeof(gpc_polygon));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::free_result()
|
||||
{
|
||||
if(m_result.contour)
|
||||
{
|
||||
gpc_free_polygon(&m_result);
|
||||
}
|
||||
memset(&m_result, 0, sizeof(m_result));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::free_gpc_data()
|
||||
{
|
||||
free_polygon(m_poly_a);
|
||||
free_polygon(m_poly_b);
|
||||
free_result();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::start_contour()
|
||||
{
|
||||
contour_header_type h;
|
||||
memset(&h, 0, sizeof(h));
|
||||
m_contour_accumulator.add(h);
|
||||
m_vertex_accumulator.remove_all();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)
|
||||
{
|
||||
gpc_vertex v;
|
||||
v.x = x;
|
||||
v.y = y;
|
||||
m_vertex_accumulator.add(v);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::end_contour(unsigned orientation)
|
||||
{
|
||||
if(m_contour_accumulator.size())
|
||||
{
|
||||
if(m_vertex_accumulator.size() > 2)
|
||||
{
|
||||
contour_header_type& h =
|
||||
m_contour_accumulator[m_contour_accumulator.size() - 1];
|
||||
|
||||
h.num_vertices = m_vertex_accumulator.size();
|
||||
h.hole_flag = 0;
|
||||
|
||||
// TO DO: Clarify the "holes"
|
||||
//if(is_cw(orientation)) h.hole_flag = 1;
|
||||
|
||||
h.vertices = new gpc_vertex [h.num_vertices];
|
||||
gpc_vertex* d = h.vertices;
|
||||
int i;
|
||||
for(i = 0; i < h.num_vertices; i++)
|
||||
{
|
||||
const gpc_vertex& s = m_vertex_accumulator[i];
|
||||
d->x = s.x;
|
||||
d->y = s.y;
|
||||
++d;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vertex_accumulator.remove_last();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
|
||||
{
|
||||
free_polygon(p);
|
||||
if(m_contour_accumulator.size())
|
||||
{
|
||||
p.num_contours = m_contour_accumulator.size();
|
||||
|
||||
// TO DO: Clarify the "holes"
|
||||
//p.hole = new int[p.num_contours];
|
||||
p.hole = 0;
|
||||
|
||||
p.contour = new gpc_vertex_list[p.num_contours];
|
||||
|
||||
int i;
|
||||
//int* ph = p.hole;
|
||||
gpc_vertex_list* pv = p.contour;
|
||||
for(i = 0; i < p.num_contours; i++)
|
||||
{
|
||||
const contour_header_type& h = m_contour_accumulator[i];
|
||||
// *ph++ = h.hole_flag;
|
||||
pv->num_vertices = h.num_vertices;
|
||||
pv->vertex = h.vertices;
|
||||
++pv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::start_extracting()
|
||||
{
|
||||
m_status = status_move_to;
|
||||
m_contour = -1;
|
||||
m_vertex = -1;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
bool conv_gpc<VSA, VSB>::next_contour()
|
||||
{
|
||||
if(++m_contour < m_result.num_contours)
|
||||
{
|
||||
m_vertex = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)
|
||||
{
|
||||
const gpc_vertex_list& vlist = m_result.contour[m_contour];
|
||||
if(++m_vertex < vlist.num_vertices)
|
||||
{
|
||||
const gpc_vertex& v = vlist.vertex[m_vertex];
|
||||
*x = v.x;
|
||||
*y = v.y;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::rewind(unsigned path_id)
|
||||
{
|
||||
free_result();
|
||||
m_src_a->rewind(path_id);
|
||||
m_src_b->rewind(path_id);
|
||||
add(*m_src_a, m_poly_a);
|
||||
add(*m_src_b, m_poly_b);
|
||||
switch(m_operation)
|
||||
{
|
||||
case gpc_or:
|
||||
gpc_polygon_clip(GPC_UNION,
|
||||
&m_poly_a,
|
||||
&m_poly_b,
|
||||
&m_result);
|
||||
break;
|
||||
|
||||
case gpc_and:
|
||||
gpc_polygon_clip(GPC_INT,
|
||||
&m_poly_a,
|
||||
&m_poly_b,
|
||||
&m_result);
|
||||
break;
|
||||
|
||||
case gpc_xor:
|
||||
gpc_polygon_clip(GPC_XOR,
|
||||
&m_poly_a,
|
||||
&m_poly_b,
|
||||
&m_result);
|
||||
break;
|
||||
|
||||
case gpc_a_minus_b:
|
||||
gpc_polygon_clip(GPC_DIFF,
|
||||
&m_poly_a,
|
||||
&m_poly_b,
|
||||
&m_result);
|
||||
break;
|
||||
|
||||
case gpc_b_minus_a:
|
||||
gpc_polygon_clip(GPC_DIFF,
|
||||
&m_poly_b,
|
||||
&m_poly_a,
|
||||
&m_result);
|
||||
break;
|
||||
}
|
||||
start_extracting();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)
|
||||
{
|
||||
if(m_status == status_move_to)
|
||||
{
|
||||
if(next_contour())
|
||||
{
|
||||
if(next_vertex(x, y))
|
||||
{
|
||||
m_status = status_line_to;
|
||||
return path_cmd_move_to;
|
||||
}
|
||||
m_status = status_stop;
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(next_vertex(x, y))
|
||||
{
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_status = status_move_to;
|
||||
}
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
148
agg/include/agg_conv_marker.h
Normal file
148
agg/include/agg_conv_marker.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// conv_marker
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_MARKER_INCLUDED
|
||||
#define AGG_CONV_MARKER_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_trans_affine.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-------------------------------------------------------------conv_marker
|
||||
template<class MarkerLocator, class MarkerShapes>
|
||||
class conv_marker
|
||||
{
|
||||
public:
|
||||
conv_marker(MarkerLocator& ml, MarkerShapes& ms);
|
||||
|
||||
trans_affine& transform() { return m_transform; }
|
||||
const trans_affine& transform() const { return m_transform; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&);
|
||||
const conv_marker<MarkerLocator, MarkerShapes>&
|
||||
operator = (const conv_marker<MarkerLocator, MarkerShapes>&);
|
||||
|
||||
enum status_e
|
||||
{
|
||||
initial,
|
||||
markers,
|
||||
polygon,
|
||||
stop
|
||||
};
|
||||
|
||||
MarkerLocator* m_marker_locator;
|
||||
MarkerShapes* m_marker_shapes;
|
||||
trans_affine m_transform;
|
||||
trans_affine m_mtx;
|
||||
status_e m_status;
|
||||
unsigned m_marker;
|
||||
unsigned m_num_markers;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class MarkerLocator, class MarkerShapes>
|
||||
conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) :
|
||||
m_marker_locator(&ml),
|
||||
m_marker_shapes(&ms),
|
||||
m_status(initial),
|
||||
m_marker(0),
|
||||
m_num_markers(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class MarkerLocator, class MarkerShapes>
|
||||
void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned)
|
||||
{
|
||||
m_status = initial;
|
||||
m_marker = 0;
|
||||
m_num_markers = 1;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class MarkerLocator, class MarkerShapes>
|
||||
unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_move_to;
|
||||
double x1, y1, x2, y2;
|
||||
|
||||
while(!is_stop(cmd))
|
||||
{
|
||||
switch(m_status)
|
||||
{
|
||||
case initial:
|
||||
if(m_num_markers == 0)
|
||||
{
|
||||
cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
m_marker_locator->rewind(m_marker);
|
||||
++m_marker;
|
||||
m_num_markers = 0;
|
||||
m_status = markers;
|
||||
|
||||
case markers:
|
||||
if(is_stop(m_marker_locator->vertex(&x1, &y1)))
|
||||
{
|
||||
m_status = initial;
|
||||
break;
|
||||
}
|
||||
if(is_stop(m_marker_locator->vertex(&x2, &y2)))
|
||||
{
|
||||
m_status = initial;
|
||||
break;
|
||||
}
|
||||
++m_num_markers;
|
||||
m_mtx = m_transform;
|
||||
m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1));
|
||||
m_mtx *= trans_affine_translation(x1, y1);
|
||||
m_marker_shapes->rewind(m_marker - 1);
|
||||
m_status = polygon;
|
||||
|
||||
case polygon:
|
||||
cmd = m_marker_shapes->vertex(x, y);
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
cmd = path_cmd_move_to;
|
||||
m_status = markers;
|
||||
break;
|
||||
}
|
||||
m_mtx.transform(x, y);
|
||||
return cmd;
|
||||
|
||||
case stop:
|
||||
cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
51
agg/include/agg_conv_marker_adaptor.h
Normal file
51
agg/include/agg_conv_marker_adaptor.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_MARKER_ADAPTOR_INCLUDED
|
||||
#define AGG_CONV_MARKER_ADAPTOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
#include "agg_vcgen_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=====================================================conv_marker_adaptor
|
||||
template<class VertexSource, class Markers=null_markers>
|
||||
struct conv_marker_adaptor :
|
||||
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>
|
||||
{
|
||||
typedef Markers marker_type;
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> base_type;
|
||||
|
||||
conv_marker_adaptor(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void shorten(double s) { base_type::generator().shorten(s); }
|
||||
double shorten() const { return base_type::generator().shorten(); }
|
||||
|
||||
private:
|
||||
conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&);
|
||||
const conv_marker_adaptor<VertexSource, Markers>&
|
||||
operator = (const conv_marker_adaptor<VertexSource, Markers>&);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
48
agg/include/agg_conv_segmentator.h
Normal file
48
agg/include/agg_conv_segmentator.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_SEGMENTATOR_INCLUDED
|
||||
#define AGG_CONV_SEGMENTATOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vpgen.h"
|
||||
#include "agg_vpgen_segmentator.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//========================================================conv_segmentator
|
||||
template<class VertexSource>
|
||||
struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator>
|
||||
{
|
||||
typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type;
|
||||
|
||||
conv_segmentator(VertexSource& vs) :
|
||||
conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {}
|
||||
|
||||
void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); }
|
||||
double approximation_scale() const { return base_type::vpgen().approximation_scale(); }
|
||||
|
||||
private:
|
||||
conv_segmentator(const conv_segmentator<VertexSource>&);
|
||||
const conv_segmentator<VertexSource>&
|
||||
operator = (const conv_segmentator<VertexSource>&);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
50
agg/include/agg_conv_shorten_path.h
Normal file
50
agg/include/agg_conv_shorten_path.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_SHORTEN_PATH_INCLUDED
|
||||
#define AGG_CONV_SHORTEN_PATH_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
#include "agg_vcgen_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================conv_shorten_path
|
||||
template<class VertexSource> class conv_shorten_path :
|
||||
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>
|
||||
{
|
||||
public:
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type;
|
||||
|
||||
conv_shorten_path(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void shorten(double s) { base_type::generator().shorten(s); }
|
||||
double shorten() const { return base_type::generator().shorten(); }
|
||||
|
||||
private:
|
||||
conv_shorten_path(const conv_shorten_path<VertexSource>&);
|
||||
const conv_shorten_path<VertexSource>&
|
||||
operator = (const conv_shorten_path<VertexSource>&);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
80
agg/include/agg_conv_smooth_poly1.h
Normal file
80
agg/include/agg_conv_smooth_poly1.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Smooth polygon generator
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED
|
||||
#define AGG_CONV_SMOOTH_POLY1_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_smooth_poly1.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
#include "agg_conv_curve.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-------------------------------------------------------conv_smooth_poly1
|
||||
template<class VertexSource>
|
||||
struct conv_smooth_poly1 :
|
||||
public conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>
|
||||
{
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> base_type;
|
||||
|
||||
conv_smooth_poly1(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void smooth_value(double v) { base_type::generator().smooth_value(v); }
|
||||
double smooth_value() const { return base_type::generator().smooth_value(); }
|
||||
|
||||
private:
|
||||
conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&);
|
||||
const conv_smooth_poly1<VertexSource>&
|
||||
operator = (const conv_smooth_poly1<VertexSource>&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------conv_smooth_poly1_curve
|
||||
template<class VertexSource>
|
||||
struct conv_smooth_poly1_curve :
|
||||
public conv_curve<conv_smooth_poly1<VertexSource> >
|
||||
{
|
||||
conv_smooth_poly1_curve(VertexSource& vs) :
|
||||
conv_curve<conv_smooth_poly1<VertexSource> >(m_smooth),
|
||||
m_smooth(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
|
||||
double smooth_value() const { return m_smooth.generator().smooth_value(); }
|
||||
|
||||
private:
|
||||
conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&);
|
||||
const conv_smooth_poly1_curve<VertexSource>&
|
||||
operator = (const conv_smooth_poly1_curve<VertexSource>&);
|
||||
|
||||
conv_smooth_poly1<VertexSource> m_smooth;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
73
agg/include/agg_conv_stroke.h
Normal file
73
agg/include/agg_conv_stroke.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// conv_stroke
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_STROKE_INCLUDED
|
||||
#define AGG_CONV_STROKE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_stroke.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-------------------------------------------------------------conv_stroke
|
||||
template<class VertexSource, class Markers=null_markers>
|
||||
struct conv_stroke :
|
||||
public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>
|
||||
{
|
||||
typedef Markers marker_type;
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type;
|
||||
|
||||
conv_stroke(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); }
|
||||
void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
|
||||
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
|
||||
|
||||
line_cap_e line_cap() const { return base_type::generator().line_cap(); }
|
||||
line_join_e line_join() const { return base_type::generator().line_join(); }
|
||||
inner_join_e inner_join() const { return base_type::generator().inner_join(); }
|
||||
|
||||
void width(double w) { base_type::generator().width(w); }
|
||||
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
|
||||
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
|
||||
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
|
||||
|
||||
double width() const { return base_type::generator().width(); }
|
||||
double miter_limit() const { return base_type::generator().miter_limit(); }
|
||||
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
|
||||
double approximation_scale() const { return base_type::generator().approximation_scale(); }
|
||||
|
||||
void shorten(double s) { base_type::generator().shorten(s); }
|
||||
double shorten() const { return base_type::generator().shorten(); }
|
||||
|
||||
private:
|
||||
conv_stroke(const conv_stroke<VertexSource, Markers>&);
|
||||
const conv_stroke<VertexSource, Markers>&
|
||||
operator = (const conv_stroke<VertexSource, Markers>&);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
69
agg/include/agg_conv_transform.h
Normal file
69
agg/include/agg_conv_transform.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 conv_transform
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_TRANSFORM_INCLUDED
|
||||
#define AGG_CONV_TRANSFORM_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_trans_affine.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------------------conv_transform
|
||||
template<class VertexSource, class Transformer=trans_affine> class conv_transform
|
||||
{
|
||||
public:
|
||||
conv_transform(VertexSource& source, const Transformer& tr) :
|
||||
m_source(&source), m_trans(&tr) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = m_source->vertex(x, y);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_trans->transform(x, y);
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void transformer(const Transformer& tr)
|
||||
{
|
||||
m_trans = &tr;
|
||||
}
|
||||
|
||||
private:
|
||||
conv_transform(const conv_transform<VertexSource>&);
|
||||
const conv_transform<VertexSource>&
|
||||
operator = (const conv_transform<VertexSource>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
const Transformer* m_trans;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
53
agg/include/agg_conv_unclose_polygon.h
Normal file
53
agg/include/agg_conv_unclose_polygon.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_UNCLOSE_POLYGON_INCLUDED
|
||||
#define AGG_CONV_UNCLOSE_POLYGON_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//====================================================conv_unclose_polygon
|
||||
template<class VertexSource> class conv_unclose_polygon
|
||||
{
|
||||
public:
|
||||
conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = m_source->vertex(x, y);
|
||||
if(is_end_poly(cmd)) cmd &= ~path_flags_close;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
private:
|
||||
conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
|
||||
const conv_unclose_polygon<VertexSource>&
|
||||
operator = (const conv_unclose_polygon<VertexSource>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
695
agg/include/agg_curves.h
Normal file
695
agg/include/agg_curves.h
Normal file
|
@ -0,0 +1,695 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
// Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CURVES_INCLUDED
|
||||
#define AGG_CURVES_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
// See Implementation agg_curves.cpp
|
||||
|
||||
//--------------------------------------------curve_approximation_method_e
|
||||
enum curve_approximation_method_e
|
||||
{
|
||||
curve_inc,
|
||||
curve_div
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------curve3_inc
|
||||
class curve3_inc
|
||||
{
|
||||
public:
|
||||
curve3_inc() :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0) { }
|
||||
|
||||
curve3_inc(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void reset() { m_num_steps = 0; m_step = -1; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
curve_approximation_method_e approximation_method() const { return curve_inc; }
|
||||
|
||||
void approximation_scale(double s);
|
||||
double approximation_scale() const;
|
||||
|
||||
void angle_tolerance(double) {}
|
||||
double angle_tolerance() const { return 0.0; }
|
||||
|
||||
void cusp_limit(double) {}
|
||||
double cusp_limit() const { return 0.0; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
int m_num_steps;
|
||||
int m_step;
|
||||
double m_scale;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
double m_end_x;
|
||||
double m_end_y;
|
||||
double m_fx;
|
||||
double m_fy;
|
||||
double m_dfx;
|
||||
double m_dfy;
|
||||
double m_ddfx;
|
||||
double m_ddfy;
|
||||
double m_saved_fx;
|
||||
double m_saved_fy;
|
||||
double m_saved_dfx;
|
||||
double m_saved_dfy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve3_div
|
||||
class curve3_div
|
||||
{
|
||||
public:
|
||||
curve3_div() :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_count(0)
|
||||
{}
|
||||
|
||||
curve3_div(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_count(0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void reset() { m_points.remove_all(); m_count = 0; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
curve_approximation_method_e approximation_method() const { return curve_div; }
|
||||
|
||||
void approximation_scale(double s) { m_approximation_scale = s; }
|
||||
double approximation_scale() const { return m_approximation_scale; }
|
||||
|
||||
void angle_tolerance(double a) { m_angle_tolerance = a; }
|
||||
double angle_tolerance() const { return m_angle_tolerance; }
|
||||
|
||||
void cusp_limit(double) {}
|
||||
double cusp_limit() const { return 0.0; }
|
||||
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_count >= m_points.size()) return path_cmd_stop;
|
||||
const point_d& p = m_points[m_count++];
|
||||
*x = p.x;
|
||||
*y = p.y;
|
||||
return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
|
||||
}
|
||||
|
||||
private:
|
||||
void bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
void recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
unsigned level);
|
||||
|
||||
double m_approximation_scale;
|
||||
double m_distance_tolerance_square;
|
||||
double m_distance_tolerance_manhattan;
|
||||
double m_angle_tolerance;
|
||||
unsigned m_count;
|
||||
pod_bvector<point_d> m_points;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve4_points
|
||||
struct curve4_points
|
||||
{
|
||||
double cp[8];
|
||||
curve4_points() {}
|
||||
curve4_points(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
|
||||
cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
|
||||
}
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
|
||||
cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
|
||||
}
|
||||
double operator [] (unsigned i) const { return cp[i]; }
|
||||
double& operator [] (unsigned i) { return cp[i]; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve4_inc
|
||||
class curve4_inc
|
||||
{
|
||||
public:
|
||||
curve4_inc() :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0) { }
|
||||
|
||||
curve4_inc(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4) :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
curve4_inc(const curve4_points& cp) :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void reset() { m_num_steps = 0; m_step = -1; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
|
||||
void init(const curve4_points& cp)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
curve_approximation_method_e approximation_method() const { return curve_inc; }
|
||||
|
||||
void approximation_scale(double s);
|
||||
double approximation_scale() const;
|
||||
|
||||
void angle_tolerance(double) {}
|
||||
double angle_tolerance() const { return 0.0; }
|
||||
|
||||
void cusp_limit(double) {}
|
||||
double cusp_limit() const { return 0.0; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
int m_num_steps;
|
||||
int m_step;
|
||||
double m_scale;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
double m_end_x;
|
||||
double m_end_y;
|
||||
double m_fx;
|
||||
double m_fy;
|
||||
double m_dfx;
|
||||
double m_dfy;
|
||||
double m_ddfx;
|
||||
double m_ddfy;
|
||||
double m_dddfx;
|
||||
double m_dddfy;
|
||||
double m_saved_fx;
|
||||
double m_saved_fy;
|
||||
double m_saved_dfx;
|
||||
double m_saved_dfy;
|
||||
double m_saved_ddfx;
|
||||
double m_saved_ddfy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------catrom_to_bezier
|
||||
inline curve4_points catrom_to_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
// Trans. matrix Catmull-Rom to Bezier
|
||||
//
|
||||
// 0 1 0 0
|
||||
// -1/6 1 1/6 0
|
||||
// 0 1/6 1 -1/6
|
||||
// 0 0 1 0
|
||||
//
|
||||
return curve4_points(
|
||||
x2,
|
||||
y2,
|
||||
(-x1 + 6*x2 + x3) / 6,
|
||||
(-y1 + 6*y2 + y3) / 6,
|
||||
( x2 + 6*x3 - x4) / 6,
|
||||
( y2 + 6*y3 - y4) / 6,
|
||||
x3,
|
||||
y3);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
inline curve4_points
|
||||
catrom_to_bezier(const curve4_points& cp)
|
||||
{
|
||||
return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3],
|
||||
cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------ubspline_to_bezier
|
||||
inline curve4_points ubspline_to_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
// Trans. matrix Uniform BSpline to Bezier
|
||||
//
|
||||
// 1/6 4/6 1/6 0
|
||||
// 0 4/6 2/6 0
|
||||
// 0 2/6 4/6 0
|
||||
// 0 1/6 4/6 1/6
|
||||
//
|
||||
return curve4_points(
|
||||
(x1 + 4*x2 + x3) / 6,
|
||||
(y1 + 4*y2 + y3) / 6,
|
||||
(4*x2 + 2*x3) / 6,
|
||||
(4*y2 + 2*y3) / 6,
|
||||
(2*x2 + 4*x3) / 6,
|
||||
(2*y2 + 4*y3) / 6,
|
||||
(x2 + 4*x3 + x4) / 6,
|
||||
(y2 + 4*y3 + y4) / 6);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
inline curve4_points
|
||||
ubspline_to_bezier(const curve4_points& cp)
|
||||
{
|
||||
return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3],
|
||||
cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------hermite_to_bezier
|
||||
inline curve4_points hermite_to_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
// Trans. matrix Hermite to Bezier
|
||||
//
|
||||
// 1 0 0 0
|
||||
// 1 0 1/3 0
|
||||
// 0 1 0 -1/3
|
||||
// 0 1 0 0
|
||||
//
|
||||
return curve4_points(
|
||||
x1,
|
||||
y1,
|
||||
(3*x1 + x3) / 3,
|
||||
(3*y1 + y3) / 3,
|
||||
(3*x2 - x4) / 3,
|
||||
(3*y2 - y4) / 3,
|
||||
x2,
|
||||
y2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
inline curve4_points
|
||||
hermite_to_bezier(const curve4_points& cp)
|
||||
{
|
||||
return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3],
|
||||
cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve4_div
|
||||
class curve4_div
|
||||
{
|
||||
public:
|
||||
curve4_div() :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_cusp_limit(0.0),
|
||||
m_count(0)
|
||||
{}
|
||||
|
||||
curve4_div(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4) :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_cusp_limit(0.0),
|
||||
m_count(0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
curve4_div(const curve4_points& cp) :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_count(0)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void reset() { m_points.remove_all(); m_count = 0; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
|
||||
void init(const curve4_points& cp)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return curve_div;
|
||||
}
|
||||
|
||||
void approximation_scale(double s) { m_approximation_scale = s; }
|
||||
double approximation_scale() const { return m_approximation_scale; }
|
||||
|
||||
void angle_tolerance(double a) { m_angle_tolerance = a; }
|
||||
double angle_tolerance() const { return m_angle_tolerance; }
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_cusp_limit = (v == 0.0) ? 0.0 : pi - v;
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit;
|
||||
}
|
||||
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_count >= m_points.size()) return path_cmd_stop;
|
||||
const point_d& p = m_points[m_count++];
|
||||
*x = p.x;
|
||||
*y = p.y;
|
||||
return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
|
||||
}
|
||||
|
||||
private:
|
||||
void bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
|
||||
void recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4,
|
||||
unsigned level);
|
||||
|
||||
double m_approximation_scale;
|
||||
double m_distance_tolerance_square;
|
||||
double m_distance_tolerance_manhattan;
|
||||
double m_angle_tolerance;
|
||||
double m_cusp_limit;
|
||||
unsigned m_count;
|
||||
pod_bvector<point_d> m_points;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------curve3
|
||||
class curve3
|
||||
{
|
||||
public:
|
||||
curve3() : m_approximation_method(curve_div) {}
|
||||
curve3(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) :
|
||||
m_approximation_method(curve_div)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_curve_inc.reset();
|
||||
m_curve_div.reset();
|
||||
}
|
||||
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
m_approximation_method = v;
|
||||
}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return m_approximation_method;
|
||||
}
|
||||
|
||||
void approximation_scale(double s)
|
||||
{
|
||||
m_curve_inc.approximation_scale(s);
|
||||
m_curve_div.approximation_scale(s);
|
||||
}
|
||||
|
||||
double approximation_scale() const
|
||||
{
|
||||
return m_curve_inc.approximation_scale();
|
||||
}
|
||||
|
||||
void angle_tolerance(double a)
|
||||
{
|
||||
m_curve_div.angle_tolerance(a);
|
||||
}
|
||||
|
||||
double angle_tolerance() const
|
||||
{
|
||||
return m_curve_div.angle_tolerance();
|
||||
}
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_curve_div.cusp_limit(v);
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return m_curve_div.cusp_limit();
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.rewind(path_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.rewind(path_id);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
return m_curve_inc.vertex(x, y);
|
||||
}
|
||||
return m_curve_div.vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
curve3_inc m_curve_inc;
|
||||
curve3_div m_curve_div;
|
||||
curve_approximation_method_e m_approximation_method;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------curve4
|
||||
class curve4
|
||||
{
|
||||
public:
|
||||
curve4() : m_approximation_method(curve_div) {}
|
||||
curve4(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4) :
|
||||
m_approximation_method(curve_div)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
curve4(const curve4_points& cp) :
|
||||
m_approximation_method(curve_div)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_curve_inc.reset();
|
||||
m_curve_div.reset();
|
||||
}
|
||||
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
}
|
||||
|
||||
void init(const curve4_points& cp)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
m_approximation_method = v;
|
||||
}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return m_approximation_method;
|
||||
}
|
||||
|
||||
void approximation_scale(double s)
|
||||
{
|
||||
m_curve_inc.approximation_scale(s);
|
||||
m_curve_div.approximation_scale(s);
|
||||
}
|
||||
double approximation_scale() const { return m_curve_inc.approximation_scale(); }
|
||||
|
||||
void angle_tolerance(double v)
|
||||
{
|
||||
m_curve_div.angle_tolerance(v);
|
||||
}
|
||||
|
||||
double angle_tolerance() const
|
||||
{
|
||||
return m_curve_div.angle_tolerance();
|
||||
}
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_curve_div.cusp_limit(v);
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return m_curve_div.cusp_limit();
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.rewind(path_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.rewind(path_id);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
return m_curve_inc.vertex(x, y);
|
||||
}
|
||||
return m_curve_div.vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
curve4_inc m_curve_inc;
|
||||
curve4_div m_curve_div;
|
||||
curve_approximation_method_e m_approximation_method;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
290
agg/include/agg_dda_line.h
Normal file
290
agg/include/agg_dda_line.h
Normal file
|
@ -0,0 +1,290 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 <stdlib.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===================================================dda_line_interpolator
|
||||
template<int FractionShift, int YShift=0> class dda_line_interpolator
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
dda_line_interpolator() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
dda_line_interpolator(int y1, int y2, unsigned count) :
|
||||
m_y(y1),
|
||||
m_inc(((y2 - y1) << FractionShift) / 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(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)),
|
||||
m_len(m_ver ? abs(m_y2_lr - m_y1_lr) :
|
||||
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
|
123
agg/include/agg_ellipse.h
Normal file
123
agg/include/agg_ellipse.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 ellipse
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ELLIPSE_INCLUDED
|
||||
#define AGG_ELLIPSE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------ellipse
|
||||
class ellipse
|
||||
{
|
||||
public:
|
||||
ellipse() :
|
||||
m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0),
|
||||
m_num(4), m_step(0), m_cw(false) {}
|
||||
|
||||
ellipse(double x, double y, double rx, double ry,
|
||||
unsigned num_steps=0, bool cw=false) :
|
||||
m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0),
|
||||
m_num(num_steps), m_step(0), m_cw(cw)
|
||||
{
|
||||
if(m_num == 0) calc_num_steps();
|
||||
}
|
||||
|
||||
void init(double x, double y, double rx, double ry,
|
||||
unsigned num_steps=0, bool cw=false);
|
||||
|
||||
void approximation_scale(double scale);
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
void calc_num_steps();
|
||||
|
||||
double m_x;
|
||||
double m_y;
|
||||
double m_rx;
|
||||
double m_ry;
|
||||
double m_scale;
|
||||
unsigned m_num;
|
||||
unsigned m_step;
|
||||
bool m_cw;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void ellipse::init(double x, double y, double rx, double ry,
|
||||
unsigned num_steps, bool cw)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_rx = rx;
|
||||
m_ry = ry;
|
||||
m_num = num_steps;
|
||||
m_step = 0;
|
||||
m_cw = cw;
|
||||
if(m_num == 0) calc_num_steps();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void ellipse::approximation_scale(double scale)
|
||||
{
|
||||
m_scale = scale;
|
||||
calc_num_steps();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void ellipse::calc_num_steps()
|
||||
{
|
||||
double ra = (fabs(m_rx) + fabs(m_ry)) / 2;
|
||||
double da = acos(ra / (ra + 0.125 / m_scale)) * 2;
|
||||
m_num = uround(2*pi / da);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void ellipse::rewind(unsigned)
|
||||
{
|
||||
m_step = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline unsigned ellipse::vertex(double* x, double* y)
|
||||
{
|
||||
if(m_step == m_num)
|
||||
{
|
||||
++m_step;
|
||||
return path_cmd_end_poly | path_flags_close | path_flags_ccw;
|
||||
}
|
||||
if(m_step > m_num) return path_cmd_stop;
|
||||
double angle = double(m_step) / double(m_num) * 2.0 * pi;
|
||||
if(m_cw) angle = 2.0 * pi - angle;
|
||||
*x = m_x + cos(angle) * m_rx;
|
||||
*y = m_y + sin(angle) * m_ry;
|
||||
m_step++;
|
||||
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
113
agg/include/agg_ellipse_bresenham.h
Normal file
113
agg/include/agg_ellipse_bresenham.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Simple Bresenham interpolator for ellipsees
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED
|
||||
#define AGG_ELLIPSE_BRESENHAM_INCLUDED
|
||||
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------ellipse_bresenham_interpolator
|
||||
class ellipse_bresenham_interpolator
|
||||
{
|
||||
public:
|
||||
ellipse_bresenham_interpolator(int rx, int ry) :
|
||||
m_rx2(rx * rx),
|
||||
m_ry2(ry * ry),
|
||||
m_two_rx2(m_rx2 << 1),
|
||||
m_two_ry2(m_ry2 << 1),
|
||||
m_dx(0),
|
||||
m_dy(0),
|
||||
m_inc_x(0),
|
||||
m_inc_y(-ry * m_two_rx2),
|
||||
m_cur_f(0)
|
||||
{}
|
||||
|
||||
int dx() const { return m_dx; }
|
||||
int dy() const { return m_dy; }
|
||||
|
||||
void operator++ ()
|
||||
{
|
||||
int mx, my, mxy, min_m;
|
||||
int fx, fy, fxy;
|
||||
|
||||
mx = fx = m_cur_f + m_inc_x + m_ry2;
|
||||
if(mx < 0) mx = -mx;
|
||||
|
||||
my = fy = m_cur_f + m_inc_y + m_rx2;
|
||||
if(my < 0) my = -my;
|
||||
|
||||
mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2;
|
||||
if(mxy < 0) mxy = -mxy;
|
||||
|
||||
min_m = mx;
|
||||
bool flag = true;
|
||||
|
||||
if(min_m > my)
|
||||
{
|
||||
min_m = my;
|
||||
flag = false;
|
||||
}
|
||||
|
||||
m_dx = m_dy = 0;
|
||||
|
||||
if(min_m > mxy)
|
||||
{
|
||||
m_inc_x += m_two_ry2;
|
||||
m_inc_y += m_two_rx2;
|
||||
m_cur_f = fxy;
|
||||
m_dx = 1;
|
||||
m_dy = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(flag)
|
||||
{
|
||||
m_inc_x += m_two_ry2;
|
||||
m_cur_f = fx;
|
||||
m_dx = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
m_inc_y += m_two_rx2;
|
||||
m_cur_f = fy;
|
||||
m_dy = 1;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_rx2;
|
||||
int m_ry2;
|
||||
int m_two_rx2;
|
||||
int m_two_ry2;
|
||||
int m_dx;
|
||||
int m_dy;
|
||||
int m_inc_x;
|
||||
int m_inc_y;
|
||||
int m_cur_f;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
59
agg/include/agg_embedded_raster_fonts.h
Normal file
59
agg/include/agg_embedded_raster_fonts.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_EMBEDDED_RASTER_FONTS_INCLUDED
|
||||
#define AGG_EMBEDDED_RASTER_FONTS_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
extern const int8u gse4x6[];
|
||||
extern const int8u gse4x8[];
|
||||
extern const int8u gse5x7[];
|
||||
extern const int8u gse5x9[];
|
||||
extern const int8u gse6x12[];
|
||||
extern const int8u gse6x9[];
|
||||
extern const int8u gse7x11[];
|
||||
extern const int8u gse7x11_bold[];
|
||||
extern const int8u gse7x15[];
|
||||
extern const int8u gse7x15_bold[];
|
||||
extern const int8u gse8x16[];
|
||||
extern const int8u gse8x16_bold[];
|
||||
extern const int8u mcs11_prop[];
|
||||
extern const int8u mcs11_prop_condensed[];
|
||||
extern const int8u mcs12_prop[];
|
||||
extern const int8u mcs13_prop[];
|
||||
extern const int8u mcs5x10_mono[];
|
||||
extern const int8u mcs5x11_mono[];
|
||||
extern const int8u mcs6x10_mono[];
|
||||
extern const int8u mcs6x11_mono[];
|
||||
extern const int8u mcs7x12_mono_high[];
|
||||
extern const int8u mcs7x12_mono_low[];
|
||||
extern const int8u verdana12[];
|
||||
extern const int8u verdana12_bold[];
|
||||
extern const int8u verdana13[];
|
||||
extern const int8u verdana13_bold[];
|
||||
extern const int8u verdana14[];
|
||||
extern const int8u verdana14_bold[];
|
||||
extern const int8u verdana16[];
|
||||
extern const int8u verdana16_bold[];
|
||||
extern const int8u verdana17[];
|
||||
extern const int8u verdana17_bold[];
|
||||
extern const int8u verdana18[];
|
||||
extern const int8u verdana18_bold[];
|
||||
}
|
||||
|
||||
#endif
|
397
agg/include/agg_font_cache_manager.h
Normal file
397
agg/include/agg_font_cache_manager.h
Normal file
|
@ -0,0 +1,397 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_FONT_CACHE_MANAGER_INCLUDED
|
||||
#define AGG_FONT_CACHE_MANAGER_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//---------------------------------------------------------glyph_data_type
|
||||
enum glyph_data_type
|
||||
{
|
||||
glyph_data_invalid = 0,
|
||||
glyph_data_mono = 1,
|
||||
glyph_data_gray8 = 2,
|
||||
glyph_data_outline = 3
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------glyph_cache
|
||||
struct glyph_cache
|
||||
{
|
||||
unsigned glyph_index;
|
||||
int8u* data;
|
||||
unsigned data_size;
|
||||
glyph_data_type data_type;
|
||||
rect_i bounds;
|
||||
double advance_x;
|
||||
double advance_y;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------font_cache
|
||||
class font_cache
|
||||
{
|
||||
public:
|
||||
enum block_size_e { block_size = 16384-16 };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
font_cache(const char* font_signature) :
|
||||
m_allocator(block_size),
|
||||
m_font_signature(0)
|
||||
{
|
||||
m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
|
||||
strcpy(m_font_signature, font_signature);
|
||||
memset(m_glyphs, 0, sizeof(m_glyphs));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool font_is(const char* font_signature) const
|
||||
{
|
||||
return strcmp(font_signature, m_font_signature) == 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const glyph_cache* find_glyph(unsigned glyph_code) const
|
||||
{
|
||||
unsigned msb = (glyph_code >> 8) & 0xFF;
|
||||
if(m_glyphs[msb])
|
||||
{
|
||||
return m_glyphs[msb][glyph_code & 0xFF];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
glyph_cache* cache_glyph(unsigned glyph_code,
|
||||
unsigned glyph_index,
|
||||
unsigned data_size,
|
||||
glyph_data_type data_type,
|
||||
const rect_i& bounds,
|
||||
double advance_x,
|
||||
double advance_y)
|
||||
{
|
||||
unsigned msb = (glyph_code >> 8) & 0xFF;
|
||||
if(m_glyphs[msb] == 0)
|
||||
{
|
||||
m_glyphs[msb] =
|
||||
(glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
|
||||
sizeof(glyph_cache*));
|
||||
memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
|
||||
}
|
||||
|
||||
unsigned lsb = glyph_code & 0xFF;
|
||||
if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
|
||||
|
||||
glyph_cache* glyph =
|
||||
(glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
|
||||
sizeof(double));
|
||||
|
||||
glyph->glyph_index = glyph_index;
|
||||
glyph->data = m_allocator.allocate(data_size);
|
||||
glyph->data_size = data_size;
|
||||
glyph->data_type = data_type;
|
||||
glyph->bounds = bounds;
|
||||
glyph->advance_x = advance_x;
|
||||
glyph->advance_y = advance_y;
|
||||
return m_glyphs[msb][lsb] = glyph;
|
||||
}
|
||||
|
||||
private:
|
||||
pod_allocator m_allocator;
|
||||
glyph_cache** m_glyphs[256];
|
||||
char* m_font_signature;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------font_cache_pool
|
||||
class font_cache_pool
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
~font_cache_pool()
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_num_fonts; ++i)
|
||||
{
|
||||
delete m_fonts[i];
|
||||
}
|
||||
delete [] m_fonts;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
font_cache_pool(unsigned max_fonts=32) :
|
||||
m_fonts(new font_cache* [max_fonts]),
|
||||
m_max_fonts(max_fonts),
|
||||
m_num_fonts(0),
|
||||
m_cur_font(0)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void font(const char* font_signature, bool reset_cache = false)
|
||||
{
|
||||
int idx = find_font(font_signature);
|
||||
if(idx >= 0)
|
||||
{
|
||||
if(reset_cache)
|
||||
{
|
||||
delete m_fonts[idx];
|
||||
m_fonts[idx] = new font_cache(font_signature);
|
||||
}
|
||||
m_cur_font = m_fonts[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_num_fonts >= m_max_fonts)
|
||||
{
|
||||
delete m_fonts[0];
|
||||
memcpy(m_fonts,
|
||||
m_fonts + 1,
|
||||
(m_max_fonts - 1) * sizeof(font_cache*));
|
||||
m_num_fonts = m_max_fonts - 1;
|
||||
}
|
||||
m_fonts[m_num_fonts] = new font_cache(font_signature);
|
||||
m_cur_font = m_fonts[m_num_fonts];
|
||||
++m_num_fonts;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const font_cache* font() const
|
||||
{
|
||||
return m_cur_font;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const glyph_cache* find_glyph(unsigned glyph_code) const
|
||||
{
|
||||
if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
glyph_cache* cache_glyph(unsigned glyph_code,
|
||||
unsigned glyph_index,
|
||||
unsigned data_size,
|
||||
glyph_data_type data_type,
|
||||
const rect_i& bounds,
|
||||
double advance_x,
|
||||
double advance_y)
|
||||
{
|
||||
if(m_cur_font)
|
||||
{
|
||||
return m_cur_font->cache_glyph(glyph_code,
|
||||
glyph_index,
|
||||
data_size,
|
||||
data_type,
|
||||
bounds,
|
||||
advance_x,
|
||||
advance_y);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int find_font(const char* font_signature)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_num_fonts; i++)
|
||||
{
|
||||
if(m_fonts[i]->font_is(font_signature)) return int(i);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private:
|
||||
font_cache** m_fonts;
|
||||
unsigned m_max_fonts;
|
||||
unsigned m_num_fonts;
|
||||
font_cache* m_cur_font;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum glyph_rendering
|
||||
{
|
||||
glyph_ren_native_mono,
|
||||
glyph_ren_native_gray8,
|
||||
glyph_ren_outline,
|
||||
glyph_ren_agg_mono,
|
||||
glyph_ren_agg_gray8
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------font_cache_manager
|
||||
template<class FontEngine> class font_cache_manager
|
||||
{
|
||||
public:
|
||||
typedef FontEngine font_engine_type;
|
||||
typedef font_cache_manager<FontEngine> self_type;
|
||||
typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
|
||||
typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
|
||||
typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
|
||||
typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
|
||||
typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
|
||||
m_fonts(max_fonts),
|
||||
m_engine(engine),
|
||||
m_change_stamp(-1),
|
||||
m_prev_glyph(0),
|
||||
m_last_glyph(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const glyph_cache* glyph(unsigned glyph_code)
|
||||
{
|
||||
synchronize();
|
||||
const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
|
||||
if(gl)
|
||||
{
|
||||
m_prev_glyph = m_last_glyph;
|
||||
return m_last_glyph = gl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_engine.prepare_glyph(glyph_code))
|
||||
{
|
||||
m_prev_glyph = m_last_glyph;
|
||||
m_last_glyph = m_fonts.cache_glyph(glyph_code,
|
||||
m_engine.glyph_index(),
|
||||
m_engine.data_size(),
|
||||
m_engine.data_type(),
|
||||
m_engine.bounds(),
|
||||
m_engine.advance_x(),
|
||||
m_engine.advance_y());
|
||||
m_engine.write_glyph_to(m_last_glyph->data);
|
||||
return m_last_glyph;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init_embedded_adaptors(const glyph_cache* gl,
|
||||
double x, double y,
|
||||
double scale=1.0)
|
||||
{
|
||||
if(gl)
|
||||
{
|
||||
switch(gl->data_type)
|
||||
{
|
||||
default: return;
|
||||
case glyph_data_mono:
|
||||
m_mono_adaptor.init(gl->data, gl->data_size, x, y);
|
||||
break;
|
||||
|
||||
case glyph_data_gray8:
|
||||
m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
|
||||
break;
|
||||
|
||||
case glyph_data_outline:
|
||||
m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
path_adaptor_type& path_adaptor() { return m_path_adaptor; }
|
||||
gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
|
||||
gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
|
||||
mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
|
||||
mono_scanline_type& mono_scanline() { return m_mono_scanline; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const glyph_cache* perv_glyph() const { return m_prev_glyph; }
|
||||
const glyph_cache* last_glyph() const { return m_last_glyph; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool add_kerning(double* x, double* y)
|
||||
{
|
||||
if(m_prev_glyph && m_last_glyph)
|
||||
{
|
||||
return m_engine.add_kerning(m_prev_glyph->glyph_index,
|
||||
m_last_glyph->glyph_index,
|
||||
x, y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void precache(unsigned from, unsigned to)
|
||||
{
|
||||
for(; from <= to; ++from) glyph(from);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_cache()
|
||||
{
|
||||
m_fonts.font(m_engine.font_signature(), true);
|
||||
m_change_stamp = m_engine.change_stamp();
|
||||
m_prev_glyph = m_last_glyph = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
font_cache_manager(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void synchronize()
|
||||
{
|
||||
if(m_change_stamp != m_engine.change_stamp())
|
||||
{
|
||||
m_fonts.font(m_engine.font_signature());
|
||||
m_change_stamp = m_engine.change_stamp();
|
||||
m_prev_glyph = m_last_glyph = 0;
|
||||
}
|
||||
}
|
||||
|
||||
font_cache_pool m_fonts;
|
||||
font_engine_type& m_engine;
|
||||
int m_change_stamp;
|
||||
double m_dx;
|
||||
double m_dy;
|
||||
const glyph_cache* m_prev_glyph;
|
||||
const glyph_cache* m_last_glyph;
|
||||
path_adaptor_type m_path_adaptor;
|
||||
gray8_adaptor_type m_gray8_adaptor;
|
||||
gray8_scanline_type m_gray8_scanline;
|
||||
mono_adaptor_type m_mono_adaptor;
|
||||
mono_scanline_type m_mono_scanline;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
123
agg/include/agg_gamma_functions.h
Normal file
123
agg/include/agg_gamma_functions.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GAMMA_FUNCTIONS_INCLUDED
|
||||
#define AGG_GAMMA_FUNCTIONS_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//===============================================================gamma_none
|
||||
struct gamma_none
|
||||
{
|
||||
double operator()(double x) const { return x; }
|
||||
};
|
||||
|
||||
|
||||
//==============================================================gamma_power
|
||||
class gamma_power
|
||||
{
|
||||
public:
|
||||
gamma_power() : m_gamma(1.0) {}
|
||||
gamma_power(double g) : m_gamma(g) {}
|
||||
|
||||
void gamma(double g) { m_gamma = g; }
|
||||
double gamma() const { return m_gamma; }
|
||||
|
||||
double operator() (double x) const
|
||||
{
|
||||
return pow(x, m_gamma);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_gamma;
|
||||
};
|
||||
|
||||
|
||||
//==========================================================gamma_threshold
|
||||
class gamma_threshold
|
||||
{
|
||||
public:
|
||||
gamma_threshold() : m_threshold(0.5) {}
|
||||
gamma_threshold(double t) : m_threshold(t) {}
|
||||
|
||||
void threshold(double t) { m_threshold = t; }
|
||||
double threshold() const { return m_threshold; }
|
||||
|
||||
double operator() (double x) const
|
||||
{
|
||||
return (x < m_threshold) ? 0.0 : 1.0;
|
||||
}
|
||||
|
||||
private:
|
||||
double m_threshold;
|
||||
};
|
||||
|
||||
|
||||
//============================================================gamma_linear
|
||||
class gamma_linear
|
||||
{
|
||||
public:
|
||||
gamma_linear() : m_start(0.0), m_end(1.0) {}
|
||||
gamma_linear(double s, double e) : m_start(s), m_end(e) {}
|
||||
|
||||
void set(double s, double e) { m_start = s; m_end = e; }
|
||||
void start(double s) { m_start = s; }
|
||||
void end(double e) { m_end = e; }
|
||||
double start() const { return m_start; }
|
||||
double end() const { return m_end; }
|
||||
|
||||
double operator() (double x) const
|
||||
{
|
||||
if(x < m_start) return 0.0;
|
||||
if(x > m_end) return 1.0;
|
||||
return (x - m_start) / (m_end - m_start);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_start;
|
||||
double m_end;
|
||||
};
|
||||
|
||||
|
||||
//==========================================================gamma_multiply
|
||||
class gamma_multiply
|
||||
{
|
||||
public:
|
||||
gamma_multiply() : m_mul(1.0) {}
|
||||
gamma_multiply(double v) : m_mul(v) {}
|
||||
|
||||
void value(double v) { m_mul = v; }
|
||||
double value() const { return m_mul; }
|
||||
|
||||
double operator() (double x) const
|
||||
{
|
||||
double y = x * m_mul;
|
||||
if(y > 1.0) y = 1.0;
|
||||
return y;
|
||||
}
|
||||
|
||||
private:
|
||||
double m_mul;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
121
agg/include/agg_gamma_lut.h
Normal file
121
agg/include/agg_gamma_lut.h
Normal file
|
@ -0,0 +1,121 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GAMMA_LUT_INCLUDED
|
||||
#define AGG_GAMMA_LUT_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
template<class LoResT=int8u,
|
||||
class HiResT=int8u,
|
||||
unsigned GammaShift=8,
|
||||
unsigned HiResShift=8> class gamma_lut
|
||||
{
|
||||
public:
|
||||
typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type;
|
||||
|
||||
enum gamma_scale_e
|
||||
{
|
||||
gamma_shift = GammaShift,
|
||||
gamma_size = 1 << gamma_shift,
|
||||
gamma_mask = gamma_size - 1
|
||||
};
|
||||
|
||||
enum hi_res_scale_e
|
||||
{
|
||||
hi_res_shift = HiResShift,
|
||||
hi_res_size = 1 << hi_res_shift,
|
||||
hi_res_mask = hi_res_size - 1
|
||||
};
|
||||
|
||||
~gamma_lut()
|
||||
{
|
||||
delete [] m_inv_gamma;
|
||||
delete [] m_dir_gamma;
|
||||
}
|
||||
|
||||
gamma_lut() :
|
||||
m_gamma(1.0),
|
||||
m_dir_gamma(new HiResT[gamma_size]),
|
||||
m_inv_gamma(new LoResT[hi_res_size])
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < gamma_size; i++)
|
||||
{
|
||||
m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
|
||||
}
|
||||
|
||||
for(i = 0; i < hi_res_size; i++)
|
||||
{
|
||||
m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
|
||||
}
|
||||
}
|
||||
|
||||
gamma_lut(double g) :
|
||||
m_gamma(1.0),
|
||||
m_dir_gamma(new HiResT[gamma_size]),
|
||||
m_inv_gamma(new LoResT[hi_res_size])
|
||||
{
|
||||
gamma(g);
|
||||
}
|
||||
|
||||
void gamma(double g)
|
||||
{
|
||||
m_gamma = g;
|
||||
|
||||
unsigned i;
|
||||
for(i = 0; i < gamma_size; i++)
|
||||
{
|
||||
m_dir_gamma[i] = (HiResT)
|
||||
uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask));
|
||||
}
|
||||
|
||||
double inv_g = 1.0 / g;
|
||||
for(i = 0; i < hi_res_size; i++)
|
||||
{
|
||||
m_inv_gamma[i] = (LoResT)
|
||||
uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask));
|
||||
}
|
||||
}
|
||||
|
||||
double gamma() const
|
||||
{
|
||||
return m_gamma;
|
||||
}
|
||||
|
||||
HiResT dir(LoResT v) const
|
||||
{
|
||||
return m_dir_gamma[unsigned(v)];
|
||||
}
|
||||
|
||||
LoResT inv(HiResT v) const
|
||||
{
|
||||
return m_inv_gamma[unsigned(v)];
|
||||
}
|
||||
|
||||
private:
|
||||
gamma_lut(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
double m_gamma;
|
||||
HiResT* m_dir_gamma;
|
||||
LoResT* m_inv_gamma;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
155
agg/include/agg_glyph_raster_bin.h
Normal file
155
agg/include/agg_glyph_raster_bin.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GLYPH_RASTER_BIN_INCLUDED
|
||||
#define AGG_GLYPH_RASTER_BIN_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//========================================================glyph_raster_bin
|
||||
template<class ColorT> class glyph_raster_bin
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct glyph_rect
|
||||
{
|
||||
int x1,y1,x2,y2;
|
||||
double dx, dy;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
glyph_raster_bin(const int8u* font) :
|
||||
m_font(font),
|
||||
m_big_endian(false)
|
||||
{
|
||||
int t = 1;
|
||||
if(*(char*)&t == 0) m_big_endian = true;
|
||||
memset(m_span, 0, sizeof(m_span));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* font() const { return m_font; }
|
||||
void font(const int8u* f) { m_font = f; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double height() const { return m_font[0]; }
|
||||
double base_line() const { return m_font[1]; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class CharT>
|
||||
double width(const CharT* str) const
|
||||
{
|
||||
unsigned start_char = m_font[2];
|
||||
unsigned num_chars = m_font[3];
|
||||
|
||||
unsigned w = 0;
|
||||
while(*str)
|
||||
{
|
||||
unsigned glyph = *str;
|
||||
const int8u* bits = m_font + 4 + num_chars * 2 +
|
||||
value(m_font + 4 + (glyph - start_char) * 2);
|
||||
w += *bits;
|
||||
++str;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip)
|
||||
{
|
||||
unsigned start_char = m_font[2];
|
||||
unsigned num_chars = m_font[3];
|
||||
|
||||
m_bits = m_font + 4 + num_chars * 2 +
|
||||
value(m_font + 4 + (glyph - start_char) * 2);
|
||||
|
||||
m_glyph_width = *m_bits++;
|
||||
m_glyph_byte_width = (m_glyph_width + 7) >> 3;
|
||||
|
||||
r->x1 = int(x);
|
||||
r->x2 = r->x1 + m_glyph_width - 1;
|
||||
if(flip)
|
||||
{
|
||||
r->y1 = int(y) - m_font[0] + m_font[1];
|
||||
r->y2 = r->y1 + m_font[0] - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
r->y1 = int(y) - m_font[1] + 1;
|
||||
r->y2 = r->y1 + m_font[0] - 1;
|
||||
}
|
||||
r->dx = m_glyph_width;
|
||||
r->dy = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const cover_type* span(unsigned i)
|
||||
{
|
||||
i = m_font[0] - i - 1;
|
||||
const int8u* bits = m_bits + i * m_glyph_byte_width;
|
||||
unsigned j;
|
||||
unsigned val = *bits;
|
||||
unsigned nb = 0;
|
||||
for(j = 0; j < m_glyph_width; ++j)
|
||||
{
|
||||
m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none);
|
||||
val <<= 1;
|
||||
if(++nb >= 8)
|
||||
{
|
||||
val = *++bits;
|
||||
nb = 0;
|
||||
}
|
||||
}
|
||||
return m_span;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
int16u value(const int8u* p) const
|
||||
{
|
||||
int16u v;
|
||||
if(m_big_endian)
|
||||
{
|
||||
*(int8u*)&v = p[1];
|
||||
*((int8u*)&v + 1) = p[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
*(int8u*)&v = p[0];
|
||||
*((int8u*)&v + 1) = p[1];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* m_font;
|
||||
bool m_big_endian;
|
||||
cover_type m_span[32];
|
||||
const int8u* m_bits;
|
||||
unsigned m_glyph_width;
|
||||
unsigned m_glyph_byte_width;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
154
agg/include/agg_gsv_text.h
Normal file
154
agg/include/agg_gsv_text.h
Normal file
|
@ -0,0 +1,154 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 gsv_text
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GSV_TEXT_INCLUDED
|
||||
#define AGG_GSV_TEXT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
#include "agg_conv_transform.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//---------------------------------------------------------------gsv_text
|
||||
//
|
||||
// See Implementation agg_gsv_text.cpp
|
||||
//
|
||||
class gsv_text
|
||||
{
|
||||
enum status
|
||||
{
|
||||
initial,
|
||||
next_char,
|
||||
start_glyph,
|
||||
glyph
|
||||
};
|
||||
|
||||
public:
|
||||
~gsv_text();
|
||||
gsv_text();
|
||||
|
||||
void font(const void* font);
|
||||
void flip(bool flip_y) { m_flip = flip_y; }
|
||||
void load_font(const char* file);
|
||||
void size(double height, double width=0.0);
|
||||
void space(double space);
|
||||
void line_space(double line_space);
|
||||
void start_point(double x, double y);
|
||||
void text(const char* text);
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
// not supposed to be copied
|
||||
gsv_text(const gsv_text&);
|
||||
const gsv_text& operator = (const gsv_text&);
|
||||
|
||||
int16u value(const int8u* p) const
|
||||
{
|
||||
int16u v;
|
||||
if(m_big_endian)
|
||||
{
|
||||
*(int8u*)&v = p[1];
|
||||
*((int8u*)&v + 1) = p[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
*(int8u*)&v = p[0];
|
||||
*((int8u*)&v + 1) = p[1];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private:
|
||||
double m_x;
|
||||
double m_y;
|
||||
double m_start_x;
|
||||
double m_width;
|
||||
double m_height;
|
||||
double m_space;
|
||||
double m_line_space;
|
||||
char m_chr[2];
|
||||
char* m_text;
|
||||
char* m_text_buf;
|
||||
unsigned m_buf_size;
|
||||
char* m_cur_chr;
|
||||
const void* m_font;
|
||||
char* m_loaded_font;
|
||||
status m_status;
|
||||
bool m_big_endian;
|
||||
bool m_flip;
|
||||
|
||||
int8u* m_indices;
|
||||
int8* m_glyphs;
|
||||
int8* m_bglyph;
|
||||
int8* m_eglyph;
|
||||
double m_w;
|
||||
double m_h;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------gsv_text_outline
|
||||
template<class Transformer = trans_affine> class gsv_text_outline
|
||||
{
|
||||
public:
|
||||
gsv_text_outline(gsv_text& text, const Transformer& trans) :
|
||||
m_polyline(text),
|
||||
m_trans(m_polyline, trans)
|
||||
{
|
||||
}
|
||||
|
||||
void width(double w)
|
||||
{
|
||||
m_polyline.width(w);
|
||||
}
|
||||
|
||||
void transformer(const Transformer* trans)
|
||||
{
|
||||
m_trans->transformer(trans);
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_trans.rewind(path_id);
|
||||
m_polyline.line_join(round_join);
|
||||
m_polyline.line_cap(round_cap);
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
return m_trans.vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
conv_stroke<gsv_text> m_polyline;
|
||||
conv_transform<conv_stroke<gsv_text>, Transformer> m_trans;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
476
agg/include/agg_image_accessors.h
Normal file
476
agg/include/agg_image_accessors.h
Normal file
|
@ -0,0 +1,476 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_IMAGE_ACCESSORS_INCLUDED
|
||||
#define AGG_IMAGE_ACCESSORS_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------image_accessor_clip
|
||||
template<class PixFmt> class image_accessor_clip
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::order_type order_type;
|
||||
typedef typename pixfmt_type::value_type value_type;
|
||||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_clip() {}
|
||||
image_accessor_clip(const pixfmt_type& pixf, const color_type& bk) :
|
||||
m_pixf(&pixf)
|
||||
{
|
||||
pixfmt_type::make_pix(m_bk_buf, bk);
|
||||
}
|
||||
|
||||
void set_source(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
||||
void background_color(const color_type& bk)
|
||||
{
|
||||
pixfmt_type::make_pix(m_bk_buf, bk);
|
||||
}
|
||||
|
||||
private:
|
||||
AGG_INLINE const int8u* pixel() const
|
||||
{
|
||||
if(m_y >= 0 && m_y < (int)m_pixf->height() &&
|
||||
m_x >= 0 && m_x < (int)m_pixf->width())
|
||||
{
|
||||
return m_pixf->pix_ptr(m_x, m_y);
|
||||
}
|
||||
return m_bk_buf;
|
||||
}
|
||||
|
||||
public:
|
||||
AGG_INLINE const int8u* span(int x, int y, unsigned len)
|
||||
{
|
||||
m_x = m_x0 = x;
|
||||
m_y = y;
|
||||
if(y >= 0 && y < (int)m_pixf->height() &&
|
||||
x >= 0 && x+len <= (int)m_pixf->width())
|
||||
{
|
||||
return m_pix_ptr = m_pixf->pix_ptr(x, y);
|
||||
}
|
||||
m_pix_ptr = 0;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_x()
|
||||
{
|
||||
if(m_pix_ptr) return m_pix_ptr += pix_width;
|
||||
++m_x;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_y()
|
||||
{
|
||||
++m_y;
|
||||
m_x = m_x0;
|
||||
if(m_pix_ptr &&
|
||||
m_y >= 0 && m_y < (int)m_pixf->height())
|
||||
{
|
||||
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
|
||||
}
|
||||
m_pix_ptr = 0;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
private:
|
||||
const pixfmt_type* m_pixf;
|
||||
int8u m_bk_buf[4];
|
||||
int m_x, m_x0, m_y;
|
||||
const int8u* m_pix_ptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------image_accessor_no_clip
|
||||
template<class PixFmt> class image_accessor_no_clip
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::order_type order_type;
|
||||
typedef typename pixfmt_type::value_type value_type;
|
||||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_no_clip() {}
|
||||
image_accessor_no_clip(const pixfmt_type& pixf) : m_pixf(&pixf) {}
|
||||
|
||||
void set_source(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* span(int x, int y, unsigned)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
return m_pix_ptr = m_pixf->pix_ptr(x, y);
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_x()
|
||||
{
|
||||
return m_pix_ptr += pix_width;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_y()
|
||||
{
|
||||
++m_y;
|
||||
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
|
||||
}
|
||||
|
||||
private:
|
||||
const pixfmt_type* m_pixf;
|
||||
int m_x, m_y;
|
||||
const int8u* m_pix_ptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------image_accessor_clone
|
||||
template<class PixFmt> class image_accessor_clone
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::order_type order_type;
|
||||
typedef typename pixfmt_type::value_type value_type;
|
||||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_clone() {}
|
||||
image_accessor_clone(const pixfmt_type& pixf) : m_pixf(&pixf) {}
|
||||
|
||||
void set_source(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
||||
private:
|
||||
AGG_INLINE const int8u* pixel() const
|
||||
{
|
||||
register int x = m_x;
|
||||
register int y = m_y;
|
||||
if(x < 0) x = 0;
|
||||
if(y < 0) y = 0;
|
||||
if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1;
|
||||
if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1;
|
||||
return m_pixf->pix_ptr(x, y);
|
||||
}
|
||||
|
||||
public:
|
||||
AGG_INLINE const int8u* span(int x, int y, unsigned len)
|
||||
{
|
||||
m_x = m_x0 = x;
|
||||
m_y = y;
|
||||
if(y >= 0 && y < (int)m_pixf->height() &&
|
||||
x >= 0 && x+len <= (int)m_pixf->width())
|
||||
{
|
||||
return m_pix_ptr = m_pixf->pix_ptr(x, y);
|
||||
}
|
||||
m_pix_ptr = 0;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_x()
|
||||
{
|
||||
if(m_pix_ptr) return m_pix_ptr += pix_width;
|
||||
++m_x;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_y()
|
||||
{
|
||||
++m_y;
|
||||
m_x = m_x0;
|
||||
if(m_pix_ptr &&
|
||||
m_y >= 0 && m_y < (int)m_pixf->height())
|
||||
{
|
||||
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
|
||||
}
|
||||
m_pix_ptr = 0;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
private:
|
||||
const pixfmt_type* m_pixf;
|
||||
int m_x, m_x0, m_y;
|
||||
const int8u* m_pix_ptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------image_accessor_wrap
|
||||
template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::order_type order_type;
|
||||
typedef typename pixfmt_type::value_type value_type;
|
||||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_wrap() {}
|
||||
image_accessor_wrap(const pixfmt_type& pixf) :
|
||||
m_pixf(&pixf),
|
||||
m_wrap_x(pixf.width()),
|
||||
m_wrap_y(pixf.height())
|
||||
{}
|
||||
|
||||
void set_source(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* span(int x, int y, unsigned)
|
||||
{
|
||||
m_x = x;
|
||||
m_row_ptr = m_pixf->row_ptr(m_wrap_y(y));
|
||||
return m_row_ptr + m_wrap_x(x) * pix_width;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_x()
|
||||
{
|
||||
int x = ++m_wrap_x;
|
||||
return m_row_ptr + x * pix_width;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_y()
|
||||
{
|
||||
m_row_ptr = m_pixf->row_ptr(++m_wrap_y);
|
||||
return m_row_ptr + m_wrap_x(m_x) * pix_width;
|
||||
}
|
||||
|
||||
private:
|
||||
const pixfmt_type* m_pixf;
|
||||
const int8u* m_row_ptr;
|
||||
int m_x;
|
||||
WrapX m_wrap_x;
|
||||
WrapY m_wrap_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------wrap_mode_repeat
|
||||
class wrap_mode_repeat
|
||||
{
|
||||
public:
|
||||
wrap_mode_repeat() {}
|
||||
wrap_mode_repeat(unsigned size) :
|
||||
m_size(size),
|
||||
m_add(size * (0x3FFFFFFF / size)),
|
||||
m_value(0)
|
||||
{}
|
||||
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
return m_value = (unsigned(v) + m_add) % m_size;
|
||||
}
|
||||
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value >= m_size) m_value = 0;
|
||||
return m_value;
|
||||
}
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_add;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------wrap_mode_repeat_pow2
|
||||
class wrap_mode_repeat_pow2
|
||||
{
|
||||
public:
|
||||
wrap_mode_repeat_pow2() {}
|
||||
wrap_mode_repeat_pow2(unsigned size) : m_value(0)
|
||||
{
|
||||
m_mask = 1;
|
||||
while(m_mask < size) m_mask = (m_mask << 1) | 1;
|
||||
m_mask >>= 1;
|
||||
}
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
return m_value = unsigned(v) & m_mask;
|
||||
}
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value > m_mask) m_value = 0;
|
||||
return m_value;
|
||||
}
|
||||
private:
|
||||
unsigned m_mask;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------wrap_mode_repeat_auto_pow2
|
||||
class wrap_mode_repeat_auto_pow2
|
||||
{
|
||||
public:
|
||||
wrap_mode_repeat_auto_pow2() {}
|
||||
wrap_mode_repeat_auto_pow2(unsigned size) :
|
||||
m_size(size),
|
||||
m_add(size * (0x3FFFFFFF / size)),
|
||||
m_mask((m_size & (m_size-1)) ? 0 : m_size-1),
|
||||
m_value(0)
|
||||
{}
|
||||
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
if(m_mask) return m_value = unsigned(v) & m_mask;
|
||||
return m_value = (unsigned(v) + m_add) % m_size;
|
||||
}
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value >= m_size) m_value = 0;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_add;
|
||||
unsigned m_mask;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------wrap_mode_reflect
|
||||
class wrap_mode_reflect
|
||||
{
|
||||
public:
|
||||
wrap_mode_reflect() {}
|
||||
wrap_mode_reflect(unsigned size) :
|
||||
m_size(size),
|
||||
m_size2(size * 2),
|
||||
m_add(m_size2 * (0x3FFFFFFF / m_size2)),
|
||||
m_value(0)
|
||||
{}
|
||||
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
m_value = (unsigned(v) + m_add) % m_size2;
|
||||
if(m_value >= m_size) return m_size2 - m_value - 1;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value >= m_size2) m_value = 0;
|
||||
if(m_value >= m_size) return m_size2 - m_value - 1;
|
||||
return m_value;
|
||||
}
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_size2;
|
||||
unsigned m_add;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------wrap_mode_reflect_pow2
|
||||
class wrap_mode_reflect_pow2
|
||||
{
|
||||
public:
|
||||
wrap_mode_reflect_pow2() {}
|
||||
wrap_mode_reflect_pow2(unsigned size) : m_value(0)
|
||||
{
|
||||
m_mask = 1;
|
||||
m_size = 1;
|
||||
while(m_mask < size)
|
||||
{
|
||||
m_mask = (m_mask << 1) | 1;
|
||||
m_size <<= 1;
|
||||
}
|
||||
}
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
m_value = unsigned(v) & m_mask;
|
||||
if(m_value >= m_size) return m_mask - m_value;
|
||||
return m_value;
|
||||
}
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
m_value &= m_mask;
|
||||
if(m_value >= m_size) return m_mask - m_value;
|
||||
return m_value;
|
||||
}
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_mask;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------wrap_mode_reflect_auto_pow2
|
||||
class wrap_mode_reflect_auto_pow2
|
||||
{
|
||||
public:
|
||||
wrap_mode_reflect_auto_pow2() {}
|
||||
wrap_mode_reflect_auto_pow2(unsigned size) :
|
||||
m_size(size),
|
||||
m_size2(size * 2),
|
||||
m_add(m_size2 * (0x3FFFFFFF / m_size2)),
|
||||
m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1),
|
||||
m_value(0)
|
||||
{}
|
||||
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
m_value = m_mask ? unsigned(v) & m_mask :
|
||||
(unsigned(v) + m_add) % m_size2;
|
||||
if(m_value >= m_size) return m_size2 - m_value - 1;
|
||||
return m_value;
|
||||
}
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value >= m_size2) m_value = 0;
|
||||
if(m_value >= m_size) return m_size2 - m_value - 1;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_size2;
|
||||
unsigned m_add;
|
||||
unsigned m_mask;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
451
agg/include/agg_image_filters.h
Normal file
451
agg/include/agg_image_filters.h
Normal file
|
@ -0,0 +1,451 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Image transformation filters,
|
||||
// Filtering classes (image_filter_lut, image_filter),
|
||||
// Basic filter shape classes
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_IMAGE_FILTERS_INCLUDED
|
||||
#define AGG_IMAGE_FILTERS_INCLUDED
|
||||
|
||||
#include "agg_math.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
// See Implementation agg_image_filters.cpp
|
||||
|
||||
enum image_filter_scale_e
|
||||
{
|
||||
image_filter_shift = 14, //----image_filter_shift
|
||||
image_filter_scale = 1 << image_filter_shift, //----image_filter_scale
|
||||
image_filter_mask = image_filter_scale - 1 //----image_filter_mask
|
||||
};
|
||||
|
||||
enum image_subpixel_scale_e
|
||||
{
|
||||
image_subpixel_shift = 8, //----image_subpixel_shift
|
||||
image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale
|
||||
image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------image_filter_lut
|
||||
class image_filter_lut
|
||||
{
|
||||
public:
|
||||
~image_filter_lut();
|
||||
image_filter_lut();
|
||||
|
||||
template<class FilterF> void calculate(const FilterF& filter,
|
||||
bool normalization=true)
|
||||
{
|
||||
double r = filter.radius();
|
||||
realloc_lut(r);
|
||||
unsigned i;
|
||||
unsigned pivot = diameter() << (image_subpixel_shift - 1);
|
||||
for(i = 0; i < pivot; i++)
|
||||
{
|
||||
double x = double(i) / double(image_subpixel_scale);
|
||||
double y = filter.calc_weight(x);
|
||||
m_weight_array[pivot + i] =
|
||||
m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale);
|
||||
}
|
||||
unsigned end = (diameter() << image_subpixel_shift) - 1;
|
||||
m_weight_array[0] = m_weight_array[end];
|
||||
if(normalization)
|
||||
{
|
||||
normalize();
|
||||
}
|
||||
}
|
||||
|
||||
template<class FilterF> image_filter_lut(const FilterF& filter,
|
||||
bool normalization=true) :
|
||||
m_weight_array(0),
|
||||
m_max_size(0)
|
||||
{
|
||||
calculate(filter, normalization);
|
||||
}
|
||||
|
||||
double radius() const { return m_radius; }
|
||||
unsigned diameter() const { return m_diameter; }
|
||||
int start() const { return m_start; }
|
||||
const int16* weight_array() const { return m_weight_array; }
|
||||
void normalize();
|
||||
|
||||
private:
|
||||
void realloc_lut(double radius);
|
||||
image_filter_lut(const image_filter_lut&);
|
||||
const image_filter_lut& operator = (const image_filter_lut&);
|
||||
|
||||
double m_radius;
|
||||
unsigned m_diameter;
|
||||
int m_start;
|
||||
int16* m_weight_array;
|
||||
unsigned m_max_size;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------image_filter
|
||||
template<class FilterF> class image_filter : public image_filter_lut
|
||||
{
|
||||
public:
|
||||
image_filter()
|
||||
{
|
||||
calculate(m_filter_function);
|
||||
}
|
||||
private:
|
||||
FilterF m_filter_function;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------image_filter_bilinear
|
||||
struct image_filter_bilinear
|
||||
{
|
||||
static double radius() { return 1.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return 1.0 - x;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------image_filter_hanning
|
||||
struct image_filter_hanning
|
||||
{
|
||||
static double radius() { return 1.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return 0.5 + 0.5 * cos(pi * x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------image_filter_hamming
|
||||
struct image_filter_hamming
|
||||
{
|
||||
static double radius() { return 1.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return 0.54 + 0.46 * cos(pi * x);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------image_filter_hermite
|
||||
struct image_filter_hermite
|
||||
{
|
||||
static double radius() { return 1.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return (2.0 * x - 3.0) * x * x + 1.0;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------image_filter_quadric
|
||||
struct image_filter_quadric
|
||||
{
|
||||
static double radius() { return 1.5; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
double t;
|
||||
if(x < 0.5) return 0.75 - x * x;
|
||||
if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;}
|
||||
return 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------image_filter_bicubic
|
||||
class image_filter_bicubic
|
||||
{
|
||||
static double pow3(double x)
|
||||
{
|
||||
return (x <= 0.0) ? 0.0 : x * x * x;
|
||||
}
|
||||
|
||||
public:
|
||||
static double radius() { return 2.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return
|
||||
(1.0/6.0) *
|
||||
(pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------image_filter_kaiser
|
||||
class image_filter_kaiser
|
||||
{
|
||||
double a;
|
||||
double i0a;
|
||||
double epsilon;
|
||||
|
||||
public:
|
||||
image_filter_kaiser(double b = 6.33) :
|
||||
a(b), epsilon(1e-12)
|
||||
{
|
||||
i0a = 1.0 / bessel_i0(b);
|
||||
}
|
||||
|
||||
static double radius() { return 1.0; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
return bessel_i0(a * sqrt(1. - x * x)) * i0a;
|
||||
}
|
||||
|
||||
private:
|
||||
double bessel_i0(double x) const
|
||||
{
|
||||
int i;
|
||||
double sum, y, t;
|
||||
|
||||
sum = 1.;
|
||||
y = x * x / 4.;
|
||||
t = y;
|
||||
|
||||
for(i = 2; t > epsilon; i++)
|
||||
{
|
||||
sum += t;
|
||||
t *= (double)y / (i * i);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------image_filter_catrom
|
||||
struct image_filter_catrom
|
||||
{
|
||||
static double radius() { return 2.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
|
||||
if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
|
||||
return 0.;
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------image_filter_mitchell
|
||||
class image_filter_mitchell
|
||||
{
|
||||
double p0, p2, p3;
|
||||
double q0, q1, q2, q3;
|
||||
|
||||
public:
|
||||
image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) :
|
||||
p0((6.0 - 2.0 * b) / 6.0),
|
||||
p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0),
|
||||
p3((12.0 - 9.0 * b - 6.0 * c) / 6.0),
|
||||
q0((8.0 * b + 24.0 * c) / 6.0),
|
||||
q1((-12.0 * b - 48.0 * c) / 6.0),
|
||||
q2((6.0 * b + 30.0 * c) / 6.0),
|
||||
q3((-b - 6.0 * c) / 6.0)
|
||||
{}
|
||||
|
||||
static double radius() { return 2.0; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
if(x < 1.0) return p0 + x * x * (p2 + x * p3);
|
||||
if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3));
|
||||
return 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------image_filter_spline16
|
||||
struct image_filter_spline16
|
||||
{
|
||||
static double radius() { return 2.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
if(x < 1.0)
|
||||
{
|
||||
return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
|
||||
}
|
||||
return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------image_filter_spline36
|
||||
struct image_filter_spline36
|
||||
{
|
||||
static double radius() { return 3.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
if(x < 1.0)
|
||||
{
|
||||
return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0;
|
||||
}
|
||||
if(x < 2.0)
|
||||
{
|
||||
return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1);
|
||||
}
|
||||
return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------image_filter_gaussian
|
||||
struct image_filter_gaussian
|
||||
{
|
||||
static double radius() { return 2.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return exp(-2.0 * x * x) * sqrt(2.0 / pi);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------image_filter_bessel
|
||||
struct image_filter_bessel
|
||||
{
|
||||
static double radius() { return 3.2383; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------image_filter_sinc
|
||||
class image_filter_sinc
|
||||
{
|
||||
public:
|
||||
image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
|
||||
double radius() const { return m_radius; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
if(x == 0.0) return 1.0;
|
||||
x *= pi;
|
||||
return sin(x) / x;
|
||||
}
|
||||
private:
|
||||
double m_radius;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------image_filter_lanczos
|
||||
class image_filter_lanczos
|
||||
{
|
||||
public:
|
||||
image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
|
||||
double radius() const { return m_radius; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
if(x == 0.0) return 1.0;
|
||||
if(x > m_radius) return 0.0;
|
||||
x *= pi;
|
||||
double xr = x / m_radius;
|
||||
return (sin(x) / x) * (sin(xr) / xr);
|
||||
}
|
||||
private:
|
||||
double m_radius;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------image_filter_blackman
|
||||
class image_filter_blackman
|
||||
{
|
||||
public:
|
||||
image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
|
||||
double radius() const { return m_radius; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
if(x == 0.0) return 1.0;
|
||||
if(x > m_radius) return 0.0;
|
||||
x *= pi;
|
||||
double xr = x / m_radius;
|
||||
return (sin(x) / x) * (0.42 + 0.5*cos(xr) + 0.08*cos(2*xr));
|
||||
}
|
||||
private:
|
||||
double m_radius;
|
||||
};
|
||||
|
||||
//------------------------------------------------image_filter_sinc36
|
||||
class image_filter_sinc36 : public image_filter_sinc
|
||||
{ public: image_filter_sinc36() : image_filter_sinc(3.0){} };
|
||||
|
||||
//------------------------------------------------image_filter_sinc64
|
||||
class image_filter_sinc64 : public image_filter_sinc
|
||||
{ public: image_filter_sinc64() : image_filter_sinc(4.0){} };
|
||||
|
||||
//-----------------------------------------------image_filter_sinc100
|
||||
class image_filter_sinc100 : public image_filter_sinc
|
||||
{ public: image_filter_sinc100() : image_filter_sinc(5.0){} };
|
||||
|
||||
//-----------------------------------------------image_filter_sinc144
|
||||
class image_filter_sinc144 : public image_filter_sinc
|
||||
{ public: image_filter_sinc144() : image_filter_sinc(6.0){} };
|
||||
|
||||
//-----------------------------------------------image_filter_sinc196
|
||||
class image_filter_sinc196 : public image_filter_sinc
|
||||
{ public: image_filter_sinc196() : image_filter_sinc(7.0){} };
|
||||
|
||||
//-----------------------------------------------image_filter_sinc256
|
||||
class image_filter_sinc256 : public image_filter_sinc
|
||||
{ public: image_filter_sinc256() : image_filter_sinc(8.0){} };
|
||||
|
||||
//---------------------------------------------image_filter_lanczos36
|
||||
class image_filter_lanczos36 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos36() : image_filter_lanczos(3.0){} };
|
||||
|
||||
//---------------------------------------------image_filter_lanczos64
|
||||
class image_filter_lanczos64 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos64() : image_filter_lanczos(4.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_lanczos100
|
||||
class image_filter_lanczos100 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos100() : image_filter_lanczos(5.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_lanczos144
|
||||
class image_filter_lanczos144 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos144() : image_filter_lanczos(6.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_lanczos196
|
||||
class image_filter_lanczos196 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos196() : image_filter_lanczos(7.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_lanczos256
|
||||
class image_filter_lanczos256 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos256() : image_filter_lanczos(8.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_blackman36
|
||||
class image_filter_blackman36 : public image_filter_blackman
|
||||
{ public: image_filter_blackman36() : image_filter_blackman(3.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_blackman64
|
||||
class image_filter_blackman64 : public image_filter_blackman
|
||||
{ public: image_filter_blackman64() : image_filter_blackman(4.0){} };
|
||||
|
||||
//-------------------------------------------image_filter_blackman100
|
||||
class image_filter_blackman100 : public image_filter_blackman
|
||||
{ public: image_filter_blackman100() : image_filter_blackman(5.0){} };
|
||||
|
||||
//-------------------------------------------image_filter_blackman144
|
||||
class image_filter_blackman144 : public image_filter_blackman
|
||||
{ public: image_filter_blackman144() : image_filter_blackman(6.0){} };
|
||||
|
||||
//-------------------------------------------image_filter_blackman196
|
||||
class image_filter_blackman196 : public image_filter_blackman
|
||||
{ public: image_filter_blackman196() : image_filter_blackman(7.0){} };
|
||||
|
||||
//-------------------------------------------image_filter_blackman256
|
||||
class image_filter_blackman256 : public image_filter_blackman
|
||||
{ public: image_filter_blackman256() : image_filter_blackman(8.0){} };
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
189
agg/include/agg_line_aa_basics.h
Normal file
189
agg/include/agg_line_aa_basics.h
Normal file
|
@ -0,0 +1,189 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_LINE_AA_BASICS_INCLUDED
|
||||
#define AGG_LINE_AA_BASICS_INCLUDED
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
// See Implementation agg_line_aa_basics.cpp
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
enum line_subpixel_scale_e
|
||||
{
|
||||
line_subpixel_shift = 8, //----line_subpixel_shift
|
||||
line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale
|
||||
line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask
|
||||
line_max_coord = (1 << 28) - 1, //----line_max_coord
|
||||
line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
enum line_mr_subpixel_scale_e
|
||||
{
|
||||
line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift
|
||||
line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale
|
||||
line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------line_mr
|
||||
AGG_INLINE int line_mr(int x)
|
||||
{
|
||||
return x >> (line_subpixel_shift - line_mr_subpixel_shift);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------line_hr
|
||||
AGG_INLINE int line_hr(int x)
|
||||
{
|
||||
return x << (line_subpixel_shift - line_mr_subpixel_shift);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------line_dbl_hr
|
||||
AGG_INLINE int line_dbl_hr(int x)
|
||||
{
|
||||
return x << line_subpixel_shift;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------line_coord
|
||||
struct line_coord
|
||||
{
|
||||
AGG_INLINE static int conv(double x)
|
||||
{
|
||||
return iround(x * line_subpixel_scale);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------line_coord_sat
|
||||
struct line_coord_sat
|
||||
{
|
||||
AGG_INLINE static int conv(double x)
|
||||
{
|
||||
return saturation<line_max_coord>::iround(x * line_subpixel_scale);
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================line_parameters
|
||||
struct line_parameters
|
||||
{
|
||||
//---------------------------------------------------------------------
|
||||
line_parameters() {}
|
||||
line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) :
|
||||
x1(x1_), y1(y1_), x2(x2_), y2(y2_),
|
||||
dx(abs(x2_ - x1_)),
|
||||
dy(abs(y2_ - y1_)),
|
||||
sx((x2_ > x1_) ? 1 : -1),
|
||||
sy((y2_ > y1_) ? 1 : -1),
|
||||
vertical(dy >= dx),
|
||||
inc(vertical ? sy : sx),
|
||||
len(len_),
|
||||
octant((sy & 4) | (sx & 2) | int(vertical))
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; }
|
||||
unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
bool same_orthogonal_quadrant(const line_parameters& lp) const
|
||||
{
|
||||
return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
bool same_diagonal_quadrant(const line_parameters& lp) const
|
||||
{
|
||||
return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void divide(line_parameters& lp1, line_parameters& lp2) const
|
||||
{
|
||||
int xmid = (x1 + x2) >> 1;
|
||||
int ymid = (y1 + y2) >> 1;
|
||||
int len2 = len >> 1;
|
||||
|
||||
lp1 = *this;
|
||||
lp2 = *this;
|
||||
|
||||
lp1.x2 = xmid;
|
||||
lp1.y2 = ymid;
|
||||
lp1.len = len2;
|
||||
lp1.dx = abs(lp1.x2 - lp1.x1);
|
||||
lp1.dy = abs(lp1.y2 - lp1.y1);
|
||||
|
||||
lp2.x1 = xmid;
|
||||
lp2.y1 = ymid;
|
||||
lp2.len = len2;
|
||||
lp2.dx = abs(lp2.x2 - lp2.x1);
|
||||
lp2.dy = abs(lp2.y2 - lp2.y1);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
int x1, y1, x2, y2, dx, dy, sx, sy;
|
||||
bool vertical;
|
||||
int inc;
|
||||
int len;
|
||||
int octant;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
static int8u s_orthogonal_quadrant[8];
|
||||
static int8u s_diagonal_quadrant[8];
|
||||
};
|
||||
|
||||
|
||||
|
||||
// See Implementation agg_line_aa_basics.cpp
|
||||
|
||||
//----------------------------------------------------------------bisectrix
|
||||
void bisectrix(const line_parameters& l1,
|
||||
const line_parameters& l2,
|
||||
int* x, int* y);
|
||||
|
||||
|
||||
//-------------------------------------------fix_degenerate_bisectrix_start
|
||||
void inline fix_degenerate_bisectrix_start(const line_parameters& lp,
|
||||
int* x, int* y)
|
||||
{
|
||||
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
|
||||
double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
|
||||
if(d < line_subpixel_scale/2)
|
||||
{
|
||||
*x = lp.x1 + (lp.y2 - lp.y1);
|
||||
*y = lp.y1 - (lp.x2 - lp.x1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------fix_degenerate_bisectrix_end
|
||||
void inline fix_degenerate_bisectrix_end(const line_parameters& lp,
|
||||
int* x, int* y)
|
||||
{
|
||||
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
|
||||
double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
|
||||
if(d < line_subpixel_scale/2)
|
||||
{
|
||||
*x = lp.x2 + (lp.y2 - lp.y1);
|
||||
*y = lp.y2 - (lp.x2 - lp.x1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
389
agg/include/agg_math.h
Normal file
389
agg/include/agg_math.h
Normal file
|
@ -0,0 +1,389 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
// Bessel function (besj) was adapted for use in AGG library by Andy Wilk
|
||||
// Contact: castor.vulgaris@gmail.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_MATH_INCLUDED
|
||||
#define AGG_MATH_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------vertex_dist_epsilon
|
||||
// Coinciding points maximal distance (Epsilon)
|
||||
const double vertex_dist_epsilon = 1e-14;
|
||||
|
||||
//-----------------------------------------------------intersection_epsilon
|
||||
// See calc_intersection
|
||||
const double intersection_epsilon = 1.0e-30;
|
||||
|
||||
//------------------------------------------------------------cross_product
|
||||
AGG_INLINE double cross_product(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y)
|
||||
{
|
||||
return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------point_in_triangle
|
||||
AGG_INLINE bool point_in_triangle(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x, double y)
|
||||
{
|
||||
bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0;
|
||||
bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0;
|
||||
bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0;
|
||||
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------calc_distance
|
||||
AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
double dx = x2-x1;
|
||||
double dy = y2-y1;
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------calc_line_point_distance
|
||||
AGG_INLINE double calc_line_point_distance(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y)
|
||||
{
|
||||
double dx = x2-x1;
|
||||
double dy = y2-y1;
|
||||
double d = sqrt(dx * dx + dy * dy);
|
||||
if(d < vertex_dist_epsilon)
|
||||
{
|
||||
return calc_distance(x1, y1, x, y);
|
||||
}
|
||||
return ((x - x2) * dy - (y - y2) * dx) / d;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------calc_intersection
|
||||
AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
|
||||
double cx, double cy, double dx, double dy,
|
||||
double* x, double* y)
|
||||
{
|
||||
double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
|
||||
double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
|
||||
if(fabs(den) < intersection_epsilon) return false;
|
||||
double r = num / den;
|
||||
*x = ax + r * (bx-ax);
|
||||
*y = ay + r * (by-ay);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------intersection_exists
|
||||
AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
|
||||
double x3, double y3, double x4, double y4)
|
||||
{
|
||||
// It's less expensive but you can't control the
|
||||
// boundary conditions: Less or LessEqual
|
||||
double dx1 = x2 - x1;
|
||||
double dy1 = y2 - y1;
|
||||
double dx2 = x4 - x3;
|
||||
double dy2 = y4 - y3;
|
||||
return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) !=
|
||||
((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) &&
|
||||
((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) !=
|
||||
((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0);
|
||||
|
||||
// It's is more expensive but more flexible
|
||||
// in terms of boundary conditions.
|
||||
//--------------------
|
||||
//double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3);
|
||||
//if(fabs(den) < intersection_epsilon) return false;
|
||||
//double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
|
||||
//double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
|
||||
//double ua = nom1 / den;
|
||||
//double ub = nom2 / den;
|
||||
//return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------calc_orthogonal
|
||||
AGG_INLINE void calc_orthogonal(double thickness,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double* x, double* y)
|
||||
{
|
||||
double dx = x2 - x1;
|
||||
double dy = y2 - y1;
|
||||
double d = sqrt(dx*dx + dy*dy);
|
||||
*x = thickness * dy / d;
|
||||
*y = thickness * dx / d;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------dilate_triangle
|
||||
AGG_INLINE void dilate_triangle(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double *x, double* y,
|
||||
double d)
|
||||
{
|
||||
double dx1=0.0;
|
||||
double dy1=0.0;
|
||||
double dx2=0.0;
|
||||
double dy2=0.0;
|
||||
double dx3=0.0;
|
||||
double dy3=0.0;
|
||||
double loc = cross_product(x1, y1, x2, y2, x3, y3);
|
||||
if(fabs(loc) > intersection_epsilon)
|
||||
{
|
||||
if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0)
|
||||
{
|
||||
d = -d;
|
||||
}
|
||||
calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1);
|
||||
calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
|
||||
calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
|
||||
}
|
||||
*x++ = x1 + dx1; *y++ = y1 - dy1;
|
||||
*x++ = x2 + dx1; *y++ = y2 - dy1;
|
||||
*x++ = x2 + dx2; *y++ = y2 - dy2;
|
||||
*x++ = x3 + dx2; *y++ = y3 - dy2;
|
||||
*x++ = x3 + dx3; *y++ = y3 - dy3;
|
||||
*x++ = x1 + dx3; *y++ = y1 - dy3;
|
||||
}
|
||||
|
||||
//------------------------------------------------------calc_triangle_area
|
||||
AGG_INLINE double calc_triangle_area(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3)
|
||||
{
|
||||
return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------calc_polygon_area
|
||||
template<class Storage> double calc_polygon_area(const Storage& st)
|
||||
{
|
||||
unsigned i;
|
||||
double sum = 0.0;
|
||||
double x = st[0].x;
|
||||
double y = st[0].y;
|
||||
double xs = x;
|
||||
double ys = y;
|
||||
|
||||
for(i = 1; i < st.size(); i++)
|
||||
{
|
||||
const typename Storage::value_type& v = st[i];
|
||||
sum += x * v.y - y * v.x;
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
}
|
||||
return (sum + x * ys - y * xs) * 0.5;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Tables for fast sqrt
|
||||
extern int16u g_sqrt_table[1024];
|
||||
extern int8 g_elder_bit_table[256];
|
||||
|
||||
|
||||
//---------------------------------------------------------------fast_sqrt
|
||||
//Fast integer Sqrt - really fast: no cycles, divisions or multiplications
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4035) //Disable warning "no return value"
|
||||
#endif
|
||||
AGG_INLINE unsigned fast_sqrt(unsigned val)
|
||||
{
|
||||
#if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
|
||||
//For Ix86 family processors this assembler code is used.
|
||||
//The key command here is bsr - determination the number of the most
|
||||
//significant bit of the value. For other processors
|
||||
//(and maybe compilers) the pure C "#else" section is used.
|
||||
__asm
|
||||
{
|
||||
mov ebx, val
|
||||
mov edx, 11
|
||||
bsr ecx, ebx
|
||||
sub ecx, 9
|
||||
jle less_than_9_bits
|
||||
shr ecx, 1
|
||||
adc ecx, 0
|
||||
sub edx, ecx
|
||||
shl ecx, 1
|
||||
shr ebx, cl
|
||||
less_than_9_bits:
|
||||
xor eax, eax
|
||||
mov ax, g_sqrt_table[ebx*2]
|
||||
mov ecx, edx
|
||||
shr eax, cl
|
||||
}
|
||||
#else
|
||||
|
||||
//This code is actually pure C and portable to most
|
||||
//arcitectures including 64bit ones.
|
||||
unsigned t = val;
|
||||
int bit=0;
|
||||
unsigned shift = 11;
|
||||
|
||||
//The following piece of code is just an emulation of the
|
||||
//Ix86 assembler command "bsr" (see above). However on old
|
||||
//Intels (like Intel MMX 233MHz) this code is about twice
|
||||
//faster (sic!) then just one "bsr". On PIII and PIV the
|
||||
//bsr is optimized quite well.
|
||||
bit = t >> 24;
|
||||
if(bit)
|
||||
{
|
||||
bit = g_elder_bit_table[bit] + 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit = (t >> 16) & 0xFF;
|
||||
if(bit)
|
||||
{
|
||||
bit = g_elder_bit_table[bit] + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit = (t >> 8) & 0xFF;
|
||||
if(bit)
|
||||
{
|
||||
bit = g_elder_bit_table[bit] + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit = g_elder_bit_table[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//This is calculation sqrt itself.
|
||||
bit -= 9;
|
||||
if(bit > 0)
|
||||
{
|
||||
bit = (bit >> 1) + (bit & 1);
|
||||
shift -= bit;
|
||||
val >>= (bit << 1);
|
||||
}
|
||||
return g_sqrt_table[val] >> shift;
|
||||
#endif
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------besj
|
||||
// Function BESJ calculates Bessel function of first kind of order n
|
||||
// Arguments:
|
||||
// n - an integer (>=0), the order
|
||||
// x - value at which the Bessel function is required
|
||||
//--------------------
|
||||
// C++ Mathematical Library
|
||||
// Convereted from equivalent FORTRAN library
|
||||
// Converetd by Gareth Walker for use by course 392 computational project
|
||||
// All functions tested and yield the same results as the corresponding
|
||||
// FORTRAN versions.
|
||||
//
|
||||
// If you have any problems using these functions please report them to
|
||||
// M.Muldoon@UMIST.ac.uk
|
||||
//
|
||||
// Documentation available on the web
|
||||
// http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
|
||||
// Version 1.0 8/98
|
||||
// 29 October, 1999
|
||||
//--------------------
|
||||
// Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
|
||||
//------------------------------------------------------------------------
|
||||
inline double besj(double x, int n)
|
||||
{
|
||||
if(n < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
double d = 1E-6;
|
||||
double b = 0;
|
||||
if(fabs(x) <= d)
|
||||
{
|
||||
if(n != 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
double b1 = 0; // b1 is the value from the previous iteration
|
||||
// Set up a starting order for recurrence
|
||||
int m1 = (int)fabs(x) + 6;
|
||||
if(fabs(x) > 5)
|
||||
{
|
||||
m1 = (int)(fabs(1.4 * x + 60 / x));
|
||||
}
|
||||
int m2 = (int)(n + 2 + fabs(x) / 4);
|
||||
if (m1 > m2)
|
||||
{
|
||||
m2 = m1;
|
||||
}
|
||||
|
||||
// Apply recurrence down from curent max order
|
||||
for(;;)
|
||||
{
|
||||
double c3 = 0;
|
||||
double c2 = 1E-30;
|
||||
double c4 = 0;
|
||||
int m8 = 1;
|
||||
if (m2 / 2 * 2 == m2)
|
||||
{
|
||||
m8 = -1;
|
||||
}
|
||||
int imax = m2 - 2;
|
||||
for (int i = 1; i <= imax; i++)
|
||||
{
|
||||
double c6 = 2 * (m2 - i) * c2 / x - c3;
|
||||
c3 = c2;
|
||||
c2 = c6;
|
||||
if(m2 - i - 1 == n)
|
||||
{
|
||||
b = c6;
|
||||
}
|
||||
m8 = -1 * m8;
|
||||
if (m8 > 0)
|
||||
{
|
||||
c4 = c4 + 2 * c6;
|
||||
}
|
||||
}
|
||||
double c6 = 2 * c2 / x - c3;
|
||||
if(n == 0)
|
||||
{
|
||||
b = c6;
|
||||
}
|
||||
c4 += c6;
|
||||
b /= c4;
|
||||
if(fabs(b - b1) < d)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
b1 = b;
|
||||
m2 += 3;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
384
agg/include/agg_math_stroke.h
Normal file
384
agg/include/agg_math_stroke.h
Normal file
|
@ -0,0 +1,384 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Stroke math
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_STROKE_MATH_INCLUDED
|
||||
#define AGG_STROKE_MATH_INCLUDED
|
||||
|
||||
#include "agg_math.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-------------------------------------------------------------line_cap_e
|
||||
enum line_cap_e
|
||||
{
|
||||
butt_cap,
|
||||
square_cap,
|
||||
round_cap
|
||||
};
|
||||
|
||||
//------------------------------------------------------------line_join_e
|
||||
enum line_join_e
|
||||
{
|
||||
miter_join = 0,
|
||||
miter_join_revert = 1,
|
||||
miter_join_round = 4,
|
||||
round_join = 2,
|
||||
bevel_join = 3
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------inner_join_e
|
||||
enum inner_join_e
|
||||
{
|
||||
inner_bevel,
|
||||
inner_miter,
|
||||
inner_jag,
|
||||
inner_round
|
||||
};
|
||||
|
||||
// Minimal angle to calculate round joins, less than 0.1 degree.
|
||||
const double stroke_theta = 0.001; //----stroke_theta
|
||||
|
||||
//--------------------------------------------------------stroke_calc_arc
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_arc(VertexConsumer& out_vertices,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double width,
|
||||
double approximation_scale)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
double a1 = atan2(dy1, dx1);
|
||||
double a2 = atan2(dy2, dx2);
|
||||
double da = a1 - a2;
|
||||
|
||||
// Possible optimization. Not important at all; consumes time but happens rarely
|
||||
//if(fabs(da) < stroke_theta)
|
||||
//{
|
||||
// out_vertices.add(coord_type((x + x + dx1 + dx2) * 0.5,
|
||||
// (y + y + dy1 + dy2) * 0.5));
|
||||
// return;
|
||||
//}
|
||||
|
||||
bool ccw = da > 0.0 && da < pi;
|
||||
|
||||
if(width < 0) width = -width;
|
||||
da = acos(width / (width + 0.125 / approximation_scale)) * 2;
|
||||
|
||||
out_vertices.add(coord_type(x + dx1, y + dy1));
|
||||
if(!ccw)
|
||||
{
|
||||
if(a1 > a2) a2 += 2 * pi;
|
||||
a2 -= da / 4;
|
||||
a1 += da;
|
||||
while(a1 < a2)
|
||||
{
|
||||
out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width));
|
||||
a1 += da;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(a1 < a2) a2 -= 2 * pi;
|
||||
a2 += da / 4;
|
||||
a1 -= da;
|
||||
while(a1 > a2)
|
||||
{
|
||||
out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width));
|
||||
a1 -= da;
|
||||
}
|
||||
}
|
||||
out_vertices.add(coord_type(x + dx2, y + dy2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------stroke_calc_miter
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_miter(VertexConsumer& out_vertices,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double width,
|
||||
line_join_e line_join,
|
||||
double miter_limit,
|
||||
double approximation_scale)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
double xi = v1.x;
|
||||
double yi = v1.y;
|
||||
bool miter_limit_exceeded = true; // Assume the worst
|
||||
|
||||
if(calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
v1.x + dx2, v1.y - dy2,
|
||||
v2.x + dx2, v2.y - dy2,
|
||||
&xi, &yi))
|
||||
{
|
||||
// Calculation of the intersection succeeded
|
||||
//---------------------
|
||||
double d1 = calc_distance(v1.x, v1.y, xi, yi);
|
||||
double lim = width * miter_limit;
|
||||
if(d1 <= lim)
|
||||
{
|
||||
// Inside the miter limit
|
||||
//---------------------
|
||||
out_vertices.add(coord_type(xi, yi));
|
||||
miter_limit_exceeded = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculation of the intersection failed, most probably
|
||||
// the three points lie one straight line.
|
||||
// First check if v0 and v2 lie on the opposite sides of vector:
|
||||
// (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
|
||||
// to the line determined by vertices v0 and v1.
|
||||
// This condition determines whether the next line segments continues
|
||||
// the previous one or goes back.
|
||||
//----------------
|
||||
double x2 = v1.x + dx1;
|
||||
double y2 = v1.y - dy1;
|
||||
if(((x2 - v0.x)*dy1 - (v0.y - y2)*dx1 < 0.0) !=
|
||||
((x2 - v2.x)*dy1 - (v2.y - y2)*dx1 < 0.0))
|
||||
{
|
||||
// This case means that the next segment continues
|
||||
// the previous one (straight line)
|
||||
//-----------------
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
miter_limit_exceeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(miter_limit_exceeded)
|
||||
{
|
||||
// Miter limit exceeded
|
||||
//------------------------
|
||||
switch(line_join)
|
||||
{
|
||||
case miter_join_revert:
|
||||
// For the compatibility with SVG, PDF, etc,
|
||||
// we use a simple bevel join instead of
|
||||
// "smart" bevel
|
||||
//-------------------
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
break;
|
||||
|
||||
case miter_join_round:
|
||||
stroke_calc_arc(out_vertices,
|
||||
v1.x, v1.y, dx1, -dy1, dx2, -dy2,
|
||||
width, approximation_scale);
|
||||
break;
|
||||
|
||||
default:
|
||||
// If no miter-revert, calculate new dx1, dy1, dx2, dy2
|
||||
//----------------
|
||||
out_vertices.add(coord_type(v1.x + dx1 + dy1 * miter_limit,
|
||||
v1.y - dy1 + dx1 * miter_limit));
|
||||
out_vertices.add(coord_type(v1.x + dx2 - dy2 * miter_limit,
|
||||
v1.y - dy2 - dx2 * miter_limit));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------stroke_calc_cap
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_cap(VertexConsumer& out_vertices,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len,
|
||||
line_cap_e line_cap,
|
||||
double width,
|
||||
double approximation_scale)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
out_vertices.remove_all();
|
||||
|
||||
double dx1 = (v1.y - v0.y) / len;
|
||||
double dy1 = (v1.x - v0.x) / len;
|
||||
double dx2 = 0;
|
||||
double dy2 = 0;
|
||||
|
||||
dx1 *= width;
|
||||
dy1 *= width;
|
||||
|
||||
if(line_cap != round_cap)
|
||||
{
|
||||
if(line_cap == square_cap)
|
||||
{
|
||||
dx2 = dy1;
|
||||
dy2 = dx1;
|
||||
}
|
||||
out_vertices.add(coord_type(v0.x - dx1 - dx2, v0.y + dy1 - dy2));
|
||||
out_vertices.add(coord_type(v0.x + dx1 - dx2, v0.y - dy1 - dy2));
|
||||
}
|
||||
else
|
||||
{
|
||||
double a1 = atan2(dy1, -dx1);
|
||||
double a2 = a1 + pi;
|
||||
double da = acos(width / (width + 0.125 / approximation_scale)) * 2;
|
||||
out_vertices.add(coord_type(v0.x - dx1, v0.y + dy1));
|
||||
a1 += da;
|
||||
a2 -= da/4;
|
||||
while(a1 < a2)
|
||||
{
|
||||
out_vertices.add(coord_type(v0.x + cos(a1) * width,
|
||||
v0.y + sin(a1) * width));
|
||||
a1 += da;
|
||||
}
|
||||
out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------stroke_calc_join
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_join(VertexConsumer& out_vertices,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1,
|
||||
double len2,
|
||||
double width,
|
||||
line_join_e line_join,
|
||||
inner_join_e inner_join,
|
||||
double miter_limit,
|
||||
double inner_miter_limit,
|
||||
double approximation_scale)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
double dx1, dy1, dx2, dy2;
|
||||
|
||||
dx1 = width * (v1.y - v0.y) / len1;
|
||||
dy1 = width * (v1.x - v0.x) / len1;
|
||||
|
||||
dx2 = width * (v2.y - v1.y) / len2;
|
||||
dy2 = width * (v2.x - v1.x) / len2;
|
||||
|
||||
out_vertices.remove_all();
|
||||
|
||||
if(cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y) > 0)
|
||||
{
|
||||
// Inner join
|
||||
//---------------
|
||||
switch(inner_join)
|
||||
{
|
||||
default: // inner_bevel
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
break;
|
||||
|
||||
case inner_miter:
|
||||
stroke_calc_miter(out_vertices,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
width,
|
||||
miter_join_revert,
|
||||
inner_miter_limit,
|
||||
1.0);
|
||||
break;
|
||||
|
||||
case inner_jag:
|
||||
case inner_round:
|
||||
{
|
||||
double d = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
|
||||
if(d < len1 * len1 && d < len2 * len2)
|
||||
{
|
||||
stroke_calc_miter(out_vertices,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
width,
|
||||
miter_join_revert,
|
||||
inner_miter_limit,
|
||||
1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(inner_join == inner_jag)
|
||||
{
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x, v1.y ));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
}
|
||||
else
|
||||
{
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x, v1.y ));
|
||||
stroke_calc_arc(out_vertices,
|
||||
v1.x, v1.y, dx2, -dy2, dx1, -dy1,
|
||||
width, approximation_scale);
|
||||
out_vertices.add(coord_type(v1.x, v1.y ));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outer join
|
||||
//---------------
|
||||
switch(line_join)
|
||||
{
|
||||
case miter_join:
|
||||
case miter_join_revert:
|
||||
case miter_join_round:
|
||||
stroke_calc_miter(out_vertices,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
width,
|
||||
line_join,
|
||||
miter_limit,
|
||||
approximation_scale);
|
||||
break;
|
||||
|
||||
case round_join:
|
||||
stroke_calc_arc(out_vertices,
|
||||
v1.x, v1.y, dx1, -dy1, dx2, -dy2,
|
||||
width, approximation_scale);
|
||||
break;
|
||||
|
||||
default: // Bevel join
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
65
agg/include/agg_path_length.h
Normal file
65
agg/include/agg_path_length.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_PATH_LENGTH_INCLUDED
|
||||
#define AGG_PATH_LENGTH_INCLUDED
|
||||
|
||||
#include "agg_math.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
template<class VertexSource>
|
||||
double path_length(VertexSource& vs, unsigned path_id = 0)
|
||||
{
|
||||
double len = 0.0;
|
||||
double start_x = 0.0;
|
||||
double start_y = 0.0;
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double x2 = 0.0;
|
||||
double y2 = 0.0;
|
||||
bool first = true;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
while(!is_stop(cmd = vs.vertex(&x2, &y2)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first || is_move_to(cmd))
|
||||
{
|
||||
start_x = x2;
|
||||
start_y = y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += calc_distance(x1, y1, x2, y2);
|
||||
}
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_close(cmd) && !first)
|
||||
{
|
||||
len += calc_distance(x1, y1, start_x, start_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
1478
agg/include/agg_path_storage.h
Normal file
1478
agg/include/agg_path_storage.h
Normal file
File diff suppressed because it is too large
Load diff
295
agg/include/agg_path_storage_integer.h
Normal file
295
agg/include/agg_path_storage_integer.h
Normal file
|
@ -0,0 +1,295 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED
|
||||
#define AGG_PATH_STORAGE_INTEGER_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//---------------------------------------------------------vertex_integer
|
||||
template<class T, unsigned CoordShift=6> struct vertex_integer
|
||||
{
|
||||
enum path_cmd
|
||||
{
|
||||
cmd_move_to = 0,
|
||||
cmd_line_to = 1,
|
||||
cmd_curve3 = 2,
|
||||
cmd_curve4 = 3
|
||||
};
|
||||
|
||||
enum coord_scale_e
|
||||
{
|
||||
coord_shift = CoordShift,
|
||||
coord_scale = 1 << coord_shift
|
||||
};
|
||||
|
||||
T x,y;
|
||||
vertex_integer() {}
|
||||
vertex_integer(T x_, T y_, unsigned flag) :
|
||||
x(((x_ << 1) & ~1) | (flag & 1)),
|
||||
y(((y_ << 1) & ~1) | (flag >> 1)) {}
|
||||
|
||||
unsigned vertex(double* x_, double* y_,
|
||||
double dx=0, double dy=0,
|
||||
double scale=1.0) const
|
||||
{
|
||||
*x_ = dx + (double(x >> 1) / coord_scale) * scale;
|
||||
*y_ = dy + (double(y >> 1) / coord_scale) * scale;
|
||||
switch(((y & 1) << 1) | (x & 1))
|
||||
{
|
||||
case cmd_move_to: return path_cmd_move_to;
|
||||
case cmd_line_to: return path_cmd_line_to;
|
||||
case cmd_curve3: return path_cmd_curve3;
|
||||
case cmd_curve4: return path_cmd_curve4;
|
||||
}
|
||||
return path_cmd_stop;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------path_storage_integer
|
||||
template<class T, unsigned CoordShift=6> class path_storage_integer
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef vertex_integer<T, CoordShift> vertex_integer_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void remove_all() { m_storage.remove_all(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(T x, T y)
|
||||
{
|
||||
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line_to(T x, T y)
|
||||
{
|
||||
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void curve3(T x_ctrl, T y_ctrl,
|
||||
T x_to, T y_to)
|
||||
{
|
||||
m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3));
|
||||
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void curve4(T x_ctrl1, T y_ctrl1,
|
||||
T x_ctrl2, T y_ctrl2,
|
||||
T x_to, T y_to)
|
||||
{
|
||||
m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4));
|
||||
m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4));
|
||||
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void close_polygon() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned size() const { return m_storage.size(); }
|
||||
unsigned vertex(unsigned idx, double* x, double* y) const
|
||||
{
|
||||
return m_storage[idx].vertex(x, y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); }
|
||||
void serialize(int8u* ptr) const
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_storage.size(); i++)
|
||||
{
|
||||
memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
|
||||
ptr += sizeof(vertex_integer_type);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_vertex_idx = 0;
|
||||
m_closed = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_storage.size() < 2 || m_vertex_idx > m_storage.size())
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
return path_cmd_stop;
|
||||
}
|
||||
if(m_vertex_idx == m_storage.size())
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
++m_vertex_idx;
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
unsigned cmd = m_storage[m_vertex_idx].vertex(x, y);
|
||||
if(is_move_to(cmd) && !m_closed)
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
m_closed = true;
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
m_closed = false;
|
||||
++m_vertex_idx;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rect_d bounding_rect() const
|
||||
{
|
||||
rect_d bounds(1e100, 1e100, -1e100, -1e100);
|
||||
if(m_storage.size() == 0)
|
||||
{
|
||||
bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_storage.size(); i++)
|
||||
{
|
||||
double x, y;
|
||||
m_storage[i].vertex(&x, &y);
|
||||
if(x < bounds.x1) bounds.x1 = x;
|
||||
if(y < bounds.y1) bounds.y1 = y;
|
||||
if(x > bounds.x2) bounds.x2 = x;
|
||||
if(y > bounds.y2) bounds.y2 = y;
|
||||
}
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
private:
|
||||
pod_bvector<vertex_integer_type, 6> m_storage;
|
||||
unsigned m_vertex_idx;
|
||||
bool m_closed;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------serialized_integer_path_adaptor
|
||||
template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
|
||||
{
|
||||
public:
|
||||
typedef vertex_integer<T, CoordShift> vertex_integer_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
serialized_integer_path_adaptor() :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_ptr(0),
|
||||
m_dx(0.0),
|
||||
m_dy(0.0),
|
||||
m_scale(1.0),
|
||||
m_vertices(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
serialized_integer_path_adaptor(const int8u* data, unsigned size,
|
||||
double dx, double dy) :
|
||||
m_data(data),
|
||||
m_end(data + size),
|
||||
m_ptr(data),
|
||||
m_dx(dx),
|
||||
m_dy(dy),
|
||||
m_vertices(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(const int8u* data, unsigned size,
|
||||
double dx, double dy, double scale=1.0)
|
||||
{
|
||||
m_data = data;
|
||||
m_end = data + size;
|
||||
m_ptr = data;
|
||||
m_dx = dx;
|
||||
m_dy = dy;
|
||||
m_scale = scale;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_ptr = m_data;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_data == 0 || m_ptr > m_end)
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
if(m_ptr == m_end)
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
m_ptr += sizeof(vertex_integer_type);
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
|
||||
vertex_integer_type v;
|
||||
memcpy(&v, m_ptr, sizeof(vertex_integer_type));
|
||||
unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
|
||||
if(is_move_to(cmd) && m_vertices > 2)
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
m_vertices = 0;
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
++m_vertices;
|
||||
m_ptr += sizeof(vertex_integer_type);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_data;
|
||||
const int8u* m_end;
|
||||
const int8u* m_ptr;
|
||||
double m_dx;
|
||||
double m_dy;
|
||||
double m_scale;
|
||||
unsigned m_vertices;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
122
agg/include/agg_pattern_filters_rgba.h
Normal file
122
agg/include/agg_pattern_filters_rgba.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_PATTERN_FILTERS_RGBA8_INCLUDED
|
||||
#define AGG_PATTERN_FILTERS_RGBA8_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_line_aa_basics.h"
|
||||
#include "agg_color_rgba.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================pattern_filter_nn
|
||||
template<class ColorT> struct pattern_filter_nn
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
static unsigned dilation() { return 0; }
|
||||
|
||||
static void AGG_INLINE pixel_low_res(color_type const* const* buf,
|
||||
color_type* p, int x, int y)
|
||||
{
|
||||
*p = buf[y][x];
|
||||
}
|
||||
|
||||
static void AGG_INLINE pixel_high_res(color_type const* const* buf,
|
||||
color_type* p, int x, int y)
|
||||
{
|
||||
*p = buf[y >> line_subpixel_shift]
|
||||
[x >> line_subpixel_shift];
|
||||
}
|
||||
};
|
||||
|
||||
typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
|
||||
typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16;
|
||||
|
||||
|
||||
//===========================================pattern_filter_bilinear_rgba
|
||||
template<class ColorT> struct pattern_filter_bilinear_rgba
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
|
||||
|
||||
static unsigned dilation() { return 1; }
|
||||
|
||||
static AGG_INLINE void pixel_low_res(color_type const* const* buf,
|
||||
color_type* p, int x, int y)
|
||||
{
|
||||
*p = buf[y][x];
|
||||
}
|
||||
|
||||
static AGG_INLINE void pixel_high_res(color_type const* const* buf,
|
||||
color_type* p, int x, int y)
|
||||
{
|
||||
calc_type r, g, b, a;
|
||||
r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2;
|
||||
|
||||
calc_type weight;
|
||||
int x_lr = x >> line_subpixel_shift;
|
||||
int y_lr = y >> line_subpixel_shift;
|
||||
|
||||
x &= line_subpixel_mask;
|
||||
y &= line_subpixel_mask;
|
||||
const color_type* ptr = buf[y_lr] + x_lr;
|
||||
|
||||
weight = (line_subpixel_scale - x) *
|
||||
(line_subpixel_scale - y);
|
||||
r += weight * ptr->r;
|
||||
g += weight * ptr->g;
|
||||
b += weight * ptr->b;
|
||||
a += weight * ptr->a;
|
||||
|
||||
++ptr;
|
||||
|
||||
weight = x * (line_subpixel_scale - y);
|
||||
r += weight * ptr->r;
|
||||
g += weight * ptr->g;
|
||||
b += weight * ptr->b;
|
||||
a += weight * ptr->a;
|
||||
|
||||
ptr = buf[y_lr + 1] + x_lr;
|
||||
|
||||
weight = (line_subpixel_scale - x) * y;
|
||||
r += weight * ptr->r;
|
||||
g += weight * ptr->g;
|
||||
b += weight * ptr->b;
|
||||
a += weight * ptr->a;
|
||||
|
||||
++ptr;
|
||||
|
||||
weight = x * y;
|
||||
r += weight * ptr->r;
|
||||
g += weight * ptr->g;
|
||||
b += weight * ptr->b;
|
||||
a += weight * ptr->a;
|
||||
|
||||
p->r = (value_type)(r >> line_subpixel_shift * 2);
|
||||
p->g = (value_type)(g >> line_subpixel_shift * 2);
|
||||
p->b = (value_type)(b >> line_subpixel_shift * 2);
|
||||
p->a = (value_type)(a >> line_subpixel_shift * 2);
|
||||
}
|
||||
};
|
||||
|
||||
typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8;
|
||||
typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16;
|
||||
}
|
||||
|
||||
#endif
|
232
agg/include/agg_pixfmt_amask_adaptor.h
Normal file
232
agg/include/agg_pixfmt_amask_adaptor.h
Normal file
|
@ -0,0 +1,232 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
|
||||
#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//==================================================pixfmt_amask_adaptor
|
||||
template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::row_data row_data;
|
||||
typedef AlphaMask amask_type;
|
||||
typedef typename amask_type::cover_type cover_type;
|
||||
|
||||
private:
|
||||
enum span_extra_tail_e { span_extra_tail = 256 };
|
||||
|
||||
void realloc_span(unsigned len)
|
||||
{
|
||||
if(len > m_max_len)
|
||||
{
|
||||
delete [] m_span;
|
||||
m_span = new cover_type[m_max_len = len + span_extra_tail];
|
||||
}
|
||||
}
|
||||
|
||||
void init_span(unsigned len)
|
||||
{
|
||||
realloc_span(len);
|
||||
|
||||
// ATTN! May work incorrectly if cover_type is more that one byte
|
||||
memset(m_span, amask_type::cover_full, len * sizeof(cover_type));
|
||||
}
|
||||
|
||||
void init_span(unsigned len, const cover_type* covers)
|
||||
{
|
||||
realloc_span(len);
|
||||
memcpy(m_span, covers, len * sizeof(cover_type));
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
~pixfmt_amask_adaptor() { delete [] m_span; }
|
||||
|
||||
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) :
|
||||
m_pixf(&pixf), m_mask(&mask), m_span(0), m_max_len(0)
|
||||
{}
|
||||
|
||||
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
|
||||
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_pixf->width(); }
|
||||
unsigned height() const { return m_pixf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
{
|
||||
return m_pixf->pixel(x, y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||
{
|
||||
m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_hspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
cover_type cover)
|
||||
{
|
||||
init_span(len);
|
||||
m_mask->combine_hspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_vspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
cover_type cover)
|
||||
{
|
||||
init_span(len);
|
||||
m_mask->combine_vspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_from(const rendering_buffer& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const cover_type* covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_hspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const cover_type* covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_vspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_hspan(x, y, m_span, len);
|
||||
m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover_full);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
if(covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_hspan(x, y, m_span, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_hspan(x, y, m_span, len);
|
||||
}
|
||||
m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
if(covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_vspan(x, y, m_span, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_vspan(x, y, m_span, len);
|
||||
}
|
||||
m_pixf->blend_color_vspan(x, y, len, colors, m_span, cover);
|
||||
}
|
||||
|
||||
private:
|
||||
pixfmt_type* m_pixf;
|
||||
const amask_type* m_mask;
|
||||
|
||||
cover_type* m_span;
|
||||
unsigned m_max_len;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
584
agg/include/agg_pixfmt_gray.h
Normal file
584
agg/include/agg_pixfmt_gray.h
Normal file
|
@ -0,0 +1,584 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PIXFMT_GRAY_INCLUDED
|
||||
#define AGG_PIXFMT_GRAY_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_gray.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//============================================================blender_gray
|
||||
template<class ColorT> struct blender_gray
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha, unsigned cover=0)
|
||||
{
|
||||
*p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//======================================================blender_gray_pre
|
||||
template<class ColorT> struct blender_gray_pre
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha, unsigned cover)
|
||||
{
|
||||
alpha = color_type::base_mask - alpha;
|
||||
cover = (cover + 1) << (base_shift - 8);
|
||||
*p = (value_type)((*p * alpha + cv * cover) >> base_shift);
|
||||
}
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha)
|
||||
{
|
||||
*p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================================apply_gamma_dir_gray
|
||||
template<class ColorT, class GammaLut> class apply_gamma_dir_gray
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
*p = m_gamma.dir(*p);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================================apply_gamma_inv_gray
|
||||
template<class ColorT, class GammaLut> class apply_gamma_inv_gray
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
*p = m_gamma.inv(*p);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=================================================pixfmt_alpha_blend_gray
|
||||
template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0>
|
||||
class pixfmt_alpha_blend_gray
|
||||
{
|
||||
public:
|
||||
typedef RenBuf rbuf_type;
|
||||
typedef typename rbuf_type::row_data row_data;
|
||||
typedef Blender blender_type;
|
||||
typedef typename blender_type::color_type color_type;
|
||||
typedef int order_type; // A fake one
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_scale = color_type::base_scale,
|
||||
base_mask = color_type::base_mask,
|
||||
pix_width = sizeof(value_type)
|
||||
};
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
static AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c,
|
||||
unsigned cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, c.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_alpha_blend_gray(rbuf_type& rb) :
|
||||
m_rbuf(&rb)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row_ptr(int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data row(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row(y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
|
||||
{
|
||||
*(value_type*)p = c.v;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type pixel(int x, int y) const
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset;
|
||||
return color_type(*p);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
*((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
copy_or_blend_pix((value_type*)
|
||||
m_rbuf->row_ptr(x, y, 1) + x * Step + Offset,
|
||||
c,
|
||||
cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
*p = c.v;
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
*p = c.v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
*p = c.v;
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p;
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
*p = c.v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, *covers);
|
||||
}
|
||||
p += Step;
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
do
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, *covers);
|
||||
}
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
*p++ = colors->v;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(colors->a == base_mask)
|
||||
{
|
||||
*p = colors->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_or_blend_pix(p, *colors);
|
||||
}
|
||||
p += Step;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
value_type* p;
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
if(colors->a == base_mask)
|
||||
{
|
||||
*p = colors->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_or_blend_pix(p, *colors);
|
||||
}
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Function> void for_each_pixel(Function f)
|
||||
{
|
||||
unsigned y;
|
||||
for(y = 0; y < height(); ++y)
|
||||
{
|
||||
row_data r = m_rbuf->row(y);
|
||||
if(r.ptr)
|
||||
{
|
||||
unsigned len = r.x2 - r.x1 + 1;
|
||||
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
f(p);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf2>
|
||||
void copy_from(const RenBuf2& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
const int8u* p = from.row_ptr(ysrc);
|
||||
if(p)
|
||||
{
|
||||
memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
|
||||
p + xsrc * pix_width,
|
||||
len * pix_width);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
};
|
||||
|
||||
typedef blender_gray<gray8> blender_gray8;
|
||||
typedef blender_gray_pre<gray8> blender_gray8_pre;
|
||||
typedef blender_gray<gray16> blender_gray16;
|
||||
typedef blender_gray_pre<gray16> blender_gray16_pre;
|
||||
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8; //----pixfmt_gray8
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre; //----pixfmt_gray8_pre
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16; //----pixfmt_gray16
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre
|
||||
}
|
||||
|
||||
#endif
|
||||
|
757
agg/include/agg_pixfmt_rgb.h
Normal file
757
agg/include/agg_pixfmt_rgb.h
Normal file
|
@ -0,0 +1,757 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PIXFMT_RGB_INCLUDED
|
||||
#define AGG_PIXFMT_RGB_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=====================================================apply_gamma_dir_rgb
|
||||
template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
p[Order::R] = m_gamma.dir(p[Order::R]);
|
||||
p[Order::G] = m_gamma.dir(p[Order::G]);
|
||||
p[Order::B] = m_gamma.dir(p[Order::B]);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================================apply_gamma_inv_rgb
|
||||
template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
p[Order::R] = m_gamma.inv(p[Order::R]);
|
||||
p[Order::G] = m_gamma.inv(p[Order::G]);
|
||||
p[Order::B] = m_gamma.inv(p[Order::B]);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
//=========================================================blender_rgb
|
||||
template<class ColorT, class Order> struct blender_rgb
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef Order order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned cr, unsigned cg, unsigned cb,
|
||||
unsigned alpha,
|
||||
unsigned cover=0)
|
||||
{
|
||||
p[Order::R] += (value_type)(((cr - p[Order::R]) * alpha) >> base_shift);
|
||||
p[Order::G] += (value_type)(((cg - p[Order::G]) * alpha) >> base_shift);
|
||||
p[Order::B] += (value_type)(((cb - p[Order::B]) * alpha) >> base_shift);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//======================================================blender_rgb_pre
|
||||
template<class ColorT, class Order> struct blender_rgb_pre
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef Order order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned cr, unsigned cg, unsigned cb,
|
||||
unsigned alpha,
|
||||
unsigned cover)
|
||||
{
|
||||
alpha = color_type::base_mask - alpha;
|
||||
cover = (cover + 1) << (base_shift - 8);
|
||||
p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift);
|
||||
p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift);
|
||||
p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned cr, unsigned cg, unsigned cb,
|
||||
unsigned alpha)
|
||||
{
|
||||
alpha = color_type::base_mask - alpha;
|
||||
p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr);
|
||||
p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg);
|
||||
p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//===================================================blender_rgb_gamma
|
||||
template<class ColorT, class Order, class Gamma> class blender_rgb_gamma
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
typedef Order order_type;
|
||||
typedef Gamma gamma_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
blender_rgb_gamma() : m_gamma(0) {}
|
||||
void gamma(const gamma_type& g) { m_gamma = &g; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned cr, unsigned cg, unsigned cb,
|
||||
unsigned alpha,
|
||||
unsigned cover=0)
|
||||
{
|
||||
calc_type r = m_gamma->dir(p[Order::R]);
|
||||
calc_type g = m_gamma->dir(p[Order::G]);
|
||||
calc_type b = m_gamma->dir(p[Order::B]);
|
||||
p[Order::R] = m_gamma->inv((((m_gamma->dir(cr) - r) * alpha) >> base_shift) + r);
|
||||
p[Order::G] = m_gamma->inv((((m_gamma->dir(cg) - g) * alpha) >> base_shift) + g);
|
||||
p[Order::B] = m_gamma->inv((((m_gamma->dir(cb) - b) * alpha) >> base_shift) + b);
|
||||
}
|
||||
|
||||
private:
|
||||
const gamma_type* m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//==================================================pixfmt_alpha_blend_rgb
|
||||
template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb
|
||||
{
|
||||
public:
|
||||
typedef RenBuf rbuf_type;
|
||||
typedef typename rbuf_type::row_data row_data;
|
||||
typedef Blender blender_type;
|
||||
typedef typename blender_type::color_type color_type;
|
||||
typedef typename blender_type::order_type order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_scale = color_type::base_scale,
|
||||
base_mask = color_type::base_mask,
|
||||
pix_width = sizeof(value_type) * 3
|
||||
};
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c,
|
||||
unsigned cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, c.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_alpha_blend_rgb(rbuf_type& rb) :
|
||||
m_rbuf(&rb)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
Blender& blender() { return m_blender; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row_ptr(int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data row(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row(y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
|
||||
{
|
||||
((value_type*)p)[order_type::R] = c.r;
|
||||
((value_type*)p)[order_type::G] = c.g;
|
||||
((value_type*)p)[order_type::B] = c.b;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type pixel(int x, int y) const
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(y) + x + x + x;
|
||||
return color_type(p[order_type::R],
|
||||
p[order_type::G],
|
||||
p[order_type::B]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x;
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
copy_or_blend_pix((value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x, c, cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
do
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p;
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
|
||||
do
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
|
||||
}
|
||||
p += 3;
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
|
||||
}
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
|
||||
do
|
||||
{
|
||||
p[order_type::R] = colors->r;
|
||||
p[order_type::G] = colors->g;
|
||||
p[order_type::B] = colors->b;
|
||||
++colors;
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
value_type* p;
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
copy_or_blend_pix(p, *colors++);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Function> void for_each_pixel(Function f)
|
||||
{
|
||||
unsigned y;
|
||||
for(y = 0; y < height(); ++y)
|
||||
{
|
||||
row_data r = m_rbuf->row(y);
|
||||
if(r.ptr)
|
||||
{
|
||||
unsigned len = r.x2 - r.x1 + 1;
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(r.x1, y, len) + r.x1 * 3;
|
||||
do
|
||||
{
|
||||
f(p);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf2>
|
||||
void copy_from(const RenBuf2& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
const int8u* p = from.row_ptr(ysrc);
|
||||
if(p)
|
||||
{
|
||||
memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
|
||||
p + xsrc * pix_width,
|
||||
len * pix_width);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::order_type src_order;
|
||||
|
||||
const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
psrc += xsrc * 4;
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
|
||||
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type alpha = psrc[src_order::A];
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
pdst[order_type::R] = psrc[src_order::R];
|
||||
pdst[order_type::G] = psrc[src_order::G];
|
||||
pdst[order_type::B] = psrc[src_order::B];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(pdst,
|
||||
psrc[src_order::R],
|
||||
psrc[src_order::G],
|
||||
psrc[src_order::B],
|
||||
alpha);
|
||||
}
|
||||
}
|
||||
psrc += 4;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
color_type color;
|
||||
do
|
||||
{
|
||||
color.r = psrc[src_order::R];
|
||||
color.g = psrc[src_order::G];
|
||||
color.b = psrc[src_order::B];
|
||||
color.a = psrc[src_order::A];
|
||||
copy_or_blend_pix(pdst, color, cover);
|
||||
psrc += 4;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
Blender m_blender;
|
||||
};
|
||||
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24; //----pixfmt_rgb24
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24; //----pixfmt_bgr24
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48; //----pixfmt_rgb48
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48; //----pixfmt_bgr48
|
||||
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48_pre; //----pixfmt_rgb48_pre
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48_pre; //----pixfmt_bgr48_pre
|
||||
|
||||
//-----------------------------------------------------pixfmt_rgb24_gamma
|
||||
template<class Gamma> class pixfmt_rgb24_gamma :
|
||||
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>
|
||||
{
|
||||
public:
|
||||
pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>(rb)
|
||||
{
|
||||
this->blender().gamma(g);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------pixfmt_bgr24_gamma
|
||||
template<class Gamma> class pixfmt_bgr24_gamma :
|
||||
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>
|
||||
{
|
||||
public:
|
||||
pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>(rb)
|
||||
{
|
||||
this->blender().gamma(g);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------pixfmt_rgb48_gamma
|
||||
template<class Gamma> class pixfmt_rgb48_gamma :
|
||||
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>
|
||||
{
|
||||
public:
|
||||
pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>(rb)
|
||||
{
|
||||
this->blender().gamma(g);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------pixfmt_bgr48_gamma
|
||||
template<class Gamma> class pixfmt_bgr48_gamma :
|
||||
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>
|
||||
{
|
||||
public:
|
||||
pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>(rb)
|
||||
{
|
||||
this->blender().gamma(g);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
1218
agg/include/agg_pixfmt_rgb_packed.h
Normal file
1218
agg/include/agg_pixfmt_rgb_packed.h
Normal file
File diff suppressed because it is too large
Load diff
2586
agg/include/agg_pixfmt_rgba.h
Normal file
2586
agg/include/agg_pixfmt_rgba.h
Normal file
File diff suppressed because it is too large
Load diff
726
agg/include/agg_rasterizer_cells_aa.h
Executable file
726
agg/include/agg_rasterizer_cells_aa.h
Executable file
|
@ -0,0 +1,726 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// The author gratefully acknowleges the support of David Turner,
|
||||
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
|
||||
// libray - in producing this work. See http://www.freetype.org for details.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_CELLS_AA_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "agg_math.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------rasterizer_cells_aa
|
||||
// An internal class that implements the main rasterization algorithm.
|
||||
// Used in the rasterizer. Should not be used direcly.
|
||||
template<class Cell> class rasterizer_cells_aa
|
||||
{
|
||||
enum cell_block_scale_e
|
||||
{
|
||||
cell_block_shift = 12,
|
||||
cell_block_size = 1 << cell_block_shift,
|
||||
cell_block_mask = cell_block_size - 1,
|
||||
cell_block_pool = 256,
|
||||
cell_block_limit = 1024
|
||||
};
|
||||
|
||||
struct sorted_y
|
||||
{
|
||||
unsigned start;
|
||||
unsigned num;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Cell cell_type;
|
||||
typedef rasterizer_cells_aa<Cell> self_type;
|
||||
|
||||
~rasterizer_cells_aa();
|
||||
rasterizer_cells_aa();
|
||||
|
||||
void reset();
|
||||
void style(const cell_type& style_cell);
|
||||
void line(int x1, int y1, int x2, int y2);
|
||||
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
void sort_cells();
|
||||
|
||||
unsigned total_cells() const
|
||||
{
|
||||
return m_num_cells;
|
||||
}
|
||||
|
||||
unsigned scanline_num_cells(unsigned y) const
|
||||
{
|
||||
return m_sorted_y[y - m_min_y].num;
|
||||
}
|
||||
|
||||
const cell_type* const* scanline_cells(unsigned y) const
|
||||
{
|
||||
return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start;
|
||||
}
|
||||
|
||||
bool sorted() const { return m_sorted; }
|
||||
|
||||
private:
|
||||
rasterizer_cells_aa(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
void set_curr_cell(int x, int y);
|
||||
void add_curr_cell();
|
||||
void render_hline(int ey, int x1, int y1, int x2, int y2);
|
||||
void allocate_block();
|
||||
|
||||
private:
|
||||
unsigned m_num_blocks;
|
||||
unsigned m_max_blocks;
|
||||
unsigned m_curr_block;
|
||||
unsigned m_num_cells;
|
||||
cell_type** m_cells;
|
||||
cell_type* m_curr_cell_ptr;
|
||||
pod_vector<cell_type*> m_sorted_cells;
|
||||
pod_vector<sorted_y> m_sorted_y;
|
||||
cell_type m_curr_cell;
|
||||
cell_type m_style_cell;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
bool m_sorted;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
rasterizer_cells_aa<Cell>::~rasterizer_cells_aa()
|
||||
{
|
||||
if(m_num_blocks)
|
||||
{
|
||||
cell_type** ptr = m_cells + m_num_blocks - 1;
|
||||
while(m_num_blocks--)
|
||||
{
|
||||
delete [] *ptr;
|
||||
ptr--;
|
||||
}
|
||||
delete [] m_cells;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
rasterizer_cells_aa<Cell>::rasterizer_cells_aa() :
|
||||
m_num_blocks(0),
|
||||
m_max_blocks(0),
|
||||
m_curr_block(0),
|
||||
m_num_cells(0),
|
||||
m_cells(0),
|
||||
m_curr_cell_ptr(0),
|
||||
m_sorted_cells(),
|
||||
m_sorted_y(),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF),
|
||||
m_sorted(false)
|
||||
{
|
||||
m_style_cell.initial();
|
||||
m_curr_cell.initial();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void rasterizer_cells_aa<Cell>::reset()
|
||||
{
|
||||
m_num_cells = 0;
|
||||
m_curr_block = 0;
|
||||
m_curr_cell.initial();
|
||||
m_style_cell.initial();
|
||||
m_sorted = false;
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
AGG_INLINE void rasterizer_cells_aa<Cell>::add_curr_cell()
|
||||
{
|
||||
if(m_curr_cell.area | m_curr_cell.cover)
|
||||
{
|
||||
if((m_num_cells & cell_block_mask) == 0)
|
||||
{
|
||||
if(m_num_blocks >= cell_block_limit) return;
|
||||
allocate_block();
|
||||
}
|
||||
*m_curr_cell_ptr++ = m_curr_cell;
|
||||
++m_num_cells;
|
||||
//if(m_curr_cell.x < m_min_x) m_min_x = m_curr_cell.x;
|
||||
//if(m_curr_cell.x > m_max_x) m_max_x = m_curr_cell.x;
|
||||
//if(m_curr_cell.y < m_min_y) m_min_y = m_curr_cell.y;
|
||||
//if(m_curr_cell.y > m_max_y) m_max_y = m_curr_cell.y;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
AGG_INLINE void rasterizer_cells_aa<Cell>::set_curr_cell(int x, int y)
|
||||
{
|
||||
if(m_curr_cell.not_equal(x, y, m_style_cell))
|
||||
{
|
||||
add_curr_cell();
|
||||
m_curr_cell.style(m_style_cell);
|
||||
m_curr_cell.x = x;
|
||||
m_curr_cell.y = y;
|
||||
m_curr_cell.cover = 0;
|
||||
m_curr_cell.area = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
AGG_INLINE void rasterizer_cells_aa<Cell>::render_hline(int ey,
|
||||
int x1, int y1,
|
||||
int x2, int y2)
|
||||
{
|
||||
int ex1 = x1 >> poly_subpixel_shift;
|
||||
int ex2 = x2 >> poly_subpixel_shift;
|
||||
int fx1 = x1 & poly_subpixel_mask;
|
||||
int fx2 = x2 & poly_subpixel_mask;
|
||||
|
||||
int delta, p, first, dx;
|
||||
int incr, lift, mod, rem;
|
||||
|
||||
//trivial case. Happens often
|
||||
if(y1 == y2)
|
||||
{
|
||||
set_curr_cell(ex2, ey);
|
||||
return;
|
||||
}
|
||||
|
||||
//everything is located in a single cell. That is easy!
|
||||
if(ex1 == ex2)
|
||||
{
|
||||
delta = y2 - y1;
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += (fx1 + fx2) * delta;
|
||||
return;
|
||||
}
|
||||
|
||||
//ok, we'll have to render a run of adjacent cells on the same
|
||||
//hline...
|
||||
p = (poly_subpixel_scale - fx1) * (y2 - y1);
|
||||
first = poly_subpixel_scale;
|
||||
incr = 1;
|
||||
|
||||
dx = x2 - x1;
|
||||
|
||||
if(dx < 0)
|
||||
{
|
||||
p = fx1 * (y2 - y1);
|
||||
first = 0;
|
||||
incr = -1;
|
||||
dx = -dx;
|
||||
}
|
||||
|
||||
delta = p / dx;
|
||||
mod = p % dx;
|
||||
|
||||
if(mod < 0)
|
||||
{
|
||||
delta--;
|
||||
mod += dx;
|
||||
}
|
||||
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += (fx1 + first) * delta;
|
||||
|
||||
ex1 += incr;
|
||||
set_curr_cell(ex1, ey);
|
||||
y1 += delta;
|
||||
|
||||
if(ex1 != ex2)
|
||||
{
|
||||
p = poly_subpixel_scale * (y2 - y1 + delta);
|
||||
lift = p / dx;
|
||||
rem = p % dx;
|
||||
|
||||
if (rem < 0)
|
||||
{
|
||||
lift--;
|
||||
rem += dx;
|
||||
}
|
||||
|
||||
mod -= dx;
|
||||
|
||||
while (ex1 != ex2)
|
||||
{
|
||||
delta = lift;
|
||||
mod += rem;
|
||||
if(mod >= 0)
|
||||
{
|
||||
mod -= dx;
|
||||
delta++;
|
||||
}
|
||||
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += poly_subpixel_scale * delta;
|
||||
y1 += delta;
|
||||
ex1 += incr;
|
||||
set_curr_cell(ex1, ey);
|
||||
}
|
||||
}
|
||||
delta = y2 - y1;
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
AGG_INLINE void rasterizer_cells_aa<Cell>::style(const cell_type& style_cell)
|
||||
{
|
||||
m_style_cell.style(style_cell);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void rasterizer_cells_aa<Cell>::line(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift };
|
||||
|
||||
int dx = x2 - x1;
|
||||
|
||||
if(dx >= dx_limit || dx <= -dx_limit)
|
||||
{
|
||||
int cx = (x1 + x2) >> 1;
|
||||
int cy = (y1 + y2) >> 1;
|
||||
line(x1, y1, cx, cy);
|
||||
line(cx, cy, x2, y2);
|
||||
}
|
||||
|
||||
int dy = y2 - y1;
|
||||
int ex1 = x1 >> poly_subpixel_shift;
|
||||
int ex2 = x2 >> poly_subpixel_shift;
|
||||
int ey1 = y1 >> poly_subpixel_shift;
|
||||
int ey2 = y2 >> poly_subpixel_shift;
|
||||
int fy1 = y1 & poly_subpixel_mask;
|
||||
int fy2 = y2 & poly_subpixel_mask;
|
||||
|
||||
int x_from, x_to;
|
||||
int p, rem, mod, lift, delta, first, incr;
|
||||
|
||||
if(ex1 < m_min_x) m_min_x = ex1;
|
||||
if(ex1 > m_max_x) m_max_x = ex1;
|
||||
if(ey1 < m_min_y) m_min_y = ey1;
|
||||
if(ey1 > m_max_y) m_max_y = ey1;
|
||||
if(ex2 < m_min_x) m_min_x = ex2;
|
||||
if(ex2 > m_max_x) m_max_x = ex2;
|
||||
if(ey2 < m_min_y) m_min_y = ey2;
|
||||
if(ey2 > m_max_y) m_max_y = ey2;
|
||||
|
||||
set_curr_cell(ex1, ey1);
|
||||
|
||||
//everything is on a single hline
|
||||
if(ey1 == ey2)
|
||||
{
|
||||
render_hline(ey1, x1, fy1, x2, fy2);
|
||||
return;
|
||||
}
|
||||
|
||||
//Vertical line - we have to calculate start and end cells,
|
||||
//and then - the common values of the area and coverage for
|
||||
//all cells of the line. We know exactly there's only one
|
||||
//cell, so, we don't have to call render_hline().
|
||||
incr = 1;
|
||||
if(dx == 0)
|
||||
{
|
||||
int ex = x1 >> poly_subpixel_shift;
|
||||
int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1;
|
||||
int area;
|
||||
|
||||
first = poly_subpixel_scale;
|
||||
if(dy < 0)
|
||||
{
|
||||
first = 0;
|
||||
incr = -1;
|
||||
}
|
||||
|
||||
x_from = x1;
|
||||
|
||||
//render_hline(ey1, x_from, fy1, x_from, first);
|
||||
delta = first - fy1;
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += two_fx * delta;
|
||||
|
||||
ey1 += incr;
|
||||
set_curr_cell(ex, ey1);
|
||||
|
||||
delta = first + first - poly_subpixel_scale;
|
||||
area = two_fx * delta;
|
||||
while(ey1 != ey2)
|
||||
{
|
||||
//render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first);
|
||||
m_curr_cell.cover = delta;
|
||||
m_curr_cell.area = area;
|
||||
ey1 += incr;
|
||||
set_curr_cell(ex, ey1);
|
||||
}
|
||||
//render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2);
|
||||
delta = fy2 - poly_subpixel_scale + first;
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += two_fx * delta;
|
||||
return;
|
||||
}
|
||||
|
||||
//ok, we have to render several hlines
|
||||
p = (poly_subpixel_scale - fy1) * dx;
|
||||
first = poly_subpixel_scale;
|
||||
|
||||
if(dy < 0)
|
||||
{
|
||||
p = fy1 * dx;
|
||||
first = 0;
|
||||
incr = -1;
|
||||
dy = -dy;
|
||||
}
|
||||
|
||||
delta = p / dy;
|
||||
mod = p % dy;
|
||||
|
||||
if(mod < 0)
|
||||
{
|
||||
delta--;
|
||||
mod += dy;
|
||||
}
|
||||
|
||||
x_from = x1 + delta;
|
||||
render_hline(ey1, x1, fy1, x_from, first);
|
||||
|
||||
ey1 += incr;
|
||||
set_curr_cell(x_from >> poly_subpixel_shift, ey1);
|
||||
|
||||
if(ey1 != ey2)
|
||||
{
|
||||
p = poly_subpixel_scale * dx;
|
||||
lift = p / dy;
|
||||
rem = p % dy;
|
||||
|
||||
if(rem < 0)
|
||||
{
|
||||
lift--;
|
||||
rem += dy;
|
||||
}
|
||||
mod -= dy;
|
||||
|
||||
while(ey1 != ey2)
|
||||
{
|
||||
delta = lift;
|
||||
mod += rem;
|
||||
if (mod >= 0)
|
||||
{
|
||||
mod -= dy;
|
||||
delta++;
|
||||
}
|
||||
|
||||
x_to = x_from + delta;
|
||||
render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first);
|
||||
x_from = x_to;
|
||||
|
||||
ey1 += incr;
|
||||
set_curr_cell(x_from >> poly_subpixel_shift, ey1);
|
||||
}
|
||||
}
|
||||
render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void rasterizer_cells_aa<Cell>::allocate_block()
|
||||
{
|
||||
if(m_curr_block >= m_num_blocks)
|
||||
{
|
||||
if(m_num_blocks >= m_max_blocks)
|
||||
{
|
||||
cell_type** new_cells = new cell_type* [m_max_blocks + cell_block_pool];
|
||||
if(m_cells)
|
||||
{
|
||||
memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*));
|
||||
delete [] m_cells;
|
||||
}
|
||||
m_cells = new_cells;
|
||||
m_max_blocks += cell_block_pool;
|
||||
}
|
||||
m_cells[m_num_blocks++] = new cell_type [unsigned(cell_block_size)];
|
||||
}
|
||||
m_curr_cell_ptr = m_cells[m_curr_block++];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <class T> static AGG_INLINE void swap_cells(T* a, T* b)
|
||||
{
|
||||
T temp = *a;
|
||||
*a = *b;
|
||||
*b = temp;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum
|
||||
{
|
||||
qsort_threshold = 9
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void qsort_cells(Cell** start, unsigned num)
|
||||
{
|
||||
Cell** stack[80];
|
||||
Cell*** top;
|
||||
Cell** limit;
|
||||
Cell** base;
|
||||
|
||||
limit = start + num;
|
||||
base = start;
|
||||
top = stack;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int len = int(limit - base);
|
||||
|
||||
Cell** i;
|
||||
Cell** j;
|
||||
Cell** pivot;
|
||||
|
||||
if(len > qsort_threshold)
|
||||
{
|
||||
// we use base + len/2 as the pivot
|
||||
pivot = base + len / 2;
|
||||
swap_cells(base, pivot);
|
||||
|
||||
i = base + 1;
|
||||
j = limit - 1;
|
||||
|
||||
// now ensure that *i <= *base <= *j
|
||||
if((*j)->x < (*i)->x)
|
||||
{
|
||||
swap_cells(i, j);
|
||||
}
|
||||
|
||||
if((*base)->x < (*i)->x)
|
||||
{
|
||||
swap_cells(base, i);
|
||||
}
|
||||
|
||||
if((*j)->x < (*base)->x)
|
||||
{
|
||||
swap_cells(base, j);
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int x = (*base)->x;
|
||||
do i++; while( (*i)->x < x );
|
||||
do j--; while( x < (*j)->x );
|
||||
|
||||
if(i > j)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
swap_cells(i, j);
|
||||
}
|
||||
|
||||
swap_cells(base, j);
|
||||
|
||||
// now, push the largest sub-array
|
||||
if(j - base > limit - i)
|
||||
{
|
||||
top[0] = base;
|
||||
top[1] = j;
|
||||
base = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
top[0] = i;
|
||||
top[1] = limit;
|
||||
limit = j;
|
||||
}
|
||||
top += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the sub-array is small, perform insertion sort
|
||||
j = base;
|
||||
i = j + 1;
|
||||
|
||||
for(; i < limit; j = i, i++)
|
||||
{
|
||||
for(; j[1]->x < (*j)->x; j--)
|
||||
{
|
||||
swap_cells(j + 1, j);
|
||||
if (j == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(top > stack)
|
||||
{
|
||||
top -= 2;
|
||||
base = top[0];
|
||||
limit = top[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void rasterizer_cells_aa<Cell>::sort_cells()
|
||||
{
|
||||
if(m_sorted) return; //Perform sort only the first time.
|
||||
|
||||
add_curr_cell();
|
||||
m_curr_cell.x = 0x7FFFFFFF;
|
||||
m_curr_cell.y = 0x7FFFFFFF;
|
||||
m_curr_cell.cover = 0;
|
||||
m_curr_cell.area = 0;
|
||||
|
||||
if(m_num_cells == 0) return;
|
||||
|
||||
// DBG: Check to see if min/max works well.
|
||||
//for(unsigned nc = 0; nc < m_num_cells; nc++)
|
||||
//{
|
||||
// cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask);
|
||||
// if(cell->x < m_min_x ||
|
||||
// cell->y < m_min_y ||
|
||||
// cell->x > m_max_x ||
|
||||
// cell->y > m_max_y)
|
||||
// {
|
||||
// cell = cell; // Breakpoint here
|
||||
// }
|
||||
//}
|
||||
|
||||
// Allocate the array of cell pointers
|
||||
m_sorted_cells.allocate(m_num_cells, 16);
|
||||
|
||||
// Allocate and zero the Y array
|
||||
m_sorted_y.allocate(m_max_y - m_min_y + 1, 16);
|
||||
m_sorted_y.zero();
|
||||
|
||||
// Create the Y-histogram (count the numbers of cells for each Y)
|
||||
cell_type** block_ptr = m_cells;
|
||||
cell_type* cell_ptr;
|
||||
unsigned nb = m_num_cells >> cell_block_shift;
|
||||
unsigned i;
|
||||
while(nb--)
|
||||
{
|
||||
cell_ptr = *block_ptr++;
|
||||
i = cell_block_size;
|
||||
while(i--)
|
||||
{
|
||||
m_sorted_y[cell_ptr->y - m_min_y].start++;
|
||||
++cell_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
cell_ptr = *block_ptr++;
|
||||
i = m_num_cells & cell_block_mask;
|
||||
while(i--)
|
||||
{
|
||||
m_sorted_y[cell_ptr->y - m_min_y].start++;
|
||||
++cell_ptr;
|
||||
}
|
||||
|
||||
// Convert the Y-histogram into the array of starting indexes
|
||||
unsigned start = 0;
|
||||
for(i = 0; i < m_sorted_y.size(); i++)
|
||||
{
|
||||
unsigned v = m_sorted_y[i].start;
|
||||
m_sorted_y[i].start = start;
|
||||
start += v;
|
||||
}
|
||||
|
||||
// Fill the cell pointer array sorted by Y
|
||||
block_ptr = m_cells;
|
||||
nb = m_num_cells >> cell_block_shift;
|
||||
while(nb--)
|
||||
{
|
||||
cell_ptr = *block_ptr++;
|
||||
i = cell_block_size;
|
||||
while(i--)
|
||||
{
|
||||
sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
|
||||
m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
|
||||
++curr_y.num;
|
||||
++cell_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
cell_ptr = *block_ptr++;
|
||||
i = m_num_cells & cell_block_mask;
|
||||
while(i--)
|
||||
{
|
||||
sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
|
||||
m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
|
||||
++curr_y.num;
|
||||
++cell_ptr;
|
||||
}
|
||||
|
||||
// Finally arrange the X-arrays
|
||||
for(i = 0; i < m_sorted_y.size(); i++)
|
||||
{
|
||||
const sorted_y& curr_y = m_sorted_y[i];
|
||||
if(curr_y.num)
|
||||
{
|
||||
qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num);
|
||||
}
|
||||
}
|
||||
m_sorted = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
531
agg/include/agg_rasterizer_compound_aa.h
Executable file
531
agg/include/agg_rasterizer_compound_aa.h
Executable file
|
@ -0,0 +1,531 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// The author gratefully acknowleges the support of David Turner,
|
||||
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
|
||||
// libray - in producing this work. See http://www.freetype.org for details.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_RASTERIZER_COMPOUND_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_COMPOUND_AA_INCLUDED
|
||||
|
||||
#include "agg_rasterizer_cells_aa.h"
|
||||
#include "agg_rasterizer_sl_clip.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------cell_style_aa
|
||||
// A pixel cell. There're no constructors defined and it was done
|
||||
// intentionally in order to avoid extra overhead when allocating an
|
||||
// array of cells.
|
||||
struct cell_style_aa
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int cover;
|
||||
int area;
|
||||
int16 left, right;
|
||||
|
||||
void initial()
|
||||
{
|
||||
x = 0x7FFFFFFF;
|
||||
y = 0x7FFFFFFF;
|
||||
cover = 0;
|
||||
area = 0;
|
||||
left = -1;
|
||||
right = -1;
|
||||
}
|
||||
|
||||
void style(const cell_style_aa& c)
|
||||
{
|
||||
left = c.left;
|
||||
right = c.right;
|
||||
}
|
||||
|
||||
int not_equal(int ex, int ey, const cell_style_aa& c) const
|
||||
{
|
||||
return (ex - x) | (ey - y) | (left - c.left) | (right - c.right);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==================================================rasterizer_compound_aa
|
||||
template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa
|
||||
{
|
||||
struct style_info
|
||||
{
|
||||
unsigned start_cell;
|
||||
unsigned num_cells;
|
||||
int last_x;
|
||||
};
|
||||
|
||||
struct cell_info
|
||||
{
|
||||
int x, area, cover;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Clip clip_type;
|
||||
typedef typename Clip::conv_type conv_type;
|
||||
|
||||
enum aa_scale_e
|
||||
{
|
||||
aa_shift = 8,
|
||||
aa_scale = 1 << aa_shift,
|
||||
aa_mask = aa_scale - 1
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rasterizer_compound_aa() :
|
||||
m_outline(),
|
||||
m_clipper(),
|
||||
m_styles(), // Active Styles
|
||||
m_ast(), // Active Style Table (unique values)
|
||||
m_asm(), // Active Style Mask
|
||||
m_cells(),
|
||||
m_min_style(0x7FFFFFFF),
|
||||
m_max_style(-0x7FFFFFFF),
|
||||
m_scan_y(0x7FFFFFFF)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset();
|
||||
void reset_clipping();
|
||||
void clip_box(double x1, double y1, double x2, double y2);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void styles(int left, int right);
|
||||
void move_to(int x, int y);
|
||||
void line_to(int x, int y);
|
||||
void move_to_d(double x, double y);
|
||||
void line_to_d(double x, double y);
|
||||
void add_vertex(double x, double y, unsigned cmd);
|
||||
|
||||
void edge(int x1, int y1, int x2, int y2);
|
||||
void edge_d(double x1, double y1, double x2, double y2);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void add_path(VertexSource& vs, unsigned path_id=0)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
if(m_outline.sorted()) reset();
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
add_vertex(x, y, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int min_x() const { return m_outline.min_x(); }
|
||||
int min_y() const { return m_outline.min_y(); }
|
||||
int max_x() const { return m_outline.max_x(); }
|
||||
int max_y() const { return m_outline.max_y(); }
|
||||
int min_style() const { return m_min_style; }
|
||||
int max_style() const { return m_max_style; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void sort();
|
||||
bool rewind_scanlines();
|
||||
unsigned sweep_styles();
|
||||
unsigned style(unsigned style_idx) const;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned calculate_alpha(int area) const
|
||||
{
|
||||
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
|
||||
if(cover < 0) cover = -cover;
|
||||
if(cover > aa_mask) cover = aa_mask;
|
||||
return cover;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Sweeps one scanline with one style index. The style ID can be
|
||||
// determined by calling style().
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl, int style_idx)
|
||||
{
|
||||
int scan_y = m_scan_y - 1;
|
||||
if(scan_y > m_outline.max_y()) return false;
|
||||
|
||||
sl.reset_spans();
|
||||
|
||||
if(style_idx < 0) style_idx = 0;
|
||||
else style_idx++;
|
||||
|
||||
const style_info& st = m_styles[m_ast[style_idx]];
|
||||
|
||||
unsigned num_cells = st.num_cells;
|
||||
cell_info* cell = &m_cells[st.start_cell];
|
||||
|
||||
int cover = 0;
|
||||
while(num_cells--)
|
||||
{
|
||||
unsigned alpha;
|
||||
int x = cell->x;
|
||||
int area = cell->area;
|
||||
|
||||
cover += cell->cover;
|
||||
|
||||
++cell;
|
||||
|
||||
if(area)
|
||||
{
|
||||
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
|
||||
sl.add_cell(x, alpha);
|
||||
x++;
|
||||
}
|
||||
|
||||
if(num_cells && cell->x > x)
|
||||
{
|
||||
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
|
||||
if(alpha)
|
||||
{
|
||||
sl.add_span(x, cell->x - x, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sl.num_spans() == 0) return false;
|
||||
sl.finalize(scan_y);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
void add_style(int style_id);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Disable copying
|
||||
rasterizer_compound_aa(const rasterizer_compound_aa<Clip>&);
|
||||
const rasterizer_compound_aa<Clip>&
|
||||
operator = (const rasterizer_compound_aa<Clip>&);
|
||||
|
||||
private:
|
||||
rasterizer_cells_aa<cell_style_aa> m_outline;
|
||||
clip_type m_clipper;
|
||||
pod_vector<style_info> m_styles; // Active Styles
|
||||
pod_vector<unsigned> m_ast; // Active Style Table (unique values)
|
||||
pod_vector<int8u> m_asm; // Active Style Mask
|
||||
pod_vector<cell_info> m_cells;
|
||||
|
||||
int m_min_style;
|
||||
int m_max_style;
|
||||
int m_scan_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::reset()
|
||||
{
|
||||
m_outline.reset();
|
||||
m_min_style = 0x7FFFFFFF;
|
||||
m_max_style = -0x7FFFFFFF;
|
||||
m_scan_y = 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
reset();
|
||||
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
|
||||
conv_type::upscale(x2), conv_type::upscale(y2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::reset_clipping()
|
||||
{
|
||||
reset();
|
||||
m_clipper.reset_clipping();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::styles(int left, int right)
|
||||
{
|
||||
cell_style_aa cell;
|
||||
cell.initial();
|
||||
cell.left = (int16)left;
|
||||
cell.right = (int16)right;
|
||||
m_outline.style(cell);
|
||||
if(left >= 0 && left < m_min_style) m_min_style = left;
|
||||
if(left >= 0 && left > m_max_style) m_max_style = left;
|
||||
if(right >= 0 && right < m_min_style) m_min_style = right;
|
||||
if(right >= 0 && right > m_max_style) m_max_style = right;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::move_to(int x, int y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::downscale(x), conv_type::downscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::line_to(int x, int y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x),
|
||||
conv_type::downscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::move_to_d(double x, double y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::upscale(x), conv_type::upscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::line_to_d(double x, double y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x),
|
||||
conv_type::upscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::edge(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x2),
|
||||
conv_type::downscale(y2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::edge_d(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x2),
|
||||
conv_type::upscale(y2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE void rasterizer_compound_aa<Clip>::sort()
|
||||
{
|
||||
m_outline.sort_cells();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_compound_aa<Clip>::rewind_scanlines()
|
||||
{
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(m_max_style < m_min_style)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = m_outline.min_y();
|
||||
m_styles.allocate(m_max_style - m_min_style + 2, 128);
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE void rasterizer_compound_aa<Clip>::add_style(int style_id)
|
||||
{
|
||||
if(style_id < 0) style_id = 0;
|
||||
else style_id -= m_min_style - 1;
|
||||
|
||||
unsigned nbyte = style_id >> 3;
|
||||
unsigned mask = 1 << (style_id & 7);
|
||||
|
||||
style_info* style = &m_styles[style_id];
|
||||
if((m_asm[nbyte] & mask) == 0)
|
||||
{
|
||||
m_ast.add(style_id);
|
||||
m_asm[nbyte] |= mask;
|
||||
style->start_cell = 0;
|
||||
style->num_cells = 0;
|
||||
style->last_x = -0x7FFFFFFF;
|
||||
}
|
||||
++style->start_cell;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Returns the number of styles
|
||||
template<class Clip>
|
||||
unsigned rasterizer_compound_aa<Clip>::sweep_styles()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(m_scan_y > m_outline.max_y()) return 0;
|
||||
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
|
||||
const cell_style_aa* const* cells = m_outline.scanline_cells(m_scan_y);
|
||||
unsigned num_styles = m_max_style - m_min_style + 2;
|
||||
const cell_style_aa* curr_cell;
|
||||
unsigned style_id;
|
||||
style_info* style;
|
||||
cell_info* cell;
|
||||
|
||||
m_cells.allocate(num_cells * 2, 256); // Each cell can have two styles
|
||||
m_ast.capacity(num_styles, 64);
|
||||
m_asm.allocate((num_styles + 7) >> 3, 8);
|
||||
m_asm.zero();
|
||||
|
||||
// Pre-add zero (for no-fill style, that is, -1).
|
||||
// We need that to ensure that the "-1 style" would go first.
|
||||
m_asm[0] |= 1;
|
||||
m_ast.add(0);
|
||||
style = &m_styles[0];
|
||||
style->start_cell = 0;
|
||||
style->num_cells = 0;
|
||||
style->last_x = -0x7FFFFFFF;
|
||||
|
||||
while(num_cells--)
|
||||
{
|
||||
curr_cell = *cells++;
|
||||
add_style(curr_cell->left);
|
||||
add_style(curr_cell->right);
|
||||
}
|
||||
|
||||
// Convert the Y-histogram into the array of starting indexes
|
||||
unsigned i;
|
||||
unsigned start_cell = 0;
|
||||
for(i = 0; i < m_ast.size(); i++)
|
||||
{
|
||||
style_info& st = m_styles[m_ast[i]];
|
||||
unsigned v = st.start_cell;
|
||||
st.start_cell = start_cell;
|
||||
start_cell += v;
|
||||
}
|
||||
|
||||
cells = m_outline.scanline_cells(m_scan_y);
|
||||
num_cells = m_outline.scanline_num_cells(m_scan_y);
|
||||
|
||||
while(num_cells--)
|
||||
{
|
||||
curr_cell = *cells++;
|
||||
style_id = (curr_cell->left < 0) ? 0 :
|
||||
curr_cell->left - m_min_style + 1;
|
||||
|
||||
style = &m_styles[style_id];
|
||||
if(curr_cell->x == style->last_x)
|
||||
{
|
||||
cell = &m_cells[style->start_cell + style->num_cells - 1];
|
||||
cell->area += curr_cell->area;
|
||||
cell->cover += curr_cell->cover;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell = &m_cells[style->start_cell + style->num_cells];
|
||||
cell->x = curr_cell->x;
|
||||
cell->area = curr_cell->area;
|
||||
cell->cover = curr_cell->cover;
|
||||
style->last_x = curr_cell->x;
|
||||
style->num_cells++;
|
||||
}
|
||||
|
||||
style_id = (curr_cell->right < 0) ? 0 :
|
||||
curr_cell->right - m_min_style + 1;
|
||||
|
||||
style = &m_styles[style_id];
|
||||
if(curr_cell->x == style->last_x)
|
||||
{
|
||||
cell = &m_cells[style->start_cell + style->num_cells - 1];
|
||||
cell->area -= curr_cell->area;
|
||||
cell->cover -= curr_cell->cover;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell = &m_cells[style->start_cell + style->num_cells];
|
||||
cell->x = curr_cell->x;
|
||||
cell->area = -curr_cell->area;
|
||||
cell->cover = -curr_cell->cover;
|
||||
style->last_x = curr_cell->x;
|
||||
style->num_cells++;
|
||||
}
|
||||
}
|
||||
if(m_ast.size() > 1) break;
|
||||
++m_scan_y;
|
||||
}
|
||||
++m_scan_y;
|
||||
return m_ast.size() - 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Returns style ID depending of the existing style index
|
||||
template<class Clip>
|
||||
AGG_INLINE
|
||||
unsigned rasterizer_compound_aa<Clip>::style(unsigned style_idx) const
|
||||
{
|
||||
return m_ast[style_idx + 1] + m_min_style - 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
146
agg/include/agg_rasterizer_outline.h
Normal file
146
agg/include/agg_rasterizer_outline.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_RASTERIZER_OUTLINE_INCLUDED
|
||||
#define AGG_RASTERIZER_OUTLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//======================================================rasterizer_outline
|
||||
template<class Renderer> class rasterizer_outline
|
||||
{
|
||||
public:
|
||||
rasterizer_outline(Renderer& ren) :
|
||||
m_ren(&ren),
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_vertices(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(int x, int y)
|
||||
{
|
||||
m_vertices = 1;
|
||||
m_ren->move_to(m_start_x = x, m_start_y = y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line_to(int x, int y)
|
||||
{
|
||||
++m_vertices;
|
||||
m_ren->line_to(x, y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to_d(double x, double y)
|
||||
{
|
||||
move_to(m_ren->coord(x), m_ren->coord(y));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line_to_d(double x, double y)
|
||||
{
|
||||
line_to(m_ren->coord(x), m_ren->coord(y));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void close()
|
||||
{
|
||||
if(m_vertices > 2)
|
||||
{
|
||||
line_to(m_start_x, m_start_y);
|
||||
}
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
if(is_closed(cmd)) close();
|
||||
}
|
||||
else
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void add_path(VertexSource& vs, unsigned path_id=0)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
add_vertex(x, y, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class VertexSource, class ColorStorage, class PathId>
|
||||
void render_all_paths(VertexSource& vs,
|
||||
const ColorStorage& colors,
|
||||
const PathId& path_id,
|
||||
unsigned num_paths)
|
||||
{
|
||||
for(unsigned i = 0; i < num_paths; i++)
|
||||
{
|
||||
m_ren->line_color(colors[i]);
|
||||
add_path(vs, path_id[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Ctrl> void render_ctrl(Ctrl& c)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < c.num_paths(); i++)
|
||||
{
|
||||
m_ren->line_color(c.color(i));
|
||||
add_path(c, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Renderer* m_ren;
|
||||
int m_start_x;
|
||||
int m_start_y;
|
||||
unsigned m_vertices;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
599
agg/include/agg_rasterizer_outline_aa.h
Normal file
599
agg/include/agg_rasterizer_outline_aa.h
Normal file
|
@ -0,0 +1,599 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_RASTERIZER_OUTLINE_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_OUTLINE_AA_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_line_aa_basics.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline bool cmp_dist_start(int d) { return d > 0; }
|
||||
inline bool cmp_dist_end(int d) { return d <= 0; }
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------line_aa_vertex
|
||||
// Vertex (x, y) with the distance to the next one. The last vertex has
|
||||
// the distance between the last and the first points
|
||||
struct line_aa_vertex
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int len;
|
||||
|
||||
line_aa_vertex() {}
|
||||
line_aa_vertex(int x_, int y_) :
|
||||
x(x_),
|
||||
y(y_),
|
||||
len(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator () (const line_aa_vertex& val)
|
||||
{
|
||||
double dx = val.x - x;
|
||||
double dy = val.y - y;
|
||||
return (len = uround(sqrt(dx * dx + dy * dy))) >
|
||||
(line_subpixel_scale + line_subpixel_scale / 2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------outline_aa_join_e
|
||||
enum outline_aa_join_e
|
||||
{
|
||||
outline_no_join, //-----outline_no_join
|
||||
outline_miter_join, //-----outline_miter_join
|
||||
outline_round_join, //-----outline_round_join
|
||||
outline_miter_accurate_join //-----outline_accurate_join
|
||||
};
|
||||
|
||||
//=======================================================rasterizer_outline_aa
|
||||
template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa
|
||||
{
|
||||
private:
|
||||
//------------------------------------------------------------------------
|
||||
struct draw_vars
|
||||
{
|
||||
unsigned idx;
|
||||
int x1, y1, x2, y2;
|
||||
line_parameters curr, next;
|
||||
int lcurr, lnext;
|
||||
int xb1, yb1, xb2, yb2;
|
||||
unsigned flags;
|
||||
};
|
||||
|
||||
void draw(draw_vars& dv, unsigned start, unsigned end);
|
||||
|
||||
public:
|
||||
typedef line_aa_vertex vertex_type;
|
||||
typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
|
||||
|
||||
rasterizer_outline_aa(Renderer& ren) :
|
||||
m_ren(ren),
|
||||
m_line_join(ren.accurate_join_only() ?
|
||||
outline_miter_accurate_join :
|
||||
outline_round_join),
|
||||
m_round_cap(false),
|
||||
m_start_x(0),
|
||||
m_start_y(0)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void line_join(outline_aa_join_e join)
|
||||
{
|
||||
m_line_join = m_ren.accurate_join_only() ?
|
||||
outline_miter_accurate_join :
|
||||
join;
|
||||
}
|
||||
bool line_join() const { return m_line_join; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void round_cap(bool v) { m_round_cap = v; }
|
||||
bool round_cap() const { return m_round_cap; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void move_to(int x, int y)
|
||||
{
|
||||
m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void line_to(int x, int y)
|
||||
{
|
||||
m_src_vertices.add(vertex_type(x, y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void move_to_d(double x, double y)
|
||||
{
|
||||
move_to(Coord::conv(x), Coord::conv(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void line_to_d(double x, double y)
|
||||
{
|
||||
line_to(Coord::conv(x), Coord::conv(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void render(bool close_polygon);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
render(false);
|
||||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
render(is_closed(cmd));
|
||||
if(is_closed(cmd))
|
||||
{
|
||||
move_to(m_start_x, m_start_y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void add_path(VertexSource& vs, unsigned path_id=0)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
add_vertex(x, y, cmd);
|
||||
}
|
||||
render(false);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class ColorStorage, class PathId>
|
||||
void render_all_paths(VertexSource& vs,
|
||||
const ColorStorage& colors,
|
||||
const PathId& path_id,
|
||||
unsigned num_paths)
|
||||
{
|
||||
for(unsigned i = 0; i < num_paths; i++)
|
||||
{
|
||||
m_ren.color(colors[i]);
|
||||
add_path(vs, path_id[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Ctrl> void render_ctrl(Ctrl& c)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < c.num_paths(); i++)
|
||||
{
|
||||
m_ren.color(c.color(i));
|
||||
add_path(c, i);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&);
|
||||
const rasterizer_outline_aa<Renderer, Coord>& operator =
|
||||
(const rasterizer_outline_aa<Renderer, Coord>&);
|
||||
|
||||
Renderer& m_ren;
|
||||
vertex_storage_type m_src_vertices;
|
||||
outline_aa_join_e m_line_join;
|
||||
bool m_round_cap;
|
||||
int m_start_x;
|
||||
int m_start_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Renderer, class Coord>
|
||||
void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv,
|
||||
unsigned start,
|
||||
unsigned end)
|
||||
{
|
||||
unsigned i;
|
||||
const vertex_storage_type::value_type* v;
|
||||
|
||||
for(i = start; i < end; i++)
|
||||
{
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1);
|
||||
dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1);
|
||||
dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1);
|
||||
dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1);
|
||||
}
|
||||
|
||||
switch(dv.flags)
|
||||
{
|
||||
case 0: m_ren.line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
|
||||
case 1: m_ren.line2(dv.curr, dv.xb2, dv.yb2); break;
|
||||
case 2: m_ren.line1(dv.curr, dv.xb1, dv.yb1); break;
|
||||
case 3: m_ren.line0(dv.curr); break;
|
||||
}
|
||||
|
||||
if(m_line_join == outline_round_join && (dv.flags & 2) == 0)
|
||||
{
|
||||
m_ren.pie(dv.curr.x2, dv.curr.y2,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
|
||||
dv.curr.x2 + (dv.next.y2 - dv.next.y1),
|
||||
dv.curr.y2 - (dv.next.x2 - dv.next.x1));
|
||||
}
|
||||
|
||||
dv.x1 = dv.x2;
|
||||
dv.y1 = dv.y2;
|
||||
dv.lcurr = dv.lnext;
|
||||
dv.lnext = m_src_vertices[dv.idx].len;
|
||||
|
||||
++dv.idx;
|
||||
if(dv.idx >= m_src_vertices.size()) dv.idx = 0;
|
||||
|
||||
v = &m_src_vertices[dv.idx];
|
||||
dv.x2 = v->x;
|
||||
dv.y2 = v->y;
|
||||
|
||||
dv.curr = dv.next;
|
||||
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
|
||||
dv.xb1 = dv.xb2;
|
||||
dv.yb1 = dv.yb2;
|
||||
|
||||
switch(m_line_join)
|
||||
{
|
||||
case outline_no_join:
|
||||
dv.flags = 3;
|
||||
break;
|
||||
|
||||
case outline_miter_join:
|
||||
dv.flags >>= 1;
|
||||
dv.flags |= ((dv.curr.diagonal_quadrant() ==
|
||||
dv.next.diagonal_quadrant()) << 1);
|
||||
if((dv.flags & 2) == 0)
|
||||
{
|
||||
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||
}
|
||||
break;
|
||||
|
||||
case outline_round_join:
|
||||
dv.flags >>= 1;
|
||||
dv.flags |= ((dv.curr.diagonal_quadrant() ==
|
||||
dv.next.diagonal_quadrant()) << 1);
|
||||
break;
|
||||
|
||||
case outline_miter_accurate_join:
|
||||
dv.flags = 0;
|
||||
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Renderer, class Coord>
|
||||
void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon)
|
||||
{
|
||||
m_src_vertices.close(close_polygon);
|
||||
draw_vars dv;
|
||||
const vertex_storage_type::value_type* v;
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
int y2;
|
||||
int lprev;
|
||||
|
||||
if(close_polygon)
|
||||
{
|
||||
if(m_src_vertices.size() >= 3)
|
||||
{
|
||||
dv.idx = 2;
|
||||
|
||||
v = &m_src_vertices[m_src_vertices.size() - 1];
|
||||
x1 = v->x;
|
||||
y1 = v->y;
|
||||
lprev = v->len;
|
||||
|
||||
v = &m_src_vertices[0];
|
||||
x2 = v->x;
|
||||
y2 = v->y;
|
||||
dv.lcurr = v->len;
|
||||
line_parameters prev(x1, y1, x2, y2, lprev);
|
||||
|
||||
v = &m_src_vertices[1];
|
||||
dv.x1 = v->x;
|
||||
dv.y1 = v->y;
|
||||
dv.lnext = v->len;
|
||||
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
|
||||
|
||||
v = &m_src_vertices[dv.idx];
|
||||
dv.x2 = v->x;
|
||||
dv.y2 = v->y;
|
||||
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
|
||||
|
||||
dv.xb1 = 0;
|
||||
dv.yb1 = 0;
|
||||
dv.xb2 = 0;
|
||||
dv.yb2 = 0;
|
||||
|
||||
switch(m_line_join)
|
||||
{
|
||||
case outline_no_join:
|
||||
dv.flags = 3;
|
||||
break;
|
||||
|
||||
case outline_miter_join:
|
||||
case outline_round_join:
|
||||
dv.flags =
|
||||
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
|
||||
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
|
||||
break;
|
||||
|
||||
case outline_miter_accurate_join:
|
||||
dv.flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
|
||||
{
|
||||
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
|
||||
}
|
||||
|
||||
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
|
||||
{
|
||||
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||
}
|
||||
draw(dv, 0, m_src_vertices.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(m_src_vertices.size())
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
v = &m_src_vertices[0];
|
||||
x1 = v->x;
|
||||
y1 = v->y;
|
||||
lprev = v->len;
|
||||
v = &m_src_vertices[1];
|
||||
x2 = v->x;
|
||||
y2 = v->y;
|
||||
line_parameters lp(x1, y1, x2, y2, lprev);
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
}
|
||||
m_ren.line3(lp,
|
||||
x1 + (y2 - y1),
|
||||
y1 - (x2 - x1),
|
||||
x2 + (y2 - y1),
|
||||
y2 - (x2 - x1));
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
int x3, y3;
|
||||
int lnext;
|
||||
v = &m_src_vertices[0];
|
||||
x1 = v->x;
|
||||
y1 = v->y;
|
||||
lprev = v->len;
|
||||
v = &m_src_vertices[1];
|
||||
x2 = v->x;
|
||||
y2 = v->y;
|
||||
lnext = v->len;
|
||||
v = &m_src_vertices[2];
|
||||
x3 = v->x;
|
||||
y3 = v->y;
|
||||
line_parameters lp1(x1, y1, x2, y2, lprev);
|
||||
line_parameters lp2(x2, y2, x3, y3, lnext);
|
||||
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
}
|
||||
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
m_ren.line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
|
||||
m_ren.pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
|
||||
x2 + (y3 - y2), y2 - (x3 - x2));
|
||||
|
||||
m_ren.line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
|
||||
x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
}
|
||||
else
|
||||
{
|
||||
bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
|
||||
m_ren.line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
dv.xb1, dv.yb1);
|
||||
|
||||
m_ren.line3(lp2, dv.xb1, dv.yb1,
|
||||
x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
}
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
dv.idx = 3;
|
||||
|
||||
v = &m_src_vertices[0];
|
||||
x1 = v->x;
|
||||
y1 = v->y;
|
||||
lprev = v->len;
|
||||
|
||||
v = &m_src_vertices[1];
|
||||
x2 = v->x;
|
||||
y2 = v->y;
|
||||
dv.lcurr = v->len;
|
||||
line_parameters prev(x1, y1, x2, y2, lprev);
|
||||
|
||||
v = &m_src_vertices[2];
|
||||
dv.x1 = v->x;
|
||||
dv.y1 = v->y;
|
||||
dv.lnext = v->len;
|
||||
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
|
||||
|
||||
v = &m_src_vertices[dv.idx];
|
||||
dv.x2 = v->x;
|
||||
dv.y2 = v->y;
|
||||
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
|
||||
|
||||
dv.xb1 = 0;
|
||||
dv.yb1 = 0;
|
||||
dv.xb2 = 0;
|
||||
dv.yb2 = 0;
|
||||
|
||||
switch(m_line_join)
|
||||
{
|
||||
case outline_no_join:
|
||||
dv.flags = 3;
|
||||
break;
|
||||
|
||||
case outline_miter_join:
|
||||
case outline_round_join:
|
||||
dv.flags =
|
||||
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
|
||||
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
|
||||
break;
|
||||
|
||||
case outline_miter_accurate_join:
|
||||
dv.flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
}
|
||||
if((dv.flags & 1) == 0)
|
||||
{
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
m_ren.line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
m_ren.pie(prev.x2, prev.y2,
|
||||
x2 + (y2 - y1), y2 - (x2 - x1),
|
||||
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
else
|
||||
{
|
||||
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
|
||||
m_ren.line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
dv.xb1, dv.yb1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ren.line1(prev,
|
||||
x1 + (y2 - y1),
|
||||
y1 - (x2 - x1));
|
||||
}
|
||||
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
|
||||
{
|
||||
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||
}
|
||||
|
||||
draw(dv, 1, m_src_vertices.size() - 2);
|
||||
|
||||
if((dv.flags & 1) == 0)
|
||||
{
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
m_ren.line3(dv.curr,
|
||||
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ren.line3(dv.curr, dv.xb1, dv.yb1,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ren.line2(dv.curr,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_src_vertices.remove_all();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
538
agg/include/agg_rasterizer_scanline_aa.h
Normal file
538
agg/include/agg_rasterizer_scanline_aa.h
Normal file
|
@ -0,0 +1,538 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// The author gratefully acknowleges the support of David Turner,
|
||||
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
|
||||
// libray - in producing this work. See http://www.freetype.org for details.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED
|
||||
|
||||
#include "agg_rasterizer_cells_aa.h"
|
||||
#include "agg_rasterizer_sl_clip.h"
|
||||
#include "agg_gamma_functions.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//-----------------------------------------------------------------cell_aa
|
||||
// A pixel cell. There're no constructors defined and it was done
|
||||
// intentionally in order to avoid extra overhead when allocating an
|
||||
// array of cells.
|
||||
struct cell_aa
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int cover;
|
||||
int area;
|
||||
|
||||
void initial()
|
||||
{
|
||||
x = 0x7FFFFFFF;
|
||||
y = 0x7FFFFFFF;
|
||||
cover = 0;
|
||||
area = 0;
|
||||
}
|
||||
|
||||
void style(const cell_aa&) {}
|
||||
|
||||
int not_equal(int ex, int ey, const cell_aa&) const
|
||||
{
|
||||
return (ex - x) | (ey - y);
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------filling_rule_e
|
||||
enum filling_rule_e
|
||||
{
|
||||
fill_non_zero,
|
||||
fill_even_odd
|
||||
};
|
||||
|
||||
|
||||
//==================================================rasterizer_scanline_aa
|
||||
// Polygon rasterizer that is used to render filled polygons with
|
||||
// high-quality Anti-Aliasing. Internally, by default, the class uses
|
||||
// integer coordinates in format 24.8, i.e. 24 bits for integer part
|
||||
// and 8 bits for fractional - see poly_subpixel_shift. This class can be
|
||||
// used in the following way:
|
||||
//
|
||||
// 1. filling_rule(filling_rule_e ft) - optional.
|
||||
//
|
||||
// 2. gamma() - optional.
|
||||
//
|
||||
// 3. reset()
|
||||
//
|
||||
// 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create
|
||||
// more than one contour, but each contour must consist of at least 3
|
||||
// vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
|
||||
// is the absolute minimum of vertices that define a triangle.
|
||||
// The algorithm does not check either the number of vertices nor
|
||||
// coincidence of their coordinates, but in the worst case it just
|
||||
// won't draw anything.
|
||||
// The orger of the vertices (clockwise or counterclockwise)
|
||||
// is important when using the non-zero filling rule (fill_non_zero).
|
||||
// In this case the vertex order of all the contours must be the same
|
||||
// if you want your intersecting polygons to be without "holes".
|
||||
// You actually can use different vertices order. If the contours do not
|
||||
// intersect each other the order is not important anyway. If they do,
|
||||
// contours with the same vertex order will be rendered without "holes"
|
||||
// while the intersecting contours with different orders will have "holes".
|
||||
//
|
||||
// filling_rule() and gamma() can be called anytime before "sweeping".
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa
|
||||
{
|
||||
enum status
|
||||
{
|
||||
status_initial,
|
||||
status_move_to,
|
||||
status_line_to,
|
||||
status_closed
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Clip clip_type;
|
||||
typedef typename Clip::conv_type conv_type;
|
||||
typedef typename Clip::coord_type coord_type;
|
||||
|
||||
enum aa_scale_e
|
||||
{
|
||||
aa_shift = 8,
|
||||
aa_scale = 1 << aa_shift,
|
||||
aa_mask = aa_scale - 1,
|
||||
aa_scale2 = aa_scale * 2,
|
||||
aa_mask2 = aa_scale2 - 1
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rasterizer_scanline_aa() :
|
||||
m_outline(),
|
||||
m_clipper(),
|
||||
m_filling_rule(fill_non_zero),
|
||||
m_auto_close(true),
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_status(status_initial)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < aa_scale; i++) m_gamma[i] = i;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaF>
|
||||
rasterizer_scanline_aa(const GammaF& gamma_function) :
|
||||
m_outline(),
|
||||
m_clipper(m_outline),
|
||||
m_filling_rule(fill_non_zero),
|
||||
m_auto_close(true),
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_status(status_initial)
|
||||
{
|
||||
gamma(gamma_function);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset();
|
||||
void reset_clipping();
|
||||
void clip_box(double x1, double y1, double x2, double y2);
|
||||
void filling_rule(filling_rule_e filling_rule);
|
||||
void auto_close(bool flag) { m_auto_close = flag; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaF> void gamma(const GammaF& gamma_function)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < aa_scale; i++)
|
||||
{
|
||||
m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned apply_gamma(unsigned cover) const
|
||||
{
|
||||
return m_gamma[cover];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(int x, int y);
|
||||
void line_to(int x, int y);
|
||||
void move_to_d(double x, double y);
|
||||
void line_to_d(double x, double y);
|
||||
void close_polygon();
|
||||
void add_vertex(double x, double y, unsigned cmd);
|
||||
|
||||
void edge(int x1, int y1, int x2, int y2);
|
||||
void edge_d(double x1, double y1, double x2, double y2);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void add_path(VertexSource& vs, unsigned path_id=0)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
if(m_outline.sorted()) reset();
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
add_vertex(x, y, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int min_x() const { return m_outline.min_x(); }
|
||||
int min_y() const { return m_outline.min_y(); }
|
||||
int max_x() const { return m_outline.max_x(); }
|
||||
int max_y() const { return m_outline.max_y(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void sort();
|
||||
bool rewind_scanlines();
|
||||
bool navigate_scanline(int y);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned calculate_alpha(int area) const
|
||||
{
|
||||
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
|
||||
|
||||
if(cover < 0) cover = -cover;
|
||||
if(m_filling_rule == fill_even_odd)
|
||||
{
|
||||
cover &= aa_mask2;
|
||||
if(cover > aa_scale)
|
||||
{
|
||||
cover = aa_scale2 - cover;
|
||||
}
|
||||
}
|
||||
if(cover > aa_mask) cover = aa_mask;
|
||||
return m_gamma[cover];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(m_scan_y > m_outline.max_y()) return false;
|
||||
sl.reset_spans();
|
||||
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
|
||||
const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y);
|
||||
int cover = 0;
|
||||
|
||||
while(num_cells)
|
||||
{
|
||||
const cell_aa* cur_cell = *cells;
|
||||
int x = cur_cell->x;
|
||||
int area = cur_cell->area;
|
||||
unsigned alpha;
|
||||
|
||||
cover += cur_cell->cover;
|
||||
|
||||
//accumulate all cells with the same X
|
||||
while(--num_cells)
|
||||
{
|
||||
cur_cell = *++cells;
|
||||
if(cur_cell->x != x) break;
|
||||
area += cur_cell->area;
|
||||
cover += cur_cell->cover;
|
||||
}
|
||||
|
||||
if(area)
|
||||
{
|
||||
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
|
||||
if(alpha)
|
||||
{
|
||||
sl.add_cell(x, alpha);
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if(num_cells && cur_cell->x > x)
|
||||
{
|
||||
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
|
||||
if(alpha)
|
||||
{
|
||||
sl.add_span(x, cur_cell->x - x, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sl.num_spans()) break;
|
||||
++m_scan_y;
|
||||
}
|
||||
|
||||
sl.finalize(m_scan_y);
|
||||
++m_scan_y;
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool hit_test(int tx, int ty);
|
||||
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
// Disable copying
|
||||
rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&);
|
||||
const rasterizer_scanline_aa<Clip>&
|
||||
operator = (const rasterizer_scanline_aa<Clip>&);
|
||||
|
||||
private:
|
||||
rasterizer_cells_aa<cell_aa> m_outline;
|
||||
clip_type m_clipper;
|
||||
int m_gamma[aa_scale];
|
||||
filling_rule_e m_filling_rule;
|
||||
bool m_auto_close;
|
||||
coord_type m_start_x;
|
||||
coord_type m_start_y;
|
||||
unsigned m_status;
|
||||
int m_scan_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::reset()
|
||||
{
|
||||
m_outline.reset();
|
||||
m_status = status_initial;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule)
|
||||
{
|
||||
m_filling_rule = filling_rule;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
reset();
|
||||
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
|
||||
conv_type::upscale(x2), conv_type::upscale(y2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::reset_clipping()
|
||||
{
|
||||
reset();
|
||||
m_clipper.reset_clipping();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::close_polygon()
|
||||
{
|
||||
if(m_auto_close && m_status == status_line_to)
|
||||
{
|
||||
m_clipper.line_to(m_outline, m_start_x, m_start_y);
|
||||
m_status = status_closed;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::move_to(int x, int y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
if(m_status == status_line_to) close_polygon();
|
||||
m_clipper.move_to(m_start_x = conv_type::downscale(x),
|
||||
m_start_y = conv_type::downscale(y));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::line_to(int x, int y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x),
|
||||
conv_type::downscale(y));
|
||||
m_status = status_line_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
if(m_status == status_line_to) close_polygon();
|
||||
m_clipper.move_to(m_start_x = conv_type::upscale(x),
|
||||
m_start_y = conv_type::upscale(y));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x),
|
||||
conv_type::upscale(y));
|
||||
m_status = status_line_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x2),
|
||||
conv_type::downscale(y2));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x2),
|
||||
conv_type::upscale(y2));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::sort()
|
||||
{
|
||||
m_outline.sort_cells();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines()
|
||||
{
|
||||
close_polygon();
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = m_outline.min_y();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y)
|
||||
{
|
||||
close_polygon();
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0 ||
|
||||
y < m_outline.min_y() ||
|
||||
y > m_outline.max_y())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------scanline_hit_test
|
||||
class scanline_hit_test
|
||||
{
|
||||
public:
|
||||
scanline_hit_test(int x) : m_x(x), m_hit(false) {}
|
||||
|
||||
void reset_spans() {}
|
||||
void finalize(int) {}
|
||||
void add_cell(int x, int)
|
||||
{
|
||||
if(m_x == x) m_hit = true;
|
||||
}
|
||||
void add_span(int x, int len, int)
|
||||
{
|
||||
if(m_x >= x && m_x < x+len) m_hit = true;
|
||||
}
|
||||
unsigned num_spans() const { return 1; }
|
||||
bool hit() const { return m_hit; }
|
||||
|
||||
private:
|
||||
int m_x;
|
||||
bool m_hit;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty)
|
||||
{
|
||||
if(!navigate_scanline(ty)) return false;
|
||||
scanline_hit_test sl(tx);
|
||||
sweep_scanline(sl);
|
||||
return sl.hit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
351
agg/include/agg_rasterizer_sl_clip.h
Normal file
351
agg/include/agg_rasterizer_sl_clip.h
Normal file
|
@ -0,0 +1,351 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_RASTERIZER_SL_CLIP_INCLUDED
|
||||
#define AGG_RASTERIZER_SL_CLIP_INCLUDED
|
||||
|
||||
#include "agg_clip_liang_barsky.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//--------------------------------------------------------poly_max_coord_e
|
||||
enum poly_max_coord_e
|
||||
{
|
||||
poly_max_coord = (1 << 30) - 1 //----poly_max_coord
|
||||
};
|
||||
|
||||
//------------------------------------------------------------ras_conv_int
|
||||
struct ras_conv_int
|
||||
{
|
||||
typedef int coord_type;
|
||||
static AGG_INLINE int mul_div(double a, double b, double c)
|
||||
{
|
||||
return iround(a * b / c);
|
||||
}
|
||||
static int xi(int v) { return v; }
|
||||
static int yi(int v) { return v; }
|
||||
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static int downscale(int v) { return v; }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------ras_conv_int_sat
|
||||
struct ras_conv_int_sat
|
||||
{
|
||||
typedef int coord_type;
|
||||
static AGG_INLINE int mul_div(double a, double b, double c)
|
||||
{
|
||||
return saturation<poly_max_coord>::iround(a * b / c);
|
||||
}
|
||||
static int xi(int v) { return v; }
|
||||
static int yi(int v) { return v; }
|
||||
static int upscale(double v)
|
||||
{
|
||||
return saturation<poly_max_coord>::iround(v * poly_subpixel_scale);
|
||||
}
|
||||
static int downscale(int v) { return v; }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------ras_conv_int_3x
|
||||
struct ras_conv_int_3x
|
||||
{
|
||||
typedef int coord_type;
|
||||
static AGG_INLINE int mul_div(double a, double b, double c)
|
||||
{
|
||||
return iround(a * b / c);
|
||||
}
|
||||
static int xi(int v) { return v * 3; }
|
||||
static int yi(int v) { return v; }
|
||||
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static int downscale(int v) { return v; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------ras_conv_dbl
|
||||
struct ras_conv_dbl
|
||||
{
|
||||
typedef double coord_type;
|
||||
static AGG_INLINE double mul_div(double a, double b, double c)
|
||||
{
|
||||
return a * b / c;
|
||||
}
|
||||
static int xi(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static int yi(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static double upscale(double v) { return v; }
|
||||
static double downscale(int v) { return v / double(poly_subpixel_scale); }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------ras_conv_dbl_3x
|
||||
struct ras_conv_dbl_3x
|
||||
{
|
||||
typedef double coord_type;
|
||||
static AGG_INLINE double mul_div(double a, double b, double c)
|
||||
{
|
||||
return a * b / c;
|
||||
}
|
||||
static int xi(double v) { return iround(v * poly_subpixel_scale * 3); }
|
||||
static int yi(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static double upscale(double v) { return v; }
|
||||
static double downscale(int v) { return v / double(poly_subpixel_scale); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------rasterizer_sl_clip
|
||||
template<class Conv> class rasterizer_sl_clip
|
||||
{
|
||||
public:
|
||||
typedef Conv conv_type;
|
||||
typedef typename Conv::coord_type coord_type;
|
||||
typedef rect_base<coord_type> rect_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rasterizer_sl_clip() :
|
||||
m_clip_box(0,0,0,0),
|
||||
m_x1(0),
|
||||
m_y1(0),
|
||||
m_f1(0),
|
||||
m_clipping(false)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_clipping()
|
||||
{
|
||||
m_clipping = false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2)
|
||||
{
|
||||
m_clip_box = rect_type(x1, y1, x2, y2);
|
||||
m_clip_box.normalize();
|
||||
m_clipping = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(coord_type x1, coord_type y1)
|
||||
{
|
||||
m_x1 = x1;
|
||||
m_y1 = y1;
|
||||
if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box);
|
||||
}
|
||||
|
||||
private:
|
||||
//------------------------------------------------------------------------
|
||||
template<class Rasterizer>
|
||||
AGG_INLINE void line_clip_y(Rasterizer& ras,
|
||||
coord_type x1, coord_type y1,
|
||||
coord_type x2, coord_type y2,
|
||||
unsigned f1, unsigned f2) const
|
||||
{
|
||||
f1 &= 10;
|
||||
f2 &= 10;
|
||||
if((f1 | f2) == 0)
|
||||
{
|
||||
// Fully visible
|
||||
ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(f1 == f2)
|
||||
{
|
||||
// Invisible by Y
|
||||
return;
|
||||
}
|
||||
|
||||
coord_type tx1 = x1;
|
||||
coord_type ty1 = y1;
|
||||
coord_type tx2 = x2;
|
||||
coord_type ty2 = y2;
|
||||
|
||||
if(f1 & 8) // y1 < clip.y1
|
||||
{
|
||||
tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
|
||||
ty1 = m_clip_box.y1;
|
||||
}
|
||||
|
||||
if(f1 & 2) // y1 > clip.y2
|
||||
{
|
||||
tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
|
||||
ty1 = m_clip_box.y2;
|
||||
}
|
||||
|
||||
if(f2 & 8) // y2 < clip.y1
|
||||
{
|
||||
tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
|
||||
ty2 = m_clip_box.y1;
|
||||
}
|
||||
|
||||
if(f2 & 2) // y2 > clip.y2
|
||||
{
|
||||
tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
|
||||
ty2 = m_clip_box.y2;
|
||||
}
|
||||
ras.line(Conv::xi(tx1), Conv::yi(ty1),
|
||||
Conv::xi(tx2), Conv::yi(ty2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
template<class Rasterizer>
|
||||
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
|
||||
{
|
||||
if(m_clipping)
|
||||
{
|
||||
unsigned f2 = clipping_flags(x2, y2, m_clip_box);
|
||||
|
||||
if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0)
|
||||
{
|
||||
// Invisible by Y
|
||||
m_x1 = x2;
|
||||
m_y1 = y2;
|
||||
m_f1 = f2;
|
||||
return;
|
||||
}
|
||||
|
||||
coord_type x1 = m_x1;
|
||||
coord_type y1 = m_y1;
|
||||
unsigned f1 = m_f1;
|
||||
coord_type y3, y4;
|
||||
unsigned f3, f4;
|
||||
|
||||
switch(((f1 & 5) << 1) | (f2 & 5))
|
||||
{
|
||||
case 0: // Visible by X
|
||||
line_clip_y(ras, x1, y1, x2, y2, f1, f2);
|
||||
break;
|
||||
|
||||
case 1: // x2 > clip.x2
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2);
|
||||
break;
|
||||
|
||||
case 2: // x1 > clip.x2
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2);
|
||||
break;
|
||||
|
||||
case 3: // x1 > clip.x2 && x2 > clip.x2
|
||||
line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2);
|
||||
break;
|
||||
|
||||
case 4: // x2 < clip.x1
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2);
|
||||
break;
|
||||
|
||||
case 6: // x1 > clip.x2 && x2 < clip.x1
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
|
||||
y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
f4 = clipping_flags_y(y4, m_clip_box);
|
||||
line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4);
|
||||
line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2);
|
||||
break;
|
||||
|
||||
case 8: // x1 < clip.x1
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2);
|
||||
break;
|
||||
|
||||
case 9: // x1 < clip.x1 && x2 > clip.x2
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
|
||||
y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
f4 = clipping_flags_y(y4, m_clip_box);
|
||||
line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4);
|
||||
line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2);
|
||||
break;
|
||||
|
||||
case 12: // x1 < clip.x1 && x2 < clip.x1
|
||||
line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2);
|
||||
break;
|
||||
}
|
||||
m_f1 = f2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ras.line(Conv::xi(m_x1), Conv::yi(m_y1),
|
||||
Conv::xi(x2), Conv::yi(y2));
|
||||
}
|
||||
m_x1 = x2;
|
||||
m_y1 = y2;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
rect_type m_clip_box;
|
||||
coord_type m_x1;
|
||||
coord_type m_y1;
|
||||
unsigned m_f1;
|
||||
bool m_clipping;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------rasterizer_sl_no_clip
|
||||
class rasterizer_sl_no_clip
|
||||
{
|
||||
public:
|
||||
typedef ras_conv_int conv_type;
|
||||
typedef int coord_type;
|
||||
|
||||
rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
|
||||
|
||||
void reset_clipping() {}
|
||||
void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {}
|
||||
void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; }
|
||||
|
||||
template<class Rasterizer>
|
||||
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
|
||||
{
|
||||
ras.line(m_x1, m_y1, x2, y2);
|
||||
m_x1 = x2;
|
||||
m_y1 = y2;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_x1, m_y1;
|
||||
};
|
||||
|
||||
|
||||
// -----rasterizer_sl_clip_int
|
||||
// -----rasterizer_sl_clip_int_sat
|
||||
// -----rasterizer_sl_clip_int_3x
|
||||
// -----rasterizer_sl_clip_dbl
|
||||
// -----rasterizer_sl_clip_dbl_3x
|
||||
//------------------------------------------------------------------------
|
||||
typedef rasterizer_sl_clip<ras_conv_int> rasterizer_sl_clip_int;
|
||||
typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat;
|
||||
typedef rasterizer_sl_clip<ras_conv_int_3x> rasterizer_sl_clip_int_3x;
|
||||
typedef rasterizer_sl_clip<ras_conv_dbl> rasterizer_sl_clip_dbl;
|
||||
typedef rasterizer_sl_clip<ras_conv_dbl_3x> rasterizer_sl_clip_dbl_3x;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
550
agg/include/agg_renderer_base.h
Normal file
550
agg/include/agg_renderer_base.h
Normal file
|
@ -0,0 +1,550 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 renderer_base
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_BASE_INCLUDED
|
||||
#define AGG_RENDERER_BASE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------renderer_base
|
||||
template<class PixelFormat> class renderer_base
|
||||
{
|
||||
public:
|
||||
typedef PixelFormat pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::row_data row_data;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {}
|
||||
renderer_base(pixfmt_type& ren) :
|
||||
m_ren(&ren),
|
||||
m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
|
||||
{}
|
||||
void attach(pixfmt_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const pixfmt_type& ren() const { return *m_ren; }
|
||||
pixfmt_type& ren() { return *m_ren; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_ren->width(); }
|
||||
unsigned height() const { return m_ren->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool clip_box(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i cb(x1, y1, x2, y2);
|
||||
cb.normalize();
|
||||
if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
|
||||
{
|
||||
m_clip_box = cb;
|
||||
return true;
|
||||
}
|
||||
m_clip_box.x1 = 1;
|
||||
m_clip_box.y1 = 1;
|
||||
m_clip_box.x2 = 0;
|
||||
m_clip_box.y2 = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_clipping(bool visibility)
|
||||
{
|
||||
if(visibility)
|
||||
{
|
||||
m_clip_box.x1 = 0;
|
||||
m_clip_box.y1 = 0;
|
||||
m_clip_box.x2 = width() - 1;
|
||||
m_clip_box.y2 = height() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clip_box.x1 = 1;
|
||||
m_clip_box.y1 = 1;
|
||||
m_clip_box.x2 = 0;
|
||||
m_clip_box.y2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clip_box_naked(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
m_clip_box.x1 = x1;
|
||||
m_clip_box.y1 = y1;
|
||||
m_clip_box.x2 = x2;
|
||||
m_clip_box.y2 = y2;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool inbox(int x, int y) const
|
||||
{
|
||||
return x >= m_clip_box.x1 && y >= m_clip_box.y1 &&
|
||||
x <= m_clip_box.x2 && y <= m_clip_box.y2;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& clip_box() const { return m_clip_box; }
|
||||
int xmin() const { return m_clip_box.x1; }
|
||||
int ymin() const { return m_clip_box.y1; }
|
||||
int xmax() const { return m_clip_box.x2; }
|
||||
int ymax() const { return m_clip_box.y2; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& bounding_clip_box() const { return m_clip_box; }
|
||||
int bounding_xmin() const { return m_clip_box.x1; }
|
||||
int bounding_ymin() const { return m_clip_box.y1; }
|
||||
int bounding_xmax() const { return m_clip_box.x2; }
|
||||
int bounding_ymax() const { return m_clip_box.y2; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(const color_type& c)
|
||||
{
|
||||
unsigned y;
|
||||
if(width())
|
||||
{
|
||||
for(y = 0; y < height(); y++)
|
||||
{
|
||||
m_ren->copy_hline(0, y, width(), c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
if(inbox(x, y))
|
||||
{
|
||||
m_ren->copy_pixel(x, y, c);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||
{
|
||||
if(inbox(x, y))
|
||||
{
|
||||
m_ren->blend_pixel(x, y, c, cover);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
return inbox(x, y) ?
|
||||
m_ren->pixel(x, y) :
|
||||
color_type::no_color();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_hline(int x1, int y, int x2, const color_type& c)
|
||||
{
|
||||
if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
if(x1 > xmax()) return;
|
||||
if(x2 < xmin()) return;
|
||||
|
||||
if(x1 < xmin()) x1 = xmin();
|
||||
if(x2 > xmax()) x2 = xmax();
|
||||
|
||||
m_ren->copy_hline(x1, y, x2 - x1 + 1, c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_vline(int x, int y1, int y2, const color_type& c)
|
||||
{
|
||||
if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
if(y1 > ymax()) return;
|
||||
if(y2 < ymin()) return;
|
||||
|
||||
if(y1 < ymin()) y1 = ymin();
|
||||
if(y2 > ymax()) y2 = ymax();
|
||||
|
||||
m_ren->copy_vline(x, y1, y2 - y1 + 1, c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x1, int y, int x2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
if(x1 > xmax()) return;
|
||||
if(x2 < xmin()) return;
|
||||
|
||||
if(x1 < xmin()) x1 = xmin();
|
||||
if(x2 > xmax()) x2 = xmax();
|
||||
|
||||
m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y1, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
if(y1 > ymax()) return;
|
||||
if(y2 < ymin()) return;
|
||||
|
||||
if(y1 < ymin()) y1 = ymin();
|
||||
if(y2 > ymax()) y2 = ymax();
|
||||
|
||||
m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
|
||||
{
|
||||
rect_i rc(x1, y1, x2, y2);
|
||||
rc.normalize();
|
||||
if(rc.clip(clip_box()))
|
||||
{
|
||||
int y;
|
||||
for(y = rc.y1; y <= rc.y2; y++)
|
||||
{
|
||||
m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_bar(int x1, int y1, int x2, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
rect_i rc(x1, y1, x2, y2);
|
||||
rc.normalize();
|
||||
if(rc.clip(clip_box()))
|
||||
{
|
||||
int y;
|
||||
for(y = rc.y1; y <= rc.y2; y++)
|
||||
{
|
||||
m_ren->blend_hline(rc.x1,
|
||||
y,
|
||||
unsigned(rc.x2 - rc.x1 + 1),
|
||||
c,
|
||||
cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, int len,
|
||||
const color_type& c,
|
||||
const cover_type* covers)
|
||||
{
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
|
||||
if(x < xmin())
|
||||
{
|
||||
len -= xmin() - x;
|
||||
if(len <= 0) return;
|
||||
covers += xmin() - x;
|
||||
x = xmin();
|
||||
}
|
||||
if(x + len > xmax())
|
||||
{
|
||||
len = xmax() - x + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->blend_solid_hspan(x, y, len, c, covers);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y, int len,
|
||||
const color_type& c,
|
||||
const cover_type* covers)
|
||||
{
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
|
||||
if(y < ymin())
|
||||
{
|
||||
len -= ymin() - y;
|
||||
if(len <= 0) return;
|
||||
covers += ymin() - y;
|
||||
y = ymin();
|
||||
}
|
||||
if(y + len > ymax())
|
||||
{
|
||||
len = ymax() - y + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->blend_solid_vspan(x, y, len, c, covers);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y, int len, const color_type* colors)
|
||||
{
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
|
||||
if(x < xmin())
|
||||
{
|
||||
int d = xmin() - x;
|
||||
len -= d;
|
||||
if(len <= 0) return;
|
||||
colors += d;
|
||||
x = xmin();
|
||||
}
|
||||
if(x + len > xmax())
|
||||
{
|
||||
len = xmax() - x + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->copy_color_hspan(x, y, len, colors);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y, int len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
|
||||
if(x < xmin())
|
||||
{
|
||||
int d = xmin() - x;
|
||||
len -= d;
|
||||
if(len <= 0) return;
|
||||
if(covers) covers += d;
|
||||
colors += d;
|
||||
x = xmin();
|
||||
}
|
||||
if(x + len > xmax())
|
||||
{
|
||||
len = xmax() - x + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y, int len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
|
||||
if(y < ymin())
|
||||
{
|
||||
int d = ymin() - y;
|
||||
len -= d;
|
||||
if(len <= 0) return;
|
||||
if(covers) covers += d;
|
||||
colors += d;
|
||||
y = ymin();
|
||||
}
|
||||
if(y + len > ymax())
|
||||
{
|
||||
len = ymax() - y + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const
|
||||
{
|
||||
rect_i rc(0,0,0,0);
|
||||
rect_i cb = clip_box();
|
||||
++cb.x2;
|
||||
++cb.y2;
|
||||
|
||||
if(src.x1 < 0)
|
||||
{
|
||||
dst.x1 -= src.x1;
|
||||
src.x1 = 0;
|
||||
}
|
||||
if(src.y1 < 0)
|
||||
{
|
||||
dst.y1 -= src.y1;
|
||||
src.y1 = 0;
|
||||
}
|
||||
|
||||
if(src.x2 > wsrc) src.x2 = wsrc;
|
||||
if(src.y2 > hsrc) src.y2 = hsrc;
|
||||
|
||||
if(dst.x1 < cb.x1)
|
||||
{
|
||||
src.x1 += cb.x1 - dst.x1;
|
||||
dst.x1 = cb.x1;
|
||||
}
|
||||
if(dst.y1 < cb.y1)
|
||||
{
|
||||
src.y1 += cb.y1 - dst.y1;
|
||||
dst.y1 = cb.y1;
|
||||
}
|
||||
|
||||
if(dst.x2 > cb.x2) dst.x2 = cb.x2;
|
||||
if(dst.y2 > cb.y2) dst.y2 = cb.y2;
|
||||
|
||||
rc.x2 = dst.x2 - dst.x1;
|
||||
rc.y2 = dst.y2 - dst.y1;
|
||||
|
||||
if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1;
|
||||
if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf>
|
||||
void copy_from(const RenBuf& src,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0)
|
||||
{
|
||||
rect_i rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
|
||||
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
m_ren->copy_from(src,
|
||||
rdst.x1, rdst.y1,
|
||||
rsrc.x1, rsrc.y1,
|
||||
rc.x2);
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& src,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
rect_i rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
|
||||
if(rw.ptr)
|
||||
{
|
||||
int x1src = rsrc.x1;
|
||||
int x1dst = rdst.x1;
|
||||
int len = rc.x2;
|
||||
if(rw.x1 > x1src)
|
||||
{
|
||||
x1dst += rw.x1 - x1src;
|
||||
len -= rw.x1 - x1src;
|
||||
x1src = rw.x1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x1src + len-1 > rw.x2)
|
||||
{
|
||||
len -= x1src + len - rw.x2 - 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->blend_from(src,
|
||||
x1dst, rdst.y1,
|
||||
x1src, rsrc.y1,
|
||||
len,
|
||||
cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pixfmt_type* m_ren;
|
||||
rect_i m_clip_box;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
707
agg/include/agg_renderer_markers.h
Normal file
707
agg/include/agg_renderer_markers.h
Normal file
|
@ -0,0 +1,707 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 renderer_markers
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_MARKERS_INCLUDED
|
||||
#define AGG_RENDERER_MARKERS_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_renderer_primitives.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------marker_e
|
||||
enum marker_e
|
||||
{
|
||||
marker_square,
|
||||
marker_diamond,
|
||||
marker_circle,
|
||||
marker_crossed_circle,
|
||||
marker_semiellipse_left,
|
||||
marker_semiellipse_right,
|
||||
marker_semiellipse_up,
|
||||
marker_semiellipse_down,
|
||||
marker_triangle_left,
|
||||
marker_triangle_right,
|
||||
marker_triangle_up,
|
||||
marker_triangle_down,
|
||||
marker_four_rays,
|
||||
marker_cross,
|
||||
marker_x,
|
||||
marker_dash,
|
||||
marker_dot,
|
||||
marker_pixel,
|
||||
|
||||
end_of_markers
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------renderer_markers
|
||||
template<class BaseRenderer> class renderer_markers :
|
||||
public renderer_primitives<BaseRenderer>
|
||||
{
|
||||
public:
|
||||
typedef renderer_primitives<BaseRenderer> base_type;
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_markers(base_ren_type& rbuf) :
|
||||
base_type(rbuf)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool visible(int x, int y, int r) const
|
||||
{
|
||||
rect_i rc(x-r, y-r, x+y, y+r);
|
||||
return rc.clip(base_type::ren().bounding_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void square(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r) base_type::outlined_rectangle(x-r, y-r, x+r, y+r);
|
||||
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void diamond(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
++dx;
|
||||
}
|
||||
while(dy <= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void circle(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r) base_type::outlined_ellipse(x, y, r, r);
|
||||
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void crossed_circle(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
base_type::outlined_ellipse(x, y, r, r);
|
||||
int r6 = r + (r >> 1);
|
||||
if(r <= 2) r6++;
|
||||
r >>= 1;
|
||||
base_type::ren().blend_hline(x-r6, y, x-r, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_hline(x+r, y, x+r6, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_vline(x, y-r6, y-r, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_vline(x, y+r, y+r6, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void semiellipse_left(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int r8 = r * 4 / 5;
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < r8);
|
||||
base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void semiellipse_right(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int r8 = r * 4 / 5;
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < r8);
|
||||
base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void semiellipse_up(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int r8 = r * 4 / 5;
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < r8);
|
||||
base_type::ren().blend_hline(x-dx, y-dy-1, x+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void semiellipse_down(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int r8 = r * 4 / 5;
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < r8);
|
||||
base_type::ren().blend_hline(x-dx, y+dy+1, x+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void triangle_left(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r6 = r * 3 / 5;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy < r6);
|
||||
base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void triangle_right(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r6 = r * 3 / 5;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy < r6);
|
||||
base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void triangle_up(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r6 = r * 3 / 5;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy < r6);
|
||||
base_type::ren().blend_hline(x-dx, y-dy, x+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void triangle_down(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r6 = r * 3 / 5;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy < r6);
|
||||
base_type::ren().blend_hline(x-dx, y+dy, x+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void four_rays(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r3 = -(r / 3);
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy <= r3);
|
||||
base_type::solid_rectangle(x+r3+1, y+r3+1, x-r3-1, y-r3-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void cross(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
base_type::ren().blend_vline(x, y-r, y+r, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void xing(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r * 7 / 10;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x + dy, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y - dy, base_type::line_color(), cover_full);
|
||||
++dy;
|
||||
}
|
||||
while(dy < 0);
|
||||
}
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void dash(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r) base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
|
||||
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void dot(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r) base_type::solid_ellipse(x, y, r, r);
|
||||
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void pixel(int x, int y, int)
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void marker(int x, int y, int r, marker_e type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: square(x, y, r); break;
|
||||
case marker_diamond: diamond(x, y, r); break;
|
||||
case marker_circle: circle(x, y, r); break;
|
||||
case marker_crossed_circle: crossed_circle(x, y, r); break;
|
||||
case marker_semiellipse_left: semiellipse_left(x, y, r); break;
|
||||
case marker_semiellipse_right: semiellipse_right(x, y, r); break;
|
||||
case marker_semiellipse_up: semiellipse_up(x, y, r); break;
|
||||
case marker_semiellipse_down: semiellipse_down(x, y, r); break;
|
||||
case marker_triangle_left: triangle_left(x, y, r); break;
|
||||
case marker_triangle_right: triangle_right(x, y, r); break;
|
||||
case marker_triangle_up: triangle_up(x, y, r); break;
|
||||
case marker_triangle_down: triangle_down(x, y, r); break;
|
||||
case marker_four_rays: four_rays(x, y, r); break;
|
||||
case marker_cross: cross(x, y, r); break;
|
||||
case marker_x: xing(x, y, r); break;
|
||||
case marker_dash: dash(x, y, r); break;
|
||||
case marker_dot: dot(x, y, r); break;
|
||||
case marker_pixel: pixel(x, y, r); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class T>
|
||||
void markers(int n, const T* x, const T* y, T r, marker_e type)
|
||||
{
|
||||
if(n <= 0) return;
|
||||
if(r == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(int(*x), int(*y), base_type::fill_color(), cover_full);
|
||||
++x;
|
||||
++y;
|
||||
}
|
||||
while(--n);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: do { square (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_diamond: do { diamond (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_circle: do { circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_four_rays: do { four_rays (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_cross: do { cross (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_x: do { xing (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class T>
|
||||
void markers(int n, const T* x, const T* y, const T* r, marker_e type)
|
||||
{
|
||||
if(n <= 0) return;
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: do { square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_diamond: do { diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_circle: do { circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_four_rays: do { four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_cross: do { cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_x: do { xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class T>
|
||||
void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, marker_e type)
|
||||
{
|
||||
if(n <= 0) return;
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: do { base_type::fill_color(*fc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_diamond: do { base_type::fill_color(*fc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_circle: do { base_type::fill_color(*fc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_crossed_circle: do { base_type::fill_color(*fc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_semiellipse_left: do { base_type::fill_color(*fc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_semiellipse_right: do { base_type::fill_color(*fc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_semiellipse_up: do { base_type::fill_color(*fc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_semiellipse_down: do { base_type::fill_color(*fc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_triangle_left: do { base_type::fill_color(*fc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_triangle_right: do { base_type::fill_color(*fc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_triangle_up: do { base_type::fill_color(*fc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_triangle_down: do { base_type::fill_color(*fc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_four_rays: do { base_type::fill_color(*fc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_cross: do { base_type::fill_color(*fc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_x: do { base_type::fill_color(*fc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class T>
|
||||
void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, const color_type* lc, marker_e type)
|
||||
{
|
||||
if(n <= 0) return;
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: do { base_type::fill_color(*fc); base_type::line_color(*lc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_diamond: do { base_type::fill_color(*fc); base_type::line_color(*lc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_crossed_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_semiellipse_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_semiellipse_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_semiellipse_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_semiellipse_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_triangle_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_triangle_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_triangle_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_triangle_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_four_rays: do { base_type::fill_color(*fc); base_type::line_color(*lc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_cross: do { base_type::fill_color(*fc); base_type::line_color(*lc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_x: do { base_type::fill_color(*fc); base_type::line_color(*lc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
345
agg/include/agg_renderer_mclip.h
Normal file
345
agg/include/agg_renderer_mclip.h
Normal file
|
@ -0,0 +1,345 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 renderer_mclip
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_MCLIP_INCLUDED
|
||||
#define AGG_RENDERER_MCLIP_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
#include "agg_renderer_base.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------------------renderer_mclip
|
||||
template<class PixelFormat> class renderer_mclip
|
||||
{
|
||||
public:
|
||||
typedef PixelFormat pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::row_data row_data;
|
||||
typedef renderer_base<pixfmt_type> base_ren_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_mclip(pixfmt_type& ren) :
|
||||
m_ren(ren),
|
||||
m_curr_cb(0),
|
||||
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const pixfmt_type& ren() const { return m_ren.ren(); }
|
||||
pixfmt_type& ren() { return m_ren.ren(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_ren.width(); }
|
||||
unsigned height() const { return m_ren.height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& clip_box() const { return m_ren.clip_box(); }
|
||||
int xmin() const { return m_ren.xmin(); }
|
||||
int ymin() const { return m_ren.ymin(); }
|
||||
int xmax() const { return m_ren.xmax(); }
|
||||
int ymax() const { return m_ren.ymax(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& bounding_clip_box() const { return m_bounds; }
|
||||
int bounding_xmin() const { return m_bounds.x1; }
|
||||
int bounding_ymin() const { return m_bounds.y1; }
|
||||
int bounding_xmax() const { return m_bounds.x2; }
|
||||
int bounding_ymax() const { return m_bounds.y2; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void first_clip_box()
|
||||
{
|
||||
m_curr_cb = 0;
|
||||
if(m_clip.size())
|
||||
{
|
||||
const rect_i& cb = m_clip[0];
|
||||
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool next_clip_box()
|
||||
{
|
||||
if(++m_curr_cb < m_clip.size())
|
||||
{
|
||||
const rect_i& cb = m_clip[m_curr_cb];
|
||||
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_clipping(bool visibility)
|
||||
{
|
||||
m_ren.reset_clipping(visibility);
|
||||
m_clip.remove_all();
|
||||
m_curr_cb = 0;
|
||||
m_bounds = m_ren.clip_box();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_clip_box(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i cb(x1, y1, x2, y2);
|
||||
cb.normalize();
|
||||
if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
|
||||
{
|
||||
m_clip.add(cb);
|
||||
if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1;
|
||||
if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1;
|
||||
if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2;
|
||||
if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(const color_type& c)
|
||||
{
|
||||
m_ren.clear(c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
if(m_ren.inbox(x, y))
|
||||
{
|
||||
m_ren.ren().copy_pixel(x, y, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
if(m_ren.inbox(x, y))
|
||||
{
|
||||
m_ren.ren().blend_pixel(x, y, c, cover);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
if(m_ren.inbox(x, y))
|
||||
{
|
||||
return m_ren.ren().pixel(x, y);
|
||||
}
|
||||
}
|
||||
while(next_clip_box());
|
||||
return color_type::no_color();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_hline(int x1, int y, int x2, const color_type& c)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_hline(x1, y, x2, c);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_vline(int x, int y1, int y2, const color_type& c)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_vline(x, y1, y2, c);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x1, int y, int x2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_hline(x1, y, x2, c, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y1, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_vline(x, y1, y2, c, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_bar(x1, y1, x2, y2, c);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_bar(int x1, int y1, int x2, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_bar(x1, y1, x2, y2, c, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, int len,
|
||||
const color_type& c, const cover_type* covers)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_solid_hspan(x, y, len, c, covers);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y, int len,
|
||||
const color_type& c, const cover_type* covers)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_solid_vspan(x, y, len, c, covers);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y, int len, const color_type* colors)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_color_hspan(x, y, len, colors);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y, int len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y, int len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_color_vspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_from(const rendering_buffer& from,
|
||||
const rect_i* rc=0,
|
||||
int x_to=0,
|
||||
int y_to=0)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_from(from, rc, x_to, y_to);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& src,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_from(src, rect_src_ptr, dx, dy, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
renderer_mclip(const renderer_mclip<PixelFormat>&);
|
||||
const renderer_mclip<PixelFormat>&
|
||||
operator = (const renderer_mclip<PixelFormat>&);
|
||||
|
||||
base_ren_type m_ren;
|
||||
pod_bvector<rect_i, 4> m_clip;
|
||||
unsigned m_curr_cb;
|
||||
rect_i m_bounds;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
1845
agg/include/agg_renderer_outline_aa.h
Normal file
1845
agg/include/agg_renderer_outline_aa.h
Normal file
File diff suppressed because it is too large
Load diff
1023
agg/include/agg_renderer_outline_image.h
Normal file
1023
agg/include/agg_renderer_outline_image.h
Normal file
File diff suppressed because it is too large
Load diff
224
agg/include/agg_renderer_primitives.h
Normal file
224
agg/include/agg_renderer_primitives.h
Normal file
|
@ -0,0 +1,224 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 renderer_primitives
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_PRIMITIVES_INCLUDED
|
||||
#define AGG_RENDERER_PRIMITIVES_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_renderer_base.h"
|
||||
#include "agg_dda_line.h"
|
||||
#include "agg_ellipse_bresenham.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-----------------------------------------------------renderer_primitives
|
||||
template<class BaseRenderer> class renderer_primitives
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_primitives(base_ren_type& ren) :
|
||||
m_ren(&ren),
|
||||
m_fill_color(),
|
||||
m_line_color(),
|
||||
m_curr_x(0),
|
||||
m_curr_y(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static int coord(double c)
|
||||
{
|
||||
return iround(c * line_bresenham_interpolator::subpixel_scale);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_color(const color_type& c) { m_fill_color = c; }
|
||||
void line_color(const color_type& c) { m_line_color = c; }
|
||||
const color_type& fill_color() const { return m_fill_color; }
|
||||
const color_type& line_color() const { return m_line_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rectangle(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
m_ren->blend_hline(x1, y1, x2-1, m_line_color, cover_full);
|
||||
m_ren->blend_vline(x2, y1, y2-1, m_line_color, cover_full);
|
||||
m_ren->blend_hline(x1+1, y2, x2, m_line_color, cover_full);
|
||||
m_ren->blend_vline(x1, y1+1, y2, m_line_color, cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void solid_rectangle(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void outlined_rectangle(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rectangle(x1, y1, x2, y2);
|
||||
m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void ellipse(int x, int y, int rx, int ry)
|
||||
{
|
||||
ellipse_bresenham_interpolator ei(rx, ry);
|
||||
int dx = 0;
|
||||
int dy = -ry;
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
|
||||
++ei;
|
||||
}
|
||||
while(dy < 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void solid_ellipse(int x, int y, int rx, int ry)
|
||||
{
|
||||
ellipse_bresenham_interpolator ei(rx, ry);
|
||||
int dx = 0;
|
||||
int dy = -ry;
|
||||
int dy0 = dy;
|
||||
int dx0 = dx;
|
||||
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
if(dy != dy0)
|
||||
{
|
||||
m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
|
||||
m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full);
|
||||
}
|
||||
dx0 = dx;
|
||||
dy0 = dy;
|
||||
++ei;
|
||||
}
|
||||
while(dy < 0);
|
||||
m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void outlined_ellipse(int x, int y, int rx, int ry)
|
||||
{
|
||||
ellipse_bresenham_interpolator ei(rx, ry);
|
||||
int dx = 0;
|
||||
int dy = -ry;
|
||||
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full);
|
||||
m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line(int x1, int y1, int x2, int y2, bool last=false)
|
||||
{
|
||||
line_bresenham_interpolator li(x1, y1, x2, y2);
|
||||
|
||||
unsigned len = li.len();
|
||||
if(len == 0)
|
||||
{
|
||||
if(last)
|
||||
{
|
||||
m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(last) ++len;
|
||||
|
||||
if(li.is_ver())
|
||||
{
|
||||
do
|
||||
{
|
||||
m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full);
|
||||
li.vstep();
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full);
|
||||
li.hstep();
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(int x, int y)
|
||||
{
|
||||
m_curr_x = x;
|
||||
m_curr_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line_to(int x, int y, bool last=false)
|
||||
{
|
||||
line(m_curr_x, m_curr_y, x, y, last);
|
||||
m_curr_x = x;
|
||||
m_curr_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const base_ren_type& ren() const { return *m_ren; }
|
||||
base_ren_type& ren() { return *m_ren; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
|
||||
rendering_buffer& rbuf() { return m_ren->rbuf(); }
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
color_type m_fill_color;
|
||||
color_type m_line_color;
|
||||
int m_curr_x;
|
||||
int m_curr_y;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
264
agg/include/agg_renderer_raster_text.h
Normal file
264
agg/include/agg_renderer_raster_text.h
Normal file
|
@ -0,0 +1,264 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_RASTER_TEXT_INCLUDED
|
||||
#define AGG_RENDERER_RASTER_TEXT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//==============================================renderer_raster_htext_solid
|
||||
template<class BaseRenderer, class GlyphGenerator>
|
||||
class renderer_raster_htext_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer ren_type;
|
||||
typedef GlyphGenerator glyph_gen_type;
|
||||
typedef typename glyph_gen_type::glyph_rect glyph_rect;
|
||||
typedef typename ren_type::color_type color_type;
|
||||
|
||||
renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) :
|
||||
m_ren(&ren),
|
||||
m_glyph(&glyph)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class CharT>
|
||||
void render_text(double x, double y, const CharT* str, bool flip=false)
|
||||
{
|
||||
glyph_rect r;
|
||||
while(*str)
|
||||
{
|
||||
m_glyph->prepare(&r, x, y, *str, flip);
|
||||
if(r.x2 >= r.x1)
|
||||
{
|
||||
int i;
|
||||
if(flip)
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
|
||||
m_color,
|
||||
m_glyph->span(r.y2 - i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
|
||||
m_color,
|
||||
m_glyph->span(i - r.y1));
|
||||
}
|
||||
}
|
||||
}
|
||||
x += r.dx;
|
||||
y += r.dy;
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ren_type* m_ren;
|
||||
glyph_gen_type* m_glyph;
|
||||
color_type m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=============================================renderer_raster_vtext_solid
|
||||
template<class BaseRenderer, class GlyphGenerator>
|
||||
class renderer_raster_vtext_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer ren_type;
|
||||
typedef GlyphGenerator glyph_gen_type;
|
||||
typedef typename glyph_gen_type::glyph_rect glyph_rect;
|
||||
typedef typename ren_type::color_type color_type;
|
||||
|
||||
renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph) :
|
||||
m_ren(&ren),
|
||||
m_glyph(&glyph)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class CharT>
|
||||
void render_text(double x, double y, const CharT* str, bool flip=false)
|
||||
{
|
||||
glyph_rect r;
|
||||
while(*str)
|
||||
{
|
||||
m_glyph->prepare(&r, x, y, *str, !flip);
|
||||
if(r.x2 >= r.x1)
|
||||
{
|
||||
int i;
|
||||
if(flip)
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
|
||||
m_color,
|
||||
m_glyph->span(i - r.y1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
|
||||
m_color,
|
||||
m_glyph->span(r.y2 - i));
|
||||
}
|
||||
}
|
||||
}
|
||||
x += r.dx;
|
||||
y += r.dy;
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ren_type* m_ren;
|
||||
glyph_gen_type* m_glyph;
|
||||
color_type m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===================================================renderer_raster_htext
|
||||
template<class ScanlineRenderer, class GlyphGenerator>
|
||||
class renderer_raster_htext
|
||||
{
|
||||
public:
|
||||
typedef ScanlineRenderer ren_type;
|
||||
typedef GlyphGenerator glyph_gen_type;
|
||||
typedef typename glyph_gen_type::glyph_rect glyph_rect;
|
||||
|
||||
class scanline_single_span
|
||||
{
|
||||
public:
|
||||
typedef agg::cover_type cover_type;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
struct const_span
|
||||
{
|
||||
int x;
|
||||
unsigned len;
|
||||
const cover_type* covers;
|
||||
|
||||
const_span() {}
|
||||
const_span(int x_, unsigned len_, const cover_type* covers_) :
|
||||
x(x_), len(len_), covers(covers_)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef const const_span* const_iterator;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
scanline_single_span(int x, int y, unsigned len,
|
||||
const cover_type* covers) :
|
||||
m_y(y),
|
||||
m_span(x, len, covers)
|
||||
{}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return 1; }
|
||||
const_iterator begin() const { return &m_span; }
|
||||
|
||||
private:
|
||||
//----------------------------------------------------------------
|
||||
int m_y;
|
||||
const_span m_span;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) :
|
||||
m_ren(&ren),
|
||||
m_glyph(&glyph)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class CharT>
|
||||
void render_text(double x, double y, const CharT* str, bool flip=false)
|
||||
{
|
||||
glyph_rect r;
|
||||
while(*str)
|
||||
{
|
||||
m_glyph->prepare(&r, x, y, *str, flip);
|
||||
if(r.x2 >= r.x1)
|
||||
{
|
||||
m_ren->prepare();
|
||||
int i;
|
||||
if(flip)
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->render(
|
||||
scanline_single_span(r.x1,
|
||||
i,
|
||||
(r.x2 - r.x1 + 1),
|
||||
m_glyph->span(r.y2 - i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->render(
|
||||
scanline_single_span(r.x1,
|
||||
i,
|
||||
(r.x2 - r.x1 + 1),
|
||||
m_glyph->span(i - r.y1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
x += r.dx;
|
||||
y += r.dy;
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ren_type* m_ren;
|
||||
glyph_gen_type* m_glyph;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
891
agg/include/agg_renderer_scanline.h
Normal file
891
agg/include/agg_renderer_scanline.h
Normal file
|
@ -0,0 +1,891 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_SCANLINE_INCLUDED
|
||||
#define AGG_RENDERER_SCANLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_renderer_base.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//================================================render_scanline_aa_solid
|
||||
template<class Scanline, class BaseRenderer, class ColorT>
|
||||
void render_scanline_aa_solid(const Scanline& sl,
|
||||
BaseRenderer& ren,
|
||||
const ColorT& color)
|
||||
{
|
||||
int y = sl.y();
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
if(span->len > 0)
|
||||
{
|
||||
ren.blend_solid_hspan(x, y, (unsigned)span->len,
|
||||
color,
|
||||
span->covers);
|
||||
}
|
||||
else
|
||||
{
|
||||
ren.blend_hline(x, y, (unsigned)(x - span->len - 1),
|
||||
color,
|
||||
*(span->covers));
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===============================================render_scanlines_aa_solid
|
||||
template<class Rasterizer, class Scanline,
|
||||
class BaseRenderer, class ColorT>
|
||||
void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl,
|
||||
BaseRenderer& ren, const ColorT& color)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
// Explicitly convert "color" to the BaseRenderer color type.
|
||||
// For example, it can be called with color type "rgba", while
|
||||
// "rgba8" is needed. Otherwise it will be implicitly
|
||||
// converted in the loop many times.
|
||||
//----------------------
|
||||
typename BaseRenderer::color_type ren_color(color);
|
||||
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
//render_scanline_aa_solid(sl, ren, ren_color);
|
||||
|
||||
// This code is equivalent to the above call (copy/paste).
|
||||
// It's just a "manual" optimization for old compilers,
|
||||
// like Microsoft Visual C++ v6.0
|
||||
//-------------------------------
|
||||
int y = sl.y();
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
if(span->len > 0)
|
||||
{
|
||||
ren.blend_solid_hspan(x, y, (unsigned)span->len,
|
||||
ren_color,
|
||||
span->covers);
|
||||
}
|
||||
else
|
||||
{
|
||||
ren.blend_hline(x, y, (unsigned)(x - span->len - 1),
|
||||
ren_color,
|
||||
*(span->covers));
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================renderer_scanline_aa_solid
|
||||
template<class BaseRenderer> class renderer_scanline_aa_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_aa_solid() : m_ren(0) {}
|
||||
renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {}
|
||||
void attach(base_ren_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
render_scanline_aa_solid(sl, *m_ren, m_color);
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
color_type m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//======================================================render_scanline_aa
|
||||
template<class Scanline, class BaseRenderer,
|
||||
class SpanAllocator, class SpanGenerator>
|
||||
void render_scanline_aa(const Scanline& sl, BaseRenderer& ren,
|
||||
SpanAllocator& alloc, SpanGenerator& span_gen)
|
||||
{
|
||||
int y = sl.y();
|
||||
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
const typename Scanline::cover_type* covers = span->covers;
|
||||
|
||||
if(len < 0) len = -len;
|
||||
typename BaseRenderer::color_type* colors = alloc.allocate(len);
|
||||
span_gen.generate(colors, x, y, len);
|
||||
ren.blend_color_hspan(x, y, len, colors,
|
||||
(span->len < 0) ? 0 : covers, *covers);
|
||||
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=====================================================render_scanlines_aa
|
||||
template<class Rasterizer, class Scanline, class BaseRenderer,
|
||||
class SpanAllocator, class SpanGenerator>
|
||||
void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren,
|
||||
SpanAllocator& alloc, SpanGenerator& span_gen)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
span_gen.prepare();
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
render_scanline_aa(sl, ren, alloc, span_gen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//====================================================renderer_scanline_aa
|
||||
template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
|
||||
class renderer_scanline_aa
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanAllocator alloc_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {}
|
||||
renderer_scanline_aa(base_ren_type& ren,
|
||||
alloc_type& alloc,
|
||||
span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_alloc(&alloc),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren,
|
||||
alloc_type& alloc,
|
||||
span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_alloc = &alloc;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() { m_span_gen->prepare(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen);
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
alloc_type* m_alloc;
|
||||
span_gen_type* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
//===================================================renderer_scanline_bin
|
||||
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin() : m_ren(0), m_span_gen(0) {}
|
||||
renderer_scanline_bin(base_ren_type& ren, span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren, span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(unsigned max_span_len)
|
||||
{
|
||||
m_span_gen->prepare(max_span_len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
int y = sl.y();
|
||||
m_ren->first_clip_box();
|
||||
do
|
||||
{
|
||||
int xmin = m_ren->xmin();
|
||||
int xmax = m_ren->xmax();
|
||||
|
||||
if(y >= m_ren->ymin() && y <= m_ren->ymax())
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
|
||||
if(len < 0) len = -len;
|
||||
if(x < xmin)
|
||||
{
|
||||
len -= xmin - x;
|
||||
x = xmin;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x + len > xmax)
|
||||
{
|
||||
len = xmax - x + 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->blend_color_hspan_no_clip(
|
||||
x, y, len,
|
||||
m_span_gen->generate(x, y, len),
|
||||
0);
|
||||
}
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(m_ren->next_clip_box());
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
SpanGenerator* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//================================================renderer_scanline_direct
|
||||
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_direct
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_direct() : m_ren(0), m_span_gen(0) {}
|
||||
renderer_scanline_direct(base_ren_type& ren, span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren, span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(unsigned max_span_len)
|
||||
{
|
||||
m_span_gen->prepare(max_span_len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
int y = sl.y();
|
||||
m_ren->first_clip_box();
|
||||
do
|
||||
{
|
||||
int xmin = m_ren->xmin();
|
||||
int xmax = m_ren->xmax();
|
||||
|
||||
if(y >= m_ren->ymin() && y <= m_ren->ymax())
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
|
||||
if(len < 0) len = -len;
|
||||
if(x < xmin)
|
||||
{
|
||||
len -= xmin - x;
|
||||
x = xmin;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x + len > xmax)
|
||||
{
|
||||
len = xmax - x + 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
span_data span = m_ren->span(x, y, len);
|
||||
if(span.ptr)
|
||||
{
|
||||
m_span_gen->generate(span.x, y, span.len, span.ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(m_ren->next_clip_box());
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
SpanGenerator* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============================================renderer_scanline_bin_copy
|
||||
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin_copy
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin_copy() : m_ren(0), m_span_gen(0) {}
|
||||
renderer_scanline_bin_copy(base_ren_type& ren, span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren, span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(unsigned max_span_len)
|
||||
{
|
||||
m_span_gen->prepare(max_span_len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
int y = sl.y();
|
||||
m_ren->first_clip_box();
|
||||
do
|
||||
{
|
||||
int xmin = m_ren->xmin();
|
||||
int xmax = m_ren->xmax();
|
||||
|
||||
if(y >= m_ren->ymin() && y <= m_ren->ymax())
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
|
||||
if(len < 0) len = -len;
|
||||
if(x < xmin)
|
||||
{
|
||||
len -= xmin - x;
|
||||
x = xmin;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x + len > xmax)
|
||||
{
|
||||
len = xmax - x + 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->copy_color_hspan_no_clip(
|
||||
x, y, len,
|
||||
m_span_gen->generate(x, y, len));
|
||||
}
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(m_ren->next_clip_box());
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
SpanGenerator* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=============================================renderer_scanline_bin_solid
|
||||
template<class BaseRenderer> class renderer_scanline_bin_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin_solid() : m_ren(0) {}
|
||||
renderer_scanline_bin_solid(base_ren_type& ren) :
|
||||
m_ren(&ren)
|
||||
{}
|
||||
void attach(base_ren_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(unsigned) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
m_ren->blend_hline(span->x,
|
||||
sl.y(),
|
||||
span->x - 1 + ((span->len < 0) ?
|
||||
-span->len :
|
||||
span->len),
|
||||
m_color,
|
||||
cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
color_type m_color;
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============================================render_scanline_bin_solid
|
||||
template<class Scanline, class BaseRenderer, class ColorT>
|
||||
void render_scanline_bin_solid(const Scanline& sl,
|
||||
BaseRenderer& ren,
|
||||
const ColorT& color)
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
ren.blend_hline(span->x,
|
||||
sl.y(),
|
||||
span->x - 1 + ((span->len < 0) ?
|
||||
-span->len :
|
||||
span->len),
|
||||
color,
|
||||
cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================render_scanlines_bin_solid
|
||||
template<class Rasterizer, class Scanline,
|
||||
class BaseRenderer, class ColorT>
|
||||
void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl,
|
||||
BaseRenderer& ren, const ColorT& color)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
// Explicitly convert "color" to the BaseRenderer color type.
|
||||
// For example, it can be called with color type "rgba", while
|
||||
// "rgba8" is needed. Otherwise it will be implicitly
|
||||
// converted in the loop many times.
|
||||
//----------------------
|
||||
typename BaseRenderer::color_type ren_color(color);
|
||||
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
//render_scanline_bin_solid(sl, ren, ren_color);
|
||||
|
||||
// This code is equivalent to the above call (copy/paste).
|
||||
// It's just a "manual" optimization for old compilers,
|
||||
// like Microsoft Visual C++ v6.0
|
||||
//-------------------------------
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
ren.blend_hline(span->x,
|
||||
sl.y(),
|
||||
span->x - 1 + ((span->len < 0) ?
|
||||
-span->len :
|
||||
span->len),
|
||||
ren_color,
|
||||
cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================renderer_scanline_bin_solid
|
||||
template<class BaseRenderer> class renderer_scanline_bin_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin_solid() : m_ren(0) {}
|
||||
renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {}
|
||||
void attach(base_ren_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
render_scanline_bin_solid(sl, *m_ren, m_color);
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
color_type m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//========================================================render_scanlines
|
||||
template<class Rasterizer, class Scanline, class Renderer>
|
||||
void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
ren.prepare();
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
ren.render(sl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================render_all_paths
|
||||
template<class Rasterizer, class Scanline, class Renderer,
|
||||
class VertexSource, class ColorStorage, class PathId>
|
||||
void render_all_paths(Rasterizer& ras,
|
||||
Scanline& sl,
|
||||
Renderer& r,
|
||||
VertexSource& vs,
|
||||
const ColorStorage& as,
|
||||
const PathId& path_id,
|
||||
unsigned num_paths)
|
||||
{
|
||||
for(unsigned i = 0; i < num_paths; i++)
|
||||
{
|
||||
ras.reset();
|
||||
ras.add_path(vs, path_id[i]);
|
||||
r.color(as[i]);
|
||||
render_scanlines(ras, sl, r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=============================================render_scanlines_compound
|
||||
template<class Rasterizer,
|
||||
class ScanlineAA,
|
||||
class ScanlineBin,
|
||||
class BaseRenderer,
|
||||
class SpanAllocator,
|
||||
class StyleHandler>
|
||||
void render_scanlines_compound(Rasterizer& ras,
|
||||
ScanlineAA& sl_aa,
|
||||
ScanlineBin& sl_bin,
|
||||
BaseRenderer& ren,
|
||||
SpanAllocator& alloc,
|
||||
StyleHandler& sh)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
int min_x = ras.min_x();
|
||||
int len = ras.max_x() - min_x + 2;
|
||||
sl_aa.reset(min_x, ras.max_x());
|
||||
sl_bin.reset(min_x, ras.max_x());
|
||||
|
||||
typedef typename BaseRenderer::color_type color_type;
|
||||
color_type* color_span = alloc.allocate(len * 2);
|
||||
color_type* mix_buffer = color_span + len;
|
||||
unsigned num_spans;
|
||||
|
||||
unsigned num_styles;
|
||||
unsigned style;
|
||||
bool solid;
|
||||
while((num_styles = ras.sweep_styles()) > 0)
|
||||
{
|
||||
typename ScanlineAA::const_iterator span_aa;
|
||||
if(num_styles == 1)
|
||||
{
|
||||
// Optimization for a single style. Happens often
|
||||
//-------------------------
|
||||
if(ras.sweep_scanline(sl_aa, 0))
|
||||
{
|
||||
style = ras.style(0);
|
||||
if(sh.is_solid(style))
|
||||
{
|
||||
// Just solid fill
|
||||
//-----------------------
|
||||
render_scanline_aa_solid(sl_aa, ren, sh.color(style));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary span generator
|
||||
//-----------------------
|
||||
span_aa = sl_aa.begin();
|
||||
num_spans = sl_aa.num_spans();
|
||||
for(;;)
|
||||
{
|
||||
len = span_aa->len;
|
||||
sh.generate_span(color_span,
|
||||
span_aa->x,
|
||||
sl_aa.y(),
|
||||
len,
|
||||
style);
|
||||
|
||||
ren.blend_color_hspan(span_aa->x,
|
||||
sl_aa.y(),
|
||||
span_aa->len,
|
||||
color_span,
|
||||
span_aa->covers);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ras.sweep_scanline(sl_bin, -1))
|
||||
{
|
||||
// Clear the spans of the mix_buffer
|
||||
//--------------------
|
||||
typename ScanlineBin::const_iterator span_bin = sl_bin.begin();
|
||||
num_spans = sl_bin.num_spans();
|
||||
for(;;)
|
||||
{
|
||||
memset(mix_buffer + span_bin->x - min_x,
|
||||
0,
|
||||
span_bin->len * sizeof(color_type));
|
||||
|
||||
if(--num_spans == 0) break;
|
||||
++span_bin;
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
for(i = 0; i < num_styles; i++)
|
||||
{
|
||||
style = ras.style(i);
|
||||
solid = sh.is_solid(style);
|
||||
|
||||
if(ras.sweep_scanline(sl_aa, i))
|
||||
{
|
||||
color_type* colors;
|
||||
color_type* cspan;
|
||||
typename ScanlineAA::cover_type* covers;
|
||||
span_aa = sl_aa.begin();
|
||||
num_spans = sl_aa.num_spans();
|
||||
if(solid)
|
||||
{
|
||||
// Just solid fill
|
||||
//-----------------------
|
||||
for(;;)
|
||||
{
|
||||
color_type c = sh.color(style);
|
||||
len = span_aa->len;
|
||||
colors = mix_buffer + span_aa->x - min_x;
|
||||
covers = span_aa->covers;
|
||||
do
|
||||
{
|
||||
colors->add(c, *covers);
|
||||
++colors;
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary span generator
|
||||
//-----------------------
|
||||
for(;;)
|
||||
{
|
||||
len = span_aa->len;
|
||||
colors = mix_buffer + span_aa->x - min_x;
|
||||
cspan = color_span;
|
||||
sh.generate_span(cspan,
|
||||
span_aa->x,
|
||||
sl_aa.y(),
|
||||
len,
|
||||
style);
|
||||
covers = span_aa->covers;
|
||||
do
|
||||
{
|
||||
colors->add(*cspan, *covers);
|
||||
++cspan;
|
||||
++colors;
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the blended result as a color hspan
|
||||
//-------------------------
|
||||
span_bin = sl_bin.begin();
|
||||
num_spans = sl_bin.num_spans();
|
||||
for(;;)
|
||||
{
|
||||
ren.blend_color_hspan(span_bin->x,
|
||||
sl_bin.y(),
|
||||
span_bin->len,
|
||||
mix_buffer + span_bin->x - min_x,
|
||||
0,
|
||||
cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span_bin;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
182
agg/include/agg_rendering_buffer.h
Normal file
182
agg/include/agg_rendering_buffer.h
Normal file
|
@ -0,0 +1,182 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 rendering_buffer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERING_BUFFER_INCLUDED
|
||||
#define AGG_RENDERING_BUFFER_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//==========================================================row_ptr_cache
|
||||
template<class T> class row_ptr_cache
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
struct row_data
|
||||
{
|
||||
int x1, x2;
|
||||
const int8u* ptr;
|
||||
row_data() {}
|
||||
row_data(int x1_, int x2_, const int8u* ptr_) :
|
||||
x1(x1_), x2(x2_), ptr(ptr_) {}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
~row_ptr_cache()
|
||||
{
|
||||
delete [] m_rows;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
row_ptr_cache() :
|
||||
m_buf(0),
|
||||
m_rows(0),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0),
|
||||
m_max_height(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
|
||||
m_buf(0),
|
||||
m_rows(0),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0),
|
||||
m_max_height(0)
|
||||
{
|
||||
attach(buf, width, height, stride);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void attach(T* buf, unsigned width, unsigned height, int stride)
|
||||
{
|
||||
m_buf = buf;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_stride = stride;
|
||||
if(height > m_max_height)
|
||||
{
|
||||
delete [] m_rows;
|
||||
m_rows = new T* [m_max_height = height];
|
||||
}
|
||||
|
||||
T* row_ptr = m_buf;
|
||||
|
||||
if(stride < 0)
|
||||
{
|
||||
row_ptr = m_buf - (height - 1) * stride;
|
||||
}
|
||||
|
||||
T** rows = m_rows;
|
||||
|
||||
while(height--)
|
||||
{
|
||||
*rows++ = row_ptr;
|
||||
row_ptr += stride;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
T* buf() { return m_buf; }
|
||||
const T* buf() const { return m_buf; }
|
||||
unsigned width() const { return m_width; }
|
||||
unsigned height() const { return m_height; }
|
||||
int stride() const { return m_stride; }
|
||||
unsigned stride_abs() const
|
||||
{
|
||||
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
T* row_ptr(int, int y, unsigned) { return m_rows[y]; }
|
||||
T* row_ptr(int y) { return m_rows[y]; }
|
||||
const T* row_ptr(int y) const { return m_rows[y]; }
|
||||
row_data row (int y) const { return row_data(0, m_width-1, m_rows[y]); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
T const* const* rows() const { return m_rows; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf>
|
||||
void copy_from(const RenBuf& src)
|
||||
{
|
||||
unsigned h = height();
|
||||
if(src.height() < h) h = src.height();
|
||||
|
||||
unsigned l = stride_abs();
|
||||
if(src.stride_abs() < l) l = src.stride_abs();
|
||||
|
||||
l *= sizeof(T);
|
||||
|
||||
unsigned y;
|
||||
unsigned w = width();
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(T value)
|
||||
{
|
||||
unsigned y;
|
||||
unsigned w = width();
|
||||
unsigned stride = stride_abs();
|
||||
for(y = 0; y < height(); y++)
|
||||
{
|
||||
T* p = row_ptr(0, y, w);
|
||||
unsigned x;
|
||||
for(x = 0; x < stride; x++)
|
||||
{
|
||||
*p++ = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
// Prohibit copying
|
||||
row_ptr_cache(const row_ptr_cache<T>&);
|
||||
const row_ptr_cache<T>& operator = (const row_ptr_cache<T>&);
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
T* m_buf; // Pointer to renrdering buffer
|
||||
T** m_rows; // Pointers to each row of the buffer
|
||||
unsigned m_width; // Width in pixels
|
||||
unsigned m_height; // Height in pixels
|
||||
int m_stride; // Number of bytes per row. Can be < 0
|
||||
unsigned m_max_height; // The maximal height (currently allocated)
|
||||
};
|
||||
|
||||
|
||||
|
||||
//========================================================rendering_buffer
|
||||
typedef row_ptr_cache<int8u> rendering_buffer;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
141
agg/include/agg_rendering_buffer_dynarow.h
Normal file
141
agg/include/agg_rendering_buffer_dynarow.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 rendering_buffer_dynarow
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
|
||||
#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===============================================rendering_buffer_dynarow
|
||||
// Rendering buffer class with dynamic allocation of the rows.
|
||||
// The rows are allocated as needed when requesting for span_ptr().
|
||||
// The class automatically calculates min_x and max_x for each row.
|
||||
// Generally it's more efficient to use this class as a temporary buffer
|
||||
// for rendering a few lines and then to blend it with another buffer.
|
||||
//
|
||||
class rendering_buffer_dynarow
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------
|
||||
struct row_data
|
||||
{
|
||||
int x1, x2;
|
||||
const int8u* ptr;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
~rendering_buffer_dynarow()
|
||||
{
|
||||
init(0,0,0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
rendering_buffer_dynarow() :
|
||||
m_rows(0),
|
||||
m_width(0),
|
||||
m_height(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Allocate and clear the buffer
|
||||
//--------------------------------------------------------------------
|
||||
rendering_buffer_dynarow(unsigned width, unsigned height,
|
||||
unsigned byte_width) :
|
||||
m_rows(new row_data[height]),
|
||||
m_width(width),
|
||||
m_height(height),
|
||||
m_byte_width(byte_width)
|
||||
{
|
||||
memset(m_rows, 0, sizeof(row_data) * height);
|
||||
}
|
||||
|
||||
// Allocate and clear the buffer
|
||||
//--------------------------------------------------------------------
|
||||
void init(unsigned width, unsigned height, unsigned byte_width)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_height; ++i) delete [] (int8u*)m_rows[i].ptr;
|
||||
delete [] m_rows;
|
||||
m_rows = 0;
|
||||
if(width && height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_byte_width = byte_width;
|
||||
m_rows = new row_data[height];
|
||||
memset(m_rows, 0, sizeof(row_data) * height);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_width; }
|
||||
unsigned height() const { return m_height; }
|
||||
unsigned byte_width() const { return m_byte_width; }
|
||||
|
||||
// The main function used for rendering. Returns pointer to the
|
||||
// pre-allocated span. Memory for the row is allocated as needed.
|
||||
//--------------------------------------------------------------------
|
||||
int8u* row_ptr(int x, int y, unsigned len)
|
||||
{
|
||||
row_data* r = m_rows + y;
|
||||
int x2 = x + len - 1;
|
||||
if(r->ptr)
|
||||
{
|
||||
if(x < r->x1) { r->x1 = x; }
|
||||
if(x2 > r->x2) { r->x2 = x2; }
|
||||
}
|
||||
else
|
||||
{
|
||||
int8u* p = new int8u [m_byte_width];
|
||||
r->ptr = p;
|
||||
r->x1 = x;
|
||||
r->x2 = x2;
|
||||
memset(p, 0, m_byte_width);
|
||||
}
|
||||
return (int8u*)r->ptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row_ptr(int y) const { return m_rows[y].ptr; }
|
||||
int8u* row_ptr(int y) { return row_ptr(0, y, m_width); }
|
||||
row_data row (int y) const { return m_rows[y]; }
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
// Prohibit copying
|
||||
rendering_buffer_dynarow(const rendering_buffer_dynarow&);
|
||||
const rendering_buffer_dynarow& operator = (const rendering_buffer_dynarow&);
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
row_data* m_rows; // Pointers to each row of the buffer
|
||||
unsigned m_width; // Width in pixels
|
||||
unsigned m_height; // Height in pixels
|
||||
unsigned m_byte_width; // Width in bytes
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
72
agg/include/agg_rounded_rect.h
Normal file
72
agg/include/agg_rounded_rect.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Rounded rectangle vertex generator
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ROUNDED_RECT_INCLUDED
|
||||
#define AGG_ROUNDED_RECT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_arc.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//------------------------------------------------------------rounded_rect
|
||||
//
|
||||
// See Implemantation agg_rounded_rect.cpp
|
||||
//
|
||||
class rounded_rect
|
||||
{
|
||||
public:
|
||||
rounded_rect() {}
|
||||
rounded_rect(double x1, double y1, double x2, double y2, double r);
|
||||
|
||||
void rect(double x1, double y1, double x2, double y2);
|
||||
void radius(double r);
|
||||
void radius(double rx, double ry);
|
||||
void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top);
|
||||
void radius(double rx1, double ry1, double rx2, double ry2,
|
||||
double rx3, double ry3, double rx4, double ry4);
|
||||
void normalize_radius();
|
||||
|
||||
void approximation_scale(double s) { m_arc.approximation_scale(s); }
|
||||
double approximation_scale() const { return m_arc.approximation_scale(); }
|
||||
|
||||
void rewind(unsigned);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
double m_x1;
|
||||
double m_y1;
|
||||
double m_x2;
|
||||
double m_y2;
|
||||
double m_rx1;
|
||||
double m_ry1;
|
||||
double m_rx2;
|
||||
double m_ry2;
|
||||
double m_rx3;
|
||||
double m_ry3;
|
||||
double m_rx4;
|
||||
double m_ry4;
|
||||
unsigned m_status;
|
||||
arc m_arc;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
273
agg/include/agg_scanline_bin.h
Normal file
273
agg/include/agg_scanline_bin.h
Normal file
|
@ -0,0 +1,273 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 scanline_bin - binary scanline.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SCANLINE_BIN_INCLUDED
|
||||
#define AGG_SCANLINE_BIN_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=============================================================scanline_bin
|
||||
//
|
||||
// This is binary scaline container which supports the interface
|
||||
// used in the rasterizer::render(). See description of agg_scanline_u8
|
||||
// for details.
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
class scanline_bin
|
||||
{
|
||||
public:
|
||||
typedef int32 coord_type;
|
||||
|
||||
struct span
|
||||
{
|
||||
int16 x;
|
||||
int16 len;
|
||||
};
|
||||
|
||||
typedef const span* const_iterator;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline_bin()
|
||||
{
|
||||
delete [] m_spans;
|
||||
}
|
||||
|
||||
scanline_bin() :
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_spans(0),
|
||||
m_cur_span(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 3;
|
||||
if(max_len > m_max_len)
|
||||
{
|
||||
delete [] m_spans;
|
||||
m_spans = new span [max_len];
|
||||
m_max_len = max_len;
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cur_span = m_spans;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned)
|
||||
{
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_cur_span;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = 1;
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned)
|
||||
{
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len = (int16)(m_cur_span->len + len);
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_cur_span;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = (int16)len;
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const void*)
|
||||
{
|
||||
add_span(x, len, 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cur_span = m_spans;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
|
||||
const_iterator begin() const { return m_spans + 1; }
|
||||
|
||||
private:
|
||||
scanline_bin(const scanline_bin&);
|
||||
const scanline_bin operator = (const scanline_bin&);
|
||||
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
span* m_spans;
|
||||
span* m_cur_span;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================================================scanline32_bin
|
||||
class scanline32_bin
|
||||
{
|
||||
public:
|
||||
typedef int32 coord_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct span
|
||||
{
|
||||
span() {}
|
||||
span(coord_type x_, coord_type len_) : x(x_), len(len_) {}
|
||||
|
||||
coord_type x;
|
||||
coord_type len;
|
||||
};
|
||||
typedef pod_bvector<span, 4> span_array_type;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator(const span_array_type& spans) :
|
||||
m_spans(spans),
|
||||
m_span_idx(0)
|
||||
{}
|
||||
|
||||
const span& operator*() const { return m_spans[m_span_idx]; }
|
||||
const span* operator->() const { return &m_spans[m_span_idx]; }
|
||||
|
||||
void operator ++ () { ++m_span_idx; }
|
||||
|
||||
private:
|
||||
const span_array_type& m_spans;
|
||||
unsigned m_span_idx;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
scanline32_bin() : m_max_len(0), m_last_x(0x7FFFFFF0) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned)
|
||||
{
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x), 1));
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned)
|
||||
{
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x), coord_type(len)));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const void*)
|
||||
{
|
||||
add_span(x, len, 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return m_spans.size(); }
|
||||
const_iterator begin() const { return const_iterator(m_spans); }
|
||||
|
||||
private:
|
||||
scanline32_bin(const scanline32_bin&);
|
||||
const scanline32_bin operator = (const scanline32_bin&);
|
||||
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
span_array_type m_spans;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
1563
agg/include/agg_scanline_boolean_algebra.h
Normal file
1563
agg/include/agg_scanline_boolean_algebra.h
Normal file
File diff suppressed because it is too large
Load diff
348
agg/include/agg_scanline_p.h
Normal file
348
agg/include/agg_scanline_p.h
Normal file
|
@ -0,0 +1,348 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 scanline_p - a general purpose scanline container with packed spans.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SCANLINE_P_INCLUDED
|
||||
#define AGG_SCANLINE_P_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=============================================================scanline_p8
|
||||
//
|
||||
// This is a general purpose scaline container which supports the interface
|
||||
// used in the rasterizer::render(). See description of scanline_u8
|
||||
// for details.
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
class scanline_p8
|
||||
{
|
||||
public:
|
||||
typedef scanline_p8 self_type;
|
||||
typedef int8u cover_type;
|
||||
typedef int16 coord_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct span
|
||||
{
|
||||
coord_type x;
|
||||
coord_type len; // If negative, it's a solid span, covers is valid
|
||||
const cover_type* covers;
|
||||
};
|
||||
|
||||
typedef span* iterator;
|
||||
typedef const span* const_iterator;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline_p8()
|
||||
{
|
||||
delete [] m_spans;
|
||||
delete [] m_covers;
|
||||
}
|
||||
|
||||
scanline_p8() :
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(0),
|
||||
m_cover_ptr(0),
|
||||
m_spans(0),
|
||||
m_cur_span(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 3;
|
||||
if(max_len > m_max_len)
|
||||
{
|
||||
delete [] m_spans;
|
||||
delete [] m_covers;
|
||||
m_covers = new cover_type [max_len];
|
||||
m_spans = new span [max_len];
|
||||
m_max_len = max_len;
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = m_covers;
|
||||
m_cur_span = m_spans;
|
||||
m_cur_span->len = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned cover)
|
||||
{
|
||||
*m_cover_ptr = (cover_type)cover;
|
||||
if(x == m_last_x+1 && m_cur_span->len > 0)
|
||||
{
|
||||
m_cur_span->len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->covers = m_cover_ptr;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = 1;
|
||||
}
|
||||
m_last_x = x;
|
||||
m_cover_ptr++;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1 && m_cur_span->len > 0)
|
||||
{
|
||||
m_cur_span->len += (int16)len;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->covers = m_cover_ptr;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = (int16)len;
|
||||
}
|
||||
m_cover_ptr += len;
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
if(x == m_last_x+1 &&
|
||||
m_cur_span->len < 0 &&
|
||||
cover == *m_cur_span->covers)
|
||||
{
|
||||
m_cur_span->len -= (int16)len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_cover_ptr = (cover_type)cover;
|
||||
m_cur_span++;
|
||||
m_cur_span->covers = m_cover_ptr++;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = (int16)(-int(len));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = m_covers;
|
||||
m_cur_span = m_spans;
|
||||
m_cur_span->len = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
|
||||
const_iterator begin() const { return m_spans + 1; }
|
||||
|
||||
private:
|
||||
scanline_p8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
cover_type* m_covers;
|
||||
cover_type* m_cover_ptr;
|
||||
span* m_spans;
|
||||
span* m_cur_span;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================scanline32_p8
|
||||
class scanline32_p8
|
||||
{
|
||||
public:
|
||||
typedef scanline32_p8 self_type;
|
||||
typedef int8u cover_type;
|
||||
typedef int32 coord_type;
|
||||
|
||||
struct span
|
||||
{
|
||||
span() {}
|
||||
span(coord_type x_, coord_type len_, const cover_type* covers_) :
|
||||
x(x_), len(len_), covers(covers_) {}
|
||||
|
||||
coord_type x;
|
||||
coord_type len; // If negative, it's a solid span, covers is valid
|
||||
const cover_type* covers;
|
||||
};
|
||||
typedef pod_bvector<span, 4> span_array_type;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator(const span_array_type& spans) :
|
||||
m_spans(spans),
|
||||
m_span_idx(0)
|
||||
{}
|
||||
|
||||
const span& operator*() const { return m_spans[m_span_idx]; }
|
||||
const span* operator->() const { return &m_spans[m_span_idx]; }
|
||||
|
||||
void operator ++ () { ++m_span_idx; }
|
||||
|
||||
private:
|
||||
const span_array_type& m_spans;
|
||||
unsigned m_span_idx;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline32_p8()
|
||||
{
|
||||
delete [] m_covers;
|
||||
}
|
||||
|
||||
scanline32_p8() :
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(0),
|
||||
m_cover_ptr(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 3;
|
||||
if(max_len > m_max_len)
|
||||
{
|
||||
delete [] m_covers;
|
||||
m_covers = new cover_type[max_len];
|
||||
m_max_len = max_len;
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = m_covers;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned cover)
|
||||
{
|
||||
*m_cover_ptr = cover_type(cover);
|
||||
if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
|
||||
{
|
||||
m_spans.last().len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x), 1, m_cover_ptr));
|
||||
}
|
||||
m_last_x = x;
|
||||
m_cover_ptr++;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr));
|
||||
}
|
||||
m_cover_ptr += len;
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
if(x == m_last_x+1 &&
|
||||
m_spans.size() &&
|
||||
m_spans.last().len < 0 &&
|
||||
cover == *m_spans.last().covers)
|
||||
{
|
||||
m_spans.last().len -= coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_cover_ptr = cover_type(cover);
|
||||
m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = m_covers;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return m_spans.size(); }
|
||||
const_iterator begin() const { return const_iterator(m_spans); }
|
||||
|
||||
private:
|
||||
scanline32_p8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
cover_type* m_covers;
|
||||
cover_type* m_cover_ptr;
|
||||
span_array_type m_spans;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
813
agg/include/agg_scanline_storage_aa.h
Normal file
813
agg/include/agg_scanline_storage_aa.h
Normal file
|
@ -0,0 +1,813 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED
|
||||
#define AGG_SCANLINE_STORAGE_AA_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "agg_array.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------scanline_cell_storage
|
||||
template<class T> class scanline_cell_storage
|
||||
{
|
||||
struct extra_span
|
||||
{
|
||||
unsigned len;
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
~scanline_cell_storage()
|
||||
{
|
||||
remove_all();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
scanline_cell_storage() :
|
||||
m_cells(128-2),
|
||||
m_extra_storage()
|
||||
{}
|
||||
|
||||
|
||||
// Copying
|
||||
//---------------------------------------------------------------
|
||||
scanline_cell_storage(const scanline_cell_storage<T>& v) :
|
||||
m_cells(v.m_cells),
|
||||
m_extra_storage()
|
||||
{
|
||||
copy_extra_storage(v);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const scanline_cell_storage<T>&
|
||||
operator = (const scanline_cell_storage<T>& v)
|
||||
{
|
||||
remove_all();
|
||||
m_cells = v.m_cells;
|
||||
copy_extra_storage(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
void remove_all()
|
||||
{
|
||||
int i;
|
||||
for(i = m_extra_storage.size()-1; i >= 0; --i)
|
||||
{
|
||||
delete [] m_extra_storage[(unsigned)i].ptr;
|
||||
}
|
||||
m_extra_storage.remove_all();
|
||||
m_cells.remove_all();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
int add_cells(const T* cells, unsigned num_cells)
|
||||
{
|
||||
int idx = m_cells.allocate_continuous_block(num_cells);
|
||||
if(idx >= 0)
|
||||
{
|
||||
T* ptr = &m_cells[idx];
|
||||
memcpy(ptr, cells, sizeof(T) * num_cells);
|
||||
return idx;
|
||||
}
|
||||
extra_span s;
|
||||
s.len = num_cells;
|
||||
s.ptr = new T [num_cells];
|
||||
memcpy(s.ptr, cells, sizeof(T) * num_cells);
|
||||
m_extra_storage.add(s);
|
||||
return -int(m_extra_storage.size());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const T* operator [] (int idx) const
|
||||
{
|
||||
if(idx >= 0)
|
||||
{
|
||||
if((unsigned)idx >= m_cells.size()) return 0;
|
||||
return &m_cells[(unsigned)idx];
|
||||
}
|
||||
unsigned i = unsigned(-idx - 1);
|
||||
if(i >= m_extra_storage.size()) return 0;
|
||||
return m_extra_storage[i].ptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
T* operator [] (int idx)
|
||||
{
|
||||
if(idx >= 0)
|
||||
{
|
||||
if((unsigned)idx >= m_cells.size()) return 0;
|
||||
return &m_cells[(unsigned)idx];
|
||||
}
|
||||
unsigned i = unsigned(-idx - 1);
|
||||
if(i >= m_extra_storage.size()) return 0;
|
||||
return m_extra_storage[i].ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void copy_extra_storage(const scanline_cell_storage<T>& v)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < v.m_extra_storage.size(); ++i)
|
||||
{
|
||||
const extra_span& src = v.m_extra_storage[i];
|
||||
extra_span dst;
|
||||
dst.len = src.len;
|
||||
dst.ptr = new T [dst.len];
|
||||
memcpy(dst.ptr, src.ptr, dst.len * sizeof(T));
|
||||
m_extra_storage.add(dst);
|
||||
}
|
||||
}
|
||||
|
||||
pod_bvector<T, 12> m_cells;
|
||||
pod_bvector<extra_span, 6> m_extra_storage;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------scanline_storage_aa
|
||||
template<class T> class scanline_storage_aa
|
||||
{
|
||||
public:
|
||||
typedef T cover_type;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
struct span_data
|
||||
{
|
||||
int32 x;
|
||||
int32 len; // If negative, it's a solid span, covers is valid
|
||||
int covers_id; // The index of the cells in the scanline_cell_storage
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
struct scanline_data
|
||||
{
|
||||
int y;
|
||||
unsigned num_spans;
|
||||
unsigned start_span;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
class embedded_scanline
|
||||
{
|
||||
public:
|
||||
|
||||
//-----------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
struct span
|
||||
{
|
||||
int32 x;
|
||||
int32 len; // If negative, it's a solid span, covers is valid
|
||||
const T* covers;
|
||||
};
|
||||
|
||||
const_iterator(const embedded_scanline& sl) :
|
||||
m_storage(sl.m_storage),
|
||||
m_span_idx(sl.m_scanline.start_span)
|
||||
{
|
||||
init_span();
|
||||
}
|
||||
|
||||
const span& operator*() const { return m_span; }
|
||||
const span* operator->() const { return &m_span; }
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
++m_span_idx;
|
||||
init_span();
|
||||
}
|
||||
|
||||
private:
|
||||
void init_span()
|
||||
{
|
||||
const span_data& s = m_storage->span_by_index(m_span_idx);
|
||||
m_span.x = s.x;
|
||||
m_span.len = s.len;
|
||||
m_span.covers = m_storage->covers_by_index(s.covers_id);
|
||||
}
|
||||
|
||||
const scanline_storage_aa* m_storage;
|
||||
unsigned m_span_idx;
|
||||
span m_span;
|
||||
};
|
||||
|
||||
friend class const_iterator;
|
||||
|
||||
|
||||
//-----------------------------------------------------------
|
||||
embedded_scanline(const scanline_storage_aa& storage) :
|
||||
m_storage(&storage)
|
||||
{
|
||||
init(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
void reset(int, int) {}
|
||||
unsigned num_spans() const { return m_scanline.num_spans; }
|
||||
int y() const { return m_scanline.y; }
|
||||
const_iterator begin() const { return const_iterator(*this); }
|
||||
|
||||
//-----------------------------------------------------------
|
||||
void init(unsigned scanline_idx)
|
||||
{
|
||||
m_scanline_idx = scanline_idx;
|
||||
m_scanline = m_storage->scanline_by_index(m_scanline_idx);
|
||||
}
|
||||
|
||||
private:
|
||||
const scanline_storage_aa* m_storage;
|
||||
scanline_data m_scanline;
|
||||
unsigned m_scanline_idx;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
scanline_storage_aa() :
|
||||
m_covers(),
|
||||
m_spans(256-2), // Block increment size
|
||||
m_scanlines(),
|
||||
m_min_x( 0x7FFFFFFF),
|
||||
m_min_y( 0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF),
|
||||
m_cur_scanline(0)
|
||||
{
|
||||
m_fake_scanline.y = 0;
|
||||
m_fake_scanline.num_spans = 0;
|
||||
m_fake_scanline.start_span = 0;
|
||||
m_fake_span.x = 0;
|
||||
m_fake_span.len = 0;
|
||||
m_fake_span.covers_id = 0;
|
||||
}
|
||||
|
||||
// Renderer Interface
|
||||
//---------------------------------------------------------------
|
||||
void prepare()
|
||||
{
|
||||
m_covers.remove_all();
|
||||
m_scanlines.remove_all();
|
||||
m_spans.remove_all();
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
m_cur_scanline = 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
scanline_data sl_this;
|
||||
|
||||
int y = sl.y();
|
||||
if(y < m_min_y) m_min_y = y;
|
||||
if(y > m_max_y) m_max_y = y;
|
||||
|
||||
sl_this.y = y;
|
||||
sl_this.num_spans = sl.num_spans();
|
||||
sl_this.start_span = m_spans.size();
|
||||
typename Scanline::const_iterator span_iterator = sl.begin();
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
for(;;)
|
||||
{
|
||||
span_data sp;
|
||||
|
||||
sp.x = span_iterator->x;
|
||||
sp.len = span_iterator->len;
|
||||
int len = abs(int(sp.len));
|
||||
sp.covers_id =
|
||||
m_covers.add_cells(span_iterator->covers,
|
||||
unsigned(len));
|
||||
m_spans.add(sp);
|
||||
int x1 = sp.x;
|
||||
int x2 = sp.x + len - 1;
|
||||
if(x1 < m_min_x) m_min_x = x1;
|
||||
if(x2 > m_max_x) m_max_x = x2;
|
||||
if(--num_spans == 0) break;
|
||||
++span_iterator;
|
||||
}
|
||||
m_scanlines.add(sl_this);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Iterate scanlines interface
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool rewind_scanlines()
|
||||
{
|
||||
m_cur_scanline = 0;
|
||||
return m_scanlines.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
sl.reset_spans();
|
||||
for(;;)
|
||||
{
|
||||
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||
const scanline_data& sl_this = m_scanlines[m_cur_scanline];
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
const T* covers = covers_by_index(sp.covers_id);
|
||||
if(sp.len < 0)
|
||||
{
|
||||
sl.add_span(sp.x, unsigned(-sp.len), *covers);
|
||||
}
|
||||
else
|
||||
{
|
||||
sl.add_cells(sp.x, sp.len, covers);
|
||||
}
|
||||
}
|
||||
while(--num_spans);
|
||||
++m_cur_scanline;
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(sl_this.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Specialization for embedded_scanline
|
||||
bool sweep_scanline(embedded_scanline& sl)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||
sl.init(m_cur_scanline);
|
||||
++m_cur_scanline;
|
||||
}
|
||||
while(sl.num_spans() == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
unsigned byte_size() const
|
||||
{
|
||||
unsigned i;
|
||||
unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y
|
||||
|
||||
for(i = 0; i < m_scanlines.size(); ++i)
|
||||
{
|
||||
size += sizeof(int32) * 3; // scanline size in bytes, Y, num_spans
|
||||
|
||||
const scanline_data& sl_this = m_scanlines[i];
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
|
||||
size += sizeof(int32) * 2; // X, span_len
|
||||
if(sp.len < 0)
|
||||
{
|
||||
size += sizeof(T); // cover
|
||||
}
|
||||
else
|
||||
{
|
||||
size += sizeof(T) * unsigned(sp.len); // covers
|
||||
}
|
||||
}
|
||||
while(--num_spans);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
static void write_int32(int8u* dst, int32 val)
|
||||
{
|
||||
dst[0] = ((const int8u*)&val)[0];
|
||||
dst[1] = ((const int8u*)&val)[1];
|
||||
dst[2] = ((const int8u*)&val)[2];
|
||||
dst[3] = ((const int8u*)&val)[3];
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
void serialize(int8u* data) const
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
write_int32(data, min_x()); // min_x
|
||||
data += sizeof(int32);
|
||||
write_int32(data, min_y()); // min_y
|
||||
data += sizeof(int32);
|
||||
write_int32(data, max_x()); // max_x
|
||||
data += sizeof(int32);
|
||||
write_int32(data, max_y()); // max_y
|
||||
data += sizeof(int32);
|
||||
|
||||
for(i = 0; i < m_scanlines.size(); ++i)
|
||||
{
|
||||
const scanline_data& sl_this = m_scanlines[i];
|
||||
|
||||
int8u* size_ptr = data;
|
||||
data += sizeof(int32); // Reserve space for scanline size in bytes
|
||||
|
||||
write_int32(data, sl_this.y); // Y
|
||||
data += sizeof(int32);
|
||||
|
||||
write_int32(data, sl_this.num_spans); // num_spans
|
||||
data += sizeof(int32);
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
const T* covers = covers_by_index(sp.covers_id);
|
||||
|
||||
write_int32(data, sp.x); // X
|
||||
data += sizeof(int32);
|
||||
|
||||
write_int32(data, sp.len); // span_len
|
||||
data += sizeof(int32);
|
||||
|
||||
if(sp.len < 0)
|
||||
{
|
||||
memcpy(data, covers, sizeof(T));
|
||||
data += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(data, covers, unsigned(sp.len) * sizeof(T));
|
||||
data += sizeof(T) * unsigned(sp.len);
|
||||
}
|
||||
}
|
||||
while(--num_spans);
|
||||
write_int32(size_ptr, int32(unsigned(data - size_ptr)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const scanline_data& scanline_by_index(unsigned i) const
|
||||
{
|
||||
return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const span_data& span_by_index(unsigned i) const
|
||||
{
|
||||
return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const T* covers_by_index(int i) const
|
||||
{
|
||||
return m_covers[i];
|
||||
}
|
||||
|
||||
private:
|
||||
scanline_cell_storage<T> m_covers;
|
||||
pod_bvector<span_data, 10> m_spans;
|
||||
pod_bvector<scanline_data, 8> m_scanlines;
|
||||
span_data m_fake_span;
|
||||
scanline_data m_fake_scanline;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
unsigned m_cur_scanline;
|
||||
};
|
||||
|
||||
|
||||
typedef scanline_storage_aa<int8u> scanline_storage_aa8; //--------scanline_storage_aa8
|
||||
typedef scanline_storage_aa<int16u> scanline_storage_aa16; //--------scanline_storage_aa16
|
||||
typedef scanline_storage_aa<int32u> scanline_storage_aa32; //--------scanline_storage_aa32
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------serialized_scanlines_adaptor_aa
|
||||
template<class T> class serialized_scanlines_adaptor_aa
|
||||
{
|
||||
public:
|
||||
typedef T cover_type;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
class embedded_scanline
|
||||
{
|
||||
public:
|
||||
typedef T cover_type;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
struct span
|
||||
{
|
||||
int32 x;
|
||||
int32 len; // If negative, it's a solid span, "covers" is valid
|
||||
const T* covers;
|
||||
};
|
||||
|
||||
const_iterator(const embedded_scanline& sl) :
|
||||
m_ptr(sl.m_ptr),
|
||||
m_dx(sl.m_dx)
|
||||
{
|
||||
init_span();
|
||||
}
|
||||
|
||||
const span& operator*() const { return m_span; }
|
||||
const span* operator->() const { return &m_span; }
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
if(m_span.len < 0)
|
||||
{
|
||||
m_ptr += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ptr += m_span.len * sizeof(T);
|
||||
}
|
||||
init_span();
|
||||
}
|
||||
|
||||
private:
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
void init_span()
|
||||
{
|
||||
m_span.x = read_int32() + m_dx;
|
||||
m_span.len = read_int32();
|
||||
m_span.covers = m_ptr;
|
||||
}
|
||||
|
||||
const int8u* m_ptr;
|
||||
span m_span;
|
||||
int m_dx;
|
||||
};
|
||||
|
||||
friend class const_iterator;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
void reset(int, int) {}
|
||||
unsigned num_spans() const { return m_num_spans; }
|
||||
int y() const { return m_y; }
|
||||
const_iterator begin() const { return const_iterator(*this); }
|
||||
|
||||
|
||||
private:
|
||||
//-----------------------------------------------------------------
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
public:
|
||||
//-----------------------------------------------------------------
|
||||
void init(const int8u* ptr, int dx, int dy)
|
||||
{
|
||||
m_ptr = ptr;
|
||||
m_y = read_int32() + dy;
|
||||
m_num_spans = unsigned(read_int32());
|
||||
m_dx = dx;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_ptr;
|
||||
int m_y;
|
||||
unsigned m_num_spans;
|
||||
int m_dx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
serialized_scanlines_adaptor_aa() :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_ptr(0),
|
||||
m_dx(0),
|
||||
m_dy(0),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
serialized_scanlines_adaptor_aa(const int8u* data, unsigned size,
|
||||
double dx, double dy) :
|
||||
m_data(data),
|
||||
m_end(data + size),
|
||||
m_ptr(data),
|
||||
m_dx(iround(dx)),
|
||||
m_dy(iround(dy)),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(const int8u* data, unsigned size, double dx, double dy)
|
||||
{
|
||||
m_data = data;
|
||||
m_end = data + size;
|
||||
m_ptr = data;
|
||||
m_dx = iround(dx);
|
||||
m_dy = iround(dy);
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned read_int32u()
|
||||
{
|
||||
int32u val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
public:
|
||||
// Iterate scanlines interface
|
||||
//--------------------------------------------------------------------
|
||||
bool rewind_scanlines()
|
||||
{
|
||||
m_ptr = m_data;
|
||||
if(m_ptr < m_end)
|
||||
{
|
||||
m_min_x = read_int32() + m_dx;
|
||||
m_min_y = read_int32() + m_dy;
|
||||
m_max_x = read_int32() + m_dx;
|
||||
m_max_y = read_int32() + m_dy;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
sl.reset_spans();
|
||||
for(;;)
|
||||
{
|
||||
if(m_ptr >= m_end) return false;
|
||||
|
||||
read_int32(); // Skip scanline size in bytes
|
||||
int y = read_int32() + m_dy;
|
||||
unsigned num_spans = read_int32();
|
||||
|
||||
do
|
||||
{
|
||||
int x = read_int32() + m_dx;
|
||||
int len = read_int32();
|
||||
|
||||
if(len < 0)
|
||||
{
|
||||
sl.add_span(x, unsigned(-len), *m_ptr);
|
||||
m_ptr += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
sl.add_cells(x, len, m_ptr);
|
||||
m_ptr += len * sizeof(T);
|
||||
}
|
||||
}
|
||||
while(--num_spans);
|
||||
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Specialization for embedded_scanline
|
||||
bool sweep_scanline(embedded_scanline& sl)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(m_ptr >= m_end) return false;
|
||||
|
||||
unsigned byte_size = read_int32u();
|
||||
sl.init(m_ptr, m_dx, m_dy);
|
||||
m_ptr += byte_size - sizeof(int32);
|
||||
}
|
||||
while(sl.num_spans() == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_data;
|
||||
const int8u* m_end;
|
||||
const int8u* m_ptr;
|
||||
int m_dx;
|
||||
int m_dy;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef serialized_scanlines_adaptor_aa<int8u> serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8
|
||||
typedef serialized_scanlines_adaptor_aa<int16u> serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16
|
||||
typedef serialized_scanlines_adaptor_aa<int32u> serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
585
agg/include/agg_scanline_storage_bin.h
Normal file
585
agg/include/agg_scanline_storage_bin.h
Normal file
|
@ -0,0 +1,585 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED
|
||||
#define AGG_SCANLINE_STORAGE_BIN_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "agg_array.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------scanline_storage_bin
|
||||
class scanline_storage_bin
|
||||
{
|
||||
public:
|
||||
//---------------------------------------------------------------
|
||||
struct span_data
|
||||
{
|
||||
int32 x;
|
||||
int32 len;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
struct scanline_data
|
||||
{
|
||||
int y;
|
||||
unsigned num_spans;
|
||||
unsigned start_span;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
class embedded_scanline
|
||||
{
|
||||
public:
|
||||
|
||||
//-----------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator(const embedded_scanline& sl) :
|
||||
m_storage(sl.m_storage),
|
||||
m_span_idx(sl.m_scanline.start_span)
|
||||
{
|
||||
m_span = m_storage->span_by_index(m_span_idx);
|
||||
}
|
||||
|
||||
const span_data& operator*() const { return m_span; }
|
||||
const span_data* operator->() const { return &m_span; }
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
++m_span_idx;
|
||||
m_span = m_storage->span_by_index(m_span_idx);
|
||||
}
|
||||
|
||||
private:
|
||||
const scanline_storage_bin* m_storage;
|
||||
unsigned m_span_idx;
|
||||
span_data m_span;
|
||||
};
|
||||
|
||||
friend class const_iterator;
|
||||
|
||||
|
||||
//-----------------------------------------------------------
|
||||
embedded_scanline(const scanline_storage_bin& storage) :
|
||||
m_storage(&storage)
|
||||
{
|
||||
setup(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
void reset(int, int) {}
|
||||
unsigned num_spans() const { return m_scanline.num_spans; }
|
||||
int y() const { return m_scanline.y; }
|
||||
const_iterator begin() const { return const_iterator(*this); }
|
||||
|
||||
//-----------------------------------------------------------
|
||||
void setup(unsigned scanline_idx)
|
||||
{
|
||||
m_scanline_idx = scanline_idx;
|
||||
m_scanline = m_storage->scanline_by_index(m_scanline_idx);
|
||||
}
|
||||
|
||||
private:
|
||||
const scanline_storage_bin* m_storage;
|
||||
scanline_data m_scanline;
|
||||
unsigned m_scanline_idx;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
scanline_storage_bin() :
|
||||
m_spans(256-2), // Block increment size
|
||||
m_scanlines(),
|
||||
m_min_x( 0x7FFFFFFF),
|
||||
m_min_y( 0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF),
|
||||
m_cur_scanline(0)
|
||||
{
|
||||
m_fake_scanline.y = 0;
|
||||
m_fake_scanline.num_spans = 0;
|
||||
m_fake_scanline.start_span = 0;
|
||||
m_fake_span.x = 0;
|
||||
m_fake_span.len = 0;
|
||||
}
|
||||
|
||||
// Renderer Interface
|
||||
//---------------------------------------------------------------
|
||||
void prepare()
|
||||
{
|
||||
m_scanlines.remove_all();
|
||||
m_spans.remove_all();
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
m_cur_scanline = 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
scanline_data sl_this;
|
||||
|
||||
int y = sl.y();
|
||||
if(y < m_min_y) m_min_y = y;
|
||||
if(y > m_max_y) m_max_y = y;
|
||||
|
||||
sl_this.y = y;
|
||||
sl_this.num_spans = sl.num_spans();
|
||||
sl_this.start_span = m_spans.size();
|
||||
typename Scanline::const_iterator span_iterator = sl.begin();
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
for(;;)
|
||||
{
|
||||
span_data sp;
|
||||
sp.x = span_iterator->x;
|
||||
sp.len = (int32)abs((int)(span_iterator->len));
|
||||
m_spans.add(sp);
|
||||
int x1 = sp.x;
|
||||
int x2 = sp.x + sp.len - 1;
|
||||
if(x1 < m_min_x) m_min_x = x1;
|
||||
if(x2 > m_max_x) m_max_x = x2;
|
||||
if(--num_spans == 0) break;
|
||||
++span_iterator;
|
||||
}
|
||||
m_scanlines.add(sl_this);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Iterate scanlines interface
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool rewind_scanlines()
|
||||
{
|
||||
m_cur_scanline = 0;
|
||||
return m_scanlines.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
sl.reset_spans();
|
||||
for(;;)
|
||||
{
|
||||
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||
const scanline_data& sl_this = m_scanlines[m_cur_scanline];
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
sl.add_span(sp.x, sp.len, cover_full);
|
||||
}
|
||||
while(--num_spans);
|
||||
|
||||
++m_cur_scanline;
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(sl_this.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Specialization for embedded_scanline
|
||||
bool sweep_scanline(embedded_scanline& sl)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||
sl.setup(m_cur_scanline);
|
||||
++m_cur_scanline;
|
||||
}
|
||||
while(sl.num_spans() == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
unsigned byte_size() const
|
||||
{
|
||||
unsigned i;
|
||||
unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y
|
||||
|
||||
for(i = 0; i < m_scanlines.size(); ++i)
|
||||
{
|
||||
size += sizeof(int32) * 2 + // Y, num_spans
|
||||
unsigned(m_scanlines[i].num_spans) * sizeof(int32) * 2; // X, span_len
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
static void write_int32(int8u* dst, int32 val)
|
||||
{
|
||||
dst[0] = ((const int8u*)&val)[0];
|
||||
dst[1] = ((const int8u*)&val)[1];
|
||||
dst[2] = ((const int8u*)&val)[2];
|
||||
dst[3] = ((const int8u*)&val)[3];
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
void serialize(int8u* data) const
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
write_int32(data, min_x()); // min_x
|
||||
data += sizeof(int32);
|
||||
write_int32(data, min_y()); // min_y
|
||||
data += sizeof(int32);
|
||||
write_int32(data, max_x()); // max_x
|
||||
data += sizeof(int32);
|
||||
write_int32(data, max_y()); // max_y
|
||||
data += sizeof(int32);
|
||||
|
||||
for(i = 0; i < m_scanlines.size(); ++i)
|
||||
{
|
||||
const scanline_data& sl_this = m_scanlines[i];
|
||||
|
||||
write_int32(data, sl_this.y); // Y
|
||||
data += sizeof(int32);
|
||||
|
||||
write_int32(data, sl_this.num_spans); // num_spans
|
||||
data += sizeof(int32);
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
|
||||
write_int32(data, sp.x); // X
|
||||
data += sizeof(int32);
|
||||
|
||||
write_int32(data, sp.len); // len
|
||||
data += sizeof(int32);
|
||||
}
|
||||
while(--num_spans);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const scanline_data& scanline_by_index(unsigned i) const
|
||||
{
|
||||
return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const span_data& span_by_index(unsigned i) const
|
||||
{
|
||||
return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
pod_bvector<span_data, 10> m_spans;
|
||||
pod_bvector<scanline_data, 8> m_scanlines;
|
||||
span_data m_fake_span;
|
||||
scanline_data m_fake_scanline;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
unsigned m_cur_scanline;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------serialized_scanlines_adaptor_bin
|
||||
class serialized_scanlines_adaptor_bin
|
||||
{
|
||||
public:
|
||||
typedef bool cover_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class embedded_scanline
|
||||
{
|
||||
public:
|
||||
|
||||
//----------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
struct span
|
||||
{
|
||||
int32 x;
|
||||
int32 len;
|
||||
};
|
||||
|
||||
const_iterator(const embedded_scanline& sl) :
|
||||
m_ptr(sl.m_ptr),
|
||||
m_dx(sl.m_dx)
|
||||
{
|
||||
m_span.x = read_int32() + m_dx;
|
||||
m_span.len = read_int32();
|
||||
}
|
||||
|
||||
const span& operator*() const { return m_span; }
|
||||
const span* operator->() const { return &m_span; }
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
m_span.x = read_int32() + m_dx;
|
||||
m_span.len = read_int32();
|
||||
}
|
||||
|
||||
private:
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
const int8u* m_ptr;
|
||||
span m_span;
|
||||
int m_dx;
|
||||
};
|
||||
|
||||
friend class const_iterator;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void reset(int, int) {}
|
||||
unsigned num_spans() const { return m_num_spans; }
|
||||
int y() const { return m_y; }
|
||||
const_iterator begin() const { return const_iterator(*this); }
|
||||
|
||||
|
||||
private:
|
||||
//----------------------------------------------------------------
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
public:
|
||||
//----------------------------------------------------------------
|
||||
void init(const int8u* ptr, int dx, int dy)
|
||||
{
|
||||
m_ptr = ptr;
|
||||
m_y = read_int32() + dy;
|
||||
m_num_spans = unsigned(read_int32());
|
||||
m_dx = dx;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_ptr;
|
||||
int m_y;
|
||||
unsigned m_num_spans;
|
||||
int m_dx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
serialized_scanlines_adaptor_bin() :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_ptr(0),
|
||||
m_dx(0),
|
||||
m_dy(0),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
serialized_scanlines_adaptor_bin(const int8u* data, unsigned size,
|
||||
double dx, double dy) :
|
||||
m_data(data),
|
||||
m_end(data + size),
|
||||
m_ptr(data),
|
||||
m_dx(iround(dx)),
|
||||
m_dy(iround(dy)),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(const int8u* data, unsigned size, double dx, double dy)
|
||||
{
|
||||
m_data = data;
|
||||
m_end = data + size;
|
||||
m_ptr = data;
|
||||
m_dx = iround(dx);
|
||||
m_dy = iround(dy);
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
public:
|
||||
// Iterate scanlines interface
|
||||
//--------------------------------------------------------------------
|
||||
bool rewind_scanlines()
|
||||
{
|
||||
m_ptr = m_data;
|
||||
if(m_ptr < m_end)
|
||||
{
|
||||
m_min_x = read_int32() + m_dx;
|
||||
m_min_y = read_int32() + m_dy;
|
||||
m_max_x = read_int32() + m_dx;
|
||||
m_max_y = read_int32() + m_dy;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
sl.reset_spans();
|
||||
for(;;)
|
||||
{
|
||||
if(m_ptr >= m_end) return false;
|
||||
|
||||
int y = read_int32() + m_dy;
|
||||
unsigned num_spans = read_int32();
|
||||
|
||||
do
|
||||
{
|
||||
int x = read_int32() + m_dx;
|
||||
int len = read_int32();
|
||||
|
||||
if(len < 0) len = -len;
|
||||
sl.add_span(x, unsigned(len), cover_full);
|
||||
}
|
||||
while(--num_spans);
|
||||
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Specialization for embedded_scanline
|
||||
bool sweep_scanline(embedded_scanline& sl)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(m_ptr >= m_end) return false;
|
||||
|
||||
sl.init(m_ptr, m_dx, m_dy);
|
||||
|
||||
// Jump to the next scanline
|
||||
//--------------------------
|
||||
read_int32(); // Y
|
||||
int num_spans = read_int32(); // num_spans
|
||||
m_ptr += num_spans * sizeof(int32) * 2;
|
||||
}
|
||||
while(sl.num_spans() == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_data;
|
||||
const int8u* m_end;
|
||||
const int8u* m_ptr;
|
||||
int m_dx;
|
||||
int m_dy;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
517
agg/include/agg_scanline_u.h
Normal file
517
agg/include/agg_scanline_u.h
Normal file
|
@ -0,0 +1,517 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SCANLINE_U_INCLUDED
|
||||
#define AGG_SCANLINE_U_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//=============================================================scanline_u8
|
||||
//
|
||||
// Unpacked scanline container class
|
||||
//
|
||||
// This class is used to transfer data from a scanline rasterizer
|
||||
// to the rendering buffer. It's organized very simple. The class stores
|
||||
// information of horizontal spans to render it into a pixel-map buffer.
|
||||
// Each span has staring X, length, and an array of bytes that determine the
|
||||
// cover-values for each pixel.
|
||||
// Before using this class you should know the minimal and maximal pixel
|
||||
// coordinates of your scanline. The protocol of using is:
|
||||
// 1. reset(min_x, max_x)
|
||||
// 2. add_cell() / add_span() - accumulate scanline.
|
||||
// When forming one scanline the next X coordinate must be always greater
|
||||
// than the last stored one, i.e. it works only with ordered coordinates.
|
||||
// 3. Call finalize(y) and render the scanline.
|
||||
// 3. Call reset_spans() to prepare for the new scanline.
|
||||
//
|
||||
// 4. Rendering:
|
||||
//
|
||||
// Scanline provides an iterator class that allows you to extract
|
||||
// the spans and the cover values for each pixel. Be aware that clipping
|
||||
// has not been done yet, so you should perform it yourself.
|
||||
// Use scanline_u8::iterator to render spans:
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// int y = sl.y(); // Y-coordinate of the scanline
|
||||
//
|
||||
// ************************************
|
||||
// ...Perform vertical clipping here...
|
||||
// ************************************
|
||||
//
|
||||
// scanline_u8::const_iterator span = sl.begin();
|
||||
//
|
||||
// unsigned char* row = m_rbuf->row(y); // The the address of the beginning
|
||||
// // of the current row
|
||||
//
|
||||
// unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
|
||||
// // num_spans is always greater than 0.
|
||||
//
|
||||
// do
|
||||
// {
|
||||
// const scanline_u8::cover_type* covers =
|
||||
// span->covers; // The array of the cover values
|
||||
//
|
||||
// int num_pix = span->len; // Number of pixels of the span.
|
||||
// // Always greater than 0, still it's
|
||||
// // better to use "int" instead of
|
||||
// // "unsigned" because it's more
|
||||
// // convenient for clipping
|
||||
// int x = span->x;
|
||||
//
|
||||
// **************************************
|
||||
// ...Perform horizontal clipping here...
|
||||
// ...you have x, covers, and pix_count..
|
||||
// **************************************
|
||||
//
|
||||
// unsigned char* dst = row + x; // Calculate the start address of the row.
|
||||
// // In this case we assume a simple
|
||||
// // grayscale image 1-byte per pixel.
|
||||
// do
|
||||
// {
|
||||
// *dst++ = *covers++; // Hypotetical rendering.
|
||||
// }
|
||||
// while(--num_pix);
|
||||
//
|
||||
// ++span;
|
||||
// }
|
||||
// while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// The question is: why should we accumulate the whole scanline when we
|
||||
// could render just separate spans when they're ready?
|
||||
// That's because using the scanline is generally faster. When is consists
|
||||
// of more than one span the conditions for the processor cash system
|
||||
// are better, because switching between two different areas of memory
|
||||
// (that can be very large) occurs less frequently.
|
||||
//------------------------------------------------------------------------
|
||||
class scanline_u8
|
||||
{
|
||||
public:
|
||||
typedef scanline_u8 self_type;
|
||||
typedef int8u cover_type;
|
||||
typedef int16 coord_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct span
|
||||
{
|
||||
coord_type x;
|
||||
coord_type len;
|
||||
cover_type* covers;
|
||||
};
|
||||
|
||||
typedef span* iterator;
|
||||
typedef const span* const_iterator;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline_u8()
|
||||
{
|
||||
delete [] m_spans;
|
||||
delete [] m_covers;
|
||||
}
|
||||
|
||||
scanline_u8() :
|
||||
m_min_x(0),
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(0),
|
||||
m_spans(0),
|
||||
m_cur_span(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 2;
|
||||
if(max_len > m_max_len)
|
||||
{
|
||||
delete [] m_spans;
|
||||
delete [] m_covers;
|
||||
m_covers = new cover_type [max_len];
|
||||
m_spans = new span [max_len];
|
||||
m_max_len = max_len;
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_min_x = min_x;
|
||||
m_cur_span = m_spans;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
m_covers[x] = (cover_type)cover;
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->x = (coord_type)(x + m_min_x);
|
||||
m_cur_span->len = 1;
|
||||
m_cur_span->covers = m_covers + x;
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memcpy(m_covers + x, covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len += (coord_type)len;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->x = (coord_type)(x + m_min_x);
|
||||
m_cur_span->len = (coord_type)len;
|
||||
m_cur_span->covers = m_covers + x;
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memset(m_covers + x, cover, len);
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len += (coord_type)len;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->x = (coord_type)(x + m_min_x);
|
||||
m_cur_span->len = (coord_type)len;
|
||||
m_cur_span->covers = m_covers + x;
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cur_span = m_spans;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
|
||||
const_iterator begin() const { return m_spans + 1; }
|
||||
iterator begin() { return m_spans + 1; }
|
||||
|
||||
private:
|
||||
scanline_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
private:
|
||||
int m_min_x;
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
cover_type* m_covers;
|
||||
span* m_spans;
|
||||
span* m_cur_span;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================scanline_u8_am
|
||||
//
|
||||
// The scanline container with alpha-masking
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
template<class AlphaMask>
|
||||
class scanline_u8_am : public scanline_u8
|
||||
{
|
||||
public:
|
||||
typedef scanline_u8 base_type;
|
||||
typedef AlphaMask alpha_mask_type;
|
||||
typedef base_type::cover_type cover_type;
|
||||
typedef base_type::coord_type coord_type;
|
||||
|
||||
scanline_u8_am() : base_type(), m_alpha_mask(0) {}
|
||||
scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int span_y)
|
||||
{
|
||||
base_type::finalize(span_y);
|
||||
if(m_alpha_mask)
|
||||
{
|
||||
typename base_type::iterator span = base_type::begin();
|
||||
unsigned count = base_type::num_spans();
|
||||
do
|
||||
{
|
||||
m_alpha_mask->combine_hspan(span->x,
|
||||
base_type::y(),
|
||||
span->covers,
|
||||
span->len);
|
||||
++span;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const AlphaMask* m_alpha_mask;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================================================scanline32_u8
|
||||
class scanline32_u8
|
||||
{
|
||||
public:
|
||||
typedef scanline32_u8 self_type;
|
||||
typedef int8u cover_type;
|
||||
typedef int32 coord_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct span
|
||||
{
|
||||
span() {}
|
||||
span(coord_type x_, coord_type len_, cover_type* covers_) :
|
||||
x(x_), len(len_), covers(covers_) {}
|
||||
|
||||
coord_type x;
|
||||
coord_type len;
|
||||
cover_type* covers;
|
||||
};
|
||||
|
||||
typedef pod_bvector<span, 4> span_array_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator(const span_array_type& spans) :
|
||||
m_spans(spans),
|
||||
m_span_idx(0)
|
||||
{}
|
||||
|
||||
const span& operator*() const { return m_spans[m_span_idx]; }
|
||||
const span* operator->() const { return &m_spans[m_span_idx]; }
|
||||
|
||||
void operator ++ () { ++m_span_idx; }
|
||||
|
||||
private:
|
||||
const span_array_type& m_spans;
|
||||
unsigned m_span_idx;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
iterator(span_array_type& spans) :
|
||||
m_spans(spans),
|
||||
m_span_idx(0)
|
||||
{}
|
||||
|
||||
span& operator*() { return m_spans[m_span_idx]; }
|
||||
span* operator->() { return &m_spans[m_span_idx]; }
|
||||
|
||||
void operator ++ () { ++m_span_idx; }
|
||||
|
||||
private:
|
||||
span_array_type& m_spans;
|
||||
unsigned m_span_idx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline32_u8()
|
||||
{
|
||||
delete [] m_covers;
|
||||
}
|
||||
|
||||
scanline32_u8() :
|
||||
m_min_x(0),
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 2;
|
||||
if(max_len > m_max_len)
|
||||
{
|
||||
delete [] m_covers;
|
||||
m_covers = new cover_type [max_len];
|
||||
m_max_len = max_len;
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_min_x = min_x;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
m_covers[x] = cover_type(cover);
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x + m_min_x), 1, m_covers + x));
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memcpy(m_covers + x, covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x + m_min_x), coord_type(len), m_covers + x));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memset(m_covers + x, cover, len);
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x + m_min_x), coord_type(len), m_covers + x));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return m_spans.size(); }
|
||||
const_iterator begin() const { return const_iterator(m_spans); }
|
||||
iterator begin() { return iterator(m_spans); }
|
||||
|
||||
private:
|
||||
scanline32_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
private:
|
||||
int m_min_x;
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
cover_type* m_covers;
|
||||
span_array_type m_spans;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//========================================================scanline32_u8_am
|
||||
//
|
||||
// The scanline container with alpha-masking
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
template<class AlphaMask>
|
||||
class scanline32_u8_am : public scanline32_u8
|
||||
{
|
||||
public:
|
||||
typedef scanline_u8 base_type;
|
||||
typedef AlphaMask alpha_mask_type;
|
||||
typedef base_type::cover_type cover_type;
|
||||
typedef base_type::coord_type coord_type;
|
||||
|
||||
|
||||
scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
|
||||
scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int span_y)
|
||||
{
|
||||
base_type::finalize(span_y);
|
||||
if(m_alpha_mask)
|
||||
{
|
||||
typename base_type::iterator span = base_type::begin();
|
||||
unsigned count = base_type::num_spans();
|
||||
do
|
||||
{
|
||||
m_alpha_mask->combine_hspan(span->x,
|
||||
base_type::y(),
|
||||
span->covers,
|
||||
span->len);
|
||||
++span;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const AlphaMask* m_alpha_mask;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
66
agg/include/agg_shorten_path.h
Normal file
66
agg/include/agg_shorten_path.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SHORTEN_PATH_INCLUDED
|
||||
#define AGG_SHORTEN_PATH_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===========================================================shorten_path
|
||||
template<class VertexSequence>
|
||||
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
|
||||
{
|
||||
typedef typename VertexSequence::value_type vertex_type;
|
||||
|
||||
if(s > 0.0 && vs.size() > 1)
|
||||
{
|
||||
double d;
|
||||
int n = int(vs.size() - 2);
|
||||
while(n)
|
||||
{
|
||||
d = vs[n].dist;
|
||||
if(d > s) break;
|
||||
vs.remove_last();
|
||||
s -= d;
|
||||
--n;
|
||||
}
|
||||
if(vs.size() < 2)
|
||||
{
|
||||
vs.remove_all();
|
||||
}
|
||||
else
|
||||
{
|
||||
n = vs.size() - 1;
|
||||
vertex_type& prev = vs[n-1];
|
||||
vertex_type& last = vs[n];
|
||||
d = (prev.dist - s) / prev.dist;
|
||||
double x = prev.x + (last.x - prev.x) * d;
|
||||
double y = prev.y + (last.y - prev.y) * d;
|
||||
last.x = x;
|
||||
last.y = y;
|
||||
if(!prev(last)) vs.remove_last();
|
||||
vs.close(closed != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
147
agg/include/agg_simul_eq.h
Normal file
147
agg/include/agg_simul_eq.h
Normal file
|
@ -0,0 +1,147 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Solving simultaneous equations
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SIMUL_EQ_INCLUDED
|
||||
#define AGG_SIMUL_EQ_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=============================================================swap_arrays
|
||||
template<class T> void swap_arrays(T* a1, T* a2, unsigned n)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
T tmp = *a1;
|
||||
*a1++ = *a2;
|
||||
*a2++ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================matrix_pivot
|
||||
template<unsigned Rows, unsigned Cols>
|
||||
struct matrix_pivot
|
||||
{
|
||||
static int pivot(double m[Rows][Cols], unsigned row)
|
||||
{
|
||||
int k = int(row);
|
||||
double max_val, tmp;
|
||||
|
||||
max_val = -1.0;
|
||||
unsigned i;
|
||||
for(i = row; i < Rows; i++)
|
||||
{
|
||||
if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0)
|
||||
{
|
||||
max_val = tmp;
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(m[k][row] == 0.0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(k != int(row))
|
||||
{
|
||||
swap_arrays(m[k], m[row], Cols);
|
||||
return k;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//===============================================================simul_eq
|
||||
template<unsigned Size, unsigned RightCols>
|
||||
struct simul_eq
|
||||
{
|
||||
static bool solve(const double left[Size][Size],
|
||||
const double right[Size][RightCols],
|
||||
double result[Size][RightCols])
|
||||
{
|
||||
unsigned i, j, k;
|
||||
double a1;
|
||||
|
||||
double tmp[Size][Size + RightCols];
|
||||
|
||||
for(i = 0; i < Size; i++)
|
||||
{
|
||||
for(j = 0; j < Size; j++)
|
||||
{
|
||||
tmp[i][j] = left[i][j];
|
||||
}
|
||||
for(j = 0; j < RightCols; j++)
|
||||
{
|
||||
tmp[i][Size + j] = right[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
for(k = 0; k < Size; k++)
|
||||
{
|
||||
if(matrix_pivot<Size, Size + RightCols>::pivot(tmp, k) < 0)
|
||||
{
|
||||
return false; // Singularity....
|
||||
}
|
||||
|
||||
a1 = tmp[k][k];
|
||||
|
||||
for(j = k; j < Size + RightCols; j++)
|
||||
{
|
||||
tmp[k][j] /= a1;
|
||||
}
|
||||
|
||||
for(i = k + 1; i < Size; i++)
|
||||
{
|
||||
a1 = tmp[i][k];
|
||||
for (j = k; j < Size + RightCols; j++)
|
||||
{
|
||||
tmp[i][j] -= a1 * tmp[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(k = 0; k < RightCols; k++)
|
||||
{
|
||||
int m;
|
||||
for(m = int(Size - 1); m >= 0; m--)
|
||||
{
|
||||
result[m][k] = tmp[m][Size + k];
|
||||
for(j = m + 1; j < Size; j++)
|
||||
{
|
||||
result[m][k] -= tmp[m][j] * result[j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
74
agg/include/agg_span_allocator.h
Normal file
74
agg/include/agg_span_allocator.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_ALLOCATOR_INCLUDED
|
||||
#define AGG_SPAN_ALLOCATOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//----------------------------------------------------------span_allocator
|
||||
template<class ColorT> class span_allocator
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~span_allocator()
|
||||
{
|
||||
delete [] m_span;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_allocator() :
|
||||
m_max_span_len(0),
|
||||
m_span(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type* allocate(unsigned span_len)
|
||||
{
|
||||
if(span_len > m_max_span_len)
|
||||
{
|
||||
// To reduce the number of reallocs we align the
|
||||
// span_len to 256 color elements.
|
||||
// Well, I just like this number and it looks reasonable.
|
||||
//-----------------------
|
||||
delete [] m_span;
|
||||
span_len = ((span_len + 255) >> 8) << 8;
|
||||
m_span = new color_type[m_max_span_len = span_len];
|
||||
}
|
||||
return m_span;
|
||||
}
|
||||
|
||||
AGG_INLINE color_type* span() { return m_span; }
|
||||
AGG_INLINE unsigned max_span_len() const { return m_max_span_len; }
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
span_allocator(const span_allocator<ColorT>&);
|
||||
const span_allocator<ColorT>& operator = (const span_allocator<ColorT>&);
|
||||
|
||||
unsigned m_max_span_len;
|
||||
color_type* m_span;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
53
agg/include/agg_span_converter.h
Normal file
53
agg/include/agg_span_converter.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_CONVERTER_INCLUDED
|
||||
#define AGG_SPAN_CONVERTER_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//----------------------------------------------------------span_converter
|
||||
template<class SpanGenerator, class SpanConverter> class span_converter
|
||||
{
|
||||
public:
|
||||
typedef typename SpanGenerator::color_type color_type;
|
||||
|
||||
span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) :
|
||||
m_span_gen(&span_gen), m_span_cnv(&span_cnv) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare()
|
||||
{
|
||||
m_span_gen->prepare();
|
||||
m_span_cnv->prepare();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
m_span_gen->generate(span, x, y, len);
|
||||
m_span_cnv->generate(span, x, y, len);
|
||||
}
|
||||
|
||||
private:
|
||||
SpanGenerator* m_span_gen;
|
||||
SpanConverter* m_span_cnv;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
172
agg/include/agg_span_gouraud.h
Normal file
172
agg/include/agg_span_gouraud.h
Normal file
|
@ -0,0 +1,172 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_GOURAUD_INCLUDED
|
||||
#define AGG_SPAN_GOURAUD_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_math.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//============================================================span_gouraud
|
||||
template<class ColorT> class span_gouraud
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
|
||||
struct coord_type
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
color_type color;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_gouraud() :
|
||||
m_vertex(0)
|
||||
{
|
||||
m_cmd[0] = path_cmd_stop;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_gouraud(const color_type& c1,
|
||||
const color_type& c2,
|
||||
const color_type& c3,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double d) :
|
||||
m_vertex(0)
|
||||
{
|
||||
colors(c1, c2, c3);
|
||||
triangle(x1, y1, x2, y2, x3, y3, d);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void colors(ColorT c1, ColorT c2, ColorT c3)
|
||||
{
|
||||
m_coord[0].color = c1;
|
||||
m_coord[1].color = c2;
|
||||
m_coord[2].color = c3;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Sets the triangle and dilates it if needed.
|
||||
// The trick here is to calculate beveled joins in the vertices of the
|
||||
// triangle and render it as a 6-vertex polygon.
|
||||
// It's necessary to achieve numerical stability.
|
||||
// However, the coordinates to interpolate colors are calculated
|
||||
// as miter joins (calc_intersection).
|
||||
void triangle(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double d)
|
||||
{
|
||||
m_coord[0].x = m_x[0] = x1;
|
||||
m_coord[0].y = m_y[0] = y1;
|
||||
m_coord[1].x = m_x[1] = x2;
|
||||
m_coord[1].y = m_y[1] = y2;
|
||||
m_coord[2].x = m_x[2] = x3;
|
||||
m_coord[2].y = m_y[2] = y3;
|
||||
m_cmd[0] = path_cmd_move_to;
|
||||
m_cmd[1] = path_cmd_line_to;
|
||||
m_cmd[2] = path_cmd_line_to;
|
||||
m_cmd[3] = path_cmd_stop;
|
||||
|
||||
if(d != 0.0)
|
||||
{
|
||||
dilate_triangle(m_coord[0].x, m_coord[0].y,
|
||||
m_coord[1].x, m_coord[1].y,
|
||||
m_coord[2].x, m_coord[2].y,
|
||||
m_x, m_y, d);
|
||||
|
||||
calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5],
|
||||
m_x[0], m_y[0], m_x[1], m_y[1],
|
||||
&m_coord[0].x, &m_coord[0].y);
|
||||
|
||||
calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1],
|
||||
m_x[2], m_y[2], m_x[3], m_y[3],
|
||||
&m_coord[1].x, &m_coord[1].y);
|
||||
|
||||
calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3],
|
||||
m_x[4], m_y[4], m_x[5], m_y[5],
|
||||
&m_coord[2].x, &m_coord[2].y);
|
||||
m_cmd[3] = path_cmd_line_to;
|
||||
m_cmd[4] = path_cmd_line_to;
|
||||
m_cmd[5] = path_cmd_line_to;
|
||||
m_cmd[6] = path_cmd_stop;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Vertex Source Interface to feed the coordinates to the rasterizer
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_vertex = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
*x = m_x[m_vertex];
|
||||
*y = m_y[m_vertex];
|
||||
return m_cmd[m_vertex++];
|
||||
}
|
||||
|
||||
protected:
|
||||
//--------------------------------------------------------------------
|
||||
void arrange_vertices(coord_type* coord) const
|
||||
{
|
||||
coord[0] = m_coord[0];
|
||||
coord[1] = m_coord[1];
|
||||
coord[2] = m_coord[2];
|
||||
|
||||
if(m_coord[0].y > m_coord[2].y)
|
||||
{
|
||||
coord[0] = m_coord[2];
|
||||
coord[2] = m_coord[0];
|
||||
}
|
||||
|
||||
coord_type tmp;
|
||||
if(coord[0].y > coord[1].y)
|
||||
{
|
||||
tmp = coord[1];
|
||||
coord[1] = coord[0];
|
||||
coord[0] = tmp;
|
||||
}
|
||||
|
||||
if(coord[1].y > coord[2].y)
|
||||
{
|
||||
tmp = coord[2];
|
||||
coord[2] = coord[1];
|
||||
coord[1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
coord_type m_coord[3];
|
||||
double m_x[8];
|
||||
double m_y[8];
|
||||
unsigned m_cmd[8];
|
||||
unsigned m_vertex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
241
agg/include/agg_span_gouraud_gray.h
Normal file
241
agg/include/agg_span_gouraud_gray.h
Normal file
|
@ -0,0 +1,241 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_GOURAUD_GRAY_INCLUDED
|
||||
#define AGG_SPAN_GOURAUD_GRAY_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_gray.h"
|
||||
#include "agg_dda_line.h"
|
||||
#include "agg_span_gouraud.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================span_gouraud_gray
|
||||
template<class ColorT> class span_gouraud_gray : public span_gouraud<ColorT>
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef span_gouraud<color_type> base_type;
|
||||
typedef typename base_type::coord_type coord_type;
|
||||
enum subpixel_scale_e
|
||||
{
|
||||
subpixel_shift = 4,
|
||||
subpixel_scale = 1 << subpixel_shift
|
||||
};
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
struct gray_calc
|
||||
{
|
||||
void init(const coord_type& c1, const coord_type& c2)
|
||||
{
|
||||
m_x1 = c1.x - 0.5;
|
||||
m_y1 = c1.y - 0.5;
|
||||
m_dx = c2.x - c1.x;
|
||||
double dy = c2.y - c1.y;
|
||||
m_1dy = (fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy;
|
||||
m_v1 = c1.color.v;
|
||||
m_a1 = c1.color.a;
|
||||
m_dv = c2.color.v - m_v1;
|
||||
m_da = c2.color.a - m_a1;
|
||||
}
|
||||
|
||||
void calc(double y)
|
||||
{
|
||||
double k = (y - m_y1) * m_1dy;
|
||||
if(k < 0.0) k = 0.0;
|
||||
if(k > 1.0) k = 1.0;
|
||||
m_v = m_v1 + iround(m_dv * k);
|
||||
m_a = m_a1 + iround(m_da * k);
|
||||
m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
|
||||
}
|
||||
|
||||
double m_x1;
|
||||
double m_y1;
|
||||
double m_dx;
|
||||
double m_1dy;
|
||||
int m_v1;
|
||||
int m_a1;
|
||||
int m_dv;
|
||||
int m_da;
|
||||
int m_v;
|
||||
int m_a;
|
||||
int m_x;
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
span_gouraud_gray() {}
|
||||
span_gouraud_gray(const color_type& c1,
|
||||
const color_type& c2,
|
||||
const color_type& c3,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double d = 0) :
|
||||
base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare()
|
||||
{
|
||||
coord_type coord[3];
|
||||
base_type::arrange_vertices(coord);
|
||||
|
||||
m_y2 = int(coord[1].y);
|
||||
|
||||
m_swap = cross_product(coord[0].x, coord[0].y,
|
||||
coord[2].x, coord[2].y,
|
||||
coord[1].x, coord[1].y) < 0.0;
|
||||
|
||||
m_c1.init(coord[0], coord[2]);
|
||||
m_c2.init(coord[0], coord[1]);
|
||||
m_c3.init(coord[1], coord[2]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
m_c1.calc(y);
|
||||
const gray_calc* pc1 = &m_c1;
|
||||
const gray_calc* pc2 = &m_c2;
|
||||
|
||||
if(y < m_y2)
|
||||
{
|
||||
// Bottom part of the triangle (first subtriangle)
|
||||
//-------------------------
|
||||
m_c2.calc(y + m_c2.m_1dy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Upper part (second subtriangle)
|
||||
//-------------------------
|
||||
m_c3.calc(y - m_c3.m_1dy);
|
||||
pc2 = &m_c3;
|
||||
}
|
||||
|
||||
if(m_swap)
|
||||
{
|
||||
// It means that the triangle is oriented clockwise,
|
||||
// so that we need to swap the controlling structures
|
||||
//-------------------------
|
||||
const gray_calc* t = pc2;
|
||||
pc2 = pc1;
|
||||
pc1 = t;
|
||||
}
|
||||
|
||||
// Get the horizontal length with subpixel accuracy
|
||||
// and protect it from division by zero
|
||||
//-------------------------
|
||||
int nlen = abs(pc2->m_x - pc1->m_x);
|
||||
if(nlen <= 0) nlen = 1;
|
||||
|
||||
dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen);
|
||||
dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
|
||||
|
||||
// Calculate the starting point of the gradient with subpixel
|
||||
// accuracy and correct (roll back) the interpolators.
|
||||
// This operation will also clip the beginning of the span
|
||||
// if necessary.
|
||||
//-------------------------
|
||||
int start = pc1->m_x - (x << subpixel_shift);
|
||||
v -= start;
|
||||
a -= start;
|
||||
nlen += start;
|
||||
|
||||
int vv, va;
|
||||
enum lim_e { lim = color_type::base_mask };
|
||||
|
||||
// Beginning part of the span. Since we rolled back the
|
||||
// interpolators, the color values may have overflow.
|
||||
// So that, we render the beginning part with checking
|
||||
// for overflow. It lasts until "start" is positive;
|
||||
// typically it's 1-2 pixels, but may be more in some cases.
|
||||
//-------------------------
|
||||
while(len && start > 0)
|
||||
{
|
||||
vv = v.y();
|
||||
va = a.y();
|
||||
if(vv < 0) vv = 0; if(vv > lim) vv = lim;
|
||||
if(va < 0) va = 0; if(va > lim) va = lim;
|
||||
span->v = (value_type)vv;
|
||||
span->a = (value_type)va;
|
||||
v += subpixel_scale;
|
||||
a += subpixel_scale;
|
||||
nlen -= subpixel_scale;
|
||||
start -= subpixel_scale;
|
||||
++span;
|
||||
--len;
|
||||
}
|
||||
|
||||
// Middle part, no checking for overflow.
|
||||
// Actual spans can be longer than the calculated length
|
||||
// because of anti-aliasing, thus, the interpolators can
|
||||
// overflow. But while "nlen" is positive we are safe.
|
||||
//-------------------------
|
||||
while(len && nlen > 0)
|
||||
{
|
||||
span->v = (value_type)v.y();
|
||||
span->a = (value_type)a.y();
|
||||
v += subpixel_scale;
|
||||
a += subpixel_scale;
|
||||
nlen -= subpixel_scale;
|
||||
++span;
|
||||
--len;
|
||||
}
|
||||
|
||||
// Ending part; checking for overflow.
|
||||
// Typically it's 1-2 pixels, but may be more in some cases.
|
||||
//-------------------------
|
||||
while(len)
|
||||
{
|
||||
vv = v.y();
|
||||
va = a.y();
|
||||
if(vv < 0) vv = 0; if(vv > lim) vv = lim;
|
||||
if(va < 0) va = 0; if(va > lim) va = lim;
|
||||
span->v = (value_type)vv;
|
||||
span->a = (value_type)va;
|
||||
v += subpixel_scale;
|
||||
a += subpixel_scale;
|
||||
++span;
|
||||
--len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
bool m_swap;
|
||||
int m_y2;
|
||||
gray_calc m_c1;
|
||||
gray_calc m_c2;
|
||||
gray_calc m_c3;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
277
agg/include/agg_span_gouraud_rgba.h
Normal file
277
agg/include/agg_span_gouraud_rgba.h
Normal file
|
@ -0,0 +1,277 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_GOURAUD_RGBA_INCLUDED
|
||||
#define AGG_SPAN_GOURAUD_RGBA_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_dda_line.h"
|
||||
#include "agg_span_gouraud.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================span_gouraud_rgba
|
||||
template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT>
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
typedef typename ColorT::value_type value_type;
|
||||
typedef span_gouraud<color_type> base_type;
|
||||
typedef typename base_type::coord_type coord_type;
|
||||
enum subpixel_scale_e
|
||||
{
|
||||
subpixel_shift = 4,
|
||||
subpixel_scale = 1 << subpixel_shift
|
||||
};
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
struct rgba_calc
|
||||
{
|
||||
void init(const coord_type& c1, const coord_type& c2)
|
||||
{
|
||||
m_x1 = c1.x - 0.5;
|
||||
m_y1 = c1.y - 0.5;
|
||||
m_dx = c2.x - c1.x;
|
||||
double dy = c2.y - c1.y;
|
||||
m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy;
|
||||
m_r1 = c1.color.r;
|
||||
m_g1 = c1.color.g;
|
||||
m_b1 = c1.color.b;
|
||||
m_a1 = c1.color.a;
|
||||
m_dr = c2.color.r - m_r1;
|
||||
m_dg = c2.color.g - m_g1;
|
||||
m_db = c2.color.b - m_b1;
|
||||
m_da = c2.color.a - m_a1;
|
||||
}
|
||||
|
||||
void calc(double y)
|
||||
{
|
||||
double k = (y - m_y1) * m_1dy;
|
||||
if(k < 0.0) k = 0.0;
|
||||
if(k > 1.0) k = 1.0;
|
||||
m_r = m_r1 + iround(m_dr * k);
|
||||
m_g = m_g1 + iround(m_dg * k);
|
||||
m_b = m_b1 + iround(m_db * k);
|
||||
m_a = m_a1 + iround(m_da * k);
|
||||
m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
|
||||
}
|
||||
|
||||
double m_x1;
|
||||
double m_y1;
|
||||
double m_dx;
|
||||
double m_1dy;
|
||||
int m_r1;
|
||||
int m_g1;
|
||||
int m_b1;
|
||||
int m_a1;
|
||||
int m_dr;
|
||||
int m_dg;
|
||||
int m_db;
|
||||
int m_da;
|
||||
int m_r;
|
||||
int m_g;
|
||||
int m_b;
|
||||
int m_a;
|
||||
int m_x;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_gouraud_rgba() {}
|
||||
span_gouraud_rgba(const color_type& c1,
|
||||
const color_type& c2,
|
||||
const color_type& c3,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double d = 0) :
|
||||
base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare()
|
||||
{
|
||||
coord_type coord[3];
|
||||
base_type::arrange_vertices(coord);
|
||||
|
||||
m_y2 = int(coord[1].y);
|
||||
|
||||
m_swap = cross_product(coord[0].x, coord[0].y,
|
||||
coord[2].x, coord[2].y,
|
||||
coord[1].x, coord[1].y) < 0.0;
|
||||
|
||||
m_rgba1.init(coord[0], coord[2]);
|
||||
m_rgba2.init(coord[0], coord[1]);
|
||||
m_rgba3.init(coord[1], coord[2]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
|
||||
const rgba_calc* pc1 = &m_rgba1;
|
||||
const rgba_calc* pc2 = &m_rgba2;
|
||||
|
||||
if(y <= m_y2)
|
||||
{
|
||||
// Bottom part of the triangle (first subtriangle)
|
||||
//-------------------------
|
||||
m_rgba2.calc(y + m_rgba2.m_1dy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Upper part (second subtriangle)
|
||||
m_rgba3.calc(y - m_rgba3.m_1dy);
|
||||
//-------------------------
|
||||
pc2 = &m_rgba3;
|
||||
}
|
||||
|
||||
if(m_swap)
|
||||
{
|
||||
// It means that the triangle is oriented clockwise,
|
||||
// so that we need to swap the controlling structures
|
||||
//-------------------------
|
||||
const rgba_calc* t = pc2;
|
||||
pc2 = pc1;
|
||||
pc1 = t;
|
||||
}
|
||||
|
||||
// Get the horizontal length with subpixel accuracy
|
||||
// and protect it from division by zero
|
||||
//-------------------------
|
||||
int nlen = abs(pc2->m_x - pc1->m_x);
|
||||
if(nlen <= 0) nlen = 1;
|
||||
|
||||
dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen);
|
||||
dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen);
|
||||
dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen);
|
||||
dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
|
||||
|
||||
// Calculate the starting point of the gradient with subpixel
|
||||
// accuracy and correct (roll back) the interpolators.
|
||||
// This operation will also clip the beginning of the span
|
||||
// if necessary.
|
||||
//-------------------------
|
||||
int start = pc1->m_x - (x << subpixel_shift);
|
||||
r -= start;
|
||||
g -= start;
|
||||
b -= start;
|
||||
a -= start;
|
||||
nlen += start;
|
||||
|
||||
int vr, vg, vb, va;
|
||||
enum lim_e { lim = color_type::base_mask };
|
||||
|
||||
// Beginning part of the span. Since we rolled back the
|
||||
// interpolators, the color values may have overflow.
|
||||
// So that, we render the beginning part with checking
|
||||
// for overflow. It lasts until "start" is positive;
|
||||
// typically it's 1-2 pixels, but may be more in some cases.
|
||||
//-------------------------
|
||||
while(len && start > 0)
|
||||
{
|
||||
vr = r.y();
|
||||
vg = g.y();
|
||||
vb = b.y();
|
||||
va = a.y();
|
||||
if(vr < 0) vr = 0; if(vr > lim) vr = lim;
|
||||
if(vg < 0) vg = 0; if(vg > lim) vg = lim;
|
||||
if(vb < 0) vb = 0; if(vb > lim) vb = lim;
|
||||
if(va < 0) va = 0; if(va > lim) va = lim;
|
||||
span->r = (value_type)vr;
|
||||
span->g = (value_type)vg;
|
||||
span->b = (value_type)vb;
|
||||
span->a = (value_type)va;
|
||||
r += subpixel_scale;
|
||||
g += subpixel_scale;
|
||||
b += subpixel_scale;
|
||||
a += subpixel_scale;
|
||||
nlen -= subpixel_scale;
|
||||
start -= subpixel_scale;
|
||||
++span;
|
||||
--len;
|
||||
}
|
||||
|
||||
// Middle part, no checking for overflow.
|
||||
// Actual spans can be longer than the calculated length
|
||||
// because of anti-aliasing, thus, the interpolators can
|
||||
// overflow. But while "nlen" is positive we are safe.
|
||||
//-------------------------
|
||||
while(len && nlen > 0)
|
||||
{
|
||||
span->r = (value_type)r.y();
|
||||
span->g = (value_type)g.y();
|
||||
span->b = (value_type)b.y();
|
||||
span->a = (value_type)a.y();
|
||||
r += subpixel_scale;
|
||||
g += subpixel_scale;
|
||||
b += subpixel_scale;
|
||||
a += subpixel_scale;
|
||||
nlen -= subpixel_scale;
|
||||
++span;
|
||||
--len;
|
||||
}
|
||||
|
||||
// Ending part; checking for overflow.
|
||||
// Typically it's 1-2 pixels, but may be more in some cases.
|
||||
//-------------------------
|
||||
while(len)
|
||||
{
|
||||
vr = r.y();
|
||||
vg = g.y();
|
||||
vb = b.y();
|
||||
va = a.y();
|
||||
if(vr < 0) vr = 0; if(vr > lim) vr = lim;
|
||||
if(vg < 0) vg = 0; if(vg > lim) vg = lim;
|
||||
if(vb < 0) vb = 0; if(vb > lim) vb = lim;
|
||||
if(va < 0) va = 0; if(va > lim) va = lim;
|
||||
span->r = (value_type)vr;
|
||||
span->g = (value_type)vg;
|
||||
span->b = (value_type)vb;
|
||||
span->a = (value_type)va;
|
||||
r += subpixel_scale;
|
||||
g += subpixel_scale;
|
||||
b += subpixel_scale;
|
||||
a += subpixel_scale;
|
||||
++span;
|
||||
--len;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_swap;
|
||||
int m_y2;
|
||||
rgba_calc m_rgba1;
|
||||
rgba_calc m_rgba2;
|
||||
rgba_calc m_rgba3;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
417
agg/include/agg_span_gradient.h
Normal file
417
agg/include/agg_span_gradient.h
Normal file
|
@ -0,0 +1,417 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_GRADIENT_INCLUDED
|
||||
#define AGG_SPAN_GRADIENT_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_math.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
enum gradient_subpixel_scale_e
|
||||
{
|
||||
gradient_subpixel_shift = 4, //-----gradient_subpixel_shift
|
||||
gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale
|
||||
gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==========================================================span_gradient
|
||||
template<class ColorT,
|
||||
class Interpolator,
|
||||
class GradientF,
|
||||
class ColorF>
|
||||
class span_gradient
|
||||
{
|
||||
public:
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef ColorT color_type;
|
||||
|
||||
enum downscale_shift_e
|
||||
{
|
||||
downscale_shift = interpolator_type::subpixel_shift -
|
||||
gradient_subpixel_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_gradient() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_gradient(interpolator_type& inter,
|
||||
const GradientF& gradient_function,
|
||||
const ColorF& color_function,
|
||||
double d1, double d2) :
|
||||
m_interpolator(&inter),
|
||||
m_gradient_function(&gradient_function),
|
||||
m_color_function(&color_function),
|
||||
m_d1(iround(d1 * gradient_subpixel_scale)),
|
||||
m_d2(iround(d2 * gradient_subpixel_scale))
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
interpolator_type& interpolator() { return *m_interpolator; }
|
||||
const GradientF& gradient_function() const { return *m_gradient_function; }
|
||||
const ColorF& color_function() const { return *m_color_function; }
|
||||
double d1() const { return double(m_d1) / gradient_subpixel_scale; }
|
||||
double d2() const { return double(m_d2) / gradient_subpixel_scale; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void interpolator(interpolator_type& i) { m_interpolator = &i; }
|
||||
void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
|
||||
void color_function(const ColorF& cf) { m_color_function = &cf; }
|
||||
void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
|
||||
void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
int dd = m_d2 - m_d1;
|
||||
if(dd < 1) dd = 1;
|
||||
m_interpolator->begin(x+0.5, y+0.5, len);
|
||||
do
|
||||
{
|
||||
m_interpolator->coordinates(&x, &y);
|
||||
int d = m_gradient_function->calculate(x >> downscale_shift,
|
||||
y >> downscale_shift, m_d2);
|
||||
d = ((d - m_d1) * (int)m_color_function->size()) / dd;
|
||||
if(d < 0) d = 0;
|
||||
if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1;
|
||||
*span++ = (*m_color_function)[d];
|
||||
++(*m_interpolator);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
private:
|
||||
interpolator_type* m_interpolator;
|
||||
const GradientF* m_gradient_function;
|
||||
const ColorF* m_color_function;
|
||||
int m_d1;
|
||||
int m_d2;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================================================gradient_linear_color
|
||||
template<class ColorT>
|
||||
struct gradient_linear_color
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
|
||||
gradient_linear_color() {}
|
||||
gradient_linear_color(const color_type& c1, const color_type& c2,
|
||||
unsigned size = 256) :
|
||||
m_c1(c1), m_c2(c2), m_size(size) {}
|
||||
|
||||
unsigned size() const { return m_size; }
|
||||
color_type operator [] (unsigned v) const
|
||||
{
|
||||
return m_c1.gradient(m_c2, double(v) / double(m_size - 1));
|
||||
}
|
||||
|
||||
void colors(const color_type& c1, const color_type& c2, unsigned size = 256)
|
||||
{
|
||||
m_c1 = c1;
|
||||
m_c2 = c2;
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
color_type m_c1;
|
||||
color_type m_c2;
|
||||
unsigned m_size;
|
||||
};
|
||||
|
||||
|
||||
//==========================================================gradient_circle
|
||||
class gradient_circle
|
||||
{
|
||||
// Actually the same as radial. Just for compatibility
|
||||
public:
|
||||
static AGG_INLINE int calculate(int x, int y, int)
|
||||
{
|
||||
return int(fast_sqrt(x*x + y*y));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==========================================================gradient_radial
|
||||
class gradient_radial
|
||||
{
|
||||
public:
|
||||
static AGG_INLINE int calculate(int x, int y, int)
|
||||
{
|
||||
return int(fast_sqrt(x*x + y*y));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//========================================================gradient_radial_d
|
||||
class gradient_radial_d
|
||||
{
|
||||
public:
|
||||
static AGG_INLINE int calculate(int x, int y, int)
|
||||
{
|
||||
return uround(sqrt(double(x)*double(x) + double(y)*double(y)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//====================================================gradient_radial_focus
|
||||
class gradient_radial_focus
|
||||
{
|
||||
public:
|
||||
//---------------------------------------------------------------------
|
||||
gradient_radial_focus() :
|
||||
m_radius(100 * gradient_subpixel_scale),
|
||||
m_focus_x(0),
|
||||
m_focus_y(0)
|
||||
{
|
||||
update_values();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
gradient_radial_focus(double r, double fx, double fy) :
|
||||
m_radius (iround(r * gradient_subpixel_scale)),
|
||||
m_focus_x(iround(fx * gradient_subpixel_scale)),
|
||||
m_focus_y(iround(fy * gradient_subpixel_scale))
|
||||
{
|
||||
update_values();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void init(double r, double fx, double fy)
|
||||
{
|
||||
m_radius = iround(r * gradient_subpixel_scale);
|
||||
m_focus_x = iround(fx * gradient_subpixel_scale);
|
||||
m_focus_y = iround(fy * gradient_subpixel_scale);
|
||||
update_values();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
double radius() const { return double(m_radius) / gradient_subpixel_scale; }
|
||||
double focus_x() const { return double(m_focus_x) / gradient_subpixel_scale; }
|
||||
double focus_y() const { return double(m_focus_y) / gradient_subpixel_scale; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
int calculate(int x, int y, int) const
|
||||
{
|
||||
double solution_x;
|
||||
double solution_y;
|
||||
|
||||
// Special case to avoid divide by zero or very near zero
|
||||
//---------------------------------
|
||||
if(x == iround(m_focus_x))
|
||||
{
|
||||
solution_x = m_focus_x;
|
||||
solution_y = 0.0;
|
||||
solution_y += (y > m_focus_y) ? m_trivial : -m_trivial;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Slope of the focus-current line
|
||||
//-------------------------------
|
||||
double slope = double(y - m_focus_y) / double(x - m_focus_x);
|
||||
|
||||
// y-intercept of that same line
|
||||
//--------------------------------
|
||||
double yint = double(y) - (slope * x);
|
||||
|
||||
// Use the classical quadratic formula to calculate
|
||||
// the intersection point
|
||||
//--------------------------------
|
||||
double a = (slope * slope) + 1;
|
||||
double b = 2 * slope * yint;
|
||||
double c = yint * yint - m_radius2;
|
||||
double det = sqrt((b * b) - (4.0 * a * c));
|
||||
solution_x = -b;
|
||||
|
||||
// Choose the positive or negative root depending
|
||||
// on where the X coord lies with respect to the focus.
|
||||
solution_x += (x < m_focus_x) ? -det : det;
|
||||
solution_x /= 2.0 * a;
|
||||
|
||||
// Calculating of Y is trivial
|
||||
solution_y = (slope * solution_x) + yint;
|
||||
}
|
||||
|
||||
// Calculate the percentage (0...1) of the current point along the
|
||||
// focus-circumference line and return the normalized (0...d) value
|
||||
//-------------------------------
|
||||
solution_x -= double(m_focus_x);
|
||||
solution_y -= double(m_focus_y);
|
||||
double int_to_focus = solution_x * solution_x + solution_y * solution_y;
|
||||
double cur_to_focus = double(x - m_focus_x) * double(x - m_focus_x) +
|
||||
double(y - m_focus_y) * double(y - m_focus_y);
|
||||
|
||||
return iround(sqrt(cur_to_focus / int_to_focus) * m_radius);
|
||||
}
|
||||
|
||||
private:
|
||||
//---------------------------------------------------------------------
|
||||
void update_values()
|
||||
{
|
||||
// For use in the quadratic equation
|
||||
//-------------------------------
|
||||
m_radius2 = double(m_radius) * double(m_radius);
|
||||
|
||||
double dist = sqrt(double(m_focus_x) * double(m_focus_x) +
|
||||
double(m_focus_y) * double(m_focus_y));
|
||||
|
||||
// Test if distance from focus to center is greater than the radius
|
||||
// For the sake of assurance factor restrict the point to be
|
||||
// no further than 99% of the radius.
|
||||
//-------------------------------
|
||||
double r = m_radius * 0.99;
|
||||
if(dist > r)
|
||||
{
|
||||
// clamp focus to radius
|
||||
// x = r cos theta, y = r sin theta
|
||||
//------------------------
|
||||
double a = atan2(double(m_focus_y), double(m_focus_x));
|
||||
m_focus_x = iround(r * cos(a));
|
||||
m_focus_y = iround(r * sin(a));
|
||||
}
|
||||
|
||||
// Calculate the solution to be used in the case where x == focus_x
|
||||
//------------------------------
|
||||
m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x));
|
||||
}
|
||||
|
||||
int m_radius;
|
||||
int m_focus_x;
|
||||
int m_focus_y;
|
||||
double m_radius2;
|
||||
double m_trivial;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==============================================================gradient_x
|
||||
class gradient_x
|
||||
{
|
||||
public:
|
||||
static int calculate(int x, int, int) { return x; }
|
||||
};
|
||||
|
||||
|
||||
//==============================================================gradient_y
|
||||
class gradient_y
|
||||
{
|
||||
public:
|
||||
static int calculate(int, int y, int) { return y; }
|
||||
};
|
||||
|
||||
|
||||
//========================================================gradient_diamond
|
||||
class gradient_diamond
|
||||
{
|
||||
public:
|
||||
static AGG_INLINE int calculate(int x, int y, int)
|
||||
{
|
||||
int ax = abs(x);
|
||||
int ay = abs(y);
|
||||
return ax > ay ? ax : ay;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================gradient_xy
|
||||
class gradient_xy
|
||||
{
|
||||
public:
|
||||
static AGG_INLINE int calculate(int x, int y, int d)
|
||||
{
|
||||
return abs(x) * abs(y) / d;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//========================================================gradient_sqrt_xy
|
||||
class gradient_sqrt_xy
|
||||
{
|
||||
public:
|
||||
static AGG_INLINE int calculate(int x, int y, int)
|
||||
{
|
||||
return fast_sqrt(abs(x) * abs(y));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==========================================================gradient_conic
|
||||
class gradient_conic
|
||||
{
|
||||
public:
|
||||
static AGG_INLINE int calculate(int x, int y, int d)
|
||||
{
|
||||
return uround(fabs(atan2(double(y), double(x))) * double(d) / pi);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=================================================gradient_repeat_adaptor
|
||||
template<class GradientF> class gradient_repeat_adaptor
|
||||
{
|
||||
public:
|
||||
gradient_repeat_adaptor(const GradientF& gradient) :
|
||||
m_gradient(&gradient) {}
|
||||
|
||||
AGG_INLINE int calculate(int x, int y, int d) const
|
||||
{
|
||||
int ret = m_gradient->calculate(x, y, d) % d;
|
||||
if(ret < 0) ret += d;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
const GradientF* m_gradient;
|
||||
};
|
||||
|
||||
|
||||
//================================================gradient_reflect_adaptor
|
||||
template<class GradientF> class gradient_reflect_adaptor
|
||||
{
|
||||
public:
|
||||
gradient_reflect_adaptor(const GradientF& gradient) :
|
||||
m_gradient(&gradient) {}
|
||||
|
||||
AGG_INLINE int calculate(int x, int y, int d) const
|
||||
{
|
||||
int d2 = d << 1;
|
||||
int ret = m_gradient->calculate(x, y, d) % d2;
|
||||
if(ret < 0) ret += d2;
|
||||
if(ret >= d) ret = d2 - ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
const GradientF* m_gradient;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
126
agg/include/agg_span_gradient_alpha.h
Normal file
126
agg/include/agg_span_gradient_alpha.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_GRADIENT_ALPHA_INCLUDED
|
||||
#define AGG_SPAN_GRADIENT_ALPHA_INCLUDED
|
||||
|
||||
#include "agg_span_gradient.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//======================================================span_gradient_alpha
|
||||
template<class ColorT,
|
||||
class Interpolator,
|
||||
class GradientF,
|
||||
class AlphaF>
|
||||
class span_gradient_alpha
|
||||
{
|
||||
public:
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type alpha_type;
|
||||
|
||||
enum downscale_shift_e
|
||||
{
|
||||
downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_gradient_alpha() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_gradient_alpha(interpolator_type& inter,
|
||||
const GradientF& gradient_function,
|
||||
const AlphaF& alpha_function,
|
||||
double d1, double d2) :
|
||||
m_interpolator(&inter),
|
||||
m_gradient_function(&gradient_function),
|
||||
m_alpha_function(&alpha_function),
|
||||
m_d1(iround(d1 * gradient_subpixel_scale)),
|
||||
m_d2(iround(d2 * gradient_subpixel_scale))
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
interpolator_type& interpolator() { return *m_interpolator; }
|
||||
const GradientF& gradient_function() const { return *m_gradient_function; }
|
||||
const AlphaF& alpha_function() const { return *m_alpha_function; }
|
||||
double d1() const { return double(m_d1) / gradient_subpixel_scale; }
|
||||
double d2() const { return double(m_d2) / gradient_subpixel_scale; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void interpolator(interpolator_type& i) { m_interpolator = &i; }
|
||||
void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
|
||||
void alpha_function(const AlphaF& af) { m_alpha_function = ⁡ }
|
||||
void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
|
||||
void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
int dd = m_d2 - m_d1;
|
||||
if(dd < 1) dd = 1;
|
||||
m_interpolator->begin(x+0.5, y+0.5, len);
|
||||
do
|
||||
{
|
||||
m_interpolator->coordinates(&x, &y);
|
||||
int d = m_gradient_function->calculate(x >> downscale_shift,
|
||||
y >> downscale_shift, m_d2);
|
||||
d = ((d - m_d1) * (int)m_alpha_function->size()) / dd;
|
||||
if(d < 0) d = 0;
|
||||
if(d >= (int)m_alpha_function->size()) d = m_alpha_function->size() - 1;
|
||||
span->a = (*m_alpha_function)[d];
|
||||
++span;
|
||||
++(*m_interpolator);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
private:
|
||||
interpolator_type* m_interpolator;
|
||||
const GradientF* m_gradient_function;
|
||||
const AlphaF* m_alpha_function;
|
||||
int m_d1;
|
||||
int m_d2;
|
||||
};
|
||||
|
||||
|
||||
//=======================================================gradient_alpha_x
|
||||
template<class ColorT> struct gradient_alpha_x
|
||||
{
|
||||
typedef typename ColorT::value_type alpha_type;
|
||||
alpha_type operator [] (alpha_type x) const { return x; }
|
||||
};
|
||||
|
||||
//====================================================gradient_alpha_x_u8
|
||||
struct gradient_alpha_x_u8
|
||||
{
|
||||
typedef int8u alpha_type;
|
||||
alpha_type operator [] (alpha_type x) const { return x; }
|
||||
};
|
||||
|
||||
//==========================================gradient_alpha_one_munus_x_u8
|
||||
struct gradient_alpha_one_munus_x_u8
|
||||
{
|
||||
typedef int8u alpha_type;
|
||||
alpha_type operator [] (alpha_type x) const { return 255-x; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
232
agg/include/agg_span_image_filter.h
Normal file
232
agg/include/agg_span_image_filter.h
Normal file
|
@ -0,0 +1,232 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Image transformations with filtering. Span generator base class
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED
|
||||
#define AGG_SPAN_IMAGE_FILTER_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_image_filters.h"
|
||||
#include "agg_span_interpolator_linear.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-------------------------------------------------------span_image_filter
|
||||
template<class Source, class Interpolator> class span_image_filter
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter() {}
|
||||
span_image_filter(source_type& src,
|
||||
interpolator_type& interpolator,
|
||||
const image_filter_lut* filter) :
|
||||
m_src(&src),
|
||||
m_interpolator(&interpolator),
|
||||
m_filter(filter),
|
||||
m_dx_dbl(0.5),
|
||||
m_dy_dbl(0.5),
|
||||
m_dx_int(image_subpixel_scale / 2),
|
||||
m_dy_int(image_subpixel_scale / 2)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
source_type& source() { return *m_src; }
|
||||
const source_type& source() const { return *m_src; }
|
||||
const image_filter_lut& filter() const { return *m_filter; }
|
||||
int filter_dx_int() const { return m_dx_int; }
|
||||
int filter_dy_int() const { return m_dy_int; }
|
||||
double filter_dx_dbl() const { return m_dx_dbl; }
|
||||
double filter_dy_dbl() const { return m_dy_dbl; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void set_source(source_type& v) { m_src = &v; }
|
||||
void interpolator(interpolator_type& v) { m_interpolator = &v; }
|
||||
void filter(const image_filter_lut& v) { m_filter = &v; }
|
||||
void filter_offset(double dx, double dy)
|
||||
{
|
||||
m_dx_dbl = dx;
|
||||
m_dy_dbl = dy;
|
||||
m_dx_int = iround(dx * image_subpixel_scale);
|
||||
m_dy_int = iround(dy * image_subpixel_scale);
|
||||
}
|
||||
void filter_offset(double d) { filter_offset(d, d); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
interpolator_type& interpolator() { return *m_interpolator; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
private:
|
||||
source_type* m_src;
|
||||
interpolator_type* m_interpolator;
|
||||
const image_filter_lut* m_filter;
|
||||
double m_dx_dbl;
|
||||
double m_dy_dbl;
|
||||
unsigned m_dx_int;
|
||||
unsigned m_dy_int;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//==============================================span_image_resample_affine
|
||||
template<class Source>
|
||||
class span_image_resample_affine :
|
||||
public span_image_filter<Source, span_interpolator_linear<trans_affine> >
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef span_interpolator_linear<trans_affine> interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample_affine() :
|
||||
m_scale_limit(200.0),
|
||||
m_blur_x(1.0),
|
||||
m_blur_y(1.0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample_affine(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, &filter),
|
||||
m_scale_limit(200.0),
|
||||
m_blur_x(1.0),
|
||||
m_blur_y(1.0)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int scale_limit() const { return uround(m_scale_limit); }
|
||||
void scale_limit(int v) { m_scale_limit = v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double blur_x() const { return m_blur_x; }
|
||||
double blur_y() const { return m_blur_y; }
|
||||
void blur_x(double v) { m_blur_x = v; }
|
||||
void blur_y(double v) { m_blur_y = v; }
|
||||
void blur(double v) { m_blur_x = m_blur_y = v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare()
|
||||
{
|
||||
double scale_x;
|
||||
double scale_y;
|
||||
|
||||
base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
|
||||
|
||||
m_rx = image_subpixel_scale;
|
||||
m_ry = image_subpixel_scale;
|
||||
m_rx_inv = image_subpixel_scale;
|
||||
m_ry_inv = image_subpixel_scale;
|
||||
|
||||
scale_x *= m_blur_x;
|
||||
scale_y *= m_blur_y;
|
||||
|
||||
if(scale_x * scale_y > m_scale_limit)
|
||||
{
|
||||
scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
|
||||
scale_y = scale_y * m_scale_limit / (scale_x * scale_y);
|
||||
}
|
||||
|
||||
if(scale_x > 1.0001)
|
||||
{
|
||||
if(scale_x > m_scale_limit) scale_x = m_scale_limit;
|
||||
m_rx = uround( scale_x * double(image_subpixel_scale));
|
||||
m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale));
|
||||
}
|
||||
|
||||
if(scale_y > 1.0001)
|
||||
{
|
||||
if(scale_y > m_scale_limit) scale_y = m_scale_limit;
|
||||
m_ry = uround( scale_y * double(image_subpixel_scale));
|
||||
m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_rx;
|
||||
int m_ry;
|
||||
int m_rx_inv;
|
||||
int m_ry_inv;
|
||||
|
||||
private:
|
||||
double m_scale_limit;
|
||||
double m_blur_x;
|
||||
double m_blur_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================================span_image_resample
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_resample :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample() :
|
||||
m_scale_limit(20),
|
||||
m_blur_x(image_subpixel_scale),
|
||||
m_blur_y(image_subpixel_scale)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, &filter),
|
||||
m_scale_limit(20),
|
||||
m_blur_x(image_subpixel_scale),
|
||||
m_blur_y(image_subpixel_scale)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int scale_limit() const { return m_scale_limit; }
|
||||
void scale_limit(int v) { m_scale_limit = v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); }
|
||||
double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); }
|
||||
void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); }
|
||||
void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); }
|
||||
void blur(double v) { m_blur_x =
|
||||
m_blur_y = uround(v * double(image_subpixel_scale)); }
|
||||
|
||||
protected:
|
||||
int m_scale_limit;
|
||||
int m_blur_x;
|
||||
int m_blur_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
774
agg/include/agg_span_image_filter_gray.h
Normal file
774
agg/include/agg_span_image_filter_gray.h
Normal file
|
@ -0,0 +1,774 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED
|
||||
#define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_gray.h"
|
||||
#include "agg_span_image_filter.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//==============================================span_image_filter_gray_nn
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_gray_nn :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_gray_nn() {}
|
||||
span_image_filter_gray_nn(source_type& src,
|
||||
interpolator_type& inter) :
|
||||
base_type(src, inter, 0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
span->v = *(const value_type*)
|
||||
base_type::source().span(x >> image_subpixel_shift,
|
||||
y >> image_subpixel_shift,
|
||||
1);
|
||||
span->a = base_mask;
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=========================================span_image_filter_gray_bilinear
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_gray_bilinear :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_gray_bilinear() {}
|
||||
span_image_filter_gray_bilinear(source_type& src,
|
||||
interpolator_type& inter) :
|
||||
base_type(src, inter, 0)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
calc_type fg;
|
||||
const value_type *fg_ptr;
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
unsigned weight;
|
||||
fg = image_subpixel_scale * image_subpixel_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
|
||||
fg += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr);
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
fg += *fg_ptr * x_hr * (image_subpixel_scale - y_hr);
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
fg += fg_ptr * x_hr * y_hr;
|
||||
|
||||
span->v = value_type(fg >> (image_subpixel_shift * 2));
|
||||
span->a = base_mask;
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//====================================span_image_filter_gray_bilinear_clip
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_gray_bilinear_clip :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_gray_bilinear_clip() {}
|
||||
span_image_filter_gray_bilinear_clip(source_type& src,
|
||||
const color_type& back_color,
|
||||
interpolator_type& inter) :
|
||||
base_type(src, inter, 0),
|
||||
m_back_color(back_color)
|
||||
{}
|
||||
const color_type& background_color() const { return m_back_color; }
|
||||
void background_color(const color_type& v) { m_back_color = v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
calc_type fg;
|
||||
calc_type src_alpha;
|
||||
value_type back_v = m_back_color.v;
|
||||
value_type back_a = m_back_color.a;
|
||||
|
||||
const value_type *fg_ptr;
|
||||
|
||||
int maxx = base_type::source().width() - 1;
|
||||
int maxy = base_type::source().height() - 1;
|
||||
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr < maxx && y_lr < maxy)
|
||||
{
|
||||
fg = image_subpixel_scale * image_subpixel_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr;
|
||||
|
||||
fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr);
|
||||
fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr;
|
||||
|
||||
++y_lr;
|
||||
fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr;
|
||||
|
||||
fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr;
|
||||
fg += *fg_ptr++ * x_hr * y_hr;
|
||||
|
||||
fg >>= image_subpixel_shift * 2;
|
||||
src_alpha = base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned weight;
|
||||
if(x_lr < -1 || y_lr < -1 ||
|
||||
x_lr > maxx || y_lr > maxy)
|
||||
{
|
||||
fg = back_v;
|
||||
src_alpha = back_a;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg =
|
||||
src_alpha = image_subpixel_scale * image_subpixel_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) *
|
||||
(image_subpixel_scale - y_hr);
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg += weight *
|
||||
*((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
|
||||
src_alpha += weight * base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg += back_v * weight;
|
||||
src_alpha += back_a * weight;
|
||||
}
|
||||
|
||||
x_lr++;
|
||||
|
||||
weight = x_hr * (image_subpixel_scale - y_hr);
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg += weight *
|
||||
*((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
|
||||
src_alpha += weight * base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg += back_v * weight;
|
||||
src_alpha += back_a * weight;
|
||||
}
|
||||
|
||||
x_lr--;
|
||||
y_lr++;
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) * y_hr;
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg += weight *
|
||||
*((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
|
||||
src_alpha += weight * base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg += back_v * weight;
|
||||
src_alpha += back_a * weight;
|
||||
}
|
||||
|
||||
x_lr++;
|
||||
|
||||
weight = x_hr * y_hr;
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg += weight *
|
||||
*((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
|
||||
src_alpha += weight * base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg += back_v * weight;
|
||||
src_alpha += back_a * weight;
|
||||
}
|
||||
|
||||
fg >>= image_subpixel_shift * 2;
|
||||
src_alpha >>= image_subpixel_shift * 2;
|
||||
}
|
||||
}
|
||||
|
||||
span->v = (value_type)fg;
|
||||
span->a = (value_type)src_alpha;
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
private:
|
||||
color_type m_back_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==============================================span_image_filter_gray_2x2
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_gray_2x2 :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_gray_2x2() {}
|
||||
span_image_filter_gray_2x2(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, &filter)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
calc_type fg;
|
||||
|
||||
const value_type *fg_ptr;
|
||||
const int16* weight_array = base_type::filter().weight_array() +
|
||||
((base_type::filter().diameter()/2 - 1) <<
|
||||
image_subpixel_shift);
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
unsigned weight;
|
||||
fg = image_filter_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
|
||||
weight = (weight_array[x_hr + image_subpixel_scale] *
|
||||
weight_array[y_hr + image_subpixel_scale] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = (weight_array[x_hr] *
|
||||
weight_array[y_hr + image_subpixel_scale] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
weight = (weight_array[x_hr + image_subpixel_scale] *
|
||||
weight_array[y_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = (weight_array[x_hr] *
|
||||
weight_array[y_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg += weight * *fg_ptr;
|
||||
|
||||
fg >>= image_filter_shift;
|
||||
if(fg > base_mask) fg = base_mask;
|
||||
|
||||
span->v = (value_type)fg;
|
||||
span->a = base_mask;
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==================================================span_image_filter_gray
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_gray :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_gray() {}
|
||||
span_image_filter_gray(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, &filter)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
int fg;
|
||||
const value_type *fg_ptr;
|
||||
|
||||
unsigned diameter = base_type::filter().diameter();
|
||||
int start = base_type::filter().start();
|
||||
const int16* weight_array = base_type::filter().weight_array();
|
||||
|
||||
int x_count;
|
||||
int weight_y;
|
||||
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x -= base_type::filter_dx_int();
|
||||
y -= base_type::filter_dy_int();
|
||||
|
||||
int x_hr = x;
|
||||
int y_hr = y;
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
fg = image_filter_scale / 2;
|
||||
|
||||
int x_fract = x_hr & image_subpixel_mask;
|
||||
unsigned y_count = diameter;
|
||||
|
||||
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||
fg_ptr = (const value_type*)base_type::source().span(x_lr + start,
|
||||
y_lr + start,
|
||||
diameter);
|
||||
for(;;)
|
||||
{
|
||||
x_count = diameter;
|
||||
weight_y = weight_array[y_hr];
|
||||
x_hr = image_subpixel_mask - x_fract;
|
||||
for(;;)
|
||||
{
|
||||
fg += *fg_ptr *
|
||||
((weight_y * weight_array[x_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift);
|
||||
if(--x_count == 0) break;
|
||||
x_hr += image_subpixel_scale;
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
}
|
||||
|
||||
if(--y_count == 0) break;
|
||||
y_hr += image_subpixel_scale;
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
}
|
||||
|
||||
fg >>= image_filter_shift;
|
||||
if(fg < 0) fg = 0;
|
||||
if(fg > base_mask) fg = base_mask;
|
||||
span->v = (value_type)fg;
|
||||
span->a = base_mask;
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=========================================span_image_resample_gray_affine
|
||||
template<class Source>
|
||||
class span_image_resample_gray_affine :
|
||||
public span_image_resample_affine<Source>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef span_image_resample_affine<source_type> base_type;
|
||||
typedef typename base_type::interpolator_type interpolator_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask,
|
||||
downscale_shift = image_filter_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample_gray_affine() {}
|
||||
span_image_resample_gray_affine(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, filter)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
long_type fg;
|
||||
|
||||
int diameter = base_type::filter().diameter();
|
||||
int filter_scale = diameter << image_subpixel_shift;
|
||||
int radius_x = (diameter * base_type::m_rx) >> 1;
|
||||
int radius_y = (diameter * base_type::m_ry) >> 1;
|
||||
int len_x_lr =
|
||||
(diameter * base_type::m_rx + image_subpixel_mask) >>
|
||||
image_subpixel_shift;
|
||||
|
||||
const int16* weight_array = base_type::filter().weight_array();
|
||||
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x += base_type::filter_dx_int() - radius_x;
|
||||
y += base_type::filter_dy_int() - radius_y;
|
||||
|
||||
fg = image_filter_scale / 2;
|
||||
|
||||
int y_lr = y >> image_subpixel_shift;
|
||||
int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
|
||||
base_type::m_ry_inv) >>
|
||||
image_subpixel_shift;
|
||||
int total_weight = 0;
|
||||
int x_lr = x >> image_subpixel_shift;
|
||||
int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
|
||||
base_type::m_rx_inv) >>
|
||||
image_subpixel_shift;
|
||||
|
||||
int x_hr2 = x_hr;
|
||||
const value_type* fg_ptr =
|
||||
(const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
|
||||
for(;;)
|
||||
{
|
||||
int weight_y = weight_array[y_hr];
|
||||
x_hr = x_hr2;
|
||||
for(;;)
|
||||
{
|
||||
int weight = (weight_y * weight_array[x_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
downscale_shift;
|
||||
|
||||
fg += *fg_ptr * weight;
|
||||
total_weight += weight;
|
||||
x_hr += base_type::m_rx_inv;
|
||||
if(x_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
}
|
||||
y_hr += base_type::m_ry_inv;
|
||||
if(y_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
}
|
||||
|
||||
fg /= total_weight;
|
||||
if(fg < 0) fg = 0;
|
||||
if(fg > base_mask) fg = base_mask;
|
||||
|
||||
span->v = (value_type)fg;
|
||||
span->a = base_mask;
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//================================================span_image_resample_gray
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_resample_gray :
|
||||
public span_image_resample<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_resample<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask,
|
||||
downscale_shift = image_filter_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample_gray() {}
|
||||
span_image_resample_gray(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, filter)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
long_type fg;
|
||||
|
||||
int diameter = base_type::filter().diameter();
|
||||
int filter_scale = diameter << image_subpixel_shift;
|
||||
|
||||
const int16* weight_array = base_type::filter().weight_array();
|
||||
do
|
||||
{
|
||||
int rx;
|
||||
int ry;
|
||||
int rx_inv = image_subpixel_scale;
|
||||
int ry_inv = image_subpixel_scale;
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
base_type::interpolator().local_scale(&rx, &ry);
|
||||
|
||||
rx = (rx * base_type::m_blur_x) >> image_subpixel_shift;
|
||||
ry = (ry * base_type::m_blur_y) >> image_subpixel_shift;
|
||||
|
||||
if(rx < image_subpixel_scale)
|
||||
{
|
||||
rx = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rx > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
rx = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
|
||||
}
|
||||
|
||||
if(ry < image_subpixel_scale)
|
||||
{
|
||||
ry = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ry > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
ry = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
|
||||
}
|
||||
|
||||
int radius_x = (diameter * rx) >> 1;
|
||||
int radius_y = (diameter * ry) >> 1;
|
||||
int len_x_lr =
|
||||
(diameter * rx + image_subpixel_mask) >>
|
||||
image_subpixel_shift;
|
||||
|
||||
x += base_type::filter_dx_int() - radius_x;
|
||||
y += base_type::filter_dy_int() - radius_y;
|
||||
|
||||
fg = image_filter_scale / 2;
|
||||
|
||||
int y_lr = y >> image_subpixel_shift;
|
||||
int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
|
||||
ry_inv) >>
|
||||
image_subpixel_shift;
|
||||
int total_weight = 0;
|
||||
int x_lr = x >> image_subpixel_shift;
|
||||
int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
|
||||
rx_inv) >>
|
||||
image_subpixel_shift;
|
||||
int x_hr2 = x_hr;
|
||||
const value_type* fg_ptr =
|
||||
(const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int weight_y = weight_array[y_hr];
|
||||
x_hr = x_hr2;
|
||||
for(;;)
|
||||
{
|
||||
int weight = (weight_y * weight_array[x_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
downscale_shift;
|
||||
fg += *fg_ptr * weight;
|
||||
total_weight += weight;
|
||||
x_hr += rx_inv;
|
||||
if(x_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
}
|
||||
y_hr += ry_inv;
|
||||
if(y_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
}
|
||||
|
||||
fg /= total_weight;
|
||||
if(fg < 0) fg = 0;
|
||||
if(fg > base_mask) fg = base_mask;
|
||||
|
||||
span->v = (value_type)fg;
|
||||
span->a = base_mask;
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
917
agg/include/agg_span_image_filter_rgb.h
Normal file
917
agg/include/agg_span_image_filter_rgb.h
Normal file
|
@ -0,0 +1,917 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED
|
||||
#define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_span_image_filter.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===============================================span_image_filter_rgb_nn
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgb_nn :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgb_nn() {}
|
||||
span_image_filter_rgb_nn(source_type& src,
|
||||
interpolator_type& inter) :
|
||||
base_type(src, inter, 0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
const value_type* fg_ptr = (const value_type*)
|
||||
base_type::source().span(x >> image_subpixel_shift,
|
||||
y >> image_subpixel_shift,
|
||||
1);
|
||||
span->r = fg_ptr[order_type::R];
|
||||
span->g = fg_ptr[order_type::G];
|
||||
span->b = fg_ptr[order_type::B];
|
||||
span->a = base_mask;
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==========================================span_image_filter_rgb_bilinear
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgb_bilinear :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgb_bilinear() {}
|
||||
span_image_filter_rgb_bilinear(source_type& src,
|
||||
interpolator_type& inter) :
|
||||
base_type(src, inter, 0)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
calc_type fg[3];
|
||||
const value_type *fg_ptr;
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
unsigned weight;
|
||||
|
||||
fg[0] =
|
||||
fg[1] =
|
||||
fg[2] = image_subpixel_scale * image_subpixel_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
|
||||
weight = (image_subpixel_scale - x_hr) *
|
||||
(image_subpixel_scale - y_hr);
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = x_hr * (image_subpixel_scale - y_hr);
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
weight = (image_subpixel_scale - x_hr) * y_hr;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = x_hr * y_hr;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr;
|
||||
|
||||
span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2));
|
||||
span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2));
|
||||
span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2));
|
||||
span->a = base_mask;
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================span_image_filter_rgb_bilinear_clip
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgb_bilinear_clip :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgb_bilinear_clip() {}
|
||||
span_image_filter_rgb_bilinear_clip(source_type& src,
|
||||
const color_type& back_color,
|
||||
interpolator_type& inter) :
|
||||
base_type(src, inter, 0),
|
||||
m_back_color(back_color)
|
||||
{}
|
||||
const color_type& background_color() const { return m_back_color; }
|
||||
void background_color(const color_type& v) { m_back_color = v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
calc_type fg[3];
|
||||
calc_type src_alpha;
|
||||
value_type back_r = m_back_color.r;
|
||||
value_type back_g = m_back_color.g;
|
||||
value_type back_b = m_back_color.b;
|
||||
value_type back_a = m_back_color.a;
|
||||
|
||||
const value_type *fg_ptr;
|
||||
|
||||
int maxx = base_type::source().width() - 1;
|
||||
int maxy = base_type::source().height() - 1;
|
||||
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
unsigned weight;
|
||||
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr < maxx && y_lr < maxy)
|
||||
{
|
||||
fg[0] =
|
||||
fg[1] =
|
||||
fg[2] = image_subpixel_scale * image_subpixel_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) *
|
||||
(image_subpixel_scale - y_hr);
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
|
||||
weight = x_hr * (image_subpixel_scale - y_hr);
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
|
||||
++y_lr;
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) * y_hr;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
|
||||
weight = x_hr * y_hr;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
|
||||
fg[0] >>= image_subpixel_shift * 2;
|
||||
fg[1] >>= image_subpixel_shift * 2;
|
||||
fg[2] >>= image_subpixel_shift * 2;
|
||||
src_alpha = base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(x_lr < -1 || y_lr < -1 ||
|
||||
x_lr > maxx || y_lr > maxy)
|
||||
{
|
||||
fg[order_type::R] = back_r;
|
||||
fg[order_type::G] = back_g;
|
||||
fg[order_type::B] = back_b;
|
||||
src_alpha = back_a;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[0] =
|
||||
fg[1] =
|
||||
fg[2] =
|
||||
src_alpha = image_subpixel_scale * image_subpixel_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) *
|
||||
(image_subpixel_scale - y_hr);
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
src_alpha += weight * base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[order_type::R] += back_r * weight;
|
||||
fg[order_type::G] += back_g * weight;
|
||||
fg[order_type::B] += back_b * weight;
|
||||
src_alpha += back_a * weight;
|
||||
}
|
||||
|
||||
x_lr++;
|
||||
|
||||
weight = x_hr * (image_subpixel_scale - y_hr);
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
src_alpha += weight * base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[order_type::R] += back_r * weight;
|
||||
fg[order_type::G] += back_g * weight;
|
||||
fg[order_type::B] += back_b * weight;
|
||||
src_alpha += back_a * weight;
|
||||
}
|
||||
|
||||
x_lr--;
|
||||
y_lr++;
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) * y_hr;
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
src_alpha += weight * base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[order_type::R] += back_r * weight;
|
||||
fg[order_type::G] += back_g * weight;
|
||||
fg[order_type::B] += back_b * weight;
|
||||
src_alpha += back_a * weight;
|
||||
}
|
||||
|
||||
x_lr++;
|
||||
|
||||
weight = x_hr * y_hr;
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
src_alpha += weight * base_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[order_type::R] += back_r * weight;
|
||||
fg[order_type::G] += back_g * weight;
|
||||
fg[order_type::B] += back_b * weight;
|
||||
src_alpha += back_a * weight;
|
||||
}
|
||||
|
||||
fg[0] >>= image_subpixel_shift * 2;
|
||||
fg[1] >>= image_subpixel_shift * 2;
|
||||
fg[2] >>= image_subpixel_shift * 2;
|
||||
src_alpha >>= image_subpixel_shift * 2;
|
||||
}
|
||||
}
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = (value_type)src_alpha;
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
private:
|
||||
color_type m_back_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//===============================================span_image_filter_rgb_2x2
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgb_2x2 :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgb_2x2() {}
|
||||
span_image_filter_rgb_2x2(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, &filter)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
calc_type fg[3];
|
||||
|
||||
const value_type *fg_ptr;
|
||||
const int16* weight_array = base_type::filter().weight_array() +
|
||||
((base_type::filter().diameter()/2 - 1) <<
|
||||
image_subpixel_shift);
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
unsigned weight;
|
||||
fg[0] = fg[1] = fg[2] = image_filter_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
|
||||
weight = (weight_array[x_hr + image_subpixel_scale] *
|
||||
weight_array[y_hr + image_subpixel_scale] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = (weight_array[x_hr] *
|
||||
weight_array[y_hr + image_subpixel_scale] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
weight = (weight_array[x_hr + image_subpixel_scale] *
|
||||
weight_array[y_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = (weight_array[x_hr] *
|
||||
weight_array[y_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr;
|
||||
|
||||
fg[0] >>= image_filter_shift;
|
||||
fg[1] >>= image_filter_shift;
|
||||
fg[2] >>= image_filter_shift;
|
||||
|
||||
if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask;
|
||||
if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask;
|
||||
if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask;
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = base_mask;
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//===================================================span_image_filter_rgb
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgb :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgb() {}
|
||||
span_image_filter_rgb(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, &filter)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
int fg[3];
|
||||
const value_type *fg_ptr;
|
||||
|
||||
unsigned diameter = base_type::filter().diameter();
|
||||
int start = base_type::filter().start();
|
||||
const int16* weight_array = base_type::filter().weight_array();
|
||||
|
||||
int x_count;
|
||||
int weight_y;
|
||||
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x -= base_type::filter_dx_int();
|
||||
y -= base_type::filter_dy_int();
|
||||
|
||||
int x_hr = x;
|
||||
int y_hr = y;
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
fg[0] = fg[1] = fg[2] = image_filter_scale / 2;
|
||||
|
||||
int x_fract = x_hr & image_subpixel_mask;
|
||||
unsigned y_count = diameter;
|
||||
|
||||
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||
fg_ptr = (const value_type*)base_type::source().span(x_lr + start,
|
||||
y_lr + start,
|
||||
diameter);
|
||||
for(;;)
|
||||
{
|
||||
x_count = diameter;
|
||||
weight_y = weight_array[y_hr];
|
||||
x_hr = image_subpixel_mask - x_fract;
|
||||
for(;;)
|
||||
{
|
||||
int weight = (weight_y * weight_array[x_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr;
|
||||
|
||||
if(--x_count == 0) break;
|
||||
x_hr += image_subpixel_scale;
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
}
|
||||
|
||||
if(--y_count == 0) break;
|
||||
y_hr += image_subpixel_scale;
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
}
|
||||
|
||||
fg[0] >>= image_filter_shift;
|
||||
fg[1] >>= image_filter_shift;
|
||||
fg[2] >>= image_filter_shift;
|
||||
|
||||
if(fg[0] < 0) fg[0] = 0;
|
||||
if(fg[1] < 0) fg[1] = 0;
|
||||
if(fg[2] < 0) fg[2] = 0;
|
||||
|
||||
if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask;
|
||||
if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask;
|
||||
if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask;
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = base_mask;
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==========================================span_image_resample_rgb_affine
|
||||
template<class Source>
|
||||
class span_image_resample_rgb_affine :
|
||||
public span_image_resample_affine<Source>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef span_image_resample_affine<source_type> base_type;
|
||||
typedef typename base_type::interpolator_type interpolator_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask,
|
||||
downscale_shift = image_filter_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample_rgb_affine() {}
|
||||
span_image_resample_rgb_affine(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, filter)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
long_type fg[3];
|
||||
|
||||
int diameter = base_type::filter().diameter();
|
||||
int filter_scale = diameter << image_subpixel_shift;
|
||||
int radius_x = (diameter * base_type::m_rx) >> 1;
|
||||
int radius_y = (diameter * base_type::m_ry) >> 1;
|
||||
int len_x_lr =
|
||||
(diameter * base_type::m_rx + image_subpixel_mask) >>
|
||||
image_subpixel_shift;
|
||||
|
||||
const int16* weight_array = base_type::filter().weight_array();
|
||||
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x += base_type::filter_dx_int() - radius_x;
|
||||
y += base_type::filter_dy_int() - radius_y;
|
||||
|
||||
fg[0] = fg[1] = fg[2] = image_filter_scale / 2;
|
||||
|
||||
int y_lr = y >> image_subpixel_shift;
|
||||
int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
|
||||
base_type::m_ry_inv) >>
|
||||
image_subpixel_shift;
|
||||
int total_weight = 0;
|
||||
int x_lr = x >> image_subpixel_shift;
|
||||
int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
|
||||
base_type::m_rx_inv) >>
|
||||
image_subpixel_shift;
|
||||
|
||||
int x_hr2 = x_hr;
|
||||
const value_type* fg_ptr =
|
||||
(const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
|
||||
for(;;)
|
||||
{
|
||||
int weight_y = weight_array[y_hr];
|
||||
x_hr = x_hr2;
|
||||
for(;;)
|
||||
{
|
||||
int weight = (weight_y * weight_array[x_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
downscale_shift;
|
||||
|
||||
fg[0] += *fg_ptr++ * weight;
|
||||
fg[1] += *fg_ptr++ * weight;
|
||||
fg[2] += *fg_ptr * weight;
|
||||
total_weight += weight;
|
||||
x_hr += base_type::m_rx_inv;
|
||||
if(x_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
}
|
||||
y_hr += base_type::m_ry_inv;
|
||||
if(y_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
}
|
||||
|
||||
fg[0] /= total_weight;
|
||||
fg[1] /= total_weight;
|
||||
fg[2] /= total_weight;
|
||||
|
||||
if(fg[0] < 0) fg[0] = 0;
|
||||
if(fg[1] < 0) fg[1] = 0;
|
||||
if(fg[2] < 0) fg[2] = 0;
|
||||
|
||||
if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask;
|
||||
if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask;
|
||||
if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask;
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = base_mask;
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=================================================span_image_resample_rgb
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_resample_rgb :
|
||||
public span_image_resample<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_resample<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask,
|
||||
downscale_shift = image_filter_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample_rgb() {}
|
||||
span_image_resample_rgb(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, filter)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
long_type fg[3];
|
||||
|
||||
int diameter = base_type::filter().diameter();
|
||||
int filter_scale = diameter << image_subpixel_shift;
|
||||
|
||||
const int16* weight_array = base_type::filter().weight_array();
|
||||
do
|
||||
{
|
||||
int rx;
|
||||
int ry;
|
||||
int rx_inv = image_subpixel_scale;
|
||||
int ry_inv = image_subpixel_scale;
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
base_type::interpolator().local_scale(&rx, &ry);
|
||||
|
||||
rx = (rx * base_type::m_blur_x) >> image_subpixel_shift;
|
||||
ry = (ry * base_type::m_blur_y) >> image_subpixel_shift;
|
||||
|
||||
if(rx < image_subpixel_scale)
|
||||
{
|
||||
rx = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rx > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
rx = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
|
||||
}
|
||||
|
||||
if(ry < image_subpixel_scale)
|
||||
{
|
||||
ry = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ry > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
ry = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
|
||||
}
|
||||
|
||||
int radius_x = (diameter * rx) >> 1;
|
||||
int radius_y = (diameter * ry) >> 1;
|
||||
int len_x_lr =
|
||||
(diameter * rx + image_subpixel_mask) >>
|
||||
image_subpixel_shift;
|
||||
|
||||
x += base_type::filter_dx_int() - radius_x;
|
||||
y += base_type::filter_dy_int() - radius_y;
|
||||
|
||||
fg[0] = fg[1] = fg[2] = image_filter_scale / 2;
|
||||
|
||||
int y_lr = y >> image_subpixel_shift;
|
||||
int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
|
||||
ry_inv) >>
|
||||
image_subpixel_shift;
|
||||
int total_weight = 0;
|
||||
int x_lr = x >> image_subpixel_shift;
|
||||
int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
|
||||
rx_inv) >>
|
||||
image_subpixel_shift;
|
||||
int x_hr2 = x_hr;
|
||||
const value_type* fg_ptr =
|
||||
(const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int weight_y = weight_array[y_hr];
|
||||
x_hr = x_hr2;
|
||||
for(;;)
|
||||
{
|
||||
int weight = (weight_y * weight_array[x_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
downscale_shift;
|
||||
fg[0] += *fg_ptr++ * weight;
|
||||
fg[1] += *fg_ptr++ * weight;
|
||||
fg[2] += *fg_ptr * weight;
|
||||
total_weight += weight;
|
||||
x_hr += rx_inv;
|
||||
if(x_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
}
|
||||
y_hr += ry_inv;
|
||||
if(y_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
}
|
||||
|
||||
fg[0] /= total_weight;
|
||||
fg[1] /= total_weight;
|
||||
fg[2] /= total_weight;
|
||||
|
||||
if(fg[0] < 0) fg[0] = 0;
|
||||
if(fg[1] < 0) fg[1] = 0;
|
||||
if(fg[2] < 0) fg[2] = 0;
|
||||
|
||||
if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask;
|
||||
if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask;
|
||||
if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask;
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = base_mask;
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
945
agg/include/agg_span_image_filter_rgba.h
Normal file
945
agg/include/agg_span_image_filter_rgba.h
Normal file
|
@ -0,0 +1,945 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED
|
||||
#define AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_span_image_filter.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//==============================================span_image_filter_rgba_nn
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgba_nn :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgba_nn() {}
|
||||
span_image_filter_rgba_nn(source_type& src,
|
||||
interpolator_type& inter) :
|
||||
base_type(src, inter, 0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
const value_type* fg_ptr = (const value_type*)
|
||||
base_type::source().span(x >> image_subpixel_shift,
|
||||
y >> image_subpixel_shift,
|
||||
1);
|
||||
span->r = fg_ptr[order_type::R];
|
||||
span->g = fg_ptr[order_type::G];
|
||||
span->b = fg_ptr[order_type::B];
|
||||
span->a = fg_ptr[order_type::A];
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=========================================span_image_filter_rgba_bilinear
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgba_bilinear :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgba_bilinear() {}
|
||||
span_image_filter_rgba_bilinear(source_type& src,
|
||||
interpolator_type& inter) :
|
||||
base_type(src, inter, 0)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
calc_type fg[4];
|
||||
const value_type *fg_ptr;
|
||||
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
unsigned weight;
|
||||
|
||||
fg[0] =
|
||||
fg[1] =
|
||||
fg[2] =
|
||||
fg[3] = image_subpixel_scale * image_subpixel_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
|
||||
weight = (image_subpixel_scale - x_hr) *
|
||||
(image_subpixel_scale - y_hr);
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = x_hr * (image_subpixel_scale - y_hr);
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
weight = (image_subpixel_scale - x_hr) * y_hr;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = x_hr * y_hr;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr;
|
||||
|
||||
span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2));
|
||||
span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2));
|
||||
span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2));
|
||||
span->a = value_type(fg[order_type::A] >> (image_subpixel_shift * 2));
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//====================================span_image_filter_rgba_bilinear_clip
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgba_bilinear_clip :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgba_bilinear_clip() {}
|
||||
span_image_filter_rgba_bilinear_clip(source_type& src,
|
||||
const color_type& back_color,
|
||||
interpolator_type& inter) :
|
||||
base_type(src, inter, 0),
|
||||
m_back_color(back_color)
|
||||
{}
|
||||
const color_type& background_color() const { return m_back_color; }
|
||||
void background_color(const color_type& v) { m_back_color = v; }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
calc_type fg[4];
|
||||
value_type back_r = m_back_color.r;
|
||||
value_type back_g = m_back_color.g;
|
||||
value_type back_b = m_back_color.b;
|
||||
value_type back_a = m_back_color.a;
|
||||
|
||||
const value_type *fg_ptr;
|
||||
int maxx = base_type::source().width() - 1;
|
||||
int maxy = base_type::source().height() - 1;
|
||||
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
unsigned weight;
|
||||
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr < maxx && y_lr < maxy)
|
||||
{
|
||||
fg[0] =
|
||||
fg[1] =
|
||||
fg[2] =
|
||||
fg[3] = image_subpixel_scale * image_subpixel_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + (x_lr << 2);
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) *
|
||||
(image_subpixel_scale - y_hr);
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr++;
|
||||
|
||||
weight = x_hr * (image_subpixel_scale - y_hr);
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr++;
|
||||
|
||||
++y_lr;
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + (x_lr << 2);
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) * y_hr;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr++;
|
||||
|
||||
weight = x_hr * y_hr;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr++;
|
||||
|
||||
fg[0] >>= image_subpixel_shift * 2;
|
||||
fg[1] >>= image_subpixel_shift * 2;
|
||||
fg[2] >>= image_subpixel_shift * 2;
|
||||
fg[3] >>= image_subpixel_shift * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(x_lr < -1 || y_lr < -1 ||
|
||||
x_lr > maxx || y_lr > maxy)
|
||||
{
|
||||
fg[order_type::R] = back_r;
|
||||
fg[order_type::G] = back_g;
|
||||
fg[order_type::B] = back_b;
|
||||
fg[order_type::A] = back_a;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[0] =
|
||||
fg[1] =
|
||||
fg[2] =
|
||||
fg[3] = image_subpixel_scale * image_subpixel_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) *
|
||||
(image_subpixel_scale - y_hr);
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + (x_lr << 2);
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[order_type::R] += back_r * weight;
|
||||
fg[order_type::G] += back_g * weight;
|
||||
fg[order_type::B] += back_b * weight;
|
||||
fg[order_type::A] += back_a * weight;
|
||||
}
|
||||
|
||||
x_lr++;
|
||||
|
||||
weight = x_hr * (image_subpixel_scale - y_hr);
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + (x_lr << 2);
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[order_type::R] += back_r * weight;
|
||||
fg[order_type::G] += back_g * weight;
|
||||
fg[order_type::B] += back_b * weight;
|
||||
fg[order_type::A] += back_a * weight;
|
||||
}
|
||||
|
||||
x_lr--;
|
||||
y_lr++;
|
||||
|
||||
weight = (image_subpixel_scale - x_hr) * y_hr;
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + (x_lr << 2);
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[order_type::R] += back_r * weight;
|
||||
fg[order_type::G] += back_g * weight;
|
||||
fg[order_type::B] += back_b * weight;
|
||||
fg[order_type::A] += back_a * weight;
|
||||
}
|
||||
|
||||
x_lr++;
|
||||
|
||||
weight = x_hr * y_hr;
|
||||
if(x_lr >= 0 && y_lr >= 0 &&
|
||||
x_lr <= maxx && y_lr <= maxy)
|
||||
{
|
||||
fg_ptr = (const value_type*)
|
||||
base_type::source().row_ptr(y_lr) + (x_lr << 2);
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg[order_type::R] += back_r * weight;
|
||||
fg[order_type::G] += back_g * weight;
|
||||
fg[order_type::B] += back_b * weight;
|
||||
fg[order_type::A] += back_a * weight;
|
||||
}
|
||||
|
||||
fg[0] >>= image_subpixel_shift * 2;
|
||||
fg[1] >>= image_subpixel_shift * 2;
|
||||
fg[2] >>= image_subpixel_shift * 2;
|
||||
fg[3] >>= image_subpixel_shift * 2;
|
||||
}
|
||||
}
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = (value_type)fg[order_type::A];
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
private:
|
||||
color_type m_back_color;
|
||||
};
|
||||
|
||||
|
||||
//==============================================span_image_filter_rgba_2x2
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgba_2x2 :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgba_2x2() {}
|
||||
span_image_filter_rgba_2x2(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, &filter)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
calc_type fg[4];
|
||||
|
||||
const value_type *fg_ptr;
|
||||
const int16* weight_array = base_type::filter().weight_array() +
|
||||
((base_type::filter().diameter()/2 - 1) <<
|
||||
image_subpixel_shift);
|
||||
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
unsigned weight;
|
||||
fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
|
||||
weight = (weight_array[x_hr + image_subpixel_scale] *
|
||||
weight_array[y_hr + image_subpixel_scale] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = (weight_array[x_hr] *
|
||||
weight_array[y_hr + image_subpixel_scale] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
weight = (weight_array[x_hr + image_subpixel_scale] *
|
||||
weight_array[y_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr;
|
||||
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
weight = (weight_array[x_hr] *
|
||||
weight_array[y_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr;
|
||||
|
||||
fg[0] >>= image_filter_shift;
|
||||
fg[1] >>= image_filter_shift;
|
||||
fg[2] >>= image_filter_shift;
|
||||
fg[3] >>= image_filter_shift;
|
||||
|
||||
if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask;
|
||||
if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A];
|
||||
if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A];
|
||||
if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A];
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = (value_type)fg[order_type::A];
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==================================================span_image_filter_rgba
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_filter_rgba :
|
||||
public span_image_filter<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_filter<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_filter_rgba() {}
|
||||
span_image_filter_rgba(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, &filter)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
int fg[4];
|
||||
const value_type *fg_ptr;
|
||||
|
||||
unsigned diameter = base_type::filter().diameter();
|
||||
int start = base_type::filter().start();
|
||||
const int16* weight_array = base_type::filter().weight_array();
|
||||
|
||||
int x_count;
|
||||
int weight_y;
|
||||
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x -= base_type::filter_dx_int();
|
||||
y -= base_type::filter_dy_int();
|
||||
|
||||
int x_hr = x;
|
||||
int y_hr = y;
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;
|
||||
|
||||
int x_fract = x_hr & image_subpixel_mask;
|
||||
unsigned y_count = diameter;
|
||||
|
||||
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||
fg_ptr = (const value_type*)base_type::source().span(x_lr + start,
|
||||
y_lr + start,
|
||||
diameter);
|
||||
for(;;)
|
||||
{
|
||||
x_count = diameter;
|
||||
weight_y = weight_array[y_hr];
|
||||
x_hr = image_subpixel_mask - x_fract;
|
||||
for(;;)
|
||||
{
|
||||
int weight = (weight_y * weight_array[x_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
image_filter_shift;
|
||||
|
||||
fg[0] += weight * *fg_ptr++;
|
||||
fg[1] += weight * *fg_ptr++;
|
||||
fg[2] += weight * *fg_ptr++;
|
||||
fg[3] += weight * *fg_ptr;
|
||||
|
||||
if(--x_count == 0) break;
|
||||
x_hr += image_subpixel_scale;
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
}
|
||||
|
||||
if(--y_count == 0) break;
|
||||
y_hr += image_subpixel_scale;
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
}
|
||||
|
||||
fg[0] >>= image_filter_shift;
|
||||
fg[1] >>= image_filter_shift;
|
||||
fg[2] >>= image_filter_shift;
|
||||
fg[3] >>= image_filter_shift;
|
||||
|
||||
if(fg[0] < 0) fg[0] = 0;
|
||||
if(fg[1] < 0) fg[1] = 0;
|
||||
if(fg[2] < 0) fg[2] = 0;
|
||||
if(fg[3] < 0) fg[3] = 0;
|
||||
|
||||
if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask;
|
||||
if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A];
|
||||
if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A];
|
||||
if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A];
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = (value_type)fg[order_type::A];
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//========================================span_image_resample_rgba_affine
|
||||
template<class Source>
|
||||
class span_image_resample_rgba_affine :
|
||||
public span_image_resample_affine<Source>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef span_image_resample_affine<source_type> base_type;
|
||||
typedef typename base_type::interpolator_type interpolator_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask,
|
||||
downscale_shift = image_filter_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample_rgba_affine() {}
|
||||
span_image_resample_rgba_affine(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, filter)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
long_type fg[4];
|
||||
|
||||
int diameter = base_type::filter().diameter();
|
||||
int filter_scale = diameter << image_subpixel_shift;
|
||||
int radius_x = (diameter * base_type::m_rx) >> 1;
|
||||
int radius_y = (diameter * base_type::m_ry) >> 1;
|
||||
int len_x_lr =
|
||||
(diameter * base_type::m_rx + image_subpixel_mask) >>
|
||||
image_subpixel_shift;
|
||||
|
||||
const int16* weight_array = base_type::filter().weight_array();
|
||||
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x += base_type::filter_dx_int() - radius_x;
|
||||
y += base_type::filter_dy_int() - radius_y;
|
||||
|
||||
fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;
|
||||
|
||||
int y_lr = y >> image_subpixel_shift;
|
||||
int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
|
||||
base_type::m_ry_inv) >>
|
||||
image_subpixel_shift;
|
||||
int total_weight = 0;
|
||||
int x_lr = x >> image_subpixel_shift;
|
||||
int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
|
||||
base_type::m_rx_inv) >>
|
||||
image_subpixel_shift;
|
||||
|
||||
int x_hr2 = x_hr;
|
||||
const value_type* fg_ptr =
|
||||
(const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
|
||||
for(;;)
|
||||
{
|
||||
int weight_y = weight_array[y_hr];
|
||||
x_hr = x_hr2;
|
||||
for(;;)
|
||||
{
|
||||
int weight = (weight_y * weight_array[x_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
downscale_shift;
|
||||
|
||||
fg[0] += *fg_ptr++ * weight;
|
||||
fg[1] += *fg_ptr++ * weight;
|
||||
fg[2] += *fg_ptr++ * weight;
|
||||
fg[3] += *fg_ptr++ * weight;
|
||||
total_weight += weight;
|
||||
x_hr += base_type::m_rx_inv;
|
||||
if(x_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
}
|
||||
y_hr += base_type::m_ry_inv;
|
||||
if(y_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
}
|
||||
|
||||
fg[0] /= total_weight;
|
||||
fg[1] /= total_weight;
|
||||
fg[2] /= total_weight;
|
||||
fg[3] /= total_weight;
|
||||
|
||||
if(fg[0] < 0) fg[0] = 0;
|
||||
if(fg[1] < 0) fg[1] = 0;
|
||||
if(fg[2] < 0) fg[2] = 0;
|
||||
if(fg[3] < 0) fg[3] = 0;
|
||||
|
||||
if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask;
|
||||
if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A];
|
||||
if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A];
|
||||
if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A];
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = (value_type)fg[order_type::A];
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==============================================span_image_resample_rgba
|
||||
template<class Source, class Interpolator>
|
||||
class span_image_resample_rgba :
|
||||
public span_image_resample<Source, Interpolator>
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef span_image_resample<source_type, interpolator_type> base_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask,
|
||||
downscale_shift = image_filter_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_image_resample_rgba() {}
|
||||
span_image_resample_rgba(source_type& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_lut& filter) :
|
||||
base_type(src, inter, filter)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
long_type fg[4];
|
||||
|
||||
int diameter = base_type::filter().diameter();
|
||||
int filter_scale = diameter << image_subpixel_shift;
|
||||
|
||||
const int16* weight_array = base_type::filter().weight_array();
|
||||
do
|
||||
{
|
||||
int rx;
|
||||
int ry;
|
||||
int rx_inv = image_subpixel_scale;
|
||||
int ry_inv = image_subpixel_scale;
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
base_type::interpolator().local_scale(&rx, &ry);
|
||||
|
||||
rx = (rx * base_type::m_blur_x) >> image_subpixel_shift;
|
||||
ry = (ry * base_type::m_blur_y) >> image_subpixel_shift;
|
||||
|
||||
if(rx < image_subpixel_scale)
|
||||
{
|
||||
rx = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rx > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
rx = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
|
||||
}
|
||||
|
||||
if(ry < image_subpixel_scale)
|
||||
{
|
||||
ry = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ry > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
ry = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
|
||||
}
|
||||
|
||||
int radius_x = (diameter * rx) >> 1;
|
||||
int radius_y = (diameter * ry) >> 1;
|
||||
int len_x_lr =
|
||||
(diameter * rx + image_subpixel_mask) >>
|
||||
image_subpixel_shift;
|
||||
|
||||
x += base_type::filter_dx_int() - radius_x;
|
||||
y += base_type::filter_dy_int() - radius_y;
|
||||
|
||||
fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;
|
||||
|
||||
int y_lr = y >> image_subpixel_shift;
|
||||
int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
|
||||
ry_inv) >>
|
||||
image_subpixel_shift;
|
||||
int total_weight = 0;
|
||||
int x_lr = x >> image_subpixel_shift;
|
||||
int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
|
||||
rx_inv) >>
|
||||
image_subpixel_shift;
|
||||
int x_hr2 = x_hr;
|
||||
const value_type* fg_ptr =
|
||||
(const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int weight_y = weight_array[y_hr];
|
||||
x_hr = x_hr2;
|
||||
for(;;)
|
||||
{
|
||||
int weight = (weight_y * weight_array[x_hr] +
|
||||
image_filter_scale / 2) >>
|
||||
downscale_shift;
|
||||
fg[0] += *fg_ptr++ * weight;
|
||||
fg[1] += *fg_ptr++ * weight;
|
||||
fg[2] += *fg_ptr++ * weight;
|
||||
fg[3] += *fg_ptr++ * weight;
|
||||
total_weight += weight;
|
||||
x_hr += rx_inv;
|
||||
if(x_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_x();
|
||||
}
|
||||
y_hr += ry_inv;
|
||||
if(y_hr >= filter_scale) break;
|
||||
fg_ptr = (const value_type*)base_type::source().next_y();
|
||||
}
|
||||
|
||||
fg[0] /= total_weight;
|
||||
fg[1] /= total_weight;
|
||||
fg[2] /= total_weight;
|
||||
fg[3] /= total_weight;
|
||||
|
||||
if(fg[0] < 0) fg[0] = 0;
|
||||
if(fg[1] < 0) fg[1] = 0;
|
||||
if(fg[2] < 0) fg[2] = 0;
|
||||
if(fg[3] < 0) fg[3] = 0;
|
||||
|
||||
if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask;
|
||||
if(fg[order_type::R] > fg[order_type::R]) fg[order_type::R] = fg[order_type::R];
|
||||
if(fg[order_type::G] > fg[order_type::G]) fg[order_type::G] = fg[order_type::G];
|
||||
if(fg[order_type::B] > fg[order_type::B]) fg[order_type::B] = fg[order_type::B];
|
||||
|
||||
span->r = (value_type)fg[order_type::R];
|
||||
span->g = (value_type)fg[order_type::G];
|
||||
span->b = (value_type)fg[order_type::B];
|
||||
span->a = (value_type)fg[order_type::A];
|
||||
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
} while(--len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
77
agg/include/agg_span_interpolator_adaptor.h
Normal file
77
agg/include/agg_span_interpolator_adaptor.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED
|
||||
#define AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===============================================span_interpolator_adaptor
|
||||
template<class Interpolator, class Distortion>
|
||||
class span_interpolator_adaptor : public Interpolator
|
||||
{
|
||||
public:
|
||||
typedef Interpolator base_type;
|
||||
typedef typename base_type::trans_type trans_type;
|
||||
typedef Distortion distortion_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_interpolator_adaptor() {}
|
||||
span_interpolator_adaptor(const trans_type& trans,
|
||||
const distortion_type& dist) :
|
||||
base_type(trans),
|
||||
m_distortion(&dist)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_interpolator_adaptor(const trans_type& trans,
|
||||
const distortion_type& dist,
|
||||
double x, double y, unsigned len) :
|
||||
base_type(trans, x, y, len),
|
||||
m_distortion(&dist)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const distortion_type& distortion() const
|
||||
{
|
||||
return *m_distortion;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void distortion(const distortion_type& dist)
|
||||
{
|
||||
m_distortion = dist;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void coordinates(int* x, int* y) const
|
||||
{
|
||||
base_type::coordinates(x, y);
|
||||
m_distortion->calculate(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
const distortion_type* m_distortion;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
232
agg/include/agg_span_interpolator_linear.h
Normal file
232
agg/include/agg_span_interpolator_linear.h
Normal file
|
@ -0,0 +1,232 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
|
||||
#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_dda_line.h"
|
||||
#include "agg_trans_affine.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//================================================span_interpolator_linear
|
||||
template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
|
||||
class span_interpolator_linear
|
||||
{
|
||||
public:
|
||||
typedef Transformer trans_type;
|
||||
|
||||
enum subpixel_scale_e
|
||||
{
|
||||
subpixel_shift = SubpixelShift,
|
||||
subpixel_scale = 1 << subpixel_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_interpolator_linear() {}
|
||||
span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {}
|
||||
span_interpolator_linear(const trans_type& trans,
|
||||
double x, double y, unsigned len) :
|
||||
m_trans(&trans)
|
||||
{
|
||||
begin(x, y, len);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
const trans_type& transformer() const { return *m_trans; }
|
||||
void transformer(const trans_type& trans) { m_trans = &trans; }
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void begin(double x, double y, unsigned len)
|
||||
{
|
||||
double tx;
|
||||
double ty;
|
||||
|
||||
tx = x;
|
||||
ty = y;
|
||||
m_trans->transform(&tx, &ty);
|
||||
int x1 = iround(tx * subpixel_scale);
|
||||
int y1 = iround(ty * subpixel_scale);
|
||||
|
||||
tx = x + len;
|
||||
ty = y;
|
||||
m_trans->transform(&tx, &ty);
|
||||
int x2 = iround(tx * subpixel_scale);
|
||||
int y2 = iround(ty * subpixel_scale);
|
||||
|
||||
m_li_x = dda2_line_interpolator(x1, x2, len);
|
||||
m_li_y = dda2_line_interpolator(y1, y2, len);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void resynchronize(double xe, double ye, unsigned len)
|
||||
{
|
||||
m_trans->transform(&xe, &ye);
|
||||
m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len);
|
||||
m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void operator++()
|
||||
{
|
||||
++m_li_x;
|
||||
++m_li_y;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void coordinates(int* x, int* y) const
|
||||
{
|
||||
*x = m_li_x.y();
|
||||
*y = m_li_y.y();
|
||||
}
|
||||
|
||||
private:
|
||||
const trans_type* m_trans;
|
||||
dda2_line_interpolator m_li_x;
|
||||
dda2_line_interpolator m_li_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================================span_interpolator_linear_subdiv
|
||||
template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
|
||||
class span_interpolator_linear_subdiv
|
||||
{
|
||||
public:
|
||||
typedef Transformer trans_type;
|
||||
|
||||
enum subpixel_scale_e
|
||||
{
|
||||
subpixel_shift = SubpixelShift,
|
||||
subpixel_scale = 1 << subpixel_shift
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
span_interpolator_linear_subdiv() :
|
||||
m_subdiv_shift(4),
|
||||
m_subdiv_size(1 << m_subdiv_shift),
|
||||
m_subdiv_mask(m_subdiv_size - 1) {}
|
||||
|
||||
span_interpolator_linear_subdiv(const trans_type& trans,
|
||||
unsigned subdiv_shift = 4) :
|
||||
m_subdiv_shift(subdiv_shift),
|
||||
m_subdiv_size(1 << m_subdiv_shift),
|
||||
m_subdiv_mask(m_subdiv_size - 1),
|
||||
m_trans(&trans) {}
|
||||
|
||||
span_interpolator_linear_subdiv(const trans_type& trans,
|
||||
double x, double y, unsigned len,
|
||||
unsigned subdiv_shift = 4) :
|
||||
m_subdiv_shift(subdiv_shift),
|
||||
m_subdiv_size(1 << m_subdiv_shift),
|
||||
m_subdiv_mask(m_subdiv_size - 1),
|
||||
m_trans(&trans)
|
||||
{
|
||||
begin(x, y, len);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
const trans_type& transformer() const { return *m_trans; }
|
||||
void transformer(const trans_type& trans) { m_trans = &trans; }
|
||||
|
||||
//----------------------------------------------------------------
|
||||
unsigned subdiv_shift() const { return m_subdiv_shift; }
|
||||
void subdiv_shift(unsigned shift)
|
||||
{
|
||||
m_subdiv_shift = shift;
|
||||
m_subdiv_size = 1 << m_subdiv_shift;
|
||||
m_subdiv_mask = m_subdiv_size - 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void begin(double x, double y, unsigned len)
|
||||
{
|
||||
double tx;
|
||||
double ty;
|
||||
m_pos = 1;
|
||||
m_src_x = iround(x * subpixel_scale) + subpixel_scale;
|
||||
m_src_y = y;
|
||||
m_len = len;
|
||||
|
||||
if(len > m_subdiv_size) len = m_subdiv_size;
|
||||
tx = x;
|
||||
ty = y;
|
||||
m_trans->transform(&tx, &ty);
|
||||
int x1 = iround(tx * subpixel_scale);
|
||||
int y1 = iround(ty * subpixel_scale);
|
||||
|
||||
tx = x + len;
|
||||
ty = y;
|
||||
m_trans->transform(&tx, &ty);
|
||||
|
||||
m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len);
|
||||
m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void operator++()
|
||||
{
|
||||
++m_li_x;
|
||||
++m_li_y;
|
||||
if(m_pos >= m_subdiv_size)
|
||||
{
|
||||
unsigned len = m_len;
|
||||
if(len > m_subdiv_size) len = m_subdiv_size;
|
||||
double tx = double(m_src_x) / double(subpixel_scale) + len;
|
||||
double ty = m_src_y;
|
||||
m_trans->transform(&tx, &ty);
|
||||
m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len);
|
||||
m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len);
|
||||
m_pos = 0;
|
||||
}
|
||||
m_src_x += subpixel_scale;
|
||||
++m_pos;
|
||||
--m_len;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void coordinates(int* x, int* y) const
|
||||
{
|
||||
*x = m_li_x.y();
|
||||
*y = m_li_y.y();
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned m_subdiv_shift;
|
||||
unsigned m_subdiv_size;
|
||||
unsigned m_subdiv_mask;
|
||||
const trans_type* m_trans;
|
||||
dda2_line_interpolator m_li_x;
|
||||
dda2_line_interpolator m_li_y;
|
||||
int m_src_x;
|
||||
double m_src_y;
|
||||
unsigned m_pos;
|
||||
unsigned m_len;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
462
agg/include/agg_span_interpolator_persp.h
Normal file
462
agg/include/agg_span_interpolator_persp.h
Normal file
|
@ -0,0 +1,462 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED
|
||||
#define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED
|
||||
|
||||
#include "agg_trans_perspective.h"
|
||||
#include "agg_dda_line.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
|
||||
//===========================================span_interpolator_persp_exact
|
||||
template<unsigned SubpixelShift = 8>
|
||||
class span_interpolator_persp_exact
|
||||
{
|
||||
public:
|
||||
typedef trans_perspective trans_type;
|
||||
typedef trans_perspective::iterator_x iterator_type;
|
||||
enum subpixel_scale_e
|
||||
{
|
||||
subpixel_shift = SubpixelShift,
|
||||
subpixel_scale = 1 << subpixel_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_interpolator_persp_exact() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Arbitrary quadrangle transformations
|
||||
span_interpolator_persp_exact(const double* src, const double* dst)
|
||||
{
|
||||
quad_to_quad(src, dst);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Direct transformations
|
||||
span_interpolator_persp_exact(double x1, double y1,
|
||||
double x2, double y2,
|
||||
const double* quad)
|
||||
{
|
||||
rect_to_quad(x1, y1, x2, y2, quad);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Reverse transformations
|
||||
span_interpolator_persp_exact(const double* quad,
|
||||
double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
quad_to_rect(quad, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Set the transformations using two arbitrary quadrangles.
|
||||
void quad_to_quad(const double* src, const double* dst)
|
||||
{
|
||||
m_trans_dir.quad_to_quad(src, dst);
|
||||
m_trans_inv.quad_to_quad(dst, src);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Set the direct transformations, i.e., rectangle -> quadrangle
|
||||
void rect_to_quad(double x1, double y1, double x2, double y2,
|
||||
const double* quad)
|
||||
{
|
||||
double src[8];
|
||||
src[0] = src[6] = x1;
|
||||
src[2] = src[4] = x2;
|
||||
src[1] = src[3] = y1;
|
||||
src[5] = src[7] = y2;
|
||||
quad_to_quad(src, quad);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Set the reverse transformations, i.e., quadrangle -> rectangle
|
||||
void quad_to_rect(const double* quad,
|
||||
double x1, double y1, double x2, double y2)
|
||||
{
|
||||
double dst[8];
|
||||
dst[0] = dst[6] = x1;
|
||||
dst[2] = dst[4] = x2;
|
||||
dst[1] = dst[3] = y1;
|
||||
dst[5] = dst[7] = y2;
|
||||
quad_to_quad(quad, dst);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Check if the equations were solved successfully
|
||||
bool is_valid() const { return m_trans_dir.is_valid(); }
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void begin(double x, double y, unsigned len)
|
||||
{
|
||||
m_iterator = m_trans_dir.begin(x, y, 1.0);
|
||||
double xt = m_iterator.x;
|
||||
double yt = m_iterator.y;
|
||||
|
||||
double dx;
|
||||
double dy;
|
||||
const double delta = 1/double(subpixel_scale);
|
||||
dx = xt + delta;
|
||||
dy = yt;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= x;
|
||||
dy -= y;
|
||||
int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
dx = xt;
|
||||
dy = yt + delta;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= x;
|
||||
dy -= y;
|
||||
int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
x += len;
|
||||
xt = x;
|
||||
yt = y;
|
||||
m_trans_dir.transform(&xt, &yt);
|
||||
|
||||
dx = xt + delta;
|
||||
dy = yt;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= x;
|
||||
dy -= y;
|
||||
int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
dx = xt;
|
||||
dy = yt + delta;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= x;
|
||||
dy -= y;
|
||||
int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
m_scale_x = dda2_line_interpolator(sx1, sx2, len);
|
||||
m_scale_y = dda2_line_interpolator(sy1, sy2, len);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void resynchronize(double xe, double ye, unsigned len)
|
||||
{
|
||||
// Assume x1,y1 are equal to the ones at the previous end point
|
||||
int sx1 = m_scale_x.y();
|
||||
int sy1 = m_scale_y.y();
|
||||
|
||||
// Calculate transformed coordinates at x2,y2
|
||||
double xt = xe;
|
||||
double yt = ye;
|
||||
m_trans_dir.transform(&xt, &yt);
|
||||
|
||||
const double delta = 1/double(subpixel_scale);
|
||||
double dx;
|
||||
double dy;
|
||||
|
||||
// Calculate scale by X at x2,y2
|
||||
dx = xt + delta;
|
||||
dy = yt;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= xe;
|
||||
dy -= ye;
|
||||
int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
// Calculate scale by Y at x2,y2
|
||||
dx = xt;
|
||||
dy = yt + delta;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= xe;
|
||||
dy -= ye;
|
||||
int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
// Initialize the interpolators
|
||||
m_scale_x = dda2_line_interpolator(sx1, sx2, len);
|
||||
m_scale_y = dda2_line_interpolator(sy1, sy2, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void operator++()
|
||||
{
|
||||
++m_iterator;
|
||||
++m_scale_x;
|
||||
++m_scale_y;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void coordinates(int* x, int* y) const
|
||||
{
|
||||
*x = iround(m_iterator.x * subpixel_scale);
|
||||
*y = iround(m_iterator.y * subpixel_scale);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void local_scale(int* x, int* y)
|
||||
{
|
||||
*x = m_scale_x.y();
|
||||
*y = m_scale_y.y();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void transform(double* x, double* y) const
|
||||
{
|
||||
m_trans_dir.transform(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
trans_type m_trans_dir;
|
||||
trans_type m_trans_inv;
|
||||
iterator_type m_iterator;
|
||||
dda2_line_interpolator m_scale_x;
|
||||
dda2_line_interpolator m_scale_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//============================================span_interpolator_persp_lerp
|
||||
template<unsigned SubpixelShift = 8>
|
||||
class span_interpolator_persp_lerp
|
||||
{
|
||||
public:
|
||||
typedef trans_perspective trans_type;
|
||||
enum subpixel_scale_e
|
||||
{
|
||||
subpixel_shift = SubpixelShift,
|
||||
subpixel_scale = 1 << subpixel_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_interpolator_persp_lerp() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Arbitrary quadrangle transformations
|
||||
span_interpolator_persp_lerp(const double* src, const double* dst)
|
||||
{
|
||||
quad_to_quad(src, dst);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Direct transformations
|
||||
span_interpolator_persp_lerp(double x1, double y1,
|
||||
double x2, double y2,
|
||||
const double* quad)
|
||||
{
|
||||
rect_to_quad(x1, y1, x2, y2, quad);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Reverse transformations
|
||||
span_interpolator_persp_lerp(const double* quad,
|
||||
double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
quad_to_rect(quad, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Set the transformations using two arbitrary quadrangles.
|
||||
void quad_to_quad(const double* src, const double* dst)
|
||||
{
|
||||
m_trans_dir.quad_to_quad(src, dst);
|
||||
m_trans_inv.quad_to_quad(dst, src);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Set the direct transformations, i.e., rectangle -> quadrangle
|
||||
void rect_to_quad(double x1, double y1, double x2, double y2,
|
||||
const double* quad)
|
||||
{
|
||||
double src[8];
|
||||
src[0] = src[6] = x1;
|
||||
src[2] = src[4] = x2;
|
||||
src[1] = src[3] = y1;
|
||||
src[5] = src[7] = y2;
|
||||
quad_to_quad(src, quad);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Set the reverse transformations, i.e., quadrangle -> rectangle
|
||||
void quad_to_rect(const double* quad,
|
||||
double x1, double y1, double x2, double y2)
|
||||
{
|
||||
double dst[8];
|
||||
dst[0] = dst[6] = x1;
|
||||
dst[2] = dst[4] = x2;
|
||||
dst[1] = dst[3] = y1;
|
||||
dst[5] = dst[7] = y2;
|
||||
quad_to_quad(quad, dst);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Check if the equations were solved successfully
|
||||
bool is_valid() const { return m_trans_dir.is_valid(); }
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void begin(double x, double y, unsigned len)
|
||||
{
|
||||
// Calculate transformed coordinates at x1,y1
|
||||
double xt = x;
|
||||
double yt = y;
|
||||
m_trans_dir.transform(&xt, &yt);
|
||||
int x1 = iround(xt * subpixel_scale);
|
||||
int y1 = iround(yt * subpixel_scale);
|
||||
|
||||
double dx;
|
||||
double dy;
|
||||
const double delta = 1/double(subpixel_scale);
|
||||
|
||||
// Calculate scale by X at x1,y1
|
||||
dx = xt + delta;
|
||||
dy = yt;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= x;
|
||||
dy -= y;
|
||||
int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
// Calculate scale by Y at x1,y1
|
||||
dx = xt;
|
||||
dy = yt + delta;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= x;
|
||||
dy -= y;
|
||||
int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
// Calculate transformed coordinates at x2,y2
|
||||
x += len;
|
||||
xt = x;
|
||||
yt = y;
|
||||
m_trans_dir.transform(&xt, &yt);
|
||||
int x2 = iround(xt * subpixel_scale);
|
||||
int y2 = iround(yt * subpixel_scale);
|
||||
|
||||
// Calculate scale by X at x2,y2
|
||||
dx = xt + delta;
|
||||
dy = yt;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= x;
|
||||
dy -= y;
|
||||
int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
// Calculate scale by Y at x2,y2
|
||||
dx = xt;
|
||||
dy = yt + delta;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= x;
|
||||
dy -= y;
|
||||
int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
// Initialize the interpolators
|
||||
m_coord_x = dda2_line_interpolator(x1, x2, len);
|
||||
m_coord_y = dda2_line_interpolator(y1, y2, len);
|
||||
m_scale_x = dda2_line_interpolator(sx1, sx2, len);
|
||||
m_scale_y = dda2_line_interpolator(sy1, sy2, len);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void resynchronize(double xe, double ye, unsigned len)
|
||||
{
|
||||
// Assume x1,y1 are equal to the ones at the previous end point
|
||||
int x1 = m_coord_x.y();
|
||||
int y1 = m_coord_y.y();
|
||||
int sx1 = m_scale_x.y();
|
||||
int sy1 = m_scale_y.y();
|
||||
|
||||
// Calculate transformed coordinates at x2,y2
|
||||
double xt = xe;
|
||||
double yt = ye;
|
||||
m_trans_dir.transform(&xt, &yt);
|
||||
int x2 = iround(xt * subpixel_scale);
|
||||
int y2 = iround(yt * subpixel_scale);
|
||||
|
||||
const double delta = 1/double(subpixel_scale);
|
||||
double dx;
|
||||
double dy;
|
||||
|
||||
// Calculate scale by X at x2,y2
|
||||
dx = xt + delta;
|
||||
dy = yt;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= xe;
|
||||
dy -= ye;
|
||||
int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
// Calculate scale by Y at x2,y2
|
||||
dx = xt;
|
||||
dy = yt + delta;
|
||||
m_trans_inv.transform(&dx, &dy);
|
||||
dx -= xe;
|
||||
dy -= ye;
|
||||
int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
|
||||
|
||||
// Initialize the interpolators
|
||||
m_coord_x = dda2_line_interpolator(x1, x2, len);
|
||||
m_coord_y = dda2_line_interpolator(y1, y2, len);
|
||||
m_scale_x = dda2_line_interpolator(sx1, sx2, len);
|
||||
m_scale_y = dda2_line_interpolator(sy1, sy2, len);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void operator++()
|
||||
{
|
||||
++m_coord_x;
|
||||
++m_coord_y;
|
||||
++m_scale_x;
|
||||
++m_scale_y;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void coordinates(int* x, int* y) const
|
||||
{
|
||||
*x = m_coord_x.y();
|
||||
*y = m_coord_y.y();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void local_scale(int* x, int* y)
|
||||
{
|
||||
*x = m_scale_x.y();
|
||||
*y = m_scale_y.y();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void transform(double* x, double* y) const
|
||||
{
|
||||
m_trans_dir.transform(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
trans_type m_trans_dir;
|
||||
trans_type m_trans_inv;
|
||||
dda2_line_interpolator m_coord_x;
|
||||
dda2_line_interpolator m_coord_y;
|
||||
dda2_line_interpolator m_scale_x;
|
||||
dda2_line_interpolator m_scale_y;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
92
agg/include/agg_span_interpolator_trans.h
Normal file
92
agg/include/agg_span_interpolator_trans.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Horizontal span interpolator for use with an arbitrary transformer
|
||||
// The efficiency highly depends on the operations done in the transformer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED
|
||||
#define AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//=================================================span_interpolator_trans
|
||||
template<class Transformer, unsigned SubpixelShift = 8>
|
||||
class span_interpolator_trans
|
||||
{
|
||||
public:
|
||||
typedef Transformer trans_type;
|
||||
enum subpixel_scale_e
|
||||
{
|
||||
subpixel_shift = SubpixelShift,
|
||||
subpixel_scale = 1 << subpixel_shift
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_interpolator_trans() {}
|
||||
span_interpolator_trans(const trans_type& trans) : m_trans(&trans) {}
|
||||
span_interpolator_trans(const trans_type& trans,
|
||||
double x, double y, unsigned) :
|
||||
m_trans(&trans)
|
||||
{
|
||||
begin(x, y, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
const trans_type& transformer() const { return *m_trans; }
|
||||
void transformer(const trans_type& trans) { m_trans = &trans; }
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void begin(double x, double y, unsigned)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_trans->transform(&x, &y);
|
||||
m_ix = iround(x * subpixel_scale);
|
||||
m_iy = iround(y * subpixel_scale);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void operator++()
|
||||
{
|
||||
m_x += 1.0;
|
||||
double x = m_x;
|
||||
double y = m_y;
|
||||
m_trans->transform(&x, &y);
|
||||
m_ix = iround(x * subpixel_scale);
|
||||
m_iy = iround(y * subpixel_scale);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void coordinates(int* x, int* y) const
|
||||
{
|
||||
*x = m_ix;
|
||||
*y = m_iy;
|
||||
}
|
||||
|
||||
private:
|
||||
const trans_type* m_trans;
|
||||
double m_x;
|
||||
double m_y;
|
||||
int m_ix;
|
||||
int m_iy;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
93
agg/include/agg_span_pattern_gray.h
Normal file
93
agg/include/agg_span_pattern_gray.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef AGG_SPAN_PATTERN_GRAY_INCLUDED
|
||||
#define AGG_SPAN_PATTERN_GRAY_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================span_pattern_gray
|
||||
template<class Source> class span_pattern_gray
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_pattern_gray() {}
|
||||
span_pattern_gray(source_type& src,
|
||||
unsigned offset_x, unsigned offset_y) :
|
||||
m_src(&src),
|
||||
m_offset_x(offset_x),
|
||||
m_offset_y(offset_y),
|
||||
m_alpha(color_type::base_mask)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
source_type& source() { return *m_src; }
|
||||
const source_type& source() const { return *m_src; }
|
||||
void set_source(source_type& v) { m_src = &v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void offset_x(unsigned v) { m_offset_x = v; }
|
||||
void offset_y(unsigned v) { m_offset_y = v; }
|
||||
unsigned offset_x() const { return m_offset_x; }
|
||||
unsigned offset_y() const { return m_offset_y; }
|
||||
void alpha(value_type v) { m_alpha = v; }
|
||||
value_type alpha() const { return m_alpha; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
x += m_offset_x;
|
||||
y += m_offset_y;
|
||||
const value_type* p = (const value_type*)m_src->span(x, y, len);
|
||||
do
|
||||
{
|
||||
span->v = *p;
|
||||
span->a = m_alpha;
|
||||
p = m_src->next_x();
|
||||
++span;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
private:
|
||||
source_type* m_src;
|
||||
unsigned m_offset_x;
|
||||
unsigned m_offset_y;
|
||||
value_type m_alpha;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
96
agg/include/agg_span_pattern_rgb.h
Normal file
96
agg/include/agg_span_pattern_rgb.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef AGG_SPAN_PATTERN_RGB_INCLUDED
|
||||
#define AGG_SPAN_PATTERN_RGB_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//========================================================span_pattern_rgb
|
||||
template<class Source> class span_pattern_rgb
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_pattern_rgb() {}
|
||||
span_pattern_rgb(source_type& src,
|
||||
unsigned offset_x, unsigned offset_y) :
|
||||
m_src(&src),
|
||||
m_offset_x(offset_x),
|
||||
m_offset_y(offset_y),
|
||||
m_alpha(color_type::base_mask)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
source_type& source() { return *m_src; }
|
||||
const source_type& source() const { return *m_src; }
|
||||
void set_source(source_type& v) { m_src = &v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void offset_x(unsigned v) { m_offset_x = v; }
|
||||
void offset_y(unsigned v) { m_offset_y = v; }
|
||||
unsigned offset_x() const { return m_offset_x; }
|
||||
unsigned offset_y() const { return m_offset_y; }
|
||||
void alpha(value_type v) { m_alpha = v; }
|
||||
value_type alpha() const { return m_alpha; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
x += m_offset_x;
|
||||
y += m_offset_y;
|
||||
const value_type* p = (const value_type*)m_src->span(x, y, len);
|
||||
do
|
||||
{
|
||||
span->r = p[order_type::R];
|
||||
span->g = p[order_type::G];
|
||||
span->b = p[order_type::B];
|
||||
span->a = m_alpha;
|
||||
p = m_src->next_x();
|
||||
++span;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
private:
|
||||
source_type* m_src;
|
||||
unsigned m_offset_x;
|
||||
unsigned m_offset_y;
|
||||
value_type m_alpha;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
94
agg/include/agg_span_pattern_rgba.h
Normal file
94
agg/include/agg_span_pattern_rgba.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef AGG_SPAN_PATTERN_RGBA_INCLUDED
|
||||
#define AGG_SPAN_PATTERN_RGBA_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//======================================================span_pattern_rgba
|
||||
template<class Source> class span_pattern_rgba
|
||||
{
|
||||
public:
|
||||
typedef Source source_type;
|
||||
typedef typename source_type::color_type color_type;
|
||||
typedef typename source_type::order_type order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_pattern_rgba() {}
|
||||
span_pattern_rgba(source_type& src,
|
||||
unsigned offset_x, unsigned offset_y) :
|
||||
m_src(&src),
|
||||
m_offset_x(offset_x),
|
||||
m_offset_y(offset_y)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
source_type& source() { return *m_src; }
|
||||
const source_type& source() const { return *m_src; }
|
||||
void set_source(source_type& v) { m_src = &v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void offset_x(unsigned v) { m_offset_x = v; }
|
||||
void offset_y(unsigned v) { m_offset_y = v; }
|
||||
unsigned offset_x() const { return m_offset_x; }
|
||||
unsigned offset_y() const { return m_offset_y; }
|
||||
void alpha(value_type) {}
|
||||
value_type alpha() const { return 0; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
void generate(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
x += m_offset_x;
|
||||
y += m_offset_y;
|
||||
const value_type* p = (const value_type*)m_src->span(x, y, len);
|
||||
do
|
||||
{
|
||||
span->r = p[order_type::R];
|
||||
span->g = p[order_type::G];
|
||||
span->b = p[order_type::B];
|
||||
span->a = p[order_type::A];
|
||||
p = m_src->next_x();
|
||||
++span;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
private:
|
||||
source_type* m_src;
|
||||
unsigned m_offset_x;
|
||||
unsigned m_offset_y;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue