xref: /haiku/src/servers/app/drawing/Painter/agg_clipped_alpha_mask.h (revision e532264bcbd58884ae3686004eeeaeab53ebf2f8)
1 /*
2  * Copyright 2014, Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
6  *
7  * Class clipped_alpha_mask, a modified version of alpha_mask_u8 that can
8  * offset the mask, and has a controllable value for the area outside it.
9  */
10 
11 #ifndef AGG_CLIPED_ALPHA_MASK_INCLUDED
12 #define AGG_CLIPED_ALPHA_MASK_INCLUDED
13 
14 
15 #include <agg_alpha_mask_u8.h>
16 #include <agg_rendering_buffer.h>
17 
18 
19 namespace agg
20 {
21 	class clipped_alpha_mask
22 	{
23 		public:
24 			typedef int8u cover_type;
25 			enum cover_scale_e
26 			{
27 				cover_shift = 8,
28 				cover_none  = 0,
29 				cover_full  = 255
30 			};
31 
32 			clipped_alpha_mask()
33 				: m_xOffset(0), m_yOffset(0), m_rbuf(0), m_outside(0) {}
34 			clipped_alpha_mask(rendering_buffer& rbuf)
35 				: m_xOffset(0), m_yOffset(0), m_rbuf(&rbuf), m_outside(0) {}
36 
37 			void attach(rendering_buffer& rbuf)
38 			{
39 				m_rbuf = &rbuf;
40 			}
41 
42 			void attach(rendering_buffer& rbuf, int x, int y, int8u outside)
43 			{
44 				m_rbuf = &rbuf;
45 				m_xOffset = x;
46 				m_yOffset = y;
47 				m_outside = outside;
48 			}
49 
50 			void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
51 			{
52 				int count = num_pix;
53 				cover_type* covers = dst;
54 
55 				bool has_inside = _set_outside(x, y, covers, count);
56 				if (!has_inside)
57 					return;
58 
59 				const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
60 				do
61 				{
62 					*covers = (cover_type)((cover_full + (*covers) * (*mask))
63 						>> cover_shift);
64 					++covers;
65 					mask += Step;
66 				}
67 				while(--count);
68 			}
69 
70 			void get_hspan(int x, int y, cover_type* dst, int num_pix) const
71 			{
72 				int count = num_pix;
73 				cover_type* covers = dst;
74 
75 				bool has_inside = _set_outside(x, y, covers, count);
76 				if (!has_inside)
77 					return;
78 
79 				const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
80 				memcpy(covers, mask, count);
81 			}
82 
83 		private:
84 			bool _set_outside(int& x, int& y, cover_type*& covers,
85 				int& count) const
86 			{
87 				x -= m_xOffset;
88 				y -= m_yOffset;
89 
90 				int xmax = m_rbuf->width() - 1;
91 				int ymax = m_rbuf->height() - 1;
92 
93 				int num_pix = count;
94 				cover_type* dst = covers;
95 
96 				if(y < 0 || y > ymax)
97 				{
98 					memset(dst, m_outside, num_pix * sizeof(cover_type));
99 					return false;
100 				}
101 
102 				if(x < 0)
103 				{
104 					count += x;
105 					if(count <= 0)
106 					{
107 						memset(dst, m_outside, num_pix * sizeof(cover_type));
108 						return false;
109 					}
110 					memset(covers, m_outside, -x * sizeof(cover_type));
111 					covers -= x;
112 					x = 0;
113 				}
114 
115 				if(x + count > xmax)
116 				{
117 					int rest = x + count - xmax - 1;
118 					count -= rest;
119 					if(count <= 0)
120 					{
121 						memset(dst, m_outside, num_pix * sizeof(cover_type));
122 						return false;
123 					}
124 					memset(covers + count, m_outside, rest * sizeof(cover_type));
125 				}
126 
127 				return true;
128 			}
129 
130 
131 		private:
132 			int m_xOffset;
133 			int m_yOffset;
134 
135 			rendering_buffer* m_rbuf;
136 			int8u m_outside;
137 
138 			static const int Step = 1;
139 			static const int Offset = 0;
140 	};
141 }
142 
143 
144 #endif
145