2
|
1 |
/*
|
|
2 |
* Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved.
|
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
|
7 |
* published by the Free Software Foundation. Sun designates this
|
|
8 |
* particular file as subject to the "Classpath" exception as provided
|
|
9 |
* by Sun in the LICENSE file that accompanied this code.
|
|
10 |
*
|
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
15 |
* accompanied this code).
|
|
16 |
*
|
|
17 |
* You should have received a copy of the GNU General Public License version
|
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20 |
*
|
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
23 |
* have any questions.
|
|
24 |
*/
|
|
25 |
|
|
26 |
package java.awt;
|
|
27 |
|
|
28 |
import java.awt.font.FontRenderContext;
|
|
29 |
import java.awt.font.GlyphVector;
|
|
30 |
import java.awt.font.LineMetrics;
|
|
31 |
import java.awt.font.TextAttribute;
|
|
32 |
import java.awt.font.TextLayout;
|
|
33 |
import java.awt.font.TransformAttribute;
|
|
34 |
import java.awt.geom.AffineTransform;
|
|
35 |
import java.awt.geom.Point2D;
|
|
36 |
import java.awt.geom.Rectangle2D;
|
|
37 |
import java.awt.peer.FontPeer;
|
|
38 |
import java.io.*;
|
|
39 |
import java.lang.ref.SoftReference;
|
|
40 |
import java.text.AttributedCharacterIterator.Attribute;
|
|
41 |
import java.text.CharacterIterator;
|
|
42 |
import java.text.StringCharacterIterator;
|
|
43 |
import java.util.HashMap;
|
|
44 |
import java.util.Hashtable;
|
|
45 |
import java.util.Locale;
|
|
46 |
import java.util.Map;
|
|
47 |
import sun.font.StandardGlyphVector;
|
|
48 |
import sun.java2d.FontSupport;
|
|
49 |
|
|
50 |
import sun.font.AttributeMap;
|
|
51 |
import sun.font.AttributeValues;
|
|
52 |
import sun.font.EAttribute;
|
|
53 |
import sun.font.CompositeFont;
|
|
54 |
import sun.font.Font2D;
|
|
55 |
import sun.font.Font2DHandle;
|
|
56 |
import sun.font.FontManager;
|
|
57 |
import sun.font.GlyphLayout;
|
|
58 |
import sun.font.FontLineMetrics;
|
|
59 |
import sun.font.CoreMetrics;
|
|
60 |
|
|
61 |
import static sun.font.EAttribute.*;
|
|
62 |
|
|
63 |
/**
|
|
64 |
* The <code>Font</code> class represents fonts, which are used to
|
|
65 |
* render text in a visible way.
|
|
66 |
* A font provides the information needed to map sequences of
|
|
67 |
* <em>characters</em> to sequences of <em>glyphs</em>
|
|
68 |
* and to render sequences of glyphs on <code>Graphics</code> and
|
|
69 |
* <code>Component</code> objects.
|
|
70 |
*
|
|
71 |
* <h4>Characters and Glyphs</h4>
|
|
72 |
*
|
|
73 |
* A <em>character</em> is a symbol that represents an item such as a letter,
|
|
74 |
* a digit, or punctuation in an abstract way. For example, <code>'g'</code>,
|
|
75 |
* <font size=-1>LATIN SMALL LETTER G</font>, is a character.
|
|
76 |
* <p>
|
|
77 |
* A <em>glyph</em> is a shape used to render a character or a sequence of
|
|
78 |
* characters. In simple writing systems, such as Latin, typically one glyph
|
|
79 |
* represents one character. In general, however, characters and glyphs do not
|
|
80 |
* have one-to-one correspondence. For example, the character 'á'
|
|
81 |
* <font size=-1>LATIN SMALL LETTER A WITH ACUTE</font>, can be represented by
|
|
82 |
* two glyphs: one for 'a' and one for '´'. On the other hand, the
|
|
83 |
* two-character string "fi" can be represented by a single glyph, an
|
|
84 |
* "fi" ligature. In complex writing systems, such as Arabic or the South
|
|
85 |
* and South-East Asian writing systems, the relationship between characters
|
|
86 |
* and glyphs can be more complicated and involve context-dependent selection
|
|
87 |
* of glyphs as well as glyph reordering.
|
|
88 |
*
|
|
89 |
* A font encapsulates the collection of glyphs needed to render a selected set
|
|
90 |
* of characters as well as the tables needed to map sequences of characters to
|
|
91 |
* corresponding sequences of glyphs.
|
|
92 |
*
|
|
93 |
* <h4>Physical and Logical Fonts</h4>
|
|
94 |
*
|
|
95 |
* The Java Platform distinguishes between two kinds of fonts:
|
|
96 |
* <em>physical</em> fonts and <em>logical</em> fonts.
|
|
97 |
* <p>
|
|
98 |
* <em>Physical</em> fonts are the actual font libraries containing glyph data
|
|
99 |
* and tables to map from character sequences to glyph sequences, using a font
|
|
100 |
* technology such as TrueType or PostScript Type 1.
|
|
101 |
* All implementations of the Java Platform must support TrueType fonts;
|
|
102 |
* support for other font technologies is implementation dependent.
|
|
103 |
* Physical fonts may use names such as Helvetica, Palatino, HonMincho, or
|
|
104 |
* any number of other font names.
|
|
105 |
* Typically, each physical font supports only a limited set of writing
|
|
106 |
* systems, for example, only Latin characters or only Japanese and Basic
|
|
107 |
* Latin.
|
|
108 |
* The set of available physical fonts varies between configurations.
|
|
109 |
* Applications that require specific fonts can bundle them and instantiate
|
|
110 |
* them using the {@link #createFont createFont} method.
|
|
111 |
* <p>
|
|
112 |
* <em>Logical</em> fonts are the five font families defined by the Java
|
|
113 |
* platform which must be supported by any Java runtime environment:
|
|
114 |
* Serif, SansSerif, Monospaced, Dialog, and DialogInput.
|
|
115 |
* These logical fonts are not actual font libraries. Instead, the logical
|
|
116 |
* font names are mapped to physical fonts by the Java runtime environment.
|
|
117 |
* The mapping is implementation and usually locale dependent, so the look
|
|
118 |
* and the metrics provided by them vary.
|
|
119 |
* Typically, each logical font name maps to several physical fonts in order to
|
|
120 |
* cover a large range of characters.
|
|
121 |
* <p>
|
|
122 |
* Peered AWT components, such as {@link Label Label} and
|
|
123 |
* {@link TextField TextField}, can only use logical fonts.
|
|
124 |
* <p>
|
|
125 |
* For a discussion of the relative advantages and disadvantages of using
|
|
126 |
* physical or logical fonts, see the
|
|
127 |
* <a href="http://java.sun.com/j2se/corejava/intl/reference/faqs/index.html#desktop-rendering">Internationalization FAQ</a>
|
|
128 |
* document.
|
|
129 |
*
|
|
130 |
* <h4>Font Faces and Names</h4>
|
|
131 |
*
|
|
132 |
* A <code>Font</code>
|
|
133 |
* can have many faces, such as heavy, medium, oblique, gothic and
|
|
134 |
* regular. All of these faces have similar typographic design.
|
|
135 |
* <p>
|
|
136 |
* There are three different names that you can get from a
|
|
137 |
* <code>Font</code> object. The <em>logical font name</em> is simply the
|
|
138 |
* name that was used to construct the font.
|
|
139 |
* The <em>font face name</em>, or just <em>font name</em> for
|
|
140 |
* short, is the name of a particular font face, like Helvetica Bold. The
|
|
141 |
* <em>family name</em> is the name of the font family that determines the
|
|
142 |
* typographic design across several faces, like Helvetica.
|
|
143 |
* <p>
|
|
144 |
* The <code>Font</code> class represents an instance of a font face from
|
|
145 |
* a collection of font faces that are present in the system resources
|
|
146 |
* of the host system. As examples, Arial Bold and Courier Bold Italic
|
|
147 |
* are font faces. There can be several <code>Font</code> objects
|
|
148 |
* associated with a font face, each differing in size, style, transform
|
|
149 |
* and font features.
|
|
150 |
* <p>
|
|
151 |
* The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
|
|
152 |
* of the <code>GraphicsEnvironment</code> class returns an
|
|
153 |
* array of all font faces available in the system. These font faces are
|
|
154 |
* returned as <code>Font</code> objects with a size of 1, identity
|
|
155 |
* transform and default font features. These
|
|
156 |
* base fonts can then be used to derive new <code>Font</code> objects
|
|
157 |
* with varying sizes, styles, transforms and font features via the
|
|
158 |
* <code>deriveFont</code> methods in this class.
|
|
159 |
*
|
|
160 |
* <h4>Font and TextAttribute</h4>
|
|
161 |
*
|
|
162 |
* <p><code>Font</code> supports most
|
|
163 |
* <code>TextAttribute</code>s. This makes some operations, such as
|
|
164 |
* rendering underlined text, convenient since it is not
|
|
165 |
* necessary to explicitly construct a <code>TextLayout</code> object.
|
|
166 |
* Attributes can be set on a Font by constructing or deriving it
|
|
167 |
* using a <code>Map</code> of <code>TextAttribute</code> values.
|
|
168 |
*
|
|
169 |
* <p>The values of some <code>TextAttributes</code> are not
|
|
170 |
* serializable, and therefore attempting to serialize an instance of
|
|
171 |
* <code>Font</code> that has such values will not serialize them.
|
|
172 |
* This means a Font deserialized from such a stream will not compare
|
|
173 |
* equal to the original Font that contained the non-serializable
|
|
174 |
* attributes. This should very rarely pose a problem
|
|
175 |
* since these attributes are typically used only in special
|
|
176 |
* circumstances and are unlikely to be serialized.
|
|
177 |
*
|
|
178 |
* <ul>
|
|
179 |
* <li><code>FOREGROUND</code> and <code>BACKGROUND</code> use
|
|
180 |
* <code>Paint</code> values. The subclass <code>Color</code> is
|
|
181 |
* serializable, while <code>GradientPaint</code> and
|
|
182 |
* <code>TexturePaint</code> are not.</li>
|
|
183 |
* <li><code>CHAR_REPLACEMENT</code> uses
|
|
184 |
* <code>GraphicAttribute</code> values. The subclasses
|
|
185 |
* <code>ShapeGraphicAttribute</code> and
|
|
186 |
* <code>ImageGraphicAttribute</code> are not serializable.</li>
|
|
187 |
* <li><code>INPUT_METHOD_HIGHLIGHT</code> uses
|
|
188 |
* <code>InputMethodHighlight</code> values, which are
|
|
189 |
* not serializable. See {@link java.awt.im.InputMethodHighlight}.</li>
|
|
190 |
* </ul>
|
|
191 |
*
|
|
192 |
* Clients who create custom subclasses of <code>Paint</code> and
|
|
193 |
* <code>GraphicAttribute</code> can make them serializable and
|
|
194 |
* avoid this problem. Clients who use input method highlights can
|
|
195 |
* convert these to the platform-specific attributes for that
|
|
196 |
* highlight on the current platform and set them on the Font as
|
|
197 |
* a workaround.</p>
|
|
198 |
*
|
|
199 |
* <p>The <code>Map</code>-based constructor and
|
|
200 |
* <code>deriveFont</code> APIs ignore the FONT attribute, and it is
|
|
201 |
* not retained by the Font; the static {@link #getFont} method should
|
|
202 |
* be used if the FONT attribute might be present. See {@link
|
|
203 |
* java.awt.font.TextAttribute#FONT} for more information.</p>
|
|
204 |
*
|
|
205 |
* <p>Several attributes will cause additional rendering overhead
|
|
206 |
* and potentially invoke layout. If a <code>Font</code> has such
|
|
207 |
* attributes, the <code>{@link #hasLayoutAttributes()}</code> method
|
|
208 |
* will return true.</p>
|
|
209 |
*
|
|
210 |
* <p>Note: Font rotations can cause text baselines to be rotated. In
|
|
211 |
* order to account for this (rare) possibility, font APIs are
|
|
212 |
* specified to return metrics and take parameters 'in
|
|
213 |
* baseline-relative coordinates'. This maps the 'x' coordinate to
|
|
214 |
* the advance along the baseline, (positive x is forward along the
|
|
215 |
* baseline), and the 'y' coordinate to a distance along the
|
|
216 |
* perpendicular to the baseline at 'x' (positive y is 90 degrees
|
|
217 |
* clockwise from the baseline vector). APIs for which this is
|
|
218 |
* especially important are called out as having 'baseline-relative
|
|
219 |
* coordinates.'
|
|
220 |
*/
|
|
221 |
public class Font implements java.io.Serializable
|
|
222 |
{
|
|
223 |
static {
|
|
224 |
/* ensure that the necessary native libraries are loaded */
|
|
225 |
Toolkit.loadLibraries();
|
|
226 |
initIDs();
|
|
227 |
}
|
|
228 |
|
|
229 |
/**
|
|
230 |
* This is now only used during serialization. Typically
|
|
231 |
* it is null.
|
|
232 |
*
|
|
233 |
* @serial
|
|
234 |
* @see #getAttributes()
|
|
235 |
*/
|
|
236 |
private Hashtable fRequestedAttributes;
|
|
237 |
|
|
238 |
/*
|
|
239 |
* Constants to be used for logical font family names.
|
|
240 |
*/
|
|
241 |
|
|
242 |
/**
|
|
243 |
* A String constant for the canonical family name of the
|
|
244 |
* logical font "Dialog". It is useful in Font construction
|
|
245 |
* to provide compile-time verification of the name.
|
|
246 |
* @since 1.6
|
|
247 |
*/
|
|
248 |
public static final String DIALOG = "Dialog";
|
|
249 |
|
|
250 |
/**
|
|
251 |
* A String constant for the canonical family name of the
|
|
252 |
* logical font "DialogInput". It is useful in Font construction
|
|
253 |
* to provide compile-time verification of the name.
|
|
254 |
* @since 1.6
|
|
255 |
*/
|
|
256 |
public static final String DIALOG_INPUT = "DialogInput";
|
|
257 |
|
|
258 |
/**
|
|
259 |
* A String constant for the canonical family name of the
|
|
260 |
* logical font "SansSerif". It is useful in Font construction
|
|
261 |
* to provide compile-time verification of the name.
|
|
262 |
* @since 1.6
|
|
263 |
*/
|
|
264 |
public static final String SANS_SERIF = "SansSerif";
|
|
265 |
|
|
266 |
/**
|
|
267 |
* A String constant for the canonical family name of the
|
|
268 |
* logical font "Serif". It is useful in Font construction
|
|
269 |
* to provide compile-time verification of the name.
|
|
270 |
* @since 1.6
|
|
271 |
*/
|
|
272 |
public static final String SERIF = "Serif";
|
|
273 |
|
|
274 |
/**
|
|
275 |
* A String constant for the canonical family name of the
|
|
276 |
* logical font "Monospaced". It is useful in Font construction
|
|
277 |
* to provide compile-time verification of the name.
|
|
278 |
* @since 1.6
|
|
279 |
*/
|
|
280 |
public static final String MONOSPACED = "Monospaced";
|
|
281 |
|
|
282 |
/*
|
|
283 |
* Constants to be used for styles. Can be combined to mix
|
|
284 |
* styles.
|
|
285 |
*/
|
|
286 |
|
|
287 |
/**
|
|
288 |
* The plain style constant.
|
|
289 |
*/
|
|
290 |
public static final int PLAIN = 0;
|
|
291 |
|
|
292 |
/**
|
|
293 |
* The bold style constant. This can be combined with the other style
|
|
294 |
* constants (except PLAIN) for mixed styles.
|
|
295 |
*/
|
|
296 |
public static final int BOLD = 1;
|
|
297 |
|
|
298 |
/**
|
|
299 |
* The italicized style constant. This can be combined with the other
|
|
300 |
* style constants (except PLAIN) for mixed styles.
|
|
301 |
*/
|
|
302 |
public static final int ITALIC = 2;
|
|
303 |
|
|
304 |
/**
|
|
305 |
* The baseline used in most Roman scripts when laying out text.
|
|
306 |
*/
|
|
307 |
public static final int ROMAN_BASELINE = 0;
|
|
308 |
|
|
309 |
/**
|
|
310 |
* The baseline used in ideographic scripts like Chinese, Japanese,
|
|
311 |
* and Korean when laying out text.
|
|
312 |
*/
|
|
313 |
public static final int CENTER_BASELINE = 1;
|
|
314 |
|
|
315 |
/**
|
|
316 |
* The baseline used in Devanigiri and similar scripts when laying
|
|
317 |
* out text.
|
|
318 |
*/
|
|
319 |
public static final int HANGING_BASELINE = 2;
|
|
320 |
|
|
321 |
/**
|
|
322 |
* Identify a font resource of type TRUETYPE.
|
|
323 |
* Used to specify a TrueType font resource to the
|
|
324 |
* {@link #createFont} method.
|
|
325 |
* @since 1.3
|
|
326 |
*/
|
|
327 |
|
|
328 |
public static final int TRUETYPE_FONT = 0;
|
|
329 |
|
|
330 |
/**
|
|
331 |
* Identify a font resource of type TYPE1.
|
|
332 |
* Used to specify a Type1 font resource to the
|
|
333 |
* {@link #createFont} method.
|
|
334 |
* @since 1.5
|
|
335 |
*/
|
|
336 |
public static final int TYPE1_FONT = 1;
|
|
337 |
|
|
338 |
/**
|
|
339 |
* The logical name of this <code>Font</code>, as passed to the
|
|
340 |
* constructor.
|
|
341 |
* @since JDK1.0
|
|
342 |
*
|
|
343 |
* @serial
|
|
344 |
* @see #getName
|
|
345 |
*/
|
|
346 |
protected String name;
|
|
347 |
|
|
348 |
/**
|
|
349 |
* The style of this <code>Font</code>, as passed to the constructor.
|
|
350 |
* This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
|
|
351 |
* @since JDK1.0
|
|
352 |
*
|
|
353 |
* @serial
|
|
354 |
* @see #getStyle()
|
|
355 |
*/
|
|
356 |
protected int style;
|
|
357 |
|
|
358 |
/**
|
|
359 |
* The point size of this <code>Font</code>, rounded to integer.
|
|
360 |
* @since JDK1.0
|
|
361 |
*
|
|
362 |
* @serial
|
|
363 |
* @see #getSize()
|
|
364 |
*/
|
|
365 |
protected int size;
|
|
366 |
|
|
367 |
/**
|
|
368 |
* The point size of this <code>Font</code> in <code>float</code>.
|
|
369 |
*
|
|
370 |
* @serial
|
|
371 |
* @see #getSize()
|
|
372 |
* @see #getSize2D()
|
|
373 |
*/
|
|
374 |
protected float pointSize;
|
|
375 |
|
|
376 |
/**
|
|
377 |
* The platform specific font information.
|
|
378 |
*/
|
|
379 |
private transient FontPeer peer;
|
|
380 |
private transient long pData; // native JDK1.1 font pointer
|
|
381 |
private transient Font2DHandle font2DHandle;
|
|
382 |
|
|
383 |
private transient AttributeValues values;
|
|
384 |
private transient boolean hasLayoutAttributes;
|
|
385 |
|
|
386 |
/*
|
|
387 |
* If the origin of a Font is a created font then this attribute
|
|
388 |
* must be set on all derived fonts too.
|
|
389 |
*/
|
|
390 |
private transient boolean createdFont = false;
|
|
391 |
|
|
392 |
/*
|
|
393 |
* This is true if the font transform is not identity. It
|
|
394 |
* is used to avoid unnecessary instantiation of an AffineTransform.
|
|
395 |
*/
|
|
396 |
private transient boolean nonIdentityTx;
|
|
397 |
|
|
398 |
/*
|
|
399 |
* A cached value used when a transform is required for internal
|
|
400 |
* use. This must not be exposed to callers since AffineTransform
|
|
401 |
* is mutable.
|
|
402 |
*/
|
|
403 |
private static final AffineTransform identityTx = new AffineTransform();
|
|
404 |
|
|
405 |
/*
|
|
406 |
* JDK 1.1 serialVersionUID
|
|
407 |
*/
|
|
408 |
private static final long serialVersionUID = -4206021311591459213L;
|
|
409 |
|
|
410 |
/**
|
|
411 |
* Gets the peer of this <code>Font</code>.
|
|
412 |
* @return the peer of the <code>Font</code>.
|
|
413 |
* @since JDK1.1
|
|
414 |
* @deprecated Font rendering is now platform independent.
|
|
415 |
*/
|
|
416 |
@Deprecated
|
|
417 |
public FontPeer getPeer(){
|
|
418 |
return getPeer_NoClientCode();
|
|
419 |
}
|
|
420 |
// NOTE: This method is called by privileged threads.
|
|
421 |
// We implement this functionality in a package-private method
|
|
422 |
// to insure that it cannot be overridden by client subclasses.
|
|
423 |
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
|
|
424 |
final FontPeer getPeer_NoClientCode() {
|
|
425 |
if(peer == null) {
|
|
426 |
Toolkit tk = Toolkit.getDefaultToolkit();
|
|
427 |
this.peer = tk.getFontPeer(name, style);
|
|
428 |
}
|
|
429 |
return peer;
|
|
430 |
}
|
|
431 |
|
|
432 |
/**
|
|
433 |
* Return the AttributeValues object associated with this
|
|
434 |
* font. Most of the time, the internal object is null.
|
|
435 |
* If required, it will be created from the 'standard'
|
|
436 |
* state on the font. Only non-default values will be
|
|
437 |
* set in the AttributeValues object.
|
|
438 |
*
|
|
439 |
* <p>Since the AttributeValues object is mutable, and it
|
|
440 |
* is cached in the font, care must be taken to ensure that
|
|
441 |
* it is not mutated.
|
|
442 |
*/
|
|
443 |
private AttributeValues getAttributeValues() {
|
|
444 |
if (values == null) {
|
|
445 |
values = new AttributeValues();
|
|
446 |
values.setFamily(name);
|
|
447 |
values.setSize(pointSize); // expects the float value.
|
|
448 |
|
|
449 |
if ((style & BOLD) != 0) {
|
|
450 |
values.setWeight(2); // WEIGHT_BOLD
|
|
451 |
}
|
|
452 |
|
|
453 |
if ((style & ITALIC) != 0) {
|
|
454 |
values.setPosture(.2f); // POSTURE_OBLIQUE
|
|
455 |
}
|
|
456 |
values.defineAll(PRIMARY_MASK); // for streaming compatibility
|
|
457 |
}
|
|
458 |
|
|
459 |
return values;
|
|
460 |
}
|
|
461 |
|
|
462 |
private Font2D getFont2D() {
|
|
463 |
if (FontManager.usingPerAppContextComposites &&
|
|
464 |
font2DHandle != null &&
|
|
465 |
font2DHandle.font2D instanceof CompositeFont &&
|
|
466 |
((CompositeFont)(font2DHandle.font2D)).isStdComposite()) {
|
|
467 |
return FontManager.findFont2D(name, style,
|
|
468 |
FontManager.LOGICAL_FALLBACK);
|
|
469 |
} else if (font2DHandle == null) {
|
|
470 |
font2DHandle =
|
|
471 |
FontManager.findFont2D(name, style,
|
|
472 |
FontManager.LOGICAL_FALLBACK).handle;
|
|
473 |
}
|
|
474 |
/* Do not cache the de-referenced font2D. It must be explicitly
|
|
475 |
* de-referenced to pick up a valid font in the event that the
|
|
476 |
* original one is marked invalid
|
|
477 |
*/
|
|
478 |
return font2DHandle.font2D;
|
|
479 |
}
|
|
480 |
|
|
481 |
/**
|
|
482 |
* Creates a new <code>Font</code> from the specified name, style and
|
|
483 |
* point size.
|
|
484 |
* <p>
|
|
485 |
* The font name can be a font face name or a font family name.
|
|
486 |
* It is used together with the style to find an appropriate font face.
|
|
487 |
* When a font family name is specified, the style argument is used to
|
|
488 |
* select the most appropriate face from the family. When a font face
|
|
489 |
* name is specified, the face's style and the style argument are
|
|
490 |
* merged to locate the best matching font from the same family.
|
|
491 |
* For example if face name "Arial Bold" is specified with style
|
|
492 |
* <code>Font.ITALIC</code>, the font system looks for a face in the
|
|
493 |
* "Arial" family that is bold and italic, and may associate the font
|
|
494 |
* instance with the physical font face "Arial Bold Italic".
|
|
495 |
* The style argument is merged with the specified face's style, not
|
|
496 |
* added or subtracted.
|
|
497 |
* This means, specifying a bold face and a bold style does not
|
|
498 |
* double-embolden the font, and specifying a bold face and a plain
|
|
499 |
* style does not lighten the font.
|
|
500 |
* <p>
|
|
501 |
* If no face for the requested style can be found, the font system
|
|
502 |
* may apply algorithmic styling to achieve the desired style.
|
|
503 |
* For example, if <code>ITALIC</code> is requested, but no italic
|
|
504 |
* face is available, glyphs from the plain face may be algorithmically
|
|
505 |
* obliqued (slanted).
|
|
506 |
* <p>
|
|
507 |
* Font name lookup is case insensitive, using the case folding
|
|
508 |
* rules of the US locale.
|
|
509 |
* <p>
|
|
510 |
* If the <code>name</code> parameter represents something other than a
|
|
511 |
* logical font, i.e. is interpreted as a physical font face or family, and
|
|
512 |
* this cannot be mapped by the implementation to a physical font or a
|
|
513 |
* compatible alternative, then the font system will map the Font
|
|
514 |
* instance to "Dialog", such that for example, the family as reported
|
|
515 |
* by {@link #getFamily() getFamily} will be "Dialog".
|
|
516 |
* <p>
|
|
517 |
*
|
|
518 |
* @param name the font name. This can be a font face name or a font
|
|
519 |
* family name, and may represent either a logical font or a physical
|
|
520 |
* font found in this {@code GraphicsEnvironment}.
|
|
521 |
* The family names for logical fonts are: Dialog, DialogInput,
|
|
522 |
* Monospaced, Serif, or SansSerif. Pre-defined String constants exist
|
|
523 |
* for all of these names, for example, {@code DIALOG}. If {@code name} is
|
|
524 |
* {@code null}, the <em>logical font name</em> of the new
|
|
525 |
* {@code Font} as returned by {@code getName()} is set to
|
|
526 |
* the name "Default".
|
|
527 |
* @param style the style constant for the {@code Font}
|
|
528 |
* The style argument is an integer bitmask that may
|
|
529 |
* be {@code PLAIN}, or a bitwise union of {@code BOLD} and/or
|
|
530 |
* {@code ITALIC} (for example, {@code ITALIC} or {@code BOLD|ITALIC}).
|
|
531 |
* If the style argument does not conform to one of the expected
|
|
532 |
* integer bitmasks then the style is set to {@code PLAIN}.
|
|
533 |
* @param size the point size of the {@code Font}
|
|
534 |
* @see GraphicsEnvironment#getAllFonts
|
|
535 |
* @see GraphicsEnvironment#getAvailableFontFamilyNames
|
|
536 |
* @since JDK1.0
|
|
537 |
*/
|
|
538 |
public Font(String name, int style, int size) {
|
|
539 |
this.name = (name != null) ? name : "Default";
|
|
540 |
this.style = (style & ~0x03) == 0 ? style : 0;
|
|
541 |
this.size = size;
|
|
542 |
this.pointSize = size;
|
|
543 |
}
|
|
544 |
|
|
545 |
private Font(String name, int style, float sizePts) {
|
|
546 |
this.name = (name != null) ? name : "Default";
|
|
547 |
this.style = (style & ~0x03) == 0 ? style : 0;
|
|
548 |
this.size = (int)(sizePts + 0.5);
|
|
549 |
this.pointSize = sizePts;
|
|
550 |
}
|
|
551 |
|
|
552 |
/* This constructor is used by deriveFont when attributes is null */
|
|
553 |
private Font(String name, int style, float sizePts,
|
|
554 |
boolean created, Font2DHandle handle) {
|
|
555 |
this(name, style, sizePts);
|
|
556 |
this.createdFont = created;
|
|
557 |
/* Fonts created from a stream will use the same font2D instance
|
|
558 |
* as the parent.
|
|
559 |
* One exception is that if the derived font is requested to be
|
|
560 |
* in a different style, then also check if its a CompositeFont
|
|
561 |
* and if so build a new CompositeFont from components of that style.
|
|
562 |
* CompositeFonts can only be marked as "created" if they are used
|
|
563 |
* to add fall backs to a physical font. And non-composites are
|
|
564 |
* always from "Font.createFont()" and shouldn't get this treatment.
|
|
565 |
*/
|
|
566 |
if (created) {
|
|
567 |
if (handle.font2D instanceof CompositeFont &&
|
|
568 |
handle.font2D.getStyle() != style) {
|
|
569 |
this.font2DHandle =
|
|
570 |
FontManager.getNewComposite(null, style, handle);
|
|
571 |
} else {
|
|
572 |
this.font2DHandle = handle;
|
|
573 |
}
|
|
574 |
}
|
|
575 |
}
|
|
576 |
|
|
577 |
/* used to implement Font.createFont */
|
|
578 |
private Font(File fontFile, int fontFormat, boolean isCopy)
|
|
579 |
throws FontFormatException {
|
|
580 |
this.createdFont = true;
|
|
581 |
/* Font2D instances created by this method track their font file
|
|
582 |
* so that when the Font2D is GC'd it can also remove the file.
|
|
583 |
*/
|
|
584 |
this.font2DHandle =
|
|
585 |
FontManager.createFont2D(fontFile, fontFormat, isCopy).handle;
|
|
586 |
this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
|
|
587 |
this.style = Font.PLAIN;
|
|
588 |
this.size = 1;
|
|
589 |
this.pointSize = 1f;
|
|
590 |
}
|
|
591 |
|
|
592 |
/* This constructor is used when one font is derived from another.
|
|
593 |
* Fonts created from a stream will use the same font2D instance as the
|
|
594 |
* parent. They can be distinguished because the "created" argument
|
|
595 |
* will be "true". Since there is no way to recreate these fonts they
|
|
596 |
* need to have the handle to the underlying font2D passed in.
|
|
597 |
* "created" is also true when a special composite is referenced by the
|
|
598 |
* handle for essentially the same reasons.
|
|
599 |
* But when deriving a font in these cases two particular attributes
|
|
600 |
* need special attention: family/face and style.
|
|
601 |
* The "composites" in these cases need to be recreated with optimal
|
|
602 |
* fonts for the new values of family and style.
|
|
603 |
* For fonts created with createFont() these are treated differently.
|
|
604 |
* JDK can often synthesise a different style (bold from plain
|
|
605 |
* for example). For fonts created with "createFont" this is a reasonable
|
|
606 |
* solution but its also possible (although rare) to derive a font with a
|
|
607 |
* different family attribute. In this case JDK needs
|
|
608 |
* to break the tie with the original Font2D and find a new Font.
|
|
609 |
* The oldName and oldStyle are supplied so they can be compared with
|
|
610 |
* what the Font2D and the values. To speed things along :
|
|
611 |
* oldName == null will be interpreted as the name is unchanged.
|
|
612 |
* oldStyle = -1 will be interpreted as the style is unchanged.
|
|
613 |
* In these cases there is no need to interrogate "values".
|
|
614 |
*/
|
|
615 |
private Font(AttributeValues values, String oldName, int oldStyle,
|
|
616 |
boolean created, Font2DHandle handle) {
|
|
617 |
|
|
618 |
this.createdFont = created;
|
|
619 |
if (created) {
|
|
620 |
this.font2DHandle = handle;
|
|
621 |
|
|
622 |
String newName = null;
|
|
623 |
if (oldName != null) {
|
|
624 |
newName = values.getFamily();
|
|
625 |
if (oldName.equals(newName)) newName = null;
|
|
626 |
}
|
|
627 |
int newStyle = 0;
|
|
628 |
if (oldStyle == -1) {
|
|
629 |
newStyle = -1;
|
|
630 |
} else {
|
|
631 |
if (values.getWeight() >= 2f) newStyle = BOLD;
|
|
632 |
if (values.getPosture() >= .2f) newStyle |= ITALIC;
|
|
633 |
if (oldStyle == newStyle) newStyle = -1;
|
|
634 |
}
|
|
635 |
if (handle.font2D instanceof CompositeFont) {
|
|
636 |
if (newStyle != -1 || newName != null) {
|
|
637 |
this.font2DHandle =
|
|
638 |
FontManager.getNewComposite(newName, newStyle, handle);
|
|
639 |
}
|
|
640 |
} else if (newName != null) {
|
|
641 |
this.createdFont = false;
|
|
642 |
this.font2DHandle = null;
|
|
643 |
}
|
|
644 |
}
|
|
645 |
initFromValues(values);
|
|
646 |
}
|
|
647 |
|
|
648 |
/**
|
|
649 |
* Creates a new <code>Font</code> with the specified attributes.
|
|
650 |
* Only keys defined in {@link java.awt.font.TextAttribute TextAttribute}
|
|
651 |
* are recognized. In addition the FONT attribute is
|
|
652 |
* not recognized by this constructor
|
|
653 |
* (see {@link #getAvailableAttributes}). Only attributes that have
|
|
654 |
* values of valid types will affect the new <code>Font</code>.
|
|
655 |
* <p>
|
|
656 |
* If <code>attributes</code> is <code>null</code>, a new
|
|
657 |
* <code>Font</code> is initialized with default values.
|
|
658 |
* @see java.awt.font.TextAttribute
|
|
659 |
* @param attributes the attributes to assign to the new
|
|
660 |
* <code>Font</code>, or <code>null</code>
|
|
661 |
*/
|
|
662 |
public Font(Map<? extends Attribute, ?> attributes) {
|
|
663 |
initFromValues(AttributeValues.fromMap(attributes, RECOGNIZED_MASK));
|
|
664 |
}
|
|
665 |
|
|
666 |
/**
|
|
667 |
* Creates a new <code>Font</code> from the specified <code>font</code>.
|
|
668 |
* This constructor is intended for use by subclasses.
|
|
669 |
* @param font from which to create this <code>Font</code>.
|
|
670 |
* @throws NullPointerException if <code>font</code> is null
|
|
671 |
* @since 1.6
|
|
672 |
*/
|
|
673 |
protected Font(Font font) {
|
|
674 |
if (font.values != null) {
|
|
675 |
initFromValues(font.getAttributeValues().clone());
|
|
676 |
} else {
|
|
677 |
this.name = font.name;
|
|
678 |
this.style = font.style;
|
|
679 |
this.size = font.size;
|
|
680 |
this.pointSize = font.pointSize;
|
|
681 |
}
|
|
682 |
this.font2DHandle = font.font2DHandle;
|
|
683 |
this.createdFont = font.createdFont;
|
|
684 |
}
|
|
685 |
|
|
686 |
/**
|
|
687 |
* Font recognizes all attributes except FONT.
|
|
688 |
*/
|
|
689 |
private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL
|
|
690 |
& ~AttributeValues.getMask(EFONT);
|
|
691 |
|
|
692 |
/**
|
|
693 |
* These attributes are considered primary by the FONT attribute.
|
|
694 |
*/
|
|
695 |
private static final int PRIMARY_MASK =
|
|
696 |
AttributeValues.getMask(EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE,
|
|
697 |
ETRANSFORM, ESUPERSCRIPT, ETRACKING);
|
|
698 |
|
|
699 |
/**
|
|
700 |
* These attributes are considered secondary by the FONT attribute.
|
|
701 |
*/
|
|
702 |
private static final int SECONDARY_MASK =
|
|
703 |
RECOGNIZED_MASK & ~PRIMARY_MASK;
|
|
704 |
|
|
705 |
/**
|
|
706 |
* These attributes are handled by layout.
|
|
707 |
*/
|
|
708 |
private static final int LAYOUT_MASK =
|
|
709 |
AttributeValues.getMask(ECHAR_REPLACEMENT, EFOREGROUND, EBACKGROUND,
|
|
710 |
EUNDERLINE, ESTRIKETHROUGH, ERUN_DIRECTION,
|
|
711 |
EBIDI_EMBEDDING, EJUSTIFICATION,
|
|
712 |
EINPUT_METHOD_HIGHLIGHT, EINPUT_METHOD_UNDERLINE,
|
|
713 |
ESWAP_COLORS, ENUMERIC_SHAPING, EKERNING,
|
|
714 |
ELIGATURES, ETRACKING);
|
|
715 |
|
|
716 |
private static final int EXTRA_MASK =
|
|
717 |
AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH);
|
|
718 |
|
|
719 |
/**
|
|
720 |
* Initialize the standard Font fields from the values object.
|
|
721 |
*/
|
|
722 |
private void initFromValues(AttributeValues values) {
|
|
723 |
this.values = values;
|
|
724 |
values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility
|
|
725 |
|
|
726 |
this.name = values.getFamily();
|
|
727 |
this.pointSize = values.getSize();
|
|
728 |
this.size = (int)(values.getSize() + 0.5);
|
|
729 |
if (values.getWeight() >= 2f) this.style |= BOLD; // not == 2f
|
|
730 |
if (values.getPosture() >= .2f) this.style |= ITALIC; // not == .2f
|
|
731 |
|
|
732 |
this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
|
|
733 |
this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
|
|
734 |
}
|
|
735 |
|
|
736 |
/**
|
|
737 |
* Returns a <code>Font</code> appropriate to the attributes.
|
|
738 |
* If <code>attributes</code>contains a <code>FONT</code> attribute
|
|
739 |
* with a valid <code>Font</code> as its value, it will be
|
|
740 |
* merged with any remaining attributes. See
|
|
741 |
* {@link java.awt.font.TextAttribute#FONT} for more
|
|
742 |
* information.
|
|
743 |
*
|
|
744 |
* @param attributes the attributes to assign to the new
|
|
745 |
* <code>Font</code>
|
|
746 |
* @return a new <code>Font</code> created with the specified
|
|
747 |
* attributes
|
|
748 |
* @throws NullPointerException if <code>attributes</code> is null.
|
|
749 |
* @since 1.2
|
|
750 |
* @see java.awt.font.TextAttribute
|
|
751 |
*/
|
|
752 |
public static Font getFont(Map<? extends Attribute, ?> attributes) {
|
|
753 |
// optimize for two cases:
|
|
754 |
// 1) FONT attribute, and nothing else
|
|
755 |
// 2) attributes, but no FONT
|
|
756 |
|
|
757 |
// avoid turning the attributemap into a regular map for no reason
|
|
758 |
if (attributes instanceof AttributeMap &&
|
|
759 |
((AttributeMap)attributes).getValues() != null) {
|
|
760 |
AttributeValues values = ((AttributeMap)attributes).getValues();
|
|
761 |
if (values.isNonDefault(EFONT)) {
|
|
762 |
Font font = values.getFont();
|
|
763 |
if (!values.anyDefined(SECONDARY_MASK)) {
|
|
764 |
return font;
|
|
765 |
}
|
|
766 |
// merge
|
|
767 |
values = font.getAttributeValues().clone();
|
|
768 |
values.merge(attributes, SECONDARY_MASK);
|
|
769 |
return new Font(values, font.name, font.style,
|
|
770 |
font.createdFont, font.font2DHandle);
|
|
771 |
}
|
|
772 |
return new Font(attributes);
|
|
773 |
}
|
|
774 |
|
|
775 |
Font font = (Font)attributes.get(TextAttribute.FONT);
|
|
776 |
if (font != null) {
|
|
777 |
if (attributes.size() > 1) { // oh well, check for anything else
|
|
778 |
AttributeValues values = font.getAttributeValues().clone();
|
|
779 |
values.merge(attributes, SECONDARY_MASK);
|
|
780 |
return new Font(values, font.name, font.style,
|
|
781 |
font.createdFont, font.font2DHandle);
|
|
782 |
}
|
|
783 |
|
|
784 |
return font;
|
|
785 |
}
|
|
786 |
|
|
787 |
return new Font(attributes);
|
|
788 |
}
|
|
789 |
|
|
790 |
/**
|
|
791 |
* Returns a new <code>Font</code> using the specified font type
|
|
792 |
* and input data. The new <code>Font</code> is
|
|
793 |
* created with a point size of 1 and style {@link #PLAIN PLAIN}.
|
|
794 |
* This base font can then be used with the <code>deriveFont</code>
|
|
795 |
* methods in this class to derive new <code>Font</code> objects with
|
|
796 |
* varying sizes, styles, transforms and font features. This
|
|
797 |
* method does not close the {@link InputStream}.
|
|
798 |
* <p>
|
|
799 |
* To make the <code>Font</code> available to Font constructors the
|
|
800 |
* returned <code>Font</code> must be registered in the
|
|
801 |
* <code>GraphicsEnviroment</code> by calling
|
|
802 |
* {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
|
|
803 |
* @param fontFormat the type of the <code>Font</code>, which is
|
|
804 |
* {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified.
|
|
805 |
* or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified.
|
|
806 |
* @param fontStream an <code>InputStream</code> object representing the
|
|
807 |
* input data for the font.
|
|
808 |
* @return a new <code>Font</code> created with the specified font type.
|
|
809 |
* @throws IllegalArgumentException if <code>fontFormat</code> is not
|
|
810 |
* <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
|
|
811 |
* @throws FontFormatException if the <code>fontStream</code> data does
|
|
812 |
* not contain the required font tables for the specified format.
|
|
813 |
* @throws IOException if the <code>fontStream</code>
|
|
814 |
* cannot be completely read.
|
|
815 |
* @see GraphicsEnvironment#registerFont(Font)
|
|
816 |
* @since 1.3
|
|
817 |
*/
|
|
818 |
public static Font createFont(int fontFormat, InputStream fontStream)
|
|
819 |
throws java.awt.FontFormatException, java.io.IOException {
|
|
820 |
|
|
821 |
if (fontFormat != Font.TRUETYPE_FONT &&
|
|
822 |
fontFormat != Font.TYPE1_FONT) {
|
|
823 |
throw new IllegalArgumentException ("font format not recognized");
|
|
824 |
}
|
|
825 |
final InputStream fStream = fontStream;
|
|
826 |
Object ret = java.security.AccessController.doPrivileged(
|
|
827 |
new java.security.PrivilegedAction() {
|
|
828 |
public Object run() {
|
|
829 |
File tFile = null;
|
|
830 |
FileOutputStream outStream = null;
|
|
831 |
try {
|
|
832 |
tFile = File.createTempFile("+~JF", ".tmp", null);
|
|
833 |
/* Temp file deleted by font shutdown hook */
|
|
834 |
BufferedInputStream inStream =
|
|
835 |
new BufferedInputStream(fStream);
|
|
836 |
outStream = new FileOutputStream(tFile);
|
|
837 |
int bytesRead = 0;
|
|
838 |
int bufSize = 8192;
|
|
839 |
byte [] buf = new byte[bufSize];
|
|
840 |
while (bytesRead != -1) {
|
|
841 |
try {
|
|
842 |
bytesRead = inStream.read(buf, 0, bufSize);
|
|
843 |
} catch (Throwable t) {
|
|
844 |
throw new IOException();
|
|
845 |
}
|
|
846 |
if (bytesRead != -1) {
|
|
847 |
outStream.write(buf, 0, bytesRead);
|
|
848 |
}
|
|
849 |
}
|
|
850 |
/* don't close the input stream */
|
|
851 |
outStream.close();
|
|
852 |
} catch (IOException e) {
|
|
853 |
if (outStream != null) {
|
|
854 |
try {
|
|
855 |
outStream.close();
|
|
856 |
} catch (Exception e1) {
|
|
857 |
}
|
|
858 |
}
|
|
859 |
if (tFile != null) {
|
|
860 |
try {
|
|
861 |
tFile.delete();
|
|
862 |
} catch (Exception e2) {
|
|
863 |
}
|
|
864 |
}
|
|
865 |
return e;
|
|
866 |
}
|
|
867 |
return tFile;
|
|
868 |
}
|
|
869 |
});
|
|
870 |
|
|
871 |
if (ret instanceof File) {
|
|
872 |
return new Font((File)ret, fontFormat, true);
|
|
873 |
} else if (ret instanceof IOException) {
|
|
874 |
throw (IOException)ret;
|
|
875 |
} else {
|
|
876 |
throw new FontFormatException("Couldn't access font stream");
|
|
877 |
}
|
|
878 |
}
|
|
879 |
|
|
880 |
/**
|
|
881 |
* Returns a new <code>Font</code> using the specified font type
|
|
882 |
* and the specified font file. The new <code>Font</code> is
|
|
883 |
* created with a point size of 1 and style {@link #PLAIN PLAIN}.
|
|
884 |
* This base font can then be used with the <code>deriveFont</code>
|
|
885 |
* methods in this class to derive new <code>Font</code> objects with
|
|
886 |
* varying sizes, styles, transforms and font features.
|
|
887 |
* @param fontFormat the type of the <code>Font</code>, which is
|
|
888 |
* {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is
|
|
889 |
* specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is
|
|
890 |
* specified.
|
|
891 |
* So long as the returned font, or its derived fonts are referenced
|
|
892 |
* the implementation may continue to access <code>fontFile</code>
|
|
893 |
* to retrieve font data. Thus the results are undefined if the file
|
|
894 |
* is changed, or becomes inaccessible.
|
|
895 |
* <p>
|
|
896 |
* To make the <code>Font</code> available to Font constructors the
|
|
897 |
* returned <code>Font</code> must be registered in the
|
|
898 |
* <code>GraphicsEnviroment</code> by calling
|
|
899 |
* {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
|
|
900 |
* @param fontFile a <code>File</code> object representing the
|
|
901 |
* input data for the font.
|
|
902 |
* @return a new <code>Font</code> created with the specified font type.
|
|
903 |
* @throws IllegalArgumentException if <code>fontFormat</code> is not
|
|
904 |
* <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
|
|
905 |
* @throws NullPointerException if <code>fontFile</code> is null.
|
|
906 |
* @throws IOException if the <code>fontFile</code> cannot be read.
|
|
907 |
* @throws FontFormatException if <code>fontFile</code> does
|
|
908 |
* not contain the required font tables for the specified format.
|
|
909 |
* @throws SecurityException if the executing code does not have
|
|
910 |
* permission to read from the file.
|
|
911 |
* @see GraphicsEnvironment#registerFont(Font)
|
|
912 |
* @since 1.5
|
|
913 |
*/
|
|
914 |
public static Font createFont(int fontFormat, File fontFile)
|
|
915 |
throws java.awt.FontFormatException, java.io.IOException {
|
|
916 |
if (fontFormat != Font.TRUETYPE_FONT &&
|
|
917 |
fontFormat != Font.TYPE1_FONT) {
|
|
918 |
throw new IllegalArgumentException ("font format not recognized");
|
|
919 |
}
|
|
920 |
SecurityManager sm = System.getSecurityManager();
|
|
921 |
if (sm != null) {
|
|
922 |
FilePermission filePermission =
|
|
923 |
new FilePermission(fontFile.getPath(), "read");
|
|
924 |
sm.checkPermission(filePermission);
|
|
925 |
}
|
|
926 |
if (!fontFile.canRead()) {
|
|
927 |
throw new IOException("Can't read " + fontFile);
|
|
928 |
}
|
|
929 |
return new Font(fontFile, fontFormat, false);
|
|
930 |
}
|
|
931 |
|
|
932 |
/**
|
|
933 |
* Returns a copy of the transform associated with this
|
|
934 |
* <code>Font</code>. This transform is not necessarily the one
|
|
935 |
* used to construct the font. If the font has algorithmic
|
|
936 |
* superscripting or width adjustment, this will be incorporated
|
|
937 |
* into the returned <code>AffineTransform</code>.
|
|
938 |
* <p>
|
|
939 |
* Typically, fonts will not be transformed. Clients generally
|
|
940 |
* should call {@link #isTransformed} first, and only call this
|
|
941 |
* method if <code>isTransformed</code> returns true.
|
|
942 |
*
|
|
943 |
* @return an {@link AffineTransform} object representing the
|
|
944 |
* transform attribute of this <code>Font</code> object.
|
|
945 |
*/
|
|
946 |
public AffineTransform getTransform() {
|
|
947 |
/* The most common case is the identity transform. Most callers
|
|
948 |
* should call isTransformed() first, to decide if they need to
|
|
949 |
* get the transform, but some may not. Here we check to see
|
|
950 |
* if we have a nonidentity transform, and only do the work to
|
|
951 |
* fetch and/or compute it if so, otherwise we return a new
|
|
952 |
* identity transform.
|
|
953 |
*
|
|
954 |
* Note that the transform is _not_ necessarily the same as
|
|
955 |
* the transform passed in as an Attribute in a Map, as the
|
|
956 |
* transform returned will also reflect the effects of WIDTH and
|
|
957 |
* SUPERSCRIPT attributes. Clients who want the actual transform
|
|
958 |
* need to call getRequestedAttributes.
|
|
959 |
*/
|
|
960 |
if (nonIdentityTx) {
|
|
961 |
AttributeValues values = getAttributeValues();
|
|
962 |
|
|
963 |
AffineTransform at = values.isNonDefault(ETRANSFORM)
|
|
964 |
? new AffineTransform(values.getTransform())
|
|
965 |
: new AffineTransform();
|
|
966 |
|
|
967 |
if (values.getSuperscript() != 0) {
|
|
968 |
// can't get ascent and descent here, recursive call to this fn,
|
|
969 |
// so use pointsize
|
|
970 |
// let users combine super- and sub-scripting
|
|
971 |
|
|
972 |
int superscript = values.getSuperscript();
|
|
973 |
|
|
974 |
double trans = 0;
|
|
975 |
int n = 0;
|
|
976 |
boolean up = superscript > 0;
|
|
977 |
int sign = up ? -1 : 1;
|
|
978 |
int ss = up ? superscript : -superscript;
|
|
979 |
|
|
980 |
while ((ss & 7) > n) {
|
|
981 |
int newn = ss & 7;
|
|
982 |
trans += sign * (ssinfo[newn] - ssinfo[n]);
|
|
983 |
ss >>= 3;
|
|
984 |
sign = -sign;
|
|
985 |
n = newn;
|
|
986 |
}
|
|
987 |
trans *= pointSize;
|
|
988 |
double scale = Math.pow(2./3., n);
|
|
989 |
|
|
990 |
at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
|
|
991 |
at.scale(scale, scale);
|
|
992 |
|
|
993 |
// note on placement and italics
|
|
994 |
// We preconcatenate the transform because we don't want to translate along
|
|
995 |
// the italic angle, but purely perpendicular to the baseline. While this
|
|
996 |
// looks ok for superscripts, it can lead subscripts to stack on each other
|
|
997 |
// and bring the following text too close. The way we deal with potential
|
|
998 |
// collisions that can occur in the case of italics is by adjusting the
|
|
999 |
// horizontal spacing of the adjacent glyphvectors. Examine the italic
|
|
1000 |
// angle of both vectors, if one is non-zero, compute the minimum ascent
|
|
1001 |
// and descent, and then the x position at each for each vector along its
|
|
1002 |
// italic angle starting from its (offset) baseline. Compute the difference
|
|
1003 |
// between the x positions and use the maximum difference to adjust the
|
|
1004 |
// position of the right gv.
|
|
1005 |
}
|
|
1006 |
|
|
1007 |
if (values.isNonDefault(EWIDTH)) {
|
|
1008 |
at.scale(values.getWidth(), 1f);
|
|
1009 |
}
|
|
1010 |
|
|
1011 |
return at;
|
|
1012 |
}
|
|
1013 |
|
|
1014 |
return new AffineTransform();
|
|
1015 |
}
|
|
1016 |
|
|
1017 |
// x = r^0 + r^1 + r^2... r^n
|
|
1018 |
// rx = r^1 + r^2 + r^3... r^(n+1)
|
|
1019 |
// x - rx = r^0 - r^(n+1)
|
|
1020 |
// x (1 - r) = r^0 - r^(n+1)
|
|
1021 |
// x = (r^0 - r^(n+1)) / (1 - r)
|
|
1022 |
// x = (1 - r^(n+1)) / (1 - r)
|
|
1023 |
|
|
1024 |
// scale ratio is 2/3
|
|
1025 |
// trans = 1/2 of ascent * x
|
|
1026 |
// assume ascent is 3/4 of point size
|
|
1027 |
|
|
1028 |
private static final float[] ssinfo = {
|
|
1029 |
0.0f,
|
|
1030 |
0.375f,
|
|
1031 |
0.625f,
|
|
1032 |
0.7916667f,
|
|
1033 |
0.9027778f,
|
|
1034 |
0.9768519f,
|
|
1035 |
1.0262346f,
|
|
1036 |
1.0591564f,
|
|
1037 |
};
|
|
1038 |
|
|
1039 |
/**
|
|
1040 |
* Returns the family name of this <code>Font</code>.
|
|
1041 |
*
|
|
1042 |
* <p>The family name of a font is font specific. Two fonts such as
|
|
1043 |
* Helvetica Italic and Helvetica Bold have the same family name,
|
|
1044 |
* <i>Helvetica</i>, whereas their font face names are
|
|
1045 |
* <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
|
|
1046 |
* available family names may be obtained by using the
|
|
1047 |
* {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
|
|
1048 |
*
|
|
1049 |
* <p>Use <code>getName</code> to get the logical name of the font.
|
|
1050 |
* Use <code>getFontName</code> to get the font face name of the font.
|
|
1051 |
* @return a <code>String</code> that is the family name of this
|
|
1052 |
* <code>Font</code>.
|
|
1053 |
*
|
|
1054 |
* @see #getName
|
|
1055 |
* @see #getFontName
|
|
1056 |
* @since JDK1.1
|
|
1057 |
*/
|
|
1058 |
public String getFamily() {
|
|
1059 |
return getFamily_NoClientCode();
|
|
1060 |
}
|
|
1061 |
// NOTE: This method is called by privileged threads.
|
|
1062 |
// We implement this functionality in a package-private
|
|
1063 |
// method to insure that it cannot be overridden by client
|
|
1064 |
// subclasses.
|
|
1065 |
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
|
|
1066 |
final String getFamily_NoClientCode() {
|
|
1067 |
return getFamily(Locale.getDefault());
|
|
1068 |
}
|
|
1069 |
|
|
1070 |
/**
|
|
1071 |
* Returns the family name of this <code>Font</code>, localized for
|
|
1072 |
* the specified locale.
|
|
1073 |
*
|
|
1074 |
* <p>The family name of a font is font specific. Two fonts such as
|
|
1075 |
* Helvetica Italic and Helvetica Bold have the same family name,
|
|
1076 |
* <i>Helvetica</i>, whereas their font face names are
|
|
1077 |
* <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
|
|
1078 |
* available family names may be obtained by using the
|
|
1079 |
* {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
|
|
1080 |
*
|
|
1081 |
* <p>Use <code>getFontName</code> to get the font face name of the font.
|
|
1082 |
* @param l locale for which to get the family name
|
|
1083 |
* @return a <code>String</code> representing the family name of the
|
|
1084 |
* font, localized for the specified locale.
|
|
1085 |
* @see #getFontName
|
|
1086 |
* @see java.util.Locale
|
|
1087 |
* @since 1.2
|
|
1088 |
*/
|
|
1089 |
public String getFamily(Locale l) {
|
|
1090 |
if (l == null) {
|
|
1091 |
throw new NullPointerException("null locale doesn't mean default");
|
|
1092 |
}
|
|
1093 |
return getFont2D().getFamilyName(l);
|
|
1094 |
}
|
|
1095 |
|
|
1096 |
/**
|
|
1097 |
* Returns the postscript name of this <code>Font</code>.
|
|
1098 |
* Use <code>getFamily</code> to get the family name of the font.
|
|
1099 |
* Use <code>getFontName</code> to get the font face name of the font.
|
|
1100 |
* @return a <code>String</code> representing the postscript name of
|
|
1101 |
* this <code>Font</code>.
|
|
1102 |
* @since 1.2
|
|
1103 |
*/
|
|
1104 |
public String getPSName() {
|
|
1105 |
return getFont2D().getPostscriptName();
|
|
1106 |
}
|
|
1107 |
|
|
1108 |
/**
|
|
1109 |
* Returns the logical name of this <code>Font</code>.
|
|
1110 |
* Use <code>getFamily</code> to get the family name of the font.
|
|
1111 |
* Use <code>getFontName</code> to get the font face name of the font.
|
|
1112 |
* @return a <code>String</code> representing the logical name of
|
|
1113 |
* this <code>Font</code>.
|
|
1114 |
* @see #getFamily
|
|
1115 |
* @see #getFontName
|
|
1116 |
* @since JDK1.0
|
|
1117 |
*/
|
|
1118 |
public String getName() {
|
|
1119 |
return name;
|
|
1120 |
}
|
|
1121 |
|
|
1122 |
/**
|
|
1123 |
* Returns the font face name of this <code>Font</code>. For example,
|
|
1124 |
* Helvetica Bold could be returned as a font face name.
|
|
1125 |
* Use <code>getFamily</code> to get the family name of the font.
|
|
1126 |
* Use <code>getName</code> to get the logical name of the font.
|
|
1127 |
* @return a <code>String</code> representing the font face name of
|
|
1128 |
* this <code>Font</code>.
|
|
1129 |
* @see #getFamily
|
|
1130 |
* @see #getName
|
|
1131 |
* @since 1.2
|
|
1132 |
*/
|
|
1133 |
public String getFontName() {
|
|
1134 |
return getFontName(Locale.getDefault());
|
|
1135 |
}
|
|
1136 |
|
|
1137 |
/**
|
|
1138 |
* Returns the font face name of the <code>Font</code>, localized
|
|
1139 |
* for the specified locale. For example, Helvetica Fett could be
|
|
1140 |
* returned as the font face name.
|
|
1141 |
* Use <code>getFamily</code> to get the family name of the font.
|
|
1142 |
* @param l a locale for which to get the font face name
|
|
1143 |
* @return a <code>String</code> representing the font face name,
|
|
1144 |
* localized for the specified locale.
|
|
1145 |
* @see #getFamily
|
|
1146 |
* @see java.util.Locale
|
|
1147 |
*/
|
|
1148 |
public String getFontName(Locale l) {
|
|
1149 |
if (l == null) {
|
|
1150 |
throw new NullPointerException("null locale doesn't mean default");
|
|
1151 |
}
|
|
1152 |
return getFont2D().getFontName(l);
|
|
1153 |
}
|
|
1154 |
|
|
1155 |
/**
|
|
1156 |
* Returns the style of this <code>Font</code>. The style can be
|
|
1157 |
* PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
|
|
1158 |
* @return the style of this <code>Font</code>
|
|
1159 |
* @see #isPlain
|
|
1160 |
* @see #isBold
|
|
1161 |
* @see #isItalic
|
|
1162 |
* @since JDK1.0
|
|
1163 |
*/
|
|
1164 |
public int getStyle() {
|
|
1165 |
return style;
|
|
1166 |
}
|
|
1167 |
|
|
1168 |
/**
|
|
1169 |
* Returns the point size of this <code>Font</code>, rounded to
|
|
1170 |
* an integer.
|
|
1171 |
* Most users are familiar with the idea of using <i>point size</i> to
|
|
1172 |
* specify the size of glyphs in a font. This point size defines a
|
|
1173 |
* measurement between the baseline of one line to the baseline of the
|
|
1174 |
* following line in a single spaced text document. The point size is
|
|
1175 |
* based on <i>typographic points</i>, approximately 1/72 of an inch.
|
|
1176 |
* <p>
|
|
1177 |
* The Java(tm)2D API adopts the convention that one point is
|
|
1178 |
* equivalent to one unit in user coordinates. When using a
|
|
1179 |
* normalized transform for converting user space coordinates to
|
|
1180 |
* device space coordinates 72 user
|
|
1181 |
* space units equal 1 inch in device space. In this case one point
|
|
1182 |
* is 1/72 of an inch.
|
|
1183 |
* @return the point size of this <code>Font</code> in 1/72 of an
|
|
1184 |
* inch units.
|
|
1185 |
* @see #getSize2D
|
|
1186 |
* @see GraphicsConfiguration#getDefaultTransform
|
|
1187 |
* @see GraphicsConfiguration#getNormalizingTransform
|
|
1188 |
* @since JDK1.0
|
|
1189 |
*/
|
|
1190 |
public int getSize() {
|
|
1191 |
return size;
|
|
1192 |
}
|
|
1193 |
|
|
1194 |
/**
|
|
1195 |
* Returns the point size of this <code>Font</code> in
|
|
1196 |
* <code>float</code> value.
|
|
1197 |
* @return the point size of this <code>Font</code> as a
|
|
1198 |
* <code>float</code> value.
|
|
1199 |
* @see #getSize
|
|
1200 |
* @since 1.2
|
|
1201 |
*/
|
|
1202 |
public float getSize2D() {
|
|
1203 |
return pointSize;
|
|
1204 |
}
|
|
1205 |
|
|
1206 |
/**
|
|
1207 |
* Indicates whether or not this <code>Font</code> object's style is
|
|
1208 |
* PLAIN.
|
|
1209 |
* @return <code>true</code> if this <code>Font</code> has a
|
|
1210 |
* PLAIN sytle;
|
|
1211 |
* <code>false</code> otherwise.
|
|
1212 |
* @see java.awt.Font#getStyle
|
|
1213 |
* @since JDK1.0
|
|
1214 |
*/
|
|
1215 |
public boolean isPlain() {
|
|
1216 |
return style == 0;
|
|
1217 |
}
|
|
1218 |
|
|
1219 |
/**
|
|
1220 |
* Indicates whether or not this <code>Font</code> object's style is
|
|
1221 |
* BOLD.
|
|
1222 |
* @return <code>true</code> if this <code>Font</code> object's
|
|
1223 |
* style is BOLD;
|
|
1224 |
* <code>false</code> otherwise.
|
|
1225 |
* @see java.awt.Font#getStyle
|
|
1226 |
* @since JDK1.0
|
|
1227 |
*/
|
|
1228 |
public boolean isBold() {
|
|
1229 |
return (style & BOLD) != 0;
|
|
1230 |
}
|
|
1231 |
|
|
1232 |
/**
|
|
1233 |
* Indicates whether or not this <code>Font</code> object's style is
|
|
1234 |
* ITALIC.
|
|
1235 |
* @return <code>true</code> if this <code>Font</code> object's
|
|
1236 |
* style is ITALIC;
|
|
1237 |
* <code>false</code> otherwise.
|
|
1238 |
* @see java.awt.Font#getStyle
|
|
1239 |
* @since JDK1.0
|
|
1240 |
*/
|
|
1241 |
public boolean isItalic() {
|
|
1242 |
return (style & ITALIC) != 0;
|
|
1243 |
}
|
|
1244 |
|
|
1245 |
/**
|
|
1246 |
* Indicates whether or not this <code>Font</code> object has a
|
|
1247 |
* transform that affects its size in addition to the Size
|
|
1248 |
* attribute.
|
|
1249 |
* @return <code>true</code> if this <code>Font</code> object
|
|
1250 |
* has a non-identity AffineTransform attribute.
|
|
1251 |
* <code>false</code> otherwise.
|
|
1252 |
* @see java.awt.Font#getTransform
|
|
1253 |
* @since 1.4
|
|
1254 |
*/
|
|
1255 |
public boolean isTransformed() {
|
|
1256 |
return nonIdentityTx;
|
|
1257 |
}
|
|
1258 |
|
|
1259 |
/**
|
|
1260 |
* Return true if this Font contains attributes that require extra
|
|
1261 |
* layout processing.
|
|
1262 |
* @return true if the font has layout attributes
|
|
1263 |
* @since 1.6
|
|
1264 |
*/
|
|
1265 |
public boolean hasLayoutAttributes() {
|
|
1266 |
return hasLayoutAttributes;
|
|
1267 |
}
|
|
1268 |
|
|
1269 |
/**
|
|
1270 |
* Returns a <code>Font</code> object from the system properties list.
|
|
1271 |
* <code>nm</code> is treated as the name of a system property to be
|
|
1272 |
* obtained. The <code>String</code> value of this property is then
|
|
1273 |
* interpreted as a <code>Font</code> object according to the
|
|
1274 |
* specification of <code>Font.decode(String)</code>
|
|
1275 |
* If the specified property is not found, or the executing code does
|
|
1276 |
* not have permission to read the property, null is returned instead.
|
|
1277 |
*
|
|
1278 |
* @param nm the property name
|
|
1279 |
* @return a <code>Font</code> object that the property name
|
|
1280 |
* describes, or null if no such property exists.
|
|
1281 |
* @throws NullPointerException if nm is null.
|
|
1282 |
* @since 1.2
|
|
1283 |
* @see #decode(String)
|
|
1284 |
*/
|
|
1285 |
public static Font getFont(String nm) {
|
|
1286 |
return getFont(nm, null);
|
|
1287 |
}
|
|
1288 |
|
|
1289 |
/**
|
|
1290 |
* Returns the <code>Font</code> that the <code>str</code>
|
|
1291 |
* argument describes.
|
|
1292 |
* To ensure that this method returns the desired Font,
|
|
1293 |
* format the <code>str</code> parameter in
|
|
1294 |
* one of these ways
|
|
1295 |
* <p>
|
|
1296 |
* <ul>
|
|
1297 |
* <li><em>fontname-style-pointsize</em>
|
|
1298 |
* <li><em>fontname-pointsize</em>
|
|
1299 |
* <li><em>fontname-style</em>
|
|
1300 |
* <li><em>fontname</em>
|
|
1301 |
* <li><em>fontname style pointsize</em>
|
|
1302 |
* <li><em>fontname pointsize</em>
|
|
1303 |
* <li><em>fontname style</em>
|
|
1304 |
* <li><em>fontname</em>
|
|
1305 |
* </ul>
|
|
1306 |
* in which <i>style</i> is one of the four
|
|
1307 |
* case-insensitive strings:
|
|
1308 |
* <code>"PLAIN"</code>, <code>"BOLD"</code>, <code>"BOLDITALIC"</code>, or
|
|
1309 |
* <code>"ITALIC"</code>, and pointsize is a positive decimal integer
|
|
1310 |
* representation of the point size.
|
|
1311 |
* For example, if you want a font that is Arial, bold, with
|
|
1312 |
* a point size of 18, you would call this method with:
|
|
1313 |
* "Arial-BOLD-18".
|
|
1314 |
* This is equivalent to calling the Font constructor :
|
|
1315 |
* <code>new Font("Arial", Font.BOLD, 18);</code>
|
|
1316 |
* and the values are interpreted as specified by that constructor.
|
|
1317 |
* <p>
|
|
1318 |
* A valid trailing decimal field is always interpreted as the pointsize.
|
|
1319 |
* Therefore a fontname containing a trailing decimal value should not
|
|
1320 |
* be used in the fontname only form.
|
|
1321 |
* <p>
|
|
1322 |
* If a style name field is not one of the valid style strings, it is
|
|
1323 |
* interpreted as part of the font name, and the default style is used.
|
|
1324 |
* <p>
|
|
1325 |
* Only one of ' ' or '-' may be used to separate fields in the input.
|
|
1326 |
* The identified separator is the one closest to the end of the string
|
|
1327 |
* which separates a valid pointsize, or a valid style name from
|
|
1328 |
* the rest of the string.
|
|
1329 |
* Null (empty) pointsize and style fields are treated
|
|
1330 |
* as valid fields with the default value for that field.
|
|
1331 |
*<p>
|
|
1332 |
* Some font names may include the separator characters ' ' or '-'.
|
|
1333 |
* If <code>str</code> is not formed with 3 components, e.g. such that
|
|
1334 |
* <code>style</code> or <code>pointsize</code> fields are not present in
|
|
1335 |
* <code>str</code>, and <code>fontname</code> also contains a
|
|
1336 |
* character determined to be the separator character
|
|
1337 |
* then these characters where they appear as intended to be part of
|
|
1338 |
* <code>fontname</code> may instead be interpreted as separators
|
|
1339 |
* so the font name may not be properly recognised.
|
|
1340 |
*
|
|
1341 |
* <p>
|
|
1342 |
* The default size is 12 and the default style is PLAIN.
|
|
1343 |
* If <code>str</code> does not specify a valid size, the returned
|
|
1344 |
* <code>Font</code> has a size of 12. If <code>str</code> does not
|
|
1345 |
* specify a valid style, the returned Font has a style of PLAIN.
|
|
1346 |
* If you do not specify a valid font name in
|
|
1347 |
* the <code>str</code> argument, this method will return
|
|
1348 |
* a font with the family name "Dialog".
|
|
1349 |
* To determine what font family names are available on
|
|
1350 |
* your system, use the
|
|
1351 |
* {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
|
|
1352 |
* If <code>str</code> is <code>null</code>, a new <code>Font</code>
|
|
1353 |
* is returned with the family name "Dialog", a size of 12 and a
|
|
1354 |
* PLAIN style.
|
|
1355 |
* @param str the name of the font, or <code>null</code>
|
|
1356 |
* @return the <code>Font</code> object that <code>str</code>
|
|
1357 |
* describes, or a new default <code>Font</code> if
|
|
1358 |
* <code>str</code> is <code>null</code>.
|
|
1359 |
* @see #getFamily
|
|
1360 |
* @since JDK1.1
|
|
1361 |
*/
|
|
1362 |
public static Font decode(String str) {
|
|
1363 |
String fontName = str;
|
|
1364 |
String styleName = "";
|
|
1365 |
int fontSize = 12;
|
|
1366 |
int fontStyle = Font.PLAIN;
|
|
1367 |
|
|
1368 |
if (str == null) {
|
|
1369 |
return new Font(DIALOG, fontStyle, fontSize);
|
|
1370 |
}
|
|
1371 |
|
|
1372 |
int lastHyphen = str.lastIndexOf('-');
|
|
1373 |
int lastSpace = str.lastIndexOf(' ');
|
|
1374 |
char sepChar = (lastHyphen > lastSpace) ? '-' : ' ';
|
|
1375 |
int sizeIndex = str.lastIndexOf(sepChar);
|
|
1376 |
int styleIndex = str.lastIndexOf(sepChar, sizeIndex-1);
|
|
1377 |
int strlen = str.length();
|
|
1378 |
|
|
1379 |
if (sizeIndex > 0 && sizeIndex+1 < strlen) {
|
|
1380 |
try {
|
|
1381 |
fontSize =
|
|
1382 |
Integer.valueOf(str.substring(sizeIndex+1)).intValue();
|
|
1383 |
if (fontSize <= 0) {
|
|
1384 |
fontSize = 12;
|
|
1385 |
}
|
|
1386 |
} catch (NumberFormatException e) {
|
|
1387 |
/* It wasn't a valid size, if we didn't also find the
|
|
1388 |
* start of the style string perhaps this is the style */
|
|
1389 |
styleIndex = sizeIndex;
|
|
1390 |
sizeIndex = strlen;
|
|
1391 |
if (str.charAt(sizeIndex-1) == sepChar) {
|
|
1392 |
sizeIndex--;
|
|
1393 |
}
|
|
1394 |
}
|
|
1395 |
}
|
|
1396 |
|
|
1397 |
if (styleIndex >= 0 && styleIndex+1 < strlen) {
|
|
1398 |
styleName = str.substring(styleIndex+1, sizeIndex);
|
|
1399 |
styleName = styleName.toLowerCase(Locale.ENGLISH);
|
|
1400 |
if (styleName.equals("bolditalic")) {
|
|
1401 |
fontStyle = Font.BOLD | Font.ITALIC;
|
|
1402 |
} else if (styleName.equals("italic")) {
|
|
1403 |
fontStyle = Font.ITALIC;
|
|
1404 |
} else if (styleName.equals("bold")) {
|
|
1405 |
fontStyle = Font.BOLD;
|
|
1406 |
} else if (styleName.equals("plain")) {
|
|
1407 |
fontStyle = Font.PLAIN;
|
|
1408 |
} else {
|
|
1409 |
/* this string isn't any of the expected styles, so
|
|
1410 |
* assume its part of the font name
|
|
1411 |
*/
|
|
1412 |
styleIndex = sizeIndex;
|
|
1413 |
if (str.charAt(styleIndex-1) == sepChar) {
|
|
1414 |
styleIndex--;
|
|
1415 |
}
|
|
1416 |
}
|
|
1417 |
fontName = str.substring(0, styleIndex);
|
|
1418 |
|
|
1419 |
} else {
|
|
1420 |
int fontEnd = strlen;
|
|
1421 |
if (styleIndex > 0) {
|
|
1422 |
fontEnd = styleIndex;
|
|
1423 |
} else if (sizeIndex > 0) {
|
|
1424 |
fontEnd = sizeIndex;
|
|
1425 |
}
|
|
1426 |
if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) {
|
|
1427 |
fontEnd--;
|
|
1428 |
}
|
|
1429 |
fontName = str.substring(0, fontEnd);
|
|
1430 |
}
|
|
1431 |
|
|
1432 |
return new Font(fontName, fontStyle, fontSize);
|
|
1433 |
}
|
|
1434 |
|
|
1435 |
/**
|
|
1436 |
* Gets the specified <code>Font</code> from the system properties
|
|
1437 |
* list. As in the <code>getProperty</code> method of
|
|
1438 |
* <code>System</code>, the first
|
|
1439 |
* argument is treated as the name of a system property to be
|
|
1440 |
* obtained. The <code>String</code> value of this property is then
|
|
1441 |
* interpreted as a <code>Font</code> object.
|
|
1442 |
* <p>
|
|
1443 |
* The property value should be one of the forms accepted by
|
|
1444 |
* <code>Font.decode(String)</code>
|
|
1445 |
* If the specified property is not found, or the executing code does not
|
|
1446 |
* have permission to read the property, the <code>font</code>
|
|
1447 |
* argument is returned instead.
|
|
1448 |
* @param nm the case-insensitive property name
|
|
1449 |
* @param font a default <code>Font</code> to return if property
|
|
1450 |
* <code>nm</code> is not defined
|
|
1451 |
* @return the <code>Font</code> value of the property.
|
|
1452 |
* @throws NullPointerException if nm is null.
|
|
1453 |
* @see #decode(String)
|
|
1454 |
*/
|
|
1455 |
public static Font getFont(String nm, Font font) {
|
|
1456 |
String str = null;
|
|
1457 |
try {
|
|
1458 |
str =System.getProperty(nm);
|
|
1459 |
} catch(SecurityException e) {
|
|
1460 |
}
|
|
1461 |
if (str == null) {
|
|
1462 |
return font;
|
|
1463 |
}
|
|
1464 |
return decode ( str );
|
|
1465 |
}
|
|
1466 |
|
|
1467 |
transient int hash;
|
|
1468 |
/**
|
|
1469 |
* Returns a hashcode for this <code>Font</code>.
|
|
1470 |
* @return a hashcode value for this <code>Font</code>.
|
|
1471 |
* @since JDK1.0
|
|
1472 |
*/
|
|
1473 |
public int hashCode() {
|
|
1474 |
if (hash == 0) {
|
|
1475 |
hash = name.hashCode() ^ style ^ size;
|
|
1476 |
/* It is possible many fonts differ only in transform.
|
|
1477 |
* So include the transform in the hash calculation.
|
|
1478 |
* nonIdentityTx is set whenever there is a transform in
|
|
1479 |
* 'values'. The tests for null are required because it can
|
|
1480 |
* also be set for other reasons.
|
|
1481 |
*/
|
|
1482 |
if (nonIdentityTx &&
|
|
1483 |
values != null && values.getTransform() != null) {
|
|
1484 |
hash ^= values.getTransform().hashCode();
|
|
1485 |
}
|
|
1486 |
}
|
|
1487 |
return hash;
|
|
1488 |
}
|
|
1489 |
|
|
1490 |
/**
|
|
1491 |
* Compares this <code>Font</code> object to the specified
|
|
1492 |
* <code>Object</code>.
|
|
1493 |
* @param obj the <code>Object</code> to compare
|
|
1494 |
* @return <code>true</code> if the objects are the same
|
|
1495 |
* or if the argument is a <code>Font</code> object
|
|
1496 |
* describing the same font as this object;
|
|
1497 |
* <code>false</code> otherwise.
|
|
1498 |
* @since JDK1.0
|
|
1499 |
*/
|
|
1500 |
public boolean equals(Object obj) {
|
|
1501 |
if (obj == this) {
|
|
1502 |
return true;
|
|
1503 |
}
|
|
1504 |
|
|
1505 |
if (obj != null) {
|
|
1506 |
try {
|
|
1507 |
Font font = (Font)obj;
|
|
1508 |
if (size == font.size &&
|
|
1509 |
style == font.style &&
|
|
1510 |
nonIdentityTx == font.nonIdentityTx &&
|
|
1511 |
hasLayoutAttributes == font.hasLayoutAttributes &&
|
|
1512 |
pointSize == font.pointSize &&
|
|
1513 |
name.equals(font.name)) {
|
|
1514 |
|
|
1515 |
/* 'values' is usually initialized lazily, except when
|
|
1516 |
* the font is constructed from a Map, or derived using
|
|
1517 |
* a Map or other values. So if only one font has
|
|
1518 |
* the field initialized we need to initialize it in
|
|
1519 |
* the other instance and compare.
|
|
1520 |
*/
|
|
1521 |
if (values == null) {
|
|
1522 |
if (font.values == null) {
|
|
1523 |
return true;
|
|
1524 |
} else {
|
|
1525 |
return getAttributeValues().equals(font.values);
|
|
1526 |
}
|
|
1527 |
} else {
|
|
1528 |
return values.equals(font.getAttributeValues());
|
|
1529 |
}
|
|
1530 |
}
|
|
1531 |
}
|
|
1532 |
catch (ClassCastException e) {
|
|
1533 |
}
|
|
1534 |
}
|
|
1535 |
return false;
|
|
1536 |
}
|
|
1537 |
|
|
1538 |
/**
|
|
1539 |
* Converts this <code>Font</code> object to a <code>String</code>
|
|
1540 |
* representation.
|
|
1541 |
* @return a <code>String</code> representation of this
|
|
1542 |
* <code>Font</code> object.
|
|
1543 |
* @since JDK1.0
|
|
1544 |
*/
|
|
1545 |
// NOTE: This method may be called by privileged threads.
|
|
1546 |
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
|
|
1547 |
public String toString() {
|
|
1548 |
String strStyle;
|
|
1549 |
|
|
1550 |
if (isBold()) {
|
|
1551 |
strStyle = isItalic() ? "bolditalic" : "bold";
|
|
1552 |
} else {
|
|
1553 |
strStyle = isItalic() ? "italic" : "plain";
|
|
1554 |
}
|
|
1555 |
|
|
1556 |
return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" +
|
|
1557 |
strStyle + ",size=" + size + "]";
|
|
1558 |
} // toString()
|
|
1559 |
|
|
1560 |
|
|
1561 |
/** Serialization support. A <code>readObject</code>
|
|
1562 |
* method is neccessary because the constructor creates
|
|
1563 |
* the font's peer, and we can't serialize the peer.
|
|
1564 |
* Similarly the computed font "family" may be different
|
|
1565 |
* at <code>readObject</code> time than at
|
|
1566 |
* <code>writeObject</code> time. An integer version is
|
|
1567 |
* written so that future versions of this class will be
|
|
1568 |
* able to recognize serialized output from this one.
|
|
1569 |
*/
|
|
1570 |
/**
|
|
1571 |
* The <code>Font</code> Serializable Data Form.
|
|
1572 |
*
|
|
1573 |
* @serial
|
|
1574 |
*/
|
|
1575 |
private int fontSerializedDataVersion = 1;
|
|
1576 |
|
|
1577 |
/**
|
|
1578 |
* Writes default serializable fields to a stream.
|
|
1579 |
*
|
|
1580 |
* @param s the <code>ObjectOutputStream</code> to write
|
|
1581 |
* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
|
|
1582 |
* @see #readObject(java.io.ObjectInputStream)
|
|
1583 |
*/
|
|
1584 |
private void writeObject(java.io.ObjectOutputStream s)
|
|
1585 |
throws java.lang.ClassNotFoundException,
|
|
1586 |
java.io.IOException
|
|
1587 |
{
|
|
1588 |
if (values != null) {
|
|
1589 |
synchronized(values) {
|
|
1590 |
// transient
|
|
1591 |
fRequestedAttributes = values.toSerializableHashtable();
|
|
1592 |
s.defaultWriteObject();
|
|
1593 |
fRequestedAttributes = null;
|
|
1594 |
}
|
|
1595 |
} else {
|
|
1596 |
s.defaultWriteObject();
|
|
1597 |
}
|
|
1598 |
}
|
|
1599 |
|
|
1600 |
/**
|
|
1601 |
* Reads the <code>ObjectInputStream</code>.
|
|
1602 |
* Unrecognized keys or values will be ignored.
|
|
1603 |
*
|
|
1604 |
* @param s the <code>ObjectInputStream</code> to read
|
|
1605 |
* @serial
|
|
1606 |
* @see #writeObject(java.io.ObjectOutputStream)
|
|
1607 |
*/
|
|
1608 |
private void readObject(java.io.ObjectInputStream s)
|
|
1609 |
throws java.lang.ClassNotFoundException,
|
|
1610 |
java.io.IOException
|
|
1611 |
{
|
|
1612 |
s.defaultReadObject();
|
|
1613 |
if (pointSize == 0) {
|
|
1614 |
pointSize = (float)size;
|
|
1615 |
}
|
|
1616 |
|
|
1617 |
// Handle fRequestedAttributes.
|
|
1618 |
// in 1.5, we always streamed out the font values plus
|
|
1619 |
// TRANSFORM, SUPERSCRIPT, and WIDTH, regardless of whether the
|
|
1620 |
// values were default or not. In 1.6 we only stream out
|
|
1621 |
// defined values. So, 1.6 streams in from a 1.5 stream,
|
|
1622 |
// it check each of these values and 'undefines' it if the
|
|
1623 |
// value is the default.
|
|
1624 |
|
|
1625 |
if (fRequestedAttributes != null) {
|
|
1626 |
values = getAttributeValues(); // init
|
|
1627 |
AttributeValues extras =
|
|
1628 |
AttributeValues.fromSerializableHashtable(fRequestedAttributes);
|
|
1629 |
if (!AttributeValues.is16Hashtable(fRequestedAttributes)) {
|
|
1630 |
extras.unsetDefault(); // if legacy stream, undefine these
|
|
1631 |
}
|
|
1632 |
values = getAttributeValues().merge(extras);
|
|
1633 |
this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
|
|
1634 |
this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
|
|
1635 |
|
|
1636 |
fRequestedAttributes = null; // don't need it any more
|
|
1637 |
}
|
|
1638 |
}
|
|
1639 |
|
|
1640 |
/**
|
|
1641 |
* Returns the number of glyphs in this <code>Font</code>. Glyph codes
|
|
1642 |
* for this <code>Font</code> range from 0 to
|
|
1643 |
* <code>getNumGlyphs()</code> - 1.
|
|
1644 |
* @return the number of glyphs in this <code>Font</code>.
|
|
1645 |
* @since 1.2
|
|
1646 |
*/
|
|
1647 |
public int getNumGlyphs() {
|
|
1648 |
return getFont2D().getNumGlyphs();
|
|
1649 |
}
|
|
1650 |
|
|
1651 |
/**
|
|
1652 |
* Returns the glyphCode which is used when this <code>Font</code>
|
|
1653 |
* does not have a glyph for a specified unicode code point.
|
|
1654 |
* @return the glyphCode of this <code>Font</code>.
|
|
1655 |
* @since 1.2
|
|
1656 |
*/
|
|
1657 |
public int getMissingGlyphCode() {
|
|
1658 |
return getFont2D().getMissingGlyphCode();
|
|
1659 |
}
|
|
1660 |
|
|
1661 |
/**
|
|
1662 |
* Returns the baseline appropriate for displaying this character.
|
|
1663 |
* <p>
|
|
1664 |
* Large fonts can support different writing systems, and each system can
|
|
1665 |
* use a different baseline.
|
|
1666 |
* The character argument determines the writing system to use. Clients
|
|
1667 |
* should not assume all characters use the same baseline.
|
|
1668 |
*
|
|
1669 |
* @param c a character used to identify the writing system
|
|
1670 |
* @return the baseline appropriate for the specified character.
|
|
1671 |
* @see LineMetrics#getBaselineOffsets
|
|
1672 |
* @see #ROMAN_BASELINE
|
|
1673 |
* @see #CENTER_BASELINE
|
|
1674 |
* @see #HANGING_BASELINE
|
|
1675 |
* @since 1.2
|
|
1676 |
*/
|
|
1677 |
public byte getBaselineFor(char c) {
|
|
1678 |
return getFont2D().getBaselineFor(c);
|
|
1679 |
}
|
|
1680 |
|
|
1681 |
/**
|
|
1682 |
* Returns a map of font attributes available in this
|
|
1683 |
* <code>Font</code>. Attributes include things like ligatures and
|
|
1684 |
* glyph substitution.
|
|
1685 |
* @return the attributes map of this <code>Font</code>.
|
|
1686 |
*/
|
|
1687 |
public Map<TextAttribute,?> getAttributes(){
|
|
1688 |
return new AttributeMap(getAttributeValues());
|
|
1689 |
}
|
|
1690 |
|
|
1691 |
/**
|
|
1692 |
* Returns the keys of all the attributes supported by this
|
|
1693 |
* <code>Font</code>. These attributes can be used to derive other
|
|
1694 |
* fonts.
|
|
1695 |
* @return an array containing the keys of all the attributes
|
|
1696 |
* supported by this <code>Font</code>.
|
|
1697 |
* @since 1.2
|
|
1698 |
*/
|
|
1699 |
public Attribute[] getAvailableAttributes() {
|
|
1700 |
// FONT is not supported by Font
|
|
1701 |
|
|
1702 |
Attribute attributes[] = {
|
|
1703 |
TextAttribute.FAMILY,
|
|
1704 |
TextAttribute.WEIGHT,
|
|
1705 |
TextAttribute.WIDTH,
|
|
1706 |
TextAttribute.POSTURE,
|
|
1707 |
TextAttribute.SIZE,
|
|
1708 |
TextAttribute.TRANSFORM,
|
|
1709 |
TextAttribute.SUPERSCRIPT,
|
|
1710 |
TextAttribute.CHAR_REPLACEMENT,
|
|
1711 |
TextAttribute.FOREGROUND,
|
|
1712 |
TextAttribute.BACKGROUND,
|
|
1713 |
TextAttribute.UNDERLINE,
|
|
1714 |
TextAttribute.STRIKETHROUGH,
|
|
1715 |
TextAttribute.RUN_DIRECTION,
|
|
1716 |
TextAttribute.BIDI_EMBEDDING,
|
|
1717 |
TextAttribute.JUSTIFICATION,
|
|
1718 |
TextAttribute.INPUT_METHOD_HIGHLIGHT,
|
|
1719 |
TextAttribute.INPUT_METHOD_UNDERLINE,
|
|
1720 |
TextAttribute.SWAP_COLORS,
|
|
1721 |
TextAttribute.NUMERIC_SHAPING,
|
|
1722 |
TextAttribute.KERNING,
|
|
1723 |
TextAttribute.LIGATURES,
|
|
1724 |
TextAttribute.TRACKING,
|
|
1725 |
};
|
|
1726 |
|
|
1727 |
return attributes;
|
|
1728 |
}
|
|
1729 |
|
|
1730 |
/**
|
|
1731 |
* Creates a new <code>Font</code> object by replicating this
|
|
1732 |
* <code>Font</code> object and applying a new style and size.
|
|
1733 |
* @param style the style for the new <code>Font</code>
|
|
1734 |
* @param size the size for the new <code>Font</code>
|
|
1735 |
* @return a new <code>Font</code> object.
|
|
1736 |
* @since 1.2
|
|
1737 |
*/
|
|
1738 |
public Font deriveFont(int style, float size){
|
|
1739 |
if (values == null) {
|
|
1740 |
return new Font(name, style, size, createdFont, font2DHandle);
|
|
1741 |
}
|
|
1742 |
AttributeValues newValues = getAttributeValues().clone();
|
|
1743 |
int oldStyle = (this.style != style) ? this.style : -1;
|
|
1744 |
applyStyle(style, newValues);
|
|
1745 |
newValues.setSize(size);
|
|
1746 |
return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
|
|
1747 |
}
|
|
1748 |
|
|
1749 |
/**
|
|
1750 |
* Creates a new <code>Font</code> object by replicating this
|
|
1751 |
* <code>Font</code> object and applying a new style and transform.
|
|
1752 |
* @param style the style for the new <code>Font</code>
|
|
1753 |
* @param trans the <code>AffineTransform</code> associated with the
|
|
1754 |
* new <code>Font</code>
|
|
1755 |
* @return a new <code>Font</code> object.
|
|
1756 |
* @throws IllegalArgumentException if <code>trans</code> is
|
|
1757 |
* <code>null</code>
|
|
1758 |
* @since 1.2
|
|
1759 |
*/
|
|
1760 |
public Font deriveFont(int style, AffineTransform trans){
|
|
1761 |
AttributeValues newValues = getAttributeValues().clone();
|
|
1762 |
int oldStyle = (this.style != style) ? this.style : -1;
|
|
1763 |
applyStyle(style, newValues);
|
|
1764 |
applyTransform(trans, newValues);
|
|
1765 |
return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
|
|
1766 |
}
|
|
1767 |
|
|
1768 |
/**
|
|
1769 |
* Creates a new <code>Font</code> object by replicating the current
|
|
1770 |
* <code>Font</code> object and applying a new size to it.
|
|
1771 |
* @param size the size for the new <code>Font</code>.
|
|
1772 |
* @return a new <code>Font</code> object.
|
|
1773 |
* @since 1.2
|
|
1774 |
*/
|
|
1775 |
public Font deriveFont(float size){
|
|
1776 |
if (values == null) {
|
|
1777 |
return new Font(name, style, size, createdFont, font2DHandle);
|
|
1778 |
}
|
|
1779 |
AttributeValues newValues = getAttributeValues().clone();
|
|
1780 |
newValues.setSize(size);
|
|
1781 |
return new Font(newValues, null, -1, createdFont, font2DHandle);
|
|
1782 |
}
|
|
1783 |
|
|
1784 |
/**
|
|
1785 |
* Creates a new <code>Font</code> object by replicating the current
|
|
1786 |
* <code>Font</code> object and applying a new transform to it.
|
|
1787 |
* @param trans the <code>AffineTransform</code> associated with the
|
|
1788 |
* new <code>Font</code>
|
|
1789 |
* @return a new <code>Font</code> object.
|
|
1790 |
* @throws IllegalArgumentException if <code>trans</code> is
|
|
1791 |
* <code>null</code>
|
|
1792 |
* @since 1.2
|
|
1793 |
*/
|
|
1794 |
public Font deriveFont(AffineTransform trans){
|
|
1795 |
AttributeValues newValues = getAttributeValues().clone();
|
|
1796 |
applyTransform(trans, newValues);
|
|
1797 |
return new Font(newValues, null, -1, createdFont, font2DHandle);
|
|
1798 |
}
|
|
1799 |
|
|
1800 |
/**
|
|
1801 |
* Creates a new <code>Font</code> object by replicating the current
|
|
1802 |
* <code>Font</code> object and applying a new style to it.
|
|
1803 |
* @param style the style for the new <code>Font</code>
|
|
1804 |
* @return a new <code>Font</code> object.
|
|
1805 |
* @since 1.2
|
|
1806 |
*/
|
|
1807 |
public Font deriveFont(int style){
|
|
1808 |
if (values == null) {
|
|
1809 |
return new Font(name, style, size, createdFont, font2DHandle);
|
|
1810 |
}
|
|
1811 |
AttributeValues newValues = getAttributeValues().clone();
|
|
1812 |
int oldStyle = (this.style != style) ? this.style : -1;
|
|
1813 |
applyStyle(style, newValues);
|
|
1814 |
return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
|
|
1815 |
}
|
|
1816 |
|
|
1817 |
/**
|
|
1818 |
* Creates a new <code>Font</code> object by replicating the current
|
|
1819 |
* <code>Font</code> object and applying a new set of font attributes
|
|
1820 |
* to it.
|
|
1821 |
*
|
|
1822 |
* @param attributes a map of attributes enabled for the new
|
|
1823 |
* <code>Font</code>
|
|
1824 |
* @return a new <code>Font</code> object.
|
|
1825 |
* @since 1.2
|
|
1826 |
*/
|
|
1827 |
public Font deriveFont(Map<? extends Attribute, ?> attributes) {
|
|
1828 |
if (attributes == null) {
|
|
1829 |
return this;
|
|
1830 |
}
|
|
1831 |
AttributeValues newValues = getAttributeValues().clone();
|
|
1832 |
newValues.merge(attributes, RECOGNIZED_MASK);
|
|
1833 |
|
|
1834 |
return new Font(newValues, name, style, createdFont, font2DHandle);
|
|
1835 |
}
|
|
1836 |
|
|
1837 |
/**
|
|
1838 |
* Checks if this <code>Font</code> has a glyph for the specified
|
|
1839 |
* character.
|
|
1840 |
*
|
|
1841 |
* <p> <b>Note:</b> This method cannot handle <a
|
|
1842 |
* href="../../java/lang/Character.html#supplementary"> supplementary
|
|
1843 |
* characters</a>. To support all Unicode characters, including
|
|
1844 |
* supplementary characters, use the {@link #canDisplay(int)}
|
|
1845 |
* method or <code>canDisplayUpTo</code> methods.
|
|
1846 |
*
|
|
1847 |
* @param c the character for which a glyph is needed
|
|
1848 |
* @return <code>true</code> if this <code>Font</code> has a glyph for this
|
|
1849 |
* character; <code>false</code> otherwise.
|
|
1850 |
* @since 1.2
|
|
1851 |
*/
|
|
1852 |
public boolean canDisplay(char c){
|
|
1853 |
return getFont2D().canDisplay(c);
|
|
1854 |
}
|
|
1855 |
|
|
1856 |
/**
|
|
1857 |
* Checks if this <code>Font</code> has a glyph for the specified
|
|
1858 |
* character.
|
|
1859 |
*
|
|
1860 |
* @param codePoint the character (Unicode code point) for which a glyph
|
|
1861 |
* is needed.
|
|
1862 |
* @return <code>true</code> if this <code>Font</code> has a glyph for the
|
|
1863 |
* character; <code>false</code> otherwise.
|
|
1864 |
* @throws IllegalArgumentException if the code point is not a valid Unicode
|
|
1865 |
* code point.
|
|
1866 |
* @see Character#isValidCodePoint(int)
|
|
1867 |
* @since 1.5
|
|
1868 |
*/
|
|
1869 |
public boolean canDisplay(int codePoint) {
|
|
1870 |
if (!Character.isValidCodePoint(codePoint)) {
|
|
1871 |
throw new IllegalArgumentException("invalid code point: " +
|
|
1872 |
Integer.toHexString(codePoint));
|
|
1873 |
}
|
|
1874 |
return getFont2D().canDisplay(codePoint);
|
|
1875 |
}
|
|
1876 |
|
|
1877 |
/**
|
|
1878 |
* Indicates whether or not this <code>Font</code> can display a
|
|
1879 |
* specified <code>String</code>. For strings with Unicode encoding,
|
|
1880 |
* it is important to know if a particular font can display the
|
|
1881 |
* string. This method returns an offset into the <code>String</code>
|
|
1882 |
* <code>str</code> which is the first character this
|
|
1883 |
* <code>Font</code> cannot display without using the missing glyph
|
|
1884 |
* code. If the <code>Font</code> can display all characters, -1 is
|
|
1885 |
* returned.
|
|
1886 |
* @param str a <code>String</code> object
|
|
1887 |
* @return an offset into <code>str</code> that points
|
|
1888 |
* to the first character in <code>str</code> that this
|
|
1889 |
* <code>Font</code> cannot display; or <code>-1</code> if
|
|
1890 |
* this <code>Font</code> can display all characters in
|
|
1891 |
* <code>str</code>.
|
|
1892 |
* @since 1.2
|
|
1893 |
*/
|
|
1894 |
public int canDisplayUpTo(String str) {
|
|
1895 |
return canDisplayUpTo(new StringCharacterIterator(str), 0,
|
|
1896 |
str.length());
|
|
1897 |
}
|
|
1898 |
|
|
1899 |
/**
|
|
1900 |
* Indicates whether or not this <code>Font</code> can display
|
|
1901 |
* the characters in the specified <code>text</code>
|
|
1902 |
* starting at <code>start</code> and ending at
|
|
1903 |
* <code>limit</code>. This method is a convenience overload.
|
|
1904 |
* @param text the specified array of <code>char</code> values
|
|
1905 |
* @param start the specified starting offset (in
|
|
1906 |
* <code>char</code>s) into the specified array of
|
|
1907 |
* <code>char</code> values
|
|
1908 |
* @param limit the specified ending offset (in
|
|
1909 |
* <code>char</code>s) into the specified array of
|
|
1910 |
* <code>char</code> values
|
|
1911 |
* @return an offset into <code>text</code> that points
|
|
1912 |
* to the first character in <code>text</code> that this
|
|
1913 |
* <code>Font</code> cannot display; or <code>-1</code> if
|
|
1914 |
* this <code>Font</code> can display all characters in
|
|
1915 |
* <code>text</code>.
|
|
1916 |
* @since 1.2
|
|
1917 |
*/
|
|
1918 |
public int canDisplayUpTo(char[] text, int start, int limit) {
|
|
1919 |
while (start < limit && canDisplay(text[start])) {
|
|
1920 |
++start;
|
|
1921 |
}
|
|
1922 |
|
|
1923 |
return start == limit ? -1 : start;
|
|
1924 |
}
|
|
1925 |
|
|
1926 |
/**
|
|
1927 |
* Indicates whether or not this <code>Font</code> can display the
|
|
1928 |
* text specified by the <code>iter</code> starting at
|
|
1929 |
* <code>start</code> and ending at <code>limit</code>.
|
|
1930 |
*
|
|
1931 |
* @param iter a {@link CharacterIterator} object
|
|
1932 |
* @param start the specified starting offset into the specified
|
|
1933 |
* <code>CharacterIterator</code>.
|
|
1934 |
* @param limit the specified ending offset into the specified
|
|
1935 |
* <code>CharacterIterator</code>.
|
|
1936 |
* @return an offset into <code>iter</code> that points
|
|
1937 |
* to the first character in <code>iter</code> that this
|
|
1938 |
* <code>Font</code> cannot display; or <code>-1</code> if
|
|
1939 |
* this <code>Font</code> can display all characters in
|
|
1940 |
* <code>iter</code>.
|
|
1941 |
* @since 1.2
|
|
1942 |
*/
|
|
1943 |
public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
|
|
1944 |
for (char c = iter.setIndex(start);
|
|
1945 |
iter.getIndex() < limit && canDisplay(c);
|
|
1946 |
c = iter.next()) {
|
|
1947 |
}
|
|
1948 |
|
|
1949 |
int result = iter.getIndex();
|
|
1950 |
return result == limit ? -1 : result;
|
|
1951 |
}
|
|
1952 |
|
|
1953 |
/**
|
|
1954 |
* Returns the italic angle of this <code>Font</code>. The italic angle
|
|
1955 |
* is the inverse slope of the caret which best matches the posture of this
|
|
1956 |
* <code>Font</code>.
|
|
1957 |
* @see TextAttribute#POSTURE
|
|
1958 |
* @return the angle of the ITALIC style of this <code>Font</code>.
|
|
1959 |
*/
|
|
1960 |
public float getItalicAngle() {
|
|
1961 |
return getItalicAngle(null);
|
|
1962 |
}
|
|
1963 |
|
|
1964 |
/* The FRC hints don't affect the value of the italic angle but
|
|
1965 |
* we need to pass them in to look up a strike.
|
|
1966 |
* If we can pass in ones already being used it can prevent an extra
|
|
1967 |
* strike from being allocated. Note that since italic angle is
|
|
1968 |
* a property of the font, the font transform is needed not the
|
|
1969 |
* device transform. Finally, this is private but the only caller of this
|
|
1970 |
* in the JDK - and the only likely caller - is in this same class.
|
|
1971 |
*/
|
|
1972 |
private float getItalicAngle(FontRenderContext frc) {
|
|
1973 |
AffineTransform at = (isTransformed()) ? getTransform() : identityTx;
|
|
1974 |
Object aa, fm;
|
|
1975 |
if (frc == null) {
|
|
1976 |
aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
|
|
1977 |
fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
|
|
1978 |
} else {
|
|
1979 |
aa = frc.getAntiAliasingHint();
|
|
1980 |
fm = frc.getFractionalMetricsHint();
|
|
1981 |
}
|
|
1982 |
return getFont2D().getItalicAngle(this, at, aa, fm);
|
|
1983 |
}
|
|
1984 |
|
|
1985 |
/**
|
|
1986 |
* Checks whether or not this <code>Font</code> has uniform
|
|
1987 |
* line metrics. A logical <code>Font</code> might be a
|
|
1988 |
* composite font, which means that it is composed of different
|
|
1989 |
* physical fonts to cover different code ranges. Each of these
|
|
1990 |
* fonts might have different <code>LineMetrics</code>. If the
|
|
1991 |
* logical <code>Font</code> is a single
|
|
1992 |
* font then the metrics would be uniform.
|
|
1993 |
* @return <code>true</code> if this <code>Font</code> has
|
|
1994 |
* uniform line metrics; <code>false</code> otherwise.
|
|
1995 |
*/
|
|
1996 |
public boolean hasUniformLineMetrics() {
|
|
1997 |
return false; // REMIND always safe, but prevents caller optimize
|
|
1998 |
}
|
|
1999 |
|
|
2000 |
private transient SoftReference flmref;
|
|
2001 |
private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
|
|
2002 |
FontLineMetrics flm = null;
|
|
2003 |
if (flmref == null
|
|
2004 |
|| (flm = (FontLineMetrics)flmref.get()) == null
|
|
2005 |
|| !flm.frc.equals(frc)) {
|
|
2006 |
|
|
2007 |
/* The device transform in the frc is not used in obtaining line
|
|
2008 |
* metrics, although it probably should be: REMIND find why not?
|
|
2009 |
* The font transform is used but its applied in getFontMetrics, so
|
|
2010 |
* just pass identity here
|
|
2011 |
*/
|
|
2012 |
float [] metrics = new float[8];
|
|
2013 |
getFont2D().getFontMetrics(this, identityTx,
|
|
2014 |
frc.getAntiAliasingHint(),
|
|
2015 |
frc.getFractionalMetricsHint(),
|
|
2016 |
metrics);
|
|
2017 |
float ascent = metrics[0];
|
|
2018 |
float descent = metrics[1];
|
|
2019 |
float leading = metrics[2];
|
|
2020 |
float ssOffset = 0;
|
|
2021 |
if (values != null && values.getSuperscript() != 0) {
|
|
2022 |
ssOffset = (float)getTransform().getTranslateY();
|
|
2023 |
ascent -= ssOffset;
|
|
2024 |
descent += ssOffset;
|
|
2025 |
}
|
|
2026 |
float height = ascent + descent + leading;
|
|
2027 |
|
|
2028 |
int baselineIndex = 0; // need real index, assumes roman for everything
|
|
2029 |
// need real baselines eventually
|
|
2030 |
float[] baselineOffsets = { 0, (descent/2f - ascent) / 2f, -ascent };
|
|
2031 |
|
|
2032 |
float strikethroughOffset = metrics[4];
|
|
2033 |
float strikethroughThickness = metrics[5];
|
|
2034 |
|
|
2035 |
float underlineOffset = metrics[6];
|
|
2036 |
float underlineThickness = metrics[7];
|
|
2037 |
|
|
2038 |
float italicAngle = getItalicAngle(frc);
|
|
2039 |
|
|
2040 |
if (isTransformed()) {
|
|
2041 |
AffineTransform ctx = values.getCharTransform(); // extract rotation
|
|
2042 |
if (ctx != null) {
|
|
2043 |
Point2D.Float pt = new Point2D.Float();
|
|
2044 |
pt.setLocation(0, strikethroughOffset);
|
|
2045 |
ctx.deltaTransform(pt, pt);
|
|
2046 |
strikethroughOffset = pt.y;
|
|
2047 |
pt.setLocation(0, strikethroughThickness);
|
|
2048 |
ctx.deltaTransform(pt, pt);
|
|
2049 |
strikethroughThickness = pt.y;
|
|
2050 |
pt.setLocation(0, underlineOffset);
|
|
2051 |
ctx.deltaTransform(pt, pt);
|
|
2052 |
underlineOffset = pt.y;
|
|
2053 |
pt.setLocation(0, underlineThickness);
|
|
2054 |
ctx.deltaTransform(pt, pt);
|
|
2055 |
underlineThickness = pt.y;
|
|
2056 |
}
|
|
2057 |
}
|
|
2058 |
strikethroughOffset += ssOffset;
|
|
2059 |
underlineOffset += ssOffset;
|
|
2060 |
|
|
2061 |
CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height,
|
|
2062 |
baselineIndex, baselineOffsets,
|
|
2063 |
strikethroughOffset, strikethroughThickness,
|
|
2064 |
underlineOffset, underlineThickness,
|
|
2065 |
ssOffset, italicAngle);
|
|
2066 |
|
|
2067 |
flm = new FontLineMetrics(0, cm, frc);
|
|
2068 |
flmref = new SoftReference(flm);
|
|
2069 |
}
|
|
2070 |
|
|
2071 |
return (FontLineMetrics)flm.clone();
|
|
2072 |
}
|
|
2073 |
|
|
2074 |
/**
|
|
2075 |
* Returns a {@link LineMetrics} object created with the specified
|
|
2076 |
* <code>String</code> and {@link FontRenderContext}.
|
|
2077 |
* @param str the specified <code>String</code>
|
|
2078 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2079 |
* @return a <code>LineMetrics</code> object created with the
|
|
2080 |
* specified <code>String</code> and {@link FontRenderContext}.
|
|
2081 |
*/
|
|
2082 |
public LineMetrics getLineMetrics( String str, FontRenderContext frc) {
|
|
2083 |
FontLineMetrics flm = defaultLineMetrics(frc);
|
|
2084 |
flm.numchars = str.length();
|
|
2085 |
return flm;
|
|
2086 |
}
|
|
2087 |
|
|
2088 |
/**
|
|
2089 |
* Returns a <code>LineMetrics</code> object created with the
|
|
2090 |
* specified arguments.
|
|
2091 |
* @param str the specified <code>String</code>
|
|
2092 |
* @param beginIndex the initial offset of <code>str</code>
|
|
2093 |
* @param limit the end offset of <code>str</code>
|
|
2094 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2095 |
* @return a <code>LineMetrics</code> object created with the
|
|
2096 |
* specified arguments.
|
|
2097 |
*/
|
|
2098 |
public LineMetrics getLineMetrics( String str,
|
|
2099 |
int beginIndex, int limit,
|
|
2100 |
FontRenderContext frc) {
|
|
2101 |
FontLineMetrics flm = defaultLineMetrics(frc);
|
|
2102 |
int numChars = limit - beginIndex;
|
|
2103 |
flm.numchars = (numChars < 0)? 0: numChars;
|
|
2104 |
return flm;
|
|
2105 |
}
|
|
2106 |
|
|
2107 |
/**
|
|
2108 |
* Returns a <code>LineMetrics</code> object created with the
|
|
2109 |
* specified arguments.
|
|
2110 |
* @param chars an array of characters
|
|
2111 |
* @param beginIndex the initial offset of <code>chars</code>
|
|
2112 |
* @param limit the end offset of <code>chars</code>
|
|
2113 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2114 |
* @return a <code>LineMetrics</code> object created with the
|
|
2115 |
* specified arguments.
|
|
2116 |
*/
|
|
2117 |
public LineMetrics getLineMetrics(char [] chars,
|
|
2118 |
int beginIndex, int limit,
|
|
2119 |
FontRenderContext frc) {
|
|
2120 |
FontLineMetrics flm = defaultLineMetrics(frc);
|
|
2121 |
int numChars = limit - beginIndex;
|
|
2122 |
flm.numchars = (numChars < 0)? 0: numChars;
|
|
2123 |
return flm;
|
|
2124 |
}
|
|
2125 |
|
|
2126 |
/**
|
|
2127 |
* Returns a <code>LineMetrics</code> object created with the
|
|
2128 |
* specified arguments.
|
|
2129 |
* @param ci the specified <code>CharacterIterator</code>
|
|
2130 |
* @param beginIndex the initial offset in <code>ci</code>
|
|
2131 |
* @param limit the end offset of <code>ci</code>
|
|
2132 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2133 |
* @return a <code>LineMetrics</code> object created with the
|
|
2134 |
* specified arguments.
|
|
2135 |
*/
|
|
2136 |
public LineMetrics getLineMetrics(CharacterIterator ci,
|
|
2137 |
int beginIndex, int limit,
|
|
2138 |
FontRenderContext frc) {
|
|
2139 |
FontLineMetrics flm = defaultLineMetrics(frc);
|
|
2140 |
int numChars = limit - beginIndex;
|
|
2141 |
flm.numchars = (numChars < 0)? 0: numChars;
|
|
2142 |
return flm;
|
|
2143 |
}
|
|
2144 |
|
|
2145 |
/**
|
|
2146 |
* Returns the logical bounds of the specified <code>String</code> in
|
|
2147 |
* the specified <code>FontRenderContext</code>. The logical bounds
|
|
2148 |
* contains the origin, ascent, advance, and height, which includes
|
|
2149 |
* the leading. The logical bounds does not always enclose all the
|
|
2150 |
* text. For example, in some languages and in some fonts, accent
|
|
2151 |
* marks can be positioned above the ascent or below the descent.
|
|
2152 |
* To obtain a visual bounding box, which encloses all the text,
|
|
2153 |
* use the {@link TextLayout#getBounds() getBounds} method of
|
|
2154 |
* <code>TextLayout</code>.
|
|
2155 |
* <p>Note: The returned bounds is in baseline-relative coordinates
|
|
2156 |
* (see {@link java.awt.Font class notes}).
|
|
2157 |
* @param str the specified <code>String</code>
|
|
2158 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2159 |
* @return a {@link Rectangle2D} that is the bounding box of the
|
|
2160 |
* specified <code>String</code> in the specified
|
|
2161 |
* <code>FontRenderContext</code>.
|
|
2162 |
* @see FontRenderContext
|
|
2163 |
* @see Font#createGlyphVector
|
|
2164 |
* @since 1.2
|
|
2165 |
*/
|
|
2166 |
public Rectangle2D getStringBounds( String str, FontRenderContext frc) {
|
|
2167 |
char[] array = str.toCharArray();
|
|
2168 |
return getStringBounds(array, 0, array.length, frc);
|
|
2169 |
}
|
|
2170 |
|
|
2171 |
/**
|
|
2172 |
* Returns the logical bounds of the specified <code>String</code> in
|
|
2173 |
* the specified <code>FontRenderContext</code>. The logical bounds
|
|
2174 |
* contains the origin, ascent, advance, and height, which includes
|
|
2175 |
* the leading. The logical bounds does not always enclose all the
|
|
2176 |
* text. For example, in some languages and in some fonts, accent
|
|
2177 |
* marks can be positioned above the ascent or below the descent.
|
|
2178 |
* To obtain a visual bounding box, which encloses all the text,
|
|
2179 |
* use the {@link TextLayout#getBounds() getBounds} method of
|
|
2180 |
* <code>TextLayout</code>.
|
|
2181 |
* <p>Note: The returned bounds is in baseline-relative coordinates
|
|
2182 |
* (see {@link java.awt.Font class notes}).
|
|
2183 |
* @param str the specified <code>String</code>
|
|
2184 |
* @param beginIndex the initial offset of <code>str</code>
|
|
2185 |
* @param limit the end offset of <code>str</code>
|
|
2186 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2187 |
* @return a <code>Rectangle2D</code> that is the bounding box of the
|
|
2188 |
* specified <code>String</code> in the specified
|
|
2189 |
* <code>FontRenderContext</code>.
|
|
2190 |
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
|
|
2191 |
* less than zero, or <code>limit</code> is greater than the
|
|
2192 |
* length of <code>str</code>, or <code>beginIndex</code>
|
|
2193 |
* is greater than <code>limit</code>.
|
|
2194 |
* @see FontRenderContext
|
|
2195 |
* @see Font#createGlyphVector
|
|
2196 |
* @since 1.2
|
|
2197 |
*/
|
|
2198 |
public Rectangle2D getStringBounds( String str,
|
|
2199 |
int beginIndex, int limit,
|
|
2200 |
FontRenderContext frc) {
|
|
2201 |
String substr = str.substring(beginIndex, limit);
|
|
2202 |
return getStringBounds(substr, frc);
|
|
2203 |
}
|
|
2204 |
|
|
2205 |
/**
|
|
2206 |
* Returns the logical bounds of the specified array of characters
|
|
2207 |
* in the specified <code>FontRenderContext</code>. The logical
|
|
2208 |
* bounds contains the origin, ascent, advance, and height, which
|
|
2209 |
* includes the leading. The logical bounds does not always enclose
|
|
2210 |
* all the text. For example, in some languages and in some fonts,
|
|
2211 |
* accent marks can be positioned above the ascent or below the
|
|
2212 |
* descent. To obtain a visual bounding box, which encloses all the
|
|
2213 |
* text, use the {@link TextLayout#getBounds() getBounds} method of
|
|
2214 |
* <code>TextLayout</code>.
|
|
2215 |
* <p>Note: The returned bounds is in baseline-relative coordinates
|
|
2216 |
* (see {@link java.awt.Font class notes}).
|
|
2217 |
* @param chars an array of characters
|
|
2218 |
* @param beginIndex the initial offset in the array of
|
|
2219 |
* characters
|
|
2220 |
* @param limit the end offset in the array of characters
|
|
2221 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2222 |
* @return a <code>Rectangle2D</code> that is the bounding box of the
|
|
2223 |
* specified array of characters in the specified
|
|
2224 |
* <code>FontRenderContext</code>.
|
|
2225 |
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
|
|
2226 |
* less than zero, or <code>limit</code> is greater than the
|
|
2227 |
* length of <code>chars</code>, or <code>beginIndex</code>
|
|
2228 |
* is greater than <code>limit</code>.
|
|
2229 |
* @see FontRenderContext
|
|
2230 |
* @see Font#createGlyphVector
|
|
2231 |
* @since 1.2
|
|
2232 |
*/
|
|
2233 |
public Rectangle2D getStringBounds(char [] chars,
|
|
2234 |
int beginIndex, int limit,
|
|
2235 |
FontRenderContext frc) {
|
|
2236 |
if (beginIndex < 0) {
|
|
2237 |
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
|
|
2238 |
}
|
|
2239 |
if (limit > chars.length) {
|
|
2240 |
throw new IndexOutOfBoundsException("limit: " + limit);
|
|
2241 |
}
|
|
2242 |
if (beginIndex > limit) {
|
|
2243 |
throw new IndexOutOfBoundsException("range length: " +
|
|
2244 |
(limit - beginIndex));
|
|
2245 |
}
|
|
2246 |
|
|
2247 |
// this code should be in textlayout
|
|
2248 |
// quick check for simple text, assume GV ok to use if simple
|
|
2249 |
|
|
2250 |
boolean simple = values == null ||
|
|
2251 |
(values.getKerning() == 0 && values.getLigatures() == 0 &&
|
|
2252 |
values.getBaselineTransform() == null);
|
|
2253 |
if (simple) {
|
|
2254 |
simple = !FontManager.isComplexText(chars, beginIndex, limit);
|
|
2255 |
}
|
|
2256 |
|
|
2257 |
if (simple) {
|
|
2258 |
GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
|
|
2259 |
limit - beginIndex, frc);
|
|
2260 |
return gv.getLogicalBounds();
|
|
2261 |
} else {
|
|
2262 |
// need char array constructor on textlayout
|
|
2263 |
String str = new String(chars, beginIndex, limit - beginIndex);
|
|
2264 |
TextLayout tl = new TextLayout(str, this, frc);
|
|
2265 |
return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
|
|
2266 |
tl.getAscent() + tl.getDescent() +
|
|
2267 |
tl.getLeading());
|
|
2268 |
}
|
|
2269 |
}
|
|
2270 |
|
|
2271 |
/**
|
|
2272 |
* Returns the logical bounds of the characters indexed in the
|
|
2273 |
* specified {@link CharacterIterator} in the
|
|
2274 |
* specified <code>FontRenderContext</code>. The logical bounds
|
|
2275 |
* contains the origin, ascent, advance, and height, which includes
|
|
2276 |
* the leading. The logical bounds does not always enclose all the
|
|
2277 |
* text. For example, in some languages and in some fonts, accent
|
|
2278 |
* marks can be positioned above the ascent or below the descent.
|
|
2279 |
* To obtain a visual bounding box, which encloses all the text,
|
|
2280 |
* use the {@link TextLayout#getBounds() getBounds} method of
|
|
2281 |
* <code>TextLayout</code>.
|
|
2282 |
* <p>Note: The returned bounds is in baseline-relative coordinates
|
|
2283 |
* (see {@link java.awt.Font class notes}).
|
|
2284 |
* @param ci the specified <code>CharacterIterator</code>
|
|
2285 |
* @param beginIndex the initial offset in <code>ci</code>
|
|
2286 |
* @param limit the end offset in <code>ci</code>
|
|
2287 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2288 |
* @return a <code>Rectangle2D</code> that is the bounding box of the
|
|
2289 |
* characters indexed in the specified <code>CharacterIterator</code>
|
|
2290 |
* in the specified <code>FontRenderContext</code>.
|
|
2291 |
* @see FontRenderContext
|
|
2292 |
* @see Font#createGlyphVector
|
|
2293 |
* @since 1.2
|
|
2294 |
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
|
|
2295 |
* less than the start index of <code>ci</code>, or
|
|
2296 |
* <code>limit</code> is greater than the end index of
|
|
2297 |
* <code>ci</code>, or <code>beginIndex</code> is greater
|
|
2298 |
* than <code>limit</code>
|
|
2299 |
*/
|
|
2300 |
public Rectangle2D getStringBounds(CharacterIterator ci,
|
|
2301 |
int beginIndex, int limit,
|
|
2302 |
FontRenderContext frc) {
|
|
2303 |
int start = ci.getBeginIndex();
|
|
2304 |
int end = ci.getEndIndex();
|
|
2305 |
|
|
2306 |
if (beginIndex < start) {
|
|
2307 |
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
|
|
2308 |
}
|
|
2309 |
if (limit > end) {
|
|
2310 |
throw new IndexOutOfBoundsException("limit: " + limit);
|
|
2311 |
}
|
|
2312 |
if (beginIndex > limit) {
|
|
2313 |
throw new IndexOutOfBoundsException("range length: " +
|
|
2314 |
(limit - beginIndex));
|
|
2315 |
}
|
|
2316 |
|
|
2317 |
char[] arr = new char[limit - beginIndex];
|
|
2318 |
|
|
2319 |
ci.setIndex(beginIndex);
|
|
2320 |
for(int idx = 0; idx < arr.length; idx++) {
|
|
2321 |
arr[idx] = ci.current();
|
|
2322 |
ci.next();
|
|
2323 |
}
|
|
2324 |
|
|
2325 |
return getStringBounds(arr,0,arr.length,frc);
|
|
2326 |
}
|
|
2327 |
|
|
2328 |
/**
|
|
2329 |
* Returns the bounds for the character with the maximum
|
|
2330 |
* bounds as defined in the specified <code>FontRenderContext</code>.
|
|
2331 |
* <p>Note: The returned bounds is in baseline-relative coordinates
|
|
2332 |
* (see {@link java.awt.Font class notes}).
|
|
2333 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2334 |
* @return a <code>Rectangle2D</code> that is the bounding box
|
|
2335 |
* for the character with the maximum bounds.
|
|
2336 |
*/
|
|
2337 |
public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
|
|
2338 |
float [] metrics = new float[4];
|
|
2339 |
|
|
2340 |
getFont2D().getFontMetrics(this, frc, metrics);
|
|
2341 |
|
|
2342 |
return new Rectangle2D.Float(0, -metrics[0],
|
|
2343 |
metrics[3],
|
|
2344 |
metrics[0] + metrics[1] + metrics[2]);
|
|
2345 |
}
|
|
2346 |
|
|
2347 |
/**
|
|
2348 |
* Creates a {@link java.awt.font.GlyphVector GlyphVector} by
|
|
2349 |
* mapping characters to glyphs one-to-one based on the
|
|
2350 |
* Unicode cmap in this <code>Font</code>. This method does no other
|
|
2351 |
* processing besides the mapping of glyphs to characters. This
|
|
2352 |
* means that this method is not useful for some scripts, such
|
|
2353 |
* as Arabic, Hebrew, Thai, and Indic, that require reordering,
|
|
2354 |
* shaping, or ligature substitution.
|
|
2355 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2356 |
* @param str the specified <code>String</code>
|
|
2357 |
* @return a new <code>GlyphVector</code> created with the
|
|
2358 |
* specified <code>String</code> and the specified
|
|
2359 |
* <code>FontRenderContext</code>.
|
|
2360 |
*/
|
|
2361 |
public GlyphVector createGlyphVector(FontRenderContext frc, String str)
|
|
2362 |
{
|
|
2363 |
return (GlyphVector)new StandardGlyphVector(this, str, frc);
|
|
2364 |
}
|
|
2365 |
|
|
2366 |
/**
|
|
2367 |
* Creates a {@link java.awt.font.GlyphVector GlyphVector} by
|
|
2368 |
* mapping characters to glyphs one-to-one based on the
|
|
2369 |
* Unicode cmap in this <code>Font</code>. This method does no other
|
|
2370 |
* processing besides the mapping of glyphs to characters. This
|
|
2371 |
* means that this method is not useful for some scripts, such
|
|
2372 |
* as Arabic, Hebrew, Thai, and Indic, that require reordering,
|
|
2373 |
* shaping, or ligature substitution.
|
|
2374 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2375 |
* @param chars the specified array of characters
|
|
2376 |
* @return a new <code>GlyphVector</code> created with the
|
|
2377 |
* specified array of characters and the specified
|
|
2378 |
* <code>FontRenderContext</code>.
|
|
2379 |
*/
|
|
2380 |
public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars)
|
|
2381 |
{
|
|
2382 |
return (GlyphVector)new StandardGlyphVector(this, chars, frc);
|
|
2383 |
}
|
|
2384 |
|
|
2385 |
/**
|
|
2386 |
* Creates a {@link java.awt.font.GlyphVector GlyphVector} by
|
|
2387 |
* mapping the specified characters to glyphs one-to-one based on the
|
|
2388 |
* Unicode cmap in this <code>Font</code>. This method does no other
|
|
2389 |
* processing besides the mapping of glyphs to characters. This
|
|
2390 |
* means that this method is not useful for some scripts, such
|
|
2391 |
* as Arabic, Hebrew, Thai, and Indic, that require reordering,
|
|
2392 |
* shaping, or ligature substitution.
|
|
2393 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2394 |
* @param ci the specified <code>CharacterIterator</code>
|
|
2395 |
* @return a new <code>GlyphVector</code> created with the
|
|
2396 |
* specified <code>CharacterIterator</code> and the specified
|
|
2397 |
* <code>FontRenderContext</code>.
|
|
2398 |
*/
|
|
2399 |
public GlyphVector createGlyphVector( FontRenderContext frc,
|
|
2400 |
CharacterIterator ci)
|
|
2401 |
{
|
|
2402 |
return (GlyphVector)new StandardGlyphVector(this, ci, frc);
|
|
2403 |
}
|
|
2404 |
|
|
2405 |
/**
|
|
2406 |
* Creates a {@link java.awt.font.GlyphVector GlyphVector} by
|
|
2407 |
* mapping characters to glyphs one-to-one based on the
|
|
2408 |
* Unicode cmap in this <code>Font</code>. This method does no other
|
|
2409 |
* processing besides the mapping of glyphs to characters. This
|
|
2410 |
* means that this method is not useful for some scripts, such
|
|
2411 |
* as Arabic, Hebrew, Thai, and Indic, that require reordering,
|
|
2412 |
* shaping, or ligature substitution.
|
|
2413 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2414 |
* @param glyphCodes the specified integer array
|
|
2415 |
* @return a new <code>GlyphVector</code> created with the
|
|
2416 |
* specified integer array and the specified
|
|
2417 |
* <code>FontRenderContext</code>.
|
|
2418 |
*/
|
|
2419 |
public GlyphVector createGlyphVector( FontRenderContext frc,
|
|
2420 |
int [] glyphCodes)
|
|
2421 |
{
|
|
2422 |
return (GlyphVector)new StandardGlyphVector(this, glyphCodes, frc);
|
|
2423 |
}
|
|
2424 |
|
|
2425 |
/**
|
|
2426 |
* Returns a new <code>GlyphVector</code> object, performing full
|
|
2427 |
* layout of the text if possible. Full layout is required for
|
|
2428 |
* complex text, such as Arabic or Hindi. Support for different
|
|
2429 |
* scripts depends on the font and implementation.
|
|
2430 |
* <p>
|
|
2431 |
* Layout requires bidi analysis, as performed by
|
|
2432 |
* <code>Bidi</code>, and should only be performed on text that
|
|
2433 |
* has a uniform direction. The direction is indicated in the
|
|
2434 |
* flags parameter,by using LAYOUT_RIGHT_TO_LEFT to indicate a
|
|
2435 |
* right-to-left (Arabic and Hebrew) run direction, or
|
|
2436 |
* LAYOUT_LEFT_TO_RIGHT to indicate a left-to-right (English)
|
|
2437 |
* run direction.
|
|
2438 |
* <p>
|
|
2439 |
* In addition, some operations, such as Arabic shaping, require
|
|
2440 |
* context, so that the characters at the start and limit can have
|
|
2441 |
* the proper shapes. Sometimes the data in the buffer outside
|
|
2442 |
* the provided range does not have valid data. The values
|
|
2443 |
* LAYOUT_NO_START_CONTEXT and LAYOUT_NO_LIMIT_CONTEXT can be
|
|
2444 |
* added to the flags parameter to indicate that the text before
|
|
2445 |
* start, or after limit, respectively, should not be examined
|
|
2446 |
* for context.
|
|
2447 |
* <p>
|
|
2448 |
* All other values for the flags parameter are reserved.
|
|
2449 |
*
|
|
2450 |
* @param frc the specified <code>FontRenderContext</code>
|
|
2451 |
* @param text the text to layout
|
|
2452 |
* @param start the start of the text to use for the <code>GlyphVector</code>
|
|
2453 |
* @param limit the limit of the text to use for the <code>GlyphVector</code>
|
|
2454 |
* @param flags control flags as described above
|
|
2455 |
* @return a new <code>GlyphVector</code> representing the text between
|
|
2456 |
* start and limit, with glyphs chosen and positioned so as to best represent
|
|
2457 |
* the text
|
|
2458 |
* @throws ArrayIndexOutOfBoundsException if start or limit is
|
|
2459 |
* out of bounds
|
|
2460 |
* @see java.text.Bidi
|
|
2461 |
* @see #LAYOUT_LEFT_TO_RIGHT
|
|
2462 |
* @see #LAYOUT_RIGHT_TO_LEFT
|
|
2463 |
* @see #LAYOUT_NO_START_CONTEXT
|
|
2464 |
* @see #LAYOUT_NO_LIMIT_CONTEXT
|
|
2465 |
* @since 1.4
|
|
2466 |
*/
|
|
2467 |
public GlyphVector layoutGlyphVector(FontRenderContext frc,
|
|
2468 |
char[] text,
|
|
2469 |
int start,
|
|
2470 |
int limit,
|
|
2471 |
int flags) {
|
|
2472 |
|
|
2473 |
GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines
|
|
2474 |
StandardGlyphVector gv = gl.layout(this, frc, text,
|
|
2475 |
start, limit-start, flags, null);
|
|
2476 |
GlyphLayout.done(gl);
|
|
2477 |
return gv;
|
|
2478 |
}
|
|
2479 |
|
|
2480 |
/**
|
|
2481 |
* A flag to layoutGlyphVector indicating that text is left-to-right as
|
|
2482 |
* determined by Bidi analysis.
|
|
2483 |
*/
|
|
2484 |
public static final int LAYOUT_LEFT_TO_RIGHT = 0;
|
|
2485 |
|
|
2486 |
/**
|
|
2487 |
* A flag to layoutGlyphVector indicating that text is right-to-left as
|
|
2488 |
* determined by Bidi analysis.
|
|
2489 |
*/
|
|
2490 |
public static final int LAYOUT_RIGHT_TO_LEFT = 1;
|
|
2491 |
|
|
2492 |
/**
|
|
2493 |
* A flag to layoutGlyphVector indicating that text in the char array
|
|
2494 |
* before the indicated start should not be examined.
|
|
2495 |
*/
|
|
2496 |
public static final int LAYOUT_NO_START_CONTEXT = 2;
|
|
2497 |
|
|
2498 |
/**
|
|
2499 |
* A flag to layoutGlyphVector indicating that text in the char array
|
|
2500 |
* after the indicated limit should not be examined.
|
|
2501 |
*/
|
|
2502 |
public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
|
|
2503 |
|
|
2504 |
|
|
2505 |
private static void applyTransform(AffineTransform trans, AttributeValues values) {
|
|
2506 |
if (trans == null) {
|
|
2507 |
throw new IllegalArgumentException("transform must not be null");
|
|
2508 |
}
|
|
2509 |
values.setTransform(trans);
|
|
2510 |
}
|
|
2511 |
|
|
2512 |
private static void applyStyle(int style, AttributeValues values) {
|
|
2513 |
// WEIGHT_BOLD, WEIGHT_REGULAR
|
|
2514 |
values.setWeight((style & BOLD) != 0 ? 2f : 1f);
|
|
2515 |
// POSTURE_OBLIQUE, POSTURE_REGULAR
|
|
2516 |
values.setPosture((style & ITALIC) != 0 ? .2f : 0f);
|
|
2517 |
}
|
|
2518 |
|
|
2519 |
/*
|
|
2520 |
* Initialize JNI field and method IDs
|
|
2521 |
*/
|
|
2522 |
private static native void initIDs();
|
|
2523 |
}
|