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