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. */
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
;
49 * A CompositeContext implementation for {@link AlphaComposite}.
51 * @author Roman Kennke (kennke@aicas.com)
53 public class AlphaCompositeContext
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 AlphaCompositeContext(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
- 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
:
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
);