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