xref: /haiku/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSelect.h (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
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(d, r, g, b, a) \
16 { \
17 	BLEND(d, r, g, b, a); \
18 }
19 
20 // ASSIGN_SELECT
21 #define ASSIGN_SELECT(d, r, g, b) \
22 { \
23 	d[0] = (b); \
24 	d[1] = (g); \
25 	d[2] = (r); \
26 	d[3] = 255; \
27 }
28 
29 // compare
30 inline bool
31 compare(uint8* p, const rgb_color& high, const rgb_color& low, rgb_color* result)
32 {
33 	pixel32 _p;
34 	_p.data32 = *(uint32*)p;
35 	if (_p.data8[2] == high.red &&
36 		_p.data8[1] == high.green &&
37 		_p.data8[0] == high.blue) {
38 		result->red = low.red;
39 		result->green = low.green;
40 		result->blue = low.blue;
41 		return true;
42 	} else if (_p.data8[2] == low.red &&
43 			   _p.data8[1] == low.green &&
44 			   _p.data8[0] == low.blue) {
45 		result->red = high.red;
46 		result->green = high.green;
47 		result->blue = high.blue;
48 		return true;
49 	}
50 	return false;
51 }
52 
53 // blend_pixel_select
54 void
55 blend_pixel_select(int x, int y, const color_type& c, uint8 cover,
56 				   agg_buffer* buffer, const PatternHandler* pattern)
57 {
58 	if (pattern->IsHighColor(x, y)) {
59 		uint8* p = buffer->row_ptr(y) + (x << 2);
60 		rgb_color high = pattern->HighColor().GetColor32();
61 		rgb_color low = pattern->LowColor().GetColor32();
62 		rgb_color color;
63 		if (compare(p, high, low, &color)) {
64 			if (cover == 255) {
65 				ASSIGN_SELECT(p, color.red, color.green, color.blue);
66 			} else {
67 				BLEND_SELECT(p, color.red, color.green, color.blue, cover);
68 			}
69 		}
70 	}
71 }
72 
73 // blend_hline_select
74 void
75 blend_hline_select(int x, int y, unsigned len,
76 				   const color_type& c, uint8 cover,
77 				   agg_buffer* buffer, const PatternHandler* pattern)
78 {
79 	uint8* p = buffer->row_ptr(y) + (x << 2);
80 	rgb_color high = pattern->HighColor().GetColor32();
81 	rgb_color low = pattern->LowColor().GetColor32();
82 	rgb_color color;
83 	if (cover == 255) {
84 		do {
85 			if (pattern->IsHighColor(x, y)
86 				&& compare(p, high, low, &color))
87 				ASSIGN_SELECT(p, color.red, color.green, color.blue);
88 			x++;
89 			p += 4;
90 		} while(--len);
91 	} else {
92 		do {
93 			if (pattern->IsHighColor(x, y)
94 				&& compare(p, high, low, &color)) {
95 				BLEND_SELECT(p, color.red, color.green, color.blue, cover);
96 			}
97 			x++;
98 			p += 4;
99 		} while(--len);
100 	}
101 }
102 
103 // blend_solid_hspan_select
104 void
105 blend_solid_hspan_select(int x, int y, unsigned len,
106 						 const color_type& c, const uint8* covers,
107 						 agg_buffer* buffer, const PatternHandler* pattern)
108 {
109 	uint8* p = buffer->row_ptr(y) + (x << 2);
110 	rgb_color high = pattern->HighColor().GetColor32();
111 	rgb_color low = pattern->LowColor().GetColor32();
112 	rgb_color color;
113 	do {
114 		if (pattern->IsHighColor(x, y)) {
115 			if (*covers && compare(p, high, low, &color)) {
116 				if (*covers == 255) {
117 					ASSIGN_SELECT(p, color.red, color.green, color.blue);
118 				} else {
119 					BLEND_SELECT(p, color.red, color.green, color.blue, *covers);
120 				}
121 			}
122 		}
123 		covers++;
124 		p += 4;
125 		x++;
126 	} while(--len);
127 }
128 
129 
130 
131 // blend_solid_vspan_select
132 void
133 blend_solid_vspan_select(int x, int y, unsigned len,
134 						 const color_type& c, const uint8* covers,
135 						 agg_buffer* buffer, const PatternHandler* pattern)
136 {
137 	uint8* p = buffer->row_ptr(y) + (x << 2);
138 	rgb_color high = pattern->HighColor().GetColor32();
139 	rgb_color low = pattern->LowColor().GetColor32();
140 	rgb_color color;
141 	do {
142 		if (pattern->IsHighColor(x, y)) {
143 			if (*covers && compare(p, high, low, &color)) {
144 				if (*covers == 255) {
145 					ASSIGN_SELECT(p, color.red, color.green, color.blue);
146 				} else {
147 					BLEND_SELECT(p, color.red, color.green, color.blue, *covers);
148 				}
149 			}
150 		}
151 		covers++;
152 		p += buffer->stride();
153 		y++;
154 	} while(--len);
155 }
156 
157 
158 // blend_color_hspan_select
159 void
160 blend_color_hspan_select(int x, int y, unsigned len,
161 						 const color_type* colors,
162 						 const uint8* covers, uint8 cover,
163 						 agg_buffer* buffer, const PatternHandler* pattern)
164 {
165 	uint8* p = buffer->row_ptr(y) + (x << 2);
166 	rgb_color high = pattern->HighColor().GetColor32();
167 	rgb_color low = pattern->LowColor().GetColor32();
168 	rgb_color color;
169 	if (covers) {
170 		// non-solid opacity
171 		do {
172 			if (*covers && compare(p, high, low, &color)) {
173 				if (*covers == 255) {
174 					ASSIGN_SELECT(p, color.red, color.green, color.blue);
175 				} else {
176 					BLEND_SELECT(p, color.red, color.green, color.blue, *covers);
177 				}
178 			}
179 			covers++;
180 			p += 4;
181 			++colors;
182 		} while(--len);
183 	} else {
184 		// solid full opcacity
185 		if (cover == 255) {
186 			do {
187 				if (compare(p, high, low, &color)) {
188 					ASSIGN_SELECT(p, color.red, color.green, color.blue);
189 				}
190 				p += 4;
191 				++colors;
192 			} while(--len);
193 		// solid partial opacity
194 		} else if (cover) {
195 			do {
196 				if (compare(p, high, low, &color)) {
197 					BLEND_SELECT(p, color.red, color.green, color.blue, *covers);
198 				}
199 				p += 4;
200 				++colors;
201 			} while(--len);
202 		}
203 	}
204 }
205 
206 #endif // DRAWING_MODE_SELECT_H
207 
208