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