xref: /haiku/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSubtract.h (revision 74994d1307d9898fcc7c52ac176911895d837901)
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_SUBTRACT on B_RGBA32.
6  *
7  */
8 
9 #ifndef DRAWING_MODE_SUBTRACT_H
10 #define DRAWING_MODE_SUBTRACT_H
11 
12 #include <SupportDefs.h>
13 
14 #include "DrawingMode.h"
15 #include "PatternHandler.h"
16 
17 // BLEND_SUBTRACT
18 #define BLEND_SUBTRACT(d1, d2, d3, da, s1, s2, s3, a) \
19 { \
20 	uint8 t1 = max_c(0, (d1) - (s1)); \
21 	uint8 t2 = max_c(0, (d2) - (s2)); \
22 	uint8 t3 = max_c(0, (d3) - (s3)); \
23 	BLEND(d1, d2, d3, da, t1, t2, t3, a); \
24 }
25 
26 // ASSIGN_SUBTRACT
27 #define ASSIGN_SUBTRACT(d1, d2, d3, da, s1, s2, s3) \
28 { \
29 	(d1) = max_c(0, (d1) - (s1)); \
30 	(d2) = max_c(0, (d2) - (s2)); \
31 	(d3) = max_c(0, (d3) - (s3)); \
32 	(da) = 255; \
33 }
34 
35 
36 template<class Order>
37 class DrawingModeSubtract : public DrawingMode {
38  public:
39 	// constructor
40 	DrawingModeSubtract()
41 		: DrawingMode()
42 	{
43 	}
44 
45 	// blend_pixel
46 	virtual	void blend_pixel(int x, int y, const color_type& c, uint8 cover)
47 	{
48 		uint8* p = fBuffer->row(y) + (x << 2);
49 		rgb_color color = fPatternHandler->R5ColorAt(x, y);
50 		if (cover == 255) {
51 			ASSIGN_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
52 							color.red, color.green, color.blue);
53 		} else {
54 			BLEND_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
55 						   color.red, color.green, color.blue, cover);
56 		}
57 	}
58 
59 	// blend_hline
60 	virtual	void blend_hline(int x, int y, unsigned len,
61 							 const color_type& c, uint8 cover)
62 	{
63 		uint8* p = fBuffer->row(y) + (x << 2);
64 		if (cover == 255) {
65 			do {
66 				rgb_color color = fPatternHandler->R5ColorAt(x, y);
67 
68 				ASSIGN_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
69 								color.red, color.green, color.blue);
70 
71 				p += 4;
72 				x++;
73 			} while(--len);
74 		} else {
75 			do {
76 				rgb_color color = fPatternHandler->R5ColorAt(x, y);
77 
78 				BLEND_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
79 							   color.red, color.green, color.blue, cover);
80 
81 				x++;
82 				p += 4;
83 			}
84 			while(--len);
85 		}
86 	}
87 
88 	// blend_vline
89 	virtual	void blend_vline(int x, int y, unsigned len,
90 							 const color_type& c, uint8 cover)
91 	{
92 printf("DrawingModeSubtract::blend_vline()\n");
93 	}
94 
95 	// blend_solid_hspan
96 	virtual	void blend_solid_hspan(int x, int y, unsigned len,
97 								   const color_type& c, const uint8* covers)
98 	{
99 		uint8* p = fBuffer->row(y) + (x << 2);
100 		do {
101 			rgb_color color = fPatternHandler->R5ColorAt(x, y);
102 			if (*covers) {
103 				if (*covers == 255) {
104 					ASSIGN_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
105 									color.red, color.green, color.blue);
106 				} else {
107 					BLEND_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
108 								   color.red, color.green, color.blue, *covers);
109 				}
110 			}
111 			covers++;
112 			p += 4;
113 			x++;
114 		} while(--len);
115 	}
116 
117 
118 
119 	// blend_solid_vspan
120 	virtual	void blend_solid_vspan(int x, int y, unsigned len,
121 								   const color_type& c, const uint8* covers)
122 	{
123 		uint8* p = fBuffer->row(y) + (x << 2);
124 		do {
125 			rgb_color color = fPatternHandler->R5ColorAt(x, y);
126 			if (*covers) {
127 				if (*covers == 255) {
128 					ASSIGN_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
129 									color.red, color.green, color.blue);
130 				} else {
131 					BLEND_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
132 								   color.red, color.green, color.blue, *covers);
133 				}
134 			}
135 			covers++;
136 			p += fBuffer->stride();
137 			y++;
138 		} while(--len);
139 	}
140 
141 
142 	// blend_color_hspan
143 	virtual	void blend_color_hspan(int x, int y, unsigned len,
144 								   const color_type* colors,
145 								   const uint8* covers,
146 								   uint8 cover)
147 	{
148 		uint8* p = fBuffer->row(y) + (x << 2);
149 		if (covers) {
150 			// non-solid opacity
151 			do {
152 				if (*covers) {
153 					if (*covers == 255) {
154 						ASSIGN_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
155 										colors->r, colors->g, colors->b);
156 					} else {
157 						BLEND_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
158 									   colors->r, colors->g, colors->b, *covers);
159 					}
160 				}
161 				covers++;
162 				p += 4;
163 				++colors;
164 			} while(--len);
165 		} else {
166 			// solid full opcacity
167 			if (cover == 255) {
168 				do {
169 					ASSIGN_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
170 									colors->r, colors->g, colors->b);
171 					p += 4;
172 					++colors;
173 				} while(--len);
174 			// solid partial opacity
175 			} else if (cover) {
176 				do {
177 					BLEND_SUBTRACT(p[Order::R], p[Order::G], p[Order::B], p[Order::A],
178 								   colors->r, colors->g, colors->b, cover);
179 					p += 4;
180 					++colors;
181 				} while(--len);
182 			}
183 		}
184 	}
185 
186 
187 	// blend_color_vspan
188 	virtual	void blend_color_vspan(int x, int y, unsigned len,
189 								   const color_type* colors,
190 								   const uint8* covers,
191 								   uint8 cover)
192 	{
193 printf("DrawingModeSubtract::blend_color_vspan()\n");
194 	}
195 
196 };
197 
198 typedef DrawingModeSubtract<agg::order_rgba32> DrawingModeRGBA32Subtract;
199 typedef DrawingModeSubtract<agg::order_argb32> DrawingModeARGB32Subtract;
200 typedef DrawingModeSubtract<agg::order_abgr32> DrawingModeABGR32Subtract;
201 typedef DrawingModeSubtract<agg::order_bgra32> DrawingModeBGRA32Subtract;
202 
203 #endif // DRAWING_MODE_SUBTRACT_H
204 
205