1. /*
  2. * @(#)GlyphPainter1.java 1.6 00/02/02
  3. *
  4. * Copyright 1997-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. package javax.swing.text;
  11. import java.awt.*;
  12. /**
  13. * A class to perform rendering of the glyphs.
  14. * This can be implemented to be stateless, or
  15. * to hold some information as a cache to
  16. * facilitate faster rendering and model/view
  17. * translation. At a minimum, the GlyphPainter
  18. * allows a View implementation to perform its
  19. * duties independant of a particular version
  20. * of JVM and selection of capabilities (i.e.
  21. * shaping for i18n, etc).
  22. * <p>
  23. * This implementation is intended for operation
  24. * under the JDK1.1 API of the Java Platform.
  25. * Since the Java 2 SDK is backward compatible with
  26. * JDK1.1 API, this class will also function on
  27. * Java 2. The Java 2 SDK introduces improved
  28. * API for rendering text however, so the GlyphPainter2
  29. * is recommended for the Java 2 SDK.
  30. *
  31. * @author Timothy Prinzing
  32. * @version 1.6 02/02/00
  33. * @see GlyphView
  34. */
  35. class GlyphPainter1 extends GlyphView.GlyphPainter {
  36. /**
  37. * Determine the span the glyphs given a start location
  38. * (for tab expansion).
  39. */
  40. public float getSpan(GlyphView v, int p0, int p1,
  41. TabExpander e, float x) {
  42. sync(v);
  43. Segment text = v.getText(p0, p1);
  44. int width = Utilities.getTabbedTextWidth(text, metrics, (int) x, e, p0);
  45. return width;
  46. }
  47. public float getHeight(GlyphView v) {
  48. sync(v);
  49. return metrics.getHeight();
  50. }
  51. /**
  52. * Fetch the ascent above the baseline for the glyphs
  53. * corresponding to the given range in the model.
  54. */
  55. public float getAscent(GlyphView v) {
  56. sync(v);
  57. return metrics.getAscent();
  58. }
  59. /**
  60. * Fetch the descent below the baseline for the glyphs
  61. * corresponding to the given range in the model.
  62. */
  63. public float getDescent(GlyphView v) {
  64. sync(v);
  65. return metrics.getDescent();
  66. }
  67. /**
  68. * Paint the glyphs representing the given range.
  69. */
  70. public void paint(GlyphView v, Graphics g, Shape a, int p0, int p1) {
  71. sync(v);
  72. Segment text;
  73. TabExpander expander = v.getTabExpander();
  74. Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds();
  75. // determine the x coordinate to render the glyphs
  76. int x = alloc.x;
  77. int p = v.getStartOffset();
  78. if (p != p0) {
  79. text = v.getText(p, p0);
  80. int width = Utilities.getTabbedTextWidth(text, metrics, x, expander, p);
  81. x += width;
  82. }
  83. // determine the y coordinate to render the glyphs
  84. int y = alloc.y + metrics.getHeight() - metrics.getDescent();
  85. // render the glyphs
  86. text = v.getText(p0, p1);
  87. g.setFont(metrics.getFont());
  88. Utilities.drawTabbedText(text, x, y, g, expander, p0);
  89. }
  90. public Shape modelToView(GlyphView v, int pos, Position.Bias bias,
  91. Shape a) throws BadLocationException {
  92. sync(v);
  93. Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds();
  94. int p0 = v.getStartOffset();
  95. int p1 = v.getEndOffset();
  96. TabExpander expander = v.getTabExpander();
  97. Segment text;
  98. if(pos == p1) {
  99. // The caller of this is left to right and borders a right to
  100. // left view, return our end location.
  101. return new Rectangle(alloc.x + alloc.width, alloc.y, 0,
  102. metrics.getHeight());
  103. }
  104. if ((pos >= p0) && (pos <= p1)) {
  105. // determine range to the left of the position
  106. text = v.getText(p0, pos);
  107. int width = Utilities.getTabbedTextWidth(text, metrics, alloc.x, expander, p0);
  108. return new Rectangle(alloc.x + width, alloc.y, 0, metrics.getHeight());
  109. }
  110. throw new BadLocationException("modelToView - can't convert", p1);
  111. }
  112. /**
  113. * Provides a mapping from the view coordinate space to the logical
  114. * coordinate space of the model.
  115. *
  116. * @param x the X coordinate
  117. * @param y the Y coordinate
  118. * @param a the allocated region to render into
  119. * @param rightToLeft true if the text is rendered right to left
  120. * @return the location within the model that best represents the
  121. * given point of view
  122. * @see View#viewToModel
  123. */
  124. public int viewToModel(GlyphView v, float x, float y, Shape a,
  125. Position.Bias[] biasReturn) {
  126. sync(v);
  127. Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds();
  128. int p0 = v.getStartOffset();
  129. int p1 = v.getEndOffset();
  130. TabExpander expander = v.getTabExpander();
  131. Segment text = v.getText(p0, p1);
  132. int offs = Utilities.getTabbedTextOffset(text, metrics,
  133. alloc.x, (int) x, expander, p0);
  134. int retValue = p0 + offs;
  135. if(retValue == p1) {
  136. biasReturn[0] = Position.Bias.Backward;
  137. } else {
  138. biasReturn[0] = Position.Bias.Forward;
  139. }
  140. return retValue;
  141. }
  142. /**
  143. * Determines the model location to break the given view.
  144. * This is implemented to attempt to break on a whitespace
  145. * location. If a whitespace location can't be found, the
  146. * nearest character location is returned.
  147. *
  148. * @param v the view to find the model location to break at.
  149. * @param p0 the location in the model where the
  150. * fragment should start it's representation >= 0.
  151. * @param pos the graphic location along the axis that the
  152. * broken view would occupy >= 0. This may be useful for
  153. * things like tab calculations.
  154. * @param len specifies the distance into the view
  155. * where a potential break is desired >= 0.
  156. * @return the model location desired for a break.
  157. * @see View#breakView
  158. */
  159. public int getBoundedPosition(GlyphView v, int p0, float x, float len) {
  160. sync(v);
  161. TabExpander expander = v.getTabExpander();
  162. Segment s = v.getText(p0, v.getEndOffset());
  163. int index = Utilities.getTabbedTextOffset(s, metrics, (int)x, (int)(x+len),
  164. expander, p0, false);
  165. int p1 = p0 + index;
  166. return p1;
  167. }
  168. void sync(GlyphView v) {
  169. Font f = v.getFont();
  170. if ((metrics == null) || (! f.equals(metrics.getFont()))) {
  171. // fetch a new FontMetrics
  172. Toolkit kit;
  173. Component c = v.getContainer();
  174. if (c != null) {
  175. kit = c.getToolkit();
  176. } else {
  177. kit = Toolkit.getDefaultToolkit();
  178. }
  179. metrics = kit.getFontMetrics(f);
  180. }
  181. }
  182. // --- variables ---------------------------------------------
  183. FontMetrics metrics;
  184. }