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