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)
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
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
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. */
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;
49
* A CompositeContext implementation for {@link AlphaComposite}.
51
* @author Roman Kennke (kennke@aicas.com)
53
public class SunCompositeContext
54
implements CompositeContext
58
* The Composite object for which we perform compositing.
60
private AlphaComposite composite;
63
* The source color model.
65
private ColorModel srcColorModel;
68
* The destination color model.
70
private ColorModel dstColorModel;
73
* The blending factor for the source.
78
* The blending factor for the destination.
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 SunCompositeContext(AlphaComposite aComp, ColorModel srcCM,
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:
106
case AlphaComposite.DST:
110
case AlphaComposite.DST_ATOP:
111
fs = 1.F; // Determined later as 1 - alpha_dst;
112
fd = 1.F; // Determined later as alpha_src;
114
case AlphaComposite.DST_IN:
116
fd = 0.F; // Determined later as alpha_src;
118
case AlphaComposite.DST_OUT:
120
fd = 0.F; // Determined later as 1 - alpha_src;
122
case AlphaComposite.DST_OVER:
123
fs = 1.F; // Determined later as 1 - alpha_dst.
126
case AlphaComposite.SRC:
130
case AlphaComposite.SRC_ATOP:
131
fs = 1.F; // Determined later as alpha_dst;
132
fd = 1.F; // Determined later as 1 - alpha_src;
134
case AlphaComposite.SRC_IN:
135
fs = 0.F; // Determined later as alpha_dst;
138
case AlphaComposite.SRC_OUT:
139
fs = 0.F; // Determined later as 1 - alpha_dst;
142
case AlphaComposite.SRC_OVER:
144
fd= 1.F; // Determined later as 1 - alpha_src.
146
case AlphaComposite.XOR:
147
fs = 1.F; // Determined later as 1 - alpha_dst.
148
fd= 1.F; // Determined later as 1 - alpha_src.
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
175
// 2. Native implementation.
177
int x0 = src.getMinX();
178
int y0 = src.getMinY();
179
int width = src.getWidth();
180
int height = src.getHeight();
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
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.
221
srcColorModel.getNormalizedComponents(srcPixel, srcComponents, 0);
222
if (! srcColorModel.hasAlpha())
223
srcComponents[srcComponentsLength - 1] = 1.0F;
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;
239
for (int i = srcComponentsLength - 2; 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:
259
case AlphaComposite.DST_IN:
262
case AlphaComposite.DST_OUT:
265
case AlphaComposite.DST_OVER:
268
case AlphaComposite.SRC_ATOP:
272
case AlphaComposite.SRC_IN:
275
case AlphaComposite.SRC_OUT:
278
case AlphaComposite.SRC_OVER:
281
case AlphaComposite.XOR:
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,
311
dstOut.setDataElements(x, y, dstPixel);