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_ALPHA in "Constant Composite" mode on B_RGBA32.
6 *
7 */
8
9#ifndef DRAWING_MODE_ALPHA_CC_H
10#define DRAWING_MODE_ALPHA_CC_H
11
12#include "DrawingMode.h"
13
14// BLEND_ALPHA_CC
15#define BLEND_ALPHA_CC(d, r, g, b, a) \
16{ \
17	BLEND_COMPOSITE16(d, r, g, b, a); \
18}
19
20// ASSIGN_ALPHA_CC
21#define ASSIGN_ALPHA_CC(d, r, g, b) \
22{ \
23	d[0] = (b); \
24	d[1] = (g); \
25	d[2] = (r); \
26	d[3] = 255; \
27}
28
29// blend_pixel_alpha_cc
30void
31blend_pixel_alpha_cc(int x, int y, const color_type& c, uint8 cover,
32					 agg_buffer* buffer, const PatternHandler* pattern)
33{
34	uint8* p = buffer->row_ptr(y) + (x << 2);
35	rgb_color color = pattern->ColorAt(x, y);
36	uint16 alpha = pattern->HighColor().alpha * cover;
37	if (alpha == 255 * 255) {
38		ASSIGN_ALPHA_CC(p, color.red, color.green, color.blue);
39	} else {
40		BLEND_ALPHA_CC(p, color.red, color.green, color.blue, alpha);
41	}
42}
43
44// blend_hline_alpha_cc
45void
46blend_hline_alpha_cc(int x, int y, unsigned len,
47					 const color_type& c, uint8 cover,
48					 agg_buffer* buffer, const PatternHandler* pattern)
49{
50	rgb_color color = pattern->HighColor();
51	uint16 alpha = color.alpha * cover;
52	if (alpha == 255 * 255) {
53		// cache the low and high color as 32bit values
54		// high color
55		uint32 vh;
56		uint8* p8 = (uint8*)&vh;
57		p8[0] = color.blue;
58		p8[1] = color.green;
59		p8[2] = color.red;
60		p8[3] = 255;
61		// low color
62		color = pattern->LowColor();
63		uint32 vl;
64		p8 = (uint8*)&vl;
65		p8[0] = color.blue;
66		p8[1] = color.green;
67		p8[2] = color.red;
68		p8[3] = 255;
69		// row offset as 32 bit pointer
70		uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x;
71		do {
72			if (pattern->IsHighColor(x, y))
73				*p32 = vh;
74			else
75				*p32 = vl;
76			p32++;
77			x++;
78		} while(--len);
79	} else {
80		uint8* p = buffer->row_ptr(y) + (x << 2);
81		do {
82			rgb_color color = pattern->ColorAt(x, y);
83			BLEND_ALPHA_CC(p, color.red, color.green, color.blue, alpha);
84			x++;
85			p += 4;
86		} while(--len);
87	}
88}
89
90// blend_solid_hspan_alpha_cc
91void
92blend_solid_hspan_alpha_cc(int x, int y, unsigned len,
93						   const color_type& c, const uint8* covers,
94						   agg_buffer* buffer, const PatternHandler* pattern)
95{
96	uint8* p = buffer->row_ptr(y) + (x << 2);
97	uint8 hAlpha = pattern->HighColor().alpha;
98	do {
99		rgb_color color = pattern->ColorAt(x, y);
100		uint16 alpha = hAlpha * *covers;
101		if (alpha) {
102			if (alpha == 255 * 255) {
103				ASSIGN_ALPHA_CC(p, color.red, color.green, color.blue);
104			} else {
105				BLEND_ALPHA_CC(p, color.red, color.green, color.blue, alpha);
106			}
107		}
108		covers++;
109		p += 4;
110		x++;
111	} while(--len);
112}
113
114// blend_solid_vspan_alpha_cc
115void
116blend_solid_vspan_alpha_cc(int x, int y, unsigned len,
117						   const color_type& c, const uint8* covers,
118						   agg_buffer* buffer, const PatternHandler* pattern)
119{
120	uint8* p = buffer->row_ptr(y) + (x << 2);
121	uint8 hAlpha = pattern->HighColor().alpha;
122	do {
123		rgb_color color = pattern->ColorAt(x, y);
124		uint16 alpha = hAlpha * *covers;
125		if (alpha) {
126			if (alpha == 255 * 255) {
127				ASSIGN_ALPHA_CC(p, color.red, color.green, color.blue);
128			} else {
129				BLEND_ALPHA_CC(p, color.red, color.green, color.blue, alpha);
130			}
131		}
132		covers++;
133		p += buffer->stride();
134		y++;
135	} while(--len);
136}
137
138
139// blend_color_hspan_alpha_cc
140void
141blend_color_hspan_alpha_cc(int x, int y, unsigned len,
142						   const color_type* colors,
143						   const uint8* covers, uint8 cover,
144						   agg_buffer* buffer, const PatternHandler* pattern)
145{
146	uint8* p = buffer->row_ptr(y) + (x << 2);
147	uint8 hAlpha = pattern->HighColor().alpha;
148	if (covers) {
149		// non-solid opacity
150		do {
151			uint16 alpha = hAlpha * colors->a * *covers / 255;
152			if (alpha) {
153				if (alpha == 255 * 255) {
154					ASSIGN_ALPHA_CC(p, colors->r, colors->g, colors->b);
155				} else {
156					BLEND_ALPHA_CC(p, colors->r, colors->g, colors->b, alpha);
157				}
158			}
159			covers++;
160			p += 4;
161			++colors;
162		} while(--len);
163	} else {
164		// solid full opcacity
165		uint16 alpha = hAlpha * colors->a * cover / 255;
166		if (alpha == 255 * 255) {
167			do {
168				ASSIGN_ALPHA_CC(p, colors->r, colors->g, colors->b);
169				p += 4;
170				++colors;
171			} while(--len);
172		// solid partial opacity
173		} else if (alpha) {
174			do {
175				BLEND_ALPHA_CC(p, colors->r, colors->g, colors->b, alpha);
176				p += 4;
177				++colors;
178			} while(--len);
179		}
180	}
181}
182
183#endif // DRAWING_MODE_ALPHA_CC_H
184
185