1/*
2 * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 *
5 * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
6 *
7 *
8 * Class scanline_p8_subpix_avrg_filtering, a slightly modified version of
9 * scanline_p8 customized to store 3 covers per pixel
10 *
11 */
12
13#ifndef AGG_SCANLINE_P_SUBPIX_INCLUDED
14#define AGG_SCANLINE_P_SUBPIX_INCLUDED
15
16#include "agg_array.h"
17
18namespace agg
19{
20
21	//======================================================scanline_p8_subpix
22	//
23	// This is a general purpose scaline container which supports the interface
24	// used in the rasterizer::render(). See description of scanline_u8
25	// for details.
26	//
27	//------------------------------------------------------------------------
28	class scanline_p8_subpix
29	{
30	public:
31		typedef scanline_p8_subpix	self_type;
32		typedef int8u				cover_type;
33		typedef int16				coord_type;
34
35		//--------------------------------------------------------------------
36		struct span
37		{
38			coord_type		  x;
39			coord_type		  len; // If negative, it's a solid span, covers is valid
40			const cover_type* covers;
41		};
42
43		typedef span* iterator;
44		typedef const span* const_iterator;
45
46		scanline_p8_subpix() :
47			m_last_x(0x7FFFFFF0),
48			m_covers(),
49			m_cover_ptr(0),
50			m_spans(),
51			m_cur_span(0)
52		{
53		}
54
55		//--------------------------------------------------------------------
56		void reset(int min_x, int max_x)
57		{
58			unsigned max_len = 3*(max_x - min_x + 3);
59			if(max_len > m_spans.size())
60			{
61				m_spans.resize(max_len);
62				m_covers.resize(max_len);
63			}
64			m_last_x	= 0x7FFFFFF0;
65			m_cover_ptr = &m_covers[0];
66			m_cur_span	= &m_spans[0];
67			m_cur_span->len = 0;
68		}
69
70		//--------------------------------------------------------------------
71		void add_cell(int x, unsigned cover1, unsigned cover2, unsigned cover3)
72		{
73			m_cover_ptr[0] = (cover_type)cover1;
74			m_cover_ptr[1] = (cover_type)cover2;
75			m_cover_ptr[2] = (cover_type)cover3;
76			if(x == m_last_x+1 && m_cur_span->len > 0)
77			{
78				m_cur_span->len += 3;
79			}
80			else
81			{
82				m_cur_span++;
83				m_cur_span->covers = m_cover_ptr;
84				m_cur_span->x = (int16)x;
85				m_cur_span->len = 3;
86			}
87			m_last_x = x;
88			m_cover_ptr += 3;
89		}
90
91		//--------------------------------------------------------------------
92		void add_cells(int x, unsigned len, const cover_type* covers)
93		{
94			memcpy(m_cover_ptr, covers, 3 * len * sizeof(cover_type));
95			if(x == m_last_x+1 && m_cur_span->len > 0)
96			{
97				m_cur_span->len += 3 * (int16)len;
98			}
99			else
100			{
101				m_cur_span++;
102				m_cur_span->covers = m_cover_ptr;
103				m_cur_span->x = (int16)x;
104				m_cur_span->len = 3 * (int16)len;
105			}
106			m_cover_ptr += 3 * len;
107			m_last_x = x + len - 1;
108		}
109
110		//--------------------------------------------------------------------
111		void add_span(int x, unsigned len, unsigned cover)
112		{
113			if(x == m_last_x+1 &&
114			   m_cur_span->len < 0 &&
115			   cover == *m_cur_span->covers)
116			{
117				m_cur_span->len -= 3 * (int16)len;
118			}
119			else
120			{
121				*m_cover_ptr = (cover_type)cover;
122				m_cur_span++;
123				m_cur_span->covers = m_cover_ptr;
124				m_cover_ptr += 3;
125				m_cur_span->x	   = (int16)x;
126				m_cur_span->len	   = 3 * (int16)(-int(len));
127			}
128			m_last_x = x + len - 1;
129		}
130
131		//--------------------------------------------------------------------
132		void finalize(int y)
133		{
134			m_y = y;
135		}
136
137		//--------------------------------------------------------------------
138		void reset_spans()
139		{
140			m_last_x	= 0x7FFFFFF0;
141			m_cover_ptr = &m_covers[0];
142			m_cur_span	= &m_spans[0];
143			m_cur_span->len = 0;
144		}
145
146		//--------------------------------------------------------------------
147		int			   y()		   const { return m_y; }
148		unsigned	   num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
149		const_iterator begin()	   const { return &m_spans[1]; }
150
151	private:
152		scanline_p8_subpix(const self_type&);
153		const self_type& operator = (const self_type&);
154
155		int					  m_last_x;
156		int					  m_y;
157		pod_array<cover_type> m_covers;
158		cover_type*			  m_cover_ptr;
159		pod_array<span>		  m_spans;
160		span*				  m_cur_span;
161	};
162
163}
164
165
166#endif
167
168