xref: /haiku/src/servers/app/drawing/Painter/drawing_modes/DrawingMode.h (revision 60d98a49ed6eb66b24e4d2e562db8e031b447475)
1 /*
2  * Copyright 2005, Stephan Aßmus <superstippi@gmx.de>.
3  * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
4  * All rights reserved. Distributed under the terms of the MIT License.
5  *
6  * Base class for different drawing modes.
7  *
8  */
9 
10 #ifndef DRAWING_MODE_H
11 #define DRAWING_MODE_H
12 
13 #include "drawing_support.h"
14 
15 #include "PatternHandler.h"
16 #include "PixelFormat.h"
17 
18 class PatternHandler;
19 
20 typedef PixelFormat::color_type		color_type;
21 typedef PixelFormat::agg_buffer		agg_buffer;
22 
23 // BLEND
24 //
25 // This macro assumes source alpha in range 0..255 and
26 // ignores dest alpha (is assumed to equal 255).
27 // TODO: We need the assignment of alpha only when drawing into bitmaps!
28 #define BLEND(d, r, g, b, a) \
29 { \
30 	pixel32 _p; \
31 	_p.data32 = *(uint32*)d; \
32 	d[0] = (((((b) - _p.data8[0]) * (a)) + (_p.data8[0] << 8)) >> 8); \
33 	d[1] = (((((g) - _p.data8[1]) * (a)) + (_p.data8[1] << 8)) >> 8); \
34 	d[2] = (((((r) - _p.data8[2]) * (a)) + (_p.data8[2] << 8)) >> 8); \
35 	d[3] = 255; \
36 }
37 
38 #define BLEND_SUBPIX(d, r, g, b, a1, a2, a3) \
39 { \
40 	pixel32 _p; \
41 	_p.data32 = *(uint32*)d; \
42 	d[0] = (((((b) - _p.data8[0]) * (a1)) + (_p.data8[0] << 8)) >> 8); \
43 	d[1] = (((((g) - _p.data8[1]) * (a2)) + (_p.data8[1] << 8)) >> 8); \
44 	d[2] = (((((r) - _p.data8[2]) * (a3)) + (_p.data8[2] << 8)) >> 8); \
45 	d[3] = 255; \
46 }
47 
48 // BLEND_FROM
49 //
50 // This macro assumes source alpha in range 0..255 and
51 // ignores dest alpha (is assumed to equal 255).
52 // It uses two colors for the blending (f and s) and writes
53 // the result into a third color (d).
54 // TODO: We need the assignment of alpha only when drawing into bitmaps!
55 #define BLEND_FROM(d, r1, g1, b1, r2, g2, b2, a) \
56 { \
57 	d[0] = (((((b2) - (b1)) * (a)) + ((b1) << 8)) >> 8); \
58 	d[1] = (((((g2) - (g1)) * (a)) + ((g1) << 8)) >> 8); \
59 	d[2] = (((((r2) - (r1)) * (a)) + ((r1) << 8)) >> 8); \
60 	d[3] = 255; \
61 }
62 
63 #define BLEND_FROM_SUBPIX(d, r1, g1, b1, r2, g2, b2, a1, a2, a3) \
64 { \
65 	d[0] = (((((b2) - (b1)) * (a1)) + ((b1) << 8)) >> 8); \
66 	d[1] = (((((g2) - (g1)) * (a2)) + ((g1) << 8)) >> 8); \
67 	d[2] = (((((r2) - (r1)) * (a3)) + ((r1) << 8)) >> 8); \
68 	d[3] = 255; \
69 }
70 
71 // BLEND16
72 //
73 // This macro assumes source alpha in range 0..65025 and
74 // ignores dest alpha (is assumed to equal 255).
75 // TODO: We need the assignment of alpha only when drawing into bitmaps!
76 // BLEND16
77 #define BLEND16(d, r, g, b, a) \
78 { \
79 	pixel32 _p; \
80 	_p.data32 = *(uint32*)d; \
81 	d[0] = (((((b) - _p.data8[0]) * (a)) + (_p.data8[0] << 16)) >> 16); \
82 	d[1] = (((((g) - _p.data8[1]) * (a)) + (_p.data8[1] << 16)) >> 16); \
83 	d[2] = (((((r) - _p.data8[2]) * (a)) + (_p.data8[2] << 16)) >> 16); \
84 	d[3] = 255; \
85 }
86 
87 // BLEND16_SUBPIX
88 #define BLEND16_SUBPIX(d, r, g, b, a1, a2, a3) \
89 { \
90 	pixel32 _p; \
91 	_p.data32 = *(uint32*)d; \
92 	d[0] = (((((b) - _p.data8[0]) * (a1)) + (_p.data8[0] << 16)) >> 16); \
93 	d[1] = (((((g) - _p.data8[1]) * (a2)) + (_p.data8[1] << 16)) >> 16); \
94 	d[2] = (((((r) - _p.data8[2]) * (a3)) + (_p.data8[2] << 16)) >> 16); \
95 	d[3] = 255; \
96 }
97 
98 // BLEND_COMPOSITE
99 //
100 // This macro assumes source alpha in range 0..255 and
101 // composes the source color over a possibly semi-transparent background.
102 #define BLEND_COMPOSITE(d, r, g, b, a) \
103 { \
104 	pixel32 _p; \
105 	_p.data32 = *(uint32*)d; \
106 	if (_p.data8[3] == 255) { \
107 		d[0] = (((((b) - _p.data8[0]) * (a)) + (_p.data8[0] << 8)) >> 8); \
108 		d[1] = (((((g) - _p.data8[1]) * (a)) + (_p.data8[1] << 8)) >> 8); \
109 		d[2] = (((((r) - _p.data8[2]) * (a)) + (_p.data8[2] << 8)) >> 8); \
110 		d[3] = 255; \
111 	} else { \
112 		if (_p.data8[3] == 0) { \
113 			d[0] = (b); \
114 			d[1] = (g); \
115 			d[2] = (r); \
116 			d[3] = (a); \
117 		} else { \
118 			uint8 alphaRest = 255 - (a); \
119 			uint32 alphaTemp = (65025 - alphaRest * (255 - _p.data8[3])); \
120 			uint32 alphaDest = _p.data8[3] * alphaRest; \
121 			uint32 alphaSrc = 255 * (a); \
122 			d[0] = (_p.data8[0] * alphaDest + (b) * alphaSrc) / alphaTemp; \
123 			d[1] = (_p.data8[1] * alphaDest + (g) * alphaSrc) / alphaTemp; \
124 			d[2] = (_p.data8[2] * alphaDest + (r) * alphaSrc) / alphaTemp; \
125 			d[3] = alphaTemp / 255; \
126 		} \
127 	} \
128 }
129 
130 // BLEND_COMPOSITE_SUBPIX
131 #define BLEND_COMPOSITE_SUBPIX(d, r, g, b, a1, a2, a3) \
132 { \
133 	pixel32 _p; \
134 	_p.data32 = *(uint32*)d; \
135 	if (_p.data8[3] == 255) { \
136 		d[0] = (((((b) - _p.data8[0]) * (a1)) + (_p.data8[0] << 8)) >> 8); \
137 		d[1] = (((((g) - _p.data8[1]) * (a2)) + (_p.data8[1] << 8)) >> 8); \
138 		d[2] = (((((r) - _p.data8[2]) * (a3)) + (_p.data8[2] << 8)) >> 8); \
139 		d[3] = 255; \
140 	} else { \
141 		if (_p.data8[3] == 0) { \
142 			d[0] = (b); \
143 			d[1] = (g); \
144 			d[2] = (r); \
145 			d[3] = (a1 + a2 + a3)/3; \
146 		} else { \
147 			uint8 alphaRest1 = 255 - (a1); \
148 			uint8 alphaRest2 = 255 - (a2); \
149 			uint8 alphaRest3 = 255 - (a3); \
150 			uint32 alphaTemp1 = (65025 - alphaRest1 * (255 - _p.data8[3])); \
151 			uint32 alphaTemp2 = (65025 - alphaRest2 * (255 - _p.data8[3])); \
152 			uint32 alphaTemp3 = (65025 - alphaRest3 * (255 - _p.data8[3])); \
153 			uint32 alphaDest1 = _p.data8[3] * alphaRest1; \
154 			uint32 alphaDest2 = _p.data8[3] * alphaRest2; \
155 			uint32 alphaDest3 = _p.data8[3] * alphaRest3; \
156 			uint32 alphaSrc1 = 255 * (a1); \
157 			uint32 alphaSrc2 = 255 * (a2); \
158 			uint32 alphaSrc3 = 255 * (a3); \
159 			d[0] = (_p.data8[0] * alphaDest1 + (b) * alphaSrc1) / alphaTemp1; \
160 			d[1] = (_p.data8[1] * alphaDest2 + (g) * alphaSrc2) / alphaTemp2; \
161 			d[2] = (_p.data8[2] * alphaDest3 + (r) * alphaSrc3) / alphaTemp3; \
162 			d[3] = (alphaTemp1 + alphaTemp2 + alphaTemp3)/765; \
163 		} \
164 	} \
165 }
166 
167 // BLEND_COMPOSITE16
168 //
169 // This macro assumes source alpha in range 0..65025 and
170 // composes the source color over a possibly semi-transparent background.
171 // TODO: implement a faster version
172 #define BLEND_COMPOSITE16(d, r, g, b, a) \
173 { \
174 	uint16 _a = (a) / 255; \
175 	BLEND_COMPOSITE(d, r, g, b, _a); \
176 }
177 
178 // BLEND_COMPOSITE16_SUBPIX
179 #define BLEND_COMPOSITE16_SUBPIX(d, r, g, b, a1, a2, a3) \
180 { \
181 	uint16 _a1 = (a1) / 255; \
182 	uint16 _a2 = (a2) / 255; \
183 	uint16 _a3 = (a3) / 255; \
184 	BLEND_COMPOSITE_SUBPIX(d, r, g, b, _a1, _a2, _a3); \
185 }
186 
187 static inline
188 uint8
189 brightness_for(uint8 red, uint8 green, uint8 blue)
190 {
191 	// brightness = 0.301 * red + 0.586 * green + 0.113 * blue
192 	// we use for performance reasons:
193 	// brightness = (308 * red + 600 * green + 116 * blue) / 1024
194 	return uint8((308 * red + 600 * green + 116 * blue) / 1024);
195 }
196 
197 #endif // DRAWING_MODE_H
198 
199