Hi,
This patch implements custom composites for the BufferedImageGraphics
peer, and also cleans up some of the ambiguity regarding cairo vs gdk
native formats.
Cheers,
Francis
2006-10-11 Francis Kung <[EMAIL PROTECTED]>
* gnu/java/awt/peer/gtk/BufferedImageGraphics.java
(buffer, locked): New fields.
(constructors): Initialize new variables.
(createBuffer): New method.
(draw): Implement custom composites.
(drawComposite): New method.
(drawGlyphVector): Implement custom composites.
(drawImage): Implement custom composites.
(drawRenderedImage): Implement custom composites.
(fill): Implement custom composites.
(getBufferCM): New method.
(getNativeCM): New method.
(updateBufferedImage): Fix premultiplication.
* gnu/java/awt/peer/gtk/CairoGraphics2D.java
(copy): Copy composite.
(drawImage): Set background properly.
(getBufferCM): New method.
(setComposite): Reset alpha composite when using custom composite.
* gnu/java/awt/peer/gtk/CairoSurface.java
(cairoColorModel): New field.
(nativeColorModel): Renamed.
(constructor): Use renamed createCairoSampleModel method.
(createCairoSampleModel): New method.
(createNativeSampleModel): Renamed.
(getBufferedImage): Use renamed cairoColorModel field.
* gnu/java/awt/peer/gtk/GtkVolatileImage.java
(gdkColorModel): New field.
(createGdkSampleModel): New method.
(getPixels): Added comments.
(getSnapshot): Use GDK colour and sample models.
* gnu/java/awt/peer/gtk/VolatileImageGraphics.java
(createBuffer): Use GDK colour and sample models.
(getNativeCM): Added comments.
* java/awt/image/BufferedImage.java
(constructor): Set premultiplied flag properly.
Index: gnu/java/awt/peer/gtk/BufferedImageGraphics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java,v
retrieving revision 1.11
diff -u -r1.11 BufferedImageGraphics.java
--- gnu/java/awt/peer/gtk/BufferedImageGraphics.java 2 Oct 2006 21:36:21 -0000 1.11
+++ gnu/java/awt/peer/gtk/BufferedImageGraphics.java 11 Oct 2006 19:56:44 -0000
@@ -38,23 +38,27 @@
package gnu.java.awt.peer.gtk;
+import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
+import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
+import java.awt.Toolkit;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
-import java.awt.image.Raster;
-import java.awt.image.DataBuffer;
-import java.awt.image.DataBufferInt;
import java.awt.image.ColorModel;
+import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
-import java.awt.image.RenderedImage;
import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
import java.util.WeakHashMap;
/**
@@ -68,7 +72,13 @@
/**
* the buffered Image.
*/
- private BufferedImage image;
+ private BufferedImage image, buffer;
+
+ /**
+ * Allows us to lock the image from updates (if we want to perform a few
+ * intermediary operations on the cairo surface, then update it all at once)
+ */
+ private boolean locked;
/**
* Image size.
@@ -105,6 +115,8 @@
this.image = bi;
imageWidth = bi.getWidth();
imageHeight = bi.getHeight();
+ locked = false;
+
if(bi.getColorModel().equals(rgb32))
{
hasFastCM = true;
@@ -113,7 +125,7 @@
else if(bi.getColorModel().equals(argb32))
{
hasFastCM = true;
- hasAlpha = false;
+ hasAlpha = true;
}
else
hasFastCM = false;
@@ -163,6 +175,7 @@
cairo_t = surface.newCairoContext();
imageWidth = copyFrom.imageWidth;
imageHeight = copyFrom.imageHeight;
+ locked = false;
copy( copyFrom, cairo_t );
setClip(0, 0, surface.width, surface.height);
}
@@ -172,6 +185,9 @@
*/
private void updateBufferedImage(int x, int y, int width, int height)
{
+ if (locked)
+ return;
+
int[] pixels = surface.getPixels(imageWidth * imageHeight);
if( x > imageWidth || y > imageHeight )
@@ -184,18 +200,18 @@
if( y + height > imageHeight )
height = imageHeight - y;
- boolean wasPremultiplied = image.isAlphaPremultiplied();
- image.coerceData(true);
-
- if( !hasFastCM )
+ // The setRGB method assumes (or should assume) that pixels are NOT
+ // alpha-premultiplied, but Cairo stores data with premultiplication
+ // (thus the pixels returned in getPixels are premultiplied).
+ // This is ignored for consistency, however, since in
+ // CairoGrahpics2D.drawImage we also use non-premultiplied data
+ if(!hasFastCM)
image.setRGB(x, y, width, height, pixels,
x + y * imageWidth, imageWidth);
else
System.arraycopy(pixels, y * imageWidth,
((DataBufferInt)image.getRaster().getDataBuffer()).
getData(), y * imageWidth, height * imageWidth);
-
- image.coerceData(wasPremultiplied);
}
/**
@@ -228,36 +244,207 @@
*/
public void draw(Shape s)
{
- super.draw(s);
- Rectangle r = s.getBounds();
- updateBufferedImage(r.x, r.y, r.width, r.height);
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ super.draw(s);
+ Rectangle r = s.getBounds();
+ updateBufferedImage(r.x, r.y, r.width, r.height);
+ }
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setStroke(this.getStroke());
+ g2d.setColor(this.getColor());
+ g2d.draw(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
}
public void fill(Shape s)
{
- super.fill(s);
- Rectangle r = s.getBounds();
- updateBufferedImage(r.x, r.y, r.width, r.height);
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ super.fill(s);
+ Rectangle r = s.getBounds();
+ updateBufferedImage(r.x, r.y, r.width, r.height);
+ }
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setColor(this.getColor());
+ g2d.fill(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
}
public void drawRenderedImage(RenderedImage image, AffineTransform xform)
{
- super.drawRenderedImage(image, xform);
- updateBufferedImage(0, 0, imageWidth, imageHeight);
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ super.drawRenderedImage(image, xform);
+ updateBufferedImage(0, 0, imageWidth, imageHeight);
+ }
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.drawRenderedImage(image, xform);
+
+ drawComposite(buffer.getRaster().getBounds(), null);
+ }
+
}
protected boolean drawImage(Image img, AffineTransform xform,
Color bgcolor, ImageObserver obs)
{
- boolean rv = super.drawImage(img, xform, bgcolor, obs);
- updateBufferedImage(0, 0, imageWidth, imageHeight);
- return rv;
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ boolean rv = super.drawImage(img, xform, bgcolor, obs);
+ updateBufferedImage(0, 0, imageWidth, imageHeight);
+ return rv;
+ }
+ else
+ {
+ // Get buffered image of source
+ if( !(img instanceof BufferedImage) )
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ img = Toolkit.getDefaultToolkit().createImage(source);
+ }
+ BufferedImage bImg = (BufferedImage) img;
+
+ // Find translated bounds
+ Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
+ Point2D pt = new Point2D.Double(bImg.getWidth() + bImg.getMinX(),
+ bImg.getHeight() + bImg.getMinY());
+ if (xform != null)
+ {
+ origin = xform.transform(origin, origin);
+ pt = xform.transform(pt, pt);
+ }
+
+ // Create buffer and draw image
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.drawImage(img, xform, obs);
+
+ // Perform compositing
+ return drawComposite(new Rectangle2D.Double(origin.getX(),
+ origin.getY(),
+ pt.getX(), pt.getY()),
+ obs);
+ }
}
public void drawGlyphVector(GlyphVector gv, float x, float y)
{
- super.drawGlyphVector(gv, x, y);
- updateBufferedImage(0, 0, imageWidth, imageHeight);
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ super.drawGlyphVector(gv, x, y);
+ updateBufferedImage(0, 0, imageWidth, imageHeight);
+ }
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setStroke(this.getStroke());
+ g2d.drawGlyphVector(gv, x, y);
+
+ Rectangle2D bounds = gv.getLogicalBounds();
+ bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
+ bounds.getWidth(), bounds.getHeight());
+ drawComposite(bounds, null);
+ }
+ }
+
+ private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
+ {
+ // Clip source to visible areas that need updating
+ Rectangle2D clip = this.getClipBounds();
+ Rectangle2D.intersect(bounds, clip, bounds);
+
+ BufferedImage buffer2 = buffer;
+ if (!bounds.equals(buffer2.getRaster().getBounds()))
+ buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(),
+ (int)bounds.getHeight());
+
+ // Get destination clip to bounds
+ double[] points = new double[] {bounds.getX(), bounds.getY(),
+ bounds.getMaxX(), bounds.getMaxY()};
+ transform.transform(points, 0, points, 0, 2);
+
+ Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
+ points[2] - points[0],
+ points[3] - points[1]);
+
+ Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
+
+ BufferedImage current = image;
+ current = current.getSubimage((int)deviceBounds.getX(),
+ (int)deviceBounds.getY(),
+ (int)deviceBounds.getWidth(),
+ (int)deviceBounds.getHeight());
+
+ // Perform actual composite operation
+ compCtx.compose(buffer2.getRaster(), current.getRaster(),
+ current.getRaster());
+
+ // Prevent the clearRect in CairoGraphics2D.drawImage from clearing
+ // our composited image
+ locked = true;
+
+ // This MUST call directly into the "action" method in CairoGraphics2D,
+ // not one of the wrappers, to ensure that the composite isn't processed
+ // more than once!
+ boolean rv = super.drawImage(current,
+ AffineTransform.getTranslateInstance(bounds.getX(),
+ bounds.getY()),
+ new Color(0,0,0,0), null);
+ locked = false;
+ return rv;
+ }
+
+ private void createBuffer()
+ {
+ if (buffer == null)
+ {
+ buffer = new BufferedImage(image.getWidth(), image.getHeight(),
+ BufferedImage.TYPE_INT_ARGB);
+ }
+ else
+ {
+ Graphics2D g2d = ((Graphics2D)buffer.getGraphics());
+
+ g2d.setBackground(new Color(0,0,0,0));
+ g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
+ }
+ }
+
+ protected ColorModel getNativeCM()
+ {
+ return image.getColorModel();
+ }
+
+ protected ColorModel getBufferCM()
+ {
+ return ColorModel.getRGBdefault();
}
}
Index: gnu/java/awt/peer/gtk/CairoSurface.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoSurface.java,v
retrieving revision 1.19
diff -u -r1.19 CairoSurface.java
--- gnu/java/awt/peer/gtk/CairoSurface.java 3 Oct 2006 19:47:58 -0000 1.19
+++ gnu/java/awt/peer/gtk/CairoSurface.java 11 Oct 2006 19:56:44 -0000
@@ -72,15 +72,13 @@
*/
long bufferPointer;
- // nativeGetPixels will return [0]=red, [1]=green, [2]=blue, [3]=alpha
- static ColorModel nativeColorModel = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
- 32,
- 0x000000FF,
- 0x0000FF00,
- 0x00FF0000,
- 0xFF000000,
- true,
- Buffers.smallestAppropriateTransferType(32));
+ static ColorModel cairoColorModel = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ 32, 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF,
+ 0xFF000000,
+ true,
+ Buffers.smallestAppropriateTransferType(32));
/**
* Allocates and clears the buffer and creates the cairo surface.
@@ -147,7 +145,7 @@
*/
public CairoSurface(int width, int height)
{
- super(createNativeSampleModel(width, height),
+ super(createCairoSampleModel(width, height),
null, new Point(0, 0));
if(width <= 0 || height <= 0)
@@ -260,7 +258,9 @@
*/
public static BufferedImage getBufferedImage(CairoSurface surface)
{
- return new BufferedImage(nativeColorModel, surface, true, new Hashtable());
+ return new BufferedImage(cairoColorModel, surface,
+ cairoColorModel.isAlphaPremultiplied(),
+ new Hashtable());
}
private class CairoDataBuffer extends DataBuffer
@@ -326,10 +326,10 @@
/**
* Creates a SampleModel that matches Cairo's native format
*/
- protected static SampleModel createNativeSampleModel(int w, int h)
+ protected static SampleModel createCairoSampleModel(int w, int h)
{
return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, w, h,
- new int[]{0x000000FF, 0x0000FF00,
- 0x00FF0000, 0xFF000000});
+ new int[]{0x00FF0000, 0x0000FF00,
+ 0x000000FF, 0xFF000000});
}
}
Index: gnu/java/awt/peer/gtk/CairoGraphics2D.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java,v
retrieving revision 1.43
diff -u -r1.43 CairoGraphics2D.java
--- gnu/java/awt/peer/gtk/CairoGraphics2D.java 10 Oct 2006 20:24:15 -0000 1.43
+++ gnu/java/awt/peer/gtk/CairoGraphics2D.java 11 Oct 2006 19:56:44 -0000
@@ -236,7 +236,6 @@
nativePointer = init(cairo_t_pointer);
paint = g.paint;
stroke = g.stroke;
- comp = g.comp;
setRenderingHints(g.hints);
Color foreground;
@@ -965,27 +964,30 @@
compCtx.dispose();
compCtx = null;
- if (comp == null)
- comp = AlphaComposite.SrcOver;
-
if (comp instanceof AlphaComposite)
{
AlphaComposite a = (AlphaComposite) comp;
- cairoSetOperator(nativePointer, a.getRule());
+ cairoSetOperator(nativePointer, a.getRule());
}
else
{
- // FIXME: this check is only required "if this Graphics2D
- // context is drawing to a Component on the display screen".
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPermission(new AWTPermission("readDisplayPixels"));
-
- // FIXME: implement general Composite support
- //throw new java.lang.UnsupportedOperationException();
- // this is in progress! yay!
- compCtx = comp.createContext(getNativeCM(), getNativeCM(), hints);
+ cairoSetOperator(nativePointer, AlphaComposite.SRC_OVER);
+
+ if (comp != null)
+ {
+ // FIXME: this check is only required "if this Graphics2D
+ // context is drawing to a Component on the display screen".
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new AWTPermission("readDisplayPixels"));
+
+ // FIXME: implement general Composite support
+ //throw new java.lang.UnsupportedOperationException();
+ // this is in progress! yay!
+ //compCtx = comp.createContext(getNativeCM(), getNativeCM(), hints);
+ compCtx = comp.createContext(getBufferCM(), getNativeCM(), hints);
+ }
}
}
@@ -1003,6 +1005,12 @@
// for now, so that the build doesn't break.
return null;
}
+
+ // This may be overridden by some subclasses
+ protected ColorModel getBufferCM()
+ {
+ return getNativeCM();
+ }
///////////////////////// DRAWING PRIMITIVES ///////////////////////////////////
@@ -1358,9 +1366,6 @@
int width = b.getWidth();
int height = b.getHeight();
- boolean wasPremultplied = b.isAlphaPremultiplied();
- b.coerceData(true);
-
// If this BufferedImage has a BufferedImageGraphics object,
// use the cached CairoSurface that BIG is drawing onto
@@ -1380,31 +1385,32 @@
((CairoSurface)raster).drawSurface(nativePointer, i2u, alpha,
getInterpolation());
updateColor();
- b.coerceData(wasPremultplied);
return true;
}
if( bgcolor != null )
{
- // Fill a rectangle with the background color
- // to composite the image onto.
- Paint oldPaint = paint;
- AffineTransform oldTransform = transform;
- setPaint( bgcolor );
- setTransform( invertedXform );
- fillRect(0, 0, width, height);
- setTransform( oldTransform );
- setPaint( oldPaint );
+ Color oldColor = bg;
+ setBackground(bgcolor);
+
+ double[] origin = new double[] {0,0};
+ xform.transform(origin, 0, origin, 0, 1);
+ clearRect((int)origin[0], (int)origin[1], width, height);
+
+ setBackground(oldColor);
}
int[] pixels = b.getRGB(0, 0, width, height, null, 0, width);
+
+ // FIXME: The above method returns data in the standard ARGB colorspace,
+ // meaning data should NOT be alpha pre-multiplied; however Cairo expects
+ // data to be premultiplied.
drawPixels(nativePointer, pixels, width, height, width, i2u, alpha,
getInterpolation());
// Cairo seems to lose the current color which must be restored.
updateColor();
- b.coerceData(wasPremultplied);
return true;
}
Index: gnu/java/awt/peer/gtk/GtkVolatileImage.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java,v
retrieving revision 1.8
diff -u -r1.8 GtkVolatileImage.java
--- gnu/java/awt/peer/gtk/GtkVolatileImage.java 15 Jun 2006 18:29:34 -0000 1.8
+++ gnu/java/awt/peer/gtk/GtkVolatileImage.java 11 Oct 2006 19:56:45 -0000
@@ -37,13 +37,21 @@
package gnu.java.awt.peer.gtk;
-import java.awt.ImageCapabilities;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
+import java.awt.ImageCapabilities;
+import java.awt.Point;
import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DirectColorModel;
import java.awt.image.ImageObserver;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
public class GtkVolatileImage extends VolatileImage
{
@@ -52,6 +60,12 @@
final GtkComponentPeer component;
+ static ColorModel gdkColorModel = new DirectColorModel(32,
+ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000,
+ 0xFF000000);
+
/**
* Don't touch, accessed from native code.
*/
@@ -62,6 +76,17 @@
native void destroy(long pointer);
native int[] nativeGetPixels(long pointer);
+
+ /**
+ * Gets the pixels in the current image from GDK.
+ *
+ * Note that pixels are in 32-bit RGBA, non-premultiplied, which is different
+ * from Cairo's premultiplied ARGB, which is different from Java's standard
+ * non-premultiplied ARGB. Caution is advised when using this method, to
+ * ensure that the data format remains consistent with what you expect.
+ *
+ * @return the current pixels, as reported by GDK.
+ */
public int[] getPixels()
{
return nativeGetPixels(nativePointer);
@@ -113,9 +138,11 @@
public BufferedImage getSnapshot()
{
- CairoSurface cs = new CairoSurface( width, height );
- cs.setPixels( getPixels() );
- return CairoSurface.getBufferedImage( cs );
+ WritableRaster raster = Raster.createWritableRaster(createGdkSampleModel(width, height),
+ new Point(0, 0));
+ raster.setDataElements(0, 0, getPixels());
+ return new BufferedImage(gdkColorModel, raster,
+ gdkColorModel.isAlphaPremultiplied(), null);
}
public Graphics getGraphics()
@@ -167,4 +194,14 @@
{
return null;
}
+
+ /**
+ * Creates a SampleModel that matches GDK's native format
+ */
+ protected static SampleModel createGdkSampleModel(int w, int h)
+ {
+ return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, w, h,
+ new int[]{0x000000FF, 0x0000FF00,
+ 0x00FF0000, 0xFF000000});
+ }
}
Index: gnu/java/awt/peer/gtk/VolatileImageGraphics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java,v
retrieving revision 1.8
diff -u -r1.8 VolatileImageGraphics.java
--- gnu/java/awt/peer/gtk/VolatileImageGraphics.java 3 Oct 2006 19:47:58 -0000 1.8
+++ gnu/java/awt/peer/gtk/VolatileImageGraphics.java 11 Oct 2006 19:56:45 -0000
@@ -282,12 +282,12 @@
if (buffer == null)
{
WritableRaster rst;
- rst = Raster.createWritableRaster(CairoSurface.
- createNativeSampleModel(owner.width,
+ rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(owner.width,
owner.height),
new Point(0,0));
- buffer = new BufferedImage(CairoSurface.nativeColorModel, rst, true,
+ buffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
+ GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
new Hashtable());
}
else
@@ -301,7 +301,12 @@
protected ColorModel getNativeCM()
{
- return CairoSurface.nativeColorModel;
+ // We should really return GtkVolatileImage.gdkColorModel ,
+ // but CairoGraphics2D doesn't handle alpha premultiplication properly (see
+ // the fixme in drawImage) so we use the naive Cairo model instead to trick
+ // the compositing context.
+ // Because getNativeCM() == getBufferCM() for this peer, it doesn't break.
+ return CairoSurface.cairoColorModel;
}
}
Index: java/awt/image/BufferedImage.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/image/BufferedImage.java,v
retrieving revision 1.20
diff -u -r1.20 BufferedImage.java
--- java/awt/image/BufferedImage.java 2 Oct 2006 21:36:21 -0000 1.20
+++ java/awt/image/BufferedImage.java 11 Oct 2006 19:56:45 -0000
@@ -38,6 +38,7 @@
package java.awt.image;
+import gnu.java.awt.Buffers;
import gnu.java.awt.ComponentDataBlitOp;
import java.awt.Graphics;
@@ -172,7 +173,13 @@
0x0000FF00,
0x000000FF,
0xFF000000 } );
- cm = new DirectColorModel( 32, 0xff0000, 0xff00, 0xff, 0xff000000 );
+ if (premultiplied)
+ cm = new DirectColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ 32, 0xff0000, 0xff00, 0xff, 0xff000000,
+ true,
+ Buffers.smallestAppropriateTransferType(32));
+ else
+ cm = new DirectColorModel( 32, 0xff0000, 0xff00, 0xff, 0xff000000 );
break;
case BufferedImage.TYPE_4BYTE_ABGR:
@@ -183,7 +190,13 @@
0xFF000000,
0x00FF0000,
0x0000FF00 } );
- cm = new DirectColorModel( 32, 0xff, 0xff00, 0xff0000, 0xff000000 );
+ if (premultiplied)
+ cm = new DirectColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ 32, 0xff0000, 0xff00, 0xff, 0xff000000,
+ true,
+ Buffers.smallestAppropriateTransferType(32));
+ else
+ cm = new DirectColorModel( 32, 0xff0000, 0xff00, 0xff, 0xff000000 );
break;
case BufferedImage.TYPE_INT_BGR: