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