xref: /haiku/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 /*
2  * Copyright 2005, Stephan Aßmus <superstippi@gmx.de>.
3  * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>
4  * All rights reserved. Distributed under the terms of the MIT License.
5  *
6  * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
7  *
8  * A class implementing the AGG "pixel format" interface which maintains
9  * a PatternHandler and pointers to blending functions implementing the
10  * different BeOS "drawing_modes".
11  *
12  */
13 
14 #include "PixelFormat.h"
15 
16 #include <stdio.h>
17 
18 #include "DrawingModeAdd.h"
19 #include "DrawingModeAlphaCC.h"
20 #include "DrawingModeAlphaCO.h"
21 #include "DrawingModeAlphaCOSolid.h"
22 #include "DrawingModeAlphaPC.h"
23 #include "DrawingModeAlphaPO.h"
24 #include "DrawingModeAlphaPOSolid.h"
25 #include "DrawingModeBlend.h"
26 #include "DrawingModeCopy.h"
27 #include "DrawingModeCopySolid.h"
28 #include "DrawingModeCopyText.h"
29 #include "DrawingModeErase.h"
30 #include "DrawingModeInvert.h"
31 #include "DrawingModeMin.h"
32 #include "DrawingModeMax.h"
33 #include "DrawingModeOver.h"
34 #include "DrawingModeOverSolid.h"
35 #include "DrawingModeSelect.h"
36 #include "DrawingModeSubtract.h"
37 
38 #include "DrawingModeAddSUBPIX.h"
39 #include "DrawingModeAlphaCCSUBPIX.h"
40 #include "DrawingModeAlphaCOSUBPIX.h"
41 #include "DrawingModeAlphaCOSolidSUBPIX.h"
42 #include "DrawingModeAlphaPCSUBPIX.h"
43 #include "DrawingModeAlphaPOSUBPIX.h"
44 #include "DrawingModeAlphaPOSolidSUBPIX.h"
45 #include "DrawingModeBlendSUBPIX.h"
46 #include "DrawingModeCopySUBPIX.h"
47 #include "DrawingModeCopySolidSUBPIX.h"
48 #include "DrawingModeCopyTextSUBPIX.h"
49 #include "DrawingModeEraseSUBPIX.h"
50 #include "DrawingModeInvertSUBPIX.h"
51 #include "DrawingModeMinSUBPIX.h"
52 #include "DrawingModeMaxSUBPIX.h"
53 #include "DrawingModeOverSUBPIX.h"
54 #include "DrawingModeOverSolidSUBPIX.h"
55 #include "DrawingModeSelectSUBPIX.h"
56 #include "DrawingModeSubtractSUBPIX.h"
57 
58 #include "PatternHandler.h"
59 
60 // blend_pixel_empty
61 void
62 blend_pixel_empty(int x, int y, const color_type& c, uint8 cover,
63 				  agg_buffer* buffer, const PatternHandler* pattern)
64 {
65 	printf("blend_pixel_empty()\n");
66 }
67 
68 // blend_hline_empty
69 void
70 blend_hline_empty(int x, int y, unsigned len,
71 				  const color_type& c, uint8 cover,
72 				  agg_buffer* buffer, const PatternHandler* pattern)
73 {
74 	printf("blend_hline_empty()\n");
75 }
76 
77 // blend_vline_empty
78 void
79 blend_vline_empty(int x, int y, unsigned len,
80 				  const color_type& c, uint8 cover,
81 				  agg_buffer* buffer, const PatternHandler* pattern)
82 {
83 	printf("blend_vline_empty()\n");
84 }
85 
86 // blend_solid_hspan_empty
87 void
88 blend_solid_hspan_empty(int x, int y, unsigned len,
89 						const color_type& c, const uint8* covers,
90 						agg_buffer* buffer, const PatternHandler* pattern)
91 {
92 	printf("blend_solid_hspan_empty()\n");
93 }
94 
95 // blend_solid_hspan_subpix_empty
96 void
97 blend_solid_hspan_empty_subpix(int x, int y, unsigned len,
98 						const color_type& c, const uint8* covers,
99 						agg_buffer* buffer, const PatternHandler* pattern)
100 {
101 	printf("blend_solid_hspan_empty_subpix()\n");
102 }
103 
104 // blend_solid_vspan_empty
105 void
106 blend_solid_vspan_empty(int x, int y,
107 						unsigned len, const color_type& c,
108 						const uint8* covers,
109 						agg_buffer* buffer, const PatternHandler* pattern)
110 {
111 	printf("blend_solid_vspan_empty()\n");
112 }
113 
114 // blend_color_hspan_empty
115 void
116 blend_color_hspan_empty(int x, int y, unsigned len,
117 						const color_type* colors,
118 						const uint8* covers, uint8 cover,
119 						agg_buffer* buffer, const PatternHandler* pattern)
120 {
121 	printf("blend_color_hspan_empty()\n");
122 }
123 
124 // blend_color_vspan_empty
125 void
126 blend_color_vspan_empty(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 	printf("blend_color_vspan_empty()\n");
132 }
133 
134 // #pragma mark -
135 
136 // constructor
137 PixelFormat::PixelFormat(agg::rendering_buffer& rb,
138 						 const PatternHandler* handler)
139 	: fBuffer(&rb),
140 	  fPatternHandler(handler),
141 	  fUsesOpCopyForText(false),
142 
143 	  fBlendPixel(blend_pixel_empty),
144 	  fBlendHLine(blend_hline_empty),
145 	  fBlendVLine(blend_vline_empty),
146 	  fBlendSolidHSpan(blend_solid_hspan_empty),
147 	  fBlendSolidHSpanSubpix(blend_solid_hspan_empty_subpix),
148 	  fBlendSolidVSpan(blend_solid_vspan_empty),
149 	  fBlendColorHSpan(blend_color_hspan_empty),
150 	  fBlendColorVSpan(blend_color_vspan_empty)
151 {
152 }
153 
154 // destructor
155 PixelFormat::~PixelFormat()
156 {
157 }
158 
159 // SetDrawingMode
160 void
161 PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
162 							alpha_function alphaFncMode, bool text)
163 {
164 	fUsesOpCopyForText = false;
165 	switch (mode) {
166 		// these drawing modes discard source pixels
167 		// which have the current low color
168 		case B_OP_OVER:
169 			if (fPatternHandler->IsSolid()) {
170 				fBlendPixel = blend_pixel_over_solid;
171 				fBlendHLine = blend_hline_over_solid;
172 				fBlendSolidHSpan = blend_solid_hspan_over_solid;
173 				fBlendSolidVSpan = blend_solid_vspan_over_solid;
174 				fBlendSolidHSpanSubpix = blend_solid_hspan_over_solid_subpix;
175 			} else {
176 				fBlendPixel = blend_pixel_over;
177 				fBlendHLine = blend_hline_over;
178 				fBlendSolidHSpanSubpix = blend_solid_hspan_over_subpix;
179 				fBlendSolidHSpan = blend_solid_hspan_over;
180 				fBlendSolidVSpan = blend_solid_vspan_over;
181 			}
182 			fBlendColorHSpan = blend_color_hspan_over;
183 			break;
184 		case B_OP_ERASE:
185 			fBlendPixel = blend_pixel_erase;
186 			fBlendHLine = blend_hline_erase;
187 			fBlendSolidHSpanSubpix = blend_solid_hspan_erase_subpix;
188 			fBlendSolidHSpan = blend_solid_hspan_erase;
189 			fBlendSolidVSpan = blend_solid_vspan_erase;
190 			fBlendColorHSpan = blend_color_hspan_erase;
191 			break;
192 		case B_OP_INVERT:
193 			fBlendPixel = blend_pixel_invert;
194 			fBlendHLine = blend_hline_invert;
195 			fBlendSolidHSpanSubpix = blend_solid_hspan_invert_subpix;
196 			fBlendSolidHSpan = blend_solid_hspan_invert;
197 			fBlendSolidVSpan = blend_solid_vspan_invert;
198 			fBlendColorHSpan = blend_color_hspan_invert;
199 			break;
200 		case B_OP_SELECT:
201 			fBlendPixel = blend_pixel_select;
202 			fBlendHLine = blend_hline_select;
203 			fBlendSolidHSpanSubpix = blend_solid_hspan_select_subpix;
204 			fBlendSolidHSpan = blend_solid_hspan_select;
205 			fBlendSolidVSpan = blend_solid_vspan_select;
206 			fBlendColorHSpan = blend_color_hspan_select;
207 			break;
208 
209 		// in these drawing modes, the current high
210 		// and low color are treated equally
211 		case B_OP_COPY:
212 			if (text) {
213 				fBlendPixel = blend_pixel_copy_text;
214 				fBlendHLine = blend_hline_copy_text;
215 				fBlendSolidHSpanSubpix = blend_solid_hspan_copy_text_subpix;
216 				fBlendSolidHSpan = blend_solid_hspan_copy_text;
217 				fBlendSolidVSpan = blend_solid_vspan_copy_text;
218 				fBlendColorHSpan = blend_color_hspan_copy_text;
219 				// set the special flag so that Painter
220 				// knows if an update is needed even though
221 				// "nothing changed"
222 				fUsesOpCopyForText = true;
223 			} else if (fPatternHandler->IsSolid()) {
224 				fBlendPixel = blend_pixel_copy_solid;
225 				fBlendHLine = blend_hline_copy_solid;
226 				fBlendSolidHSpanSubpix = blend_solid_hspan_copy_solid_subpix;
227 				fBlendSolidHSpan = blend_solid_hspan_copy_solid;
228 				fBlendSolidVSpan = blend_solid_vspan_copy_solid;
229 				fBlendColorHSpan = blend_color_hspan_copy_solid;
230 			} else {
231 				fBlendPixel = blend_pixel_copy;
232 				fBlendHLine = blend_hline_copy;
233 				fBlendSolidHSpanSubpix = blend_solid_hspan_copy_subpix;
234 				fBlendSolidHSpan = blend_solid_hspan_copy;
235 				fBlendSolidVSpan = blend_solid_vspan_copy;
236 				fBlendColorHSpan = blend_color_hspan_copy;
237 			}
238 			break;
239 		case B_OP_ADD:
240 			fBlendPixel = blend_pixel_add;
241 			fBlendHLine = blend_hline_add;
242 			fBlendSolidHSpanSubpix = blend_solid_hspan_add_subpix;
243 			fBlendSolidHSpan = blend_solid_hspan_add;
244 			fBlendSolidVSpan = blend_solid_vspan_add;
245 			fBlendColorHSpan = blend_color_hspan_add;
246 			break;
247 		case B_OP_SUBTRACT:
248 			fBlendPixel = blend_pixel_subtract;
249 			fBlendHLine = blend_hline_subtract;
250 			fBlendSolidHSpanSubpix = blend_solid_hspan_subtract_subpix;
251 			fBlendSolidHSpan = blend_solid_hspan_subtract;
252 			fBlendSolidVSpan = blend_solid_vspan_subtract;
253 			fBlendColorHSpan = blend_color_hspan_subtract;
254 			break;
255 		case B_OP_BLEND:
256 			fBlendPixel = blend_pixel_blend;
257 			fBlendHLine = blend_hline_blend;
258 			fBlendSolidHSpanSubpix = blend_solid_hspan_blend_subpix;
259 			fBlendSolidHSpan = blend_solid_hspan_blend;
260 			fBlendSolidVSpan = blend_solid_vspan_blend;
261 			fBlendColorHSpan = blend_color_hspan_blend;
262 			break;
263 		case B_OP_MIN:
264 			fBlendPixel = blend_pixel_min;
265 			fBlendHLine = blend_hline_min;
266 			fBlendSolidHSpanSubpix = blend_solid_hspan_min_subpix;
267 			fBlendSolidHSpan = blend_solid_hspan_min;
268 			fBlendSolidVSpan = blend_solid_vspan_min;
269 			fBlendColorHSpan = blend_color_hspan_min;
270 			break;
271 		case B_OP_MAX:
272 			fBlendPixel = blend_pixel_max;
273 			fBlendHLine = blend_hline_max;
274 			fBlendSolidHSpanSubpix = blend_solid_hspan_max_subpix;
275 			fBlendSolidHSpan = blend_solid_hspan_max;
276 			fBlendSolidVSpan = blend_solid_vspan_max;
277 			fBlendColorHSpan = blend_color_hspan_max;
278 			break;
279 
280 		// this drawing mode is the only one considering
281 		// alpha at all. In B_CONSTANT_ALPHA, the alpha
282 		// value from the current high color is used for
283 		// all computations. In B_PIXEL_ALPHA, the alpha
284 		// is considered at every source pixel.
285 		// To simplify the implementation, four separate
286 		// DrawingMode classes are used to cover the
287 		// four possible combinations of alpha enabled drawing.
288 		case B_OP_ALPHA:
289 			if (alphaSrcMode == B_CONSTANT_ALPHA) {
290 				if (alphaFncMode == B_ALPHA_OVERLAY) {
291 					if (fPatternHandler->IsSolid()) {
292 						fBlendPixel = blend_pixel_alpha_co_solid;
293 						fBlendHLine = blend_hline_alpha_co_solid;
294 						fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_co_solid_subpix;
295 						fBlendSolidHSpan = blend_solid_hspan_alpha_co_solid;
296 						fBlendSolidVSpan = blend_solid_vspan_alpha_co_solid;
297 					} else {
298 						fBlendPixel = blend_pixel_alpha_co;
299 						fBlendHLine = blend_hline_alpha_co;
300 						fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_co_subpix;
301 						fBlendSolidHSpan = blend_solid_hspan_alpha_co;
302 						fBlendSolidVSpan = blend_solid_vspan_alpha_co;
303 					}
304 					fBlendColorHSpan = blend_color_hspan_alpha_co;
305 				} else if (alphaFncMode == B_ALPHA_COMPOSITE) {
306 					fBlendPixel = blend_pixel_alpha_cc;
307 					fBlendHLine = blend_hline_alpha_cc;
308 					fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_cc_subpix;
309 					fBlendSolidHSpan = blend_solid_hspan_alpha_cc;
310 					fBlendSolidVSpan = blend_solid_vspan_alpha_cc;
311 					fBlendColorHSpan = blend_color_hspan_alpha_cc;
312 				}
313 			} else if (alphaSrcMode == B_PIXEL_ALPHA){
314 				if (alphaFncMode == B_ALPHA_OVERLAY) {
315 					if (fPatternHandler->IsSolid()) {
316 						fBlendPixel = blend_pixel_alpha_po_solid;
317 						fBlendHLine = blend_hline_alpha_po_solid;
318 						fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_po_solid_subpix;
319 						fBlendSolidHSpan = blend_solid_hspan_alpha_po_solid;
320 						fBlendSolidVSpan = blend_solid_vspan_alpha_po_solid;
321 					} else {
322 						fBlendPixel = blend_pixel_alpha_po;
323 						fBlendHLine = blend_hline_alpha_po;
324 						fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_po_subpix;
325 						fBlendSolidHSpan = blend_solid_hspan_alpha_po;
326 						fBlendSolidVSpan = blend_solid_vspan_alpha_po;
327 					}
328 					fBlendColorHSpan = blend_color_hspan_alpha_po;
329 				} else if (alphaFncMode == B_ALPHA_COMPOSITE) {
330 					fBlendPixel = blend_pixel_alpha_pc;
331 					fBlendHLine = blend_hline_alpha_pc;
332 					fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_pc_subpix;
333 					fBlendSolidHSpan = blend_solid_hspan_alpha_pc;
334 					fBlendSolidVSpan = blend_solid_vspan_alpha_pc;
335 					fBlendColorHSpan = blend_color_hspan_alpha_pc;
336 				}
337 			}
338 			break;
339 
340 		default:
341 fprintf(stderr, "PixelFormat::SetDrawingMode() - drawing_mode not implemented\n");
342 //			return fDrawingModeBGRA32Copy;
343 			break;
344 	}
345 }
346