UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

206 lines (191 loc) 33.5 kB
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"><head><title>Using Fonts</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Using Fonts"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-20-SECT-6"/>Using Fonts</h1></div></div></div><p><a id="idx11087" class="indexterm"/> <a id="idx11097" class="indexterm"/>Text fonts in Java are represented by instances of the <a id="I_indexterm20_id812194" class="indexterm"/><code class="literal">java.awt.Font</code> class. A <code class="literal">Font</code> object is constructed from a name, style identifier, and a point size. We can create a <code class="literal">Font</code> object at any time, but it’s meaningful only when applied to a particular component on a given display device. Here are a couple of fonts:</p><a id="I_20_tt1153"/><pre class="programlisting"> <code class="n">Font</code> <code class="n">smallFont</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Font</code><code class="o">(</code><code class="s">"Monospaced"</code><code class="o">,</code> <code class="n">Font</code><code class="o">.</code><code class="na">PLAIN</code><code class="o">,</code> <code class="mi">10</code><code class="o">);</code> <code class="n">Font</code> <code class="n">bigFont</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Font</code><code class="o">(</code><code class="s">"Serif"</code><code class="o">,</code> <code class="n">Font</code><code class="o">.</code><code class="na">BOLD</code><code class="o">,</code> <code class="mi">18</code><code class="o">);</code></pre><p>Font names come in three varieties: <a id="I_indexterm20_id812230" class="indexterm"/><span class="emphasis"><em>family</em></span> names, <span class="emphasis"><em>face</em></span> names (also called font names), and <a id="I_indexterm20_id812243" class="indexterm"/><span class="emphasis"><em>logical</em></span> names. Family and font names are closely related. For example, Garamond Italic is a font name for a font whose family name is Garamond.</p><p>A <span class="emphasis"><em>logical name</em></span> is a generic name for the font family. The following logical font names should be available on all platforms:</p><div class="itemizedlist"><ul class="itemizedlist"><li class="listitem"><p><a id="I_indexterm20_id812262" class="indexterm"/> <code class="literal">Serif</code> (generic name for <code class="literal">TimesRoman</code>)</p></li><li class="listitem"><p><a id="I_indexterm20_id812282" class="indexterm"/> <code class="literal">SansSerif</code> (generic name for <code class="literal">Helvetica</code>)</p></li><li class="listitem"><p><a id="I_indexterm20_id812301" class="indexterm"/> <code class="literal">Monospaced</code> (generic name for <code class="literal">Courier</code>)</p></li><li class="listitem"><p><a id="I_indexterm20_id812321" class="indexterm"/> <code class="literal">Dialog</code></p></li><li class="listitem"><p><a id="I_indexterm20_id812334" class="indexterm"/> <code class="literal">DialogInput</code></p></li></ul></div><p>The logical font name is mapped to an actual font on the local platform. Java’s <span class="emphasis"><em>fonts.properties</em></span> file maps the font names to the available fonts, covering as much of the Unicode character set as possible. If you request a font that doesn’t exist, you get the default font.</p><p>One of the big wins in the 2D API is that it can use most of the fonts you have installed on your computer. The following program prints out a full list of the fonts that are available to the 2D API:</p><a id="I_20_tt1154"/><pre class="programlisting"> <code class="c1">//file: ShowFonts.java</code> <code class="kn">import</code> <code class="nn">java.awt.*</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">ShowFonts</code> <code class="o">{</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code><code class="o">[]</code> <code class="n">args</code><code class="o">)</code> <code class="o">{</code> <code class="n">Font</code><code class="o">[]</code> <code class="n">fonts</code><code class="o">;</code> <code class="n">fonts</code> <code class="o">=</code> <code class="n">GraphicsEnvironment</code><code class="o">.</code><code class="na">getLocalGraphicsEnvironment</code><code class="o">().</code><code class="na">getAllFonts</code><code class="o">();</code> <code class="k">for</code> <code class="o">(</code><code class="kt">int</code> <code class="n">i</code> <code class="o">=</code> <code class="mi">0</code><code class="o">;</code> <code class="n">i</code> <code class="o">&lt;</code> <code class="n">fonts</code><code class="o">.</code><code class="na">length</code><code class="o">;</code> <code class="n">i</code><code class="o">++)</code> <code class="o">{</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">print</code><code class="o">(</code><code class="n">fonts</code><code class="o">[</code><code class="n">i</code><code class="o">].</code><code class="na">getFontName</code><code class="o">()</code> <code class="o">+</code> <code class="s">" : "</code><code class="o">);</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">print</code><code class="o">(</code><code class="n">fonts</code><code class="o">[</code><code class="n">i</code><code class="o">].</code><code class="na">getFamily</code><code class="o">()</code> <code class="o">+</code> <code class="s">" : "</code><code class="o">);</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">print</code><code class="o">(</code><code class="n">fonts</code><code class="o">[</code><code class="n">i</code><code class="o">].</code><code class="na">getName</code><code class="o">());</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">();</code> <code class="o">}</code> <code class="o">}</code> <code class="o">}</code></pre><p>Note, however, that the fonts installed on your system may not match the fonts installed on someone else’s system. For true portability, you can use one of the logical names (although your application won’t look exactly the same on all platforms) or go with the defaults. Alternatively, you can test for the existence of your preferred font and fall back on a logical font, or you can allow your users to configure the application by choosing fonts themselves.</p><p>The <code class="literal">static</code> method <a id="I_indexterm20_id812388" class="indexterm"/><code class="literal">Font.getFont()</code> looks up a font by name in the system properties list just like <a id="I_indexterm20_id812399" class="indexterm"/><code class="literal">Color.getColor()</code>. And as with <code class="literal">Color.getColor()</code>, this is interesting but useless. Normally, you’ll either choose a <code class="literal">Font</code> from one that is available in the environment (as in the <code class="literal">ShowFonts</code> example) or use identifiers to describe the font you want in the <code class="literal">Font</code> constructor.</p><p>The <code class="literal">Font</code> class defines three <code class="literal">static</code> style identifiers: <a id="I_indexterm20_id812447" class="indexterm"/><code class="literal">PLAIN</code>, <a id="I_indexterm20_id812458" class="indexterm"/><code class="literal">BOLD</code>, and <a id="I_indexterm20_id812468" class="indexterm"/><code class="literal">ITALIC</code>. You can use these values on all fonts, although some fonts may not provide bold or italic versions. The point size determines the size of the font on a display. If a given point size isn’t available, <code class="literal">Font</code> substitutes a default size.</p><p>You can retrieve information about an existing <code class="literal">Font</code> with a number of routines. The <a id="I_indexterm20_id812497" class="indexterm"/><code class="literal">getName()</code>, <a id="I_indexterm20_id812507" class="indexterm"/><code class="literal">getSize()</code>, and <a id="I_indexterm20_id812518" class="indexterm"/><code class="literal">getStyle()</code> methods retrieve the logical name, point size, and style, respectively. You can use the <a id="I_indexterm20_id812530" class="indexterm"/><code class="literal">getFamily()</code> method to find out the family name, while <a id="I_indexterm20_id812541" class="indexterm"/><code class="literal">getFontName()</code> returns the face name of the font.</p><p>Finally, to actually use a <code class="literal">Font</code> object, you can simply specify it as an argument to the <a id="I_indexterm20_id812560" class="indexterm"/><code class="literal">setFont()</code> method of a <code class="literal">Component</code> or <code class="literal">Graphics2D</code> object. Subsequent text drawing commands such as <code class="literal">drawString()</code> for that component or in that graphics context use the specified font.</p><div class="sect2" title="Font Metrics"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-20-SECT-6.1"/>Font Metrics</h2></div></div></div><p>To get detailed size and spacing information for text rendered in a font, we can ask for a <a id="I_indexterm20_id812597" class="indexterm"/><code class="literal">java.awt.font.LineMetrics</code> object. Different systems have different real fonts available; the available fonts may not match the font you request. Furthermore, the measurements of different characters within a single font may be different, especially in multilingual text. Thus, a <code class="literal">LineMetrics</code> object presents information about a particular set of text in a particular font on a particular system, not general information about a font. For example, if you ask for the metrics of a nine-point <code class="literal">Monospaced</code> font, what you get isn’t some abstract truth about <code class="literal">Monospaced</code> fonts; you get the metrics of the font that the particular system uses for nine-point <code class="literal">Monospaced</code>—which may not be exactly nine points or even fixed width.</p><p>Use the <a id="I_indexterm20_id812638" class="indexterm"/><code class="literal">getLineMetrics()</code> method for a <code class="literal">Font</code> to retrieve the metrics for text as it would appear for that component. This method also needs to know some information about how you plan to render the text—if you’re planning to use anti-aliasing, for instance, which affects the text measurements. This extra information is encapsulated in the <a id="I_indexterm20_id812660" class="indexterm"/><code class="literal">FontRenderContext</code> class. Fortunately, you can just ask <code class="literal">Graphics2D</code> for its current <code class="literal">FontRenderContext</code> rather than having to create one yourself:</p><a id="I_20_tt1155"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">paint</code><code class="o">(</code><code class="n">Graphics</code> <code class="n">g</code><code class="o">)</code> <code class="o">{</code> <code class="n">Graphics2D</code> <code class="n">g2</code> <code class="o">=</code> <code class="o">(</code><code class="n">Graphics2D</code><code class="o">)</code><code class="n">g</code><code class="o">;</code> <code class="o">...</code> <code class="n">FontRenderContext</code> <code class="n">frc</code> <code class="o">=</code> <code class="n">g2</code><code class="o">.</code><code class="na">getFontRenderContext</code><code class="o">();</code> <code class="n">LineMetrics</code> <code class="n">metrics</code> <code class="o">=</code> <code class="n">font</code><code class="o">.</code><code class="na">getLineMetrics</code><code class="o">(</code><code class="s">"Monkey"</code><code class="o">,</code> <code class="n">frc</code><code class="o">);</code> <code class="o">...</code> <code class="o">}</code></pre><p>The <code class="literal">Font</code> class also has a <a id="I_indexterm20_id812701" class="indexterm"/><code class="literal">getStringBounds()</code> method that returns the bounding box of a piece of text:</p><a id="I_20_tt1156"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">paint</code><code class="o">(</code><code class="n">Graphics</code> <code class="n">g</code><code class="o">)</code> <code class="o">{</code> <code class="n">Graphics2D</code> <code class="n">g2</code> <code class="o">=</code> <code class="o">(</code><code class="n">Graphics2D</code><code class="o">)</code><code class="n">g</code><code class="o">;</code> <code class="o">...</code> <code class="n">FontRenderContext</code> <code class="n">frc</code> <code class="o">=</code> <code class="n">g2</code><code class="o">.</code><code class="na">getFontRenderContext</code><code class="o">();</code> <code class="kt">float</code> <code class="n">messageWidth</code> <code class="o">=</code> <code class="o">(</code><code class="kt">float</code><code class="o">)</code><code class="n">font</code><code class="o">.</code><code class="na">getStringBounds</code><code class="o">(</code><code class="s">"Monkey"</code><code class="o">,</code> <code class="n">frc</code><code class="o">).</code><code class="na">getWidth</code><code class="o">();</code> <code class="o">...</code> <code class="o">}</code></pre><p>The following application, <code class="literal">FontShow</code>, displays a word and draws reference lines showing certain characteristics of its font, as shown in <a class="xref" href="ch20s06.html#learnjava3-CHP-20-FIG-3" title="Figure 20-3. The FontShow application">Figure 20-3</a>. Clicking in the application window toggles the point size between a small and a large value.</p><a id="I_20_tt1157"/><pre class="programlisting"> <code class="c1">//file: FontShow.java</code> <code class="kn">import</code> <code class="nn">java.awt.*</code><code class="o">;</code> <code class="kn">import</code> <code class="nn">java.awt.event.*</code><code class="o">;</code> <code class="kn">import</code> <code class="nn">java.awt.font.*</code><code class="o">;</code> <code class="kn">import</code> <code class="nn">javax.swing.*</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">FontShow</code> <code class="kd">extends</code> <code class="n">JComponent</code> <code class="o">{</code> <code class="kd">private</code> <code class="kd">static</code> <code class="kd">final</code> <code class="kt">int</code> <code class="n">PAD</code> <code class="o">=</code> <code class="mi">25</code><code class="o">;</code> <code class="c1">// frilly line padding</code> <code class="kd">private</code> <code class="kt">boolean</code> <code class="n">bigFont</code> <code class="o">=</code> <code class="kc">true</code><code class="o">;</code> <code class="kd">private</code> <code class="n">String</code> <code class="n">message</code><code class="o">;</code> <code class="kd">public</code> <code class="nf">FontShow</code><code class="o">(</code><code class="n">String</code> <code class="n">message</code><code class="o">)</code> <code class="o">{</code> <code class="k">this</code><code class="o">.</code><code class="na">message</code> <code class="o">=</code> <code class="n">message</code><code class="o">;</code> <code class="n">addMouseListener</code><code class="o">(</code><code class="k">new</code> <code class="n">MouseAdapter</code><code class="o">()</code> <code class="o">{</code> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">mouseClicked</code><code class="o">(</code><code class="n">MouseEvent</code> <code class="n">e</code><code class="o">)</code> <code class="o">{</code> <code class="n">bigFont</code> <code class="o">=</code> <code class="o">!</code><code class="n">bigFont</code><code class="o">;</code> <code class="n">repaint</code><code class="o">();</code> <code class="o">}</code> <code class="o">});</code> <code class="o">}</code> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">paint</code><code class="o">(</code><code class="n">Graphics</code> <code class="n">g</code><code class="o">)</code> <code class="o">{</code> <code class="n">Graphics2D</code> <code class="n">g2</code> <code class="o">=</code> <code class="o">(</code><code class="n">Graphics2D</code><code class="o">)</code><code class="n">g</code><code class="o">;</code> <code class="n">g2</code><code class="o">.</code><code class="na">setRenderingHint</code><code class="o">(</code><code class="n">RenderingHints</code><code class="o">.</code><code class="na">KEY_ANTIALIASING</code><code class="o">,</code> <code class="n">RenderingHints</code><code class="o">.</code><code class="na">VALUE_ANTIALIAS_ON</code><code class="o">);</code> <code class="kt">int</code> <code class="n">size</code> <code class="o">=</code> <code class="n">bigFont</code> <code class="o">?</code> <code class="mi">96</code> <code class="o">:</code> <code class="mi">64</code><code class="o">;</code> <code class="n">Font</code> <code class="n">font</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Font</code><code class="o">(</code><code class="s">"Dialog"</code><code class="o">,</code> <code class="n">Font</code><code class="o">.</code><code class="na">PLAIN</code><code class="o">,</code> <code class="n">size</code><code class="o">);</code> <code class="n">g2</code><code class="o">.</code><code class="na">setFont</code><code class="o">(</code><code class="n">font</code><code class="o">);</code> <code class="kt">int</code> <code class="n">width</code> <code class="o">=</code> <code class="n">getSize</code><code class="o">().</code><code class="na">width</code><code class="o">;</code> <code class="kt">int</code> <code class="n">height</code> <code class="o">=</code> <code class="n">getSize</code><code class="o">().</code><code class="na">height</code><code class="o">;</code> <code class="n">FontRenderContext</code> <code class="n">frc</code> <code class="o">=</code> <code class="n">g2</code><code class="o">.</code><code class="na">getFontRenderContext</code><code class="o">();</code> <code class="n">LineMetrics</code> <code class="n">metrics</code> <code class="o">=</code> <code class="n">font</code><code class="o">.</code><code class="na">getLineMetrics</code><code class="o">(</code><code class="n">message</code><code class="o">,</code> <code class="n">frc</code><code class="o">);</code> <code class="kt">float</code> <code class="n">messageWidth</code> <code class="o">=</code> <code class="o">(</code><code class="kt">float</code><code class="o">)</code><code class="n">font</code><code class="o">.</code><code class="na">getStringBounds</code><code class="o">(</code><code class="n">message</code><code class="o">,</code> <code class="n">frc</code><code class="o">).</code><code class="na">getWidth</code><code class="o">();</code> <code class="c1">// center text</code> <code class="kt">float</code> <code class="n">ascent</code> <code class="o">=</code> <code class="n">metrics</code><code class="o">.</code><code class="na">getAscent</code><code class="o">();</code> <code class="kt">float</code> <code class="n">descent</code> <code class="o">=</code> <code class="n">metrics</code><code class="o">.</code><code class="na">getDescent</code><code class="o">();</code> <code class="kt">float</code> <code class="n">x</code> <code class="o">=</code> <code class="o">(</code><code class="n">width</code> <code class="o">-</code> <code class="n">messageWidth</code><code class="o">)</code> <code class="o">/</code> <code class="mi">2</code><code class="o">;</code> <code class="kt">float</code> <code class="n">y</code> <code class="o">=</code> <code class="o">(</code><code class="n">height</code> <code class="o">+</code> <code class="n">metrics</code><code class="o">.</code><code class="na">getHeight</code><code class="o">())</code> <code class="o">/</code> <code class="mi">2</code> <code class="o">-</code> <code class="n">descent</code><code class="o">;</code> <code class="n">g2</code><code class="o">.</code><code class="na">setPaint</code><code class="o">(</code><code class="n">getBackground</code><code class="o">());</code> <code class="n">g2</code><code class="o">.</code><code class="na">fillRect</code><code class="o">(</code><code class="mi">0</code><code class="o">,</code> <code class="mi">0</code><code class="o">,</code> <code class="n">width</code><code class="o">,</code> <code class="n">height</code><code class="o">);</code> <code class="n">g2</code><code class="o">.</code><code class="na">setPaint</code><code class="o">(</code><code class="n">getForeground</code><code class="o">());</code> <code class="n">g2</code><code class="o">.</code><code class="na">drawString</code><code class="o">(</code><code class="n">message</code><code class="o">,</code> <code class="n">x</code><code class="o">,</code> <code class="n">y</code><code class="o">);</code> <code class="n">g2</code><code class="o">.</code><code class="na">setPaint</code><code class="o">(</code><code class="n">Color</code><code class="o">.</code><code class="na">white</code><code class="o">);</code> <code class="c1">// Base lines</code> <code class="n">drawLine</code><code class="o">(</code><code class="n">g2</code><code class="o">,</code> <code class="n">x</code> <code class="o">-</code> <code class="n">PAD</code><code class="o">,</code> <code class="n">y</code><code class="o">,</code> <code class="n">x</code> <code class="o">+</code> <code class="n">messageWidth</code> <code class="o">+</code> <code class="n">PAD</code><code class="o">,</code> <code class="n">y</code><code class="o">);</code> <code class="n">drawLine</code><code class="o">(</code><code class="n">g2</code><code class="o">,</code> <code class="n">x</code><code class="o">,</code> <code class="n">y</code> <code class="o">+</code> <code class="n">PAD</code><code class="o">,</code> <code class="n">x</code><code class="o">,</code> <code class="n">y</code> <code class="o">-</code> <code class="n">ascent</code> <code class="o">-</code> <code class="n">PAD</code><code class="o">);</code> <code class="n">g2</code><code class="o">.</code><code class="na">setPaint</code><code class="o">(</code><code class="n">Color</code><code class="o">.</code><code class="na">green</code><code class="o">);</code> <code class="c1">// Ascent line</code> <code class="n">drawLine</code><code class="o">(</code><code class="n">g2</code><code class="o">,</code> <code class="n">x</code> <code class="o">-</code> <code class="n">PAD</code><code class="o">,</code> <code class="n">y</code> <code class="o">-</code> <code class="n">ascent</code><code class="o">,</code> <code class="n">x</code> <code class="o">+</code> <code class="n">messageWidth</code> <code class="o">+</code> <code class="n">PAD</code><code class="o">,</code> <code class="n">y</code> <code class="o">-</code> <code class="n">ascent</code><code class="o">);</code> <code class="n">g2</code><code class="o">.</code><code class="na">setPaint</code><code class="o">(</code><code class="n">Color</code><code class="o">.</code><code class="na">red</code><code class="o">);</code> <code class="c1">// Descent line</code> <code class="n">drawLine</code><code class="o">(</code><code class="n">g2</code><code class="o">,</code> <code class="n">x</code> <code class="o">-</code> <code class="n">PAD</code><code class="o">,</code> <code class="n">y</code> <code class="o">+</code> <code class="n">descent</code><code class="o">,</code> <code class="n">x</code> <code class="o">+</code> <code class="n">messageWidth</code> <code class="o">+</code> <code class="n">PAD</code><code class="o">,</code> <code class="n">y</code> <code class="o">+</code> <code class="n">descent</code><code class="o">);</code> <code class="o">}</code> <code class="kd">private</code> <code class="kt">void</code> <code class="nf">drawLine</code><code class="o">(</code><code class="n">Graphics2D</code> <code class="n">g2</code><code class="o">,</code> <code class="kt">double</code> <code class="n">x0</code><code class="o">,</code> <code class="kt">double</code> <code class="n">y0</code><code class="o">,</code> <code class="kt">double</code> <code class="n">x1</code><code class="o">,</code> <code class="kt">double</code> <code class="n">y1</code><code class="o">)</code> <code class="o">{</code> <code class="n">Shape</code> <code class="n">line</code> <code class="o">=</code> <code class="k">new</code> <code class="n">java</code><code class="o">.</code><code class="na">awt</code><code class="o">.</code><code class="na">geom</code><code class="o">.</code><code class="na">Line2D</code><code class="o">.</code><code class="na">Double</code><code class="o">(</code><code class="n">x0</code><code class="o">,</code> <code class="n">y0</code><code class="o">,</code> <code class="n">x1</code><code class="o">,</code> <code class="n">y1</code><code class="o">);</code> <code class="n">g2</code><code class="o">.</code><code class="na">draw</code><code class="o">(</code><code class="n">line</code><code class="o">);</code> <code class="o">}</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code> <code class="n">args</code><code class="o">[])</code> <code class="o">{</code> <code class="n">String</code> <code class="n">message</code> <code class="o">=</code> <code class="s">"Lemming"</code><code class="o">;</code> <code class="k">if</code> <code class="o">(</code><code class="n">args</code><code class="o">.</code><code class="na">length</code> <code class="o">&gt;</code> <code class="mi">0</code><code class="o">)</code> <code class="n">message</code> <code class="o">=</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">];</code> <code class="n">JFrame</code> <code class="n">frame</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JFrame</code><code class="o">(</code><code class="s">"FontShow"</code><code class="o">);</code> <code class="n">frame</code><code class="o">.</code><code class="na">setSize</code><code class="o">(</code><code class="mi">420</code><code class="o">,</code> <code class="mi">300</code><code class="o">);</code> <code class="n">frame</code><code class="o">.</code><code class="na">setDefaultCloseOperation</code><code class="o">(</code> <code class="n">JFrame</code><code class="o">.</code><code class="na">EXIT_ON_CLOSE</code> <code class="o">);</code> <code class="n">frame</code><code class="o">.</code><code class="na">getContentPane</code><code class="o">().</code><code class="na">add</code><code class="o">(</code><code class="k">new</code> <code class="n">FontShow</code><code class="o">(</code><code class="n">message</code><code class="o">));</code> <code class="n">frame</code><code class="o">.</code><code class="na">setVisible</code><code class="o">(</code><code class="kc">true</code><code class="o">);</code> <code class="o">}</code> <code class="o">}</code></pre><div class="figure"><a id="learnjava3-CHP-20-FIG-3"/><div class="figure-contents"><div class="mediaobject"><a id="I_20_tt1159"/><img src="httpatomoreillycomsourceoreillyimages1707693.png" alt="The FontShow application"/></div></div><p class="title">Figure 20-3. The FontShow application</p></div><p>You can specify the text to be displayed as a command-line argument:</p><a id="I_20_tt1158"/><pre class="programlisting"> <code class="o">%</code> <strong class="userinput"><code><code class="n">java</code> <code class="n">FontShow</code> <code class="s">"When in the course of human events ..."</code></code></strong></pre><p><code class="literal">FontShow</code> may look a bit complicated, but there’s really not much to it. The bulk of the code is in <code class="literal">paint()</code>, which sets the font, draws the text, and adds a few lines to illustrate some of the font’s characteristics (metrics). For fun, we also catch mouse clicks (using an event handler defined in the constructor) and alternate the font size by setting the <code class="literal">bigFont</code> toggle variable and repainting.</p><p>By default, text is rendered above and to the right of the coordinates specified in the <code class="literal">drawString()</code> method. Think of that starting point as the origin of a coordinate system; the axes are the <a id="I_indexterm20_id812852" class="indexterm"/><span class="emphasis"><em>baselines</em></span> of the font. <code class="literal">FontShow</code> draws these lines in white. The greatest height the characters stretch above the baseline is called the <a id="I_indexterm20_id812867" class="indexterm"/><span class="emphasis"><em>ascent</em></span> and is shown by a green line. Some fonts also have parts of letters that fall below the baseline. The farthest distance any character reaches below the baseline is called the <a id="I_indexterm20_id812877" class="indexterm"/><span class="emphasis"><em>descent</em></span>, which is illustrated with a red line.</p><p>We ask for the ascent and descent of our font with the <code class="literal">LineMetrics</code> class’s <code class="literal">getAscent()</code> and <code class="literal">getDescent()</code> methods. We also ask for the width of our string (when rendered in this font) with <code class="literal">Font</code>’s <a id="I_indexterm20_id812911" class="indexterm"/><code class="literal">getStringBounds()</code> method. This information is used to center the word in the display area. To center the word vertically, we use the height and adjust with the descent to calculate the baseline location. <a class="xref" href="ch20s06.html#learnjava3-CHP-20-TABLE-2" title="Table 20-2. LineMetrics methods">Table 20-2</a> provides a short list of methods that return useful font metrics.</p><div class="table"><a id="learnjava3-CHP-20-TABLE-2"/><p class="title">Table 20-2. LineMetrics methods</p><div class="table-contents"><table summary="LineMetrics methods" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; "><colgroup><col/><col/></colgroup><thead><tr><th style="text-align: left"><p>Method</p></th><th style="text-align: left"><p>Description</p></th></tr></thead><tbody><tr><td style="text-align: left"><p> <a id="I_indexterm20_id812974" class="indexterm"/> <code class="literal">getAscent()</code> </p></td><td style="text-align: left"><p>Height above baseline</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm20_id812998" class="indexterm"/> <code class="literal">getDescent()</code> </p></td><td style="text-align: left"><p>Depth below baseline</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm20_id813021" class="indexterm"/> <code class="literal">getLeading()</code> </p></td><td style="text-align: left"><p>Standard vertical spacing between lines</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm20_id813045" class="indexterm"/> <code class="literal">getHeight()</code> </p></td><td style="text-align: left"><p>Total line height (ascent + descent + leading)</p></td></tr></tbody></table></div></div><p><span class="emphasis"><em>Leading space</em></span> is the padding between lines of text. The <code class="literal">getHeight()</code> method reports the total height of a line of text, including the leading space.<a id="I_indexterm20_id813073" class="indexterm"/><a id="I_indexterm20_id813080" class="indexterm"/></p></div></div></body></html>