/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.awt.util; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Toolkit; import java.awt.geom.Rectangle2D; /** * @author Levente S\u00e1ntha */ public abstract class BasicGraphics extends Graphics { protected Rectangle clip; protected Point origin = new Point(); protected Color color = Color.BLACK; protected Font font = new Font("Luxi Sans", Font.PLAIN, 10); protected BasicGraphics() { } protected BasicGraphics(BasicGraphics g) { this.clip = g.clip.getBounds(); this.origin = g.origin.getLocation(); this.color = g.color; this.font = g.font; } /** * Intersects the current clip with the specified rectangle. * The resulting clipping area is the intersection of the current * clipping area and the specified rectangle. If there is no * current clipping area, either because the clip has never been * set, or the clip has been cleared using <code>setClip(null)</code>, * the specified rectangle becomes the new clip. * This method sets the user clip, which is independent of the * clipping associated with device bounds and window visibility. * This method can only be used to make the current clip smaller. * To set the current clip larger, use any of the setClip methods. * Rendering operations have no effect outside of the clipping area. * * @param x the x coordinate of the rectangle to intersect the clip with * @param y the y coordinate of the rectangle to intersect the clip with * @param width the width of the rectangle to intersect the clip with * @param height the height of the rectangle to intersect the clip with * @see #setClip(int, int, int, int) * @see #setClip(java.awt.Shape) */ public void clipRect(int x, int y, int width, int height) { Rectangle r = new Rectangle(x, y, width, height); _transform(r); if (clip == null) clip = r; else clip = clip.intersection(r); if (this.clip.width == 0 && this.clip.height == 0) { //TODO it's probably a regular (but rare) use case since a GUI (swing/awt) // component can have width=0 and height=0 org.jnode.vm.Unsafe.debug(getClass().getSimpleName() + ": zero clip\n"); } } /** * Disposes of this graphics context and releases * any system resources that it is using. * A <code>Graphics</code> object cannot be used after * <code>dispose</code>has been called. * <p/> * When a Java program runs, a large number of <code>Graphics</code> * objects can be created within a short time frame. * Although the finalization process of the garbage collector * also disposes of the same system resources, it is preferable * to manually free the associated resources by calling this * method rather than to rely on a finalization process which * may not run to completion for a long period of time. * <p/> * Graphics objects which are provided as arguments to the * <code>paint</code> and <code>update</code> methods * of components are automatically released by the system when * those methods return. For efficiency, programmers should * call <code>dispose</code> when finished using * a <code>Graphics</code> object only if it was created * directly from a component or another <code>Graphics</code> object. * * @see java.awt.Graphics#finalize * @see java.awt.Component#paint * @see java.awt.Component#update * @see java.awt.Component#getGraphics * @see java.awt.Graphics#create */ public void dispose() { } /** * Gets the current clipping area. * This method returns the user clip, which is independent of the * clipping associated with device bounds and window visibility. * If no clip has previously been set, or if the clip has been * cleared using <code>setClip(null)</code>, this method returns * <code>null</code>. * * @return a <code>Shape</code> object representing the * current clipping area, or <code>null</code> if * no clip is set. * @see java.awt.Graphics#getClipBounds * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(int, int, int, int) * @see java.awt.Graphics#setClip(java.awt.Shape) * @since JDK1.1 */ public Shape getClip() { if (clip == null) return null; Rectangle c = new Rectangle(clip); i_transform(c); return c; } /** * Returns the bounding rectangle of the current clipping area. * This method refers to the user clip, which is independent of the * clipping associated with device bounds and window visibility. * If no clip has previously been set, or if the clip has been * cleared using <code>setClip(null)</code>, this method returns * <code>null</code>. * The coordinates in the rectangle are relative to the coordinate * system origin of this graphics context. * * @return the bounding rectangle of the current clipping area, * or <code>null</code> if no clip is set. * @see java.awt.Graphics#getClip * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(int, int, int, int) * @see java.awt.Graphics#setClip(java.awt.Shape) * @since JDK1.1 */ public Rectangle getClipBounds() { if (clip == null) return null; Rectangle c = new Rectangle(clip); i_transform(c); return c; } /** * Gets this graphics context's current color. * * @return this graphics context's current color. * @see java.awt.Color * @see java.awt.Graphics#setColor(java.awt.Color) */ public Color getColor() { return color; } /** * Gets the current font. * * @return this graphics context's current font. * @see java.awt.Font * @see java.awt.Graphics#setFont(java.awt.Font) */ public Font getFont() { return font; } /** * Gets the font metrics for the specified font. * * @param f the specified font * @return the font metrics for the specified font. * @see java.awt.Graphics#getFont * @see java.awt.FontMetrics * @see java.awt.Graphics#getFontMetrics() */ public FontMetrics getFontMetrics(Font f) { return Toolkit.getDefaultToolkit().getFontMetrics(font); } /** * Sets the current clipping area to an arbitrary clip shape. * Not all objects that implement the <code>Shape</code> * interface can be used to set the clip. The only * <code>Shape</code> objects that are guaranteed to be * supported are <code>Shape</code> objects that are * obtained via the <code>getClip</code> method and via * <code>Rectangle</code> objects. This method sets the * user clip, which is independent of the clipping associated * with device bounds and window visibility. * * @param clip the <code>Shape</code> to use to set the clip * @see java.awt.Graphics#getClip() * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(int, int, int, int) * @since JDK1.1 */ public void setClip(Shape clip) { if (clip instanceof Rectangle) { this.clip = new Rectangle((Rectangle) clip); _transform(this.clip); } else if (clip instanceof Rectangle2D) { this.clip = clip.getBounds(); _transform(this.clip); } } /** * Sets the current clip to the rectangle specified by the given * coordinates. This method sets the user clip, which is * independent of the clipping associated with device bounds * and window visibility. * Rendering operations have no effect outside of the clipping area. * * @param x the <i>x</i> coordinate of the new clip rectangle. * @param y the <i>y</i> coordinate of the new clip rectangle. * @param width the width of the new clip rectangle. * @param height the height of the new clip rectangle. * @see java.awt.Graphics#getClip * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(java.awt.Shape) * @since JDK1.1 */ public void setClip(int x, int y, int width, int height) { this.clip = new Rectangle(x, y, width, height); _transform(this.clip); } /** * Sets this graphics context's current color to the specified * color. All subsequent graphics operations using this graphics * context use this specified color. * * @param c the new rendering color. * @see java.awt.Color * @see java.awt.Graphics#getColor */ public void setColor(Color c) { if (c != null) this.color = c; } /** * Sets this graphics context's font to the specified font. * All subsequent text operations using this graphics context * use this font. A null argument is silently ignored. * * @param font the font. * @see java.awt.Graphics#getFont * @see java.awt.Graphics#drawString(String, int, int) * @see java.awt.Graphics#drawBytes(byte[], int, int, int, int) * @see java.awt.Graphics#drawChars(char[], int, int, int, int) */ public void setFont(Font font) { if (font != null) this.font = font; } /** * Sets the paint mode of this graphics context to overwrite the * destination with this graphics context's current color. * This sets the logical pixel operation function to the paint or * overwrite mode. All subsequent rendering operations will * overwrite the destination with the current color. */ public void setPaintMode() { //todo } /** * Sets the paint mode of this graphics context to alternate between * this graphics context's current color and the new specified color. * This specifies that logical pixel operations are performed in the * XOR mode, which alternates pixels between the current color and * a specified XOR color. * <p/> * When drawing operations are performed, pixels which are the * current color are changed to the specified color, and vice versa. * <p/> * Pixels that are of colors other than those two colors are changed * in an unpredictable but reversible manner; if the same figure is * drawn twice, then all pixels are restored to their original values. * * @param c1 the XOR alternation color */ public void setXORMode(Color c1) { //todo } /** * Translates the origin of the graphics context to the point * (<i>x</i>, <i>y</i>) in the current coordinate system. * Modifies this graphics context so that its new origin corresponds * to the point (<i>x</i>, <i>y</i>) in this graphics context's * original coordinate system. All coordinates used in subsequent * rendering operations on this graphics context will be relative * to this new origin. * * @param x the <i>x</i> coordinate. * @param y the <i>y</i> coordinate. */ public void translate(int x, int y) { origin.translate(x, y); } protected void _transform(Rectangle r) { r.x = r.x + origin.x; r.y = r.y + origin.y; } protected void i_transform(Rectangle r) { r.x = r.x - origin.x; r.y = r.y - origin.y; } }