diff options
Diffstat (limited to 'gnu/java/awt/peer/gtk')
-rw-r--r-- | gnu/java/awt/peer/gtk/GdkGraphics.java | 169 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GdkGraphics2D.java | 31 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkComponentPeer.java | 46 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkContainerPeer.java | 11 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkFramePeer.java | 37 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkImage.java | 560 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkImageConsumer.java | 155 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkImagePainter.java | 267 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkOffScreenImage.java | 93 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkToolkit.java | 68 |
10 files changed, 588 insertions, 849 deletions
diff --git a/gnu/java/awt/peer/gtk/GdkGraphics.java b/gnu/java/awt/peer/gtk/GdkGraphics.java index 70b3abca7..c870dc1d4 100644 --- a/gnu/java/awt/peer/gtk/GdkGraphics.java +++ b/gnu/java/awt/peer/gtk/GdkGraphics.java @@ -58,6 +58,7 @@ public class GdkGraphics extends Graphics GtkComponentPeer component; Font font; Rectangle clip; + GtkImage image; int xOffset = 0; int yOffset = 0; @@ -66,6 +67,7 @@ public class GdkGraphics extends Graphics native void initState (GtkComponentPeer component); native void initState (int width, int height); + native void initFromImage (GtkImage image); native void copyState (GdkGraphics g); GdkGraphics (GdkGraphics g) @@ -87,10 +89,21 @@ public class GdkGraphics extends Graphics font = new Font ("Dialog", Font.PLAIN, 12); } + GdkGraphics (GtkImage image) + { + this.image = image; + initFromImage (image); + color = Color.black; + clip = new Rectangle (0, 0, + image.getWidth(null), image.getHeight(null)); + font = new Font ("Dialog", Font.PLAIN, 12); + } + GdkGraphics (GtkComponentPeer component) { this.component = component; font = component.awtComponent.getFont (); + color = Color.black; if (component.isRealized ()) initComponentGraphics (); @@ -129,169 +142,57 @@ public class GdkGraphics extends Graphics public native void dispose(); - native void copyPixmap (Graphics g, int x, int y, int width, int height); - native void copyAndScalePixmap (Graphics g, boolean flip_x, boolean flip_y, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height); public boolean drawImage (Image img, int x, int y, Color bgcolor, ImageObserver observer) { - if (component != null && ! component.isRealized ()) - return false; - - if (img instanceof GtkOffScreenImage) - { - int width = img.getWidth (null); - int height = img.getHeight (null); - copyPixmap (img.getGraphics (), - x, y, width, height); - return true; - } - - GtkImage image = (GtkImage) img; - new GtkImagePainter (image, this, x, y, -1, -1, bgcolor, observer); - return image.isLoaded (); + return drawImage(img, x, y, img.getWidth(null), img.getHeight(null), + bgcolor, observer); } public boolean drawImage (Image img, int x, int y, ImageObserver observer) { - if (component != null && ! component.isRealized ()) - return false; - - if (img instanceof GtkOffScreenImage) - { - int width = img.getWidth (null); - int height = img.getHeight (null); - copyPixmap (img.getGraphics (), - x, y, width, height); - return true; - } - - if (component != null) - return drawImage (img, x, y, component.getBackground (), observer); - else - return drawImage (img, x, y, SystemColor.window, observer); + return drawImage (img, x, y, null, observer); } public boolean drawImage (Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { - if (component != null && ! component.isRealized ()) - return false; - - if (img instanceof GtkOffScreenImage) - { - copyAndScalePixmap (img.getGraphics (), false, false, - 0, 0, img.getWidth (null), img.getHeight (null), - x, y, width, height); - return true; - } - - GtkImage image = (GtkImage) img; - new GtkImagePainter (image, this, x, y, width, height, bgcolor, observer); - return image.isLoaded (); + if (img instanceof GtkImage) + return ((GtkImage)img).drawImage (this, x, y, width, height, + bgcolor, observer); + else + return (new GtkImage(img.getSource())).drawImage (this, x, y, + width, height, + bgcolor, observer); } public boolean drawImage (Image img, int x, int y, int width, int height, ImageObserver observer) { - if (component != null && ! component.isRealized ()) - return false; - - if (component != null) - return drawImage (img, x, y, width, height, component.getBackground (), - observer); - else - return drawImage (img, x, y, width, height, SystemColor.window, - observer); + return drawImage (img, x, y, width, height, null, observer); } public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) { - if (component != null && ! component.isRealized ()) - return false; - - if (img instanceof GtkOffScreenImage) - { - int dx_start, dy_start, d_width, d_height; - int sx_start, sy_start, s_width, s_height; - boolean x_flip = false; - boolean y_flip = false; - - if (dx1 < dx2) - { - dx_start = dx1; - d_width = dx2 - dx1; - } - else - { - dx_start = dx2; - d_width = dx1 - dx2; - x_flip ^= true; - } - if (dy1 < dy2) - { - dy_start = dy1; - d_height = dy2 - dy1; - } - else - { - dy_start = dy2; - d_height = dy1 - dy2; - y_flip ^= true; - } - if (sx1 < sx2) - { - sx_start = sx1; - s_width = sx2 - sx1; - } - else - { - sx_start = sx2; - s_width = sx1 - sx2; - x_flip ^= true; - } - if (sy1 < sy2) - { - sy_start = sy1; - s_height = sy2 - sy1; - } - else - { - sy_start = sy2; - s_height = sy1 - sy2; - y_flip ^= true; - } - - copyAndScalePixmap (img.getGraphics (), x_flip, y_flip, - sx_start, sy_start, s_width, s_height, - dx_start, dy_start, d_width, d_height); - return true; - } - - GtkImage image = (GtkImage) img; - new GtkImagePainter (image, this, dx1, dy1, dx2, dy2, - sx1, sy1, sx2, sy2, bgcolor, observer); - return image.isLoaded (); + if (img instanceof GtkImage) + return ((GtkImage)img).drawImage(this, dx1, dy1, dx2, dy2, + sx1, sy1, sx2, sy2, bgcolor, observer); + else + return (new GtkImage(img.getSource())).drawImage(this, dx1, dy1, + dx2, dy2, + sx1, sy1, sx2, sy2, + bgcolor, observer); } public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { - if (component != null && ! component.isRealized ()) - return false; - - if (component != null) - return drawImage (img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, - component.getBackground (), observer); - else - return drawImage (img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, - SystemColor.window, observer); + return drawImage (img, dx1, dy1, dx2, dy2, + sx1, sy1, sx2, sy2, + null, observer); } public native void drawLine(int x1, int y1, int x2, int y2); diff --git a/gnu/java/awt/peer/gtk/GdkGraphics2D.java b/gnu/java/awt/peer/gtk/GdkGraphics2D.java index 6c04f7834..0ddc1c7a8 100644 --- a/gnu/java/awt/peer/gtk/GdkGraphics2D.java +++ b/gnu/java/awt/peer/gtk/GdkGraphics2D.java @@ -510,21 +510,22 @@ public class GdkGraphics2D extends Graphics2D if (img == null) return false; - if (img instanceof GtkOffScreenImage - && img.getGraphics() instanceof GdkGraphics2D - && (xform == null || xform.getType() == AffineTransform.TYPE_IDENTITY - || xform.getType() == AffineTransform.TYPE_TRANSLATION)) - { - // we are being asked to flush a double buffer from Gdk - GdkGraphics2D g2 = (GdkGraphics2D) img.getGraphics(); - gdkDrawDrawable(g2, (int) xform.getTranslateX(), - (int) xform.getTranslateY()); - - updateBufferedImage(); - - return true; - } - else + // FIXME: I'll fix this, /Sven +// if (img instanceof GtkOffScreenImage +// && img.getGraphics() instanceof GdkGraphics2D +// && (xform == null || xform.getType() == AffineTransform.TYPE_IDENTITY +// || xform.getType() == AffineTransform.TYPE_TRANSLATION)) +// { +// // we are being asked to flush a double buffer from Gdk +// GdkGraphics2D g2 = (GdkGraphics2D) img.getGraphics(); +// gdkDrawDrawable(g2, (int) xform.getTranslateX(), +// (int) xform.getTranslateY()); + +// updateBufferedImage(); + +// return true; +// } +// else { // In this case, xform is an AffineTransform that transforms bounding // box of the specified image from image space to user space. However diff --git a/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/gnu/java/awt/peer/gtk/GtkComponentPeer.java index e3e7afb19..3a1bf8b66 100644 --- a/gnu/java/awt/peer/gtk/GtkComponentPeer.java +++ b/gnu/java/awt/peer/gtk/GtkComponentPeer.java @@ -198,33 +198,21 @@ public class GtkComponentPeer extends GtkGenericPeer public int checkImage (Image image, int width, int height, ImageObserver observer) { - GtkImage i = (GtkImage) image; - return i.checkImage (); + return getToolkit().checkImage(image, width, height, observer); } public Image createImage (ImageProducer producer) { - GtkImage image = new GtkImage (producer, null); - producer.startProduction (image); - return image; + return new GtkImage (producer); } public Image createImage (int width, int height) { - Graphics g; - if (GtkToolkit.useGraphics2D ()) - { - Graphics2D g2 = new GdkGraphics2D (width, height); - g2.setBackground (getBackground ()); - g = g2; - } - else - g = new GdkGraphics (width, height); - + GtkImage image = new GtkImage (width, height); + Graphics g = image.getGraphics(); g.setColor(getBackground()); g.fillRect(0, 0, width, height); - - return new GtkOffScreenImage (null, g, width, height); + return image; } public void disable () @@ -353,29 +341,7 @@ public class GtkComponentPeer extends GtkGenericPeer public boolean prepareImage (Image image, int width, int height, ImageObserver observer) { - GtkImage i = (GtkImage) image; - - if (i.isLoaded ()) return true; - - class PrepareImage extends Thread - { - GtkImage image; - ImageObserver observer; - - PrepareImage (GtkImage image, ImageObserver observer) - { - this.image = image; - image.setObserver (observer); - } - - public void run () - { - image.source.startProduction (image); - } - } - - new PrepareImage (i, observer).start (); - return false; + return getToolkit().prepareImage(image, width, height, observer); } public void print (Graphics g) diff --git a/gnu/java/awt/peer/gtk/GtkContainerPeer.java b/gnu/java/awt/peer/gtk/GtkContainerPeer.java index 61551835e..e4aea64c9 100644 --- a/gnu/java/awt/peer/gtk/GtkContainerPeer.java +++ b/gnu/java/awt/peer/gtk/GtkContainerPeer.java @@ -115,9 +115,14 @@ public class GtkContainerPeer extends GtkComponentPeer Component[] components = ((Container) awtComponent).getComponents(); for (int i = 0; i < components.length; i++) { - GtkComponentPeer peer = (GtkComponentPeer) components[i].getPeer(); - if (peer != null && ! peer.awtComponent.isFontSet()) - peer.setFont(f); + if (components[i].isLightweight ()) + components[i].setFont (f); + else + { + GtkComponentPeer peer = (GtkComponentPeer) components[i].getPeer(); + if (peer != null && ! peer.awtComponent.isFontSet()) + peer.setFont(f); + } } } diff --git a/gnu/java/awt/peer/gtk/GtkFramePeer.java b/gnu/java/awt/peer/gtk/GtkFramePeer.java index b22a25e88..53e06bc08 100644 --- a/gnu/java/awt/peer/gtk/GtkFramePeer.java +++ b/gnu/java/awt/peer/gtk/GtkFramePeer.java @@ -166,36 +166,17 @@ public class GtkFramePeer extends GtkWindowPeer setIconImage(frame.getIconImage()); } - native void nativeSetIconImageFromDecoder (GdkPixbufDecoder decoder); - native void nativeSetIconImageFromData (int[] pixels, int width, int height); + native void nativeSetIconImage (GtkImage image); + public void setIconImage (Image image) { - if (image != null && image instanceof GtkImage) - { - GtkImage img = (GtkImage) image; - // FIXME: Image should be loaded, but if not, do image loading here. - if (img.isLoaded()) - { - if (img.getSource() instanceof GdkPixbufDecoder) - { - nativeSetIconImageFromDecoder((GdkPixbufDecoder) img.getSource()); - } - else - { - int[] pixels = img.getPixelCache(); - ColorModel model = img.getColorModel(); - int[] data = new int[pixels.length * 4]; - for (int i = 0; i < pixels.length; i++) - { - data[i * 4] = model.getRed(pixels[i]); - data[i * 4 + 1] = model.getGreen(pixels[i]); - data[i * 4 + 2] = model.getBlue(pixels[i]); - data[i * 4 + 3] = model.getAlpha(pixels[i]); - } - nativeSetIconImageFromData(data, img.getWidth(null), img.getHeight(null)); - } - } - } + if (image != null) + { + if (image instanceof GtkImage) + nativeSetIconImage((GtkImage) image); + else + nativeSetIconImage(new GtkImage(image.getSource())); + } } public Graphics getGraphics () diff --git a/gnu/java/awt/peer/gtk/GtkImage.java b/gnu/java/awt/peer/gtk/GtkImage.java index 510646c5a..9b794b4aa 100644 --- a/gnu/java/awt/peer/gtk/GtkImage.java +++ b/gnu/java/awt/peer/gtk/GtkImage.java @@ -1,5 +1,5 @@ /* GtkImage.java - Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,306 +39,420 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; import java.awt.Graphics; +import java.awt.Color; import java.awt.Image; import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.MemoryImageSource; import java.awt.image.ImageConsumer; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; +import java.io.File; +import java.io.IOException; import java.util.Hashtable; import java.util.Vector; - -public class GtkImage extends Image implements ImageConsumer +import gnu.classpath.RawData; + +/** + * GtkImage - wraps a GdkPixbuf or GdkPixmap. + * + * The constructor GtkImage(int, int) creates an 'off-screen' GdkPixmap, + * this can be drawn to (it's a GdkDrawable), and correspondingly, you can + * create a GdkGraphics object for it. + * + * This corresponds to the Image implementation returned by + * Component.createImage(int, int). + * + * A GdkPixbuf is 'on-screen' and the gdk cannot draw to it, + * this is used for the other constructors (and other createImage methods), and + * corresponds to the Image implementations returned by the Toolkit.createImage + * methods, and is basically immutable. + * + * @author Sven de Marothy + */ +public class GtkImage extends Image { int width = -1, height = -1; - Hashtable props = null; - boolean isLoaded = false; - boolean isCacheable = true; - boolean loading = false; - - Vector widthObservers = new Vector (); - Vector heightObservers = new Vector (); - Vector propertyObservers = new Vector (); + /** + * Properties. + */ + Hashtable props; + + /** + * Loaded or not flag, for asynchronous compatibility. + */ + boolean isLoaded; + + /** + * Pointer to the GdkPixbuf + */ + RawData pixmap; + + /** + * Observer queue. + */ + Vector observers; + + /** + * If offScreen is set, a GdkBitmap is wrapped and not a Pixbuf. + */ + boolean offScreen; + + /** + * Original source, if created from an ImageProducer. + */ ImageProducer source; - ImageObserver observer; - Graphics g; - - /* Variables in which we stored cached data, if possible. - An image is cached if the following properties are true: - 1. The ColorModel passed into setColorModel is the same ColorModel - passed to all invocations of setPixels. - 2. The image contains a single frame. - - */ - int[] pixelCache; - ColorModel model; - - public - GtkImage (ImageProducer producer, Graphics g) + /* + * The 32-bit AABBGGRR format the GDK uses. + */ + static ColorModel nativeModel = new DirectColorModel(32, + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000); + + /** + * Returns a copy of the pixel data as a java array. + */ + private native int[] getPixels(); + + /** + * Sets the pixel data from a java array. + */ + private native void setPixels(int[] pixels); + + /** + * Loads an image using gdk-pixbuf. + */ + private native boolean loadPixbuf(String name); + + /** + * Allocates a Gtk Pixbuf or pixmap + */ + private native void createPixmap(); + + /** + * Frees the above. + */ + private native void freePixmap(); + + /** + * Sets the pixmap to scaled copy of src image. hints are rendering hints. + */ + private native void createScaledPixmap(GtkImage src, int hints); + + /** + * Draws the image, optionally scaled and composited. + */ + private native void drawPixelsScaled (GdkGraphics gc, + int bg_red, int bg_green, int bg_blue, + int x, int y, int width, int height, + boolean composite); + + /** + * Draws the image, optionally scaled flipped and composited. + */ + private native void drawPixelsScaledFlipped (GdkGraphics gc, + int bg_red, int bg_green, + int bg_blue, + boolean flipX, boolean flipY, + int srcX, int srcY, + int srcWidth, int srcHeight, + int dstX, int dstY, + int dstWidth, int dstHeight, + boolean composite); + + /** + * Constructs a GtkImage from an ImageProducer. Asynchronity is handled in + * the following manner: + * A GtkImageConsumer gets the image data, and calls setImage() when + * completely finished. The GtkImage is not considered loaded until the + * GtkImageConsumer is completely finished. We go for all "all or nothing". + */ + public GtkImage (ImageProducer producer) { + isLoaded = false; + observers = new Vector(); source = producer; - this.g = g; + source.startProduction(new GtkImageConsumer(this, source)); + offScreen = false; + } - if (source != null) - source.addConsumer (this); + /** + * Constructs a GtkImage by loading a given file. + * + * @throws IllegalArgumentException if the image could not be loaded. + */ + public GtkImage (String filename) + { + File f = new File(filename); + try + { + if (loadPixbuf(f.getCanonicalPath()) != true) + throw new IllegalArgumentException("Couldn't load image: "+filename); + } + catch(IOException e) + { + throw new IllegalArgumentException("Couldn't load image: "+filename); + } + + isLoaded = true; + observers = null; + offScreen = false; + props = new Hashtable(); } - public void setObserver (ImageObserver observer) + /** + * Constructs an empty GtkImage. + */ + public GtkImage (int width, int height) { - this.observer = observer; + this.width = width; + this.height = height; + props = new Hashtable(); + isLoaded = true; + observers = null; + offScreen = true; + createPixmap(); } - public synchronized int[] - getPixelCache () + /** + * Constructs a scaled version of the src bitmap, using the GDK. + */ + private GtkImage (GtkImage src, int width, int height, int hints) { - return pixelCache; + this.width = width; + this.height = height; + props = new Hashtable(); + isLoaded = true; + observers = null; + offScreen = false; + + // Use the GDK scaling method. + createScaledPixmap(src, hints); } - public synchronized ColorModel - getColorModel () + /** + * Callback from the image consumer. + */ + public void setImage(int width, int height, + int[] pixels, Hashtable properties) { - return model; + this.width = width; + this.height = height; + props = (properties != null) ? properties : new Hashtable(); + isLoaded = true; + deliver(); + createPixmap(); + setPixels(pixels); } - public synchronized int - getWidth (ImageObserver observer) + // java.awt.Image methods //////////////////////////////////////////////// + + public synchronized int getWidth (ImageObserver observer) { - if (width == -1) - widthObservers.addElement (observer); - + if (addObserver(observer)) + return -1; + return width; } - public synchronized int - getHeight (ImageObserver observer) + public synchronized int getHeight (ImageObserver observer) { - if (height == -1) - heightObservers.addElement (observer); + if (addObserver(observer)) + return -1; return height; } - - public ImageProducer - getSource () - { - return source; - } - public Graphics - getGraphics () - { - return g; - } - - public synchronized Object - getProperty (String name, ImageObserver observer) + public synchronized Object getProperty (String name, ImageObserver observer) { - if (props == null) - { - propertyObservers.addElement (observer); - return null; - } + if (addObserver(observer)) + return UndefinedProperty; Object value = props.get (name); return (value == null) ? UndefinedProperty : value; } - public synchronized void - flush () + /** + * Returns the source of this image. + */ + public ImageProducer getSource () { - isLoaded = false; - isCacheable = true; - width = height = -1; - props = null; - pixelCache = null; - model = null; - - if (source != null) - { - source.removeConsumer (this); - source.addConsumer (this); - } + return new MemoryImageSource(width, height, nativeModel, getPixels(), + 0, width); } - public boolean - isLoaded () + /** + * Creates a GdkGraphics context for this pixmap. + */ + public Graphics getGraphics () { - return isLoaded; + if (!isLoaded) + return null; + if (offScreen) + return new GdkGraphics(this); + else + throw new IllegalAccessError("This method only works for off-screen" + +" Images."); } - - /* ImageConsumer methods */ - - public synchronized void - setDimensions (int width, int height) + + /** + * Returns a scaled instance of this pixmap. + */ + public Image getScaledInstance(int width, + int height, + int hints) { - pixelCache = new int[width*height]; + if (width <= 0 || height <= 0) + throw new IllegalArgumentException("Width and height of scaled bitmap"+ + "must be >= 0"); - this.width = width; - this.height = height; - - for (int i = 0; i < widthObservers.size (); i++) - { - ImageObserver io = (ImageObserver) widthObservers.elementAt (i); - if (io != null) - io.imageUpdate (this, ImageObserver.WIDTH, -1, -1, width, height); - } - - for (int i = 0; i < heightObservers.size (); i++) - { - ImageObserver io = (ImageObserver) heightObservers.elementAt (i); - if (io != null) - io.imageUpdate (this, ImageObserver.HEIGHT, -1, -1, width, height); - } - - if (observer != null) - observer.imageUpdate (this, - (ImageObserver.WIDTH - | ImageObserver.HEIGHT), - -1, -1, width, height); + return new GtkImage(this, width, height, hints); } - public synchronized void - setProperties (Hashtable props) + /** + * If the image is loaded and comes from an ImageProducer, + * regenerate the image from there. + * + * I have no idea if this is ever actually used. Since GtkImage can't be + * instantiated directly, how is the user to know if it was created from + * an ImageProducer or not? + */ + public synchronized void flush () { - this.props = props; - - for (int i = 0; i < propertyObservers.size (); i++) + if (isLoaded && source != null) { - ImageObserver io = (ImageObserver) propertyObservers.elementAt (i); - if (io != null) - io.imageUpdate (this, ImageObserver.PROPERTIES, -1, -1, width, height); + observers = new Vector(); + isLoaded = false; + freePixmap(); + source.startProduction(new GtkImageConsumer(this, source)); } } - public synchronized void - setColorModel (ColorModel model) - { - if (this.model == null || this.model.equals(model)) - this.model = model; - else - isCacheable = false; - } - - public synchronized void - setHints (int flags) + public void finalize() { + if (isLoaded) + freePixmap(); } - public synchronized void - setPixels (int x, int y, int width, int height, ColorModel cm, byte[] pixels, - int offset, int scansize) + /** + * Returns the image status, used by GtkToolkit + */ + public int checkImage (ImageObserver observer) { - setPixels (x, y, width, height, cm, convertPixels (pixels), offset, - scansize); + if (addObserver(observer)) + return 0; - if (observer != null) - observer.imageUpdate (this, - ImageObserver.SOMEBITS, - x, y, width, height); + return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT; } - public synchronized void - setPixels (int x, int y, int width, int height, ColorModel cm, int[] pixels, - int offset, int scansize) - { - loading = true; + // Drawing methods //////////////////////////////////////////////// - if (!isCacheable) - return; - - if (!cm.equals(model) || pixelCache == null) + /** + * Draws an image with eventual scaling/transforming. + */ + public boolean drawImage (GdkGraphics g, int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, + Color bgcolor, ImageObserver observer) + { + if (addObserver(observer)) + return false; + + boolean flipX = (dx1 > dx2)^(sx1 > sx2); + boolean flipY = (dy1 > dy2)^(sy1 > sy2); + int dstWidth = Math.abs (dx2 - dx1); + int dstHeight = Math.abs (dy2 - dy1); + int srcWidth = Math.abs (sx2 - sx1); + int srcHeight = Math.abs (sy2 - sy1); + int srcX = (sx1 < sx2) ? sx1 : sx2; + int srcY = (sy1 < sy2) ? sy1 : sy2; + int dstX = (dx1 < dx2) ? dx1 : dx2; + int dstY = (dy1 < dy2) ? dy1 : dy2; + + // Clipping. This requires the dst to be scaled as well, + if (srcWidth + srcX > width) { - isCacheable = false; - return; - } + dstWidth = (int)((double)dstWidth * (double)(width - srcX)/(double)srcWidth); + srcWidth = width - srcX; + } - if (scansize == width && height == 1) - { - // Copy contents of pixels array into pixel cache. - System.arraycopy (pixels, offset, - pixelCache, y * this.width + x, - pixels.length - offset); - } - else // skip over scansize-width for each row + if (srcHeight + srcY > height) { - for (int i = 0; i < height; i++) - System.arraycopy (pixels, offset + (i * scansize), - pixelCache, (y + i) * this.width + x, - width); + dstHeight = (int)((double)dstHeight * (double)(width - srcY)/(double)srcHeight); + srcHeight = height - srcY; } + + if(bgcolor != null) + drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (), + bgcolor.getBlue (), + flipX, flipY, + srcX, srcY, + srcWidth, srcHeight, + dstX, dstY, + dstWidth, dstHeight, + true); + else + drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY, + srcX, srcY, srcWidth, srcHeight, + dstX, dstY, dstWidth, dstHeight, + false); + return true; } - public synchronized void - imageComplete (int status) + /** + * Draws an image to the GdkGraphics context, at (x,y) scaled to + * width and height, with optional compositing with a background color. + */ + public boolean drawImage (GdkGraphics g, int x, int y, int width, int height, + Color bgcolor, ImageObserver observer) { - if (status == ImageConsumer.STATICIMAGEDONE && isCacheable) - isLoaded = true; + if (addObserver(observer)) + return false; - if (status == ImageConsumer.SINGLEFRAME) - isCacheable = false; - - if (observer != null) - { - if (status == ImageConsumer.IMAGEERROR) - observer.imageUpdate (null, - ImageObserver.ERROR, - -1, -1, -1, -1); - else - observer.imageUpdate (null, - ImageObserver.ALLBITS, - -1, -1, -1, -1); - } + if(bgcolor != null) + drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (), + bgcolor.getBlue (), x, y, width, height, true); + else + drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false); - if (source != null && status != ImageConsumer.SINGLEFRAME) - source.removeConsumer (this); + return true; } - public synchronized void - startProduction (GtkImagePainter painter) - { - if (isLoaded) - { - painter.setDimensions (width, height); - painter.setPixels (0, 0, width, height, model, pixelCache, 0, width); - } - else - { - if (source != null) - { - source.startProduction (painter); - source.removeConsumer (painter); - } - } - } + // Private methods //////////////////////////////////////////////// - private int[] - convertPixels (byte[] pixels) + /** + * Delivers notifications to all queued observers. + */ + private void deliver() { - int ret[] = new int[pixels.length]; + int flags = ImageObserver.HEIGHT | + ImageObserver.WIDTH | + ImageObserver.PROPERTIES | + ImageObserver.ALLBITS; - for (int i = 0; i < pixels.length; i++) - ret[i] = pixels[i]; - - return ret; - } + for(int i=0; i < observers.size(); i++) + ((ImageObserver)observers.elementAt(i)). + imageUpdate(this, flags, 0, 0, width, height); - synchronized int - checkImage () + observers = null; + } + + /** + * Adds an observer, if we need to. + * @return true if an observer was added. + */ + private boolean addObserver(ImageObserver observer) { - int bits = 0; - - if (width != -1) - bits |= ImageObserver.WIDTH; - if (height != -1) - bits |= ImageObserver.HEIGHT; - if (props != null) - bits |= ImageObserver.PROPERTIES; - if (loading) - bits |= ImageObserver.SOMEBITS; - if (isLoaded) - bits |= ImageObserver.ALLBITS; - - return bits; + if (!isLoaded) + { + if(observer != null) + if (!observers.contains (observer)) + observers.addElement (observer); + return true; + } + return false; } } diff --git a/gnu/java/awt/peer/gtk/GtkImageConsumer.java b/gnu/java/awt/peer/gtk/GtkImageConsumer.java new file mode 100644 index 000000000..93743fe1a --- /dev/null +++ b/gnu/java/awt/peer/gtk/GtkImageConsumer.java @@ -0,0 +1,155 @@ +/* GtkImageConsumer.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.awt.peer.gtk; + +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.util.Hashtable; +import java.util.Vector; + +/** + * Helper class to GtkImage. Sits and gathers pixels for a GtkImage and then + * calls GtkImage.setImage(). + * + * @author Sven de Marothy + */ +public class GtkImageConsumer implements ImageConsumer +{ + private GtkImage target; + private int width, height; + private Hashtable properties; + private int[] pixelCache = null; + private ImageProducer source; + + public GtkImageConsumer(GtkImage target, ImageProducer source) + { + this.target = target; + this.source = source; + } + + public synchronized void imageComplete (int status) + { + source.removeConsumer(this); + target.setImage(width, height, pixelCache, properties); + } + + public synchronized void setColorModel (ColorModel model) + { + // This method is to inform on what the most used color model + // in the image is, for optimization reasons. We ignore this + // information. + } + + public synchronized void setDimensions (int width, int height) + { + pixelCache = new int[width*height]; + + this.width = width; + this.height = height; + } + + public synchronized void setHints (int flags) + { + // This method informs us in which order the pixels are + // delivered, for progressive-loading support, etc. + // Since we wait until it's all loaded, we can ignore the hints. + } + + public synchronized void setPixels (int x, int y, int width, int height, + ColorModel cm, byte[] pixels, + int offset, int scansize) + { + setPixels (x, y, width, height, cm, convertPixels (pixels), offset, + scansize); + } + + public synchronized void setPixels (int x, int y, int width, int height, + ColorModel cm, int[] pixels, + int offset, int scansize) + { + if (pixelCache == null) + return; // Not sure this should ever happen. + + if (cm.equals(GtkImage.nativeModel)) + for (int i = 0; i < height; i++) + System.arraycopy (pixels, offset + (i * scansize), + pixelCache, (y + i) * this.width + x, + width); + else + { + for (int i = 0; i < height; i++) + for (int j = 0; j < width; j++) + { + // get in AARRGGBB and convert to AABBGGRR + int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]); + byte b = (byte)(pix & 0xFF); + byte r = (byte)(((pix & 0x00FF0000) >> 16) & 0xFF); + pix &= 0xFF00FF00; + pix |= ((b & 0xFF) << 16); + pix |= (r & 0xFF); + pixelCache[(y + i) * this.width + x + j] = pix; + } + } + } + + /** + * This is an old method, no idea if it's correct. + */ + private int[] convertPixels (byte[] pixels) + { + int ret[] = new int[pixels.length]; + + for (int i = 0; i < pixels.length; i++) + ret[i] = pixels[i] & 0xFF; + + return ret; + } + + public synchronized void setProperties (Hashtable props) + { + this.properties = props; + } +} + + diff --git a/gnu/java/awt/peer/gtk/GtkImagePainter.java b/gnu/java/awt/peer/gtk/GtkImagePainter.java deleted file mode 100644 index 9f2ecb7dc..000000000 --- a/gnu/java/awt/peer/gtk/GtkImagePainter.java +++ /dev/null @@ -1,267 +0,0 @@ -/* GtkImagePainter.java - Copyright (C) 1999, 2000 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.java.awt.peer.gtk; - -import java.awt.Color; -import java.awt.Rectangle; -import java.awt.image.ColorModel; -import java.awt.image.ImageConsumer; -import java.awt.image.ImageObserver; -import java.util.Hashtable; - -public class GtkImagePainter implements Runnable, ImageConsumer -{ - GtkImage image; - GdkGraphics gc; - int startX, startY; - int redBG; - int greenBG; - int blueBG; - double affine[]; - int width, height; - boolean flipX, flipY; - Rectangle clip; - int s_width, s_height; - ImageObserver observer; - - public - GtkImagePainter (GtkImage image, GdkGraphics gc, int x, int y, - int width, int height, Color bgcolor, ImageObserver o) - { - this.image = image; - this.gc = (GdkGraphics) gc.create (); - startX = x; - startY = y; - redBG = bgcolor.getRed (); - greenBG = bgcolor.getGreen (); - blueBG = bgcolor.getBlue (); - this.width = width; - this.height = height; - flipX = flipY = false; - s_width = s_height = 0; - clip = null; - observer = o; - - run (); - } - - public - GtkImagePainter (GtkImage image, GdkGraphics gc, - int dx1, int dy1, int dx2, int dy2, - int sx1, int sy1, int sx2, int sy2, - Color bgcolor, ImageObserver o) - { - this.image = image; - this.gc = (GdkGraphics) gc.create (); - startX = (dx1 < dx2) ? dx1 : dx2; - startY = dy1; - redBG = bgcolor.getRed (); - greenBG = bgcolor.getGreen (); - blueBG = bgcolor.getBlue (); - observer = o; - - this.width = Math.abs (dx2 - dx1); - this.height = Math.abs (dy2 - dy1); - - flipX = ((dx1 > dx2 && sx2 > sx1) - || (dx1 < dx2 && sx2 < sx1)); - - flipY = ((dy1 > dy2 && sy2 > sy1) - || (dy1 < dy2 && sy2 < sy1)); - - s_width = Math.abs (sx2 - sx1); - s_height = Math.abs (sy2 - sy1); - clip = new Rectangle (sx1, sy1, s_width, s_height); - - run (); - } - - public void - run () - { - image.startProduction (this); - gc.dispose (); - } - - /* Convert pixel data into a format that gdkrgb can understand */ - static int[] - convertPixels (int[] pixels, ColorModel model) - { - if (pixels == null || model == null) - { - return null; - } - - if (model.equals (ColorModel.getRGBdefault ())) - return pixels; - - int ret[] = new int[pixels.length]; - - for (int i = 0; i < pixels.length; i++) - ret[i] = model.getRGB (pixels[i]); - - return ret; - } - - static int[] - convertPixels (byte[] pixels, ColorModel model) - { - if (pixels == null || model == null) - { - return null; - } - - int ret[] = new int[pixels.length]; - - for (int i = 0; i < pixels.length; i++) - ret[i] = model.getRGB (pixels[i]); - - return ret; - } - - native void - drawPixels (GdkGraphics gc, int bg_red, int bg_green, int bg_blue, - int x, int y, int width, int height, int[] pixels, int offset, - int scansize, double affine[]); - - - public void - setPixels (int x, int y, int width, int height, ColorModel model, - int[] pixels, int offset, int scansize) - { - if (clip != null) - { - Rectangle r; - r = clip.intersection (new Rectangle (x, y, width, height)); - if (r.width == 0 && r.height == 0) - return; - - offset += r.y * scansize + r.x; - - width = r.width; - height = r.height; - x = r.x; - y = r.y; - } - - drawPixels (gc, redBG, greenBG, blueBG, - startX + x, startY + y, - width, height, convertPixels (pixels, model), offset, - scansize, affine); - } - - public void - setPixels (int x, int y, int width, int height, ColorModel model, - byte[] pixels, int offset, int scansize) - { - setPixels (x, y, width, height, ColorModel.getRGBdefault(), - convertPixels (pixels, model), offset, scansize); - } - - public void - setDimensions (int width, int height) - { - if (!flipX && !flipY && - ((this.width == -1 && this.height == -1) - || (this.width == width && this.height == height))) - return; - - affine = new double[6]; - affine[1] = affine[2] = affine[4] = affine[5] = 0; - - if (clip != null) - { - affine[0] = this.width / (double) s_width; - affine[3] = this.height / (double) s_height; - } - else - { - affine[0] = this.width / (double) width; - affine[3] = this.height / (double) height; - } - - if (flipX) - { - affine[0] = -affine[0]; - affine[4] = this.width; - } - - if (flipY) - { - affine[3] = -affine[3]; - affine[5] = this.height; - } - - if (affine[0] == 1 && affine[3] == 1) - affine = null; - } - - public void - setProperties (Hashtable props) - { - } - - public void - setColorModel (ColorModel model) - { - } - - public void - setHints (int flags) - { - } - - public void - imageComplete (int status) - { - image.imageComplete(status); - - if (observer != null) - { - if (status == ImageConsumer.IMAGEERROR) - observer.imageUpdate (null, - ImageObserver.ERROR, - -1, -1, -1, -1); - else - observer.imageUpdate (null, - ImageObserver.ALLBITS, - -1, -1, -1, -1); - } - } -} diff --git a/gnu/java/awt/peer/gtk/GtkOffScreenImage.java b/gnu/java/awt/peer/gtk/GtkOffScreenImage.java deleted file mode 100644 index 786c4b449..000000000 --- a/gnu/java/awt/peer/gtk/GtkOffScreenImage.java +++ /dev/null @@ -1,93 +0,0 @@ -/* GtkOffScreenImage.java - Copyright (C) 1999 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.java.awt.peer.gtk; - -import java.awt.Graphics; -import java.awt.Image; -import java.awt.image.ImageObserver; -import java.awt.image.ImageProducer; - -public class GtkOffScreenImage extends Image -{ - int width, height; - ImageProducer source; - Graphics g; - - public GtkOffScreenImage (ImageProducer source, Graphics g, - int width, int height) - { - this.width = width; - this.height = height; - - this.source = source; - this.g = g; - } - - public int getWidth (ImageObserver observer) - { - return width; - } - - public int getHeight (ImageObserver observer) - { - return height; - } - - public ImageProducer getSource () - { - return source; - } - - public Graphics getGraphics () - { - if (g instanceof GdkGraphics2D) - return new GdkGraphics2D ((GdkGraphics2D) this.g); - else - return new GdkGraphics ((GdkGraphics) this.g); - } - - public Object getProperty (String name, ImageObserver observer) - { - return Image.UndefinedProperty; - } - - public void flush () - { - } -} diff --git a/gnu/java/awt/peer/gtk/GtkToolkit.java b/gnu/java/awt/peer/gtk/GtkToolkit.java index 3bbbe27ac..5c0ab5438 100644 --- a/gnu/java/awt/peer/gtk/GtkToolkit.java +++ b/gnu/java/awt/peer/gtk/GtkToolkit.java @@ -53,6 +53,7 @@ import java.awt.font.FontRenderContext; import java.awt.im.InputMethodHighlight; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; import java.awt.image.ImageConsumer; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; @@ -140,9 +141,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit | ImageObserver.HEIGHT; if (image instanceof GtkImage) - { - status = ((GtkImage) image).checkImage (); - } + return ((GtkImage) image).checkImage (observer); if (observer != null) observer.imageUpdate (image, status, @@ -250,12 +249,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit if (useGraphics2D()) return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (filename)); else - { - GdkPixbufDecoder d = new GdkPixbufDecoder (filename); - GtkImage image = new GtkImage (d, null); - d.startProduction (image); - return image; - } + return new GtkImage (filename); } public Image createImage (URL url) @@ -265,8 +259,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit else { GdkPixbufDecoder d = new GdkPixbufDecoder (url); - GtkImage image = new GtkImage (d, null); - d.startProduction (image); + GtkImage image = new GtkImage (d); return image; } } @@ -276,11 +269,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit if (useGraphics2D()) return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (producer)); else - { - GtkImage image = new GtkImage (producer, null); - producer.startProduction (image); - return image; - } + return new GtkImage (producer); } public Image createImage (byte[] imagedata, int imageoffset, @@ -295,8 +284,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit GdkPixbufDecoder d = new GdkPixbufDecoder (imagedata, imageoffset, imagelength); - GtkImage image = new GtkImage (d, null); - d.startProduction (image); + GtkImage image = new GtkImage (d); return image; } } @@ -312,9 +300,18 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit return new GdkPixbufDecoder(url); } + /** + * Returns the native color model (which isn't the same as the default + * ARGB color model, but doesn't have to be). + */ public ColorModel getColorModel () { - return ColorModel.getRGBdefault (); + /* Return the GDK-native ABGR format */ + return new DirectColorModel(32, + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000); } public String[] getFontList () @@ -410,34 +407,13 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit public boolean prepareImage (Image image, int width, int height, ImageObserver observer) { + /* GtkImages are always prepared, as long as they're loaded. */ if (image instanceof GtkImage) - { - GtkImage i = (GtkImage) image; - - if (i.isLoaded ()) return true; - - class PrepareImage extends Thread - { - GtkImage image; - ImageObserver observer; - - PrepareImage (GtkImage image, ImageObserver observer) - { - this.image = image; - image.setObserver (observer); - } - - public void run () - { - image.source.startProduction (image); - } - } - - new PrepareImage (i, observer).start (); - return false; - } - else - return true; + return ((((GtkImage)image).checkImage (observer) & + ImageObserver.ALLBITS) != 0); + + /* Assume anything else is too */ + return true; } public native void sync(); |