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_SELECT on B_RGBA32.
6 *
7 */
8
9#ifndef DRAWING_MODE_SELECT_H
10#define DRAWING_MODE_SELECT_H
11
12#include "DrawingMode.h"
13
14// BLEND_SELECT
15#define BLEND_SELECT(d, r, g, b, a) \
16{ \
17	BLEND(d, r, g, b, a); \
18}
19
20// ASSIGN_SELECT
21#define ASSIGN_SELECT(d, r, g, b) \
22{ \
23	d[0] = (b); \
24	d[1] = (g); \
25	d[2] = (r); \
26	d[3] = 255; \
27}
28
29// compare
30inline bool
31compare(uint8* p, const rgb_color& high, const rgb_color& low, rgb_color* result)
32{
33	pixel32 _p;
34	_p.data32 = *(uint32*)p;
35	if (_p.data8[2] == high.red &&
36		_p.data8[1] == high.green &&
37		_p.data8[0] == high.blue) {
38		result->red = low.red;
39		result->green = low.green;
40		result->blue = low.blue;
41		return true;
42	} else if (_p.data8[2] == low.red &&
43			   _p.data8[1] == low.green &&
44			   _p.data8[0] == low.blue) {
45		result->red = high.red;
46		result->green = high.green;
47		result->blue = high.blue;
48		return true;
49	}
50	return false;
51}
52
53// blend_pixel_select
54void
55blend_pixel_select(int x, int y, const color_type& c, uint8 cover,
56				   agg_buffer* buffer, const PatternHandler* pattern)
57{
58	if (pattern->IsHighColor(x, y)) {
59		uint8* p = buffer->row_ptr(y) + (x << 2);
60		rgb_color high = pattern->HighColor();
61		rgb_color low = pattern->LowColor();
62		rgb_color color;
63		if (compare(p, high, low, &color)) {
64			if (cover == 255) {
65				ASSIGN_SELECT(p, color.red, color.green, color.blue);
66			} else {
67				BLEND_SELECT(p, color.red, color.green, color.blue, cover);
68			}
69		}
70	}
71}
72
73// blend_hline_select
74void
75blend_hline_select(int x, int y, unsigned len,
76				   const color_type& c, uint8 cover,
77				   agg_buffer* buffer, const PatternHandler* pattern)
78{
79	uint8* p = buffer->row_ptr(y) + (x << 2);
80	rgb_color high = pattern->HighColor();
81	rgb_color low = pattern->LowColor();
82	rgb_color color;
83	if (cover == 255) {
84		do {
85			if (pattern->IsHighColor(x, y)
86				&& compare(p, high, low, &color))
87				ASSIGN_SELECT(p, color.red, color.green, color.blue);
88			x++;
89			p += 4;
90		} while(--len);
91	} else {
92		do {
93			if (pattern->IsHighColor(x, y)
94				&& compare(p, high, low, &color)) {
95				BLEND_SELECT(p, color.red, color.green, color.blue, cover);
96			}
97			x++;
98			p += 4;
99		} while(--len);
100	}
101}
102
103// blend_solid_hspan_select
104void
105blend_solid_hspan_select(int x, int y, unsigned len,
106						 const color_type& c, const uint8* covers,
107						 agg_buffer* buffer, const PatternHandler* pattern)
108{
109	uint8* p = buffer->row_ptr(y) + (x << 2);
110	rgb_color high = pattern->HighColor();
111	rgb_color low = pattern->LowColor();
112	rgb_color color;
113	do {
114		if (pattern->IsHighColor(x, y)) {
115			if (*covers && compare(p, high, low, &color)) {
116				if (*covers == 255) {
117					ASSIGN_SELECT(p, color.red, color.green, color.blue);
118				} else {
119					BLEND_SELECT(p, color.red, color.green, color.blue, *covers);
120				}
121			}
122		}
123		covers++;
124		p += 4;
125		x++;
126	} while(--len);
127}
128
129
130
131// blend_solid_vspan_select
132void
133blend_solid_vspan_select(int x, int y, unsigned len,
134						 const color_type& c, const uint8* covers,
135						 agg_buffer* buffer, const PatternHandler* pattern)
136{
137	uint8* p = buffer->row_ptr(y) + (x << 2);
138	rgb_color high = pattern->HighColor();
139	rgb_color low = pattern->LowColor();
140	rgb_color color;
141	do {
142		if (pattern->IsHighColor(x, y)) {
143			if (*covers && compare(p, high, low, &color)) {
144				if (*covers == 255) {
145					ASSIGN_SELECT(p, color.red, color.green, color.blue);
146				} else {
147					BLEND_SELECT(p, color.red, color.green, color.blue, *covers);
148				}
149			}
150		}
151		covers++;
152		p += buffer->stride();
153		y++;
154	} while(--len);
155}
156
157
158// blend_color_hspan_select
159void
160blend_color_hspan_select(int x, int y, unsigned len,
161						 const color_type* colors,
162						 const uint8* covers, uint8 cover,
163						 agg_buffer* buffer, const PatternHandler* pattern)
164{
165	uint8* p = buffer->row_ptr(y) + (x << 2);
166	rgb_color high = pattern->HighColor();
167	rgb_color low = pattern->LowColor();
168	rgb_color color;
169	if (covers) {
170		// non-solid opacity
171		do {
172			if (*covers && colors->a > 0 && compare(p, high, low, &color)) {
173				if (*covers == 255) {
174					ASSIGN_SELECT(p, color.red, color.green, color.blue);
175				} else {
176					BLEND_SELECT(p, color.red, color.green, color.blue, *covers);
177				}
178			}
179			covers++;
180			p += 4;
181			++colors;
182		} while(--len);
183	} else {
184		// solid full opcacity
185		if (cover == 255) {
186			do {
187				if (colors->a > 0 && compare(p, high, low, &color)) {
188					ASSIGN_SELECT(p, color.red, color.green, color.blue);
189				}
190				p += 4;
191				++colors;
192			} while(--len);
193		// solid partial opacity
194		} else if (cover) {
195			do {
196				if (colors->a > 0 && compare(p, high, low, &color)) {
197					BLEND_SELECT(p, color.red, color.green, color.blue, cover);
198				}
199				p += 4;
200				++colors;
201			} while(--len);
202		}
203	}
204}
205
206#endif // DRAWING_MODE_SELECT_H
207
208