xref: /haiku/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSubtract.h (revision 61ed28ee13e6bcf41a9c39c834c1a238881214bd)
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
41 void
blend_pixel_subtract(int x,int y,const color_type & c,uint8 cover,agg_buffer * buffer,const PatternHandler * pattern)42 blend_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
55 void
blend_hline_subtract(int x,int y,unsigned len,const color_type & c,uint8 cover,agg_buffer * buffer,const PatternHandler * pattern)56 blend_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
83 void
blend_solid_hspan_subtract(int x,int y,unsigned len,const color_type & c,const uint8 * covers,agg_buffer * buffer,const PatternHandler * pattern)84 blend_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
107 void
blend_solid_vspan_subtract(int x,int y,unsigned len,const color_type & c,const uint8 * covers,agg_buffer * buffer,const PatternHandler * pattern)108 blend_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
130 void
blend_color_hspan_subtract(int x,int y,unsigned len,const color_type * colors,const uint8 * covers,uint8 cover,agg_buffer * buffer,const PatternHandler * pattern)131 blend_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