xref: /haiku/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSelect.h (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
1 /*
2  * Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * DrawingMode implementing B_OP_SELECT on B_RGBA32.
6  *
7  */
8 
9 #ifndef DRAWING_MODE_SELECT_H
10 #define DRAWING_MODE_SELECT_H
11 
12 #include "DrawingMode.h"
13 
14 // BLEND_SELECT
15 #define BLEND_SELECT(d1, d2, d3, da, s1, s2, s3, a) \
16 { \
17 	BLEND(d1, d2, d3, da, s1, s2, s3, a); \
18 }
19 
20 // ASSIGN_SELECT
21 #define ASSIGN_SELECT(d1, d2, d3, da, s1, s2, s3) \
22 { \
23 	(d1) = (s1); \
24 	(d2) = (s2); \
25 	(d3) = (s3); \
26 	(da) = 255; \
27 }
28 
29 
30 template<class Order>
31 class DrawingModeSelect : public DrawingMode {
32  public:
33 	// constructor
34 	DrawingModeSelect()
35 		: DrawingMode()
36 	{
37 	}
38 
39 	// compare
40 	inline bool compare(uint8* p,
41 						const rgb_color& high,
42 						const rgb_color& low, rgb_color* result)
43 	{
44 		if (p[Order::R] == high.red &&
45 			p[Order::G] == high.green &&
46 			p[Order::B] == high.blue) {
47 			result->red = low.red;
48 			result->green = low.green;
49 			result->blue = low.blue;
50 			return true;
51 		} else if (p[Order::R] == low.red &&
52 				   p[Order::G] == low.green &&
53 				   p[Order::B] == low.blue) {
54 			result->red = high.red;
55 			result->green = high.green;
56 			result->blue = high.blue;
57 			return true;
58 		}
59 		return false;
60 	}
61 
62 
63 	// blend_pixel
64 	virtual	void blend_pixel(int x, int y, const color_type& c, uint8 cover)
65 	{
66 		if (fPatternHandler->IsHighColor(x, y)) {
67 			uint8* p = fBuffer->row(y) + (x << 2);
68 			rgb_color high = fPatternHandler->HighColor().GetColor32();
69 			rgb_color low = fPatternHandler->LowColor().GetColor32();
70 			rgb_color color;
71 			if (compare(p, high, low, &color)) {
72 				if (cover == 255) {
73 					ASSIGN_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
74 								  color.red, color.green, color.blue);
75 				} else {
76 					BLEND_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
77 								 color.red, color.green, color.blue, cover);
78 				}
79 			}
80 		}
81 	}
82 
83 	// blend_hline
84 	virtual	void blend_hline(int x, int y, unsigned len,
85 							 const color_type& c, uint8 cover)
86 	{
87 		uint8* p = fBuffer->row(y) + (x << 2);
88 		rgb_color high = fPatternHandler->HighColor().GetColor32();
89 		rgb_color low = fPatternHandler->LowColor().GetColor32();
90 		rgb_color color;
91 		if (cover == 255) {
92 			do {
93 				if (fPatternHandler->IsHighColor(x, y)
94 					&& compare(p, high, low, &color))
95 					ASSIGN_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
96 								  color.red, color.green, color.blue);
97 				x++;
98 				p += 4;
99 			} while(--len);
100 		} else {
101 			do {
102 				if (fPatternHandler->IsHighColor(x, y)
103 					&& compare(p, high, low, &color)) {
104 					BLEND_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
105 							   color.red, color.green, color.blue, cover);
106 				}
107 				x++;
108 				p += 4;
109 			} while(--len);
110 		}
111 	}
112 
113 	// blend_vline
114 	virtual	void blend_vline(int x, int y, unsigned len,
115 							 const color_type& c, uint8 cover)
116 	{
117 printf("DrawingModeSelect::blend_vline()\n");
118 	}
119 
120 	// blend_solid_hspan
121 	virtual	void blend_solid_hspan(int x, int y, unsigned len,
122 								   const color_type& c, const uint8* covers)
123 	{
124 		uint8* p = fBuffer->row(y) + (x << 2);
125 		rgb_color high = fPatternHandler->HighColor().GetColor32();
126 		rgb_color low = fPatternHandler->LowColor().GetColor32();
127 		rgb_color color;
128 		do {
129 			if (fPatternHandler->IsHighColor(x, y)) {
130 				if (*covers && compare(p, high, low, &color)) {
131 					if (*covers == 255) {
132 						ASSIGN_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
133 									  color.red, color.green, color.blue);
134 					} else {
135 						BLEND_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
136 									 color.red, color.green, color.blue, *covers);
137 					}
138 				}
139 			}
140 			covers++;
141 			p += 4;
142 			x++;
143 		} while(--len);
144 	}
145 
146 
147 
148 	// blend_solid_vspan
149 	virtual	void blend_solid_vspan(int x, int y, unsigned len,
150 								   const color_type& c, const uint8* covers)
151 	{
152 		uint8* p = fBuffer->row(y) + (x << 2);
153 		rgb_color high = fPatternHandler->HighColor().GetColor32();
154 		rgb_color low = fPatternHandler->LowColor().GetColor32();
155 		rgb_color color;
156 		do {
157 			if (fPatternHandler->IsHighColor(x, y)) {
158 				if (*covers && compare(p, high, low, &color)) {
159 					if (*covers == 255) {
160 						ASSIGN_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
161 									  color.red, color.green, color.blue);
162 					} else {
163 						BLEND_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
164 									 color.red, color.green, color.blue, *covers);
165 					}
166 				}
167 			}
168 			covers++;
169 			p += fBuffer->stride();
170 			y++;
171 		} while(--len);
172 	}
173 
174 
175 	// blend_color_hspan
176 	virtual	void blend_color_hspan(int x, int y, unsigned len,
177 								   const color_type* colors,
178 								   const uint8* covers,
179 								   uint8 cover)
180 	{
181 		uint8* p = fBuffer->row(y) + (x << 2);
182 		rgb_color high = fPatternHandler->HighColor().GetColor32();
183 		rgb_color low = fPatternHandler->LowColor().GetColor32();
184 		rgb_color color;
185 		if (covers) {
186 			// non-solid opacity
187 			do {
188 				if (*covers && compare(p, high, low, &color)) {
189 					if (*covers == 255) {
190 						ASSIGN_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
191 									  color.red, color.green, color.blue);
192 					} else {
193 						BLEND_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
194 									 color.red, color.green, color.blue, *covers);
195 					}
196 				}
197 				covers++;
198 				p += 4;
199 				++colors;
200 			} while(--len);
201 		} else {
202 			// solid full opcacity
203 			if (cover == 255) {
204 				do {
205 					if (compare(p, high, low, &color)) {
206 						ASSIGN_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
207 									  color.red, color.green, color.blue);
208 					}
209 					p += 4;
210 					++colors;
211 				} while(--len);
212 			// solid partial opacity
213 			} else if (cover) {
214 				do {
215 					if (compare(p, high, low, &color)) {
216 						BLEND_SELECT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
217 									 color.red, color.green, color.blue, *covers);
218 					}
219 					p += 4;
220 					++colors;
221 				} while(--len);
222 			}
223 		}
224 	}
225 
226 
227 	// blend_color_vspan
228 	virtual	void blend_color_vspan(int x, int y, unsigned len,
229 								   const color_type* colors,
230 								   const uint8* covers,
231 								   uint8 cover)
232 	{
233 printf("DrawingModeSelect::blend_color_vspan()\n");
234 	}
235 
236 };
237 
238 typedef DrawingModeSelect<agg::order_rgba32> DrawingModeRGBA32Select;
239 typedef DrawingModeSelect<agg::order_argb32> DrawingModeARGB32Select;
240 typedef DrawingModeSelect<agg::order_abgr32> DrawingModeABGR32Select;
241 typedef DrawingModeSelect<agg::order_bgra32> DrawingModeBGRA32Select;
242 
243 #endif // DRAWING_MODE_SELECT_H
244 
245