diff options
author | Roman Kennke <roman@kennke.org> | 2007-05-08 15:03:07 +0000 |
---|---|---|
committer | Roman Kennke <roman@kennke.org> | 2007-05-08 15:03:07 +0000 |
commit | 986e05ca141e0d698141df19d2a6d48bb819d255 (patch) | |
tree | e48ca955b16546acc52c44b3bfa19435a43b613b /gnu/java | |
parent | 589ee23f46853c68a1703d5478957a522ec47f1d (diff) | |
download | classpath-986e05ca141e0d698141df19d2a6d48bb819d255.tar.gz |
2007-05-08 Roman Kennke <roman@kennke.org>
* gnu/java/awt/peer/x/XFontPeer.java: Removed.
* gnu/java/awt/peer/x/XGraphics.java: Removed
* gnu/java/awt/peer/x/XFontPeer2.java
(XLineMetrics.getDescent): Use cached idendity transform.
(XFontMetrics.cachedPoint): New field. Caches a Point2D instance
for reuse.
(XFontMetrics.getAscent): Use cached idendity transform.
(XFontMetrics.getDescent): Use cached idendity transform.
(XFontMetrics.getHeight): Use cached idendity transform.
(XFontMetrics.charWidth): Map character to glyph index first.
(XFontMetrics.stringWidth): Use cached idendity transform.
(IDENDITY): New static field. A reused AffineTransform instance.
Diffstat (limited to 'gnu/java')
-rw-r--r-- | gnu/java/awt/peer/x/XFontPeer.java | 759 | ||||
-rw-r--r-- | gnu/java/awt/peer/x/XFontPeer2.java | 32 | ||||
-rw-r--r-- | gnu/java/awt/peer/x/XGraphics.java | 792 |
3 files changed, 20 insertions, 1563 deletions
diff --git a/gnu/java/awt/peer/x/XFontPeer.java b/gnu/java/awt/peer/x/XFontPeer.java deleted file mode 100644 index 8183fed0c..000000000 --- a/gnu/java/awt/peer/x/XFontPeer.java +++ /dev/null @@ -1,759 +0,0 @@ -/* XFontPeer.java -- The font peer for X - 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.x; - -import java.awt.AWTError; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphVector; -import java.awt.font.LineMetrics; -import java.awt.font.TextAttribute; -import java.awt.geom.Rectangle2D; -import java.io.IOException; -import java.io.InputStream; -import java.text.CharacterIterator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; - -import gnu.java.awt.peer.ClasspathFontPeer; -import gnu.x11.Display; -import gnu.x11.Fontable; - -/** - * The bridge from AWT to X fonts. - * - * @author Roman Kennke (kennke@aicas.com) - */ -public class XFontPeer - extends ClasspathFontPeer -{ - - /** - * The font mapping as specified in the file fonts.properties. - */ - private static Properties fontProperties; - static - { - fontProperties = new Properties(); - InputStream in = XFontPeer.class.getResourceAsStream("fonts.properties"); - try - { - fontProperties.load(in); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - /** - * The FontMetrics implementation for XFontPeer. - */ - private class XFontMetrics - extends FontMetrics - { - /** - * The ascent of the font. - */ - int ascent; - - /** - * The descent of the font. - */ - int descent; - - /** - * The maximum of the character advances. - */ - private int maxAdvance; - - /** - * The internal leading. - */ - int leading; - - /** - * Cached string metrics. This caches string metrics locally so that the - * server doesn't have to be asked each time. - */ - private HashMap metricsCache; - - /** - * The widths of the characters indexed by the characters themselves. - */ - private int[] charWidths; - - /** - * Creates a new XFontMetrics for the specified font. - * - * @param font the font - */ - protected XFontMetrics(Font font) - { - super(font); - metricsCache = new HashMap(); - Fontable.FontReply info = getXFont().info(); - ascent = info.font_ascent(); - descent = info.font_descent(); - maxAdvance = info.max_bounds().character_width(); - leading = 0; // TODO: Not provided by X. Possible not needed. - - if (info.min_byte1() == 0 && info.max_byte1() == 0) - readCharWidthsLinear(info); - else - readCharWidthsNonLinear(info); - } - - /** - * Reads the character widths when specified in a linear fashion. That is - * when the min-byte1 and max-byte2 fields are both zero in the X protocol. - * - * @param info the font info reply - */ - private void readCharWidthsLinear(Fontable.FontReply info) - { - int startIndex = info.min_char_or_byte2(); - int endIndex = info.max_char_or_byte2(); - charWidths = new int[endIndex + 1]; - // All the characters before startIndex are zero width. - for (int i = 0; i < startIndex; i++) - { - charWidths[i] = 0; - } - // All the other character info is fetched from the font info. - int index = startIndex; - Iterator charInfos = info.char_infos().iterator(); - while (charInfos.hasNext()) - { - Fontable.FontReply.CharInfo charInfo = - (Fontable.FontReply.CharInfo) charInfos.next(); - charWidths[index] = charInfo.character_width(); - index++; - } - } - - private void readCharWidthsNonLinear(Fontable.FontReply info) - { - // TODO: Implement. - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Returns the ascent of the font. - * - * @return the ascent of the font - */ - public int getAscent() - { - return ascent; - } - - /** - * Returns the descent of the font. - * - * @return the descent of the font - */ - public int getDescent() - { - return descent; - } - - /** - * Returns the overall height of the font. This is the distance from - * baseline to baseline (usually ascent + descent + leading). - * - * @return the overall height of the font - */ - public int getHeight() - { - return ascent + descent; - } - - /** - * Returns the leading of the font. - * - * @return the leading of the font - */ - public int getLeading() - { - return leading; - } - - /** - * Returns the maximum advance for this font. - * - * @return the maximum advance for this font - */ - public int getMaxAdvance() - { - return maxAdvance; - } - - /** - * Determines the width of the specified character <code>c</code>. - * - * @param c the character - * - * @return the width of the character - */ - public int charWidth(char c) - { - int width; - if (c > charWidths.length) - width = charWidths['?']; - else - width = charWidths[c]; - return width; - } - - /** - * Determines the overall width of the specified string. - * - * @param c the char buffer holding the string - * @param offset the starting offset of the string in the buffer - * @param length the number of characters in the string buffer - * - * @return the overall width of the specified string - */ - public int charsWidth(char[] c, int offset, int length) - { - int width = 0; - if (c.length > 0 && length > 0) - { - String s = new String(c, offset, length); - width = stringWidth(s); - } - return width; - } - - /** - * Determines the overall width of the specified string. - * - * @param s the string - * - * @return the overall width of the specified string - */ - public int stringWidth(String s) - { - int width = 0; - if (s.length() > 0) - { - if (metricsCache.containsKey(s)) - { - width = ((Integer) metricsCache.get(s)).intValue(); - } - else - { - Fontable.TextExtentReply extents = getXFont().text_extent(s); - /* - System.err.println("string: '" + s + "' : "); - System.err.println("ascent: " + extents.getAscent()); - System.err.println("descent: " + extents.getDescent()); - System.err.println("overall ascent: " + extents.getOverallAscent()); - System.err.println("overall descent: " + extents.getOverallDescent()); - System.err.println("overall width: " + extents.getOverallWidth()); - System.err.println("overall left: " + extents.getOverallLeft()); - System.err.println("overall right: " + extents.getOverallRight()); - */ - width = extents.overall_width(); // + extents.overall_left(); - //System.err.println("String: " + s + ", width: " + width); - metricsCache.put(s, new Integer(width)); - } - } - //System.err.print("stringWidth: '" + s + "': "); - //System.err.println(width); - return width; - } - } - - /** - * The LineMetrics implementation for the XFontPeer. - */ - private class XLineMetrics - extends LineMetrics - { - - /** - * Returns the ascent of the font. - * - * @return the ascent of the font - */ - public float getAscent() - { - return fontMetrics.ascent; - } - - public int getBaselineIndex() - { - // FIXME: Implement this. - throw new UnsupportedOperationException(); - } - - public float[] getBaselineOffsets() - { - // FIXME: Implement this. - throw new UnsupportedOperationException(); - } - - /** - * Returns the descent of the font. - * - * @return the descent of the font - */ - public float getDescent() - { - return fontMetrics.descent; - } - - /** - * Returns the overall height of the font. This is the distance from - * baseline to baseline (usually ascent + descent + leading). - * - * @return the overall height of the font - */ - public float getHeight() - { - return fontMetrics.ascent + fontMetrics.descent; - } - - /** - * Returns the leading of the font. - * - * @return the leading of the font - */ - public float getLeading() - { - return fontMetrics.leading; - } - - public int getNumChars() - { - // FIXME: Implement this. - throw new UnsupportedOperationException(); - } - - public float getStrikethroughOffset() - { - return 0.F; // TODO: Provided by X?? - } - - public float getStrikethroughThickness() - { - return 1.F; // TODO: Provided by X?? - } - - public float getUnderlineOffset() - { - return 0.F; // TODO: Provided by X?? - } - - public float getUnderlineThickness() - { - return 1.F; // TODO: Provided by X?? - } - - } - - /** - * The X font. - */ - private gnu.x11.Font xfont; - - private String name; - - private int style; - - private int size; - - /** - * The font metrics for this font. - */ - XFontMetrics fontMetrics; - - /** - * Creates a new XFontPeer for the specified font name, style and size. - * - * @param name the font name - * @param style the font style (bold / italic / normal) - * @param size the size of the font - */ - public XFontPeer(String name, int style, int size) - { - super(name, style, size); - this.name = name; - this.style = style; - this.size = size; - } - - /** - * Creates a new XFontPeer for the specified font name and style - * attributes. - * - * @param name the font name - * @param atts the font attributes - */ - public XFontPeer(String name, Map atts) - { - super(name, atts); - String family = name; - if (family == null || family.equals("")) - family = (String) atts.get(TextAttribute.FAMILY); - if (family == null) - family = "SansSerif"; - - int size = 12; - Float sizeFl = (Float) atts.get(TextAttribute.SIZE); - if (sizeFl != null) - size = sizeFl.intValue(); - - int style = 0; - // Detect italic attribute. - Float posture = (Float) atts.get(TextAttribute.POSTURE); - if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR)) - style |= Font.ITALIC; - - // Detect bold attribute. - Float weight = (Float) atts.get(TextAttribute.WEIGHT); - if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0) - style |= Font.BOLD; - - this.name = name; - this.style = style; - this.size = size; - } - - /** - * Initializes the font peer with the specified attributes. This method is - * called from both constructors. - * - * @param name the font name - * @param style the font style - * @param size the font size - */ - private void init(String name, int style, int size) - { - GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice dev = env.getDefaultScreenDevice(); - if (dev instanceof XGraphicsDevice) - { - Display display = ((XGraphicsDevice) dev).getDisplay(); - String fontDescr = encodeFont(name, style, size); - if (XToolkit.DEBUG) - System.err.println("XLFD font description: " + fontDescr); - xfont = new gnu.x11.Font(display, fontDescr); - } - else - { - throw new AWTError("Local GraphicsEnvironment is not XWindowGraphicsEnvironment"); - } - } - - public boolean canDisplay(Font font, char c) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public int canDisplayUpTo(Font font, CharacterIterator i, int start, int limit) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public String getSubFamilyName(Font font, Locale locale) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public String getPostScriptName(Font font) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public int getNumGlyphs(Font font) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public int getMissingGlyphCode(Font font) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public byte getBaselineFor(Font font, char c) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public String getGlyphName(Font font, int glyphIndex) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public GlyphVector createGlyphVector(Font font, FontRenderContext frc, - CharacterIterator ci) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public GlyphVector createGlyphVector(Font font, FontRenderContext ctx, - int[] glyphCodes) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public GlyphVector layoutGlyphVector(Font font, FontRenderContext frc, - char[] chars, int start, int limit, - int flags) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - /** - * Returns the font metrics for the specified font. - * - * @param font the font for which to fetch the font metrics - * - * @return the font metrics for the specified font - */ - public FontMetrics getFontMetrics(Font font) - { - if (font.getPeer() != this) - throw new AWTError("The specified font has a different peer than this"); - - if (fontMetrics == null) - fontMetrics = new XFontMetrics(font); - return fontMetrics; - } - - /** - * Frees the font in the X server. - */ - protected void finalize() - { - if (xfont != null) - xfont.close(); - } - - public boolean hasUniformLineMetrics(Font font) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - /** - * Returns the line metrics for this font and the specified string and - * font render context. - */ - public LineMetrics getLineMetrics(Font font, CharacterIterator ci, int begin, - int limit, FontRenderContext rc) - { - return new XLineMetrics(); - } - - public Rectangle2D getMaxCharBounds(Font font, FontRenderContext rc) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - /** - * Encodes a font name + style + size specification into a X logical font - * description (XLFD) as described here: - * - * http://www.meretrx.com/e93/docs/xlfd.html - * - * This is implemented to look up the font description in the - * fonts.properties of this package. - * - * @param name the font name - * @param atts the text attributes - * - * @return the encoded font description - */ - static String encodeFont(String name, Map atts) - { - String family = name; - if (family == null || family.equals("")) - family = (String) atts.get(TextAttribute.FAMILY); - if (family == null) - family = "SansSerif"; - - int size = 12; - Float sizeFl = (Float) atts.get(TextAttribute.SIZE); - if (sizeFl != null) - size = sizeFl.intValue(); - - int style = 0; - // Detect italic attribute. - Float posture = (Float) atts.get(TextAttribute.POSTURE); - if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR)) - style |= Font.ITALIC; - - // Detect bold attribute. - Float weight = (Float) atts.get(TextAttribute.WEIGHT); - if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0) - style |= Font.BOLD; - - return encodeFont(name, style, size); - } - - /** - * Encodes a font name + style + size specification into a X logical font - * description (XLFD) as described here: - * - * http://www.meretrx.com/e93/docs/xlfd.html - * - * This is implemented to look up the font description in the - * fonts.properties of this package. - * - * @param name the font name - * @param style the font style - * @param size the font size - * - * @return the encoded font description - */ - static String encodeFont(String name, int style, int size) - { - StringBuilder key = new StringBuilder(); - key.append(validName(name)); - key.append('.'); - switch (style) - { - case Font.BOLD: - key.append("bold"); - break; - case Font.ITALIC: - key.append("italic"); - break; - case (Font.BOLD | Font.ITALIC): - key.append("bolditalic"); - break; - case Font.PLAIN: - default: - key.append("plain"); - - } - - String protoType = fontProperties.getProperty(key.toString()); - int s = validSize(size); - return protoType.replaceFirst("%d", String.valueOf(s * 10)); - } - - /** - * Checks the specified font name for a valid font name. If the font name - * is not known, then this returns 'sansserif' as fallback. - * - * @param name the font name to check - * - * @return a valid font name - */ - static String validName(String name) - { - String retVal; - if (name.equalsIgnoreCase("sansserif") - || name.equalsIgnoreCase("serif") - || name.equalsIgnoreCase("monospaced") - || name.equalsIgnoreCase("dialog") - || name.equalsIgnoreCase("dialoginput")) - { - retVal = name.toLowerCase(); - } - else - { - retVal = "sansserif"; - } - return retVal; - } - - /** - * Translates an arbitrary point size to a size that is typically available - * on an X server. These are the sizes 8, 10, 12, 14, 18 and 24. - * - * @param size the queried size - * @return the real available size - */ - private static final int validSize(int size) - { - int val; - if (size <= 9) - val = 8; - else if (size <= 11) - val = 10; - else if (size <= 13) - val = 12; - else if (size <= 17) - val = 14; - else if (size <= 23) - val = 18; - else - val = 24; - return val; - } - - /** - * Returns the X Font reference. This lazily loads the font when first - * requested. - * - * @return the X Font reference - */ - gnu.x11.Font getXFont() - { - if (xfont == null) - { - init(name, style, size); - } - return xfont; - } -} diff --git a/gnu/java/awt/peer/x/XFontPeer2.java b/gnu/java/awt/peer/x/XFontPeer2.java index e1e3f38ad..fd21ebae1 100644 --- a/gnu/java/awt/peer/x/XFontPeer2.java +++ b/gnu/java/awt/peer/x/XFontPeer2.java @@ -127,9 +127,8 @@ public class XFontPeer2 public float getDescent() { - return (int) fontDelegate.getDescent(font.getSize(), - new AffineTransform(), false, false, - false); + return (int) fontDelegate.getDescent(font.getSize(), IDENDITY, false, + false, false); } public float getHeight() @@ -173,6 +172,11 @@ public class XFontPeer2 private class XFontMetrics extends FontMetrics { + /** + * A cached point instance, to be used in #charWidth(). + */ + private Point2D cachedPoint = new Point2D.Double(); + XFontMetrics(Font f) { super(f); @@ -180,22 +184,20 @@ public class XFontPeer2 public int getAscent() { - return (int) fontDelegate.getAscent(getFont().getSize(), - new AffineTransform(), false, false, - false); + return (int) fontDelegate.getAscent(getFont().getSize(), IDENDITY, + false, false, false); } public int getDescent() { - return (int) fontDelegate.getDescent(getFont().getSize(), - new AffineTransform(), false, false, - false); + return (int) fontDelegate.getDescent(getFont().getSize(), IDENDITY, + false, false, false); } public int getHeight() { GlyphVector gv = fontDelegate.createGlyphVector(getFont(), - new FontRenderContext(new AffineTransform(), false, false), + new FontRenderContext(IDENDITY, false, false), new StringCharacterIterator("m")); Rectangle2D b = gv.getVisualBounds(); return (int) b.getHeight(); @@ -203,8 +205,9 @@ public class XFontPeer2 public int charWidth(char c) { + int code = fontDelegate.getGlyphIndex(c); Point2D advance = new Point2D.Double(); - fontDelegate.getAdvance(c, getFont().getSize(), new AffineTransform(), + fontDelegate.getAdvance(code, font.getSize2D(), IDENDITY, false, false, true, advance); return (int) advance.getX(); } @@ -217,13 +220,18 @@ public class XFontPeer2 public int stringWidth(String s) { GlyphVector gv = fontDelegate.createGlyphVector(getFont(), - new FontRenderContext(new AffineTransform(), false, false), + new FontRenderContext(IDENDITY, false, false), new StringCharacterIterator(s)); Rectangle2D b = gv.getVisualBounds(); return (int) b.getWidth(); } } + /** + * The indendity transform, to be used in several methods. + */ + private static final AffineTransform IDENDITY = new AffineTransform(); + private FontDelegate fontDelegate; XFontPeer2(String name, int style, int size) diff --git a/gnu/java/awt/peer/x/XGraphics.java b/gnu/java/awt/peer/x/XGraphics.java deleted file mode 100644 index 134d7d330..000000000 --- a/gnu/java/awt/peer/x/XGraphics.java +++ /dev/null @@ -1,792 +0,0 @@ -/* XGraphics.java -- The Graphics implementation for X - 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.x; - -import gnu.x11.Colormap; -import gnu.x11.Data; -import gnu.x11.Display; -import gnu.x11.Drawable; -import gnu.x11.GC; -import gnu.x11.Pixmap; -import gnu.x11.Point; -import gnu.x11.image.ZPixmap; - -import java.awt.AWTError; -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.Toolkit; -import java.awt.Transparency; -import java.awt.image.BufferedImage; -import java.awt.image.ImageObserver; -import java.awt.image.ImageProducer; -import java.text.AttributedCharacterIterator; -import java.util.HashMap; - -public class XGraphics - extends Graphics - implements Cloneable -{ - - /** - * The X Drawable to draw on. - */ - private Drawable xdrawable; - - /** - * The X graphics context (GC). - */ - private GC xgc; - - /** - * The current translation. - */ - private int translateX; - private int translateY; - - /** - * The current clip. Possibly null. - */ - private Rectangle clip; - - /** - * The current font, possibly null. - */ - private Font font; - - /** - * The current foreground color, possibly null. - */ - private Color foreground; - - /** - * Indicates if this object has been disposed. - */ - private boolean disposed = false; - - // TODO: Workaround for limitation in current Escher. - private Pixmap.Format pixmapFormat; - private int imageByteOrder; - private int pixelByteCount; - - /** - * Creates a new XGraphics on the specified X Drawable. - * - * @param d the X Drawable for which we create the Graphics - */ - XGraphics(Drawable d) - { - xdrawable = d; - xgc = new GC(d); - translateX = 0; - translateY = 0; - clip = new Rectangle(0, 0, d.width, d.height); - - Display display = xdrawable.display; - pixmapFormat = display.default_pixmap_format; - imageByteOrder = display.image_byte_order; - pixelByteCount = pixmapFormat.bits_per_pixel () / 8; - } - - /** - * Creates an exact copy of this graphics context. - * - * @return an exact copy of this graphics context - */ - public Graphics create() - { - XGraphics copy = (XGraphics) clone(); - return copy; - } - - /** - * Translates the origin by (x, y). - */ - public void translate(int x, int y) - { - translateX += x; - translateY += y; - if (clip != null) - { - clip.x -= x; - clip.y -= y; - } - } - - /** - * Returns the current foreground color, possibly <code>null</code>. - * - * @return the current foreground color, possibly <code>null</code> - */ - public Color getColor() - { - return foreground; - } - - /** - * Sets the current foreground color. A <code>null</code> value doesn't - * change the current setting. - * - * @param c the foreground color to set - */ - public void setColor(Color c) - { - if (c != null) - { - XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit(); - HashMap colorMap = tk.colorMap; - gnu.x11.Color col = (gnu.x11.Color) colorMap.get(c); - if (col == null) - { - Colormap map = xdrawable.display.default_colormap; - col = map.alloc_color (c.getRed() * 256, - c.getGreen() * 256, - c.getBlue() * 256); - colorMap.put(c, col); - } - xgc.set_foreground(col); - foreground = c; - } - } - - public void setPaintMode() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void setXORMode(Color color) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Returns the current font, possibly <code>null</code>. - * - * @return the current font, possibly <code>null</code> - */ - public Font getFont() - { - return font; - } - - /** - * Sets the font on the graphics context. A <code>null</code> value doesn't - * change the current setting. - * - * @param f the font to set - */ - public void setFont(Font f) - { - if (f != null) - { - XFontPeer xFontPeer = (XFontPeer) f.getPeer(); - xgc.set_font(xFontPeer.getXFont()); - font = f; - } - } - - /** - * Returns the font metrics for the specified font. - * - * @param font the font for which we want the font metrics - * - * @return the font metrics for the specified font - */ - public FontMetrics getFontMetrics(Font font) - { - if (font == null) - { - if (this.font == null) - setFont(new Font("Dialog", Font.PLAIN, 12)); - font = this.font; - } - XFontPeer xFontPeer = (XFontPeer) font.getPeer(); - return xFontPeer.getFontMetrics(font); - } - - /** - * Returns the bounds of the current clip. - * - * @return the bounds of the current clip - */ - public Rectangle getClipBounds() - { - return clip != null ? clip.getBounds() : null; - } - - /** - * Clips the current clip with the specified clip. - */ - public void clipRect(int x, int y, int width, int height) - { - if (clip == null) - { - clip = new Rectangle(x, y, width, height); - } - else - { - computeIntersection(x, y, width, height, clip); - } - // Update the X clip setting. - setXClip(clip.x, clip.y, clip.width, clip.height); - } - - /** - * Returns <code>true</code> when the specified rectangle intersects with - * the current clip, <code>false</code> otherwise. This is overridden to - * avoid unnecessary creation of Rectangles via getBounds(). - * - * @param x the x coordinate of the rectangle - * @param y the y coordinate of the rectangle - * @param w the width of the rectangle - * @param h the height of the rectangle - * - * @return <code>true</code> when the specified rectangle intersects with - * the current clip, <code>false</code> otherwise - */ - public boolean hitClip(int x, int y, int w, int h) - { - boolean hit; - if (clip == null) - { - hit = true; - } - else - { - // It's easier to determine if the rectangle lies outside the clip, - // so we determine that and reverse the result (if it's not completely - // outside, it most likely hits the clip rectangle). - int x2 = x + w; - int y2 = y + h; - int clipX2 = clip.x + clip.width; - int clipY2 = clip.y + clip.height; - boolean outside = (x < clip.x && x2 < clip.x) // Left. - || (x > clipX2 && x2 > clipX2) // Right. - || (y < clip.y && y2 < clip.y) // Top. - || (y > clipY2 && y2 > clipY2); // Bottom. - hit = ! outside; - } - return hit; - } - - public void setClip(int x, int y, int width, int height) - { - if (clip != null) - clip.setBounds(x, y, width, height); - else - clip = new Rectangle(x, y, width, height); - setXClip(clip.x, clip.y, clip.width, clip.height); - } - - /** - * Sets the clip on the X server GC. The coordinates are not yet translated, - * this will be performed by the X server. - * - * @param x the clip, X coordinate - * @param y the clip, Y coordinate - * @param w the clip, width - * @param h the clip, height - */ - private void setXClip(int x, int y, int w, int h) - { - gnu.x11.Rectangle[] clipRects = new gnu.x11.Rectangle[] { - new gnu.x11.Rectangle(x, y, w, h) }; - xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.YX_BANDED); - } - - public Shape getClip() - { - // Return a copy here, so nobody can trash our clip. - return clip == null ? null : clip.getBounds(); - } - - /** - * Sets the current clip. - * - * @param c the clip to set - */ - public void setClip(Shape c) - { - if (c != null) - { - Rectangle b; - if (c instanceof Rectangle) - { - b = (Rectangle) c; - } - else - { - b = c.getBounds(); - } - clip.setBounds(b); - setXClip(b.x, b.y, b.width, b.height); - } - else - { - clip.setBounds(0, 0, xdrawable.width, xdrawable.height); - setXClip(0, 0, xdrawable.width, xdrawable.height); - } - } - - public void copyArea(int x, int y, int width, int height, int dx, int dy) - { - // Clip and translate src rectangle. - int srcX = Math.min(Math.max(x, clip.x), clip.x + clip.width) - + translateX; - int srcY = Math.min(Math.max(y, clip.y), clip.y + clip.height) - + translateY; - int srcWidth = Math.min(Math.max(x + width, clip.x), - clip.x + clip.width) - x; - int srcHeight = Math.min(Math.max(y + height, clip.y), - clip.y + clip.height) - y; - xdrawable.copy_area(xdrawable, xgc, srcX, srcY, srcWidth, srcHeight, - srcX + dx, srcY + dy); - } - - /** - * Draws a line from point (x1, y1) to point (x2, y2). - */ - public void drawLine(int x1, int y1, int x2, int y2) - { - //System.err.println("drawLine: " + (x1 + translateX) + ", " + ( y1 + translateY) + ", " + (x2 + translateX) + ", " + (y2 + translateY) + " on: " + xdrawable); - xdrawable.line(xgc, x1 + translateX, y1 + translateY, - x2 + translateX, y2 + translateY); - } - - /** - * Fills the specified rectangle. - */ - public void fillRect(int x, int y, int width, int height) - { - xdrawable.rectangle(xgc, x + translateX, y + translateY, - width, height, true); - } - - public void clearRect(int x, int y, int width, int height) - { - xgc.set_foreground(Color.WHITE.getRGB()); - xdrawable.rectangle(xgc, x, y, width, height, true); - if (foreground != null) - xgc.set_foreground(foreground.getRGB()); - } - - public void drawRoundRect(int x, int y, int width, int height, int arcWidth, - int arcHeight) - { - // Draw 4 lines. - int arcRadiusX = arcWidth / 2; - int arcRadiusY = arcHeight / 2; - drawLine(x + arcRadiusX, y, x + width - arcRadiusX, y); - drawLine(x, y + arcRadiusY, x, y + height - arcRadiusY); - drawLine(x + arcRadiusX, y + height, x + width - arcRadiusX, y + height); - drawLine(x + width, y + arcRadiusY, x + width, y + height - arcRadiusY); - - // Draw the 4 arcs at the corners. - // Upper left. - drawArc(x, y, arcWidth, arcHeight, 90, 90); - // Lower left. - drawArc(x, y + height - arcHeight, arcWidth, arcHeight, 180, 90); - // Upper right. - drawArc(x + width - arcWidth, y, arcWidth, arcHeight, 0, 90); - // Lower right. - drawArc(x + width - arcWidth, y + height - arcHeight, arcWidth, arcHeight, - 270, 90); - } - - public void fillRoundRect(int x, int y, int width, int height, int arcWidth, - int arcHeight) - { - // Fill the 3 rectangles that make up the inner area. - int arcRadiusX = arcWidth / 2; - int arcRadiusY = arcHeight / 2; - // Left. - fillRect(x, y + arcRadiusY, arcRadiusX, height - arcHeight); - // Middle. - fillRect(x + arcRadiusX, y, width - arcWidth, height); - // Right. - fillRect(x + width - arcRadiusX, y + arcRadiusY, arcRadiusX, - height - arcHeight); - - // Fill the 4 arcs in the corners. - // Upper left. - fillArc(x, y, arcWidth, arcHeight, 90, 90); - // Lower left. - fillArc(x, y + height - arcHeight, arcWidth, arcHeight, 180, 90); - // Upper right. - fillArc(x + width - arcWidth, y, arcWidth, arcHeight, 0, 90); - // Lower right. - fillArc(x + width - arcWidth, y + height - arcHeight, arcWidth, arcHeight, - 270, 90); - } - - public void drawOval(int x, int y, int width, int height) - { - xdrawable.arc(xgc, x, y, width, height, 0, 360 * 64, false); - } - - public void fillOval(int x, int y, int width, int height) - { - xdrawable.arc(xgc, x, y, width, height, 0, 360 * 64, true); - } - - public void drawArc(int x, int y, int width, int height, int arcStart, - int arcAngle) - { - xdrawable.arc(xgc, x, y, width, height, arcStart * 64, arcAngle * 64, false); - } - - public void fillArc(int x, int y, int width, int height, int arcStart, - int arcAngle) - { - xdrawable.arc(xgc, x, y, width, height, arcStart * 64, arcAngle * 64, true); - } - - public void drawPolyline(int[] xPoints, int[] yPoints, int npoints) - { - int numPoints = Math.min(xPoints.length, yPoints.length); - Point[] points = new Point[numPoints]; - // FIXME: Improve Escher API to accept arrays to avoid creation - // of many Point objects. - for (int i = 0; i < numPoints; i++) - points[i] = new Point(xPoints[i], yPoints[i]); - xdrawable.poly_line(xgc, points, Drawable.ORIGIN); - } - - public void drawPolygon(int[] xPoints, int[] yPoints, int npoints) - { - int numPoints = Math.min(xPoints.length, yPoints.length); - Point[] points = new Point[numPoints]; - // FIXME: Improve Escher API to accept arrays to avoid creation - // of many Point objects. - for (int i = 0; i < numPoints; i++) - points[i] = new Point(xPoints[i], yPoints[i]); - xdrawable.poly_line(xgc, points, Drawable.ORIGIN); - } - - public void fillPolygon(int[] xPoints, int[] yPoints, int npoints) - { - int numPoints = Math.min(xPoints.length, yPoints.length); - Point[] points = new Point[numPoints]; - // FIXME: Improve Escher API to accept arrays to avoid creation - // of many Point objects. - for (int i = 0; i < numPoints; i++) - points[i] = new Point(xPoints[i], yPoints[i]); - xdrawable.fill_poly(xgc, points, Drawable.COMPLEX, Drawable.ORIGIN); - } - - /** - * Draws the specified string at (x, y). - */ - public void drawString(String string, int x, int y) - { - if (disposed) - throw new AWTError("XGraphics already disposed"); - - xdrawable.text(xgc, x + translateX, y + translateY, string); - } - - public void drawString(AttributedCharacterIterator ci, int x, int y) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Draws the specified image on the drawable at position (x,y). - */ - public boolean drawImage(Image image, int x, int y, ImageObserver observer) - { - if (image instanceof XImage) - { - XImage xim = (XImage) image; - Pixmap pm = xim.pixmap; - xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height, - x + translateX, y + translateY); - } - else if (image instanceof BufferedImage - && ((BufferedImage) image).getTransparency() != Transparency.OPAQUE) - { - BufferedImage bi = (BufferedImage) image; - int width = bi.getWidth(); - int height = bi.getHeight(); - Data img = xdrawable.image(x + translateX, y + translateY, - width, height, 0xFFFFFFFF, 2); - - // Compute line byte count. - int lineBitCount = width * pixmapFormat.bits_per_pixel (); - int rem = lineBitCount % pixmapFormat.scanline_pad (); - int linePadCount = lineBitCount / pixmapFormat.scanline_pad () - + (rem == 0 ? 0 : 1); - int lineByteCount = linePadCount * pixmapFormat.scanline_pad () / 8; - - // Composite source and destination pixel data. - int[] trgb = new int[3]; // The device rgb pixels. - for (int yy = 0; yy < height; yy++) - { - for (int xx = 0; xx < width; xx++) - { - getRGB(xx, yy, img, trgb, lineByteCount); - int srgb = bi.getRGB(xx, yy); - float alpha = ((srgb >> 24) & 0xff) / 256F; - float tAlpha = 1.F - alpha; - int red = (srgb >> 16) & 0xFF; - int green = (srgb >> 8) & 0xFF; - int blue = (srgb) & 0xFF; - trgb[0] = (int) (trgb[0] * tAlpha + red * alpha); - trgb[1] = (int) (trgb[1] * tAlpha + green * alpha); - trgb[2] = (int) (trgb[2] * tAlpha + blue * alpha); - setRGB(xx, yy, img, trgb, lineByteCount); - } - } - - // Now we have the transparent image composited onto the target - // Image, now we only must copy it to the Drawable. - ZPixmap pm = new ZPixmap(xdrawable.display); - pm.width = width; - pm.height = height; - pm.init(); - System.arraycopy(img.data, 32, pm.data, 0, img.data.length - 32); - xdrawable.put_image(xgc, pm, x + translateX, y + translateY); - } - else - { - // Pre-render the image into an XImage. - ImageProducer source = image.getSource(); - ImageConverter conv = new ImageConverter(); - source.startProduction(conv); - XImage xim = conv.getXImage(); - Pixmap pm = xim.pixmap; - xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height, - x + translateX, y + translateY); - } - return true; - } - - /** - * Helper method to work around limitation in the current Escher impl. - * - * @param x the x position - * @param y the y position - * @param img the image data - * @param rgb an 3-size array that holds the rgb values on method exit - */ - private void getRGB(int x, int y, Data img, int[] rgb, int lineByteCount) - { - // TODO: Does this also work on non-RGB devices? - int i = y * lineByteCount + pixelByteCount * x; - if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST) - {//if (i >= 5716-33) System.err.println("lbc: " + lineByteCount + ", " + pixelByteCount); - rgb[2] = img.data[32 + i]; - rgb[1] = img.data[32 + i + 1]; - rgb[0] = img.data[32 + i + 2]; - } - else - { // MSB_FIRST - rgb[0] = img.data[32 + i]; - rgb[1] = img.data[32 + i + 1]; - rgb[2] = img.data[32 + i + 2]; - } - - } - - /** - * Helper method to work around limitation in the current Escher impl. - * - * @param x the x position - * @param y the y position - * @param img the image data - * @param rgb an 3-size array that holds the rgb values on method exit - */ - private void setRGB(int x, int y, Data img, int[] rgb, int lineByteCount) - { - // TODO: Does this also work on non-RGB devices? - int i = y * lineByteCount + pixelByteCount * x; - if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST) - { - img.data[32 + i] = (byte) rgb[2]; - img.data[32 + i + 1] = (byte) rgb[1]; - img.data[32 + i + 2] = (byte) rgb[0]; - } - else - { // MSB_FIRST - img.data[32 + i] = (byte) rgb[0]; - img.data[32 + i + 1] = (byte) rgb[1]; - img.data[32 + i + 2] = (byte) rgb[2]; - } - } - - public boolean drawImage(Image image, int x, int y, int width, int height, - ImageObserver observer) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public boolean drawImage(Image image, int x, int y, Color bgcolor, - ImageObserver observer) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public boolean drawImage(Image image, int x, int y, int width, int height, - Color bgcolor, ImageObserver observer) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, - int sx1, int sy1, int sx2, int sy2, - ImageObserver observer) - { - return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, - observer); - } - - public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, - int sx1, int sy1, int sx2, int sy2, Color bgcolor, - ImageObserver observer) - { - - // FIXME: What to do with bgcolor? - - // Scale the image. - int sw = image.getWidth(observer); - int sh = image.getHeight(observer); - double scaleX = Math.abs(dx2 - dx1) / (double) Math.abs(sx2 - sx1); - double scaleY = Math.abs(dy2 - dy1) / (double) Math.abs(sy2 - sy1); - Image scaled = image.getScaledInstance((int) (scaleX * sw), - (int) (scaleY * sh), - Image.SCALE_FAST); - - // Scaled source coordinates. - int sx1s = (int) (scaleX * Math.min(sx1, sx2)); - int sx2s = (int) (scaleX * Math.max(sx1, sx2)); - - // Temporarily clip to the target rectangle. - Rectangle old = clip; - clipRect(dx1, dy1, dx2 - dx1, dy2 - dy1); - - // Draw scaled image. - boolean res = drawImage(scaled, dx1 - sx1s, dy1 - sx2s, observer); - - // Reset clip. - setClip(old); - - return res; - } - - /** - * Frees any resources associated with this object. - */ - public void dispose() - { - if (! disposed) - { - xgc.free(); - xdrawable.display.flush(); - disposed = true; - } - } - - // Additional helper methods. - - /** - * Creates and returns an exact copy of this XGraphics. - */ - protected Object clone() - { - try - { - XGraphics copy = (XGraphics) super.clone(); - copy.xgc = xgc.copy(); - if (clip != null) - { - copy.clip = new Rectangle(clip); - copy.setXClip(clip.x, clip.y, clip.width, clip.height); - } - return copy; - } - catch (CloneNotSupportedException ex) - { - assert false; - } - return null; - } - - /** - * Computes the intersection between two rectangles and stores the result - * int the second rectangle. - * - * This method has been copied from {@link javax.swing.SwingUtilities}. - * - * @param x the x coordinate of the rectangle #1 - * @param y the y coordinate of the rectangle #1 - * @param w the width of the rectangle #1 - * @param h the height of the rectangle #1 - * @param rect the rectangle #2 and output rectangle - */ - private static void computeIntersection(int x, int y, int w, int h, - Rectangle rect) - { - int x2 = (int) rect.x; - int y2 = (int) rect.y; - int w2 = (int) rect.width; - int h2 = (int) rect.height; - - int dx = (x > x2) ? x : x2; - int dy = (y > y2) ? y : y2; - int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx); - int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy); - - if (dw >= 0 && dh >= 0) - rect.setBounds(dx, dy, dw, dh); - else - rect.setBounds(0, 0, 0, 0); - } - - -} |