001/* FontMetrics.java -- Information about about a fonts display characteristics
002   Copyright (C) 1999, 2002, 2005  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.awt;
040
041import java.awt.font.FontRenderContext;
042import java.awt.font.LineMetrics;
043import java.awt.geom.Rectangle2D;
044import java.text.CharacterIterator;
045
046// FIXME: I leave many methods basically unimplemented.  This
047// should be reviewed.
048
049/**
050  * This class returns information about the display characteristics of
051  * a font.  It is abstract, and concrete subclasses should implement at
052  * least the following methods:
053  *
054  * <ul>
055  * <li>getAscent()</li>
056  * <li>getDescent()</li>
057  * <li>getLeading()</li>
058  * <li>getMaxAdvance()</li>
059  * <li>charWidth(char)</li>
060  * <li>charsWidth(char[], int, int)</li>
061  * </ul>
062  *
063  * @author Aaron M. Renn (arenn@urbanophile.com)
064  */
065public abstract class FontMetrics implements java.io.Serializable
066{
067  // Serialization constant.
068  private static final long serialVersionUID = 1681126225205050147L;
069
070  /**
071   * This is the font for which metrics will be returned.
072   */
073  protected Font font;
074
075  /**
076   * Initializes a new instance of <code>FontMetrics</code> for the
077   * specified font.
078   *
079   * @param font The font to return metric information for.
080   */
081  protected FontMetrics(Font font)
082  {
083    this.font = font;
084  }
085
086  /**
087   * Returns the font that this object is creating metric information fo.
088   *
089   * @return The font for this object.
090   */
091  public Font getFont()
092  {
093    return font;
094  }
095
096  /**
097   * Returns the leading, or spacing between lines, for this font.
098   *
099   * @return The font leading.
100   */
101  public int getLeading()
102  {
103    return 0;
104  }
105
106  /**
107   * Returns the ascent of the font, which is the distance from the base
108   * to the top of the majority of characters in the set.  Some characters
109   * can exceed this value however.
110   *
111   * @return The font ascent.
112   */
113  public int getAscent()
114  {
115    return 1;
116  }
117
118  /**
119   * Returns the descent of the font, which is the distance from the base
120   * to the bottom of the majority of characters in the set.  Some characters
121   * can exceed this value however.
122   *
123   * @return The font descent.
124   */
125  public int getDescent()
126  {
127    return 1;
128  }
129
130  /**
131   * Returns the height of a line in this font.  This will be the sum
132   * of the leading, the ascent, and the descent.
133   *
134   * @return The height of the font.
135   */
136  public int getHeight()
137  {
138    return getAscent() + getDescent() + getLeading();
139  }
140
141  /**
142   * Returns the maximum ascent value.  This is the maximum distance any
143   * character in the font rised above the baseline.
144   *
145   * @return The maximum ascent for this font.
146   */
147  public int getMaxAscent()
148  {
149    return getAscent();
150  }
151
152  /**
153   * Returns the maximum descent value.  This is the maximum distance any
154   * character in the font extends below the baseline.
155   *
156   * @return The maximum descent for this font.
157   */
158  public int getMaxDescent()
159  {
160    return getMaxDecent();
161  }
162
163  /**
164   * Returns the maximum descent value.  This is the maximum distance any
165   * character in the font extends below the baseline.
166   *
167   * @return The maximum descent for this font.
168   *
169   * @deprecated This method is deprecated in favor of
170   * <code>getMaxDescent()</code>.
171   */
172  public int getMaxDecent()
173  {
174    return getDescent();
175  }
176
177  /**
178   * Returns the width of the widest character in the font.
179   *
180   * @return The width of the widest character in the font.
181   */
182  public int getMaxAdvance()
183  {
184    return -1;
185  }
186
187  /**
188   * Returns the width of the specified character.
189   *
190   * @param ch The character to return the width of.
191   *
192   * @return The width of the specified character.
193   */
194  public int charWidth(int ch)
195  {
196    char[] chars = Character.toChars(ch);
197    return charsWidth(chars, 0, chars.length);
198  }
199
200  /**
201   * Returns the width of the specified character.
202   *
203   * @param ch The character to return the width of.
204   *
205   * @return The width of the specified character.
206   */
207  public int charWidth(char ch)
208  {
209    return 1;
210  }
211
212  /**
213   * Returns the total width of the specified string
214   *
215   * @param str The string to return the width of.
216   *
217   * @return The width of the string.
218   */
219  public int stringWidth(String str)
220  {
221    char[] buf = new char[str.length()];
222    str.getChars(0, str.length(), buf, 0);
223
224    return charsWidth(buf, 0, buf.length);
225  }
226
227  /**
228   * Returns the total width of the specified character array.
229   *
230   * @param buf The character array containing the data.
231   * @param offset The offset into the array to start calculating from.
232   * @param len The total number of bytes to process.
233   *
234   * @return The width of the requested characters.
235   */
236  public int charsWidth(char[] buf, int offset, int len)
237  {
238    int total_width = 0;
239    int endOffset = offset + len;
240    for (int i = offset; i < endOffset; i++)
241      total_width += charWidth(buf[i]);
242    return total_width;
243  }
244
245  /**
246   * Returns the total width of the specified byte array.
247   *
248   * @param buf The byte array containing the data.
249   * @param offset The offset into the array to start calculating from.
250   * @param len The total number of bytes to process.
251   *
252   * @return The width of the requested characters.
253   */
254  public int bytesWidth(byte[] buf, int offset, int len)
255  {
256    int total_width = 0;
257    for (int i = offset; i < len; i++)
258      total_width = charWidth((char) buf[i]);
259
260    return total_width;
261  }
262
263  /**
264   * Returns the widths of the first 256 characters in the font.
265   *
266   * @return The widths of the first 256 characters in the font.
267   */
268  public int[] getWidths()
269  {
270    int[] result = new int[256];
271    for (char i = 0; i < 256; i++)
272      result[i] = charWidth(i);
273    return result;
274  }
275
276  /**
277   * Returns a string representation of this object.
278   *
279   * @return A string representation of this object.
280   */
281  public String toString()
282  {
283    return (this.getClass() + "[font=" + font + ",ascent=" + getAscent()
284            + ",descent=" + getDescent() + ",height=" + getHeight() + "]");
285  }
286
287  // Generic FontRenderContext used when getLineMetrics is called with a
288  // plain Graphics object.
289  private static final FontRenderContext gRC = new FontRenderContext(null,
290                                                                     false,
291                                                                     false);
292
293  /**
294   * Returns a {@link LineMetrics} object constructed with the
295   * specified text and the {@link FontRenderContext} of the Graphics
296   * object when it is an instance of Graphics2D or a generic
297   * FontRenderContext with a null transform, not anti-aliased and not
298   * using fractional metrics.
299   *
300   * @param text The string to calculate metrics from.
301   * @param g The Graphics object that will be used.
302   *
303   * @return A new {@link LineMetrics} object.
304   */
305  public LineMetrics getLineMetrics(String text, Graphics g)
306  {
307    return getLineMetrics(text, 0, text.length(), g);
308  }
309
310  /**
311   * Returns a {@link LineMetrics} object constructed with the
312   * specified text and the {@link FontRenderContext} of the Graphics
313   * object when it is an instance of Graphics2D or a generic
314   * FontRenderContext with a null transform, not anti-aliased and not
315   * using fractional metrics.
316   *
317   * @param text The string to calculate metrics from.
318   * @param begin Index of first character in <code>text</code> to measure.
319   * @param limit Index of last character in <code>text</code> to measure.
320   * @param g The Graphics object that will be used.
321   *
322   * @return A new {@link LineMetrics} object.
323   *
324   * @throws IndexOutOfBoundsException if the range [begin, limit] is
325   * invalid in <code>text</code>.
326   */
327  public LineMetrics getLineMetrics(String text, int begin, int limit,
328                                    Graphics g)
329  {
330    FontRenderContext rc;
331    if (g instanceof Graphics2D)
332      rc = ((Graphics2D) g).getFontRenderContext();
333    else
334      rc = gRC;
335    return font.getLineMetrics(text, begin, limit, rc);
336  }
337
338  /**
339   * Returns a {@link LineMetrics} object constructed with the
340   * specified text and the {@link FontRenderContext} of the Graphics
341   * object when it is an instance of Graphics2D or a generic
342   * FontRenderContext with a null transform, not anti-aliased and not
343   * using fractional metrics.
344   *
345   * @param chars The string to calculate metrics from.
346   * @param begin Index of first character in <code>text</code> to measure.
347   * @param limit Index of last character in <code>text</code> to measure.
348   * @param g The Graphics object that will be used.
349   *
350   * @return A new {@link LineMetrics} object.
351   *
352   * @throws IndexOutOfBoundsException if the range [begin, limit] is
353   * invalid in <code>text</code>.
354   */
355  public LineMetrics getLineMetrics(char[] chars, int begin, int limit,
356                                    Graphics g)
357  {
358    FontRenderContext rc;
359    if (g instanceof Graphics2D)
360      rc = ((Graphics2D) g).getFontRenderContext();
361    else
362      rc = gRC;
363    return font.getLineMetrics(chars, begin, limit, rc);
364  }
365
366  /**
367   * Returns the bounds of the largest character in a Graphics context.
368   * @param context the Graphics context object.
369   * @return a <code>Rectangle2D</code> representing the bounds
370   */
371  public Rectangle2D getMaxCharBounds(Graphics context)
372  {
373    if( context instanceof Graphics2D )
374      return font.getMaxCharBounds(((Graphics2D)context).getFontRenderContext());
375    return font.getMaxCharBounds( gRC );
376  }
377
378  /**
379   * Returns a {@link LineMetrics} object constructed with the
380   * specified text and the {@link FontRenderContext} of the Graphics
381   * object when it is an instance of Graphics2D or a generic
382   * FontRenderContext with a null transform, not anti-aliased and not
383   * using fractional metrics.
384   *
385   * @param ci An iterator over the string to calculate metrics from.
386   * @param begin Index of first character in <code>text</code> to measure.
387   * @param limit Index of last character in <code>text</code> to measure.
388   * @param g The Graphics object that will be used.
389   *
390   * @return A new {@link LineMetrics} object.
391   *
392   * @throws IndexOutOfBoundsException if the range [begin, limit] is
393   * invalid in <code>text</code>.
394   */
395  public LineMetrics getLineMetrics(CharacterIterator ci, int begin,
396                                    int limit, Graphics g)
397  {
398    FontRenderContext rc;
399    if (g instanceof Graphics2D)
400      rc = ((Graphics2D) g).getFontRenderContext();
401    else
402      rc = gRC;
403    return font.getLineMetrics(ci, begin, limit, rc);
404  }
405
406  public Rectangle2D getStringBounds(String str, Graphics context)
407  {
408    return font.getStringBounds(str, getFontRenderContext(context));
409  }
410
411  public Rectangle2D getStringBounds(String str, int beginIndex, int limit,
412                                     Graphics context)
413  {
414    return font.getStringBounds(str, beginIndex, limit,
415                                getFontRenderContext(context));
416  }
417
418  public Rectangle2D getStringBounds(char[] chars, int beginIndex, int limit,
419                                     Graphics context)
420  {
421    return font.getStringBounds(chars, beginIndex, limit,
422                                getFontRenderContext(context));
423  }
424
425  public Rectangle2D getStringBounds(CharacterIterator ci, int beginIndex,
426                                     int limit, Graphics context)
427  {
428    return font.getStringBounds(ci, beginIndex, limit,
429                                getFontRenderContext(context));
430  }
431
432  private FontRenderContext getFontRenderContext(Graphics context)
433  {
434    if (context instanceof Graphics2D)
435      return ((Graphics2D) context).getFontRenderContext();
436
437    return gRC;
438  }
439
440  /**
441   * Returns if the font has uniform line metrics.
442   * @see Font#hasUniformLineMetrics()
443   */
444  public boolean hasUniformLineMetrics()
445  {
446    return font.hasUniformLineMetrics();
447  }
448}