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