| /* Copyright (C) 2000, 2003 Free Software Foundation |
| |
| This file is part of libgcj. |
| |
| This software is copyrighted work licensed under the terms of the |
| Libgcj License. Please consult the file "LIBGCJ_LICENSE" for |
| details. */ |
| |
| package gnu.awt.j2d; |
| |
| import java.awt.Color; |
| import java.awt.Image; |
| import java.awt.Shape; |
| import java.awt.Rectangle; |
| import java.awt.Graphics; |
| import java.awt.Graphics2D; |
| import java.awt.GraphicsConfiguration; |
| import java.awt.Font; |
| import java.awt.FontMetrics; |
| import java.awt.image.BufferedImage; |
| import java.awt.image.ImageObserver; |
| import java.awt.image.Raster; |
| import java.awt.image.WritableRaster; |
| import java.awt.image.ColorModel; |
| |
| /** |
| * IntegerGraphicsState is one of several graphics state |
| * implementations. This graphics state is used when the graphics |
| * object has simple properties, (coordinate translation only, no |
| * transform) and the backend supports integer coordinates (pixel |
| * based). For primitive paint operations, this object translates the |
| * coordinates and forwards the request to the backend. For requests |
| * to draw arbitrary shapes and paths, this object translates the |
| * requests to primitive drawing operations supported by the |
| * backend. IntegerGraphicsState is meant to support the most common |
| * state of an graphics object. The degree of functionality is roughly |
| * equivalent with the old java.awt.Graphics API. |
| */ |
| public class IntegerGraphicsState extends AbstractGraphicsState |
| { |
| int tx; |
| int ty; |
| |
| DirectRasterGraphics directGfx; |
| Shape clip; |
| |
| /** Interface for images which are coupled to a GraphicsConfiguration, |
| * as is typically the case for an off-screen buffer used in |
| * double-buffering. Any image which implements this interface is |
| * rendered directly by DirectRasterGraphics (i.e. by directGfx.drawImage) |
| */ |
| public interface ScreenCoupledImage |
| { |
| /** Get the GraphicsConfiguration to which this image is coupled |
| * @return the GraphicsConfiguration |
| */ |
| GraphicsConfiguration getGraphicsConfiguration (); |
| } |
| |
| public IntegerGraphicsState(DirectRasterGraphics directGfx) |
| { |
| this.directGfx = directGfx; |
| } |
| |
| public Object clone() |
| { |
| IntegerGraphicsState clone = (IntegerGraphicsState) super.clone(); |
| clone.directGfx = (DirectRasterGraphics) directGfx.clone(); |
| |
| return clone; |
| } |
| |
| public void dispose() |
| { |
| DirectRasterGraphics lDeviceGfx = directGfx; |
| |
| directGfx = null; |
| |
| if (lDeviceGfx != null) |
| lDeviceGfx.dispose(); |
| |
| super.dispose(); |
| } |
| |
| // -------- Graphics methods: |
| |
| public void setColor(Color color) |
| { |
| directGfx.setColor(color); |
| } |
| |
| public void setPaintMode() |
| { |
| directGfx.setPaintMode(); |
| } |
| |
| public void setXORMode(Color altColor) |
| { |
| directGfx.setXORMode(altColor); |
| } |
| |
| public void setFont(Font font) |
| { |
| directGfx.setFont(font); |
| } |
| |
| public FontMetrics getFontMetrics(Font font) |
| { |
| return directGfx.getFontMetrics(font); |
| } |
| |
| public void setClip(Shape clip) |
| { |
| if (clip instanceof Rectangle) |
| { |
| Rectangle clipRect = (Rectangle) ((Rectangle) clip).clone(); |
| clipRect.x += tx; |
| clipRect.y += ty; |
| |
| this.clip = clipRect; |
| |
| directGfx.setClip(clipRect); |
| return; |
| } |
| |
| String msg = |
| "translating clip shape " + clip + " into device " + |
| "coordinate space has not been implemented yet"; |
| |
| throw new UnsupportedOperationException(msg); |
| } |
| |
| public Shape getClip() |
| { |
| if (clip == null) |
| return null; |
| if (clip instanceof Rectangle) |
| { |
| Rectangle clipRect = (Rectangle) ((Rectangle) clip).clone(); |
| clipRect.x -= tx; |
| clipRect.y -= ty; |
| return clipRect; |
| } |
| |
| String msg = |
| "translating clip shape " + clip + " into user " + |
| "coordinate space has not been implemented yet"; |
| |
| throw new UnsupportedOperationException(msg); |
| } |
| |
| public Rectangle getClipBounds() |
| { |
| if (clip == null) |
| return null; |
| Rectangle clipRect = clip.getBounds(); |
| |
| clipRect.x -= tx; |
| clipRect.y -= ty; |
| return clipRect; |
| } |
| |
| public void copyArea(int x, int y, |
| int width, int height, |
| int dx, int dy) |
| { |
| directGfx.copyArea(x+tx, y+ty, width, height, dx, dy); |
| } |
| |
| public void drawLine(int x1, int y1, |
| int x2, int y2) |
| { |
| directGfx.drawLine(x1+tx, y1+ty, x2+tx, y2+ty); |
| } |
| |
| public void fillRect(int x, int y, |
| int width, int height) |
| { |
| directGfx.fillRect(x+tx, y+ty, width, height); |
| } |
| |
| public void clearRect(int x, int y, |
| int width, int height) |
| { |
| directGfx.setColor(frontend.getBackground()); |
| directGfx.fillRect(x+tx, y+ty, width, height); |
| directGfx.setColor(frontend.getColor()); |
| } |
| |
| public void drawRoundRect(int x, int y, |
| int width, int height, |
| int arcWidth, int arcHeight) |
| { |
| throw new UnsupportedOperationException("not implemented yet"); |
| } |
| |
| public void fillRoundRect(int x, int y, |
| int width, int height, |
| int arcWidth, int arcHeight) |
| { |
| throw new UnsupportedOperationException("not implemented yet"); |
| } |
| |
| public void drawOval(int x, int y, |
| int width, int height) |
| { |
| drawArc (x, y, width, height, 0, 360); |
| } |
| |
| public void fillOval(int x, int y, |
| int width, int height) |
| { |
| fillArc (x, y, width, height, 0, 360); |
| } |
| |
| public void drawArc(int x, int y, |
| int width, int height, |
| int startAngle, int arcAngle) |
| { |
| directGfx.drawArc(x+tx, y+ty, width, height, startAngle, arcAngle); |
| } |
| |
| public void fillArc(int x, int y, |
| int width, int height, |
| int startAngle, int arcAngle) |
| { |
| directGfx.fillArc(x+tx, y+ty, width, height, startAngle, arcAngle); |
| } |
| |
| public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) |
| { |
| if ((tx == 0) && (ty == 0)) |
| { |
| directGfx.drawPolyline(xPoints, yPoints, nPoints); |
| return; |
| } |
| |
| throw new UnsupportedOperationException("translate not implemented"); |
| } |
| |
| public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) |
| { |
| if ((tx == 0) && (ty == 0)) |
| { |
| directGfx.drawPolygon(xPoints, yPoints, nPoints); |
| return; |
| } |
| |
| throw new UnsupportedOperationException("translate not implemented"); |
| } |
| |
| public void fillPolygon (int[] xPoints, int[] yPoints, int nPoints) |
| { |
| // FIXME: remove tx & ty args once translation via AffineTransform |
| // is implemented. |
| directGfx.fillPolygon (xPoints, yPoints, nPoints, tx, ty); |
| } |
| |
| public boolean drawImage(Image image, int x, int y, |
| ImageObserver observer) |
| { |
| x += tx; |
| y += ty; |
| |
| if (image instanceof ScreenCoupledImage) |
| { |
| GraphicsConfiguration config |
| = ((ScreenCoupledImage)image).getGraphicsConfiguration (); |
| if (config == frontend.config) |
| return directGfx.drawImage (image, x, y, observer); |
| } |
| if (image instanceof BufferedImage) |
| { |
| BufferedImage bImage = (BufferedImage) image; |
| // FIXME: eliminate? ScreenCoupledImage is probably more efficient |
| Object config = bImage.getProperty ("java.awt.GraphicsConfiguration"); |
| if (config == frontend.config) |
| return directGfx.drawImage (image, x, y, observer); |
| |
| int width = image.getWidth (null); |
| int height = image.getHeight (null); |
| |
| Rectangle bounds = new Rectangle (x, y, width, height); |
| |
| MappedRaster mr = directGfx.mapRaster (bounds); |
| |
| // manipulate raster here... |
| ColorModel colorModel = mr.getColorModel (); |
| WritableRaster raster = mr.getRaster (); |
| |
| int xEnd = x + width; |
| int yEnd = y + height; |
| |
| // FIXME: Use the following code only as a fallback. It's SLOW! |
| |
| Object rgbElem = null; |
| for (int yy=0; yy<height; yy++) |
| { |
| for (int xx=0; xx<width; xx++) |
| { |
| int srgb = bImage.getRGB (xx, yy); |
| int sa = ((srgb >>> 24) & 0xff) + 1; |
| int sr = ((srgb >>> 16) & 0xff) + 1; |
| int sg = ((srgb >>> 8) & 0xff) + 1; |
| int sb = (srgb & 0xff) + 1; |
| |
| rgbElem = raster.getDataElements (xx+x, yy+y, rgbElem); |
| int drgb = colorModel.getRGB (rgbElem); |
| int dr = ((drgb >>> 16) & 0xff) + 1; |
| int dg = ((drgb >>> 8) & 0xff) + 1; |
| int db = (drgb & 0xff) + 1; |
| int da = 256 - sa; |
| |
| dr = ((sr*sa + dr*da) >>> 8) - 1; |
| dg = ((sg*sa + dg*da) >>> 8) - 1; |
| db = ((sb*sa + db*da) >>> 8) - 1; |
| |
| drgb = (dr<<16) | (dg<<8) | db; |
| |
| rgbElem = colorModel.getDataElements (drgb, rgbElem); |
| |
| raster.setDataElements (xx+x, yy+y, rgbElem); |
| } |
| } |
| directGfx.unmapRaster (mr); |
| return true; |
| |
| } |
| throw new UnsupportedOperationException ("drawing image " + image + |
| "not implemented"); |
| } |
| |
| |
| // -------- Graphics2D methods: |
| |
| public void draw(Shape shape) |
| { |
| if (shape instanceof Rectangle) |
| { |
| Rectangle rect = (Rectangle) shape; |
| directGfx.drawRect(rect.x+tx, rect.y+ty, rect.width, rect.height); |
| return; |
| } |
| |
| throw new UnsupportedOperationException("shape not implemented"); |
| } |
| |
| public void fill(Shape shape) |
| { |
| if (shape instanceof Rectangle) |
| { |
| Rectangle rect = (Rectangle) shape; |
| directGfx.fillRect(rect.x+tx, rect.y+ty, rect.width, rect.height); |
| return; |
| } |
| |
| throw new UnsupportedOperationException("not implemented"); |
| } |
| |
| public boolean hit(Rectangle rect, Shape text, |
| boolean onStroke) |
| { |
| throw new UnsupportedOperationException("not implemented"); |
| } |
| |
| public void drawString(String text, int x, int y) |
| { |
| directGfx.drawString(text, x+tx, y+ty); |
| } |
| |
| public void drawString(String text, float x, float y) |
| { |
| drawString(text, (int) x, (int) y); |
| } |
| |
| public void translate(int x, int y) |
| { |
| tx += x; |
| ty += y; |
| } |
| |
| public void translate(double tx, double ty) |
| { |
| if ((tx == 0) && (ty == 0)) |
| return; |
| |
| needAffineTransform(); |
| } |
| |
| public void rotate(double theta) |
| { |
| if (theta == 0) |
| return; |
| |
| needAffineTransform(); |
| } |
| |
| public void rotate(double theta, double x, double y) |
| { |
| if (theta == 0) |
| return; |
| |
| needAffineTransform(); |
| } |
| |
| public void scale(double scaleX, double scaleY) |
| { |
| if ((scaleX == 1) && (scaleY == 1)) |
| return; |
| |
| needAffineTransform(); |
| } |
| |
| public void shear(double shearX, double shearY) |
| { |
| if ((shearX == 0) && (shearY == 0)) |
| return; |
| |
| needAffineTransform(); |
| } |
| |
| private void needAffineTransform() |
| { |
| throw new UnsupportedOperationException("state with affine " + |
| "transform not implemented"); |
| } |
| } |