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