1. /*
  2. * @(#)ShapeGraphicAttribute.java 1.10 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
  9. * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
  10. *
  11. * The original version of this source code and documentation is
  12. * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
  13. * of IBM. These materials are provided under terms of a License
  14. * Agreement between Taligent and Sun. This technology is protected
  15. * by multiple US and International patents.
  16. *
  17. * This notice and attribution to Taligent may not be removed.
  18. * Taligent is a registered trademark of Taligent, Inc.
  19. *
  20. */
  21. package java.awt.font;
  22. import java.awt.Shape;
  23. import java.awt.Graphics;
  24. import java.awt.Rectangle;
  25. import java.awt.Graphics2D;
  26. import java.awt.geom.Rectangle2D;
  27. /**
  28. * The <code>ShapeGraphicAttribute</code> class is an implementation of
  29. * {@link GraphicAttribute} that draws shapes in a {@link TextLayout}.
  30. * @see GraphicAttribute
  31. */
  32. public final class ShapeGraphicAttribute extends GraphicAttribute {
  33. private Shape fShape;
  34. private boolean fStroke;
  35. /**
  36. * A key indicating the shape should be stroked with a 1-pixel wide stroke.
  37. */
  38. public static final boolean STROKE = true;
  39. /**
  40. * A key indicating the shape should be filled.
  41. */
  42. public static final boolean FILL = false;
  43. // cache shape bounds, since GeneralPath doesn't
  44. private Rectangle2D fShapeBounds;
  45. /**
  46. * Constructs a <code>ShapeGraphicAttribute</code> for the specified
  47. * {@link Shape}.
  48. * @param shape the <code>Shape</code> to render. The
  49. * <code>Shape</code> is rendered with its origin at the origin of
  50. * this <code>ShapeGraphicAttribute</code> in the
  51. * host <code>TextLayout</code>. This object maintains a reference to
  52. * <code>shape</code>.
  53. * @param alignment one of the alignments from this
  54. * <code>ShapeGraphicAttribute</code>.
  55. * @param stroke <code>true</code> if the <code>Shape</code> should be
  56. * stroked; <code>false</code> if the <code>Shape</code> should be
  57. * filled.
  58. */
  59. public ShapeGraphicAttribute(Shape shape,
  60. int alignment,
  61. boolean stroke) {
  62. super(alignment);
  63. fShape = shape;
  64. fStroke = stroke;
  65. fShapeBounds = fShape.getBounds2D();
  66. }
  67. /**
  68. * Returns the ascent of this <code>ShapeGraphicAttribute</code>. The
  69. * ascent of a <code>ShapeGraphicAttribute</code> is the positive
  70. * distance from the origin of its <code>Shape</code> to the top of
  71. * bounds of its <code>Shape</code>.
  72. * @return the ascent of this <code>ShapeGraphicAttribute</code>.
  73. */
  74. public float getAscent() {
  75. return (float) Math.max(0, -fShapeBounds.getMinY());
  76. }
  77. /**
  78. * Returns the descent of this <code>ShapeGraphicAttribute</code>.
  79. * The descent of a <code>ShapeGraphicAttribute</code> is the distance
  80. * from the origin of its <code>Shape</code> to the bottom of the
  81. * bounds of its <code>Shape</code>.
  82. * @return the descent of this <code>ShapeGraphicAttribute</code>.
  83. */
  84. public float getDescent() {
  85. return (float) Math.max(0, fShapeBounds.getMaxY());
  86. }
  87. /**
  88. * Returns the advance of this <code>ShapeGraphicAttribute</code>.
  89. * The advance of a <code>ShapeGraphicAttribute</code> is the distance
  90. * from the origin of its <code>Shape</code> to the right side of the
  91. * bounds of its <code>Shape</code>.
  92. * @return the advance of this <code>ShapeGraphicAttribute</code>.
  93. */
  94. public float getAdvance() {
  95. return (float) Math.max(0, fShapeBounds.getMaxX());
  96. }
  97. /**
  98. * Draws the graphic at the given location. The <code>Shape</code>
  99. * is drawn with its origin at (x, y).
  100. * @param graphics the {@link Graphics2D} into which to draw the
  101. * graphic
  102. * @param x, y the user space coordinates where the graphic is
  103. * drawn
  104. */
  105. public void draw(Graphics2D graphics, float x, float y) {
  106. // translating graphics to draw Shape !!!
  107. graphics.translate((int)x, (int)y);
  108. try {
  109. if (fStroke == STROKE) {
  110. // REMIND: set stroke to correct size
  111. graphics.draw(fShape);
  112. }
  113. else {
  114. graphics.fill(fShape);
  115. }
  116. }
  117. finally {
  118. graphics.translate(-(int)x, -(int)y);
  119. }
  120. }
  121. /**
  122. * Returns a {@link Rectangle2D} that encloses all of the
  123. * bits drawn by this <code>ShapeGraphicAttribute</code> relative to
  124. * the rendering position. A graphic can be rendered beyond its
  125. * origin, ascent, descent, or advance; but if it does, this method's
  126. * implementation should indicate where the graphic is rendered.
  127. * @return a <code>Rectangle2D</code> that encloses all of the bits
  128. * rendered by this <code>ShapeGraphicAttribute</code>.
  129. */
  130. public Rectangle2D getBounds() {
  131. Rectangle2D.Float bounds = new Rectangle2D.Float();
  132. bounds.setRect(fShapeBounds);
  133. if (fStroke == STROKE) {
  134. ++bounds.width;
  135. ++bounds.height;
  136. }
  137. return bounds;
  138. }
  139. /**
  140. * Returns a hashcode for this <code>ShapeGraphicAttribute</code>.
  141. * @return a hash code value for this
  142. * <code>ShapeGraphicAttribute</code>.
  143. */
  144. public int hashCode() {
  145. return fShape.hashCode();
  146. }
  147. /**
  148. * Compares this <code>ShapeGraphicAttribute</code> to the specified
  149. * <code>Object</code>.
  150. * @param rhs the <code>Object</code> to compare for equality
  151. * @return <code>true</code> if this
  152. * <code>ShapeGraphicAttribute</code> equals <code>rhs</code>
  153. * <code>false</code> otherwise.
  154. */
  155. public boolean equals(Object rhs) {
  156. try {
  157. return equals((ShapeGraphicAttribute) rhs);
  158. }
  159. catch(ClassCastException e) {
  160. return false;
  161. }
  162. }
  163. /**
  164. * Compares this <code>ShapeGraphicAttribute</code> to the specified
  165. * <code>ShapeGraphicAttribute</code>.
  166. * @param rhs the <code>ShapeGraphicAttribute</code> to compare for
  167. * equality
  168. * @return <code>true</code> if this
  169. * <code>ShapeGraphicAttribute</code> equals <code>rhs</code>
  170. * <code>false</code> otherwise.
  171. */
  172. public boolean equals(ShapeGraphicAttribute rhs) {
  173. if (rhs == null) {
  174. return false;
  175. }
  176. if (this == rhs) {
  177. return true;
  178. }
  179. if (fStroke != rhs.fStroke) {
  180. return false;
  181. }
  182. if (getAlignment() != rhs.getAlignment()) {
  183. return false;
  184. }
  185. if (!fShape.equals(rhs.fShape)) {
  186. return false;
  187. }
  188. return true;
  189. }
  190. }