xref: /haiku/src/servers/app/drawing/Painter/agg_clipped_alpha_mask.h (revision f4f05935dbe4fa5c5b1fda880e23d81a18b11da2)
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, int x, int y, int8u outside)
38 			{
39 				m_rbuf = &rbuf;
40 				m_xOffset = x;
41 				m_yOffset = y;
42 				m_outside = outside;
43 			}
44 
45 			void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
46 			{
47 				int count = num_pix;
48 				cover_type* covers = dst;
49 
50 				bool has_inside = _set_outside(x, y, covers, count);
51 				if (!has_inside)
52 					return;
53 
54 				const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
55 				do
56 				{
57 					*covers = (cover_type)((cover_full + (*covers) * (*mask))
58 						>> cover_shift);
59 					++covers;
60 					mask += Step;
61 				}
62 				while(--count);
63 			}
64 
65 			void get_hspan(int x, int y, cover_type* dst, int num_pix) const
66 			{
67 				int count = num_pix;
68 				cover_type* covers = dst;
69 
70 				bool has_inside = _set_outside(x, y, covers, count);
71 				if (!has_inside)
72 					return;
73 
74 				const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
75 				memcpy(covers, mask, count);
76 			}
77 
78 		private:
79 			bool _set_outside(int& x, int& y, cover_type*& covers,
80 				int& count) const
81 			{
82 				x -= m_xOffset;
83 				y -= m_yOffset;
84 
85 				int xmax = m_rbuf->width() - 1;
86 				int ymax = m_rbuf->height() - 1;
87 
88 				int num_pix = count;
89 				cover_type* dst = covers;
90 
91 				if(y < 0 || y > ymax)
92 				{
93 					memset(dst, m_outside, num_pix * sizeof(cover_type));
94 					return false;
95 				}
96 
97 				if(x < 0)
98 				{
99 					count += x;
100 					if(count <= 0)
101 					{
102 						memset(dst, m_outside, num_pix * sizeof(cover_type));
103 						return false;
104 					}
105 					memset(covers, m_outside, -x * sizeof(cover_type));
106 					covers -= x;
107 					x = 0;
108 				}
109 
110 				if(x + count > xmax)
111 				{
112 					int rest = x + count - xmax - 1;
113 					count -= rest;
114 					if(count <= 0)
115 					{
116 						memset(dst, m_outside, num_pix * sizeof(cover_type));
117 						return false;
118 					}
119 					memset(covers + count, m_outside, rest * sizeof(cover_type));
120 				}
121 
122 				return true;
123 			}
124 
125 
126 		private:
127 			int m_xOffset;
128 			int m_yOffset;
129 
130 			rendering_buffer* m_rbuf;
131 			int8u m_outside;
132 
133 			static const int Step = 1;
134 			static const int Offset = 0;
135 	};
136 }
137 
138 
139 #endif
140