/* GdkGraphics2D.java
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
package gnu.java.awt.peer.gtk;
-import java.awt.*;
-import java.awt.geom.*;
-import java.awt.font.*;
-import java.awt.color.*;
-import java.awt.image.*;
-import java.awt.image.renderable.*;
-import java.util.HashMap;
-import java.util.Map;
+import gnu.classpath.Configuration;
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.peer.ClasspathFontPeer;
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.GradientPaint;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.TexturePaint;
+import java.awt.Toolkit;
+import java.awt.color.ColorSpace;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.GlyphJustificationInfo;
+import java.awt.geom.Arc2D;
+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.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ColorModel;
+import java.awt.image.CropImageFilter;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferInt;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImagingOpException;
+import java.awt.image.SampleModel;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.WritableRaster;
+import java.awt.image.renderable.RenderableImage;
+import java.awt.image.renderable.RenderContext;
import java.text.AttributedCharacterIterator;
+import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
-import java.lang.Integer;
-import gnu.java.awt.ClasspathToolkit;
-import gnu.java.awt.peer.ClasspathFontPeer;
-import gnu.classpath.Configuration;
public class GdkGraphics2D extends Graphics2D
{
private RenderingHints hints;
private BufferedImage bimage;
+ private Composite comp;
+
private Stack stateStack;
- native private int[] initState (GtkComponentPeer component);
+ native private void initState (GtkComponentPeer component);
native private void initState (int width, int height);
native private void copyState (GdkGraphics2D g);
native public void dispose ();
native private int[] getImagePixels();
native private void cairoSurfaceSetFilter(int filter);
+ native void connectSignals (GtkComponentPeer component);
public void finalize ()
{
{
paint = g.paint;
stroke = g.stroke;
- hints = g.hints;
+ setRenderingHints (g.hints);
if (g.fg.getAlpha() != -1)
fg = new Color (g.fg.getRed (), g.fg.getGreen (),
setBackground (bg);
setPaint (paint);
setStroke (stroke);
- setClip (clip);
setTransform (transform);
+ setClip (clip);
stateStack = new Stack();
}
GdkGraphics2D (GtkComponentPeer component)
{
this.component = component;
- int rgb[] = initState (component);
- setColor (new Color (rgb[0], rgb[1], rgb[2]));
- setBackground (new Color (rgb[3], rgb[4], rgb[5]));
- setPaint (getColor());
setFont (new Font("SansSerif", Font.PLAIN, 12));
+
+ if (component.isRealized ())
+ initComponentGraphics2D ();
+ else
+ connectSignals (component);
+ }
+
+ void initComponentGraphics2D ()
+ {
+ initState (component);
+
+ setColor (component.awtComponent.getForeground ());
+ setBackground (component.awtComponent.getBackground ());
+ setPaint (getColor());
setTransform (new AffineTransform ());
setStroke (new BasicStroke ());
setRenderingHints (getDefaultHints());
private native void cairoSave ();
private native void cairoRestore ();
private native void cairoSetMatrix (double m[]);
- private native void cairoSetFont (GdkClasspathFontPeer peer);
- private native void cairoShowGlyphs (int codes[],
- float positions[]);
private native void cairoSetOperator (int cairoOperator);
private native void cairoSetRGBColor (double red, double green, double blue);
private native void cairoSetAlpha (double alpha);
private Shape clip;
private AffineTransform transform;
private Font font;
+ private Composite comp;
DrawState (GdkGraphics2D g)
{
this.paint = g.paint;
if (g.transform != null)
this.transform = (AffineTransform) g.transform.clone();
this.font = g.font;
+ this.comp = g.comp;
}
public void restore(GdkGraphics2D g)
{
g.clip = this.clip;
g.transform = this.transform;
g.font = this.font;
+ g.comp = this.comp;
}
}
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.
- double x;
- double y;
- private void setPos (double nx, double ny)
+ private boolean shiftDrawCalls = false;
+ private final double shifted(double coord, boolean doShift)
{
- x = nx;
- y = ny;
+ if (doShift)
+ return Math.floor(coord) + 0.5;
+ else
+ return coord;
}
- private void walkPath(PathIterator p)
+ private final void walkPath(PathIterator p, boolean doShift)
{
+ double x = 0;
+ double y = 0;
double coords[] = new double[6];
cairoSetFillRule (p.getWindingRule ());
{
case PathIterator.SEG_MOVETO:
- setPos(coords[0], coords[1]);
- cairoMoveTo (coords[0], coords[1]);
+ x = shifted(coords[0], doShift);
+ y = shifted(coords[1], doShift);
+ cairoMoveTo (x, y);
break;
case PathIterator.SEG_LINETO:
- setPos(coords[0], coords[1]);
- cairoLineTo (coords[0], coords[1]);
+ 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) * (coords[0] - x);
- double y1 = y + (2.0/3.0) * (coords[1] - y);
+ 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) * (coords[2] - x);
- double y2 = y1 + (1.0/3.0) * (coords[3] - 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);
- setPos(coords[2], coords[3]);
+ x = shifted(coords[2], doShift);
+ y = shifted(coords[3], doShift);
cairoCurveTo (x1, y1,
x2, y2,
- coords[2], coords[3]);
+ x, y);
break;
case PathIterator.SEG_CUBICTO:
- setPos(coords[4], coords[5]);
- cairoCurveTo (coords[0], coords[1],
- coords[2], coords[3],
- coords[4], coords[5]);
+ 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:
}
- private Map getDefaultHints()
+ private final Map getDefaultHints()
{
HashMap defaultHints = new HashMap ();
}
- private void updateBufferedImage()
+ private final void updateBufferedImage()
{
int[] pixels = getImagePixels();
updateImagePixels(pixels);
}
- private boolean isBufferedImageGraphics ()
+ private final boolean isBufferedImageGraphics ()
{
-
- if (bimage != null)
- return true;
- else
- return false;
+ return bimage != null;
}
- private void updateImagePixels (int[] pixels)
+ private final void updateImagePixels (int[] pixels)
{
// This function can only be used if
}
- private boolean drawImage(Image img,
- AffineTransform xform,
- Color bgcolor,
- ImageObserver obs)
+ private final boolean drawImage(Image img,
+ AffineTransform xform,
+ Color bgcolor,
+ ImageObserver obs)
{
+
+ if (img == null)
+ return false;
+
if (img instanceof GtkOffScreenImage &&
img.getGraphics () instanceof GdkGraphics2D &&
(xform == null
return true;
}
else
- {
-
+ {
+
// In this case, xform is an AffineTransform that transforms bounding
// box of the specified image from image space to user space. However
// when we pass this transform to cairo, cairo will use this transform
try
{
- invertedXform = xform.createInverse();
+ 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.getData (),
- invertedXform,
- bgcolor);
+ BufferedImage b = (BufferedImage) img;
+ return drawRaster (b.getColorModel (),
+ b.getData (),
+ invertedXform,
+ bgcolor);
}
else
{
- // begin progressive loading in a separate thread
- new PainterThread (this, img, invertedXform, bgcolor);
- return false;
+ return this.drawImage(GdkPixbufDecoder.createBufferedImage(img.getSource()),
+ xform, bgcolor,obs);
}
}
catch (NoninvertibleTransformException e)
return;
}
- stateSave ();
cairoNewPath ();
-
- boolean normalize;
- normalize = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE)
- || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT);
-
- if (normalize)
- translate (0.5,0.5);
if (s instanceof Rectangle2D)
{
Rectangle2D r = (Rectangle2D)s;
- cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
+ cairoRectangle (shifted(r.getX (), shiftDrawCalls),
+ shifted(r.getY (), shiftDrawCalls),
+ r.getWidth (), r.getHeight ());
}
else
- walkPath (s.getPathIterator (null));
+ walkPath (s.getPathIterator (null), shiftDrawCalls);
cairoStroke ();
- if (normalize)
- translate (-0.5,-0.5);
-
- stateRestore ();
-
if (isBufferedImageGraphics ())
updateBufferedImage();
-
}
public void fill (Shape s)
{
- stateSave();
cairoNewPath ();
if (s instanceof Rectangle2D)
{
cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
}
else
- walkPath (s.getPathIterator (null));
+ walkPath (s.getPathIterator (null), false);
cairoFill ();
- stateRestore ();
if (isBufferedImageGraphics ())
updateBufferedImage();
r.getWidth (), r.getHeight ());
}
else
- walkPath (clip.getPathIterator (null));
- cairoClosePath ();
+ walkPath (clip.getPathIterator (null), false);
+ // cairoClosePath ();
cairoClip ();
}
}
{
BasicStroke bs = (BasicStroke) stroke;
cairoSetLineCap (bs.getEndCap());
- cairoSetLineWidth (bs.getLineWidth() / 2.0);
+ cairoSetLineWidth (bs.getLineWidth());
cairoSetLineJoin (bs.getLineJoin());
cairoSetMiterLimit (bs.getMiterLimit());
float dashes[] = bs.getDashArray();
public void setColor (Color c)
{
+ if (c == null)
+ c = Color.BLACK;
+
fg = c;
paint = c;
cairoSetRGBColor (fg.getRed() / 255.0,
return clip.getBounds ();
}
- protected Rectangle2D getClipInDevSpace ()
- {
- Rectangle2D uclip = clip.getBounds2D ();
- if (transform == null)
- return uclip;
- else
- {
- Point2D pos = transform.transform (new Point2D.Double(uclip.getX (),
- uclip.getY ()),
- (Point2D)null);
- Point2D extent = transform.deltaTransform (new Point2D.Double(uclip.getWidth (),
- uclip.getHeight ()),
- (Point2D)null);
- return new Rectangle2D.Double (pos.getX (), pos.getY (),
- extent.getX (), extent.getY ());
- }
- }
+ protected Rectangle2D getClipInDevSpace ()
+ {
+ Rectangle2D uclip = clip.getBounds2D ();
+ if (transform == null)
+ return uclip;
+ else
+ {
+ Point2D pos = transform.transform (new Point2D.Double(uclip.getX (),
+ uclip.getY ()),
+ (Point2D)null);
+ Point2D extent = transform.deltaTransform (new Point2D.Double(uclip.getWidth (),
+ uclip.getHeight ()),
+ (Point2D)null);
+ return new Rectangle2D.Double (pos.getX (), pos.getY (),
+ extent.getX (), extent.getY ());
+ }
+ }
public void setClip (int x, int y, int width, int height)
{
r.getWidth (), r.getHeight ());
}
else
- walkPath (s.getPathIterator (null));
- cairoClosePath ();
+ walkPath (s.getPathIterator (null), false);
+ // cairoClosePath ();
cairoClip ();
}
}
+ private static BasicStroke draw3DRectStroke = new BasicStroke();
+
public void draw3DRect(int x, int y, int width,
int height, boolean raised)
{
- Color std = fg;
- Color light = std.brighter();
- Color dark = std.darker();
-
- if (!raised)
- {
- Color t = light;
- light = dark;
- dark = t;
- }
-
- double x1 = (double) x;
- double x2 = (double) x + width;
-
- double y1 = (double) y;
- double y2 = (double) y + height;
-
- stateSave ();
-
- cairoNewPath ();
-
- boolean normalize;
- normalize = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE)
- || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT);
-
- if (normalize)
- {
- x1 += 0.5;
- y1 += 0.5;
- x2 += 0.5;
- y2 += 0.5;
- }
-
- setColor (light);
- cairoMoveTo (x1, y1);
- cairoLineTo (x2, y1);
- cairoLineTo (x2, y2);
- cairoStroke ();
-
- cairoNewPath ();
- setColor (dark);
- cairoMoveTo (x1, y1);
- cairoLineTo (x1, y2);
- cairoLineTo (x2, y2);
- cairoStroke ();
-
- stateRestore ();
-
+ Stroke tmp = stroke;
+ setStroke(draw3DRectStroke);
+ super.draw3DRect(x, y, width, height, raised);
+ setStroke(tmp);
if (isBufferedImageGraphics ())
updateBufferedImage();
-
}
public void fill3DRect(int x, int y, int width,
int height, boolean raised)
{
- double step = 1.0;
- if (stroke != null && stroke instanceof BasicStroke)
- {
- BasicStroke bs = (BasicStroke) stroke;
- step = bs.getLineWidth();
- }
-
- Color bright = fg.brighter ();
- Color dark = fg.darker ();
-
- draw3DRect (x, y, width, height, raised);
-
- stateSave ();
- translate (step/2.0, step/2.0);
- cairoNewPath ();
- cairoRectangle ((double) x, (double) y,
- ((double) width) - step,
- ((double) height) - step );
- cairoClosePath ();
- cairoFill ();
- stateRestore ();
-
+ Stroke tmp = stroke;
+ setStroke(draw3DRectStroke);
+ super.fill3DRect(x, y, width, height, raised);
+ setStroke(tmp);
if (isBufferedImageGraphics ())
updateBufferedImage();
-
}
public void fillRect (int x, int y, int width, int height)
{
- fill(new Rectangle (x, y, width, height));
+ cairoNewPath ();
+ cairoRectangle (x, y, width, height);
+ cairoFill ();
}
public void clearRect (int x, int y, int width, int height)
{
- stateSave ();
cairoSetRGBColor (bg.getRed() / 255.0,
bg.getGreen() / 255.0,
bg.getBlue() / 255.0);
cairoSetAlpha (1.0);
cairoNewPath ();
cairoRectangle (x, y, width, height);
- cairoClosePath ();
cairoFill ();
- stateRestore ();
+ setColor (fg);
if (isBufferedImageGraphics ())
updateBufferedImage();
return bg;
}
- private void doPolygon(int[] xPoints, int[] yPoints, int nPoints,
- boolean close, boolean fill)
+ private final void doPolygon(int[] xPoints, int[] yPoints, int nPoints,
+ boolean close, boolean fill)
{
if (nPoints < 1)
return;
doPolygon (xPoints, yPoints, nPoints, false, false);
}
- private boolean drawRaster (ColorModel cm, Raster r,
- AffineTransform imageToUser,
- Color bgcolor)
+ private final boolean drawRaster (ColorModel cm, Raster r,
+ AffineTransform imageToUser,
+ Color bgcolor)
{
if (r == null)
return false;
}
}
- stateSave ();
- translate (x, y);
drawPixels (pixels, r.getWidth (), r.getHeight (), r.getWidth (), i2u);
- stateRestore ();
if (isBufferedImageGraphics ())
updateBufferedImage();
}
- ////////////////////////////////////////
- ////// Supporting Private Classes //////
- ////////////////////////////////////////
-
- private class PainterThread implements Runnable, ImageConsumer
- {
-
- // this is a helper which is spun off when someone tries to do
- // Graphics2D.drawImage on an image we cannot determine to be either
- // one of our own offscreen images or a BufferedImage; that is, when
- // someone wants to draw an image which is possibly still loading over
- // a network or something. you run it in a separate thread and it
- // writes through to the underlying Graphics2D as pixels becomg
- // available.
-
- GdkGraphics2D gr;
- Image image;
- ColorModel defaultModel;
- AffineTransform xform;
- Color bgcolor;
-
- public PainterThread (GdkGraphics2D g, Image im,
- AffineTransform xf, Color bg)
- {
- image = im;
- xform = xf;
- bgcolor = bg;
- this.gr = (GdkGraphics2D) g.create ();
- new Thread (this).start ();
- }
-
- public void imageComplete (int status)
- {
- }
-
- public void setColorModel (ColorModel model)
- {
- defaultModel = model;
- }
-
- public void setDimensions (int width, int height)
- {
- }
-
- public void setHints (int hintflags)
- {
- }
-
- public void setPixels (int x, int y, int w, int h, ColorModel model,
- byte[] pixels, int off, int scansize)
- {
- }
-
- public void setPixels (int x, int y, int w, int h, ColorModel model,
- int[] pixels, int off, int scansize)
- {
- gr.stateSave ();
- gr.translate (x, y);
-
- if (model == null)
- model = defaultModel;
-
- int pixels2[];
- if (model != null)
- {
- pixels2 = new int[pixels.length];
- for (int yy = 0; yy < h; yy++)
- for (int xx = 0; xx < w; xx++)
- {
- int i = yy * scansize + xx;
- pixels2[i] = model.getRGB (pixels[i]);
- }
- }
- else
- pixels2 = pixels;
-
- // change all transparent pixels in the image to the
- // specified bgcolor
-
- if (bgcolor != null)
- {
- for (int i = 0; i < pixels2.length; i++)
- {
- if (model.getAlpha (pixels2[i]) == 0)
- pixels2[i] = bgcolor.getRGB ();
- }
- }
-
- double[] xf = new double[6];
- xform.getMatrix(xf);
- gr.drawPixels (pixels2, w, h, scansize, xf);
- gr.stateRestore ();
- }
-
- public void setProperties (java.util.Hashtable props)
- {
- }
-
- public void run ()
- {
- image.getSource ().startProduction (this);
- gr.dispose ();
- }
- }
-
-
-
///////////////////////////////////////////////
////// Unimplemented Stubs and Overloads //////
///////////////////////////////////////////////
public void setComposite(Composite comp)
{
+ this.comp = comp;
+
if (comp instanceof AlphaComposite)
{
AlphaComposite a = (AlphaComposite) comp;
else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT))
cairoSurfaceSetFilter(4);
- }
+ }
+ shiftDrawCalls = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE)
+ || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT);
+
}
public Object getRenderingHint(RenderingHints.Key hintKey)
else if(hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT))
cairoSurfaceSetFilter(4);
}
+
+ shiftDrawCalls = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE)
+ || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT);
}
public void addRenderingHints(Map hints)
public Composite getComposite()
{
- throw new java.lang.UnsupportedOperationException ();
+ if (comp == null)
+ return AlphaComposite.SrcOver;
+ else
+ return comp;
}
public FontRenderContext getFontRenderContext ()
return new FontRenderContext (transform, true, true);
}
- public void drawGlyphVector (GlyphVector g, float x, float y)
- {
- stateSave ();
- setFont (g.getFont ());
- translate ((double)x, (double)y);
- cairoMoveTo (0, 0);
- int nglyphs = g.getNumGlyphs ();
- int codes[] = g.getGlyphCodes (0, nglyphs, (int []) null);
- float posns[] = g.getGlyphPositions (0, nglyphs, (float []) null);
- cairoShowGlyphs (codes, posns);
-
- if (isBufferedImageGraphics ())
- updateBufferedImage();
-
- stateRestore ();
- }
-
public void copyArea (int x, int y, int width, int height, int dx, int dy)
{
throw new java.lang.UnsupportedOperationException ();
Color bgcolor, ImageObserver observer)
{
+ if (img == null)
+ return false;
+
Image subImage;
int sourceWidth = sx2 - sx1;
public void drawRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight)
{
- int x1 = x + arcWidth, x2 = x + width - arcWidth;
- int y1 = y + arcHeight, y2 = y + height - arcHeight;
- fillRect (x1, y, x2 - x1, height);
- fillRect (x, y1, width, y2 - y1);
- fillArc (x, y, arcWidth, arcHeight, 90, 90);
- fillArc (x1, y, arcWidth, arcHeight, 0, 90);
- fillArc (x2, y2, arcWidth, arcHeight, 270, 90);
- fillArc (x, y2, arcWidth, arcHeight, 180, 90);
+ 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);
}
- public void drawString (String str, int x, int y)
+ // these are the most accelerated painting paths
+ native void cairoDrawGdkGlyphVector (GdkFontPeer f, GdkGlyphVector gv, float x, float y);
+ native void cairoDrawGdkTextLayout (GdkFontPeer f, GdkTextLayout gl, float x, float y);
+ native void cairoDrawString (GdkFontPeer f, String str, float x, float y);
+
+ GdkFontPeer getFontPeer()
{
- drawString (str, (float)x, (float)y);
+ return (GdkFontPeer) getFont().getPeer();
+ }
+
+ public void drawGdkGlyphVector(GdkGlyphVector gv, float x, float y)
+ {
+ cairoDrawGdkGlyphVector(getFontPeer(), gv, x, y);
+ if (isBufferedImageGraphics ())
+ updateBufferedImage();
+ }
+
+ public void drawGdkTextLayout(GdkTextLayout gl, float x, float y)
+ {
+ cairoDrawGdkTextLayout(getFontPeer(), gl, x, y);
+ if (isBufferedImageGraphics ())
+ updateBufferedImage();
}
public void drawString (String str, float x, float y)
{
- GlyphVector gv = font.createGlyphVector (getFontRenderContext(), str);
- drawGlyphVector (gv, x, y);
+ cairoDrawString(getFontPeer(), str, x, y);
+ if (isBufferedImageGraphics ())
+ updateBufferedImage();
+ }
+
+ public void drawString (String str, int x, int y)
+ {
+ drawString (str, (float)x, (float)y);
}
public void drawString (AttributedCharacterIterator ci, int x, int y)
drawString (ci, (float)x, (float)y);
}
+ public void drawGlyphVector (GlyphVector gv, float x, float y)
+ {
+ if (gv instanceof GdkGlyphVector)
+ drawGdkGlyphVector((GdkGlyphVector)gv, x, y);
+ else
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
public void drawString (AttributedCharacterIterator ci, float x, float y)
{
GlyphVector gv = font.createGlyphVector (getFontRenderContext(), ci);
public void fillRoundRect (int x, int y, int width, int height,
int arcWidth, int arcHeight)
{
- int x1 = x + arcWidth, x2 = x + width - arcWidth;
- int y1 = y + arcHeight, y2 = y + height - arcHeight;
- fillRect (x1, y, x2 - x1, height);
- fillRect (x, y1, width, y2 - y1);
+ 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 (x1, y, arcWidth, arcHeight, 0, 90);
- fillArc (x2, y2, arcWidth, arcHeight, 270, 90);
- fillArc (x, y2, arcWidth, arcHeight, 180, 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 ()
return font;
}
+ // 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);
+ static native void getPeerTextMetrics (GdkFontPeer f, String str, double [] metrics);
+ static native void getPeerFontMetrics (GdkFontPeer f, double [] metrics);
+
public FontMetrics getFontMetrics ()
{
+ // the reason we go via the toolkit here is to try to get
+ // a cached object. the toolkit keeps such a cache.
return Toolkit.getDefaultToolkit ().getFontMetrics (font);
}
public FontMetrics getFontMetrics (Font f)
{
+ // the reason we go via the toolkit here is to try to get
+ // a cached object. the toolkit keeps such a cache.
return Toolkit.getDefaultToolkit ().getFontMetrics (f);
}
public void setFont (Font f)
{
- if (f.getPeer() instanceof GdkClasspathFontPeer)
+ if (f.getPeer() instanceof GdkFontPeer)
font = f;
else
font =
((ClasspathToolkit)(Toolkit.getDefaultToolkit ()))
- .getFont (f.getName(), f.getAttributes ());
-
- if (f != null &&
- f.getPeer() instanceof GdkClasspathFontPeer)
- cairoSetFont ((GdkClasspathFontPeer) f.getPeer());
+ .getFont (f.getName(), f.getAttributes ());
}
-
+
public String toString()
{
return getClass ().getName () +