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