xref: /haiku/src/servers/app/drawing/Painter/agg_rasterizer_scanline_aa_subpix.h (revision 70b978fd9fc574e72a9f91f58beb36c521ec57c4)
159e13a3fSStephan Aßmus /*
259e13a3fSStephan Aßmus  * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
359e13a3fSStephan Aßmus  * All rights reserved. Distributed under the terms of the MIT License.
459e13a3fSStephan Aßmus  *
559e13a3fSStephan Aßmus  * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
659e13a3fSStephan Aßmus  *
759e13a3fSStephan Aßmus  *
859e13a3fSStephan Aßmus  */
959e13a3fSStephan Aßmus 
1059e13a3fSStephan Aßmus #ifndef AGG_RASTERIZER_SCANLINE_AA_SUBPIX_INCLUDED
1159e13a3fSStephan Aßmus #define AGG_RASTERIZER_SCANLINE_AA_SUBPIX_INCLUDED
1259e13a3fSStephan Aßmus 
1359e13a3fSStephan Aßmus #include "agg_rasterizer_cells_aa.h"
1459e13a3fSStephan Aßmus #include "agg_rasterizer_sl_clip.h"
1559e13a3fSStephan Aßmus #include "agg_gamma_functions.h"
1659e13a3fSStephan Aßmus 
1759e13a3fSStephan Aßmus 
1859e13a3fSStephan Aßmus namespace agg
1959e13a3fSStephan Aßmus {
2059e13a3fSStephan Aßmus 	template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa_subpix
2159e13a3fSStephan Aßmus 	{
2259e13a3fSStephan Aßmus 		enum status
2359e13a3fSStephan Aßmus 		{
2459e13a3fSStephan Aßmus 			status_initial,
2559e13a3fSStephan Aßmus 			status_move_to,
2659e13a3fSStephan Aßmus 			status_line_to,
2759e13a3fSStephan Aßmus 			status_closed
2859e13a3fSStephan Aßmus 		};
2959e13a3fSStephan Aßmus 
3059e13a3fSStephan Aßmus 	public:
3159e13a3fSStephan Aßmus 		typedef Clip					  clip_type;
3259e13a3fSStephan Aßmus 		typedef typename Clip::conv_type  conv_type;
3359e13a3fSStephan Aßmus 		typedef typename Clip::coord_type coord_type;
3459e13a3fSStephan Aßmus 
3559e13a3fSStephan Aßmus 		enum aa_scale_e
3659e13a3fSStephan Aßmus 		{
3759e13a3fSStephan Aßmus 			aa_shift  = 8,
3859e13a3fSStephan Aßmus 			aa_scale  = 1 << aa_shift,
3959e13a3fSStephan Aßmus 			aa_mask	  = aa_scale - 1,
4059e13a3fSStephan Aßmus 			aa_scale2 = aa_scale * 2,
4159e13a3fSStephan Aßmus 			aa_mask2  = aa_scale2 - 1
4259e13a3fSStephan Aßmus 		};
4359e13a3fSStephan Aßmus 
4459e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
rasterizer_scanline_aa_subpix()4559e13a3fSStephan Aßmus 		rasterizer_scanline_aa_subpix() :
4659e13a3fSStephan Aßmus 			m_outline(),
4759e13a3fSStephan Aßmus 			m_clipper(),
4859e13a3fSStephan Aßmus 			m_filling_rule(fill_non_zero),
4959e13a3fSStephan Aßmus 			m_auto_close(true),
5059e13a3fSStephan Aßmus 			m_start_x(0),
5159e13a3fSStephan Aßmus 			m_start_y(0),
5259e13a3fSStephan Aßmus 			m_status(status_initial)
5359e13a3fSStephan Aßmus 		{
5459e13a3fSStephan Aßmus 			int i;
5559e13a3fSStephan Aßmus 			for(i = 0; i < aa_scale; i++) m_gamma[i] = i;
5659e13a3fSStephan Aßmus 		}
5759e13a3fSStephan Aßmus 
5859e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
5959e13a3fSStephan Aßmus 		template<class GammaF>
rasterizer_scanline_aa_subpix(const GammaF & gamma_function)6059e13a3fSStephan Aßmus 		rasterizer_scanline_aa_subpix(const GammaF& gamma_function) :
6159e13a3fSStephan Aßmus 			m_outline(),
6259e13a3fSStephan Aßmus 			m_clipper(m_outline),
6359e13a3fSStephan Aßmus 			m_filling_rule(fill_non_zero),
6459e13a3fSStephan Aßmus 			m_auto_close(true),
6559e13a3fSStephan Aßmus 			m_start_x(0),
6659e13a3fSStephan Aßmus 			m_start_y(0),
6759e13a3fSStephan Aßmus 			m_status(status_initial)
6859e13a3fSStephan Aßmus 		{
6959e13a3fSStephan Aßmus 			gamma(gamma_function);
7059e13a3fSStephan Aßmus 		}
7159e13a3fSStephan Aßmus 
7259e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
7359e13a3fSStephan Aßmus 		void reset();
7459e13a3fSStephan Aßmus 		void reset_clipping();
7559e13a3fSStephan Aßmus 		void clip_box(double x1, double y1, double x2, double y2);
7659e13a3fSStephan Aßmus 		void filling_rule(filling_rule_e filling_rule);
auto_close(bool flag)7759e13a3fSStephan Aßmus 		void auto_close(bool flag) { m_auto_close = flag; }
7859e13a3fSStephan Aßmus 
7959e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
gamma(const GammaF & gamma_function)8059e13a3fSStephan Aßmus 		template<class GammaF> void gamma(const GammaF& gamma_function)
8159e13a3fSStephan Aßmus 		{
8259e13a3fSStephan Aßmus 			int i;
8359e13a3fSStephan Aßmus 			for(i = 0; i < aa_scale; i++)
8459e13a3fSStephan Aßmus 			{
8559e13a3fSStephan Aßmus 				m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask);
8659e13a3fSStephan Aßmus 			}
8759e13a3fSStephan Aßmus 		}
8859e13a3fSStephan Aßmus 
8959e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
apply_gamma(unsigned cover)9059e13a3fSStephan Aßmus 		unsigned apply_gamma(unsigned cover) const
9159e13a3fSStephan Aßmus 		{
9259e13a3fSStephan Aßmus 			return m_gamma[cover];
9359e13a3fSStephan Aßmus 		}
9459e13a3fSStephan Aßmus 
9559e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
9659e13a3fSStephan Aßmus 		void move_to(int x, int y);
9759e13a3fSStephan Aßmus 		void line_to(int x, int y);
9859e13a3fSStephan Aßmus 		void move_to_d(double x, double y);
9959e13a3fSStephan Aßmus 		void line_to_d(double x, double y);
10059e13a3fSStephan Aßmus 		void close_polygon();
10159e13a3fSStephan Aßmus 		void add_vertex(double x, double y, unsigned cmd);
10259e13a3fSStephan Aßmus 
10359e13a3fSStephan Aßmus 		void edge(int x1, int y1, int x2, int y2);
10459e13a3fSStephan Aßmus 		void edge_d(double x1, double y1, double x2, double y2);
10559e13a3fSStephan Aßmus 
10659e13a3fSStephan Aßmus 		//-------------------------------------------------------------------
10759e13a3fSStephan Aßmus 		template<class VertexSource>
10859e13a3fSStephan Aßmus 		void add_path(VertexSource& vs, unsigned path_id=0)
10959e13a3fSStephan Aßmus 		{
110*70b978fdSMurai Takashi 			double x = 0;
111*70b978fdSMurai Takashi 			double y = 0;
11259e13a3fSStephan Aßmus 
11359e13a3fSStephan Aßmus 			unsigned cmd;
11459e13a3fSStephan Aßmus 			vs.rewind(path_id);
11559e13a3fSStephan Aßmus 			if(m_outline.sorted()) reset();
11659e13a3fSStephan Aßmus 			while(!is_stop(cmd = vs.vertex(&x, &y)))
11759e13a3fSStephan Aßmus 			{
11859e13a3fSStephan Aßmus 				if (is_vertex(cmd)) {
11959e13a3fSStephan Aßmus 					x *= 3;
12059e13a3fSStephan Aßmus 				}
12159e13a3fSStephan Aßmus 				add_vertex(x, y, cmd);
12259e13a3fSStephan Aßmus 			}
12359e13a3fSStephan Aßmus 		}
12459e13a3fSStephan Aßmus 
12559e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
min_x()12659e13a3fSStephan Aßmus 		int min_x() const { return m_outline.min_x() / 3; }
min_y()12759e13a3fSStephan Aßmus 		int min_y() const { return m_outline.min_y(); }
max_x()12859e13a3fSStephan Aßmus 		int max_x() const { return m_outline.max_x() / 3; }
max_y()12959e13a3fSStephan Aßmus 		int max_y() const { return m_outline.max_y(); }
13059e13a3fSStephan Aßmus 
13159e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
13259e13a3fSStephan Aßmus 		void sort();
13359e13a3fSStephan Aßmus 		bool rewind_scanlines();
13459e13a3fSStephan Aßmus 		bool navigate_scanline(int y);
13559e13a3fSStephan Aßmus 
13659e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
calculate_alpha(int area)13759e13a3fSStephan Aßmus 		AGG_INLINE unsigned calculate_alpha(int area) const
13859e13a3fSStephan Aßmus 		{
13959e13a3fSStephan Aßmus 			int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
14059e13a3fSStephan Aßmus 
14159e13a3fSStephan Aßmus 			if(cover < 0) cover = -cover;
14259e13a3fSStephan Aßmus 			if(m_filling_rule == fill_even_odd)
14359e13a3fSStephan Aßmus 			{
14459e13a3fSStephan Aßmus 				cover &= aa_mask2;
14559e13a3fSStephan Aßmus 				if(cover > aa_scale)
14659e13a3fSStephan Aßmus 				{
14759e13a3fSStephan Aßmus 					cover = aa_scale2 - cover;
14859e13a3fSStephan Aßmus 				}
14959e13a3fSStephan Aßmus 			}
15059e13a3fSStephan Aßmus 			if(cover > aa_mask) cover = aa_mask;
15159e13a3fSStephan Aßmus 			return m_gamma[cover];
15259e13a3fSStephan Aßmus 		}
15359e13a3fSStephan Aßmus 
15459e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
sweep_scanline(Scanline & sl)15559e13a3fSStephan Aßmus 		template<class Scanline> bool sweep_scanline(Scanline& sl)
15659e13a3fSStephan Aßmus 		{
15759e13a3fSStephan Aßmus 			for(;;)
15859e13a3fSStephan Aßmus 			{
15959e13a3fSStephan Aßmus 				if(m_scan_y > m_outline.max_y()) return false;
16059e13a3fSStephan Aßmus 				sl.reset_spans();
16159e13a3fSStephan Aßmus 				unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
16259e13a3fSStephan Aßmus 				const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y);
16359e13a3fSStephan Aßmus 				int cover = 0;
16459e13a3fSStephan Aßmus 				int cover2 = 0;
16559e13a3fSStephan Aßmus 				int cover3 = 0;
16659e13a3fSStephan Aßmus 
16759e13a3fSStephan Aßmus 				while(num_cells)
16859e13a3fSStephan Aßmus 				{
16959e13a3fSStephan Aßmus 					const cell_aa* cur_cell = *cells;
17059e13a3fSStephan Aßmus 					int x	 = cur_cell->x;
17159e13a3fSStephan Aßmus 					int area1 = cur_cell->area;
17259e13a3fSStephan Aßmus 					int area2;
17359e13a3fSStephan Aßmus 					int area3;
17459e13a3fSStephan Aßmus 					unsigned alpha1;
17559e13a3fSStephan Aßmus 					unsigned alpha2;
17659e13a3fSStephan Aßmus 					unsigned alpha3;
17759e13a3fSStephan Aßmus 
17859e13a3fSStephan Aßmus 					int last_cover = cover3;
17959e13a3fSStephan Aßmus 					cover = cover3;
18059e13a3fSStephan Aßmus 					cover += cur_cell->cover;
18159e13a3fSStephan Aßmus 
18259e13a3fSStephan Aßmus 					while(--num_cells)
18359e13a3fSStephan Aßmus 					{
18459e13a3fSStephan Aßmus 						cur_cell = *++cells;
18559e13a3fSStephan Aßmus 						if(cur_cell->x != x) break;
18659e13a3fSStephan Aßmus 						area1  += cur_cell->area;
18759e13a3fSStephan Aßmus 						cover += cur_cell->cover;
18859e13a3fSStephan Aßmus 					}
18959e13a3fSStephan Aßmus 
19059e13a3fSStephan Aßmus 					if (x % 3 == 0)
19159e13a3fSStephan Aßmus 					{
19259e13a3fSStephan Aßmus 						if (cur_cell->x == x + 1)
19359e13a3fSStephan Aßmus 						{
19459e13a3fSStephan Aßmus 							area2 = cur_cell->area;
19559e13a3fSStephan Aßmus 							cover2 = cover + cur_cell->cover;
19659e13a3fSStephan Aßmus 
19759e13a3fSStephan Aßmus 							while (--num_cells)
19859e13a3fSStephan Aßmus 							{
19959e13a3fSStephan Aßmus 								cur_cell = *++cells;
20059e13a3fSStephan Aßmus 								if (cur_cell->x != x+1) break;
20159e13a3fSStephan Aßmus 								area2 += cur_cell->area;
20259e13a3fSStephan Aßmus 								cover2 += cur_cell->cover;
20359e13a3fSStephan Aßmus 							}
20459e13a3fSStephan Aßmus 						}
20559e13a3fSStephan Aßmus 						else
20659e13a3fSStephan Aßmus 						{
20759e13a3fSStephan Aßmus 							area2 = 0;
20859e13a3fSStephan Aßmus 							cover2 = cover;
20959e13a3fSStephan Aßmus 						}
21059e13a3fSStephan Aßmus 
21159e13a3fSStephan Aßmus 						if (cur_cell->x == x + 2)
21259e13a3fSStephan Aßmus 						{
21359e13a3fSStephan Aßmus 							area3 = cur_cell->area;
21459e13a3fSStephan Aßmus 							cover3 = cover2 + cur_cell->cover;
21559e13a3fSStephan Aßmus 
21659e13a3fSStephan Aßmus 							while (--num_cells)
21759e13a3fSStephan Aßmus 							{
21859e13a3fSStephan Aßmus 								cur_cell = *++cells;
21959e13a3fSStephan Aßmus 								if (cur_cell->x != x+2) break;
22059e13a3fSStephan Aßmus 								area3 += cur_cell->area;
22159e13a3fSStephan Aßmus 								cover3 += cur_cell->cover;
22259e13a3fSStephan Aßmus 							}
22359e13a3fSStephan Aßmus 						}
22459e13a3fSStephan Aßmus 						else
22559e13a3fSStephan Aßmus 						{
22659e13a3fSStephan Aßmus 							area3 = 0;
22759e13a3fSStephan Aßmus 							cover3 = cover2;
22859e13a3fSStephan Aßmus 						}
22959e13a3fSStephan Aßmus 					}
23059e13a3fSStephan Aßmus 					else if (x % 3 == 1)
23159e13a3fSStephan Aßmus 					{
23259e13a3fSStephan Aßmus 						area2 = area1;
23359e13a3fSStephan Aßmus 						area1 = 0;
23459e13a3fSStephan Aßmus 						cover2 = cover;
23559e13a3fSStephan Aßmus 						cover = last_cover;
23659e13a3fSStephan Aßmus 						if (cur_cell->x == x+1)
23759e13a3fSStephan Aßmus 						{
23859e13a3fSStephan Aßmus 							area3 = cur_cell->area;
23959e13a3fSStephan Aßmus 							cover3 = cover2 + cur_cell->cover;
24059e13a3fSStephan Aßmus 
24159e13a3fSStephan Aßmus 							while (--num_cells)
24259e13a3fSStephan Aßmus 							{
24359e13a3fSStephan Aßmus 								cur_cell = *++cells;
24459e13a3fSStephan Aßmus 								if (cur_cell->x != x+1) break;
24559e13a3fSStephan Aßmus 								area3 += cur_cell->area;
24659e13a3fSStephan Aßmus 								cover3 += cur_cell->cover;
24759e13a3fSStephan Aßmus 							}
24859e13a3fSStephan Aßmus 						}
24959e13a3fSStephan Aßmus 						else
25059e13a3fSStephan Aßmus 						{
25159e13a3fSStephan Aßmus 							area3 = 0;
25259e13a3fSStephan Aßmus 							cover3 = cover2;
25359e13a3fSStephan Aßmus 						}
25459e13a3fSStephan Aßmus 					}
25559e13a3fSStephan Aßmus 					else // if (x % 3 == 2)
25659e13a3fSStephan Aßmus 					{
25759e13a3fSStephan Aßmus 						area3 = area1;
25859e13a3fSStephan Aßmus 						area2 = 0;
25959e13a3fSStephan Aßmus 						area1 = 0;
26059e13a3fSStephan Aßmus 						cover3 = cover;
26159e13a3fSStephan Aßmus 						cover = last_cover;
26259e13a3fSStephan Aßmus 						cover2 = last_cover;
26359e13a3fSStephan Aßmus 					}
26459e13a3fSStephan Aßmus 
26559e13a3fSStephan Aßmus 					alpha1 = area1 ? calculate_alpha((cover
26659e13a3fSStephan Aßmus 						<< (poly_subpixel_shift + 1)) - area1) : 0;
26759e13a3fSStephan Aßmus 					alpha2 = area2 ? calculate_alpha((cover2
26859e13a3fSStephan Aßmus 						<< (poly_subpixel_shift + 1)) - area2) : 0;
26959e13a3fSStephan Aßmus 					alpha3 = area3 ? calculate_alpha((cover3
27059e13a3fSStephan Aßmus 						<< (poly_subpixel_shift + 1)) - area3) : 0;
27159e13a3fSStephan Aßmus 					if(alpha1 || alpha2 || alpha3)
27259e13a3fSStephan Aßmus 					{
27359e13a3fSStephan Aßmus 						x += 3 - (x % 3);
27459e13a3fSStephan Aßmus 						if (area1 && !area2 && area3)
27559e13a3fSStephan Aßmus 						{
27659e13a3fSStephan Aßmus 							alpha2 = calculate_alpha(cover
27759e13a3fSStephan Aßmus 								<< (poly_subpixel_shift + 1));
27859e13a3fSStephan Aßmus 						}
27959e13a3fSStephan Aßmus 						else if (num_cells && cur_cell->x >= x)
28059e13a3fSStephan Aßmus 						{
28159e13a3fSStephan Aßmus 							if (area1 && !area2)
28259e13a3fSStephan Aßmus 							{
28359e13a3fSStephan Aßmus 								alpha2 = calculate_alpha(cover
28459e13a3fSStephan Aßmus 									<< (poly_subpixel_shift + 1));
28559e13a3fSStephan Aßmus 								alpha3 = alpha2;
28659e13a3fSStephan Aßmus 							}
28759e13a3fSStephan Aßmus 							if (area2 && !area3)
28859e13a3fSStephan Aßmus 							{
28959e13a3fSStephan Aßmus 								alpha3 = calculate_alpha(cover2
29059e13a3fSStephan Aßmus 									<< (poly_subpixel_shift + 1));
29159e13a3fSStephan Aßmus 							}
29259e13a3fSStephan Aßmus 						}
29359e13a3fSStephan Aßmus 						if (!area1)
29459e13a3fSStephan Aßmus 						{
29559e13a3fSStephan Aßmus 							if (area2)
29659e13a3fSStephan Aßmus 							{
29759e13a3fSStephan Aßmus 								alpha1 = calculate_alpha(cover
29859e13a3fSStephan Aßmus 									<< (poly_subpixel_shift + 1));
29959e13a3fSStephan Aßmus 							}
30059e13a3fSStephan Aßmus 							else if (area3)
30159e13a3fSStephan Aßmus 							{
30259e13a3fSStephan Aßmus 								alpha2 = calculate_alpha(cover
30359e13a3fSStephan Aßmus 									<< (poly_subpixel_shift + 1));
30459e13a3fSStephan Aßmus 								alpha1 = alpha2;
30559e13a3fSStephan Aßmus 							}
30659e13a3fSStephan Aßmus 						}
30759e13a3fSStephan Aßmus 						sl.add_cell(x / 3 - 1, alpha1, alpha2, alpha3);
30859e13a3fSStephan Aßmus 					}
30959e13a3fSStephan Aßmus 
31059e13a3fSStephan Aßmus 					if (num_cells && cur_cell->x - x >= 3)
31159e13a3fSStephan Aßmus 					{
31259e13a3fSStephan Aßmus 						alpha1 = calculate_alpha(cover3
31359e13a3fSStephan Aßmus 							<< (poly_subpixel_shift + 1));
31459e13a3fSStephan Aßmus 						sl.add_span(x / 3, cur_cell->x / 3 - x / 3, alpha1);
31559e13a3fSStephan Aßmus 					}
31659e13a3fSStephan Aßmus 				}
31759e13a3fSStephan Aßmus 
31859e13a3fSStephan Aßmus 				if(sl.num_spans()) break;
31959e13a3fSStephan Aßmus 				++m_scan_y;
32059e13a3fSStephan Aßmus 			}
32159e13a3fSStephan Aßmus 
32259e13a3fSStephan Aßmus 			sl.finalize(m_scan_y);
32359e13a3fSStephan Aßmus 			++m_scan_y;
32459e13a3fSStephan Aßmus 			return true;
32559e13a3fSStephan Aßmus 		}
32659e13a3fSStephan Aßmus 
32759e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
32859e13a3fSStephan Aßmus 		bool hit_test(int tx, int ty);
32959e13a3fSStephan Aßmus 
33059e13a3fSStephan Aßmus 
33159e13a3fSStephan Aßmus 	private:
33259e13a3fSStephan Aßmus 		//--------------------------------------------------------------------
33359e13a3fSStephan Aßmus 		// Disable copying
33459e13a3fSStephan Aßmus 		rasterizer_scanline_aa_subpix(const rasterizer_scanline_aa_subpix<Clip>&);
33559e13a3fSStephan Aßmus 		const rasterizer_scanline_aa_subpix<Clip>&
33659e13a3fSStephan Aßmus 		operator = (const rasterizer_scanline_aa_subpix<Clip>&);
33759e13a3fSStephan Aßmus 
33859e13a3fSStephan Aßmus 	private:
33959e13a3fSStephan Aßmus 		rasterizer_cells_aa<cell_aa> m_outline;
34059e13a3fSStephan Aßmus 		clip_type	   m_clipper;
34159e13a3fSStephan Aßmus 		int			   m_gamma[aa_scale];
34259e13a3fSStephan Aßmus 		filling_rule_e m_filling_rule;
34359e13a3fSStephan Aßmus 		bool		   m_auto_close;
34459e13a3fSStephan Aßmus 		coord_type	   m_start_x;
34559e13a3fSStephan Aßmus 		coord_type	   m_start_y;
34659e13a3fSStephan Aßmus 		unsigned	   m_status;
34759e13a3fSStephan Aßmus 		int			   m_scan_y;
34859e13a3fSStephan Aßmus 	};
34959e13a3fSStephan Aßmus 
35059e13a3fSStephan Aßmus 
35159e13a3fSStephan Aßmus 
35259e13a3fSStephan Aßmus 
35359e13a3fSStephan Aßmus 
35459e13a3fSStephan Aßmus 
35559e13a3fSStephan Aßmus 
35659e13a3fSStephan Aßmus 
35759e13a3fSStephan Aßmus 
35859e13a3fSStephan Aßmus 
35959e13a3fSStephan Aßmus 
36059e13a3fSStephan Aßmus 
36159e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
36259e13a3fSStephan Aßmus 	template<class Clip>
reset()36359e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::reset()
36459e13a3fSStephan Aßmus 	{
36559e13a3fSStephan Aßmus 		m_outline.reset();
36659e13a3fSStephan Aßmus 		m_status = status_initial;
36759e13a3fSStephan Aßmus 	}
36859e13a3fSStephan Aßmus 
36959e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
37059e13a3fSStephan Aßmus 	template<class Clip>
filling_rule(filling_rule_e filling_rule)37159e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::filling_rule(filling_rule_e filling_rule)
37259e13a3fSStephan Aßmus 	{
37359e13a3fSStephan Aßmus 		m_filling_rule = filling_rule;
37459e13a3fSStephan Aßmus 	}
37559e13a3fSStephan Aßmus 
37659e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
37759e13a3fSStephan Aßmus 	template<class Clip>
clip_box(double x1,double y1,double x2,double y2)37859e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::clip_box(double x1, double y1,
37959e13a3fSStephan Aßmus 												double x2, double y2)
38059e13a3fSStephan Aßmus 	{
38159e13a3fSStephan Aßmus 		reset();
38259e13a3fSStephan Aßmus 		m_clipper.clip_box(3 * conv_type::downscale(x1), conv_type::upscale(y1),
38359e13a3fSStephan Aßmus 						   conv_type::upscale(3 * x2), conv_type::upscale(y2));
38459e13a3fSStephan Aßmus 	}
38559e13a3fSStephan Aßmus 
38659e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
38759e13a3fSStephan Aßmus 	template<class Clip>
reset_clipping()38859e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::reset_clipping()
38959e13a3fSStephan Aßmus 	{
39059e13a3fSStephan Aßmus 		reset();
39159e13a3fSStephan Aßmus 		m_clipper.reset_clipping();
39259e13a3fSStephan Aßmus 	}
39359e13a3fSStephan Aßmus 
39459e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
39559e13a3fSStephan Aßmus 	template<class Clip>
close_polygon()39659e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::close_polygon()
39759e13a3fSStephan Aßmus 	{
39859e13a3fSStephan Aßmus 		if(m_status == status_line_to)
39959e13a3fSStephan Aßmus 		{
40059e13a3fSStephan Aßmus 			m_clipper.line_to(m_outline, m_start_x, m_start_y);
40159e13a3fSStephan Aßmus 			m_status = status_closed;
40259e13a3fSStephan Aßmus 		}
40359e13a3fSStephan Aßmus 	}
40459e13a3fSStephan Aßmus 
40559e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
40659e13a3fSStephan Aßmus 	template<class Clip>
move_to(int x,int y)40759e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::move_to(int x, int y)
40859e13a3fSStephan Aßmus 	{
40959e13a3fSStephan Aßmus 		if(m_outline.sorted()) reset();
41059e13a3fSStephan Aßmus 		if(m_auto_close) close_polygon();
41159e13a3fSStephan Aßmus 		m_clipper.move_to(m_start_x = conv_type::downscale(x),
41259e13a3fSStephan Aßmus 						  m_start_y = conv_type::downscale(y));
41359e13a3fSStephan Aßmus 		m_status = status_move_to;
41459e13a3fSStephan Aßmus 	}
41559e13a3fSStephan Aßmus 
41659e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
41759e13a3fSStephan Aßmus 	template<class Clip>
line_to(int x,int y)41859e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::line_to(int x, int y)
41959e13a3fSStephan Aßmus 	{
42059e13a3fSStephan Aßmus 		m_clipper.line_to(m_outline,
42159e13a3fSStephan Aßmus 						  conv_type::downscale(x),
42259e13a3fSStephan Aßmus 						  conv_type::downscale(y));
42359e13a3fSStephan Aßmus 		m_status = status_line_to;
42459e13a3fSStephan Aßmus 	}
42559e13a3fSStephan Aßmus 
42659e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
42759e13a3fSStephan Aßmus 	template<class Clip>
move_to_d(double x,double y)42859e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::move_to_d(double x, double y)
42959e13a3fSStephan Aßmus 	{
43059e13a3fSStephan Aßmus 		if(m_outline.sorted()) reset();
43159e13a3fSStephan Aßmus 		if(m_auto_close) close_polygon();
43259e13a3fSStephan Aßmus 		m_clipper.move_to(m_start_x = conv_type::upscale(x),
43359e13a3fSStephan Aßmus 						  m_start_y = conv_type::upscale(y));
43459e13a3fSStephan Aßmus 		m_status = status_move_to;
43559e13a3fSStephan Aßmus 	}
43659e13a3fSStephan Aßmus 
43759e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
43859e13a3fSStephan Aßmus 	template<class Clip>
line_to_d(double x,double y)43959e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::line_to_d(double x, double y)
44059e13a3fSStephan Aßmus 	{
44159e13a3fSStephan Aßmus 		m_clipper.line_to(m_outline,
44259e13a3fSStephan Aßmus 						  conv_type::upscale(x),
44359e13a3fSStephan Aßmus 						  conv_type::upscale(y));
44459e13a3fSStephan Aßmus 		m_status = status_line_to;
44559e13a3fSStephan Aßmus 	}
44659e13a3fSStephan Aßmus 
44759e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
44859e13a3fSStephan Aßmus 	template<class Clip>
add_vertex(double x,double y,unsigned cmd)44959e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::add_vertex(double x, double y, unsigned cmd)
45059e13a3fSStephan Aßmus 	{
45159e13a3fSStephan Aßmus 		if(is_move_to(cmd))
45259e13a3fSStephan Aßmus 		{
45359e13a3fSStephan Aßmus 			move_to_d(x, y);
45459e13a3fSStephan Aßmus 		}
45559e13a3fSStephan Aßmus 		else
45659e13a3fSStephan Aßmus 		if(is_vertex(cmd))
45759e13a3fSStephan Aßmus 		{
45859e13a3fSStephan Aßmus 			line_to_d(x, y);
45959e13a3fSStephan Aßmus 		}
46059e13a3fSStephan Aßmus 		else
46159e13a3fSStephan Aßmus 		if(is_close(cmd))
46259e13a3fSStephan Aßmus 		{
46359e13a3fSStephan Aßmus 			close_polygon();
46459e13a3fSStephan Aßmus 		}
46559e13a3fSStephan Aßmus 	}
46659e13a3fSStephan Aßmus 
46759e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
46859e13a3fSStephan Aßmus 	template<class Clip>
edge(int x1,int y1,int x2,int y2)46959e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::edge(int x1, int y1, int x2, int y2)
47059e13a3fSStephan Aßmus 	{
47159e13a3fSStephan Aßmus 		if(m_outline.sorted()) reset();
47259e13a3fSStephan Aßmus 		m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
47359e13a3fSStephan Aßmus 		m_clipper.line_to(m_outline,
47459e13a3fSStephan Aßmus 						  conv_type::downscale(x2),
47559e13a3fSStephan Aßmus 						  conv_type::downscale(y2));
47659e13a3fSStephan Aßmus 		m_status = status_move_to;
47759e13a3fSStephan Aßmus 	}
47859e13a3fSStephan Aßmus 
47959e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
48059e13a3fSStephan Aßmus 	template<class Clip>
edge_d(double x1,double y1,double x2,double y2)48159e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::edge_d(double x1, double y1,
48259e13a3fSStephan Aßmus 											  double x2, double y2)
48359e13a3fSStephan Aßmus 	{
48459e13a3fSStephan Aßmus 		if(m_outline.sorted()) reset();
48559e13a3fSStephan Aßmus 		m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
48659e13a3fSStephan Aßmus 		m_clipper.line_to(m_outline,
48759e13a3fSStephan Aßmus 						  conv_type::upscale(x2),
48859e13a3fSStephan Aßmus 						  conv_type::upscale(y2));
48959e13a3fSStephan Aßmus 		m_status = status_move_to;
49059e13a3fSStephan Aßmus 	}
49159e13a3fSStephan Aßmus 
49259e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
49359e13a3fSStephan Aßmus 	template<class Clip>
sort()49459e13a3fSStephan Aßmus 	void rasterizer_scanline_aa_subpix<Clip>::sort()
49559e13a3fSStephan Aßmus 	{
49659e13a3fSStephan Aßmus 		m_outline.sort_cells();
49759e13a3fSStephan Aßmus 	}
49859e13a3fSStephan Aßmus 
49959e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
50059e13a3fSStephan Aßmus 	template<class Clip>
rewind_scanlines()50159e13a3fSStephan Aßmus 	AGG_INLINE bool rasterizer_scanline_aa_subpix<Clip>::rewind_scanlines()
50259e13a3fSStephan Aßmus 	{
50359e13a3fSStephan Aßmus 		if(m_auto_close) close_polygon();
50459e13a3fSStephan Aßmus 		m_outline.sort_cells();
50559e13a3fSStephan Aßmus 		if(m_outline.total_cells() == 0)
50659e13a3fSStephan Aßmus 		{
50759e13a3fSStephan Aßmus 			return false;
50859e13a3fSStephan Aßmus 		}
50959e13a3fSStephan Aßmus 		m_scan_y = m_outline.min_y();
51059e13a3fSStephan Aßmus 		return true;
51159e13a3fSStephan Aßmus 	}
51259e13a3fSStephan Aßmus 
51359e13a3fSStephan Aßmus 
51459e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
51559e13a3fSStephan Aßmus 	template<class Clip>
navigate_scanline(int y)51659e13a3fSStephan Aßmus 	AGG_INLINE bool rasterizer_scanline_aa_subpix<Clip>::navigate_scanline(int y)
51759e13a3fSStephan Aßmus 	{
51859e13a3fSStephan Aßmus 		if(m_auto_close) close_polygon();
51959e13a3fSStephan Aßmus 		m_outline.sort_cells();
52059e13a3fSStephan Aßmus 		if(m_outline.total_cells() == 0 ||
52159e13a3fSStephan Aßmus 		   y < m_outline.min_y() ||
52259e13a3fSStephan Aßmus 		   y > m_outline.max_y())
52359e13a3fSStephan Aßmus 		{
52459e13a3fSStephan Aßmus 			return false;
52559e13a3fSStephan Aßmus 		}
52659e13a3fSStephan Aßmus 		m_scan_y = y;
52759e13a3fSStephan Aßmus 		return true;
52859e13a3fSStephan Aßmus 	}
52959e13a3fSStephan Aßmus 
53059e13a3fSStephan Aßmus 	//------------------------------------------------------------------------
53159e13a3fSStephan Aßmus 	template<class Clip>
hit_test(int tx,int ty)53259e13a3fSStephan Aßmus 	bool rasterizer_scanline_aa_subpix<Clip>::hit_test(int tx, int ty)
53359e13a3fSStephan Aßmus 	{
53459e13a3fSStephan Aßmus 		if(!navigate_scanline(ty)) return false;
53559e13a3fSStephan Aßmus 		scanline_hit_test sl(tx);
53659e13a3fSStephan Aßmus 		sweep_scanline(sl);
53759e13a3fSStephan Aßmus 		return sl.hit();
53859e13a3fSStephan Aßmus 	}
53959e13a3fSStephan Aßmus 
54059e13a3fSStephan Aßmus 
54159e13a3fSStephan Aßmus 
54259e13a3fSStephan Aßmus }
54359e13a3fSStephan Aßmus 
54459e13a3fSStephan Aßmus 
54559e13a3fSStephan Aßmus 
54659e13a3fSStephan Aßmus #endif
54759e13a3fSStephan Aßmus 
548