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_storage_subpix, a slightly modified version of
9 * scanline_storage customized to store 3 covers per pixel
10 *
11 */
12
13#ifndef AGG_SCANLINE_STORAGE_SUBPIX_INCLUDED
14#define AGG_SCANLINE_STORAGE_SUBPIX_INCLUDED
15
16#include <string.h>
17#include <stdlib.h>
18#include <math.h>
19#include "agg_array.h"
20#include "agg_scanline_storage_aa.h"
21
22
23namespace agg
24{
25	//--------------------------------------------scanline_storage_subpix
26	template<class T> class scanline_storage_subpix
27	{
28	public:
29		typedef T cover_type;
30
31		//---------------------------------------------------------------
32		struct span_data
33		{
34			int32 x;
35			int32 len;		 // If negative, it's a solid span, covers is valid
36			int	  covers_id; // The index of the cells in the scanline_cell_storage
37		};
38
39		//---------------------------------------------------------------
40		struct scanline_data
41		{
42			int		 y;
43			unsigned num_spans;
44			unsigned start_span;
45		};
46
47
48		//---------------------------------------------------------------
49		class embedded_scanline
50		{
51		public:
52
53			//-----------------------------------------------------------
54			class const_iterator
55			{
56			public:
57				struct span
58				{
59					int32	 x;
60					int32	 len; // If negative, it's a solid span, covers is valid
61					const T* covers;
62				};
63
64				const_iterator() : m_storage(0) {}
65				const_iterator(const embedded_scanline& sl) :
66					m_storage(sl.m_storage),
67					m_span_idx(sl.m_scanline.start_span)
68				{
69					init_span();
70				}
71
72				const span& operator*()	 const { return m_span;	 }
73				const span* operator->() const { return &m_span; }
74
75				void operator ++ ()
76				{
77					++m_span_idx;
78					init_span();
79				}
80
81			private:
82				void init_span()
83				{
84					const span_data& s = m_storage->span_by_index(m_span_idx);
85					m_span.x	  = s.x;
86					m_span.len	  = s.len;
87					m_span.covers = m_storage->covers_by_index(s.covers_id);
88				}
89
90				const scanline_storage_subpix* m_storage;
91				unsigned				   m_span_idx;
92				span					   m_span;
93			};
94
95			friend class const_iterator;
96
97
98			//-----------------------------------------------------------
99			embedded_scanline(const scanline_storage_subpix& storage) :
100				m_storage(&storage)
101			{
102				init(0);
103			}
104
105			//-----------------------------------------------------------
106			void	 reset(int, int)	 {}
107			unsigned num_spans()   const { return m_scanline.num_spans;	 }
108			int		 y()		   const { return m_scanline.y;			 }
109			const_iterator begin() const { return const_iterator(*this); }
110
111			//-----------------------------------------------------------
112			void init(unsigned scanline_idx)
113			{
114				m_scanline_idx = scanline_idx;
115				m_scanline = m_storage->scanline_by_index(m_scanline_idx);
116			}
117
118		private:
119			const scanline_storage_subpix* m_storage;
120			scanline_data			   m_scanline;
121			unsigned				   m_scanline_idx;
122		};
123
124
125		//---------------------------------------------------------------
126		scanline_storage_subpix() :
127			m_covers(),
128			m_spans(256-2),			// Block increment size
129			m_scanlines(),
130			m_min_x( 0x7FFFFFFF),
131			m_min_y( 0x7FFFFFFF),
132			m_max_x(-0x7FFFFFFF),
133			m_max_y(-0x7FFFFFFF),
134			m_cur_scanline(0)
135		{
136			m_fake_scanline.y = 0;
137			m_fake_scanline.num_spans = 0;
138			m_fake_scanline.start_span = 0;
139			m_fake_span.x = 0;
140			m_fake_span.len = 0;
141			m_fake_span.covers_id = 0;
142		}
143
144		// Renderer Interface
145		//---------------------------------------------------------------
146		void prepare()
147		{
148			m_covers.remove_all();
149			m_scanlines.remove_all();
150			m_spans.remove_all();
151			m_min_x =  0x7FFFFFFF;
152			m_min_y =  0x7FFFFFFF;
153			m_max_x = -0x7FFFFFFF;
154			m_max_y = -0x7FFFFFFF;
155			m_cur_scanline = 0;
156		}
157
158		//---------------------------------------------------------------
159		template<class Scanline> void render(const Scanline& sl)
160		{
161			scanline_data sl_this;
162
163			int y = sl.y();
164			if(y < m_min_y) m_min_y = y;
165			if(y > m_max_y) m_max_y = y;
166
167			sl_this.y = y;
168			sl_this.num_spans = sl.num_spans();
169			sl_this.start_span = m_spans.size();
170			typename Scanline::const_iterator span_iterator = sl.begin();
171
172			unsigned num_spans = sl_this.num_spans;
173			for(;;)
174			{
175				span_data sp;
176
177				sp.x		 = span_iterator->x;
178				sp.len		 = span_iterator->len;
179				int len		 = abs(int(sp.len));
180				sp.covers_id =
181					m_covers.add_cells(span_iterator->covers,
182									   (unsigned(len)));
183				m_spans.add(sp);
184				int x1 = sp.x;
185				int x2 = sp.x + len/3 - 1;
186				if(x1 < m_min_x) m_min_x = x1;
187				if(x2 > m_max_x) m_max_x = x2;
188				if(--num_spans == 0) break;
189				++span_iterator;
190			}
191			m_scanlines.add(sl_this);
192		}
193
194
195		//---------------------------------------------------------------
196		// Iterate scanlines interface
197		int min_x() const { return m_min_x; }
198		int min_y() const { return m_min_y; }
199		int max_x() const { return m_max_x; }
200		int max_y() const { return m_max_y; }
201
202		//---------------------------------------------------------------
203		bool rewind_scanlines()
204		{
205			m_cur_scanline = 0;
206			return m_scanlines.size() > 0;
207		}
208
209
210		//---------------------------------------------------------------
211		template<class Scanline> bool sweep_scanline(Scanline& sl)
212		{
213			sl.reset_spans();
214			for(;;)
215			{
216				if(m_cur_scanline >= m_scanlines.size()) return false;
217				const scanline_data& sl_this = m_scanlines[m_cur_scanline];
218
219				unsigned num_spans = sl_this.num_spans;
220				unsigned span_idx  = sl_this.start_span;
221				do
222				{
223					const span_data& sp = m_spans[span_idx++];
224					const T* covers = covers_by_index(sp.covers_id);
225					if(sp.len < 0)
226					{
227						sl.add_span(sp.x, unsigned(-sp.len), *covers);
228					}
229					else
230					{
231						sl.add_cells(sp.x, sp.len, covers);
232					}
233				}
234				while(--num_spans);
235				++m_cur_scanline;
236				if(sl.num_spans())
237				{
238					sl.finalize(sl_this.y);
239					break;
240				}
241			}
242			return true;
243		}
244
245
246		//---------------------------------------------------------------
247		// Specialization for embedded_scanline
248		bool sweep_scanline(embedded_scanline& sl)
249		{
250			do
251			{
252				if(m_cur_scanline >= m_scanlines.size()) return false;
253				sl.init(m_cur_scanline);
254				++m_cur_scanline;
255			}
256			while(sl.num_spans() == 0);
257			return true;
258		}
259
260		//---------------------------------------------------------------
261		unsigned byte_size() const
262		{
263			unsigned i;
264			unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y
265
266			for(i = 0; i < m_scanlines.size(); ++i)
267			{
268				size += sizeof(int32) * 3; // scanline size in bytes
269
270				const scanline_data& sl_this = m_scanlines[i];
271
272				unsigned num_spans = sl_this.num_spans;
273				unsigned span_idx  = sl_this.start_span;
274				do
275				{
276					const span_data& sp = m_spans[span_idx++];
277
278					size += sizeof(int32) * 2;				  // X, span_len
279					if(sp.len < 0)
280					{
281						size += sizeof(T);					  // cover
282					}
283					else
284					{
285						size += sizeof(T) * unsigned(sp.len); // covers
286					}
287				}
288				while(--num_spans);
289			}
290			return size;
291		}
292
293
294		//---------------------------------------------------------------
295		static void write_int32(int8u* dst, int32 val)
296		{
297			dst[0] = ((const int8u*)&val)[0];
298			dst[1] = ((const int8u*)&val)[1];
299			dst[2] = ((const int8u*)&val)[2];
300			dst[3] = ((const int8u*)&val)[3];
301		}
302
303
304		//---------------------------------------------------------------
305		void serialize(int8u* data) const
306		{
307			unsigned i;
308
309			write_int32(data, min_x()); // min_x
310			data += sizeof(int32);
311			write_int32(data, min_y()); // min_y
312			data += sizeof(int32);
313			write_int32(data, max_x()); // max_x
314			data += sizeof(int32);
315			write_int32(data, max_y()); // max_y
316			data += sizeof(int32);
317
318			for(i = 0; i < m_scanlines.size(); ++i)
319			{
320				const scanline_data& sl_this = m_scanlines[i];
321
322				int8u* size_ptr = data;
323				data += sizeof(int32);	// Reserve space for scanline size in bytes
324
325				write_int32(data, sl_this.y);			 // Y
326				data += sizeof(int32);
327
328				write_int32(data, sl_this.num_spans);	 // num_spans
329				data += sizeof(int32);
330
331				unsigned num_spans = sl_this.num_spans;
332				unsigned span_idx  = sl_this.start_span;
333				do
334				{
335					const span_data& sp = m_spans[span_idx++];
336					const T* covers = covers_by_index(sp.covers_id);
337
338					write_int32(data, sp.x);			// X
339					data += sizeof(int32);
340
341					write_int32(data, sp.len);			// span_len
342					data += sizeof(int32);
343
344					if(sp.len < 0)
345					{
346						memcpy(data, covers, sizeof(T));
347						data += sizeof(T);
348					}
349					else
350					{
351						memcpy(data, covers, unsigned(sp.len) * sizeof(T));
352						data += sizeof(T) * unsigned(sp.len);
353					}
354				}
355				while(--num_spans);
356				write_int32(size_ptr, int32(unsigned(data - size_ptr)));
357			}
358		}
359
360
361		//---------------------------------------------------------------
362		const scanline_data& scanline_by_index(unsigned i) const
363		{
364			return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
365		}
366
367		//---------------------------------------------------------------
368		const span_data& span_by_index(unsigned i) const
369		{
370			return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
371		}
372
373		//---------------------------------------------------------------
374		const T* covers_by_index(int i) const
375		{
376			return m_covers[i];
377		}
378
379	private:
380		scanline_cell_storage<T>	  m_covers;
381		pod_bvector<span_data, 10>	  m_spans;
382		pod_bvector<scanline_data, 8> m_scanlines;
383		span_data	  m_fake_span;
384		scanline_data m_fake_scanline;
385		int			  m_min_x;
386		int			  m_min_y;
387		int			  m_max_x;
388		int			  m_max_y;
389		unsigned	  m_cur_scanline;
390	};
391
392
393	typedef scanline_storage_subpix<int8u>	scanline_storage_subpix8;  //--------scanline_storage_subpix8
394	typedef scanline_storage_subpix<int16u> scanline_storage_subpix16; //--------scanline_storage_subpix16
395	typedef scanline_storage_subpix<int32u> scanline_storage_subpix32; //--------scanline_storage_subpix32
396
397
398	//--------------------------------------serialized_scanlines_adaptor_subpix
399	template<class T> class serialized_scanlines_adaptor_subpix
400	{
401	public:
402		typedef T cover_type;
403
404		//---------------------------------------------------------------------
405		class embedded_scanline
406		{
407		public:
408			typedef T cover_type;
409
410			//-----------------------------------------------------------------
411			class const_iterator
412			{
413			public:
414				struct span
415				{
416					int32	 x;
417					int32	 len; // If negative, it's a solid span, "covers" is valid
418					const T* covers;
419				};
420
421				const_iterator() : m_ptr(0) {}
422				const_iterator(const embedded_scanline& sl) :
423					m_ptr(sl.m_ptr),
424					m_dx(sl.m_dx)
425				{
426					init_span();
427				}
428
429				const span& operator*()	 const { return m_span;	 }
430				const span* operator->() const { return &m_span; }
431
432				void operator ++ ()
433				{
434					if(m_span.len < 0)
435					{
436						m_ptr += sizeof(T);
437					}
438					else
439					{
440						m_ptr += m_span.len * sizeof(T);
441					}
442					init_span();
443				}
444
445			private:
446				int read_int32()
447				{
448					int32 val;
449					((int8u*)&val)[0] = *m_ptr++;
450					((int8u*)&val)[1] = *m_ptr++;
451					((int8u*)&val)[2] = *m_ptr++;
452					((int8u*)&val)[3] = *m_ptr++;
453					return val;
454				}
455
456				void init_span()
457				{
458					m_span.x	  = read_int32() + m_dx;
459					m_span.len	  = read_int32();
460					m_span.covers = m_ptr;
461				}
462
463				const int8u* m_ptr;
464				span		 m_span;
465				int			 m_dx;
466			};
467
468			friend class const_iterator;
469
470
471			//-----------------------------------------------------------------
472			embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
473
474			//-----------------------------------------------------------------
475			void	 reset(int, int)	 {}
476			unsigned num_spans()   const { return m_num_spans;	}
477			int		 y()		   const { return m_y;			}
478			const_iterator begin() const { return const_iterator(*this); }
479
480
481		private:
482			//-----------------------------------------------------------------
483			int read_int32()
484			{
485				int32 val;
486				((int8u*)&val)[0] = *m_ptr++;
487				((int8u*)&val)[1] = *m_ptr++;
488				((int8u*)&val)[2] = *m_ptr++;
489				((int8u*)&val)[3] = *m_ptr++;
490				return val;
491			}
492
493		public:
494			//-----------------------------------------------------------------
495			void init(const int8u* ptr, int dx, int dy)
496			{
497				m_ptr		= ptr;
498				m_y			= read_int32() + dy;
499				m_num_spans = unsigned(read_int32());
500				m_dx		= dx;
501			}
502
503		private:
504			const int8u* m_ptr;
505			int			 m_y;
506			unsigned	 m_num_spans;
507			int			 m_dx;
508		};
509
510
511
512	public:
513		//--------------------------------------------------------------------
514		serialized_scanlines_adaptor_subpix() :
515			m_data(0),
516			m_end(0),
517			m_ptr(0),
518			m_dx(0),
519			m_dy(0),
520			m_min_x(0x7FFFFFFF),
521			m_min_y(0x7FFFFFFF),
522			m_max_x(-0x7FFFFFFF),
523			m_max_y(-0x7FFFFFFF)
524		{}
525
526		//--------------------------------------------------------------------
527		serialized_scanlines_adaptor_subpix(const int8u* data, unsigned size,
528										double dx, double dy) :
529			m_data(data),
530			m_end(data + size),
531			m_ptr(data),
532			m_dx(iround(dx)),
533			m_dy(iround(dy)),
534			m_min_x(0x7FFFFFFF),
535			m_min_y(0x7FFFFFFF),
536			m_max_x(-0x7FFFFFFF),
537			m_max_y(-0x7FFFFFFF)
538		{}
539
540		//--------------------------------------------------------------------
541		void init(const int8u* data, unsigned size, double dx, double dy)
542		{
543			m_data	= data;
544			m_end	= data + size;
545			m_ptr	= data;
546			m_dx	= iround(dx);
547			m_dy	= iround(dy);
548			m_min_x = 0x7FFFFFFF;
549			m_min_y = 0x7FFFFFFF;
550			m_max_x = -0x7FFFFFFF;
551			m_max_y = -0x7FFFFFFF;
552		}
553
554	private:
555		//--------------------------------------------------------------------
556		int read_int32()
557		{
558			int32 val;
559			((int8u*)&val)[0] = *m_ptr++;
560			((int8u*)&val)[1] = *m_ptr++;
561			((int8u*)&val)[2] = *m_ptr++;
562			((int8u*)&val)[3] = *m_ptr++;
563			return val;
564		}
565
566		//--------------------------------------------------------------------
567		unsigned read_int32u()
568		{
569			int32u val;
570			((int8u*)&val)[0] = *m_ptr++;
571			((int8u*)&val)[1] = *m_ptr++;
572			((int8u*)&val)[2] = *m_ptr++;
573			((int8u*)&val)[3] = *m_ptr++;
574			return val;
575		}
576
577	public:
578		// Iterate scanlines interface
579		//--------------------------------------------------------------------
580		bool rewind_scanlines()
581		{
582			m_ptr = m_data;
583			if(m_ptr < m_end)
584			{
585				m_min_x = read_int32() + m_dx;
586				m_min_y = read_int32() + m_dy;
587				m_max_x = read_int32() + m_dx;
588				m_max_y = read_int32() + m_dy;
589			}
590			return m_ptr < m_end;
591		}
592
593		//--------------------------------------------------------------------
594		int min_x() const { return m_min_x; }
595		int min_y() const { return m_min_y; }
596		int max_x() const { return m_max_x; }
597		int max_y() const { return m_max_y; }
598
599		//--------------------------------------------------------------------
600		template<class Scanline> bool sweep_scanline(Scanline& sl)
601		{
602			sl.reset_spans();
603			for(;;)
604			{
605				if(m_ptr >= m_end) return false;
606
607				read_int32();	   // Skip scanline size in bytes
608				int y = read_int32() + m_dy;
609				unsigned num_spans = read_int32();
610
611				do
612				{
613					int x = read_int32() + m_dx;
614					int len = read_int32();
615
616					if(len < 0)
617					{
618						sl.add_span(x, unsigned(-len), *m_ptr);
619						m_ptr += sizeof(T);
620					}
621					else
622					{
623						sl.add_cells(x, len, m_ptr);
624						m_ptr += len * sizeof(T);
625					}
626				}
627				while(--num_spans);
628
629				if(sl.num_spans())
630				{
631					sl.finalize(y);
632					break;
633				}
634			}
635			return true;
636		}
637
638
639		//--------------------------------------------------------------------
640		// Specialization for embedded_scanline
641		bool sweep_scanline(embedded_scanline& sl)
642		{
643			do
644			{
645				if(m_ptr >= m_end) return false;
646
647				unsigned byte_size = read_int32u();
648				sl.init(m_ptr, m_dx, m_dy);
649				m_ptr += byte_size - sizeof(int32);
650			}
651			while(sl.num_spans() == 0);
652			return true;
653		}
654
655	private:
656		const int8u* m_data;
657		const int8u* m_end;
658		const int8u* m_ptr;
659		int			 m_dx;
660		int			 m_dy;
661		int			 m_min_x;
662		int			 m_min_y;
663		int			 m_max_x;
664		int			 m_max_y;
665	};
666
667
668
669	typedef serialized_scanlines_adaptor_subpix<int8u>
670	serialized_scanlines_adaptor_subpix8; //serialized_scanlines_adaptor_subpix8
671
672	typedef serialized_scanlines_adaptor_subpix<int16u>
673	serialized_scanlines_adaptor_subpix16; //serialized_scanlines_adaptor_subpix16
674
675	typedef serialized_scanlines_adaptor_subpix<int32u>
676	serialized_scanlines_adaptor_subpix32; //serialized_scanlines_adaptor_subpix32
677
678}
679
680
681#endif
682
683