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
18class PatternHandler;
19
20typedef PixelFormat::color_type		color_type;
21typedef 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
188static inline
189uint8
190brightness_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