1/*
2 * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
3 * Copyright 2008, Stephan A��mus <superstippi@gmx.de>.
4 * All rights reserved. Distributed under the terms of the MIT License.
5 *
6 * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
7 *
8 *
9 * Class scanline_p8_subpix_avrg_filtering, a slightly modified version of
10 * scanline_p8 customized to store 3 covers per pixel and to implement
11 * average-based color filtering
12 *
13 */
14
15#ifndef AGG_SCANLINE_P_SUBPIX_AVRG_FILTERING_INCLUDED
16#define AGG_SCANLINE_P_SUBPIX_AVRG_FILTERING_INCLUDED
17
18#include "GlobalSubpixelSettings.h"
19
20namespace agg
21{
22	//========================================scanline_p8_subpix_avrg_filtering
23	//
24	// This is a general purpose scaline container which supports the interface
25	// used in the rasterizer::render(). See description of scanline_u8
26	// for details.
27	//
28	//------------------------------------------------------------------------
29	class scanline_p8_subpix_avrg_filtering
30	{
31	public:
32		typedef scanline_p8_subpix	self_type;
33		typedef int8u				cover_type;
34		typedef int16				coord_type;
35
36		//--------------------------------------------------------------------
37		struct span
38		{
39			coord_type		  x;
40			coord_type		  len; // If negative, it's a solid span, covers is valid
41			const cover_type* covers;
42		};
43
44		typedef span* iterator;
45		typedef const span* const_iterator;
46
47		scanline_p8_subpix_avrg_filtering() :
48			m_last_x(0x7FFFFFF0),
49			m_covers(),
50			m_cover_ptr(0),
51			m_spans(),
52			m_cur_span(0)
53		{
54		}
55
56		//--------------------------------------------------------------------
57		void reset(int min_x, int max_x)
58		{
59			unsigned max_len = 3*(max_x - min_x + 3);
60			if(max_len > m_spans.size())
61			{
62				m_spans.resize(max_len);
63				m_covers.resize(max_len);
64			}
65			m_last_x	= 0x7FFFFFF0;
66			m_cover_ptr = &m_covers[0];
67			m_cur_span	= &m_spans[0];
68			m_cur_span->len = 0;
69		}
70
71		//--------------------------------------------------------------------
72		void add_cell(int x, unsigned cover1, unsigned cover2, unsigned cover3)
73		{
74
75		// NOTE stippi: My basic idea is that filtering tries to minimize colored
76		// edges, but it does so by blurring the coverage values. This will also
77		// affect neighboring pixels and add blur where there were perfectly sharp
78		// edges. Andrej's method of filtering adds a special case for perfectly
79		// sharp edges, but the drawback here is that there will be a visible
80		// transition between blurred and non-blurred subpixels. I had the idea that
81		// when simply fading the subpixels towards the plain gray-scale-aa values,
82		// there must be a sweet spot for when colored edges become non-disturbing
83		// and there is still a benefit of sharpness compared to straight gray-scale-
84		// aa. The define above enables this method against the colored edges. My
85		// method still has a drawback, since jaggies in diagonal lines will be more
86		// visible again than with the filter method.
87
88			unsigned char averageWeight = gSubpixelAverageWeight;
89			unsigned char subpixelWeight = 255 - averageWeight;
90
91			unsigned int coverR;
92			unsigned int coverG;
93			unsigned int coverB;
94
95			unsigned int average = (cover1 + cover2 + cover3 + 2) / 3;
96
97			coverR = (cover1 * subpixelWeight + average * averageWeight) >> 8;
98			coverG = (cover2 * subpixelWeight + average * averageWeight) >> 8;
99			coverB = (cover3 * subpixelWeight + average * averageWeight) >> 8;
100
101			m_cover_ptr[0] = (cover_type)coverR;
102			m_cover_ptr[1] = (cover_type)coverG;
103			m_cover_ptr[2] = (cover_type)coverB;
104			if(x == m_last_x+1 && m_cur_span->len > 0)
105			{
106				m_cur_span->len += 3;
107			}
108			else
109			{
110				m_cur_span++;
111				m_cur_span->covers = m_cover_ptr;
112				m_cur_span->x = (int16)x;
113				m_cur_span->len = 3;
114			}
115			m_last_x = x;
116			m_cover_ptr += 3;
117		}
118
119		//--------------------------------------------------------------------
120		void add_cells(int x, unsigned len, const cover_type* covers)
121		{
122			memcpy(m_cover_ptr, covers, 3 * len * sizeof(cover_type));
123			if(x == m_last_x+1 && m_cur_span->len > 0)
124			{
125				m_cur_span->len += 3 * (int16)len;
126			}
127			else
128			{
129				m_cur_span++;
130				m_cur_span->covers = m_cover_ptr;
131				m_cur_span->x = (int16)x;
132				m_cur_span->len = 3 * (int16)len;
133			}
134			m_cover_ptr += 3 * len;
135			m_last_x = x + len - 1;
136		}
137
138		//--------------------------------------------------------------------
139		void add_span(int x, unsigned len, unsigned cover)
140		{
141			if(x == m_last_x+1 &&
142			   m_cur_span->len < 0 &&
143			   cover == *m_cur_span->covers)
144			{
145				m_cur_span->len -= 3 * (int16)len;
146			}
147			else
148			{
149				*m_cover_ptr = (cover_type)cover;
150				m_cur_span++;
151				m_cur_span->covers = m_cover_ptr;
152				m_cover_ptr += 3;
153				m_cur_span->x	   = (int16)x;
154				m_cur_span->len	   = 3 * (int16)(-int(len));
155			}
156			m_last_x = x + len - 1;
157		}
158
159		//--------------------------------------------------------------------
160		void finalize(int y)
161		{
162			m_y = y;
163		}
164
165		//--------------------------------------------------------------------
166		void reset_spans()
167		{
168			m_last_x	= 0x7FFFFFF0;
169			m_cover_ptr = &m_covers[0];
170			m_cur_span	= &m_spans[0];
171			m_cur_span->len = 0;
172		}
173
174		//--------------------------------------------------------------------
175		int			   y()		   const { return m_y; }
176		unsigned	   num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
177		const_iterator begin()	   const { return &m_spans[1]; }
178
179	private:
180		scanline_p8_subpix_avrg_filtering(const self_type&);
181		const self_type& operator = (const self_type&);
182
183		int					  m_last_x;
184		int					  m_y;
185		pod_array<cover_type> m_covers;
186		cover_type*			  m_cover_ptr;
187		pod_array<span>		  m_spans;
188		span*				  m_cur_span;
189	};
190
191}
192
193
194#endif
195
196