1 /* FontMetrics.java -- Information about about a fonts display characteristics
2    Copyright (C) 1999, 2002, 2005  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package java.awt;
40 
41 import java.awt.font.FontRenderContext;
42 import java.awt.font.LineMetrics;
43 import java.awt.geom.Rectangle2D;
44 import java.text.CharacterIterator;
45 
46 // FIXME: I leave many methods basically unimplemented.  This
47 // should be reviewed.
48 
49 /**
50   * This class returns information about the display characteristics of
51   * a font.  It is abstract, and concrete subclasses should implement at
52   * least the following methods:
53   *
54   * <ul>
55   * <li>getAscent()</li>
56   * <li>getDescent()</li>
57   * <li>getLeading()</li>
58   * <li>getMaxAdvance()</li>
59   * <li>charWidth(char)</li>
60   * <li>charsWidth(char[], int, int)</li>
61   * </ul>
62   *
63   * @author Aaron M. Renn (arenn@urbanophile.com)
64   */
65 public abstract class FontMetrics implements java.io.Serializable
66 {
67   // Serialization constant.
68   private static final long serialVersionUID = 1681126225205050147L;
69 
70   /**
71    * This is the font for which metrics will be returned.
72    */
73   protected Font font;
74 
75   /**
76    * Initializes a new instance of <code>FontMetrics</code> for the
77    * specified font.
78    *
79    * @param font The font to return metric information for.
80    */
FontMetrics(Font font)81   protected FontMetrics(Font font)
82   {
83     this.font = font;
84   }
85 
86   /**
87    * Returns the font that this object is creating metric information fo.
88    *
89    * @return The font for this object.
90    */
getFont()91   public Font getFont()
92   {
93     return font;
94   }
95 
96   /**
97    * Returns the leading, or spacing between lines, for this font.
98    *
99    * @return The font leading.
100    */
getLeading()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    */
getAscent()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    */
getDescent()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    */
getHeight()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    */
getMaxAscent()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    */
getMaxDescent()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    */
getMaxDecent()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    */
getMaxAdvance()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    */
charWidth(int ch)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    */
charWidth(char ch)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    */
stringWidth(String str)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    */
charsWidth(char[] buf, int offset, int len)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    */
bytesWidth(byte[] buf, int offset, int len)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    */
getWidths()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    */
toString()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    */
getLineMetrics(String text, Graphics g)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    */
getLineMetrics(String text, int begin, int limit, Graphics g)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    */
getLineMetrics(char[] chars, int begin, int limit, Graphics g)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    */
getMaxCharBounds(Graphics context)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    */
getLineMetrics(CharacterIterator ci, int begin, int limit, Graphics g)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 
getStringBounds(String str, Graphics context)406   public Rectangle2D getStringBounds(String str, Graphics context)
407   {
408     return font.getStringBounds(str, getFontRenderContext(context));
409   }
410 
getStringBounds(String str, int beginIndex, int limit, Graphics context)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 
getStringBounds(char[] chars, int beginIndex, int limit, Graphics context)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 
getStringBounds(CharacterIterator ci, int beginIndex, int limit, Graphics context)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 
getFontRenderContext(Graphics context)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    */
hasUniformLineMetrics()444   public boolean hasUniformLineMetrics()
445   {
446     return font.hasUniformLineMetrics();
447   }
448 }
449