xref: /haiku/src/servers/app/drawing/Painter/agg_scanline_storage_subpix.h (revision 71452e98334eaac603bf542d159e24788a46bebb)
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 
23 namespace 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