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_SUBTRACT on B_RGBA32.
6 *
7 */
8
9#ifndef DRAWING_MODE_SUBTRACT_H
10#define DRAWING_MODE_SUBTRACT_H
11
12#include <SupportDefs.h>
13
14#include "DrawingMode.h"
15#include "PatternHandler.h"
16
17// BLEND_SUBTRACT
18#define BLEND_SUBTRACT(d, r, g, b, a) \
19{ \
20	pixel32 _p; \
21	_p.data32 = *(uint32*)d; \
22	uint8 rt = max_c(0, _p.data8[2] - (r)); \
23	uint8 gt = max_c(0, _p.data8[1] - (g)); \
24	uint8 bt = max_c(0, _p.data8[0] - (b)); \
25	BLEND(d, rt, gt, bt, a); \
26}
27
28// ASSIGN_SUBTRACT
29#define ASSIGN_SUBTRACT(d, r, g, b) \
30{ \
31	pixel32 _p; \
32	_p.data32 = *(uint32*)d; \
33	d[0] = max_c(0, _p.data8[0] - (b)); \
34	d[1] = max_c(0, _p.data8[1] - (g)); \
35	d[2] = max_c(0, _p.data8[2] - (r)); \
36	d[3] = 255; \
37}
38
39
40// blend_pixel_subtract
41void
42blend_pixel_subtract(int x, int y, const color_type& c, uint8 cover,
43					 agg_buffer* buffer, const PatternHandler* pattern)
44{
45	uint8* p = buffer->row_ptr(y) + (x << 2);
46	rgb_color color = pattern->ColorAt(x, y);
47	if (cover == 255) {
48		ASSIGN_SUBTRACT(p, color.red, color.green, color.blue);
49	} else {
50		BLEND_SUBTRACT(p, color.red, color.green, color.blue, cover);
51	}
52}
53
54// blend_hline_subtract
55void
56blend_hline_subtract(int x, int y, unsigned len,
57					 const color_type& c, uint8 cover,
58					 agg_buffer* buffer, const PatternHandler* pattern)
59{
60	uint8* p = buffer->row_ptr(y) + (x << 2);
61	if (cover == 255) {
62		do {
63			rgb_color color = pattern->ColorAt(x, y);
64
65			ASSIGN_SUBTRACT(p, color.red, color.green, color.blue);
66
67			p += 4;
68			x++;
69		} while(--len);
70	} else {
71		do {
72			rgb_color color = pattern->ColorAt(x, y);
73
74			BLEND_SUBTRACT(p, color.red, color.green, color.blue, cover);
75
76			x++;
77			p += 4;
78		} while(--len);
79	}
80}
81
82// blend_solid_hspan_subtract
83void
84blend_solid_hspan_subtract(int x, int y, unsigned len,
85						   const color_type& c, const uint8* covers,
86						   agg_buffer* buffer, const PatternHandler* pattern)
87{
88	uint8* p = buffer->row_ptr(y) + (x << 2);
89	do {
90		rgb_color color = pattern->ColorAt(x, y);
91		if (*covers) {
92			if (*covers == 255) {
93				ASSIGN_SUBTRACT(p, color.red, color.green, color.blue);
94			} else {
95				BLEND_SUBTRACT(p, color.red, color.green, color.blue, *covers);
96			}
97		}
98		covers++;
99		p += 4;
100		x++;
101	} while(--len);
102}
103
104
105
106// blend_solid_vspan_subtract
107void
108blend_solid_vspan_subtract(int x, int y, unsigned len,
109						   const color_type& c, const uint8* covers,
110						   agg_buffer* buffer, const PatternHandler* pattern)
111{
112	uint8* p = buffer->row_ptr(y) + (x << 2);
113	do {
114		rgb_color color = pattern->ColorAt(x, y);
115		if (*covers) {
116			if (*covers == 255) {
117				ASSIGN_SUBTRACT(p, color.red, color.green, color.blue);
118			} else {
119				BLEND_SUBTRACT(p, color.red, color.green, color.blue, *covers);
120			}
121		}
122		covers++;
123		p += buffer->stride();
124		y++;
125	} while(--len);
126}
127
128
129// blend_color_hspan_subtract
130void
131blend_color_hspan_subtract(int x, int y, unsigned len,
132						   const color_type* colors,
133						   const uint8* covers, uint8 cover,
134						   agg_buffer* buffer, const PatternHandler* pattern)
135{
136	uint8* p = buffer->row_ptr(y) + (x << 2);
137	if (covers) {
138		// non-solid opacity
139		do {
140			if (*covers && colors->a > 0) {
141				if (*covers == 255) {
142					ASSIGN_SUBTRACT(p, colors->r, colors->g, colors->b);
143				} else {
144					BLEND_SUBTRACT(p, colors->r, colors->g, colors->b, *covers);
145				}
146			}
147			covers++;
148			p += 4;
149			++colors;
150		} while(--len);
151	} else {
152		// solid full opcacity
153		if (cover == 255) {
154			do {
155				if (colors->a > 0) {
156					ASSIGN_SUBTRACT(p, colors->r, colors->g, colors->b);
157				}
158				p += 4;
159				++colors;
160			} while(--len);
161		// solid partial opacity
162		} else if (cover) {
163			do {
164				if (colors->a > 0) {
165					BLEND_SUBTRACT(p, colors->r, colors->g, colors->b, cover);
166				}
167				p += 4;
168				++colors;
169			} while(--len);
170		}
171	}
172}
173
174#endif // DRAWING_MODE_SUBTRACT_H
175
176