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