diff options
33 files changed, 3056 insertions, 3328 deletions
@@ -1,3 +1,65 @@ +2006-05-29 Sven de Marothy <sven@physto.se> + + * gnu/java/awt/peer/gtk/BufferedImageGraphics.java + * gnu/java/awt/peer/gtk/CairoGraphics2D.java + * gnu/java/awt/peer/gtk/CairoSurface.java + * gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java + * gnu/java/awt/peer/gtk/ComponentGraphics.java + * include/gnu_java_awt_peer_gtk_CairoGraphics2D.h + * include/gnu_java_awt_peer_gtk_CairoSurface.h + * include/gnu_java_awt_peer_gtk_ComponentGraphics.h + * native/jni/gtk-peer/cairographics2d.h + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c + New files. + + * gnu/java/awt/peer/gtk/GdkGraphics2D.java + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c + * include/gnu_java_awt_peer_gtk_GdkGraphics2D.h + Removed + + * include/gnu_java_awt_peer_gtk_GdkFontPeer.h + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c + * gnu/java/awt/peer/gtk/GdkFontPeer.java + (releasePeerGraphicsResource): Moved to Font peer class. + + * gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java + (createGraphics): Use new context classes. + + * gnu/java/awt/peer/gtk/GdkPixbufDecoder.java: + Use native BufferedImages where possible. + + * gnu/java/awt/peer/gtk/GdkTextLayout.java + * include/gnu_java_awt_peer_gtk_GdkTextLayout.h + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c + Move GdkGraphics2D.drawGdkTextLayout to the GdkTextLayout class, + renamed to cairoDrawGdkTextLayout. + + * gnu/java/awt/peer/gtk/GtkComponentPeer.java + (getGraphics): Use ComponentGraphics context. + (createImage): Use native BufferedImage. + + * gnu/java/awt/peer/gtk/GtkImage.java: + * include/gnu_java_awt_peer_gtk_GtkImage.h + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c + Remove pixmap support. (GtkImage(int, int) constructor, getGraphics) + Remove drawing methods. + + * gnu/java/awt/print/JavaPrinterGraphics.java: + Use CairoSurface instead of GtkImage. + + * include/Makefile.am + * native/jni/gtk-peer/Makefile.am + Update for new files. + + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c + Remove superfluous GtkImage code for GdkPixmaps. + + * native/jni/gtk-peer/gtkpeer.h + Remove graphics2d structure. + 2006-05-29 Mark Wielaard <mark@klomp.org> * java/io/ObjectStreamConstants.java: Removed double declaration diff --git a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java new file mode 100644 index 000000000..e94d31c3b --- /dev/null +++ b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java @@ -0,0 +1,185 @@ +/* BufferedImageGraphics.java + Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.RenderedImage; +import java.awt.image.ImageObserver; + +/** + * Implementation of Graphics2D on a Cairo surface. + * + * Simutanously maintains a CairoSurface and updates the + * BufferedImage from that after each drawing operation. + */ +public class BufferedImageGraphics extends CairoGraphics2D +{ + /** + * the buffered Image. + */ + private BufferedImage image; + + /** + * Image size. + */ + private int imageWidth, imageHeight; + + /** + * The cairo surface that we actually draw on. + */ + private CairoSurface surface; + + /** + * Its corresponding cairo_t. + */ + private long cairo_t; + + public BufferedImageGraphics(BufferedImage bi) + { + this.image = bi; + imageWidth = bi.getWidth(); + imageHeight = bi.getHeight(); + + surface = new CairoSurface( imageWidth, imageHeight ); + cairo_t = surface.newCairoContext(); + + DataBuffer db = bi.getRaster().getDataBuffer(); + int[] pixels; + // get pixels + + if(db instanceof CairoSurface) + pixels = ((CairoSurface)db).getPixels(imageWidth * imageHeight * 4); + else + pixels = CairoGraphics2D.findSimpleIntegerArray (image.getColorModel(), + image.getData()); + surface.setPixels( pixels ); + + setup( cairo_t ); + setClip(0, 0, imageWidth, imageHeight); + } + + private BufferedImageGraphics(BufferedImageGraphics copyFrom) + { + + cairo_t = surface.newCairoContext(); + copy( copyFrom, cairo_t ); + setClip(0, 0, surface.width, surface.height); + } + + /** + * Update a rectangle of the bufferedImage. This can be improved upon a lot. + */ + private void updateBufferedImage(int x, int y, int width, int height) + { + int[] pixels = surface.getPixels(imageWidth * imageHeight * 4); + + int index = 0; + for (int j = y; j < y + height; ++j) + for (int i = x; i < x + width; ++i) + image.setRGB(i, j, pixels[ i + j*imageWidth ]); + } + + /** + * Abstract methods. + */ + public Graphics create() + { + return new BufferedImageGraphics( this ); + } + + public GraphicsConfiguration getDeviceConfiguration() + { + return null; + } + + public void copyArea(int x, int y, int width, int height, int dx, int dy) + { + // FIXME + } + + /** + * Overloaded methods that do actual drawing need to enter the gdk threads + * and also do certain things before and after. + */ + public void draw(Shape s) + { + super.draw(s); + Rectangle r = s.getBounds(); + updateBufferedImage(r.x, r.y, r.width, r.height); + } + + public void fill(Shape s) + { + super.fill(s); + Rectangle r = s.getBounds(); + updateBufferedImage(r.x, r.y, r.width, r.height); + } + + public void drawRenderedImage(RenderedImage image, AffineTransform xform) + { + super.drawRenderedImage(image, xform); + updateBufferedImage(0, 0, imageWidth, imageHeight); + } + + 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; + } + + public void drawGlyphVector(GlyphVector gv, float x, float y) + { + super.drawGlyphVector(gv, x, y); + Rectangle r = gv.getPixelBounds(getFontRenderContext(), x , y); + updateBufferedImage(r.x, r.y, r.width, r.height); + } +} diff --git a/gnu/java/awt/peer/gtk/GdkGraphics2D.java b/gnu/java/awt/peer/gtk/CairoGraphics2D.java index ff3555015..204805cce 100644 --- a/gnu/java/awt/peer/gtk/GdkGraphics2D.java +++ b/gnu/java/awt/peer/gtk/CairoGraphics2D.java @@ -1,5 +1,5 @@ -/* GdkGraphics2D.java -- - Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +/* CairoGraphics2D.java -- + Copyright (C) 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -58,17 +58,20 @@ import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Stroke; +import java.awt.Polygon; import java.awt.TexturePaint; import java.awt.Toolkit; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; +import java.awt.geom.Line2D; import java.awt.geom.GeneralPath; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; @@ -92,77 +95,136 @@ import java.util.HashMap; import java.util.Map; import java.util.Stack; -public class GdkGraphics2D extends Graphics2D +/** + * This is an abstract implementation of Graphics2D on Cairo. + * + * It should be subclassed for different Cairo contexts. + * + * Note for subclassers: Apart from the constructor (see comments below), + * The following abstract methods must be implemented: + * + * Graphics create() + * GraphicsConfiguration getDeviceConfiguration() + * copyArea(int x, int y, int width, int height, int dx, int dy) + * + * Also, dispose() must be overloaded to free any native datastructures + * used by subclass and in addition call super.dispose() to free the + * native cairographics2d structure and cairo_t. + * + * @author Sven de Marothy + */ +public abstract class CairoGraphics2D extends Graphics2D { - ////////////////////////////////////// - ////// State Management Methods ////// - ////////////////////////////////////// - static { if (Configuration.INIT_LOAD_LIBRARY) System.loadLibrary("gtkpeer"); - - initStaticState(); } - - static native void initStaticState(); - - private final int native_state = GtkGenericPeer.getUniqueInteger(); - // These are package-private to avoid accessor methods. + /** + * Important: This is a pointer to the native cairographics2d structure + * + * DO NOT CHANGE WITHOUT CHANGING NATIVE CODE. + */ + long nativePointer; + + // Drawing state variables + /** + * The current paint + */ Paint paint; + + /** + * The current stroke + */ Stroke stroke; - Color fg; - Color bg; + + /* + * Current foreground and background color. + */ + Color fg, bg; + + /** + * Current clip shape. + */ Shape clip; + + /** + * Current transform. + */ AffineTransform transform; - private GtkComponentPeer component; - // This is package-private to avoid an accessor method. + + /** + * Current font. + */ Font font; - private RenderingHints hints; - private BufferedImage bimage; - private boolean pixelConversionRequired; - private int[] pixelBuffer; - // This is package-private to avoid an accessor method. + + /** + * The current compositing context, if any. + */ Composite comp; - private Stack stateStack; - private native void initState(GtkComponentPeer component); - private native void initState(int width, int height); - private native void initState(int[] pixes, int width, int height); - private native void copyState(GdkGraphics2D g); - public native void dispose(); - private native void cairoSurfaceSetFilter(int filter); + /** + * Rendering hint map. + */ + private RenderingHints hints; - public void finalize() - { - dispose(); - } + /** + * Some operations (drawing rather than filling) require that their + * coords be shifted to land on 0.5-pixel boundaries, in order to land on + * "middle of pixel" coordinates and light up complete pixels. + */ + private boolean shiftDrawCalls = false; + + /** + * Keep track if the first clip to be set, which is restored on setClip(null); + */ + private boolean firstClip = true; + private Shape originalClip; + + /** + * Stroke used for 3DRects + */ + private static BasicStroke draw3DRectStroke = new BasicStroke(); - public Graphics create() + /** + * Constructor does nothing. + */ + public CairoGraphics2D() { - return new GdkGraphics2D(this); } - public Graphics create(int x, int y, int width, int height) - { - return new GdkGraphics2D(this, x, y, width, height); + /** + * Sets up the default values and allocates the native cairographics2d structure + * @param cairo_t_pointer, a native pointer to a cairo_t of the context. + */ + public void setup(long cairo_t_pointer) + { + nativePointer = init(cairo_t_pointer); + setRenderingHints(new RenderingHints(getDefaultHints())); + font = new Font("SansSerif", Font.PLAIN, 12); + setColor(Color.black); + setBackground(Color.white); + setPaint(Color.black); + setStroke(new BasicStroke()); + setTransform(new AffineTransform()); } - GdkGraphics2D(GdkGraphics2D g) + /** + * Same as above, but copies the state of another CairoGraphics2D. + */ + public void copy(CairoGraphics2D g, long cairo_t_pointer) { - Color foreground; - + nativePointer = init(cairo_t_pointer); paint = g.paint; stroke = g.stroke; setRenderingHints(g.hints); if (g.fg.getAlpha() != -1) - foreground = new Color(g.fg.getRed(), g.fg.getGreen(), g.fg.getBlue(), + fg = new Color(g.fg.getRed(), g.fg.getGreen(), g.fg.getBlue(), g.fg.getAlpha()); else - foreground = new Color(g.fg.getRGB()); + fg = new Color(g.fg.getRGB()); if (g.bg != null) { @@ -184,431 +246,244 @@ public class GdkGraphics2D extends Graphics2D transform = new AffineTransform(g.transform); font = g.font; - component = g.component; - copyState(g); - setColor(foreground); + setColor(fg); setBackground(bg); setPaint(paint); setStroke(stroke); setTransform(transform); setClip(clip); - stateStack = new Stack(); - } - - GdkGraphics2D(GdkGraphics2D g, int x, int y, int widht, int height) - { - this(g); - translate(x, y); - clipRect(0, 0, widht, height); } - GdkGraphics2D(int width, int height) - { - initState(width, height); - - setColor(Color.black); - setBackground(new Color(0, 0, 0, 0)); - setPaint(getColor()); - setFont(new Font("SansSerif", Font.PLAIN, 12)); - setTransform(new AffineTransform()); - setStroke(new BasicStroke()); - setRenderingHints(getDefaultHints()); - - stateStack = new Stack(); - } - - GdkGraphics2D(GtkComponentPeer component) + /** + * Generic destructor - call the native dispose() method. + */ + public void finalize() { - this.component = component; - - initComponentGraphics2D(); + dispose(); } - void initComponentGraphics2D() - { - initState(component); - - setColor(component.awtComponent.getForeground()); - setBackground(component.awtComponent.getBackground()); - setPaint(getColor()); - setTransform(new AffineTransform()); - setStroke(new BasicStroke()); - setRenderingHints(getDefaultHints()); - setFont(new Font("SansSerif", Font.PLAIN, 12)); - - stateStack = new Stack(); + /** + * Disposes the native cairographics2d structure, including the + * cairo_t and any gradient stuff, if allocated. + * Subclasses should of course overload and call this if + * they have additional native structures. + */ + public void dispose() + { + disposeNative(); + nativePointer = 0; } - GdkGraphics2D(BufferedImage bimage) - { - this.bimage = bimage; - this.pixelBuffer = findSimpleIntegerArray(bimage.getColorModel(), - bimage.getRaster()); - if (this.pixelBuffer == null) - { - this.pixelBuffer = new int[bimage.getRaster().getWidth() * bimage.getRaster() - .getHeight()]; - this.pixelConversionRequired = true; - } - else - { - this.pixelConversionRequired = false; - } - - initState(this.pixelBuffer, bimage.getWidth(), bimage.getHeight()); + /** + * Allocate the cairographics2d structure and set the cairo_t pointer in it. + * @param pointer - a cairo_t pointer, casted to a long. + */ + private native long init(long pointer); - setColor(Color.black); - setBackground(new Color(0, 0, 0, 0)); - setPaint(getColor()); - setFont(new Font("SansSerif", Font.PLAIN, 12)); - setTransform(new AffineTransform()); - setStroke(new BasicStroke()); - setRenderingHints(getDefaultHints()); + /** + * These are declared abstract as there may be context-specific issues. + */ + public abstract Graphics create(); - stateStack = new Stack(); + public abstract GraphicsConfiguration getDeviceConfiguration(); - // draw current buffered image to the pixmap associated - // with it, if the image is not equal to our paint buffer. - if (pixelConversionRequired) - drawImage(bimage, new AffineTransform(1, 0, 0, 1, 0, 0), bg, null); - } + public abstract void copyArea(int x, int y, int width, int height, int dx, int dy); - //////////////////////////////////// - ////// Native Drawing Methods ////// - //////////////////////////////////// + ////// Native Methods //////////////////////////////////////////////////// - // GDK drawing methods - private native void gdkDrawDrawable(GdkGraphics2D other, int x, int y); + /** + * Dispose of allocate native resouces. + */ + public native void disposeNative(); - // drawing utility methods + /** + * Draw pixels as an RGBA int matrix + * @param w, h - width and height + * @param stride - stride of the array width + * @param i2u - affine transform array + */ private native void drawPixels(int[] pixels, int w, int h, int stride, double[] i2u); - private native void setTexturePixels(int[] pixels, int w, int h, int stride); + private native void setGradient(double x1, double y1, double x2, double y2, int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2, boolean cyclic); - // simple passthroughs to cairo - private native void cairoSave(); - private native void cairoRestore(); + private native void setTexturePixels(int[] pixels, int w, int h, int stride); + + /** + * Set the current transform matrix + */ private native void cairoSetMatrix(double[] m); + + /** + * Set the compositing operator + */ private native void cairoSetOperator(int cairoOperator); + + /** + * Sets the current color in RGBA as a 0.0-1.0 double + */ private native void cairoSetRGBAColor(double red, double green, double blue, double alpha); - private native void cairoSetFillRule(int cairoFillRule); - private native void cairoSetLineWidth(double width); - private native void cairoSetLineCap(int cairoLineCap); - private native void cairoSetLineJoin(int cairoLineJoin); - private native void cairoSetDash(double[] dashes, int ndash, double offset); - private native void cairoSetMiterLimit(double limit); - private native void cairoNewPath(); - private native void cairoMoveTo(double x, double y); - private native void cairoLineTo(double x, double y); - private native void cairoCurveTo(double x1, double y1, double x2, double y2, - double x3, double y3); - private native void cairoRelMoveTo(double dx, double dy); - private native void cairoRelLineTo(double dx, double dy); - private native void cairoRelCurveTo(double dx1, double dy1, double dx2, - double dy2, double dx3, double dy3); - private native void cairoRectangle(double x, double y, double width, - double height); - private native void cairoClosePath(); - private native void cairoStroke(); - private native void cairoFill(); - private native void cairoClip(); - - ///////////////////////////////////////////// - ////// General Drawing Support Methods ////// - ///////////////////////////////////////////// - - private class DrawState - { - private Paint paint; - private Stroke stroke; - private Color fg; - private Color bg; - private Shape clip; - private AffineTransform transform; - private Font font; - private Composite comp; - - DrawState(GdkGraphics2D g) - { - this.paint = g.paint; - this.stroke = g.stroke; - this.fg = g.fg; - this.bg = g.bg; - this.clip = g.clip; - if (g.transform != null) - this.transform = (AffineTransform) g.transform.clone(); - this.font = g.font; - this.comp = g.comp; - } - - public void restore(GdkGraphics2D g) - { - g.paint = this.paint; - g.stroke = this.stroke; - g.fg = this.fg; - g.bg = this.bg; - g.clip = this.clip; - g.transform = this.transform; - g.font = this.font; - g.comp = this.comp; - } - } - - private void stateSave() - { - stateStack.push(new DrawState(this)); - cairoSave(); - } - - private void stateRestore() - { - ((DrawState) (stateStack.pop())).restore(this); - cairoRestore(); - } - - // Some operations (drawing rather than filling) require that their - // coords be shifted to land on 0.5-pixel boundaries, in order to land on - // "middle of pixel" coordinates and light up complete pixels. - private boolean shiftDrawCalls = false; - - private double shifted(double coord, boolean doShift) - { - if (doShift) - return Math.floor(coord) + 0.5; - else - return coord; - } - - private void walkPath(PathIterator p, boolean doShift) - { - double x = 0; - double y = 0; - double[] coords = new double[6]; - - cairoSetFillRule(p.getWindingRule()); - for (; ! p.isDone(); p.next()) - { - int seg = p.currentSegment(coords); - switch (seg) - { - case PathIterator.SEG_MOVETO: - x = shifted(coords[0], doShift); - y = shifted(coords[1], doShift); - cairoMoveTo(x, y); - break; - case PathIterator.SEG_LINETO: - x = shifted(coords[0], doShift); - y = shifted(coords[1], doShift); - cairoLineTo(x, y); - break; - case PathIterator.SEG_QUADTO: - // splitting a quadratic bezier into a cubic: - // see: http://pfaedit.sourceforge.net/bezier.html - double x1 = x + (2.0 / 3.0) * (shifted(coords[0], doShift) - x); - double y1 = y + (2.0 / 3.0) * (shifted(coords[1], doShift) - y); - - double x2 = x1 + (1.0 / 3.0) * (shifted(coords[2], doShift) - x); - double y2 = y1 + (1.0 / 3.0) * (shifted(coords[3], doShift) - y); - - x = shifted(coords[2], doShift); - y = shifted(coords[3], doShift); - cairoCurveTo(x1, y1, x2, y2, x, y); - break; - case PathIterator.SEG_CUBICTO: - x = shifted(coords[4], doShift); - y = shifted(coords[5], doShift); - cairoCurveTo(shifted(coords[0], doShift), - shifted(coords[1], doShift), - shifted(coords[2], doShift), - shifted(coords[3], doShift), x, y); - break; - case PathIterator.SEG_CLOSE: - cairoClosePath(); - break; - } - } - } - - private Map getDefaultHints() - { - HashMap defaultHints = new HashMap(); - - defaultHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, - RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); + /** + * Sets the current winding rule in Cairo + */ + private native void cairoSetFillRule(int cairoFillRule); - defaultHints.put(RenderingHints.KEY_STROKE_CONTROL, - RenderingHints.VALUE_STROKE_DEFAULT); + /** + * Set the line style, cap, join and miter limit. + * Cap and join parameters are in the BasicStroke enumerations. + */ + private native void cairoSetLine(double width, int cap, int join, double miterLimit); - defaultHints.put(RenderingHints.KEY_FRACTIONALMETRICS, - RenderingHints.VALUE_FRACTIONALMETRICS_OFF); + /** + * Set the dash style + */ + private native void cairoSetDash(double[] dashes, int ndash, double offset); - defaultHints.put(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_OFF); + /* + * Draws a Glyph Vector + */ + native void cairoDrawGlyphVector(GdkFontPeer font, + float x, float y, int n, + int[] codes, float[] positions); - defaultHints.put(RenderingHints.KEY_RENDERING, - RenderingHints.VALUE_RENDER_DEFAULT); - return defaultHints; - } + private native void cairoRelCurveTo(double dx1, double dy1, double dx2, + double dy2, double dx3, double dy3); - public static int[] findSimpleIntegerArray (ColorModel cm, Raster raster) - { - if (cm == null || raster == null) - return null; + /** + * Appends a rectangle to the current path + */ + private native void cairoRectangle(double x, double y, double width, + double height); - if (! cm.getColorSpace().isCS_sRGB()) - return null; + /** + * New current path + */ + private native void cairoNewPath(); - if (! (cm instanceof DirectColorModel)) - return null; + /** + * Close current path + */ + private native void cairoClosePath(); - DirectColorModel dcm = (DirectColorModel) cm; + /** moveTo */ + private native void cairoMoveTo(double x, double y); - if (dcm.getRedMask() != 0x00FF0000 || dcm.getGreenMask() != 0x0000FF00 - || dcm.getBlueMask() != 0x000000FF) - return null; + /** relative moveTo */ + private native void cairoRelMoveTo(double dx, double dy); - if (! (raster instanceof WritableRaster)) - return null; + /** lineTo */ + private native void cairoLineTo(double x, double y); - if (raster.getSampleModel().getDataType() != DataBuffer.TYPE_INT) - return null; + /** relative lineTo */ + private native void cairoRelLineTo(double dx, double dy); - if (! (raster.getDataBuffer() instanceof DataBufferInt)) - return null; + /** Cubic curve-to */ + private native void cairoCurveTo(double x1, double y1, double x2, double y2, + double x3, double y3); - DataBufferInt db = (DataBufferInt) raster.getDataBuffer(); + /** + * Stroke current path + */ + private native void cairoStroke(); - if (db.getNumBanks() != 1) - return null; + /** + * Fill current path + */ + private native void cairoFill(); - // Finally, we have determined that this is a single bank, [A]RGB-int - // buffer in sRGB space. It's worth checking all this, because it means - // that cairo can paint directly into the data buffer, which is very - // fast compared to all the normal copying and converting. + /** + * Clip current path + */ + private native void cairoClip(); - return db.getData(); - } + /** + * Set interpolation types + */ + private native void cairoSurfaceSetFilter(int filter); - private void updateBufferedImage() + ///////////////////////// TRANSFORMS /////////////////////////////////// + /** + * Set the current transform + */ + public void setTransform(AffineTransform tx) { - if (bimage != null && pixelConversionRequired) + transform = tx; + if (transform != null) { - int height = bimage.getHeight(); - int width = bimage.getWidth(); - int index = 0; - for (int y = 0; y < height; ++y) - for (int x = 0; x < width; ++x) - bimage.setRGB(x, y, pixelBuffer[index++]); + double[] m = new double[6]; + transform.getMatrix(m); + cairoSetMatrix(m); } } - - private boolean drawImage(Image img, AffineTransform xform, - Color bgcolor, ImageObserver obs) + + public void transform(AffineTransform tx) { - if (img == null) - return false; - - // 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 + if (transform == null) + transform = new AffineTransform(tx); + else + transform.concatenate(tx); + setTransform(transform); + if (clip != null) { - // In this case, xform is an AffineTransform that transforms bounding - // box of the specified image from image space to user space. However - // when we pass this transform to cairo, cairo will use this transform - // to map "user coordinates" to "pixel" coordinates, which is the - // other way around. Therefore to get the "user -> pixel" transform - // that cairo wants from "image -> user" transform that we currently - // have, we will need to invert the transformation matrix. - AffineTransform invertedXform = new AffineTransform(); - + // FIXME: this should actuall try to transform the shape + // rather than degrade to bounds. + Rectangle2D r = clip.getBounds2D(); + double[] coords = new double[] + { + r.getX(), r.getY(), r.getX() + r.getWidth(), + r.getY() + r.getHeight() + }; try { - invertedXform = xform.createInverse(); - if (img instanceof BufferedImage) - { - // draw an image which has actually been loaded - // into memory fully - BufferedImage b = (BufferedImage) img; - return drawRaster(b.getColorModel(), b.getTile(0, 0), - invertedXform, bgcolor); - } - else - return this.drawImage(GdkPixbufDecoder.createBufferedImage(img - .getSource()), - xform, bgcolor, obs); + tx.createInverse().transform(coords, 0, coords, 0, 2); + r.setRect(coords[0], coords[1], coords[2] - coords[0], + coords[3] - coords[1]); + clip = r; } - catch (NoninvertibleTransformException e) + catch (java.awt.geom.NoninvertibleTransformException e) { - throw new ImagingOpException("Unable to invert transform " - + xform.toString()); } } } - ////////////////////////////////////////////////// - ////// Implementation of Graphics2D Methods ////// - ////////////////////////////////////////////////// - - public void draw(Shape s) + public void rotate(double theta) { - if (stroke != null && ! (stroke instanceof BasicStroke)) - { - fill(stroke.createStrokedShape(s)); - return; - } - - cairoNewPath(); + transform(AffineTransform.getRotateInstance(theta)); + } - if (s instanceof Rectangle2D) - { - Rectangle2D r = (Rectangle2D) s; - cairoRectangle(shifted(r.getX(), shiftDrawCalls), - shifted(r.getY(), shiftDrawCalls), r.getWidth(), - r.getHeight()); - } - else - walkPath(s.getPathIterator(null), shiftDrawCalls); - cairoStroke(); + public void rotate(double theta, double x, double y) + { + transform(AffineTransform.getRotateInstance(theta, x, y)); + } - updateBufferedImage(); + public void scale(double sx, double sy) + { + transform(AffineTransform.getScaleInstance(sx, sy)); } - public void fill(Shape s) + public void translate(double tx, double ty) { - cairoNewPath(); - if (s instanceof Rectangle2D) - { - Rectangle2D r = (Rectangle2D) s; - cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - else - walkPath(s.getPathIterator(null), false); + transform(AffineTransform.getTranslateInstance(tx, ty)); + } - cairoFill(); + public void translate(int x, int y) + { + translate((double) x, (double) y); + } - updateBufferedImage(); + public void shear(double shearX, double shearY) + { + transform(AffineTransform.getShearInstance(shearX, shearY)); } + ///////////////////////// DRAWING STATE /////////////////////////////////// + public void clip(Shape s) { // update it @@ -635,7 +510,6 @@ public class GdkGraphics2D extends Graphics2D else walkPath(clip.getPathIterator(null), false); - // cairoClosePath (); cairoClip(); } } @@ -693,102 +567,6 @@ public class GdkGraphics2D extends Graphics2D throw new java.lang.UnsupportedOperationException(); } - public void setTransform(AffineTransform tx) - { - transform = tx; - if (transform != null) - { - double[] m = new double[6]; - transform.getMatrix(m); - cairoSetMatrix(m); - } - } - - public void transform(AffineTransform tx) - { - if (transform == null) - transform = new AffineTransform(tx); - else - transform.concatenate(tx); - setTransform(transform); - if (clip != null) - { - // FIXME: this should actuall try to transform the shape - // rather than degrade to bounds. - Rectangle2D r = clip.getBounds2D(); - double[] coords = new double[] - { - r.getX(), r.getY(), r.getX() + r.getWidth(), - r.getY() + r.getHeight() - }; - try - { - tx.createInverse().transform(coords, 0, coords, 0, 2); - r.setRect(coords[0], coords[1], coords[2] - coords[0], - coords[3] - coords[1]); - clip = r; - } - catch (java.awt.geom.NoninvertibleTransformException e) - { - } - } - } - - public void rotate(double theta) - { - transform(AffineTransform.getRotateInstance(theta)); - } - - public void rotate(double theta, double x, double y) - { - transform(AffineTransform.getRotateInstance(theta, x, y)); - } - - public void scale(double sx, double sy) - { - transform(AffineTransform.getScaleInstance(sx, sy)); - } - - /** - * Translate the system of the co-ordinates. As translation is a frequent - * operation, it is done in an optimised way, unlike scaling and rotating. - */ - public void translate(double tx, double ty) - { - // 200 -> 140 - if (transform != null) - transform.translate(tx, ty); - else - transform = AffineTransform.getTranslateInstance(tx, ty); - - if (clip != null) - { - // FIXME: this should actuall try to transform the shape - // rather than degrade to bounds. - Rectangle2D r; - - if (clip instanceof Rectangle2D) - r = (Rectangle2D) clip; - else - r = clip.getBounds2D(); - - r.setRect(r.getX() - tx, r.getY() - ty, r.getWidth(), r.getHeight()); - clip = r; - } - - setTransform(transform); - } - - public void translate(int x, int y) - { - translate((double) x, (double) y); - } - - public void shear(double shearX, double shearY) - { - transform(AffineTransform.getShearInstance(shearX, shearY)); - } - public Stroke getStroke() { return stroke; @@ -800,10 +578,9 @@ public class GdkGraphics2D extends Graphics2D if (stroke instanceof BasicStroke) { BasicStroke bs = (BasicStroke) stroke; - cairoSetLineCap(bs.getEndCap()); - cairoSetLineWidth(bs.getLineWidth()); - cairoSetLineJoin(bs.getLineJoin()); - cairoSetMiterLimit(bs.getMiterLimit()); + cairoSetLine(bs.getLineWidth(), bs.getEndCap(), + bs.getLineJoin(), bs.getMiterLimit()); + float[] dashes = bs.getDashArray(); if (dashes != null) { @@ -818,10 +595,6 @@ public class GdkGraphics2D extends Graphics2D } } - //////////////////////////////////////////////// - ////// Implementation of Graphics Methods ////// - //////////////////////////////////////////////// - public void setPaintMode() { setComposite(AlphaComposite.SrcOver); @@ -836,9 +609,6 @@ public class GdkGraphics2D extends Graphics2D { if (c == null) c = Color.BLACK; - - if (c.equals(fg)) - return; fg = c; paint = c; @@ -899,76 +669,32 @@ public class GdkGraphics2D extends Graphics2D } public void setClip(Shape s) - { + { clip = s; - if (clip == null) - { - // Reset clipping. - if (component != null) - { - Dimension d = component.awtComponent.getSize(); - setClip(0, 0, d.width, d.height); - } - } - else - { - cairoNewPath(); - if (s instanceof Rectangle2D) - { - Rectangle2D r = (Rectangle2D) s; - cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - else - walkPath(s.getPathIterator(null), false); - // cairoClosePath (); - cairoClip(); + // The first time the clip is set, save it as the original clip to reset to on + // s == null. We can rely on this being non-null because the constructor in + // subclasses is expected to set the initial clip properly. + if( firstClip ) + { + originalClip = s; + firstClip = false; } - } - - private static BasicStroke draw3DRectStroke = new BasicStroke(); - - public void draw3DRect(int x, int y, int width, int height, boolean raised) - { - Stroke tmp = stroke; - setStroke(draw3DRectStroke); - super.draw3DRect(x, y, width, height, raised); - setStroke(tmp); - updateBufferedImage(); - } - - public void fill3DRect(int x, int y, int width, int height, boolean raised) - { - Stroke tmp = stroke; - setStroke(draw3DRectStroke); - super.fill3DRect(x, y, width, height, raised); - setStroke(tmp); - updateBufferedImage(); - } - public void drawRect(int x, int y, int width, int height) - { - draw(new Rectangle(x, y, width, height)); - } + if (s == null) + clip = originalClip; - public void fillRect(int x, int y, int width, int height) - { cairoNewPath(); - cairoRectangle(x, y, width, height); - cairoFill(); - } - - public void clearRect(int x, int y, int width, int height) - { - if (bg != null) - cairoSetRGBAColor(bg.getRed() / 255.0, bg.getGreen() / 255.0, - bg.getBlue() / 255.0, 1.0); - cairoNewPath(); - cairoRectangle(x, y, width, height); - cairoFill(); - setColor(fg); - - updateBufferedImage(); + if (clip instanceof Rectangle2D) + { + Rectangle2D r = (Rectangle2D) clip; + cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + else + walkPath(clip.getPathIterator(null), false); + + // cairoClosePath (); + cairoClip(); } public void setBackground(Color c) @@ -983,196 +709,173 @@ public class GdkGraphics2D extends Graphics2D return bg; } - private void doPolygon(int[] xPoints, int[] yPoints, int nPoints, - boolean close, boolean fill) + /** + * Return the current composite. + */ + public Composite getComposite() { - if (nPoints < 1) - return; - GeneralPath gp = new GeneralPath(PathIterator.WIND_EVEN_ODD); - gp.moveTo((float) xPoints[0], (float) yPoints[0]); - for (int i = 1; i < nPoints; i++) - gp.lineTo((float) xPoints[i], (float) yPoints[i]); + if (comp == null) + return AlphaComposite.SrcOver; + else + return comp; + } - if (close) - gp.closePath(); + /** + * Sets the current composite context. + */ + public void setComposite(Composite comp) + { + this.comp = comp; - Shape sh = gp; - if (fill == false && stroke != null && ! (stroke instanceof BasicStroke)) + if (comp instanceof AlphaComposite) { - sh = stroke.createStrokedShape(gp); - fill = true; + AlphaComposite a = (AlphaComposite) comp; + cairoSetOperator(a.getRule()); + Color c = getColor(); + setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), + (int) (a.getAlpha() * ((float) c.getAlpha())))); } - - if (fill) - fill(sh); else - draw(sh); + { + // FIXME: implement general Composite support + throw new java.lang.UnsupportedOperationException(); + } } - public void drawLine(int x1, int y1, int x2, int y2) + ///////////////////////// DRAWING PRIMITIVES /////////////////////////////////// + + public void draw(Shape s) { - int[] xp = new int[2]; - int[] yp = new int[2]; + if (stroke != null && ! (stroke instanceof BasicStroke)) + { + fill(stroke.createStrokedShape(s)); + return; + } - xp[0] = x1; - xp[1] = x2; - yp[0] = y1; - yp[1] = y2; + cairoNewPath(); - doPolygon(xp, yp, 2, false, false); + if (s instanceof Rectangle2D) + { + Rectangle2D r = (Rectangle2D) s; + cairoRectangle(shifted(r.getX(), shiftDrawCalls), + shifted(r.getY(), shiftDrawCalls), r.getWidth(), + r.getHeight()); + } + else + walkPath(s.getPathIterator(null), shiftDrawCalls); + cairoStroke(); } - public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) + public void fill(Shape s) { - doPolygon(xPoints, yPoints, nPoints, true, true); + cairoNewPath(); + if (s instanceof Rectangle2D) + { + Rectangle2D r = (Rectangle2D) s; + cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + else + walkPath(s.getPathIterator(null), false); + + cairoFill(); } - public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) + /** + * Note that the rest of the drawing methods go via fill() or draw() for the drawing, + * although subclasses may with to overload these methods where context-specific + * optimizations are possible (e.g. bitmaps and fillRect(int, int, int, int) + */ + + public void clearRect(int x, int y, int width, int height) { - doPolygon(xPoints, yPoints, nPoints, true, false); + if (bg != null) + cairoSetRGBAColor(bg.getRed() / 255.0, bg.getGreen() / 255.0, + bg.getBlue() / 255.0, 1.0); + fillRect(x, y, width, height); + setColor(fg); } - public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) + public void draw3DRect(int x, int y, int width, int height, boolean raised) { - doPolygon(xPoints, yPoints, nPoints, false, false); + Stroke tmp = stroke; + setStroke(draw3DRectStroke); + super.draw3DRect(x, y, width, height, raised); + setStroke(tmp); } - private boolean drawRaster(ColorModel cm, Raster r, - AffineTransform imageToUser, Color bgcolor) + public void drawArc(int x, int y, int width, int height, int startAngle, + int arcAngle) { - if (r == null) - return false; - - SampleModel sm = r.getSampleModel(); - DataBuffer db = r.getDataBuffer(); - - if (db == null || sm == null) - return false; - - if (cm == null) - cm = ColorModel.getRGBdefault(); - - double[] i2u = new double[6]; - if (imageToUser != null) - imageToUser.getMatrix(i2u); - else - { - i2u[0] = 1; - i2u[1] = 0; - i2u[2] = 0; - i2u[3] = 1; - i2u[4] = 0; - i2u[5] = 0; - } - - int[] pixels = findSimpleIntegerArray(cm, r); - - if (pixels == null) - { - // FIXME: I don't think this code will work correctly with a non-RGB - // MultiPixelPackedSampleModel. Although this entire method should - // probably be rewritten to better utilize Cairo's different supported - // data formats. - if (sm instanceof MultiPixelPackedSampleModel) - { - pixels = r.getPixels(0, 0, r.getWidth(), r.getHeight(), pixels); - for (int i = 0; i < pixels.length; i++) - pixels[i] = cm.getRGB(pixels[i]); - } - else - { - pixels = new int[r.getWidth() * r.getHeight()]; - for (int i = 0; i < pixels.length; i++) - pixels[i] = cm.getRGB(db.getElem(i)); - } - } - - // Change all transparent pixels in the image to the specified bgcolor, - // or (if there's no alpha) fill in an alpha channel so that it paints - // correctly. - if (cm.hasAlpha()) - { - if (bgcolor != null && cm.hasAlpha()) - for (int i = 0; i < pixels.length; i++) - { - if (cm.getAlpha(pixels[i]) == 0) - pixels[i] = bgcolor.getRGB(); - } - } - else - for (int i = 0; i < pixels.length; i++) - pixels[i] |= 0xFF000000; - - drawPixels(pixels, r.getWidth(), r.getHeight(), r.getWidth(), i2u); + draw(new Arc2D.Double((double) x, (double) y, (double) width, + (double) height, (double) startAngle, + (double) arcAngle, Arc2D.OPEN)); + } - updateBufferedImage(); - - // Cairo seems loosing the current color. - setColor(fg); - - return true; + public void drawLine(int x1, int y1, int x2, int y2) + { + draw(new Line2D.Double(x1, y1, x2, y2)); } - public void drawRenderedImage(RenderedImage image, AffineTransform xform) + public void drawRect(int x, int y, int width, int height) { - drawRaster(image.getColorModel(), image.getData(), xform, bg); + draw(new Rectangle(x, y, width, height)); } - public void drawRenderableImage(RenderableImage image, AffineTransform xform) + public void fillArc(int x, int y, int width, int height, int startAngle, + int arcAngle) { - drawRenderedImage(image.createRendering(new RenderContext(xform)), xform); + fill(new Arc2D.Double((double) x, (double) y, (double) width, + (double) height, (double) startAngle, + (double) arcAngle, Arc2D.OPEN)); } - public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) + public void fillRect(int x, int y, int width, int height) { - return drawImage(img, xform, bg, obs); + fill(new Rectangle(x, y, width, height)); } - public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y) + public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) { - Image filtered = op.filter(image, null); - drawImage(filtered, new AffineTransform(1f, 0f, 0f, 1f, x, y), bg, null); + fill(new Polygon(xPoints, yPoints, nPoints)); } - public boolean drawImage(Image img, int x, int y, ImageObserver observer) + public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) { - return drawImage(img, new AffineTransform(1f, 0f, 0f, 1f, x, y), bg, - observer); + draw(new Polygon(xPoints, yPoints, nPoints)); } - /////////////////////////////////////////////// - ////// Unimplemented Stubs and Overloads ////// - /////////////////////////////////////////////// + public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) + { + draw(new Polygon(xPoints, yPoints, nPoints)); + } - public boolean hit(Rectangle rect, Shape text, boolean onStroke) + public void drawOval(int x, int y, int width, int height) { - throw new java.lang.UnsupportedOperationException(); + drawArc(x, y, width, height, 0, 360); } - public GraphicsConfiguration getDeviceConfiguration() + public void drawRoundRect(int x, int y, int width, int height, int arcWidth, + int arcHeight) { - throw new java.lang.UnsupportedOperationException(); + draw(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight)); } - public void setComposite(Composite comp) + public void fillOval(int x, int y, int width, int height) { - this.comp = comp; + fillArc(x, y, width, height, 0, 360); + } - if (comp instanceof AlphaComposite) - { - AlphaComposite a = (AlphaComposite) comp; - cairoSetOperator(a.getRule()); - Color c = getColor(); - setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), - (int) (a.getAlpha() * ((float) c.getAlpha())))); - } - else - { - // FIXME: implement general Composite support - throw new java.lang.UnsupportedOperationException(); - } + public void fillRoundRect(int x, int y, int width, int height, int arcWidth, + int arcHeight) + { + fill(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight)); } + ///////////////////////// RENDERING HINTS /////////////////////////////////// + + /** + * FIXME- support better + */ public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) { hints.put(hintKey, hintValue); @@ -1197,7 +900,7 @@ public class GdkGraphics2D extends Graphics2D } shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE) - || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT); + || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT); } public Object getRenderingHint(RenderingHints.Key hintKey) @@ -1232,7 +935,7 @@ public class GdkGraphics2D extends Graphics2D } shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE) - || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT); + || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT); } public void addRenderingHints(Map hints) @@ -1245,31 +948,80 @@ public class GdkGraphics2D extends Graphics2D return hints; } - public Composite getComposite() + ///////////////////////// IMAGE. METHODS /////////////////////////////////// + + protected boolean drawImage(Image img, AffineTransform xform, + Color bgcolor, ImageObserver obs) { - if (comp == null) - return AlphaComposite.SrcOver; - else - return comp; + if (img == null) + return false; + + // In this case, xform is an AffineTransform that transforms bounding + // box of the specified image from image space to user space. However + // when we pass this transform to cairo, cairo will use this transform + // to map "user coordinates" to "pixel" coordinates, which is the + // other way around. Therefore to get the "user -> pixel" transform + // that cairo wants from "image -> user" transform that we currently + // have, we will need to invert the transformation matrix. + AffineTransform invertedXform = new AffineTransform(); + + try + { + invertedXform = xform.createInverse(); + if (img instanceof BufferedImage) + { + // draw an image which has actually been loaded + // into memory fully + BufferedImage b = (BufferedImage) img; + DataBuffer db = b.getRaster().getDataBuffer(); + if(db instanceof CairoSurface) + { + double[] i2u = new double[6]; + invertedXform.getMatrix(i2u); + ((CairoSurface)db).drawSurface(this, i2u); + return true; + } + + return drawRaster(b.getColorModel(), b.getTile(0, 0), + invertedXform, bgcolor); + } + else + return this.drawImage(GdkPixbufDecoder.createBufferedImage(img + .getSource()), + xform, bgcolor, obs); + } + catch (NoninvertibleTransformException e) + { + throw new ImagingOpException("Unable to invert transform " + + xform.toString()); + } } - public FontRenderContext getFontRenderContext() + public void drawRenderedImage(RenderedImage image, AffineTransform xform) { - return new FontRenderContext(transform, true, true); + drawRaster(image.getColorModel(), image.getData(), xform, bg); } - public void copyArea(int x, int y, int width, int height, int dx, int dy) + public void drawRenderableImage(RenderableImage image, AffineTransform xform) { - GdkGraphics2D g = (GdkGraphics2D) create(x, y, width, height); - gdkDrawDrawable(g, x + dx, y + dy); + drawRenderedImage(image.createRendering(new RenderContext(xform)), xform); } - public void drawArc(int x, int y, int width, int height, int startAngle, - int arcAngle) + public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { - draw(new Arc2D.Double((double) x, (double) y, (double) width, - (double) height, (double) startAngle, - (double) arcAngle, Arc2D.OPEN)); + return drawImage(img, xform, bg, obs); + } + + public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y) + { + Image filtered = op.filter(image, null); + drawImage(filtered, new AffineTransform(1f, 0f, 0f, 1f, x, y), bg, null); + } + + public boolean drawImage(Image img, int x, int y, ImageObserver observer) + { + return drawImage(img, new AffineTransform(1f, 0f, 0f, 1f, x, y), bg, + observer); } public boolean drawImage(Image img, int x, int y, Color bgcolor, @@ -1310,6 +1062,10 @@ public class GdkGraphics2D extends Graphics2D int destWidth = dx2 - dx1; int destHeight = dy2 - dy1; + if(destWidth == 0 || destHeight == 0 || sourceWidth == 0 || + sourceHeight == 0) + return true; + double scaleX = destWidth / (double) sourceWidth; double scaleY = destHeight / (double) sourceHeight; @@ -1335,6 +1091,7 @@ public class GdkGraphics2D extends Graphics2D subImage = Toolkit.getDefaultToolkit().createImage(src); } + // FIXME: Avoid using an AT if possible here - it's at least twice as slow. return drawImage(subImage, new AffineTransform(scaleX, 0, 0, scaleY, dx1, dy1), bgcolor, observer); @@ -1347,56 +1104,7 @@ public class GdkGraphics2D extends Graphics2D return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bg, observer); } - public void drawOval(int x, int y, int width, int height) - { - drawArc(x, y, width, height, 0, 360); - } - - public void drawRoundRect(int x, int y, int width, int height, int arcWidth, - int arcHeight) - { - if (arcWidth > width) - arcWidth = width; - if (arcHeight > height) - arcHeight = height; - - int xx = x + width - arcWidth; - int yy = y + height - arcHeight; - - drawArc(x, y, arcWidth, arcHeight, 90, 90); - drawArc(xx, y, arcWidth, arcHeight, 0, 90); - drawArc(xx, yy, arcWidth, arcHeight, 270, 90); - drawArc(x, yy, arcWidth, arcHeight, 180, 90); - - int y1 = y + arcHeight / 2; - int y2 = y + height - arcHeight / 2; - drawLine(x, y1, x, y2); - drawLine(x + width, y1, x + width, y2); - - int x1 = x + arcWidth / 2; - int x2 = x + width - arcWidth / 2; - drawLine(x1, y, x2, y); - drawLine(x1, y + height, x2, y + height); - } - - // these are the most accelerated painting paths - native void cairoDrawGlyphVector(GdkFontPeer font, - float x, float y, int n, - int[] codes, float[] positions); - - native void cairoDrawGdkTextLayout(GdkTextLayout gl, - float x, float y); - - GdkFontPeer getFontPeer() - { - return (GdkFontPeer) getFont().getPeer(); - } - - public void drawGdkTextLayout(GdkTextLayout gl, float x, float y) - { - cairoDrawGdkTextLayout (gl, x, y); - updateBufferedImage (); - } + ///////////////////////// TEXT METHODS //////////////////////////////////// public void drawString(String str, float x, float y) { @@ -1404,7 +1112,6 @@ public class GdkGraphics2D extends Graphics2D return; drawGlyphVector(getFont().createGlyphVector(null, str), x, y); - updateBufferedImage (); } public void drawString(String str, int x, int y) @@ -1424,8 +1131,7 @@ public class GdkGraphics2D extends Graphics2D float[] positions = gv.getGlyphPositions (0, n, null); setFont (gv.getFont ()); - cairoDrawGlyphVector (getFontPeer(), x, y, n, codes, positions); - updateBufferedImage (); + cairoDrawGlyphVector( (GdkFontPeer)getFont().getPeer(), x, y, n, codes, positions); } public void drawString(AttributedCharacterIterator ci, float x, float y) @@ -1434,52 +1140,19 @@ public class GdkGraphics2D extends Graphics2D drawGlyphVector(gv, x, y); } - public void fillArc(int x, int y, int width, int height, int startAngle, - int arcAngle) - { - fill(new Arc2D.Double((double) x, (double) y, (double) width, - (double) height, (double) startAngle, - (double) arcAngle, Arc2D.OPEN)); - } - - public void fillOval(int x, int y, int width, int height) - { - fillArc(x, y, width, height, 0, 360); - } - - public void fillRoundRect(int x, int y, int width, int height, int arcWidth, - int arcHeight) - { - if (arcWidth > width) - arcWidth = width; - if (arcHeight > height) - arcHeight = height; - - int xx = x + width - arcWidth; - int yy = y + height - arcHeight; - - fillArc(x, y, arcWidth, arcHeight, 90, 90); - fillArc(xx, y, arcWidth, arcHeight, 0, 90); - fillArc(xx, yy, arcWidth, arcHeight, 270, 90); - fillArc(x, yy, arcWidth, arcHeight, 180, 90); - - fillRect(x, y + arcHeight / 2, width, height - arcHeight + 1); - fillRect(x + arcWidth / 2, y, width - arcWidth + 1, height); - } - - public Font getFont() + /** + * Should perhaps be contexct dependent, but this is left for now as an + * overloadable default implementation. + */ + public FontRenderContext getFontRenderContext() { - if (font == null) - return new Font("SansSerif", Font.PLAIN, 12); - return font; + return new FontRenderContext(transform, true, true); } // Until such time as pango is happy to talk directly to cairo, we // actually need to redirect some calls from the GtkFontPeer and // GtkFontMetrics into the drawing kit and ask cairo ourselves. - static native void releasePeerGraphicsResource(GdkFontPeer f); - public FontMetrics getFontMetrics() { return getFontMetrics(getFont()); @@ -1507,6 +1180,27 @@ public class GdkGraphics2D extends Graphics2D .getFont(f.getName(), f.getAttributes()); } + public Font getFont() + { + if (font == null) + return new Font("SansSerif", Font.PLAIN, 12); + return font; + } + + /////////////////////// MISC. PUBLIC METHODS ///////////////////////////////// + + public boolean hit(Rectangle rect, Shape s, boolean onStroke) + { + if( onStroke ) + { + Shape stroked = stroke.createStrokedShape( s ); + return stroked.intersects( (double)rect.x, (double)rect.y, + (double)rect.width, (double)rect.height ); + } + return s.intersects( (double)rect.x, (double)rect.y, + (double)rect.width, (double)rect.height ); + } + public String toString() { return (getClass().getName() @@ -1514,4 +1208,211 @@ public class GdkGraphics2D extends Graphics2D + ",color=" + fg.toString() + "]"); } + + ///////////////////////// PRIVATE METHODS /////////////////////////////////// + + private boolean drawRaster(ColorModel cm, Raster r, + AffineTransform imageToUser, Color bgcolor) + { + if (r == null) + return false; + + SampleModel sm = r.getSampleModel(); + DataBuffer db = r.getDataBuffer(); + + if (db == null || sm == null) + return false; + + if (cm == null) + cm = ColorModel.getRGBdefault(); + + double[] i2u = new double[6]; + if (imageToUser != null) + imageToUser.getMatrix(i2u); + else + { + i2u[0] = 1; + i2u[1] = 0; + i2u[2] = 0; + i2u[3] = 1; + i2u[4] = 0; + i2u[5] = 0; + } + + int[] pixels = findSimpleIntegerArray(cm, r); + + if (pixels == null) + { + // FIXME: I don't think this code will work correctly with a non-RGB + // MultiPixelPackedSampleModel. Although this entire method should + // probably be rewritten to better utilize Cairo's different supported + // data formats. + if (sm instanceof MultiPixelPackedSampleModel) + { + pixels = r.getPixels(0, 0, r.getWidth(), r.getHeight(), pixels); + for (int i = 0; i < pixels.length; i++) + pixels[i] = cm.getRGB(pixels[i]); + } + else + { + pixels = new int[r.getWidth() * r.getHeight()]; + for (int i = 0; i < pixels.length; i++) + pixels[i] = cm.getRGB(db.getElem(i)); + } + } + + // Change all transparent pixels in the image to the specified bgcolor, + // or (if there's no alpha) fill in an alpha channel so that it paints + // correctly. + if (cm.hasAlpha()) + { + if (bgcolor != null && cm.hasAlpha()) + for (int i = 0; i < pixels.length; i++) + { + if (cm.getAlpha(pixels[i]) == 0) + pixels[i] = bgcolor.getRGB(); + } + } + else + for (int i = 0; i < pixels.length; i++) + pixels[i] |= 0xFF000000; + + drawPixels(pixels, r.getWidth(), r.getHeight(), r.getWidth(), i2u); + + // Cairo seems loosing the current color. + setColor(fg); + + return true; + } + + /** + * Shifts coordinates by 0.5. + */ + private double shifted(double coord, boolean doShift) + { + if (doShift) + return Math.floor(coord) + 0.5; + else + return coord; + } + + /** + * Adds a pathIterator to the current Cairo path, also sets the cairo winding rule. + */ + private void walkPath(PathIterator p, boolean doShift) + { + double x = 0; + double y = 0; + double[] coords = new double[6]; + + cairoSetFillRule(p.getWindingRule()); + for (; ! p.isDone(); p.next()) + { + int seg = p.currentSegment(coords); + switch (seg) + { + case PathIterator.SEG_MOVETO: + x = shifted(coords[0], doShift); + y = shifted(coords[1], doShift); + cairoMoveTo(x, y); + break; + case PathIterator.SEG_LINETO: + x = shifted(coords[0], doShift); + y = shifted(coords[1], doShift); + cairoLineTo(x, y); + break; + case PathIterator.SEG_QUADTO: + // splitting a quadratic bezier into a cubic: + // see: http://pfaedit.sourceforge.net/bezier.html + double x1 = x + (2.0 / 3.0) * (shifted(coords[0], doShift) - x); + double y1 = y + (2.0 / 3.0) * (shifted(coords[1], doShift) - y); + + double x2 = x1 + (1.0 / 3.0) * (shifted(coords[2], doShift) - x); + double y2 = y1 + (1.0 / 3.0) * (shifted(coords[3], doShift) - y); + + x = shifted(coords[2], doShift); + y = shifted(coords[3], doShift); + cairoCurveTo(x1, y1, x2, y2, x, y); + break; + case PathIterator.SEG_CUBICTO: + x = shifted(coords[4], doShift); + y = shifted(coords[5], doShift); + cairoCurveTo(shifted(coords[0], doShift), + shifted(coords[1], doShift), + shifted(coords[2], doShift), + shifted(coords[3], doShift), x, y); + break; + case PathIterator.SEG_CLOSE: + cairoClosePath(); + break; + } + } + } + + /** + * Used by setRenderingHints() + */ + private Map getDefaultHints() + { + HashMap defaultHints = new HashMap(); + + defaultHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); + + defaultHints.put(RenderingHints.KEY_STROKE_CONTROL, + RenderingHints.VALUE_STROKE_DEFAULT); + + defaultHints.put(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_OFF); + + defaultHints.put(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + + defaultHints.put(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_DEFAULT); + + return defaultHints; + } + + /** + * Used by drawRaster and GdkPixbufDecoder + */ + public static int[] findSimpleIntegerArray (ColorModel cm, Raster raster) + { + if (cm == null || raster == null) + return null; + + if (! cm.getColorSpace().isCS_sRGB()) + return null; + + if (! (cm instanceof DirectColorModel)) + return null; + + DirectColorModel dcm = (DirectColorModel) cm; + + if (dcm.getRedMask() != 0x00FF0000 || dcm.getGreenMask() != 0x0000FF00 + || dcm.getBlueMask() != 0x000000FF) + return null; + + if (! (raster instanceof WritableRaster)) + return null; + + if (raster.getSampleModel().getDataType() != DataBuffer.TYPE_INT) + return null; + + if (! (raster.getDataBuffer() instanceof DataBufferInt)) + return null; + + DataBufferInt db = (DataBufferInt) raster.getDataBuffer(); + + if (db.getNumBanks() != 1) + return null; + + // Finally, we have determined that this is a single bank, [A]RGB-int + // buffer in sRGB space. It's worth checking all this, because it means + // that cairo can paint directly into the data buffer, which is very + // fast compared to all the normal copying and converting. + + return db.getData(); + } } diff --git a/gnu/java/awt/peer/gtk/CairoSurface.java b/gnu/java/awt/peer/gtk/CairoSurface.java new file mode 100644 index 000000000..86809f971 --- /dev/null +++ b/gnu/java/awt/peer/gtk/CairoSurface.java @@ -0,0 +1,210 @@ +/* CairoSurface.java + Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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.Color; +import java.awt.Image; +import java.awt.Point; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.image.DataBuffer; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.io.File; +import java.io.IOException; +import java.util.Hashtable; +import java.util.Vector; +import java.io.ByteArrayOutputStream; +import java.io.BufferedInputStream; +import java.net.URL; +import gnu.classpath.Pointer; + +/** + * CairoSurface - wraps a Cairo surface. + * + * @author Sven de Marothy + */ +public class CairoSurface extends DataBuffer +{ + int width = -1, height = -1; + + /** + * The native pointer to the Cairo surface. + */ + long surfacePointer; + + /** + * The native pointer to the image's data buffer + */ + long bufferPointer; + + + static ColorModel nativeModel = new DirectColorModel(32, + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000); + + /** + * Allocates and clears the buffer and creates the cairo surface. + * @param width, height - the image size + * @param stride - the buffer row stride. + */ + private native void create(int width, int height, int stride); + + /** + * Destroys the cairo surface and frees the buffer. + */ + private native void destroy(); + + /** + * Gets buffer elements + */ + private native int nativeGetElem(int i); + + /** + * Sets buffer elements. + */ + private native void nativeSetElem(int i, int val); + + /** + * Draws this image to a given CairoGraphics context, + * with an affine transform given by i2u. + */ + public native void drawSurface(CairoGraphics2D context, double[] i2u); + + /** + * getPixels -return the pixels as a java array. + */ + native int[] getPixels(int size); + + /** + * getPixels -return the pixels as a java array. + */ + native void setPixels(int[] pixels); + + /** + * Create a cairo_surface_t with specified width and height. + * The format will be ARGB32 with premultiplied alpha and native bit + * and word ordering. + */ + CairoSurface(int width, int height) + { + super(DataBuffer.TYPE_INT, width * height); + + if(width <= 0 || height <= 0) + throw new IllegalArgumentException("Image must be at least 1x1 pixels."); + + this.width = width; + this.height = height; + + create(width, height, width * 4); + + if(surfacePointer == 0 || bufferPointer == 0) + throw new Error("Could not allocate bitmap."); + } + + /** + * Dispose of the native data. + */ + public void dispose() + { + if(surfacePointer != 0) + destroy(); + } + + /** + * Returns a BufferedImage backed by a Cairo surface. + */ + public static BufferedImage getBufferedImage(int width, int height) + { + WritableRaster raster = Raster.createPackedRaster + (new CairoSurface(width, height), width, height, width, + new int[]{ 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, + new Point(0,0)); + + return new BufferedImage(nativeModel, raster, true, new Hashtable()); + } + + /** + * DataBank.getElem implementation + */ + public int getElem(int bank, int i) + { + if(bank != 0 || i <= 0 || i >= width*height) + throw new IndexOutOfBoundsException(); + return getElem(i); + } + + /** + * DataBank.setElem implementation + */ + public void setElem(int bank, int i, int val) + { + if(bank != 0 || i <= 0 || i >= width*height) + throw new IndexOutOfBoundsException(); + setElem(i, val); + } + + /** + * Return a Graphics2D drawing to the CairoSurface. + */ + public Graphics2D getGraphics() + { + return new CairoSurfaceGraphics(this); + } + + ///// Methods used by CairoSurfaceGraphics ///// + /** + * Creates a cairo_t drawing context, returns the pointer as a long. + * Used by CairoSurfaceGraphics. + */ + native long newCairoContext(); + + /** + * Copy an area of the surface. Expects parameters must be within bounds. + * Count on a segfault otherwise. + */ + native void copyAreaNative(int x, int y, int width, int height, + int dx, int dy, int stride); +} diff --git a/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java new file mode 100644 index 000000000..7150adf60 --- /dev/null +++ b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java @@ -0,0 +1,101 @@ +/* CairoSurfaceGraphics.java + Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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.Color; +import java.awt.Image; +import java.awt.Point; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.image.*; + +/** + * Implementation of Graphics2D on a Cairo surface. + */ +public class CairoSurfaceGraphics extends CairoGraphics2D +{ + private CairoSurface surface; + private long cairo_t; + + /** + * Create a graphics context from a cairo surface + */ + public CairoSurfaceGraphics(CairoSurface surface) + { + this.surface = surface; + cairo_t = surface.newCairoContext(); + setup( cairo_t ); + setClip(0, 0, surface.width, surface.height); + } + + /** + * Creates another context from a surface. + * Used by create(). + */ + private CairoSurfaceGraphics(CairoSurfaceGraphics copyFrom) + { + surface = copyFrom.surface; + cairo_t = surface.newCairoContext(); + copy( copyFrom, cairo_t ); + setClip(0, 0, surface.width, surface.height); + } + + public Graphics create() + { + return new CairoSurfaceGraphics(this); + } + + public GraphicsConfiguration getDeviceConfiguration() + { + throw new UnsupportedOperationException(); + } + + public void copyArea(int x, int y, int width, int height, int dx, int dy) + { + // FIXME: Adjust parameters so that clipping on the edges occurs. + + if( x + dx + width >= surface.width || y + dy + height >= surface.height) + return; + if( x + dx <= 0 || y + dy <= 0) + return; + + surface.copyAreaNative(x, y, width, height, dx, dy, surface.width*4); + } +} diff --git a/gnu/java/awt/peer/gtk/ComponentGraphics.java b/gnu/java/awt/peer/gtk/ComponentGraphics.java new file mode 100644 index 000000000..e650bc7ac --- /dev/null +++ b/gnu/java/awt/peer/gtk/ComponentGraphics.java @@ -0,0 +1,170 @@ +/* ComponentGraphics.java -- + Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.ImageObserver; +import java.awt.image.ImagingOpException; +import java.awt.image.RenderedImage; + +/** + * ComponentGraphics - context for drawing directly to a component, + * as this is an X drawable, it requires that we use GTK locks. + * + * This context draws directly to the drawable and requires xrender. + */ +public class ComponentGraphics extends CairoGraphics2D +{ + private GtkComponentPeer component; + private long cairo_t; + + private ComponentGraphics(GtkComponentPeer component) + { + this.component = component; + cairo_t = initState(component); + setup( cairo_t ); + setColor(component.awtComponent.getForeground()); + setBackground(component.awtComponent.getBackground()); + setClip(component.awtComponent.getBounds()); + } + + private ComponentGraphics(ComponentGraphics cg) + { + component = cg.component; + cairo_t = initState(component); + copy( cg, cairo_t ); + } + + /** + * Creates a cairo_t for the component surface and return it. + */ + private native long initState(GtkComponentPeer component); + + /** + * Grab lock + */ + private native void start_gdk_drawing(); + + /** + * Release lock + */ + private native void end_gdk_drawing(); + + /** + * Query if the system has the XRender extension. + */ + public static native boolean hasXRender(); + + /** + * Returns a Graphics2D object for a component, either an instance of this + * class (if xrender is supported), or a context which copies. + */ + public static Graphics2D getComponentGraphics(GtkComponentPeer component) + { + if( hasXRender() ) + return new ComponentGraphics(component); + throw new UnsupportedOperationException("No non-xrender yet."); + } + + public GraphicsConfiguration getDeviceConfiguration() + { + return component.getGraphicsConfiguration(); + } + + public Graphics create() + { + return new ComponentGraphics(this); + } + + public void copyArea(int x, int y, int width, int height, int dx, int dy) + { + // FIXME + } + + /** + * Overloaded methods that do actual drawing need to enter the gdk threads + * and also do certain things before and after. + */ + public void draw(Shape s) + { + start_gdk_drawing(); + super.draw(s); + end_gdk_drawing(); + } + + public void fill(Shape s) + { + start_gdk_drawing(); + super.fill(s); + end_gdk_drawing(); + } + + public void drawRenderedImage(RenderedImage image, AffineTransform xform) + { + start_gdk_drawing(); + super.drawRenderedImage(image, xform); + end_gdk_drawing(); + } + + protected boolean drawImage(Image img, AffineTransform xform, + Color bgcolor, ImageObserver obs) + { + start_gdk_drawing(); + boolean rv = super.drawImage(img, xform, bgcolor, obs); + end_gdk_drawing(); + return rv; + } + + public void drawGlyphVector(GlyphVector gv, float x, float y) + { + start_gdk_drawing(); + super.drawGlyphVector(gv, x, y); + end_gdk_drawing(); + } +} diff --git a/gnu/java/awt/peer/gtk/GdkFontPeer.java b/gnu/java/awt/peer/gtk/GdkFontPeer.java index 544efa3c9..205617130 100644 --- a/gnu/java/awt/peer/gtk/GdkFontPeer.java +++ b/gnu/java/awt/peer/gtk/GdkFontPeer.java @@ -90,9 +90,12 @@ public class GdkFontPeer extends ClasspathFontPeer native void getFontMetrics(double [] metrics); native void getTextMetrics(String str, double [] metrics); + native void releasePeerGraphicsResource(); + + protected void finalize () { - GdkGraphics2D.releasePeerGraphicsResource(this); + releasePeerGraphicsResource(); dispose (); } diff --git a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java index 4b0b5d308..b2615a912 100644 --- a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java +++ b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java @@ -45,6 +45,7 @@ import java.awt.GraphicsEnvironment; import java.awt.HeadlessException; import java.awt.Toolkit; import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; import java.util.Locale; public class GdkGraphicsEnvironment extends GraphicsEnvironment @@ -69,7 +70,11 @@ public class GdkGraphicsEnvironment extends GraphicsEnvironment public Graphics2D createGraphics (BufferedImage image) { - return new GdkGraphics2D (image); + DataBuffer db = image.getRaster().getDataBuffer(); + if(db instanceof CairoSurface) + return ((CairoSurface)db).getGraphics(); + + return new BufferedImageGraphics( image ); } private native int nativeGetNumFontFamilies(); @@ -80,17 +85,17 @@ public class GdkGraphicsEnvironment extends GraphicsEnvironment throw new java.lang.UnsupportedOperationException (); } - public String[] getAvailableFontFamilyNames () - { - String[] family_names; - int array_size; - - array_size = nativeGetNumFontFamilies(); - family_names = new String[array_size]; - - nativeGetFontFamilies(family_names); - return family_names; - } + public String[] getAvailableFontFamilyNames () + { + String[] family_names; + int array_size; + + array_size = nativeGetNumFontFamilies(); + family_names = new String[array_size]; + + nativeGetFontFamilies(family_names); + return family_names; + } public String[] getAvailableFontFamilyNames (Locale l) { diff --git a/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java index 72908ff5c..4b8ba9472 100644 --- a/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java +++ b/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java @@ -504,19 +504,19 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder int width = ras.getWidth(); int height = ras.getHeight(); ColorModel model = image.getColorModel(); - int[] pixels = GdkGraphics2D.findSimpleIntegerArray (image.getColorModel(), ras); + int[] pixels = CairoGraphics2D.findSimpleIntegerArray (image.getColorModel(), ras); if (pixels == null) { - BufferedImage img = new BufferedImage(width, height, - (model != null && model.hasAlpha() ? - BufferedImage.TYPE_INT_ARGB - : BufferedImage.TYPE_INT_RGB)); + BufferedImage img; + if(model != null && model.hasAlpha()) + img = CairoSurface.getBufferedImage(width, height); + img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); int[] pix = new int[4]; for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) img.setRGB(x, y, model.getRGB(ras.getPixel(x, y, pix))); - pixels = GdkGraphics2D.findSimpleIntegerArray (img.getColorModel(), + pixels = CairoGraphics2D.findSimpleIntegerArray (img.getColorModel(), img.getRaster()); model = img.getColorModel(); } @@ -586,9 +586,10 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder if (bufferedImage == null) { - bufferedImage = new BufferedImage (width, height, (model != null && model.hasAlpha() ? - BufferedImage.TYPE_INT_ARGB - : BufferedImage.TYPE_INT_RGB)); + if(model != null && model.hasAlpha()) + bufferedImage = new BufferedImage (width, height, BufferedImage.TYPE_INT_ARGB); + else + bufferedImage = new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB); } int pixels2[]; diff --git a/gnu/java/awt/peer/gtk/GdkTextLayout.java b/gnu/java/awt/peer/gtk/GdkTextLayout.java index 9189bd4b7..8f45aa670 100644 --- a/gnu/java/awt/peer/gtk/GdkTextLayout.java +++ b/gnu/java/awt/peer/gtk/GdkTextLayout.java @@ -80,10 +80,17 @@ public class GdkTextLayout private native void getExtents(double[] inkExtents, double[] logExtents); private native void indexToPos(int idx, double[] pos); + private native void initState (); + private native void dispose (); + + private native void cairoDrawGdkTextLayout(CairoGraphics2D g, float x, float y); + static native void initStaticState(); + private final int native_state = GtkGenericPeer.getUniqueInteger (); + protected void finalize () { dispose (); @@ -201,9 +208,7 @@ public class GdkTextLayout public void draw (Graphics2D g2, float x, float y) { - // we share pango structures directly with GdkGraphics2D - GdkGraphics2D gg2 = (GdkGraphics2D) g2; - gg2.drawGdkTextLayout(this, x, y); + cairoDrawGdkTextLayout((CairoGraphics2D)g2, x, y); } public TextHitInfo getStrongCaret (TextHitInfo hit1, diff --git a/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/gnu/java/awt/peer/gtk/GtkComponentPeer.java index 3e464ab1a..43176d171 100644 --- a/gnu/java/awt/peer/gtk/GtkComponentPeer.java +++ b/gnu/java/awt/peer/gtk/GtkComponentPeer.java @@ -207,13 +207,7 @@ public class GtkComponentPeer extends GtkGenericPeer public Image createImage (int width, int height) { - Image image; - image = new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB); - - Graphics g = image.getGraphics(); - g.setColor(getBackground()); - g.fillRect(0, 0, width, height); - return image; + return CairoSurface.getBufferedImage(width, height); } public void disable () @@ -240,7 +234,7 @@ public class GtkComponentPeer extends GtkGenericPeer // never return null. public Graphics getGraphics () { - return new GdkGraphics2D (this); + return ComponentGraphics.getComponentGraphics(this); } public Point getLocationOnScreen () diff --git a/gnu/java/awt/peer/gtk/GtkImage.java b/gnu/java/awt/peer/gtk/GtkImage.java index 83ce2cbef..61cce154b 100644 --- a/gnu/java/awt/peer/gtk/GtkImage.java +++ b/gnu/java/awt/peer/gtk/GtkImage.java @@ -57,14 +57,7 @@ import java.net.URL; import gnu.classpath.Pointer; /** - * 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). + * GtkImage - wraps a GdkPixbuf. * * A GdkPixbuf is 'on-screen' and the gdk cannot draw to it, * this is used for the other constructors (and other createImage methods), and @@ -88,9 +81,10 @@ public class GtkImage extends Image boolean isLoaded; /** - * Pointer to the GdkPixbuf + * Pointer to the GdkPixbuf - + * don't change the name without changing the native code. */ - Pointer pixmap; + Pointer pixbuf; /** * Observer queue. @@ -98,11 +92,6 @@ public class GtkImage extends Image Vector observers; /** - * If offScreen is set, a GdkBitmap is wrapped and not a Pixbuf. - */ - boolean offScreen; - - /** * Error flag for loading. */ boolean errorLoading; @@ -125,7 +114,7 @@ public class GtkImage extends Image * Returns a copy of the pixel data as a java array. * Should be called with the GdkPixbufDecoder.pixbufLock held. */ - private native int[] getPixels(); + native int[] getPixels(); /** * Sets the pixel data from a java array. @@ -146,47 +135,22 @@ public class GtkImage extends Image private native boolean loadImageFromData(byte[] data); /** - * Allocates a Gtk Pixbuf or pixmap + * Allocates a Gtk Pixbuf * Should be called with the GdkPixbufDecoder.pixbufLock held. */ - private native void createPixmap(); + private native void createPixbuf(); /** * Frees the above. * Should be called with the GdkPixbufDecoder.pixbufLock held. */ - private native void freePixmap(); - - /** - * Sets the pixmap to scaled copy of src image. hints are rendering hints. - * Should be called with the GdkPixbufDecoder.pixbufLock held. - */ - private native void createScaledPixmap(GtkImage src, int hints); - - /** - * Draws the image, optionally scaled and composited. - * Should be called with the GdkPixbufDecoder.pixbufLock held. - * Also acquires global gdk lock for drawing. - */ - private native void drawPixelsScaled (GdkGraphics2D gc, - int bg_red, int bg_green, int bg_blue, - int x, int y, int width, int height, - boolean composite); + private native void freePixbuf(); /** - * Draws the image, optionally scaled flipped and composited. + * Sets the pixbuf to scaled copy of src image. hints are rendering hints. * Should be called with the GdkPixbufDecoder.pixbufLock held. - * Also acquires global gdk lock for drawing. */ - private native void drawPixelsScaledFlipped (GdkGraphics2D 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); + private native void createScaledPixbuf(GtkImage src, int hints); /** * Constructs a GtkImage from an ImageProducer. Asynchronity is handled in @@ -202,7 +166,6 @@ public class GtkImage extends Image source = producer; errorLoading = false; source.startProduction(new GtkImageConsumer(this, source)); - offScreen = false; } /** @@ -215,7 +178,6 @@ public class GtkImage extends Image { isLoaded = true; observers = null; - offScreen = false; props = new Hashtable(); errorLoading = false; } @@ -249,7 +211,6 @@ public class GtkImage extends Image isLoaded = true; observers = null; - offScreen = false; props = new Hashtable(); } @@ -269,7 +230,6 @@ public class GtkImage extends Image isLoaded = true; observers = null; - offScreen = false; props = new Hashtable(); errorLoading = false; } @@ -313,23 +273,6 @@ public class GtkImage extends Image } /** - * Constructs an empty GtkImage. - */ - public GtkImage (int width, int height) - { - this.width = width; - this.height = height; - props = new Hashtable(); - isLoaded = true; - observers = null; - offScreen = true; - synchronized(GdkPixbufDecoder.pixbufLock) - { - createPixmap(); - } - } - - /** * Constructs a scaled version of the src bitmap, using the GDK. */ private GtkImage (GtkImage src, int width, int height, int hints) @@ -339,12 +282,11 @@ public class GtkImage extends Image props = new Hashtable(); isLoaded = true; observers = null; - offScreen = false; // Use the GDK scaling method. synchronized(GdkPixbufDecoder.pixbufLock) { - createScaledPixmap(src, hints); + createScaledPixbuf(src, hints); } } @@ -354,14 +296,13 @@ public class GtkImage extends Image */ GtkImage (Pointer pixbuf) { - pixmap = pixbuf; + this.pixbuf = pixbuf; synchronized(GdkPixbufDecoder.pixbufLock) { createFromPixbuf(); } isLoaded = true; observers = null; - offScreen = false; props = new Hashtable(); } @@ -409,7 +350,7 @@ public class GtkImage extends Image deliver(); synchronized(GdkPixbufDecoder.pixbufLock) { - createPixmap(); + createPixbuf(); setPixels(pixels); } } @@ -459,21 +400,16 @@ public class GtkImage extends Image } /** - * Creates a GdkGraphics context for this pixmap. + * Does nothing. Should not be called. */ public Graphics getGraphics () { - if (!isLoaded) - return null; - if (offScreen) - return null; // FIXME: (Graphics) new GdkGraphics(this); - else - throw new IllegalAccessError("This method only works for off-screen" - +" Images."); + throw new IllegalAccessError("This method only works for off-screen" + +" Images."); } /** - * Returns a scaled instance of this pixmap. + * Returns a scaled instance of this pixbuf. */ public Image getScaledInstance(int width, int height, @@ -502,7 +438,7 @@ public class GtkImage extends Image isLoaded = false; synchronized(GdkPixbufDecoder.pixbufLock) { - freePixmap(); + freePixbuf(); } source.startProduction(new GtkImageConsumer(this, source)); } @@ -514,7 +450,7 @@ public class GtkImage extends Image { synchronized(GdkPixbufDecoder.pixbufLock) { - freePixmap(); + freePixbuf(); } } } @@ -535,104 +471,6 @@ public class GtkImage extends Image return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT; } - // Drawing methods //////////////////////////////////////////////// - - /** - * Draws an image with eventual scaling/transforming. - */ - public boolean drawImage (GdkGraphics2D 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 > width) - { - dstWidth = (int)((double)dstWidth*((double)width/(double)srcWidth)); - srcWidth = width - srcX; - } - - if (srcHeight > height) - { - dstHeight = (int)((double)dstHeight*((double)height/(double)srcHeight)); - srcHeight = height - srcY; - } - - if (srcWidth + srcX > width) - { - dstWidth = (int)((double)dstWidth * (double)(width - srcX)/(double)srcWidth); - srcWidth = width - srcX; - } - - if (srcHeight + srcY > height) - { - dstHeight = (int)((double)dstHeight * (double)(width - srcY)/(double)srcHeight); - srcHeight = height - srcY; - } - - if ( this.width <= 0 || this.height <= 0 ) - return true; - - if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0) - return true; - - synchronized(GdkPixbufDecoder.pixbufLock) - { - 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; - } - - /** - * 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 (GdkGraphics2D g, int x, int y, int width, int height, - Color bgcolor, ImageObserver observer) - { - if (addObserver(observer)) - return false; - - if ( this.width <= 0 || this.height <= 0 ) - return true; - - synchronized(GdkPixbufDecoder.pixbufLock) - { - 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); - } - - return true; - } // Private methods //////////////////////////////////////////////// diff --git a/gnu/java/awt/print/JavaPrinterGraphics.java b/gnu/java/awt/print/JavaPrinterGraphics.java index af31309ed..9a3db0125 100644 --- a/gnu/java/awt/print/JavaPrinterGraphics.java +++ b/gnu/java/awt/print/JavaPrinterGraphics.java @@ -37,7 +37,7 @@ exception statement from your version. */ package gnu.java.awt.print; -import gnu.java.awt.peer.gtk.GtkImage; +import gnu.java.awt.peer.gtk.CairoSurface; import java.awt.Color; import java.awt.Font; @@ -185,7 +185,7 @@ public class JavaPrinterGraphics extends Graphics implements PrinterGraphics // FIXME: This should at least be BufferedImage. // Fix once we have a working B.I. // Graphics2D should also be supported of course. - image = new GtkImage(xSize, ySize); + image = CairoSurface.getBufferedImage(xSize, ySize); g = image.getGraphics(); setColor(Color.white); diff --git a/include/Makefile.am b/include/Makefile.am index 783ba18ee..06070bb5a 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -37,8 +37,10 @@ $(top_srcdir)/include/gnu_xml_libxmlj_transform_GnomeTransformer.h \ $(top_srcdir)/include/gnu_xml_libxmlj_transform_GnomeTransformerFactory.h GTKPEER_H_FILES = \ +$(top_srcdir)/include/gnu_java_awt_peer_gtk_CairoSurface.h \ +$(top_srcdir)/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h \ +$(top_srcdir)/include/gnu_java_awt_peer_gtk_ComponentGraphics.h \ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkFontPeer.h \ -$(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkGraphics2D.h \ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h \ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkPixbufDecoder.h \ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkRobotPeer.h \ diff --git a/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h b/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h new file mode 100644 index 000000000..8c2c44044 --- /dev/null +++ b/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h @@ -0,0 +1,43 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ + +#ifndef __gnu_java_awt_peer_gtk_CairoGraphics2D__ +#define __gnu_java_awt_peer_gtk_CairoGraphics2D__ + +#include <jni.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_init (JNIEnv *env, jobject, jlong); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_disposeNative (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_drawPixels (JNIEnv *env, jobject, jintArray, jint, jint, jint, jdoubleArray); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setGradient (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble, jint, jint, jint, jint, jint, jint, jint, jint, jboolean); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setTexturePixels (JNIEnv *env, jobject, jintArray, jint, jint, jint); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetMatrix (JNIEnv *env, jobject, jdoubleArray); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetOperator (JNIEnv *env, jobject, jint); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetRGBAColor (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetFillRule (JNIEnv *env, jobject, jint); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetLine (JNIEnv *env, jobject, jdouble, jint, jint, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetDash (JNIEnv *env, jobject, jdoubleArray, jint, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector (JNIEnv *env, jobject, jobject, jfloat, jfloat, jint, jintArray, jfloatArray); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelCurveTo (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRectangle (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoNewPath (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoClosePath (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoMoveTo (JNIEnv *env, jobject, jdouble, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelMoveTo (JNIEnv *env, jobject, jdouble, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoLineTo (JNIEnv *env, jobject, jdouble, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelLineTo (JNIEnv *env, jobject, jdouble, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoCurveTo (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoStroke (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoFill (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoClip (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSurfaceSetFilter (JNIEnv *env, jobject, jint); + +#ifdef __cplusplus +} +#endif + +#endif /* __gnu_java_awt_peer_gtk_CairoGraphics2D__ */ diff --git a/include/gnu_java_awt_peer_gtk_CairoSurface.h b/include/gnu_java_awt_peer_gtk_CairoSurface.h new file mode 100644 index 000000000..df89976ca --- /dev/null +++ b/include/gnu_java_awt_peer_gtk_CairoSurface.h @@ -0,0 +1,27 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ + +#ifndef __gnu_java_awt_peer_gtk_CairoSurface__ +#define __gnu_java_awt_peer_gtk_CairoSurface__ + +#include <jni.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_create (JNIEnv *env, jobject, jint, jint, jint); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_destroy (JNIEnv *env, jobject); +JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_nativeGetElem (JNIEnv *env, jobject, jint); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_nativeSetElem (JNIEnv *env, jobject, jint, jint); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_drawSurface (JNIEnv *env, jobject, jobject, jdoubleArray); +JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_getPixels (JNIEnv *env, jobject, jint); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_setPixels (JNIEnv *env, jobject, jintArray); +JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_newCairoContext (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_copyAreaNative (JNIEnv *env, jobject, jint, jint, jint, jint, jint, jint, jint); + +#ifdef __cplusplus +} +#endif + +#endif /* __gnu_java_awt_peer_gtk_CairoSurface__ */ diff --git a/include/gnu_java_awt_peer_gtk_ComponentGraphics.h b/include/gnu_java_awt_peer_gtk_ComponentGraphics.h new file mode 100644 index 000000000..7c77ff6ea --- /dev/null +++ b/include/gnu_java_awt_peer_gtk_ComponentGraphics.h @@ -0,0 +1,22 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ + +#ifndef __gnu_java_awt_peer_gtk_ComponentGraphics__ +#define __gnu_java_awt_peer_gtk_ComponentGraphics__ + +#include <jni.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_initState (JNIEnv *env, jobject, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_start_1gdk_1drawing (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_end_1gdk_1drawing (JNIEnv *env, jobject); +JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_hasXRender (JNIEnv *env, jclass); + +#ifdef __cplusplus +} +#endif + +#endif /* __gnu_java_awt_peer_gtk_ComponentGraphics__ */ diff --git a/include/gnu_java_awt_peer_gtk_GdkFontPeer.h b/include/gnu_java_awt_peer_gtk_GdkFontPeer.h index 745be47d6..1ef60d40a 100644 --- a/include/gnu_java_awt_peer_gtk_GdkFontPeer.h +++ b/include/gnu_java_awt_peer_gtk_GdkFontPeer.h @@ -16,6 +16,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_dispose (JNIEnv *e JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont (JNIEnv *env, jobject, jstring, jint, jint); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics (JNIEnv *env, jobject, jdoubleArray); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics (JNIEnv *env, jobject, jstring, jdoubleArray); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_releasePeerGraphicsResource (JNIEnv *env, jobject); JNIEXPORT jbyteArray JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTrueTypeTable (JNIEnv *env, jobject, jbyte, jbyte, jbyte, jbyte); JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector (JNIEnv *env, jobject, jstring, jobject, jobject); diff --git a/include/gnu_java_awt_peer_gtk_GdkGraphics2D.h b/include/gnu_java_awt_peer_gtk_GdkGraphics2D.h deleted file mode 100644 index 6bf66b7aa..000000000 --- a/include/gnu_java_awt_peer_gtk_GdkGraphics2D.h +++ /dev/null @@ -1,55 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ - -#ifndef __gnu_java_awt_peer_gtk_GdkGraphics2D__ -#define __gnu_java_awt_peer_gtk_GdkGraphics2D__ - -#include <jni.h> - -#ifdef __cplusplus -extern "C" -{ -#endif - -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initStaticState (JNIEnv *env, jclass); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2 (JNIEnv *env, jobject, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II (JNIEnv *env, jobject, jint, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState___3III (JNIEnv *env, jobject, jintArray, jint, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState (JNIEnv *env, jobject, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSurfaceSetFilter (JNIEnv *env, jobject, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable (JNIEnv *env, jobject, jobject, jint, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels (JNIEnv *env, jobject, jintArray, jint, jint, jint, jdoubleArray); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels (JNIEnv *env, jobject, jintArray, jint, jint, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble, jint, jint, jint, jint, jint, jint, jint, jint, jboolean); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSave (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRestore (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix (JNIEnv *env, jobject, jdoubleArray); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator (JNIEnv *env, jobject, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetRGBAColor (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFillRule (JNIEnv *env, jobject, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineWidth (JNIEnv *env, jobject, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineCap (JNIEnv *env, jobject, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineJoin (JNIEnv *env, jobject, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash (JNIEnv *env, jobject, jdoubleArray, jint, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMiterLimit (JNIEnv *env, jobject, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoNewPath (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoMoveTo (JNIEnv *env, jobject, jdouble, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoLineTo (JNIEnv *env, jobject, jdouble, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoCurveTo (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelMoveTo (JNIEnv *env, jobject, jdouble, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelLineTo (JNIEnv *env, jobject, jdouble, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelCurveTo (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRectangle (JNIEnv *env, jobject, jdouble, jdouble, jdouble, jdouble); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClosePath (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoStroke (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoFill (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClip (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGlyphVector (JNIEnv *env, jobject, jobject, jfloat, jfloat, jint, jintArray, jfloatArray); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGdkTextLayout (JNIEnv *env, jobject, jobject, jfloat, jfloat); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_releasePeerGraphicsResource (JNIEnv *env, jclass, jobject); - -#ifdef __cplusplus -} -#endif - -#endif /* __gnu_java_awt_peer_gtk_GdkGraphics2D__ */ diff --git a/include/gnu_java_awt_peer_gtk_GdkTextLayout.h b/include/gnu_java_awt_peer_gtk_GdkTextLayout.h index c74a574e7..a9b0de654 100644 --- a/include/gnu_java_awt_peer_gtk_GdkTextLayout.h +++ b/include/gnu_java_awt_peer_gtk_GdkTextLayout.h @@ -15,6 +15,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_getExtents (JNIE JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_indexToPos (JNIEnv *env, jobject, jint, jdoubleArray); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_initState (JNIEnv *env, jobject); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_dispose (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_cairoDrawGdkTextLayout (JNIEnv *env, jobject, jobject, jfloat, jfloat); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_initStaticState (JNIEnv *env, jclass); JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_getOutline (JNIEnv *env, jobject, jobject); diff --git a/include/gnu_java_awt_peer_gtk_GtkImage.h b/include/gnu_java_awt_peer_gtk_GtkImage.h index 48940a1ca..6c6539d78 100644 --- a/include/gnu_java_awt_peer_gtk_GtkImage.h +++ b/include/gnu_java_awt_peer_gtk_GtkImage.h @@ -14,11 +14,9 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_getPixels (JNIEn JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_setPixels (JNIEnv *env, jobject, jintArray); JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_loadPixbuf (JNIEnv *env, jobject, jstring); JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_loadImageFromData (JNIEnv *env, jobject, jbyteArray); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_createPixmap (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_freePixmap (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixmap (JNIEnv *env, jobject, jobject, jint); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaled (JNIEnv *env, jobject, jobject, jint, jint, jint, jint, jint, jint, jint, jboolean); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaledFlipped (JNIEnv *env, jobject, jobject, jint, jint, jint, jboolean, jboolean, jint, jint, jint, jint, jint, jint, jint, jint, jboolean); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_createPixbuf (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_freePixbuf (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixbuf (JNIEnv *env, jobject, jobject, jint); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_createFromPixbuf (JNIEnv *env, jobject); #ifdef __cplusplus diff --git a/native/jni/gtk-peer/Makefile.am b/native/jni/gtk-peer/Makefile.am index 4b113c978..c19f064f2 100644 --- a/native/jni/gtk-peer/Makefile.am +++ b/native/jni/gtk-peer/Makefile.am @@ -1,9 +1,11 @@ nativeexeclib_LTLIBRARIES = libgtkpeer.la # GTK JNI sources. -libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c \ +libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_CairoSurface.c \ + gnu_java_awt_peer_gtk_CairoGraphics2D.c \ + gnu_java_awt_peer_gtk_ComponentGraphics.c \ + gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c \ gnu_java_awt_peer_gtk_GdkFontPeer.c \ - gnu_java_awt_peer_gtk_GdkGraphics2D.c \ gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c \ gnu_java_awt_peer_gtk_GdkPixbufDecoder.c \ gnu_java_awt_peer_gtk_GdkRobotPeer.c \ diff --git a/native/jni/gtk-peer/cairographics2d.h b/native/jni/gtk-peer/cairographics2d.h new file mode 100644 index 000000000..2be915cf6 --- /dev/null +++ b/native/jni/gtk-peer/cairographics2d.h @@ -0,0 +1,118 @@ +/* cairographics2d.h -- + Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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. */ + +#ifndef CAIROGRAPHICS2D_H +#define CAIROGRAPHICS2D_H + + +#include <cairo.h> +#include <gtk/gtk.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <config.h> +#include "native_state.h" +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include <jni.h> + +/* + * These public final constants are part of the java2d public API, so we + * write them explicitly here to save fetching them from the constant pool + * all the time. + */ +enum java_awt_alpha_composite_rule + { + java_awt_alpha_composite_CLEAR = 1, + java_awt_alpha_composite_SRC = 2, + java_awt_alpha_composite_SRC_OVER = 3, + java_awt_alpha_composite_DST_OVER = 4, + java_awt_alpha_composite_SRC_IN = 5, + java_awt_alpha_composite_DST_IN = 6, + java_awt_alpha_composite_SRC_OUT = 7, + java_awt_alpha_composite_DST_OUT = 8, + java_awt_alpha_composite_DST = 9, + java_awt_alpha_composite_SRC_ATOP = 10, + java_awt_alpha_composite_DST_ATOP = 11, + java_awt_alpha_composite_XOR = 12 + }; + +enum java_awt_basic_stroke_join_rule + { + java_awt_basic_stroke_JOIN_MITER = 0, + java_awt_basic_stroke_JOIN_ROUND = 1, + java_awt_basic_stroke_JOIN_BEVEL = 2 + }; + +enum java_awt_basic_stroke_cap_rule + { + java_awt_basic_stroke_CAP_BUTT = 0, + java_awt_basic_stroke_CAP_ROUND = 1, + java_awt_basic_stroke_CAP_SQUARE = 2 + }; + +enum java_awt_geom_path_iterator_winding_rule + { + java_awt_geom_path_iterator_WIND_EVEN_ODD = 0, + java_awt_geom_path_iterator_WIND_NON_ZERO = 1 + }; + +enum java_awt_rendering_hints_filter + { + java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR = 0, + java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR = 1, + java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED = 2, + java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY = 3, + java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT = 4 + + }; + +/** + * A structure which basically contains the cairo_t pointer. + * The rest is for gradient and texture fills. + */ +struct cairographics2d +{ + cairo_t *cr; + cairo_surface_t *pattern_surface; + cairo_pattern_t *pattern; + char *pattern_pixels; +}; + +cairo_t *CairoGraphics2D_getCairoT(JNIEnv *env, jobject cairographics2dobj); + +#endif diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c new file mode 100644 index 000000000..1571434ce --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c @@ -0,0 +1,755 @@ +/* gnu_java_awt_peer_gtk_CairoGraphics2d.c + Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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. */ + +#include "jcl.h" +#include "gdkfont.h" +#include "cairographics2d.h" +#include "gnu_java_awt_peer_gtk_CairoGraphics2D.h" +#include <gdk/gdktypes.h> +#include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> + +#include <cairo-ft.h> +#include <cairo-xlib.h> + +#include <stdio.h> +#include <stdlib.h> + +static void install_font_peer(cairo_t *cr, struct peerfont *pfont); +static void update_pattern_transform (struct cairographics2d *gr); +static struct cairographics2d *getPointer(JNIEnv *env, jobject obj); + +static struct cairographics2d * +getPointer(JNIEnv *env, jobject obj) +{ + jclass cls; + jlong value; + jfieldID nofid; + cls = (*env)->GetObjectClass( env, obj ); + nofid = (*env)->GetFieldID( env, cls, "nativePointer", "J" ); + value = (*env)->GetLongField( env, obj, nofid ); + (*env)->DeleteLocalRef( env, cls ); + + return (struct cairographics2d *) value; +} + +/** + * Returns the cairo_t * associated with a CairoGraphics2D object, + * This is used by GdkTextLayout. + */ +cairo_t *CairoGraphics2D_getCairoT(JNIEnv *env, jobject cairographics2dobj) +{ + struct cairographics2d *gr = getPointer(env, cairographics2dobj); + g_assert(gr != NULL); + return gr->cr; +} + +/** + * Allocates the cairographics2d structure. + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_init + (JNIEnv *env, jobject obj, jlong cairo_t_pointer) +{ + struct cairographics2d *g = NULL; + g_assert( cairo_t_pointer != NULL); + + g = (struct cairographics2d *) g_malloc (sizeof (struct cairographics2d)); + + g_assert (g != NULL); + memset (g, 0, sizeof(struct cairographics2d)); + g->cr = (cairo_t *)cairo_t_pointer; + + return ((jlong)g); +} + +/** + * Disposes of the cairographics2d structure. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_disposeNative + (JNIEnv *env, jobject obj) +{ + struct cairographics2d *gr = getPointer(env, obj); + + if (gr == NULL) + return; + + if (gr->cr) + cairo_destroy (gr->cr); + + if (gr->pattern) + cairo_pattern_destroy (gr->pattern); + gr->pattern = NULL; + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); + gr->pattern_surface = NULL; + + g_free( gr ); +} + +/** + * Set the gradient. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setGradient + (JNIEnv *env, jobject obj, + jdouble x1, jdouble y1, + jdouble x2, jdouble y2, + jint r1, jint g1, jint b1, jint a1, + jint r2, jint g2, jint b2, jint a2, + jboolean cyclic) +{ + struct cairographics2d *gr = NULL; + cairo_surface_t *surf = NULL; + cairo_t *cr2 = NULL; + cairo_matrix_t mat; + + gr = getPointer (env, obj); + g_assert (gr != NULL); + + if (cyclic == JNI_TRUE) + surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 3, 2); + else + surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 2, 2); + g_assert (surf != NULL); + + cr2 = cairo_create (surf); + + cairo_identity_matrix (cr2); + + cairo_set_source_rgba (cr2, r1 / 255.0, g1 / 255.0, b1 / 255.0, a1 / 255.0); + cairo_rectangle (cr2, 0, 0, 1, 2); + cairo_fill (cr2); + + cairo_set_source_rgba (cr2, r2 / 255.0, g2 / 255.0, b2 / 255.0, a2 / 255.0); + cairo_rectangle (cr2, 1, 0, 1, 2); + cairo_fill (cr2); + + if (cyclic == JNI_TRUE) + { + cairo_set_source_rgba (cr2, r1 / 255.0, g1 / 255.0, b1 / 255.0, a1 / 255.0); + cairo_rectangle (cr2, 2, 0, 1, 2); + cairo_fill (cr2); + } + + cairo_matrix_init_identity (&mat); + + /* + consider the vector [x2 - x1, y2 - y1] = [p,q] + + this is a line in space starting at an 'origin' x1, y1. + + it can also be thought of as a "transformed" unit vector in either the + x or y directions. we have just *drawn* our gradient as a unit vector + (well, a 2-3x unit vector) in the x dimension. so what we want to know + is which transformation turns our existing unit vector into [p,q]. + + which means solving for M in + + [p,q] = M[1,0] + + [p,q] = |a b| [1,0] + |c d| + + [p,q] = [a,c], with b = d = 0. + + what does this mean? it means that our gradient is 1-dimensional; as + you move through the x axis of our 2 or 3 pixel gradient from logical + x positions 0 to 1, the transformation of your x coordinate under the + matrix M causes you to accumulate both x and y values in fill + space. the y value of a gradient coordinate is ignored, since the + gradient is one dimensional. which is correct. + + unfortunately we want the opposite transformation, it seems, because of + the way cairo is going to use this transformation. I'm a bit confused by + that, but it seems to work right, so we take reciprocals of values and + negate offsets. oh well. + + */ + { + double a = (x2 - x1 == 0.) ? 0. : ((cyclic ? 3.0 : 2.0) / (x2 - x1)); + double c = (y2 - y1 == 0.) ? 0. : (1. / (y2 - y1)); + double dx = (x1 == 0.) ? 0. : 1. / x1; + double dy = (y1 == 0.) ? 0. : 1. / y1; + cairo_pattern_t *p; + + cairo_matrix_init (&mat, + a, 0., + c, 0., + dx, dy); + + p = cairo_pattern_create_for_surface (surf); + cairo_pattern_set_matrix (p, &mat); + cairo_pattern_set_filter (p, CAIRO_FILTER_BILINEAR); + } + + /* FIXME: repeating gradients (not to mention hold gradients) don't seem to work. */ + /* cairo_surface_set_repeat (surf, cyclic ? 1 : 0); */ + + if (gr->pattern) + cairo_pattern_destroy (gr->pattern); + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); + + if (gr->pattern_pixels) + g_free (gr->pattern_pixels); + + gr->pattern_pixels = NULL; + gr->pattern_surface = surf; + gr->pattern = cairo_pattern_create_for_surface(surf); + + cairo_set_source (gr->cr, gr->pattern); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setTexturePixels + (JNIEnv *env, jobject obj, jintArray jarr, jint w, jint h, jint stride) +{ + struct cairographics2d *gr = NULL; + jint *jpixels = NULL; + + gr = getPointer (env, obj); + g_assert (gr != NULL); + + if (gr->pattern) + cairo_pattern_destroy (gr->pattern); + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); + + if (gr->pattern_pixels) + g_free (gr->pattern_pixels); + + gr->pattern = NULL; + gr->pattern_surface = NULL; + gr->pattern_pixels = NULL; + + gr->pattern_pixels = (char *) g_malloc (h * stride * 4); + g_assert (gr->pattern_pixels != NULL); + + jpixels = (*env)->GetIntArrayElements (env, jarr, NULL); + g_assert (jpixels != NULL); + memcpy (gr->pattern_pixels, jpixels, h * stride * 4); + (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0); + + gr->pattern_surface = cairo_image_surface_create_for_data ((unsigned char *)gr->pattern_pixels, + CAIRO_FORMAT_ARGB32, + w, h, stride * 4); + g_assert (gr->pattern_surface != NULL); + gr->pattern = cairo_pattern_create_for_surface (gr->pattern_surface); + g_assert (gr->pattern != NULL); + cairo_pattern_set_extend (gr->pattern, CAIRO_EXTEND_REPEAT); + cairo_set_source (gr->cr, gr->pattern); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_drawPixels + (JNIEnv *env, jobject obj, jintArray java_pixels, + jint w, jint h, jint stride, jdoubleArray java_matrix) +{ + jint *native_pixels = NULL; + jdouble *native_matrix = NULL; + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + native_pixels = (*env)->GetIntArrayElements (env, java_pixels, NULL); + native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); + g_assert (native_pixels != NULL); + g_assert (native_matrix != NULL); + g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); + + { + cairo_matrix_t mat; + cairo_pattern_t *p; + cairo_surface_t *surf = cairo_image_surface_create_for_data ((unsigned char *)native_pixels, + CAIRO_FORMAT_ARGB32, + w, h, stride * 4); + cairo_matrix_init_identity (&mat); + cairo_matrix_init (&mat, + native_matrix[0], native_matrix[1], + native_matrix[2], native_matrix[3], + native_matrix[4], native_matrix[5]); + + p = cairo_pattern_create_for_surface (surf); + cairo_pattern_set_matrix (p, &mat); + if (gr->pattern) + cairo_pattern_set_filter (p, cairo_pattern_get_filter (gr->pattern)); + cairo_set_source (gr->cr, p); + cairo_paint (gr->cr); + cairo_pattern_destroy (p); + cairo_surface_destroy (surf); + } + + (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0); + (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetMatrix + (JNIEnv *env, jobject obj, jdoubleArray java_matrix) +{ + jdouble *native_matrix = NULL; + struct cairographics2d *gr = getPointer (env, obj); + + native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); + g_assert (native_matrix != NULL); + g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); + + { + cairo_matrix_t mat; + + cairo_matrix_init_identity (&mat); + cairo_matrix_init (&mat, + native_matrix[0], native_matrix[1], + native_matrix[2], native_matrix[3], + native_matrix[4], native_matrix[5]); + cairo_set_matrix (gr->cr, &mat); + } + + (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); + update_pattern_transform (gr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector + (JNIEnv *env, jobject obj, + jobject font, + jfloat x, jfloat y, jint n, + jintArray java_codes, + jfloatArray java_positions) +{ + + struct cairographics2d *gr = NULL; + struct peerfont *pfont = NULL; + cairo_glyph_t *glyphs = NULL; + int *native_codes; + float *native_positions; + jint i = 0; + + g_assert (obj != NULL); + g_assert (java_codes != NULL); + g_assert (java_positions != NULL); + + gr = getPointer (env, obj); + g_assert (gr != NULL); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); + g_assert (pfont != NULL); + + install_font_peer(gr->cr, pfont); + + glyphs = g_malloc( sizeof(cairo_glyph_t) * n); + g_assert (glyphs != NULL); + + native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); + native_positions = (*env)->GetFloatArrayElements (env, java_positions, NULL); + + for (i = 0; i < n; ++i) + { + glyphs[i].index = native_codes[i]; + glyphs[i].x = x + native_positions[ 2*i ]; + glyphs[i].y = y + native_positions[ 2*i + 1]; + } + + (*env)->ReleaseFloatArrayElements (env, java_positions, native_positions, 0); + (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); + + cairo_show_glyphs (gr->cr, glyphs, n); + + g_free(glyphs); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetOperator + (JNIEnv *env, jobject obj, jint op) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + switch ((enum java_awt_alpha_composite_rule) op) + { + case java_awt_alpha_composite_CLEAR: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_CLEAR); + break; + + case java_awt_alpha_composite_SRC: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_SOURCE); + break; + + case java_awt_alpha_composite_SRC_OVER: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER); + break; + + case java_awt_alpha_composite_DST_OVER: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OVER); + break; + + case java_awt_alpha_composite_SRC_IN: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN); + break; + + case java_awt_alpha_composite_DST_IN: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_IN); + break; + + case java_awt_alpha_composite_SRC_OUT: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT); + break; + + case java_awt_alpha_composite_DST_OUT: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OUT); + break; + + case java_awt_alpha_composite_DST: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST); + break; + + case java_awt_alpha_composite_SRC_ATOP: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP); + break; + + case java_awt_alpha_composite_DST_ATOP: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_ATOP); + break; + + case java_awt_alpha_composite_XOR: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_XOR); + break; + } +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetRGBAColor + (JNIEnv *env, jobject obj, jdouble r, jdouble g, jdouble b, jdouble a) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_set_source_rgba (gr->cr, r, g, b, a); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetFillRule + (JNIEnv *env, jobject obj, jint rule) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + switch ((enum java_awt_geom_path_iterator_winding_rule) rule) + { + case java_awt_geom_path_iterator_WIND_NON_ZERO: + cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_WINDING); + break; + case java_awt_geom_path_iterator_WIND_EVEN_ODD: + cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_EVEN_ODD); + break; + } +} + +/** + * Set the line style, except for dashes. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetLine + (JNIEnv *env, jobject obj, jdouble width, int cap, int join, double miterLimit) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + /* set width */ + cairo_set_line_width (gr->cr, width); + + /* set cap */ + switch ((enum java_awt_basic_stroke_cap_rule) cap) + { + case java_awt_basic_stroke_CAP_BUTT: + cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_BUTT); + break; + + case java_awt_basic_stroke_CAP_ROUND: + cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_ROUND); + break; + + case java_awt_basic_stroke_CAP_SQUARE: + cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_SQUARE); + break; + } + + /* set join */ + switch ((enum java_awt_basic_stroke_join_rule) join) + { + case java_awt_basic_stroke_JOIN_MITER: + cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_MITER); + break; + + case java_awt_basic_stroke_JOIN_ROUND: + cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_ROUND); + break; + + case java_awt_basic_stroke_JOIN_BEVEL: + cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_BEVEL); + break; + } + + /* set miter */ + cairo_set_miter_limit (gr->cr, miterLimit); +} + +/** + * Set the line dashes + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetDash + (JNIEnv *env, jobject obj, jdoubleArray dashes, jint ndash, jdouble offset) +{ + jdouble *dasharr = NULL; + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + dasharr = (*env)->GetDoubleArrayElements (env, dashes, NULL); + g_assert (dasharr != NULL); + + cairo_set_dash (gr->cr, dasharr, ndash, offset); + + (*env)->ReleaseDoubleArrayElements (env, dashes, dasharr, 0); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoNewPath + (JNIEnv *env, jobject obj) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_new_path (gr->cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoMoveTo + (JNIEnv *env, jobject obj, jdouble x, jdouble y) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_move_to (gr->cr, x, y); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoLineTo + (JNIEnv *env, jobject obj, jdouble x, jdouble y) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_line_to (gr->cr, x, y); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoCurveTo + (JNIEnv *env, jobject obj, jdouble x1, jdouble y1, jdouble x2, jdouble y2, jdouble x3, jdouble y3) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + cairo_curve_to (gr->cr, x1, y1, x2, y2, x3, y3); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelMoveTo + (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_rel_move_to (gr->cr, dx, dy); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelLineTo + (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_rel_line_to (gr->cr, dx, dy); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelCurveTo + (JNIEnv *env, jobject obj, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_rel_curve_to (gr->cr, dx1, dy1, dx2, dy2, dx3, dy3); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRectangle + (JNIEnv *env, jobject obj, jdouble x, jdouble y, jdouble width, jdouble height) +{ + struct cairographics2d *gr = getPointer (env, obj); + + cairo_rectangle (gr->cr, x, y, width, height); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoClosePath + (JNIEnv *env, jobject obj) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_close_path (gr->cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoStroke + (JNIEnv *env, jobject obj) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_stroke (gr->cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoFill + (JNIEnv *env, jobject obj) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_fill (gr->cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoClip + (JNIEnv *env, jobject obj) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + cairo_reset_clip (gr->cr); + cairo_clip (gr->cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSurfaceSetFilter + (JNIEnv *env, jobject obj, jint filter) +{ + struct cairographics2d *gr = getPointer (env, obj); + g_assert (gr != NULL); + + if (gr->pattern == NULL) + return; + + switch ((enum java_awt_rendering_hints_filter) filter) + { + case java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); + break; + case java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BILINEAR); + break; + case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_FAST); + break; + case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); + break; + case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BEST); + break; + } +} + +/************************** FONT STUFF ****************************/ +static void +install_font_peer(cairo_t *cr, + struct peerfont *pfont) +{ + cairo_font_face_t *ft; + FT_Face face = NULL; + + g_assert(cr != NULL); + g_assert(pfont != NULL); + + if (pfont->graphics_resource == NULL) + { + face = pango_ft2_font_get_face (pfont->font); + g_assert (face != NULL); + + ft = cairo_ft_font_face_create_for_ft_face (face, 0); + g_assert (ft != NULL); + + cairo_set_font_face (cr, ft); + cairo_font_face_destroy (ft); + cairo_set_font_size (cr, + (pango_font_description_get_size (pfont->desc) / + (double)PANGO_SCALE)); + ft = cairo_get_font_face (cr); + pfont->graphics_resource = ft; + } + else + { + ft = (cairo_font_face_t *) pfont->graphics_resource; + cairo_set_font_face (cr, ft); + cairo_set_font_size (cr, + (pango_font_description_get_size (pfont->desc) / + (double)PANGO_SCALE)); + } +} + +static void +update_pattern_transform (struct cairographics2d *gr) +{ + cairo_matrix_t mat; + + g_assert (gr != NULL); + if (gr->pattern == NULL) + return; + + cairo_get_matrix (gr->cr, &mat); + cairo_pattern_set_matrix (gr->pattern, &mat); +} + + diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c new file mode 100644 index 000000000..73a711068 --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c @@ -0,0 +1,279 @@ +/* gnu_java_awt_peer_gtk_CairoSurface.c + Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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. */ + +#include "jcl.h" +#include "gtkpeer.h" +#include <cairo-xlib.h> +#include <gdk/gdkx.h> + +#include "gnu_java_awt_peer_gtk_CairoSurface.h" +#include "cairographics2d.h" + +/** + * Field names in CairoSurface.java + */ +#define SURFACE "surfacePointer" +#define BUFFER "bufferPointer" + +/* prototypes */ +static void *getNativeObject( JNIEnv *env, jobject obj, const char *pointer ); +static void setNativeObject( JNIEnv *env, jobject obj, void *ptr, const char *pointer ); + +/** + * Creates a cairo surface, ARGB32, native ordering, premultiplied alpha. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_create (JNIEnv *env, jobject obj, jint width, jint height, jint stride) +{ + cairo_surface_t* surface; + void *data = g_malloc(stride * height * 4); + memset(data, 0, stride * height * 4); + setNativeObject(env, obj, data, BUFFER); + + surface = cairo_image_surface_create_for_data + (data, CAIRO_FORMAT_ARGB32, width, height, stride); + + setNativeObject(env, obj, surface, SURFACE); +} + +/** + * Destroy the surface + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_destroy (JNIEnv *env, jobject obj) +{ + void *buffer; + cairo_surface_t* surface = (cairo_surface_t *)getNativeObject(env, obj, SURFACE); + if( surface != NULL ) + cairo_surface_destroy(surface); + + buffer = getNativeObject(env, obj, BUFFER); + if( buffer != NULL ) + g_free(buffer); +} + +/** + * Gets a pixel + */ +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_nativeGetElem (JNIEnv *env, jobject obj, jint i) +{ + jint *pixeldata = (jint *)getNativeObject(env, obj, BUFFER); + + if( pixeldata == NULL ) + return 0; + + return pixeldata[i]; +} + +/** + * Sets a pixel + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_nativeSetElem +(JNIEnv *env, jobject obj, jint i, jint val) +{ + jint *pixeldata = (jint *)getNativeObject(env, obj, BUFFER); + + if( pixeldata == NULL ) + return; + + pixeldata[i] = val; +} + +/** + * Gets all pixels in an array + */ +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_getPixels +(JNIEnv *env, jobject obj, int size) +{ + jint *pixeldata, *jpixdata, i; + jintArray jpixels; + + pixeldata = (jint *)getNativeObject(env, obj, BUFFER); + g_assert(pixeldata != NULL); + + jpixels = (*env)->NewIntArray (env, size); + jpixdata = (*env)->GetIntArrayElements (env, jpixels, NULL); + memcpy (jpixdata, pixeldata, size); + +#ifndef WORDS_BIGENDIAN + /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */ + for (i = 0; i < size; ++i) + { + jpixdata[i] = SWAPU32 ((unsigned)jpixdata[i]); + } +#endif + + (*env)->ReleaseIntArrayElements (env, jpixels, jpixdata, 0); + return jpixels; +} + +/** + * Sets all pixels by an array. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_setPixels +(JNIEnv *env, jobject obj, jintArray jpixels) +{ + jint *pixeldata, *jpixdata, i; + + pixeldata = (jint *)getNativeObject(env, obj, BUFFER); + g_assert(pixeldata != NULL); + + jpixdata = (*env)->GetIntArrayElements (env, jpixels, NULL); + int size = (*env)->GetArrayLength( env, jpixels ); + memcpy (pixeldata, jpixdata, size); + +#ifndef WORDS_BIGENDIAN + /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */ + for (i = 0; i < size; ++i) + { + jpixdata[i] = SWAPU32 ((unsigned)jpixdata[i]); + } +#endif + + (*env)->ReleaseIntArrayElements (env, jpixels, jpixdata, 0); + return jpixels; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_drawSurface + (JNIEnv *env, jobject obj, jobject context, jdoubleArray java_matrix) +{ + cairo_t *cr; + jdouble *native_matrix = NULL; + cairo_surface_t* surface = (cairo_surface_t *)getNativeObject(env, obj, SURFACE); + g_assert(surface != NULL); + + cr = CairoGraphics2D_getCairoT(env, context); + g_assert(cr != NULL); + + native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); + g_assert (native_matrix != NULL); + g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); + + { + cairo_matrix_t mat; + cairo_pattern_t *p; + cairo_matrix_init_identity (&mat); + cairo_matrix_init (&mat, + native_matrix[0], native_matrix[1], + native_matrix[2], native_matrix[3], + native_matrix[4], native_matrix[5]); + + p = cairo_pattern_create_for_surface (surface); + cairo_pattern_set_matrix (p, &mat); + + cairo_set_source(cr, p); + cairo_paint(cr); + } + + (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); +} + +/** + * Create and return a cairo context for drawing to the surface. + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_newCairoContext (JNIEnv *env, jobject obj) +{ + cairo_surface_t* surface = (cairo_surface_t *)getNativeObject(env, obj, SURFACE); + g_assert(surface != NULL); + cairo_t *ptr = cairo_create(surface); + g_assert(ptr != NULL); + + return (jlong)ptr; +} + +/** + * copyArea. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_copyAreaNative (JNIEnv *env, jobject obj, + jint x, jint y, jint w, jint h, + jint dx, jint dy, jint stride) +{ + int row; + long srcOffset, dstOffset; + jint *pixeldata = (jint *)getNativeObject(env, obj, BUFFER); + + if( pixeldata == NULL ) + return; + + srcOffset = x + y * stride; + dstOffset = (x + dx) + (y + dy) * stride; + for( row = 0; row < h; row++) + { + memcpy(pixeldata + dstOffset, pixeldata + srcOffset, w * 4); + srcOffset += stride; + dstOffset += stride; + } +} + +/* + * Sets the native object field. + */ +static void +setNativeObject( JNIEnv *env, jobject obj, void *ptr, const char *pointer ) +{ + jclass cls; + jlong value; + jfieldID nofid; + cls = (*env)->GetObjectClass( env, obj ); + value = ((jlong)ptr); + nofid = (*env)->GetFieldID( env, cls, pointer, "J" ); + (*env)->SetLongField( env, obj, nofid, value ); + (*env)->DeleteLocalRef( env, cls ); +} + +/** + * Gets the native object field. + */ +static void * +getNativeObject( JNIEnv *env, jobject obj, const char *pointer ) +{ + jclass cls; + jlong value; + jfieldID nofid; + cls = (*env)->GetObjectClass( env, obj ); + nofid = (*env)->GetFieldID( env, cls, pointer, "J" ); + value = (*env)->GetLongField( env, obj, nofid ); + (*env)->DeleteLocalRef( env, cls ); + return (void *) value; +} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c new file mode 100644 index 000000000..ee5df8ab6 --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c @@ -0,0 +1,148 @@ +/* gnu_java_awt_peer_gtk_ComponentGraphics.c + Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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. */ + +#include "jcl.h" +#include "gtkpeer.h" +#include <cairo-xlib.h> +#include <gdk/gdktypes.h> +#include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> +#include <X11/extensions/Xrender.h> + +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdk-pixbuf/gdk-pixdata.h> + +#include <cairo-ft.h> +#include <cairo-xlib.h> + +#include <stdio.h> +#include <stdlib.h> + +#include "gnu_java_awt_peer_gtk_ComponentGraphics.h" + + +static void +grab_current_drawable (GtkWidget *widget, GdkDrawable **draw, GdkWindow **win) +{ + g_assert (widget != NULL); + g_assert (draw != NULL); + g_assert (win != NULL); + + *win = widget->window; + + *draw = *win; + gdk_window_get_internal_paint_info (*win, draw, 0, 0); + g_object_ref (*draw); + /* FIXME: Unref this. */ +} + +/** + * Returns whether the XRender extension is supported + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_hasXRender (JNIEnv *env, jclass cls) +{ + int ev = 0, err = 0; + if( XRenderQueryExtension (GDK_DISPLAY (), &ev, &err) ) + return JNI_TRUE; + return JNI_FALSE; +} + + +JNIEXPORT jlong JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_initState (JNIEnv *env, jobject obj, + jobject peer) +{ + Drawable draw; + Display * dpy; + Visual * vis; + GdkDrawable *drawable; + cairo_surface_t *surface; + GdkWindow *win; + GtkWidget *widget = NULL; + void *ptr = NULL; + int width, height; + cairo_t *cr; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, peer); + g_assert (ptr != NULL); + + widget = GTK_WIDGET (ptr); + g_assert (widget != NULL); + + grab_current_drawable (widget, &drawable, &win); + g_assert (drawable != NULL); + + width = widget->allocation.width; + height = widget->allocation.height; + + g_assert (drawable != NULL); + + draw = gdk_x11_drawable_get_xid(drawable); + g_assert (draw != NULL); + + dpy = gdk_x11_drawable_get_xdisplay(drawable); + g_assert (dpy != NULL); + + vis = gdk_x11_visual_get_xvisual(gdk_drawable_get_visual(drawable)); + g_assert (vis != NULL); + + surface = cairo_xlib_surface_create (dpy, draw, vis, width, height); + g_assert (surface != NULL); + + cr = cairo_create (surface); + g_assert(cr != NULL); + + gdk_threads_leave(); + + return (jlong)cr; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_start_1gdk_1drawing (JNIEnv *env, jobject obj) +{ + gdk_threads_enter(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_end_1gdk_1drawing (JNIEnv *env, jobject obj) +{ + gdk_threads_leave(); +} + diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c index c0f776b20..8b5609141 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c @@ -121,6 +121,25 @@ Java_gnu_java_awt_peer_gtk_GdkFontPeer_dispose } +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_releasePeerGraphicsResource + (JNIEnv *env, jobject java_font) +{ + struct peerfont *pfont = NULL; + + gdk_threads_enter(); + + pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); + g_assert (pfont != NULL); + if (pfont->graphics_resource != NULL) + { + cairo_font_face_destroy ((cairo_font_face_t *) pfont->graphics_resource); + pfont->graphics_resource = NULL; + } + + gdk_threads_leave(); +} + JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector (JNIEnv *env, jobject self, diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c deleted file mode 100644 index 56c13b6c1..000000000 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c +++ /dev/null @@ -1,1898 +0,0 @@ -/* gnu_java_awt_peer_gtk_GdkGraphics2d.c - Copyright (C) 2003, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 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. */ - -#include "jcl.h" -#include "gdkfont.h" -#include "gnu_java_awt_peer_gtk_GdkGraphics2D.h" -#include <gdk/gdktypes.h> -#include <gdk/gdkprivate.h> -#include <gdk/gdkx.h> -#include <X11/extensions/Xrender.h> - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gdk-pixbuf/gdk-pixdata.h> - -#include <cairo-ft.h> -#include <cairo-xlib.h> - -#include <stdio.h> -#include <stdlib.h> - -struct state_table *cp_gtk_native_graphics2d_state_table; - -/* - * AWT applications may call Graphics methods from threads other than - * the GDK main thread, so we must call XFlush after each batch of - * drawing operations, otherwise animations flicker. Flushing after - * every graphics operation is excessive and negatively affects - * performance (PR 26486). We set the maximum frequency to 50 times - * per second, or a minimum period of 20 milliseconds between calls to - * XFlush. See gnu.classpath.examples.awt.AnimationApplet for an - * example applet that requires these XFlush calls. - */ - -static short flush_scheduled = 0; - -static gboolean flush (gpointer data __attribute__((unused))) -{ - gdk_threads_enter (); - - XFlush (GDK_DISPLAY ()); - flush_scheduled = 0; - - gdk_threads_leave (); - - return FALSE; -} - -/* The minimum time period between calls to XFlush, in - milliseconds. */ -#define MINIMUM_FLUSH_PERIOD 20 - -/* schedule_flush must be called with the GDK lock held. */ -static void -schedule_flush () -{ - if (!flush_scheduled) - { - g_timeout_add (MINIMUM_FLUSH_PERIOD, flush, NULL); - flush_scheduled = 1; - } -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initStaticState - (JNIEnv *env, jclass clazz) -{ - gdk_threads_enter(); - - NSA_G2D_INIT (env, clazz); - - gdk_threads_leave(); -} - -/* these public final constants are part of the java2d public API, so we - write them explicitly here to save fetching them from the constant pool - all the time. */ - -#ifndef min -#define min(x,y) ((x) < (y) ? (x) : (y)) -#endif - -enum java_awt_alpha_composite_rule - { - java_awt_alpha_composite_CLEAR = 1, - java_awt_alpha_composite_SRC = 2, - java_awt_alpha_composite_SRC_OVER = 3, - java_awt_alpha_composite_DST_OVER = 4, - java_awt_alpha_composite_SRC_IN = 5, - java_awt_alpha_composite_DST_IN = 6, - java_awt_alpha_composite_SRC_OUT = 7, - java_awt_alpha_composite_DST_OUT = 8, - java_awt_alpha_composite_DST = 9, - java_awt_alpha_composite_SRC_ATOP = 10, - java_awt_alpha_composite_DST_ATOP = 11, - java_awt_alpha_composite_XOR = 12 - }; - -enum java_awt_basic_stroke_join_rule - { - java_awt_basic_stroke_JOIN_MITER = 0, - java_awt_basic_stroke_JOIN_ROUND = 1, - java_awt_basic_stroke_JOIN_BEVEL = 2 - }; - -enum java_awt_basic_stroke_cap_rule - { - java_awt_basic_stroke_CAP_BUTT = 0, - java_awt_basic_stroke_CAP_ROUND = 1, - java_awt_basic_stroke_CAP_SQUARE = 2 - }; - -enum java_awt_geom_path_iterator_winding_rule - { - java_awt_geom_path_iterator_WIND_EVEN_ODD = 0, - java_awt_geom_path_iterator_WIND_NON_ZERO = 1 - }; - -enum java_awt_rendering_hints_filter - { - java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR = 0, - java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR = 1, - java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED = 2, - java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY = 3, - java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT = 4 - - }; - -static int -peer_is_disposed(JNIEnv *env, jobject obj) -{ - static jfieldID fid = NULL; - jclass cls; - jobject peer; - - if (fid == NULL) - { - cls = (*env)->GetObjectClass(env, obj); - fid = (*env)->GetFieldID(env, cls, "component", - "Lgnu/java/awt/peer/gtk/GtkComponentPeer;"); - } - g_assert(fid != NULL); - peer = (*env)->GetObjectField(env, obj, fid); - if (peer == NULL || NSA_GET_PTR (env, peer) != NULL) - return 0; - else - return 1; -} - -static void -grab_current_drawable (GtkWidget *widget, GdkDrawable **draw, GdkWindow **win) -{ - g_assert (widget != NULL); - g_assert (draw != NULL); - g_assert (win != NULL); - - *win = widget->window; - - *draw = *win; - gdk_window_get_internal_paint_info (*win, draw, 0, 0); - g_object_ref (*draw); -} - - -static int -x_server_has_render_extension (void) -{ - int ev = 0, err = 0; - return (int) XRenderQueryExtension (GDK_DISPLAY (), &ev, &err); -} - -static void -init_graphics2d_as_pixbuf (struct graphics2d *gr) -{ - gint width, height; - gint bits_per_sample = 8; - gint total_channels = 4; - gboolean has_alpha = TRUE; - - g_assert (gr != NULL); - g_assert (gr->drawable != NULL); - - if (gr->debug) printf ("initializing graphics2d as pixbuf\n"); - gdk_drawable_get_size (gr->drawable, &width, &height); - gr->drawbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - has_alpha, bits_per_sample, - width, height); - g_assert (gr->drawbuf != NULL); - g_assert (gdk_pixbuf_get_bits_per_sample (gr->drawbuf) == bits_per_sample); - g_assert (gdk_pixbuf_get_n_channels (gr->drawbuf) == total_channels); - - gr->surface = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (gr->drawbuf), - CAIRO_FORMAT_ARGB32, - gdk_pixbuf_get_width (gr->drawbuf), - gdk_pixbuf_get_height (gr->drawbuf), - gdk_pixbuf_get_rowstride (gr->drawbuf)); - g_assert (gr->surface != NULL); - gr->mode = MODE_DRAWABLE_NO_RENDER; - if (gr->cr != NULL) - cairo_destroy (gr->cr); - gr->cr = cairo_create (gr->surface); -} - -static void -init_graphics2d_as_renderable (struct graphics2d *gr) -{ - Drawable draw; - Display * dpy; - Visual * vis; - - g_assert (gr != NULL); - g_assert (gr->drawable != NULL); - - gr->drawbuf = NULL; - - if (gr->debug) printf ("initializing graphics2d as renderable\n"); - draw = gdk_x11_drawable_get_xid (gr->drawable); - - dpy = gdk_x11_drawable_get_xdisplay (gr->drawable); - g_assert (dpy != NULL); - - vis = gdk_x11_visual_get_xvisual (gdk_drawable_get_visual (gr->drawable)); - g_assert (vis != NULL); - - gr->surface = cairo_xlib_surface_create (dpy, draw, vis, gr->width, gr->height); - g_assert (gr->surface != NULL); - gr->mode = MODE_DRAWABLE_WITH_RENDER; - if (gr->cr != NULL) - cairo_destroy (gr->cr); - gr->cr = cairo_create (gr->surface); -} - -static void -begin_drawing_operation (JNIEnv *env, struct graphics2d * gr) -{ - cairo_status_t cst = cairo_status (gr->cr); - if (cst != CAIRO_STATUS_SUCCESS) - { - const char *detail = cairo_status_to_string (cst); - JCL_ThrowException (env, "java/lang/InternalError", detail); - (*env)->ExceptionDescribe (env); - return; - } - - switch (gr->mode) - { - case MODE_DRAWABLE_WITH_RENDER: - break; - - case MODE_DRAWABLE_NO_RENDER: - { - - gint drawable_width, drawable_height; - gint pixbuf_width, pixbuf_height; - gint width, height; - - gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); - pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); - pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); - width = min (drawable_width, pixbuf_width); - height = min (drawable_height, pixbuf_height); - - gdk_pixbuf_get_from_drawable (gr->drawbuf, /* destination pixbuf */ - gr->drawable, - NULL, /* colormap */ - 0, 0, 0, 0, - width, height); - - if (gr->debug) printf ("copied (%d, %d) pixels from GDK drawable to pixbuf\n", - width, height); - } - break; - - case MODE_JAVA_ARRAY: - { - jboolean isCopy; - gr->javabuf = (*env)->GetPrimitiveArrayCritical (env, gr->jarray, &isCopy); - gr->isCopy |= isCopy; - if (gr->isCopy) - { - /* Make sure that the pixel buffer copy is already initalized, - i.e. we already failed to get direct access in initState. */ - g_assert (gr->javabuf_copy != NULL); - memcpy (gr->javabuf_copy, gr->javabuf, gr->width * gr->height * 4); - } - } - break; - } -} - -static void -end_drawing_operation (JNIEnv *env, struct graphics2d * gr) -{ - cairo_status_t cst = cairo_status (gr->cr); - if (cst != CAIRO_STATUS_SUCCESS) - { - /* Report error. */ - const char *detail = cairo_status_to_string (cst); - JCL_ThrowException (env, "java/lang/InternalError", detail); - (*env)->ExceptionDescribe (env); - - /* Recreate cairo status. */ - cairo_destroy (gr->cr); - gr->cr = cairo_create (gr->surface); - return; - } - - switch (gr->mode) - { - case MODE_DRAWABLE_WITH_RENDER: - break; - - case MODE_DRAWABLE_NO_RENDER: - { - - gint drawable_width, drawable_height; - gint pixbuf_width, pixbuf_height; - gint width, height; - - gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); - pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); - pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); - width = min (drawable_width, pixbuf_width); - height = min (drawable_height, pixbuf_height); - - gdk_draw_pixbuf (gr->drawable, NULL, gr->drawbuf, - 0, 0, 0, 0, - width, height, - GDK_RGB_DITHER_NORMAL, 0, 0); - - if (gr->debug) printf ("copied (%d, %d) pixels from pixbuf to GDK drawable\n", - width, height); - } - break; - - case MODE_JAVA_ARRAY: - if (gr->isCopy) - memcpy (gr->javabuf, gr->javabuf_copy, gr->width * gr->height * 4); - (*env)->ReleasePrimitiveArrayCritical (env, gr->jarray, gr->javabuf, JNI_COMMIT); - } - - schedule_flush (); -} - - -static void -update_pattern_transform (struct graphics2d *gr) -{ - cairo_matrix_t mat; - - g_assert (gr != NULL); - if (gr->pattern == NULL) - return; - - cairo_get_matrix (gr->cr, &mat); - cairo_pattern_set_matrix (gr->pattern, &mat); -} - -static void -check_for_debug (struct graphics2d *gr) -{ - gr->debug = (gboolean)(getenv("DEBUGJ2D") != NULL); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState - (JNIEnv *env, jobject obj, jobject old) -{ - struct graphics2d *g = NULL, *g_old = NULL; - - gdk_threads_enter(); - - g = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); - g_assert (g != NULL); - memset (g, 0, sizeof(struct graphics2d)); - - g_old = (struct graphics2d *) NSA_GET_G2D_PTR (env, old); - g_assert (g_old != NULL); - - if (g_old->debug) printf ("copying state from existing graphics2d\n"); - - g->debug = g_old->debug; - g->mode = g_old->mode; - - g->width = g_old->width; - g->height = g_old->height; - - if (g_old->mode == MODE_JAVA_ARRAY) - { - jint size = g->width * g->height * 4; - - g->jarray = (*env)->NewGlobalRef (env, g_old->jarray); - g->javabuf = (*env)->GetIntArrayElements (env, g->jarray, &g->isCopy); - g->isCopy = JNI_TRUE; - g->javabuf_copy = (jint *) g_malloc (size); - memcpy (g->javabuf_copy, g->javabuf, size); - g->surface = cairo_image_surface_create_for_data ((unsigned char *) g->javabuf, - CAIRO_FORMAT_ARGB32, - g->width, - g->height, - g->width * 4); - g_assert (g->surface != NULL); - g->cr = cairo_create (g->surface); - g_assert (g->cr != NULL); - (*env)->ReleaseIntArrayElements (env, g->jarray, g->javabuf, JNI_ABORT); - } - else - { - g->drawable = g_old->drawable; - g_object_ref (g->drawable); - - if (x_server_has_render_extension ()) - init_graphics2d_as_renderable (g); - else - init_graphics2d_as_pixbuf (g); - } - - if (g->pattern) - cairo_pattern_set_filter (g->pattern, CAIRO_FILTER_FAST); - - NSA_SET_G2D_PTR (env, obj, g); - - gdk_threads_leave(); -} - - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState___3III -(JNIEnv *env, jobject obj, jintArray jarr, jint width, jint height) -{ - struct graphics2d *gr = NULL; - jint *cairobuf = NULL; - - gdk_threads_enter(); - - gr = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); - g_assert (gr != NULL); - memset (gr, 0, sizeof(struct graphics2d)); - - check_for_debug (gr); - - if (gr->debug) printf ("constructing java-backed image of size (%d,%d)\n", - width, height); - - gr->width = width; - gr->height = height; - gr->jarray = (*env)->NewGlobalRef(env, jarr); - gr->javabuf = (*env)->GetPrimitiveArrayCritical (env, gr->jarray, &gr->isCopy); - if (gr->isCopy) - { - /* We didn't get direct access to the pixel buffer, so we'll have to - maintain a separate copy for Cairo. */ - jint size = gr->width * gr->height * 4; - gr->javabuf_copy = (jint *) g_malloc (size); - memcpy (gr->javabuf_copy, gr->javabuf, size); - cairobuf = gr->javabuf_copy; - } - else - { - /* Have Cairo write directly to the Java array. */ - cairobuf = gr->javabuf; - } - gr->surface = cairo_image_surface_create_for_data ((unsigned char *) cairobuf, - CAIRO_FORMAT_ARGB32, - gr->width, - gr->height, - gr->width * 4); - g_assert (gr->surface != NULL); - gr->cr = cairo_create (gr->surface); - g_assert (gr->cr != NULL); - (*env)->ReleasePrimitiveArrayCritical (env, gr->jarray, gr->javabuf, JNI_COMMIT); - - gr->mode = MODE_JAVA_ARRAY; - - if (gr->debug) printf ("constructed java-backed image of size (%d,%d)\n", - width, height); - - NSA_SET_G2D_PTR (env, obj, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II - (JNIEnv *env, jobject obj, jint width, jint height) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - gr = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); - g_assert (gr != NULL); - memset (gr, 0, sizeof(struct graphics2d)); - - check_for_debug (gr); - - if (gr->debug) printf ("constructing offscreen drawable of size (%d,%d)\n", - width, height); - - gr->drawable = (GdkDrawable *) gdk_pixmap_new (NULL, width, height, - gdk_rgb_get_visual ()->depth); - g_assert (gr->drawable != NULL); - - gr->width = width; - gr->height = height; - - if (x_server_has_render_extension ()) - init_graphics2d_as_renderable (gr); - else - init_graphics2d_as_pixbuf (gr); - - if (gr->debug) printf ("constructed offscreen drawable of size (%d,%d)\n", - width, height); - NSA_SET_G2D_PTR (env, obj, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable - (JNIEnv *env, jobject obj, jobject other, jint x, jint y) -{ - struct graphics2d *src = NULL; - struct graphics2d *dst = NULL; - gint s_height; - gint s_width; - gint d_height; - gint d_width; - gint height; - gint width; - cairo_matrix_t matrix; - cairo_operator_t tmp_op; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - src = (struct graphics2d *)NSA_GET_G2D_PTR (env, other); - dst = (struct graphics2d *)NSA_GET_G2D_PTR (env, obj); - g_assert (src != NULL); - g_assert (dst != NULL); - - if (src->debug) printf ("copying from offscreen drawable\n"); - - begin_drawing_operation(env, dst); - - /* gdk_flush(); */ - - if (!GDK_IS_DRAWABLE (src->drawable) || - !GDK_IS_DRAWABLE (dst->drawable)) - { - gdk_threads_leave (); - return; - } - - gdk_drawable_get_size (src->drawable, &s_width, &s_height); - gdk_drawable_get_size (dst->drawable, &d_width, &d_height); - width = min (s_width, d_width); - height = min (s_height, d_height); - - cairo_get_matrix (src->cr, &matrix); - cairo_matrix_translate (&matrix, (double)-x, (double)-y); - if (src->pattern) - cairo_pattern_set_matrix (src->pattern, &matrix); - tmp_op = cairo_get_operator (dst->cr); - cairo_set_operator(dst->cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_surface (dst->cr, src->surface, 0, 0); - cairo_paint (dst->cr); - cairo_set_operator(dst->cr, tmp_op); - - cairo_matrix_translate (&matrix, (double)x, (double)y); - if (src->pattern) - cairo_pattern_set_matrix (src->pattern, &matrix); - - end_drawing_operation(env, dst); - - if (src->debug) printf ("copied %d x %d pixels from offscreen drawable\n", width, height); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2 - (JNIEnv *env, jobject obj, jobject peer) -{ - struct graphics2d *gr = NULL; - GtkWidget *widget = NULL; - void *ptr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - ptr = NSA_GET_PTR (env, peer); - g_assert (ptr != NULL); - - gr = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); - g_assert (gr != NULL); - memset (gr, 0, sizeof(struct graphics2d)); - - check_for_debug (gr); - - widget = GTK_WIDGET (ptr); - g_assert (widget != NULL); - - grab_current_drawable (widget, &(gr->drawable), &(gr->win)); - g_assert (gr->drawable != NULL); - - gr->width = widget->allocation.width; - gr->height = widget->allocation.height; - - if (x_server_has_render_extension ()) - init_graphics2d_as_renderable (gr); - else - init_graphics2d_as_pixbuf (gr); - - NSA_SET_G2D_PTR (env, obj, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gr = (struct graphics2d *) NSA_DEL_G2D_PTR (env, obj); - - /* dispose has been called more than once */ - if (gr == NULL) - return; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->surface) - cairo_surface_destroy (gr->surface); - gr->surface = NULL; - - cairo_destroy (gr->cr); - gr->cr = NULL; - - if (gr->drawbuf) - g_object_unref (gr->drawbuf); - gr->drawbuf = NULL; - - if (gr->drawable) - g_object_unref (gr->drawable); - gr->drawable = NULL; - - if (gr->pattern) - cairo_pattern_destroy (gr->pattern); - gr->pattern = NULL; - - if (gr->pattern_surface) - cairo_surface_destroy (gr->pattern_surface); - gr->pattern_surface = NULL; - - if (gr->pattern_pixels) - g_free (gr->pattern_pixels); - gr->pattern_pixels = NULL; - - if (gr->mode == MODE_JAVA_ARRAY) - { - (*env)->DeleteGlobalRef (env, gr->jarray); - if (gr->javabuf_copy) - g_free (gr->javabuf_copy); - gr->javabuf_copy = NULL; - } - - if (gr->debug) printf ("disposed of graphics2d\n"); - - g_free (gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient - (JNIEnv *env, jobject obj, - jdouble x1, jdouble y1, - jdouble x2, jdouble y2, - jint r1, jint g1, jint b1, jint a1, - jint r2, jint g2, jint b2, jint a2, - jboolean cyclic) -{ - struct graphics2d *gr = NULL; - cairo_surface_t *surf = NULL; - cairo_t *cr2 = NULL; - cairo_matrix_t mat; - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->debug) - printf ("setGradient (%f,%f) -> (%f,%f); (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n", - x1, y1, - x2, y2, - r1, g1, b1, a1, - r2, g2, b2, a2); - - if (cyclic) - surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 3, 2); - else - surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 2, 2); - g_assert (surf != NULL); - - cr2 = cairo_create (surf); - - cairo_identity_matrix (cr2); - - cairo_set_source_rgba (cr2, r1 / 255.0, g1 / 255.0, b1 / 255.0, a1 / 255.0); - cairo_rectangle (cr2, 0, 0, 1, 2); - cairo_fill (cr2); - - cairo_set_source_rgba (cr2, r2 / 255.0, g2 / 255.0, b2 / 255.0, a2 / 255.0); - cairo_rectangle (cr2, 1, 0, 1, 2); - cairo_fill (cr2); - - if (cyclic) - { - cairo_set_source_rgba (cr2, r1 / 255.0, g1 / 255.0, b1 / 255.0, a1 / 255.0); - cairo_rectangle (cr2, 2, 0, 1, 2); - cairo_fill (cr2); - } - - cairo_matrix_init_identity (&mat); - - /* - consider the vector [x2 - x1, y2 - y1] = [p,q] - - this is a line in space starting at an 'origin' x1, y1. - - it can also be thought of as a "transformed" unit vector in either the - x or y directions. we have just *drawn* our gradient as a unit vector - (well, a 2-3x unit vector) in the x dimension. so what we want to know - is which transformation turns our existing unit vector into [p,q]. - - which means solving for M in - - [p,q] = M[1,0] - - [p,q] = |a b| [1,0] - |c d| - - [p,q] = [a,c], with b = d = 0. - - what does this mean? it means that our gradient is 1-dimensional; as - you move through the x axis of our 2 or 3 pixel gradient from logical - x positions 0 to 1, the transformation of your x coordinate under the - matrix M causes you to accumulate both x and y values in fill - space. the y value of a gradient coordinate is ignored, since the - gradient is one dimensional. which is correct. - - unfortunately we want the opposite transformation, it seems, because of - the way cairo is going to use this transformation. I'm a bit confused by - that, but it seems to work right, so we take reciprocals of values and - negate offsets. oh well. - - */ - { - double a = (x2 - x1 == 0.) ? 0. : ((cyclic ? 3.0 : 2.0) / (x2 - x1)); - double c = (y2 - y1 == 0.) ? 0. : (1. / (y2 - y1)); - double dx = (x1 == 0.) ? 0. : 1. / x1; - double dy = (y1 == 0.) ? 0. : 1. / y1; - cairo_pattern_t *p; - - cairo_matrix_init (&mat, - a, 0., - c, 0., - dx, dy); - - p = cairo_pattern_create_for_surface (surf); - cairo_pattern_set_matrix (p, &mat); - cairo_pattern_set_filter (p, CAIRO_FILTER_BILINEAR); - } - - /* FIXME: repeating gradients (not to mention hold gradients) don't seem to work. */ - /* cairo_surface_set_repeat (surf, cyclic ? 1 : 0); */ - - if (gr->pattern) - cairo_pattern_destroy (gr->pattern); - - if (gr->pattern_surface) - cairo_surface_destroy (gr->pattern_surface); - - if (gr->pattern_pixels) - g_free (gr->pattern_pixels); - - gr->pattern_pixels = NULL; - gr->pattern_surface = surf; - gr->pattern = cairo_pattern_create_for_surface(surf); - - cairo_set_source (gr->cr, gr->pattern); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels - (JNIEnv *env, jobject obj, jintArray jarr, jint w, jint h, jint stride) -{ - struct graphics2d *gr = NULL; - jint *jpixels = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - if (gr->debug) - printf ("setTexturePixels (%d pixels, %dx%d, stride: %d)\n", - (*env)->GetArrayLength (env, jarr), w, h, stride); - - if (gr->pattern) - cairo_pattern_destroy (gr->pattern); - - if (gr->pattern_surface) - cairo_surface_destroy (gr->pattern_surface); - - if (gr->pattern_pixels) - g_free (gr->pattern_pixels); - - gr->pattern = NULL; - gr->pattern_surface = NULL; - gr->pattern_pixels = NULL; - - gr->pattern_pixels = (char *) g_malloc (h * stride * 4); - g_assert (gr->pattern_pixels != NULL); - - jpixels = (*env)->GetIntArrayElements (env, jarr, NULL); - g_assert (jpixels != NULL); - memcpy (gr->pattern_pixels, jpixels, h * stride * 4); - (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0); - - gr->pattern_surface = cairo_image_surface_create_for_data ((unsigned char *)gr->pattern_pixels, - CAIRO_FORMAT_ARGB32, - w, h, stride * 4); - g_assert (gr->pattern_surface != NULL); - gr->pattern = cairo_pattern_create_for_surface (gr->pattern_surface); - g_assert (gr->pattern != NULL); - cairo_pattern_set_extend (gr->pattern, CAIRO_EXTEND_REPEAT); - cairo_set_source (gr->cr, gr->pattern); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels - (JNIEnv *env, jobject obj, jintArray java_pixels, - jint w, jint h, jint stride, jdoubleArray java_matrix) -{ - struct graphics2d *gr = NULL; - jint *native_pixels = NULL; - jdouble *native_matrix = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - if (gr->debug) - printf ("drawPixels (%d pixels, %dx%d, stride: %d)\n", - (*env)->GetArrayLength (env, java_pixels), w, h, stride); - - native_pixels = (*env)->GetIntArrayElements (env, java_pixels, NULL); - native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); - g_assert (native_pixels != NULL); - g_assert (native_matrix != NULL); - g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); - - begin_drawing_operation (env, gr); - - { - cairo_matrix_t mat; - cairo_pattern_t *p; - cairo_surface_t *surf = cairo_image_surface_create_for_data ((unsigned char *)native_pixels, - CAIRO_FORMAT_ARGB32, - w, h, stride * 4); - cairo_matrix_init_identity (&mat); - cairo_matrix_init (&mat, - native_matrix[0], native_matrix[1], - native_matrix[2], native_matrix[3], - native_matrix[4], native_matrix[5]); - - p = cairo_pattern_create_for_surface (surf); - cairo_pattern_set_matrix (p, &mat); - if (gr->pattern) - cairo_pattern_set_filter (p, cairo_pattern_get_filter (gr->pattern)); - cairo_set_source (gr->cr, p); - cairo_paint (gr->cr); - cairo_pattern_destroy (p); - cairo_surface_destroy (surf); - } - - end_drawing_operation (env, gr); - - (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0); - (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); - - gdk_threads_leave(); -} - -/* passthrough methods to cairo */ - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSave - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_save\n"); - cairo_save (gr->cr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRestore - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_restore\n"); - cairo_restore (gr->cr); - update_pattern_transform (gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix - (JNIEnv *env, jobject obj, jdoubleArray java_matrix) -{ - struct graphics2d *gr = NULL; - jdouble *native_matrix = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - - native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); - g_assert (native_matrix != NULL); - g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); - - if (gr->debug) - printf ("cairo_matrix_init [ %f, %f, %f, %f, %f, %f ]\n", - native_matrix[0], native_matrix[1], - native_matrix[2], native_matrix[3], - native_matrix[4], native_matrix[5]); - - { - cairo_matrix_t mat; - - cairo_matrix_init_identity (&mat); - cairo_matrix_init (&mat, - native_matrix[0], native_matrix[1], - native_matrix[2], native_matrix[3], - native_matrix[4], native_matrix[5]); - cairo_set_matrix (gr->cr, &mat); - } - - (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); - update_pattern_transform (gr); - - gdk_threads_leave(); -} - -static void -install_font_peer(cairo_t *cr, - struct peerfont *pfont, - int debug) -{ - cairo_font_face_t *ft; - FT_Face face = NULL; - - g_assert(cr != NULL); - g_assert(pfont != NULL); - - if (pfont->graphics_resource == NULL) - { - face = pango_ft2_font_get_face (pfont->font); - g_assert (face != NULL); - - ft = cairo_ft_font_face_create_for_ft_face (face, 0); - g_assert (ft != NULL); - - if (debug) printf ("install_font_peer made new cairo font for '%s' at %f\n", - face->family_name, - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - - cairo_set_font_face (cr, ft); - cairo_font_face_destroy (ft); - cairo_set_font_size (cr, - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - ft = cairo_get_font_face (cr); - pfont->graphics_resource = ft; - } - else - { - if (debug) printf ("install_font_peer reused existing font resource" - " for '%s' at %f\n", - pango_font_description_get_family(pfont->desc), - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - ft = (cairo_font_face_t *) pfont->graphics_resource; - cairo_set_font_face (cr, ft); - cairo_set_font_size (cr, - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - } -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_releasePeerGraphicsResource - (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject java_font) -{ - struct peerfont *pfont = NULL; - - gdk_threads_enter(); - - g_assert(java_font != NULL); - - pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); - g_assert (pfont != NULL); - if (pfont->graphics_resource != NULL) - { - cairo_font_face_destroy ((cairo_font_face_t *) pfont->graphics_resource); - pfont->graphics_resource = NULL; - } - - gdk_threads_leave(); -} - -static void -paint_glyph_run(JNIEnv *env, - struct graphics2d *gr, - cairo_glyph_t **glyphs, - gint *n_glyphs, - PangoLayoutRun *run) -{ - gint i = 0; - gint x = 0, y = 0; - - g_assert (gr != NULL); - g_assert (glyphs != NULL); - g_assert (n_glyphs != NULL); - g_assert (run != NULL); - - if (run->glyphs != NULL && run->glyphs->num_glyphs > 0) - { - if (*n_glyphs < run->glyphs->num_glyphs) - { - *glyphs = g_realloc(*glyphs, - (sizeof(cairo_glyph_t) - * run->glyphs->num_glyphs)); - *n_glyphs = run->glyphs->num_glyphs; - } - - g_assert (*glyphs != NULL); - - if (gr->debug) printf ("painting %d glyphs: ", run->glyphs->num_glyphs); - - for (i = 0; i < run->glyphs->num_glyphs; ++i) - { - (*glyphs)[i].index = run->glyphs->glyphs[i].glyph; - - (*glyphs)[i].x = - ((double) (x + run->glyphs->glyphs[i].geometry.x_offset)) - / ((double) PANGO_SCALE); - - (*glyphs)[i].y = - ((double) (y + run->glyphs->glyphs[i].geometry.y_offset)) - / ((double) PANGO_SCALE); - - if (gr->debug) printf(" (%ld @ %f,%f)", - (*glyphs)[i].index, - (*glyphs)[i].x, - (*glyphs)[i].y); - - x += run->glyphs->glyphs[i].geometry.width; - } - - if (gr->debug) printf("\n"); - begin_drawing_operation (env, gr); - cairo_show_glyphs (gr->cr, *glyphs, run->glyphs->num_glyphs); - end_drawing_operation (env, gr); - } -} - - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGlyphVector - (JNIEnv *env, jobject obj, - jobject font, - jfloat x, jfloat y, jint n, - jintArray java_codes, - jfloatArray java_positions) -{ - - struct graphics2d *gr = NULL; - struct peerfont *pfont = NULL; - cairo_glyph_t *glyphs = NULL; - int *native_codes; - float *native_positions; - jint i = 0; - - gdk_threads_enter (); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - g_assert (obj != NULL); - g_assert (java_codes != NULL); - g_assert (java_positions != NULL); - - gr = (struct graphics2d *)NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); - g_assert (pfont != NULL); - - install_font_peer(gr->cr, pfont, gr->debug); - - glyphs = g_malloc( sizeof(cairo_glyph_t) * n); - g_assert (glyphs != NULL); - - native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); - native_positions = (*env)->GetFloatArrayElements (env, java_positions, NULL); - - for (i = 0; i < n; ++i) - { - glyphs[i].index = native_codes[i]; - glyphs[i].x = x + native_positions[ 2*i ]; - glyphs[i].y = y + native_positions[ 2*i + 1]; - } - - (*env)->ReleaseFloatArrayElements (env, java_positions, native_positions, 0); - (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); - - begin_drawing_operation (env, gr); - cairo_show_glyphs (gr->cr, glyphs, n); - end_drawing_operation (env, gr); - - g_free(glyphs); - - gdk_threads_leave (); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGdkTextLayout - (JNIEnv *env, jobject obj, jobject java_layout, jfloat x, jfloat y) -{ - /* - * FIXME: Some day we expect either cairo or pango will know how to make - * a pango layout paint to a cairo surface. that day is not yet here. - */ - - struct graphics2d *gr = NULL; - struct textlayout *tl = NULL; - PangoLayoutIter *i = NULL; - PangoLayoutRun *run = NULL; - cairo_glyph_t *glyphs = NULL; - gint n_glyphs = 0; - - g_assert (obj != NULL); - g_assert (java_layout != NULL); - - gr = (struct graphics2d *)NSA_GET_G2D_PTR (env, obj); - tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, java_layout); - - g_assert (gr != NULL); - g_assert (tl != NULL); - g_assert (tl->pango_layout != NULL); - - if (gr->debug) printf ("painting pango layout\n"); - - gdk_threads_enter (); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - i = pango_layout_get_iter (tl->pango_layout); - g_assert (i != NULL); - - cairo_translate (gr->cr, x, y); - - do - { - run = pango_layout_iter_get_run (i); - if (run != NULL) - paint_glyph_run (env, gr, &glyphs, &n_glyphs, run); - } - while (pango_layout_iter_next_run (i)); - - if (glyphs != NULL) - g_free (glyphs); - - cairo_translate (gr->cr, -x, -y); - - pango_layout_iter_free (i); - - gdk_threads_leave (); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator - (JNIEnv *env, jobject obj, jint op) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_operator %d\n", op); - switch ((enum java_awt_alpha_composite_rule) op) - { - case java_awt_alpha_composite_CLEAR: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_CLEAR); - break; - - case java_awt_alpha_composite_SRC: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_SOURCE); - break; - - case java_awt_alpha_composite_SRC_OVER: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER); - break; - - case java_awt_alpha_composite_DST_OVER: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OVER); - break; - - case java_awt_alpha_composite_SRC_IN: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN); - break; - - case java_awt_alpha_composite_DST_IN: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_IN); - break; - - case java_awt_alpha_composite_SRC_OUT: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT); - break; - - case java_awt_alpha_composite_DST_OUT: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OUT); - break; - - case java_awt_alpha_composite_DST: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST); - break; - - case java_awt_alpha_composite_SRC_ATOP: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP); - break; - - case java_awt_alpha_composite_DST_ATOP: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_ATOP); - break; - - case java_awt_alpha_composite_XOR: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_XOR); - break; - } - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetRGBAColor - (JNIEnv *env, jobject obj, jdouble r, jdouble g, jdouble b, jdouble a) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - /* this is a very weird fact: GDK Pixbufs and RENDER drawables consider - colors in opposite pixel order. I have no idea why. thus when you - draw to a PixBuf, you must exchange the R and B components of your - color. */ - - if (gr->debug) - printf ("cairo_set_source_rgba (%f, %f, %f, %f)\n", r, g, b, a); - - if (gr->drawbuf) - cairo_set_source_rgba (gr->cr, b, g, r, a); - else - cairo_set_source_rgba (gr->cr, r, g, b, a); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFillRule - (JNIEnv *env, jobject obj, jint rule) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - if (gr->debug) printf ("cairo_set_fill_rule %d\n", rule); - g_assert (gr != NULL); - switch ((enum java_awt_geom_path_iterator_winding_rule) rule) - { - case java_awt_geom_path_iterator_WIND_NON_ZERO: - cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_WINDING); - break; - case java_awt_geom_path_iterator_WIND_EVEN_ODD: - cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_EVEN_ODD); - break; - } - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineWidth - (JNIEnv *env, jobject obj, jdouble width) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_line_width %f\n", width); - cairo_set_line_width (gr->cr, width); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineCap - (JNIEnv *env, jobject obj, jint cap) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_line_cap %d\n", cap); - switch ((enum java_awt_basic_stroke_cap_rule) cap) - { - case java_awt_basic_stroke_CAP_BUTT: - cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_BUTT); - break; - - case java_awt_basic_stroke_CAP_ROUND: - cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_ROUND); - break; - - case java_awt_basic_stroke_CAP_SQUARE: - cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_SQUARE); - break; - } - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineJoin - (JNIEnv *env, jobject obj, jint join) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_line_join %d\n", join); - switch ((enum java_awt_basic_stroke_join_rule) join) - { - case java_awt_basic_stroke_JOIN_MITER: - cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_MITER); - break; - - case java_awt_basic_stroke_JOIN_ROUND: - cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_ROUND); - break; - - case java_awt_basic_stroke_JOIN_BEVEL: - cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_BEVEL); - break; - } - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash - (JNIEnv *env, jobject obj, jdoubleArray dashes, jint ndash, jdouble offset) -{ - struct graphics2d *gr = NULL; - jdouble *dasharr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_dash\n"); - dasharr = (*env)->GetDoubleArrayElements (env, dashes, NULL); - g_assert (dasharr != NULL); - cairo_set_dash (gr->cr, dasharr, ndash, offset); - (*env)->ReleaseDoubleArrayElements (env, dashes, dasharr, 0); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMiterLimit - (JNIEnv *env, jobject obj, jdouble miter) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_miter_limit %f\n", miter); - cairo_set_miter_limit (gr->cr, miter); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoNewPath - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->debug) printf ("cairo_new_path\n"); - cairo_new_path (gr->cr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoMoveTo - (JNIEnv *env, jobject obj, jdouble x, jdouble y) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_move_to (%f, %f)\n", x, y); - cairo_move_to (gr->cr, x, y); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoLineTo - (JNIEnv *env, jobject obj, jdouble x, jdouble y) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_line_to (%f, %f)\n", x, y); - cairo_line_to (gr->cr, x, y); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoCurveTo - (JNIEnv *env, jobject obj, jdouble x1, jdouble y1, jdouble x2, jdouble y2, jdouble x3, jdouble y3) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) - printf ("cairo_curve_to (%f, %f), (%f, %f), (%f, %f)\n", - x1, y1, x2, y2, x3, y3); - cairo_curve_to (gr->cr, x1, y1, x2, y2, x3, y3); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelMoveTo - (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_rel_move_to (%f, %f)\n", dx, dy); - cairo_rel_move_to (gr->cr, dx, dy); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelLineTo - (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_rel_line_to (%f, %f)\n", dx, dy); - cairo_rel_line_to (gr->cr, dx, dy); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelCurveTo - (JNIEnv *env, jobject obj, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) - printf ("cairo_rel_curve_to (%f, %f), (%f, %f), (%f, %f)\n", - dx1, dy1, dx2, dy2, dx3, dy3); - cairo_rel_curve_to (gr->cr, dx1, dy1, dx2, dy2, dx3, dy3); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRectangle - (JNIEnv *env, jobject obj, jdouble x, jdouble y, jdouble width, jdouble height) -{ - struct graphics2d *gr = NULL; - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->debug) - printf ("cairo_rectangle (%f, %f) (%f, %f)\n", x, y, width, height); - cairo_rectangle (gr->cr, x, y, width, height); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClosePath - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_close_path\n"); - cairo_close_path (gr->cr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoStroke - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_stroke\n"); - begin_drawing_operation (env, gr); - cairo_stroke (gr->cr); - end_drawing_operation (env, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoFill - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_fill\n"); - begin_drawing_operation (env, gr); - cairo_fill (gr->cr); - end_drawing_operation (env, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClip - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->debug) printf ("cairo_clip\n"); - begin_drawing_operation (env, gr); - cairo_reset_clip (gr->cr); - cairo_clip (gr->cr); - end_drawing_operation (env, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSurfaceSetFilter - (JNIEnv *env, jobject obj, jint filter) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - if (gr->pattern == NULL) - return; - - if (gr->debug) printf ("cairo_pattern_set_filter %d\n", filter); - switch ((enum java_awt_rendering_hints_filter) filter) - { - case java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); - break; - case java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BILINEAR); - break; - case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_FAST); - break; - case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); - break; - case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BEST); - break; - } - - gdk_threads_leave(); -} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c index edce3917d..349d315b4 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c @@ -47,6 +47,7 @@ #include "native_state.h" #include "gdkfont.h" #include "gnu_java_awt_peer_gtk_GdkTextLayout.h" +#include "cairographics2d.h" struct state_table *cp_gtk_native_text_layout_state_table; @@ -60,6 +61,9 @@ typedef struct gp double sy; } generalpath ; +static void paint_glyph_run(cairo_t *cr, cairo_glyph_t **glyphs, + gint *n_glyphs, PangoLayoutRun *run); + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_initStaticState (JNIEnv *env, jclass clazz) @@ -207,6 +211,104 @@ Java_gnu_java_awt_peer_gtk_GdkTextLayout_dispose gdk_threads_leave (); } +/** + * Draw this textlayout on a cairo surface + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkTextLayout_cairoDrawGdkTextLayout + (JNIEnv *env, jobject obj, jobject cairographics, jfloat x, jfloat y) +{ + /* + * FIXME: Some day we expect either cairo or pango will know how to make + * a pango layout paint to a cairo surface. that day is not yet here. + */ + + cairo_t *cr; + struct cairographics2d *gr = NULL; + struct textlayout *tl = NULL; + PangoLayoutIter *i = NULL; + PangoLayoutRun *run = NULL; + cairo_glyph_t *glyphs = NULL; + gint n_glyphs = 0; + + g_assert (cairographics != NULL); + + cr = CairoGraphics2D_getCairoT(env, cairographics); + tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, obj); + + g_assert (cr != NULL); + g_assert (tl != NULL); + g_assert (tl->pango_layout != NULL); + + gdk_threads_enter (); + + i = pango_layout_get_iter (tl->pango_layout); + g_assert (i != NULL); + + cairo_translate (cr, x, y); + + do + { + run = pango_layout_iter_get_run (i); + if (run != NULL) + paint_glyph_run (cr, &glyphs, &n_glyphs, run); + } + while (pango_layout_iter_next_run (i)); + + if (glyphs != NULL) + g_free (glyphs); + + cairo_translate (cr, -x, -y); + + pango_layout_iter_free (i); + + gdk_threads_leave (); +} + +static void +paint_glyph_run(cairo_t *cr, + cairo_glyph_t **glyphs, + gint *n_glyphs, + PangoLayoutRun *run) +{ + gint i = 0; + gint x = 0, y = 0; + + g_assert (cr != NULL); + g_assert (glyphs != NULL); + g_assert (n_glyphs != NULL); + g_assert (run != NULL); + + if (run->glyphs != NULL && run->glyphs->num_glyphs > 0) + { + if (*n_glyphs < run->glyphs->num_glyphs) + { + *glyphs = g_realloc(*glyphs, + (sizeof(cairo_glyph_t) + * run->glyphs->num_glyphs)); + *n_glyphs = run->glyphs->num_glyphs; + } + + g_assert (*glyphs != NULL); + + for (i = 0; i < run->glyphs->num_glyphs; ++i) + { + (*glyphs)[i].index = run->glyphs->glyphs[i].glyph; + + (*glyphs)[i].x = + ((double) (x + run->glyphs->glyphs[i].geometry.x_offset)) + / ((double) PANGO_SCALE); + + (*glyphs)[i].y = + ((double) (y + run->glyphs->glyphs[i].geometry.y_offset)) + / ((double) PANGO_SCALE); + + x += run->glyphs->glyphs[i].geometry.width; + } + cairo_show_glyphs (cr, *glyphs, run->glyphs->num_glyphs); + } +} + /* GetOutline code follows ****************************/ /********* Freetype callback functions *****************************/ diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c index cb2c87238..7ce1185a4 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c @@ -242,14 +242,7 @@ clipboard_get_func (GtkClipboard *clipboard, pixbuf = cp_gtk_image_get_pixbuf (env, gtkimage); if (pixbuf != NULL) - { - gtk_selection_data_set_pixbuf (selection, pixbuf); - - /* if the GtkImage is offscreen, this is a temporary pixbuf - which should be thrown out. */ - if(cp_gtk_image_is_offscreen (env, gtkimage) == JNI_TRUE) - gdk_pixbuf_unref (pixbuf); - } + gtk_selection_data_set_pixbuf (selection, pixbuf); } else if (info == URI_TARGET) { diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c index c60f48f51..766964314 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c @@ -186,10 +186,5 @@ Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImage gtk_window_set_icon (GTK_WINDOW (ptr), pixbuf); - /* if the GtkImage is offscreen, this is a temporary pixbuf which should - be thrown out. */ - if(cp_gtk_image_is_offscreen (env, gtkimage) == JNI_TRUE) - gdk_pixbuf_unref (pixbuf); - gdk_threads_leave (); } diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c index dad6a1182..f1c82aaa7 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c @@ -51,13 +51,11 @@ exception statement from your version. */ /* local stuff */ static GdkInterpType mapHints(jint hints); -static jboolean offScreen (JNIEnv * env, jobject obj); -static void *getData (JNIEnv * env, jobject obj); static void createRawData (JNIEnv * env, jobject obj, void *ptr); static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height); /** - * Loads a pixmap from a file. + * Loads a pixbuf from a file. */ JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_loadPixbuf @@ -137,7 +135,7 @@ Java_gnu_java_awt_peer_gtk_GtkImage_createFromPixbuf (JNIEnv *env, jobject obj) { int width, heigth; - GdkPixbuf *pixbuf = (GdkPixbuf *) getData (env, obj); + GdkPixbuf *pixbuf = cp_gtk_image_get_pixbuf (env, obj); width = gdk_pixbuf_get_width (pixbuf); heigth = gdk_pixbuf_get_height (pixbuf); setWidthHeight(env, obj, width, heigth); @@ -194,9 +192,6 @@ Java_gnu_java_awt_peer_gtk_GtkImage_getPixels(JNIEnv *env, jobject obj) } } - if (offScreen (env, obj) == JNI_TRUE) - gdk_pixbuf_unref (pixbuf); - (*env)->ReleaseIntArrayElements (env, result_array, result_array_iter, 0); gdk_threads_leave (); @@ -211,7 +206,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv *env, jobject obj, jintArray pixels) { - GdkPixbuf *pixbuf = (GdkPixbuf *)getData (env, obj); + GdkPixbuf *pixbuf = cp_gtk_image_get_pixbuf (env, obj); int width, height, rowstride; guchar *pixeldata; jint *src_array_iter, *src; @@ -236,10 +231,10 @@ Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv *env, jobject obj, } /** - * Allocates a Gtk Pixbuf or Pixmap. + * Allocates a Gtk Pixbuf */ JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_createPixmap(JNIEnv *env, jobject obj) +Java_gnu_java_awt_peer_gtk_GtkImage_createPixbuf(JNIEnv *env, jobject obj) { int width, height; jclass cls; @@ -254,35 +249,28 @@ Java_gnu_java_awt_peer_gtk_GtkImage_createPixmap(JNIEnv *env, jobject obj) g_assert (field != 0); height = (*env)->GetIntField (env, obj, field); - if (offScreen (env, obj) == JNI_FALSE) - createRawData (env, obj, gdk_pixbuf_new (GDK_COLORSPACE_RGB, - TRUE, - 8, - width, - height)); - else - createRawData (env, obj, gdk_pixmap_new (NULL, width, height, - gdk_rgb_get_visual ()->depth)); + createRawData (env, obj, gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + 8, + width, + height)); } /** - * Frees the Gtk Pixmap. + * Frees the Gtk Pixbuf. */ JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_freePixmap(JNIEnv *env, jobject obj) +Java_gnu_java_awt_peer_gtk_GtkImage_freePixbuf(JNIEnv *env, jobject obj) { - if (offScreen (env, obj) == JNI_FALSE) - gdk_pixbuf_unref ((GdkPixbuf *)getData (env, obj)); - else - g_object_unref ((GdkPixmap *)getData (env, obj)); + gdk_pixbuf_unref (cp_gtk_image_get_pixbuf (env, obj)); } /** - * Sets this pixmap to a scaled version of the source pixmap. + * Sets this to a scaled version of the original pixbuf * width and height of the destination GtkImage must be set. */ JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixmap(JNIEnv *env, +Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixbuf(JNIEnv *env, jobject destination, jobject source, jint hints) @@ -309,238 +297,25 @@ Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixmap(JNIEnv *env, width, height, mapHints(hints)); - if (offScreen (env, source) == JNI_TRUE) - gdk_pixbuf_unref (pixbuf); - createRawData (env, destination, (void *)dst); } /** - * Draws the pixbuf at x, y, scaled to width and height and - * optionally composited with a given background color. - */ -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaled - (JNIEnv *env, jobject obj, jobject gc_obj, - jint bg_red, jint bg_green, jint bg_blue, - jint x, jint y, jint width, jint height, jboolean composite) -{ - GdkPixbuf* dst; - struct graphics2d *g; - guint32 bgColor; - - gdk_threads_enter (); - - if (width <= 0 || height <= 0) - { - gdk_threads_leave (); - return; - } - - bgColor = ((bg_red & 0xFF) << 16) | - ((bg_green & 0xFF) << 8) | (bg_blue & 0xFF); - - g = (struct graphics2d *) NSA_GET_G2D_PTR (env, gc_obj); - - if (!g || !GDK_IS_DRAWABLE (g->drawable)) - { - gdk_threads_leave (); - return; - } - - if (offScreen (env, obj) == JNI_FALSE) - { - GdkPixbuf* pixbuf = (GdkPixbuf *)getData (env, obj); - - /* Scale and composite the image */ - if (composite == JNI_TRUE) - dst = gdk_pixbuf_composite_color_simple (pixbuf, - width, - height, - GDK_INTERP_BILINEAR, - 255, - width, - bgColor, - bgColor); - else - dst = gdk_pixbuf_scale_simple(pixbuf, - width, height, - GDK_INTERP_BILINEAR); - - gdk_cairo_set_source_pixbuf (g->cr, dst, (double) x, (double) y); - gdk_pixbuf_unref (dst); - - } else { - /* Get a pixmap */ - GdkPixmap* pixmap = (GdkPixmap *)getData (env, obj); - cairo_xlib_surface_set_drawable (g->surface, - GDK_PIXMAP_XID(pixmap), - width, - height); - } - - gdk_threads_leave (); -} - -/** - * Draws the pixbuf at x, y, scaled to width and height and - * optionally composited and/or flipped with a given background color. - */ -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaledFlipped -(JNIEnv *env, jobject obj, jobject gc_obj, - jint bg_red, jint bg_green, jint bg_blue, -#if GTK_MINOR_VERSION > 4 - jboolean flipx, jboolean flipy, -#else - jboolean flipx __attribute__((unused)), - jboolean flipy __attribute__((unused)), -#endif - jint srcx, jint srcy, jint srcwidth, jint srcheight, - jint dstx, jint dsty, jint dstwidth, jint dstheight, - jboolean composite) -{ - GdkPixbuf *pixbuf; - GdkPixbuf *tmp, *dst; - struct graphics2d *g; - guint32 bgColor; - - gdk_threads_enter (); - - if (srcwidth <= 0 || srcheight <= 0 - || dstwidth <= 0 || dstheight <= 0) - { - gdk_threads_leave (); - return; - } - - bgColor = ((bg_red & 0xFF) << 16) | - ((bg_green & 0xFF) << 8) | (bg_blue & 0xFF); - - g = (struct graphics2d *) NSA_GET_G2D_PTR (env, gc_obj); - - if (!g || !GDK_IS_DRAWABLE (g->drawable)) - { - gdk_threads_leave (); - return; - } - - if (offScreen (env, obj) == JNI_FALSE) - { - pixbuf = (GdkPixbuf *)getData (env, obj); - - /* Get the source area */ - tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - TRUE, - 8, - srcwidth, - srcheight); - - gdk_pixbuf_copy_area (pixbuf, - srcx, srcy, - srcwidth, srcheight, - tmp, - 0, 0); /* dst x , dst y */ - } else { - /* Get a pixbuf from the pixmap */ - GdkDrawable *pixmap = (GdkDrawable *)getData(env, obj); - tmp = gdk_pixbuf_get_from_drawable (NULL, - pixmap, - gdk_drawable_get_colormap( pixmap ), - srcx, srcy, - 0, 0, /* dst x , dst y */ - srcwidth, srcheight); - } - - /* FIXME: This #if should be discarded once I feel comfortable about - GTK 2.6 dependence */ -#if GTK_MINOR_VERSION > 4 - /* Flip it if necessary. */ - if (flipx == JNI_TRUE) - { - GdkPixbuf *tmp2 = gdk_pixbuf_flip (tmp, TRUE); - gdk_pixbuf_unref (tmp); - tmp = tmp2; - } - if (flipy == JNI_TRUE) - { - GdkPixbuf *tmp2 = gdk_pixbuf_flip (tmp, FALSE); - gdk_pixbuf_unref (tmp); - tmp = tmp2; - } -#endif - - /* Scale and composite the image */ - if (composite == JNI_TRUE) - dst = gdk_pixbuf_composite_color_simple (tmp, - dstwidth, - dstheight, - GDK_INTERP_BILINEAR, - 255, - dstwidth, - bgColor, - bgColor); - else - dst = gdk_pixbuf_scale_simple(tmp, - dstwidth, dstheight, - GDK_INTERP_BILINEAR); - gdk_pixbuf_unref (tmp); - - gdk_cairo_set_source_pixbuf (g->cr, dst, (double) dstx, - (double) dsty); - gdk_pixbuf_unref (dst); - - gdk_threads_leave (); -} - -/** * Used by GtkFramePeer */ GdkPixbuf *cp_gtk_image_get_pixbuf (JNIEnv *env, jobject obj) { - int width, height; - GdkPixbuf *pixbuf; - GdkPixmap* pixmap; jclass cls; - jfieldID field; - - if (offScreen (env, obj) == JNI_FALSE) - return (GdkPixbuf *)getData (env, obj); + jfieldID data_fid; + jobject data; cls = (*env)->GetObjectClass (env, obj); - field = (*env)->GetFieldID (env, cls, "width", "I"); - g_assert (field != 0); - width = (*env)->GetIntField (env, obj, field); - - field = (*env)->GetFieldID (env, cls, "height", "I"); - g_assert (field != 0); - height = (*env)->GetIntField (env, obj, field); - - /* Get a pixmap */ - pixmap = (GdkPixmap *)getData (env, obj); - - pixbuf = gdk_pixbuf_get_from_drawable (NULL, - pixmap, - gdk_drawable_get_colormap( pixmap ), - 0, 0, /* src x , src y */ - 0, 0, /* dst x , dst y */ - width, height); - return pixbuf; -} - -/** - * Used by GdkGraphics - */ -GdkPixmap *cp_gtk_image_get_pixmap (JNIEnv *env, jobject obj) -{ - if (offScreen (env, obj) == JNI_FALSE) - return NULL; - return (GdkPixmap *)getData (env, obj); -} + data_fid = (*env)->GetFieldID (env, cls, "pixbuf", + "Lgnu/classpath/Pointer;"); + g_assert (data_fid != 0); + data = (*env)->GetObjectField (env, obj, data_fid); -jboolean cp_gtk_image_is_offscreen (JNIEnv *env, jobject obj) -{ - return offScreen(env, obj); + return (GdkPixbuf *)JCL_GetRawData (env, data); } /** @@ -585,18 +360,6 @@ static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height) (*env)->SetIntField (env, obj, field, (jint)height); } -/* Returns the value of the offScreen field. */ -static jboolean offScreen (JNIEnv *env, jobject obj) -{ - jclass cls; - jfieldID field; - - cls = (*env)->GetObjectClass (env, obj); - field = (*env)->GetFieldID (env, cls, "offScreen", "Z"); - g_assert (field != 0); - return (*env)->GetBooleanField (env, obj, field); -} - /* Store and get the pixbuf pointer */ static void createRawData (JNIEnv * env, jobject obj, void *ptr) @@ -606,7 +369,7 @@ createRawData (JNIEnv * env, jobject obj, void *ptr) jfieldID data_fid; cls = (*env)->GetObjectClass (env, obj); - data_fid = (*env)->GetFieldID (env, cls, "pixmap", + data_fid = (*env)->GetFieldID (env, cls, "pixbuf", "Lgnu/classpath/Pointer;"); g_assert (data_fid != 0); @@ -615,18 +378,3 @@ createRawData (JNIEnv * env, jobject obj, void *ptr) (*env)->SetObjectField (env, obj, data_fid, data); } -static void * -getData (JNIEnv * env, jobject obj) -{ - jclass cls; - jfieldID data_fid; - jobject data; - - cls = (*env)->GetObjectClass (env, obj); - data_fid = (*env)->GetFieldID (env, cls, "pixmap", - "Lgnu/classpath/Pointer;"); - g_assert (data_fid != 0); - data = (*env)->GetObjectField (env, obj, data_fid); - - return JCL_GetRawData (env, data); -} diff --git a/native/jni/gtk-peer/gtkpeer.h b/native/jni/gtk-peer/gtkpeer.h index 6ae7b06ae..d08944f24 100644 --- a/native/jni/gtk-peer/gtkpeer.h +++ b/native/jni/gtk-peer/gtkpeer.h @@ -101,53 +101,6 @@ extern struct state_table *cp_gtk_native_graphics2d_state_table; #define SWAPU32(w) \ (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24)) -/* - A graphics2d struct is both simpler and uglier than a graphics - struct. - - Most of the graphics2d drawing state is held in the referenced cairo_t - and corresponding cairo_surface_t, so we can ignore it. - - In addition to the cairo_t, we need to hold an extra reference to the - underlying GdkDrawable so its refcount matches the lifecycle of the java - Graphics object which is peering with us; also a reference to a byte - buffer and cairo_surface_t which contain the pattern you're drawing from - (if it exists). - - Finally, it is possible that we are using a non-RENDER capable X server, - therefore we will be drawing to an cairo_surface_t which is actually a - pixbuf. When this is the case, the pointer to a GdkPixbuf will be - non-NULL and any drawing operation needs to be bracketed by pixbuf - load/save operations. If the GdkPixbuf pointer is NULL, we will treat - the cairo_surface_t as RENDER-capable. - */ -struct graphics2d -{ - cairo_t *cr; - cairo_surface_t *surface; - GdkDrawable *drawable; - GdkWindow *win; - GdkPixbuf *drawbuf; - char *pattern_pixels; - cairo_surface_t *pattern_surface; - cairo_pattern_t *pattern; - gboolean debug; - enum - { - MODE_DRAWABLE_WITH_RENDER, - MODE_DRAWABLE_NO_RENDER, - MODE_JAVA_ARRAY - } - mode; - - /* Support for MODE_JAVA_ARRAY */ - jintArray jarray; - jint width, height; - jint *javabuf; - jint *javabuf_copy; - jboolean isCopy; -}; - /* New-style event masks. */ #define AWT_BUTTON1_DOWN_MASK (1 << 10) #define AWT_BUTTON2_DOWN_MASK (1 << 11) |