Merge from mainline.
[official-gcc.git] / libjava / classpath / gnu / java / awt / java2d / AlphaCompositeContext.java
blobe67c92148fbfe7f3a540183927af4b2f2449cdea
1 /* AlphaCompositeContext.java -- CompositeContext impl for AlphaComposite
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.java.awt.java2d;
41 import java.awt.AWTError;
42 import java.awt.AlphaComposite;
43 import java.awt.CompositeContext;
44 import java.awt.image.ColorModel;
45 import java.awt.image.Raster;
46 import java.awt.image.WritableRaster;
48 /**
49 * A CompositeContext implementation for {@link AlphaComposite}.
51 * @author Roman Kennke (kennke@aicas.com)
53 public class AlphaCompositeContext
54 implements CompositeContext
57 /**
58 * The Composite object for which we perform compositing.
60 private AlphaComposite composite;
62 /**
63 * The source color model.
65 private ColorModel srcColorModel;
67 /**
68 * The destination color model.
70 private ColorModel dstColorModel;
72 /**
73 * The blending factor for the source.
75 private float fs;
77 /**
78 * The blending factor for the destination.
80 private float fd;
82 /**
83 * Creates a new AlphaCompositeContext.
85 * @param aComp the AlphaComposite object
86 * @param srcCM the source color model
87 * @param dstCM the destination color model
89 public AlphaCompositeContext(AlphaComposite aComp, ColorModel srcCM,
90 ColorModel dstCM)
92 composite = aComp;
93 srcColorModel = srcCM;
94 dstColorModel = dstCM;
97 // Determine the blending factors according to the rule in the
98 // AlphaComposite. For some rules the factors must be determined
99 // dynamically because they depend on the actual pixel value.
100 switch (composite.getRule())
102 case AlphaComposite.CLEAR:
103 fs = 0.F;
104 fd= 0.F;
105 break;
106 case AlphaComposite.DST:
107 fs = 0.F;
108 fd= 1.F;
109 break;
110 case AlphaComposite.DST_ATOP:
111 fs = 1.F; // Determined later as 1 - alpha_dst;
112 fd = 1.F; // Determined later as alpha_src;
113 break;
114 case AlphaComposite.DST_IN:
115 fs = 0.F;
116 fd = 0.F; // Determined later as alpha_src;
117 break;
118 case AlphaComposite.DST_OUT:
119 fs = 0.F;
120 fd = 0.F; // Determined later as 1 - alpha_src;
121 break;
122 case AlphaComposite.DST_OVER:
123 fs = 1.F; // Determined later as 1 - alpha_dst.
124 fd= 1.F;
125 break;
126 case AlphaComposite.SRC:
127 fs = 1.F;
128 fd= 0.F;
129 break;
130 case AlphaComposite.SRC_ATOP:
131 fs = 1.F; // Determined later as alpha_dst;
132 fd = 1.F; // Determined later as 1 - alpha_src;
133 break;
134 case AlphaComposite.SRC_IN:
135 fs = 0.F; // Determined later as alpha_dst;
136 fd = 0.F;
137 break;
138 case AlphaComposite.SRC_OUT:
139 fs = 0.F; // Determined later as 1 - alpha_dst;
140 fd = 0.F;
141 break;
142 case AlphaComposite.SRC_OVER:
143 fs = 1.F;
144 fd= 1.F; // Determined later as 1 - alpha_src.
145 break;
146 case AlphaComposite.XOR:
147 fs = 1.F; // Determined later as 1 - alpha_dst.
148 fd= 1.F; // Determined later as 1 - alpha_src.
149 break;
150 default:
151 throw new AWTError("Illegal AlphaComposite rule");
157 * Releases all resources held by this composite object.
159 public void dispose()
161 // Nothing to do here yet.
165 * Performs compositing according to the rules specified in the
166 * AlphaComposite from the constructor.
168 public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
171 // TODO: This implementation is very general and highly inefficient. There
172 // are two possible ways to optimize this:
173 // 1. Special cased implementations for common ColorModels and transfer
174 // types.
175 // 2. Native implementation.
177 int x0 = src.getMinX();
178 int y0 = src.getMinY();
179 int width = src.getWidth();
180 int height = src.getHeight();
181 int x1 = x0 + width;
182 int y1 = y0 + height;
184 Object srcPixel = null;
185 Object dstPixel = null;
187 // Prepare the array that holds the color and alpha components of the
188 // source pixels.
189 float[] srcComponents;
190 int srcComponentsLength = srcColorModel.getNumComponents();
191 if (! srcColorModel.hasAlpha())
192 srcComponentsLength += 1;
193 srcComponents = new float[srcComponentsLength];
195 // Prepare the array that holds the color and alpha components of the
196 // destination pixels.
197 float[] dstComponents;
198 int dstComponentsLength = dstColorModel.getNumComponents();
199 if (! dstColorModel.hasAlpha())
200 dstComponentsLength += 1;
201 dstComponents = new float[dstComponentsLength];
203 if (srcComponentsLength != dstComponentsLength)
204 throw new AWTError("The color models of the source and destination have"
205 + "incompatible number of color components");
207 int srcTransferType = srcColorModel.getTransferType();
208 int dstTransferType = dstColorModel.getTransferType();
210 for (int y = y0; y < y1; y++)
212 for (int x = x0; x < x1; x++)
214 // Fetch source pixel.
215 srcPixel = src.getDataElements(x, y, (int[]) srcPixel);
216 // Fetch destination pixel.
217 dstPixel = dstIn.getDataElements(x, y, dstPixel);
218 // Get normalized components. This is the only type that is
219 // guaranteed to be supported by all ColorModels.
220 srcComponents =
221 srcColorModel.getNormalizedComponents(srcPixel, srcComponents, 0);
222 if (! srcColorModel.hasAlpha())
223 srcComponents[srcComponentsLength - 1] = 1.0F;
224 dstComponents =
225 dstColorModel.getNormalizedComponents(dstPixel, dstComponents, 0);
226 if (! dstColorModel.hasAlpha())
227 dstComponents[dstComponentsLength - 1] = 1.0F;
229 // Prepare the input.
230 float compositeAlpha = composite.getAlpha();
231 srcComponents[srcComponentsLength - 1] *= compositeAlpha;
232 if (srcColorModel.isAlphaPremultiplied())
234 for (int i = srcComponentsLength - 2; i >= 0; i--)
235 srcComponents[i] *= compositeAlpha;
237 else
239 for (int i = srcComponentsLength - 1; i >= 0; i--)
240 srcComponents[i] *= srcComponents[srcComponentsLength - 1];
242 if (! dstColorModel.isAlphaPremultiplied())
244 for (int i = dstComponentsLength - 2; i >= 0; i--)
245 dstComponents[i] *= dstComponents[dstComponents.length - 1];
248 // Determine the blending factors according to the rule in the
249 // AlphaComposite. For some rules the factors must be determined
250 // dynamically because they depend on the actual pixel value.
251 float srcAlpha = srcComponents[srcComponentsLength - 1];
252 float dstAlpha = dstComponents[dstComponentsLength - 1];
253 switch (composite.getRule())
255 case AlphaComposite.DST_ATOP:
256 fs = 1.F - dstAlpha;
257 fd = srcAlpha;
258 break;
259 case AlphaComposite.DST_IN:
260 fd = srcAlpha;
261 break;
262 case AlphaComposite.DST_OUT:
263 fd = 1.F - srcAlpha;
264 break;
265 case AlphaComposite.DST_OVER:
266 fs = 1.F - dstAlpha;
267 break;
268 case AlphaComposite.SRC_ATOP:
269 fs = srcAlpha;
270 fd = 1.F - srcAlpha;
271 break;
272 case AlphaComposite.SRC_IN:
273 fs = dstAlpha;
274 break;
275 case AlphaComposite.SRC_OUT:
276 fs = 1.F - dstAlpha;
277 break;
278 case AlphaComposite.SRC_OVER:
279 fd= 1.F - srcAlpha;
280 break;
281 case AlphaComposite.XOR:
282 fs = 1.F - dstAlpha;
283 fd= 1.F - srcAlpha;
284 break;
285 default:
286 // For the other cases the factors have already been determined
287 // in the constructor.
290 // Apply the blending equation to the pixels.
291 for (int i = 0; i < srcComponentsLength; i++)
293 dstComponents[i] = srcComponents[i] * fs
294 + dstComponents[i] * fd;
297 // Convert the result back when the destination is not
298 // alpha-premultiplied.
299 dstAlpha = dstComponents[dstComponentsLength - 1];
300 if (!dstColorModel.isAlphaPremultiplied() && dstAlpha != 0.F)
302 for (int i = 0; i < dstComponentsLength - 1; i++)
304 dstComponents[i] = dstComponents[i] / dstAlpha;
308 // Store the result in the destination raster.
309 dstPixel = dstColorModel.getDataElements(dstComponents, 0,
310 dstPixel);
311 dstOut.setDataElements(x, y, dstPixel);
312 } // End X loop.
313 } // End Y loop.