blob: 8edd2227badad92e9735a146653b53dcb86f25d3 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
Sergey Bylokhovb9aead12015-04-17 16:54:13 +03002 * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
J. Duke319a3b92007-12-01 00:00:00 +00003 * 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
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07007 * published by the Free Software Foundation. Oracle designates this
J. Duke319a3b92007-12-01 00:00:00 +00008 * particular file as subject to the "Classpath" exception as provided
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07009 * by Oracle in the LICENSE file that accompanied this code.
J. Duke319a3b92007-12-01 00:00:00 +000010 *
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 *
Kelly O'Hairfe008ae2010-05-25 15:58:33 -070021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
J. Duke319a3b92007-12-01 00:00:00 +000024 */
25
26package java.awt;
27
28import java.awt.font.FontRenderContext;
29import java.awt.font.GlyphVector;
30import java.awt.font.LineMetrics;
31import java.awt.font.TextAttribute;
32import java.awt.font.TextLayout;
J. Duke319a3b92007-12-01 00:00:00 +000033import java.awt.geom.AffineTransform;
34import java.awt.geom.Point2D;
35import java.awt.geom.Rectangle2D;
36import java.awt.peer.FontPeer;
37import java.io.*;
38import java.lang.ref.SoftReference;
Rob McKennac3a386e2012-04-11 17:47:56 -070039import java.nio.file.Files;
Phil Racec357cbe2009-01-05 11:28:43 -080040import java.security.AccessController;
41import java.security.PrivilegedExceptionAction;
J. Duke319a3b92007-12-01 00:00:00 +000042import java.text.AttributedCharacterIterator.Attribute;
43import java.text.CharacterIterator;
J. Duke319a3b92007-12-01 00:00:00 +000044import java.util.Hashtable;
45import java.util.Locale;
46import java.util.Map;
Sergey Bylokhov66344452015-04-17 17:01:24 +030047
48import sun.awt.ComponentFactory;
J. Duke319a3b92007-12-01 00:00:00 +000049import sun.font.StandardGlyphVector;
J. Duke319a3b92007-12-01 00:00:00 +000050
51import sun.font.AttributeMap;
52import sun.font.AttributeValues;
J. Duke319a3b92007-12-01 00:00:00 +000053import sun.font.CompositeFont;
Phil Racec357cbe2009-01-05 11:28:43 -080054import sun.font.CreatedFontTracker;
J. Duke319a3b92007-12-01 00:00:00 +000055import sun.font.Font2D;
56import sun.font.Font2DHandle;
Roman Kennkeeb125532009-08-07 18:31:11 +020057import sun.font.FontAccess;
J. Duke319a3b92007-12-01 00:00:00 +000058import sun.font.FontManager;
Roman Kennkeeb125532009-08-07 18:31:11 +020059import sun.font.FontManagerFactory;
60import sun.font.FontUtilities;
J. Duke319a3b92007-12-01 00:00:00 +000061import sun.font.GlyphLayout;
62import sun.font.FontLineMetrics;
63import sun.font.CoreMetrics;
64
65import static sun.font.EAttribute.*;
66
67/**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +030068 * The {@code Font} class represents fonts, which are used to
J. Duke319a3b92007-12-01 00:00:00 +000069 * render text in a visible way.
70 * A font provides the information needed to map sequences of
71 * <em>characters</em> to sequences of <em>glyphs</em>
Alexander Stepanov73fb68a2016-01-11 17:51:54 +030072 * and to render sequences of glyphs on {@code Graphics} and
73 * {@code Component} objects.
J. Duke319a3b92007-12-01 00:00:00 +000074 *
Dmitry Ginzburg94c66a62013-11-20 12:23:55 +040075 * <h3>Characters and Glyphs</h3>
J. Duke319a3b92007-12-01 00:00:00 +000076 *
77 * A <em>character</em> is a symbol that represents an item such as a letter,
Alexander Stepanov73fb68a2016-01-11 17:51:54 +030078 * a digit, or punctuation in an abstract way. For example, {@code 'g'},
Roger Riggse2a0a412013-12-03 16:20:44 -050079 * LATIN SMALL LETTER G, is a character.
J. Duke319a3b92007-12-01 00:00:00 +000080 * <p>
81 * A <em>glyph</em> is a shape used to render a character or a sequence of
82 * characters. In simple writing systems, such as Latin, typically one glyph
83 * represents one character. In general, however, characters and glyphs do not
84 * have one-to-one correspondence. For example, the character '&aacute;'
Roger Riggse2a0a412013-12-03 16:20:44 -050085 * LATIN SMALL LETTER A WITH ACUTE, can be represented by
J. Duke319a3b92007-12-01 00:00:00 +000086 * two glyphs: one for 'a' and one for '&acute;'. On the other hand, the
87 * two-character string "fi" can be represented by a single glyph, an
88 * "fi" ligature. In complex writing systems, such as Arabic or the South
89 * and South-East Asian writing systems, the relationship between characters
90 * and glyphs can be more complicated and involve context-dependent selection
91 * of glyphs as well as glyph reordering.
92 *
93 * A font encapsulates the collection of glyphs needed to render a selected set
94 * of characters as well as the tables needed to map sequences of characters to
95 * corresponding sequences of glyphs.
96 *
Roger Riggse2a0a412013-12-03 16:20:44 -050097 * <h3>Physical and Logical Fonts</h3>
J. Duke319a3b92007-12-01 00:00:00 +000098 *
99 * The Java Platform distinguishes between two kinds of fonts:
100 * <em>physical</em> fonts and <em>logical</em> fonts.
101 * <p>
102 * <em>Physical</em> fonts are the actual font libraries containing glyph data
103 * and tables to map from character sequences to glyph sequences, using a font
104 * technology such as TrueType or PostScript Type 1.
105 * All implementations of the Java Platform must support TrueType fonts;
106 * support for other font technologies is implementation dependent.
107 * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or
108 * any number of other font names.
109 * Typically, each physical font supports only a limited set of writing
110 * systems, for example, only Latin characters or only Japanese and Basic
111 * Latin.
112 * The set of available physical fonts varies between configurations.
113 * Applications that require specific fonts can bundle them and instantiate
114 * them using the {@link #createFont createFont} method.
115 * <p>
116 * <em>Logical</em> fonts are the five font families defined by the Java
117 * platform which must be supported by any Java runtime environment:
118 * Serif, SansSerif, Monospaced, Dialog, and DialogInput.
119 * These logical fonts are not actual font libraries. Instead, the logical
120 * font names are mapped to physical fonts by the Java runtime environment.
121 * The mapping is implementation and usually locale dependent, so the look
122 * and the metrics provided by them vary.
123 * Typically, each logical font name maps to several physical fonts in order to
124 * cover a large range of characters.
125 * <p>
126 * Peered AWT components, such as {@link Label Label} and
127 * {@link TextField TextField}, can only use logical fonts.
128 * <p>
129 * For a discussion of the relative advantages and disadvantages of using
130 * physical or logical fonts, see the
Prasanta Sadhukhan227dff52015-09-04 12:51:39 +0300131 * <a href="https://docs.oracle.com/javase/tutorial/2d/text/fonts.html#advantages-and-disadvantages">
132 * Physical and Logical Fonts</a>
133 * in <a href="https://docs.oracle.com/javase/tutorial/index.html">The Java Tutorials</a>
J. Duke319a3b92007-12-01 00:00:00 +0000134 * document.
135 *
Roger Riggse2a0a412013-12-03 16:20:44 -0500136 * <h3>Font Faces and Names</h3>
J. Duke319a3b92007-12-01 00:00:00 +0000137 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300138 * A {@code Font}
J. Duke319a3b92007-12-01 00:00:00 +0000139 * can have many faces, such as heavy, medium, oblique, gothic and
140 * regular. All of these faces have similar typographic design.
141 * <p>
142 * There are three different names that you can get from a
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300143 * {@code Font} object. The <em>logical font name</em> is simply the
J. Duke319a3b92007-12-01 00:00:00 +0000144 * name that was used to construct the font.
145 * The <em>font face name</em>, or just <em>font name</em> for
146 * short, is the name of a particular font face, like Helvetica Bold. The
147 * <em>family name</em> is the name of the font family that determines the
148 * typographic design across several faces, like Helvetica.
149 * <p>
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300150 * The {@code Font} class represents an instance of a font face from
J. Duke319a3b92007-12-01 00:00:00 +0000151 * a collection of font faces that are present in the system resources
152 * of the host system. As examples, Arial Bold and Courier Bold Italic
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300153 * are font faces. There can be several {@code Font} objects
J. Duke319a3b92007-12-01 00:00:00 +0000154 * associated with a font face, each differing in size, style, transform
155 * and font features.
156 * <p>
157 * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300158 * of the {@code GraphicsEnvironment} class returns an
J. Duke319a3b92007-12-01 00:00:00 +0000159 * array of all font faces available in the system. These font faces are
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300160 * returned as {@code Font} objects with a size of 1, identity
J. Duke319a3b92007-12-01 00:00:00 +0000161 * transform and default font features. These
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300162 * base fonts can then be used to derive new {@code Font} objects
J. Duke319a3b92007-12-01 00:00:00 +0000163 * with varying sizes, styles, transforms and font features via the
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300164 * {@code deriveFont} methods in this class.
J. Duke319a3b92007-12-01 00:00:00 +0000165 *
Roger Riggse2a0a412013-12-03 16:20:44 -0500166 * <h3>Font and TextAttribute</h3>
J. Duke319a3b92007-12-01 00:00:00 +0000167 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300168 * <p>{@code Font} supports most
169 * {@code TextAttribute}s. This makes some operations, such as
J. Duke319a3b92007-12-01 00:00:00 +0000170 * rendering underlined text, convenient since it is not
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300171 * necessary to explicitly construct a {@code TextLayout} object.
J. Duke319a3b92007-12-01 00:00:00 +0000172 * Attributes can be set on a Font by constructing or deriving it
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300173 * using a {@code Map} of {@code TextAttribute} values.
J. Duke319a3b92007-12-01 00:00:00 +0000174 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300175 * <p>The values of some {@code TextAttributes} are not
J. Duke319a3b92007-12-01 00:00:00 +0000176 * serializable, and therefore attempting to serialize an instance of
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300177 * {@code Font} that has such values will not serialize them.
J. Duke319a3b92007-12-01 00:00:00 +0000178 * This means a Font deserialized from such a stream will not compare
179 * equal to the original Font that contained the non-serializable
180 * attributes. This should very rarely pose a problem
181 * since these attributes are typically used only in special
182 * circumstances and are unlikely to be serialized.
183 *
184 * <ul>
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300185 * <li>{@code FOREGROUND} and {@code BACKGROUND} use
186 * {@code Paint} values. The subclass {@code Color} is
187 * serializable, while {@code GradientPaint} and
188 * {@code TexturePaint} are not.</li>
189 * <li>{@code CHAR_REPLACEMENT} uses
190 * {@code GraphicAttribute} values. The subclasses
191 * {@code ShapeGraphicAttribute} and
192 * {@code ImageGraphicAttribute} are not serializable.</li>
193 * <li>{@code INPUT_METHOD_HIGHLIGHT} uses
194 * {@code InputMethodHighlight} values, which are
J. Duke319a3b92007-12-01 00:00:00 +0000195 * not serializable. See {@link java.awt.im.InputMethodHighlight}.</li>
196 * </ul>
197 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300198 * <p>Clients who create custom subclasses of {@code Paint} and
199 * {@code GraphicAttribute} can make them serializable and
J. Duke319a3b92007-12-01 00:00:00 +0000200 * avoid this problem. Clients who use input method highlights can
201 * convert these to the platform-specific attributes for that
202 * highlight on the current platform and set them on the Font as
Roger Riggse2a0a412013-12-03 16:20:44 -0500203 * a workaround.
J. Duke319a3b92007-12-01 00:00:00 +0000204 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300205 * <p>The {@code Map}-based constructor and
206 * {@code deriveFont} APIs ignore the FONT attribute, and it is
J. Duke319a3b92007-12-01 00:00:00 +0000207 * not retained by the Font; the static {@link #getFont} method should
208 * be used if the FONT attribute might be present. See {@link
209 * java.awt.font.TextAttribute#FONT} for more information.</p>
210 *
211 * <p>Several attributes will cause additional rendering overhead
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300212 * and potentially invoke layout. If a {@code Font} has such
J. Duke319a3b92007-12-01 00:00:00 +0000213 * attributes, the <code>{@link #hasLayoutAttributes()}</code> method
214 * will return true.</p>
215 *
216 * <p>Note: Font rotations can cause text baselines to be rotated. In
217 * order to account for this (rare) possibility, font APIs are
218 * specified to return metrics and take parameters 'in
219 * baseline-relative coordinates'. This maps the 'x' coordinate to
220 * the advance along the baseline, (positive x is forward along the
221 * baseline), and the 'y' coordinate to a distance along the
222 * perpendicular to the baseline at 'x' (positive y is 90 degrees
223 * clockwise from the baseline vector). APIs for which this is
224 * especially important are called out as having 'baseline-relative
225 * coordinates.'
226 */
227public class Font implements java.io.Serializable
228{
Roman Kennkeeb125532009-08-07 18:31:11 +0200229 private static class FontAccessImpl extends FontAccess {
230 public Font2D getFont2D(Font font) {
231 return font.getFont2D();
232 }
233
234 public void setFont2D(Font font, Font2DHandle handle) {
235 font.font2DHandle = handle;
236 }
237
238 public void setCreatedFont(Font font) {
239 font.createdFont = true;
240 }
241
242 public boolean isCreatedFont(Font font) {
243 return font.createdFont;
244 }
Sergey Bylokhovb9aead12015-04-17 16:54:13 +0300245
246 @Override
247 public FontPeer getFontPeer(final Font font) {
248 return font.getFontPeer();
249 }
Roman Kennkeeb125532009-08-07 18:31:11 +0200250 }
251
J. Duke319a3b92007-12-01 00:00:00 +0000252 static {
253 /* ensure that the necessary native libraries are loaded */
254 Toolkit.loadLibraries();
255 initIDs();
Roman Kennkeeb125532009-08-07 18:31:11 +0200256 FontAccess.setFontAccess(new FontAccessImpl());
J. Duke319a3b92007-12-01 00:00:00 +0000257 }
258
259 /**
260 * This is now only used during serialization. Typically
261 * it is null.
262 *
263 * @serial
264 * @see #getAttributes()
265 */
Oleg Pekhovskiy37047152011-12-19 15:21:35 +0400266 private Hashtable<Object, Object> fRequestedAttributes;
J. Duke319a3b92007-12-01 00:00:00 +0000267
268 /*
269 * Constants to be used for logical font family names.
270 */
271
272 /**
273 * A String constant for the canonical family name of the
274 * logical font "Dialog". It is useful in Font construction
275 * to provide compile-time verification of the name.
276 * @since 1.6
277 */
278 public static final String DIALOG = "Dialog";
279
280 /**
281 * A String constant for the canonical family name of the
282 * logical font "DialogInput". It is useful in Font construction
283 * to provide compile-time verification of the name.
284 * @since 1.6
285 */
286 public static final String DIALOG_INPUT = "DialogInput";
287
288 /**
289 * A String constant for the canonical family name of the
290 * logical font "SansSerif". It is useful in Font construction
291 * to provide compile-time verification of the name.
292 * @since 1.6
293 */
294 public static final String SANS_SERIF = "SansSerif";
295
296 /**
297 * A String constant for the canonical family name of the
298 * logical font "Serif". It is useful in Font construction
299 * to provide compile-time verification of the name.
300 * @since 1.6
301 */
302 public static final String SERIF = "Serif";
303
304 /**
305 * A String constant for the canonical family name of the
306 * logical font "Monospaced". It is useful in Font construction
307 * to provide compile-time verification of the name.
308 * @since 1.6
309 */
310 public static final String MONOSPACED = "Monospaced";
311
312 /*
313 * Constants to be used for styles. Can be combined to mix
314 * styles.
315 */
316
317 /**
318 * The plain style constant.
319 */
320 public static final int PLAIN = 0;
321
322 /**
323 * The bold style constant. This can be combined with the other style
324 * constants (except PLAIN) for mixed styles.
325 */
326 public static final int BOLD = 1;
327
328 /**
329 * The italicized style constant. This can be combined with the other
330 * style constants (except PLAIN) for mixed styles.
331 */
332 public static final int ITALIC = 2;
333
334 /**
335 * The baseline used in most Roman scripts when laying out text.
336 */
337 public static final int ROMAN_BASELINE = 0;
338
339 /**
340 * The baseline used in ideographic scripts like Chinese, Japanese,
341 * and Korean when laying out text.
342 */
343 public static final int CENTER_BASELINE = 1;
344
345 /**
Pavel Rappo8be77ee2014-09-17 16:14:12 +0400346 * The baseline used in Devanagari and similar scripts when laying
J. Duke319a3b92007-12-01 00:00:00 +0000347 * out text.
348 */
349 public static final int HANGING_BASELINE = 2;
350
351 /**
352 * Identify a font resource of type TRUETYPE.
353 * Used to specify a TrueType font resource to the
354 * {@link #createFont} method.
Phil Race8b691382010-05-27 08:53:45 -0700355 * The TrueType format was extended to become the OpenType
356 * format, which adds support for fonts with Postscript outlines,
357 * this tag therefore references these fonts, as well as those
358 * with TrueType outlines.
J. Duke319a3b92007-12-01 00:00:00 +0000359 * @since 1.3
360 */
361
362 public static final int TRUETYPE_FONT = 0;
363
364 /**
365 * Identify a font resource of type TYPE1.
366 * Used to specify a Type1 font resource to the
367 * {@link #createFont} method.
368 * @since 1.5
369 */
370 public static final int TYPE1_FONT = 1;
371
372 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300373 * The logical name of this {@code Font}, as passed to the
J. Duke319a3b92007-12-01 00:00:00 +0000374 * constructor.
Henry Jenea9a7a82014-06-10 16:18:54 -0700375 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +0000376 *
377 * @serial
378 * @see #getName
379 */
380 protected String name;
381
382 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300383 * The style of this {@code Font}, as passed to the constructor.
J. Duke319a3b92007-12-01 00:00:00 +0000384 * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
Henry Jenea9a7a82014-06-10 16:18:54 -0700385 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +0000386 *
387 * @serial
388 * @see #getStyle()
389 */
390 protected int style;
391
392 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300393 * The point size of this {@code Font}, rounded to integer.
Henry Jenea9a7a82014-06-10 16:18:54 -0700394 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +0000395 *
396 * @serial
397 * @see #getSize()
398 */
399 protected int size;
400
401 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300402 * The point size of this {@code Font} in {@code float}.
J. Duke319a3b92007-12-01 00:00:00 +0000403 *
404 * @serial
405 * @see #getSize()
406 * @see #getSize2D()
407 */
408 protected float pointSize;
409
410 /**
411 * The platform specific font information.
412 */
413 private transient FontPeer peer;
414 private transient long pData; // native JDK1.1 font pointer
415 private transient Font2DHandle font2DHandle;
416
417 private transient AttributeValues values;
418 private transient boolean hasLayoutAttributes;
419
420 /*
421 * If the origin of a Font is a created font then this attribute
422 * must be set on all derived fonts too.
423 */
424 private transient boolean createdFont = false;
425
426 /*
427 * This is true if the font transform is not identity. It
428 * is used to avoid unnecessary instantiation of an AffineTransform.
429 */
430 private transient boolean nonIdentityTx;
431
432 /*
433 * A cached value used when a transform is required for internal
434 * use. This must not be exposed to callers since AffineTransform
435 * is mutable.
436 */
437 private static final AffineTransform identityTx = new AffineTransform();
438
439 /*
440 * JDK 1.1 serialVersionUID
441 */
442 private static final long serialVersionUID = -4206021311591459213L;
443
444 /**
Sergey Bylokhovb9aead12015-04-17 16:54:13 +0300445 * Gets the peer of this {@code Font}.
446 *
447 * @return the peer of the {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +0000448 */
Sergey Bylokhovb9aead12015-04-17 16:54:13 +0300449 private FontPeer getFontPeer() {
J. Duke319a3b92007-12-01 00:00:00 +0000450 if(peer == null) {
451 Toolkit tk = Toolkit.getDefaultToolkit();
Sergey Bylokhov66344452015-04-17 17:01:24 +0300452 if (tk instanceof ComponentFactory) {
453 peer = ((ComponentFactory) tk).getFontPeer(name, style);
454 }
J. Duke319a3b92007-12-01 00:00:00 +0000455 }
456 return peer;
457 }
458
459 /**
460 * Return the AttributeValues object associated with this
461 * font. Most of the time, the internal object is null.
462 * If required, it will be created from the 'standard'
463 * state on the font. Only non-default values will be
464 * set in the AttributeValues object.
465 *
466 * <p>Since the AttributeValues object is mutable, and it
467 * is cached in the font, care must be taken to ensure that
468 * it is not mutated.
469 */
470 private AttributeValues getAttributeValues() {
471 if (values == null) {
Phil Race886c5162009-06-22 14:10:09 -0700472 AttributeValues valuesTmp = new AttributeValues();
473 valuesTmp.setFamily(name);
474 valuesTmp.setSize(pointSize); // expects the float value.
J. Duke319a3b92007-12-01 00:00:00 +0000475
476 if ((style & BOLD) != 0) {
Phil Race886c5162009-06-22 14:10:09 -0700477 valuesTmp.setWeight(2); // WEIGHT_BOLD
J. Duke319a3b92007-12-01 00:00:00 +0000478 }
479
480 if ((style & ITALIC) != 0) {
Phil Race886c5162009-06-22 14:10:09 -0700481 valuesTmp.setPosture(.2f); // POSTURE_OBLIQUE
J. Duke319a3b92007-12-01 00:00:00 +0000482 }
Phil Race886c5162009-06-22 14:10:09 -0700483 valuesTmp.defineAll(PRIMARY_MASK); // for streaming compatibility
484 values = valuesTmp;
J. Duke319a3b92007-12-01 00:00:00 +0000485 }
486
487 return values;
488 }
489
490 private Font2D getFont2D() {
Roman Kennkeeb125532009-08-07 18:31:11 +0200491 FontManager fm = FontManagerFactory.getInstance();
492 if (fm.usingPerAppContextComposites() &&
J. Duke319a3b92007-12-01 00:00:00 +0000493 font2DHandle != null &&
494 font2DHandle.font2D instanceof CompositeFont &&
495 ((CompositeFont)(font2DHandle.font2D)).isStdComposite()) {
Roman Kennkeeb125532009-08-07 18:31:11 +0200496 return fm.findFont2D(name, style,
J. Duke319a3b92007-12-01 00:00:00 +0000497 FontManager.LOGICAL_FALLBACK);
498 } else if (font2DHandle == null) {
499 font2DHandle =
Roman Kennkeeb125532009-08-07 18:31:11 +0200500 fm.findFont2D(name, style,
501 FontManager.LOGICAL_FALLBACK).handle;
J. Duke319a3b92007-12-01 00:00:00 +0000502 }
503 /* Do not cache the de-referenced font2D. It must be explicitly
504 * de-referenced to pick up a valid font in the event that the
505 * original one is marked invalid
506 */
507 return font2DHandle.font2D;
508 }
509
510 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300511 * Creates a new {@code Font} from the specified name, style and
J. Duke319a3b92007-12-01 00:00:00 +0000512 * point size.
513 * <p>
514 * The font name can be a font face name or a font family name.
515 * It is used together with the style to find an appropriate font face.
516 * When a font family name is specified, the style argument is used to
517 * select the most appropriate face from the family. When a font face
518 * name is specified, the face's style and the style argument are
519 * merged to locate the best matching font from the same family.
520 * For example if face name "Arial Bold" is specified with style
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300521 * {@code Font.ITALIC}, the font system looks for a face in the
J. Duke319a3b92007-12-01 00:00:00 +0000522 * "Arial" family that is bold and italic, and may associate the font
523 * instance with the physical font face "Arial Bold Italic".
524 * The style argument is merged with the specified face's style, not
525 * added or subtracted.
526 * This means, specifying a bold face and a bold style does not
527 * double-embolden the font, and specifying a bold face and a plain
528 * style does not lighten the font.
529 * <p>
530 * If no face for the requested style can be found, the font system
531 * may apply algorithmic styling to achieve the desired style.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300532 * For example, if {@code ITALIC} is requested, but no italic
J. Duke319a3b92007-12-01 00:00:00 +0000533 * face is available, glyphs from the plain face may be algorithmically
534 * obliqued (slanted).
535 * <p>
536 * Font name lookup is case insensitive, using the case folding
537 * rules of the US locale.
538 * <p>
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300539 * If the {@code name} parameter represents something other than a
J. Duke319a3b92007-12-01 00:00:00 +0000540 * logical font, i.e. is interpreted as a physical font face or family, and
541 * this cannot be mapped by the implementation to a physical font or a
542 * compatible alternative, then the font system will map the Font
543 * instance to "Dialog", such that for example, the family as reported
544 * by {@link #getFamily() getFamily} will be "Dialog".
J. Duke319a3b92007-12-01 00:00:00 +0000545 *
546 * @param name the font name. This can be a font face name or a font
547 * family name, and may represent either a logical font or a physical
548 * font found in this {@code GraphicsEnvironment}.
549 * The family names for logical fonts are: Dialog, DialogInput,
550 * Monospaced, Serif, or SansSerif. Pre-defined String constants exist
551 * for all of these names, for example, {@code DIALOG}. If {@code name} is
552 * {@code null}, the <em>logical font name</em> of the new
553 * {@code Font} as returned by {@code getName()} is set to
554 * the name "Default".
555 * @param style the style constant for the {@code Font}
556 * The style argument is an integer bitmask that may
557 * be {@code PLAIN}, or a bitwise union of {@code BOLD} and/or
558 * {@code ITALIC} (for example, {@code ITALIC} or {@code BOLD|ITALIC}).
559 * If the style argument does not conform to one of the expected
560 * integer bitmasks then the style is set to {@code PLAIN}.
561 * @param size the point size of the {@code Font}
562 * @see GraphicsEnvironment#getAllFonts
563 * @see GraphicsEnvironment#getAvailableFontFamilyNames
Henry Jenea9a7a82014-06-10 16:18:54 -0700564 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +0000565 */
566 public Font(String name, int style, int size) {
567 this.name = (name != null) ? name : "Default";
568 this.style = (style & ~0x03) == 0 ? style : 0;
569 this.size = size;
570 this.pointSize = size;
571 }
572
573 private Font(String name, int style, float sizePts) {
574 this.name = (name != null) ? name : "Default";
575 this.style = (style & ~0x03) == 0 ? style : 0;
576 this.size = (int)(sizePts + 0.5);
577 this.pointSize = sizePts;
578 }
579
580 /* This constructor is used by deriveFont when attributes is null */
581 private Font(String name, int style, float sizePts,
582 boolean created, Font2DHandle handle) {
583 this(name, style, sizePts);
584 this.createdFont = created;
585 /* Fonts created from a stream will use the same font2D instance
586 * as the parent.
587 * One exception is that if the derived font is requested to be
588 * in a different style, then also check if its a CompositeFont
589 * and if so build a new CompositeFont from components of that style.
590 * CompositeFonts can only be marked as "created" if they are used
591 * to add fall backs to a physical font. And non-composites are
592 * always from "Font.createFont()" and shouldn't get this treatment.
593 */
594 if (created) {
595 if (handle.font2D instanceof CompositeFont &&
596 handle.font2D.getStyle() != style) {
Roman Kennkeeb125532009-08-07 18:31:11 +0200597 FontManager fm = FontManagerFactory.getInstance();
598 this.font2DHandle = fm.getNewComposite(null, style, handle);
J. Duke319a3b92007-12-01 00:00:00 +0000599 } else {
600 this.font2DHandle = handle;
601 }
602 }
603 }
604
605 /* used to implement Font.createFont */
Phil Racec357cbe2009-01-05 11:28:43 -0800606 private Font(File fontFile, int fontFormat,
607 boolean isCopy, CreatedFontTracker tracker)
J. Duke319a3b92007-12-01 00:00:00 +0000608 throws FontFormatException {
609 this.createdFont = true;
610 /* Font2D instances created by this method track their font file
611 * so that when the Font2D is GC'd it can also remove the file.
612 */
Roman Kennkeeb125532009-08-07 18:31:11 +0200613 FontManager fm = FontManagerFactory.getInstance();
Phil Racedd439c92016-03-22 14:46:48 -0700614 Font2D[] fonts =
615 fm.createFont2D(fontFile, fontFormat, false, isCopy, tracker);
616 this.font2DHandle = fonts[0].handle;
J. Duke319a3b92007-12-01 00:00:00 +0000617 this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
618 this.style = Font.PLAIN;
619 this.size = 1;
620 this.pointSize = 1f;
621 }
622
623 /* This constructor is used when one font is derived from another.
624 * Fonts created from a stream will use the same font2D instance as the
625 * parent. They can be distinguished because the "created" argument
626 * will be "true". Since there is no way to recreate these fonts they
627 * need to have the handle to the underlying font2D passed in.
628 * "created" is also true when a special composite is referenced by the
629 * handle for essentially the same reasons.
630 * But when deriving a font in these cases two particular attributes
631 * need special attention: family/face and style.
632 * The "composites" in these cases need to be recreated with optimal
633 * fonts for the new values of family and style.
634 * For fonts created with createFont() these are treated differently.
635 * JDK can often synthesise a different style (bold from plain
636 * for example). For fonts created with "createFont" this is a reasonable
637 * solution but its also possible (although rare) to derive a font with a
638 * different family attribute. In this case JDK needs
639 * to break the tie with the original Font2D and find a new Font.
640 * The oldName and oldStyle are supplied so they can be compared with
641 * what the Font2D and the values. To speed things along :
642 * oldName == null will be interpreted as the name is unchanged.
643 * oldStyle = -1 will be interpreted as the style is unchanged.
644 * In these cases there is no need to interrogate "values".
645 */
646 private Font(AttributeValues values, String oldName, int oldStyle,
647 boolean created, Font2DHandle handle) {
648
649 this.createdFont = created;
650 if (created) {
651 this.font2DHandle = handle;
652
653 String newName = null;
654 if (oldName != null) {
655 newName = values.getFamily();
656 if (oldName.equals(newName)) newName = null;
657 }
658 int newStyle = 0;
659 if (oldStyle == -1) {
660 newStyle = -1;
661 } else {
662 if (values.getWeight() >= 2f) newStyle = BOLD;
663 if (values.getPosture() >= .2f) newStyle |= ITALIC;
664 if (oldStyle == newStyle) newStyle = -1;
665 }
666 if (handle.font2D instanceof CompositeFont) {
667 if (newStyle != -1 || newName != null) {
Roman Kennkeeb125532009-08-07 18:31:11 +0200668 FontManager fm = FontManagerFactory.getInstance();
J. Duke319a3b92007-12-01 00:00:00 +0000669 this.font2DHandle =
Roman Kennkeeb125532009-08-07 18:31:11 +0200670 fm.getNewComposite(newName, newStyle, handle);
J. Duke319a3b92007-12-01 00:00:00 +0000671 }
672 } else if (newName != null) {
673 this.createdFont = false;
674 this.font2DHandle = null;
675 }
676 }
677 initFromValues(values);
678 }
679
680 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300681 * Creates a new {@code Font} with the specified attributes.
J. Duke319a3b92007-12-01 00:00:00 +0000682 * Only keys defined in {@link java.awt.font.TextAttribute TextAttribute}
683 * are recognized. In addition the FONT attribute is
684 * not recognized by this constructor
685 * (see {@link #getAvailableAttributes}). Only attributes that have
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300686 * values of valid types will affect the new {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +0000687 * <p>
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300688 * If {@code attributes} is {@code null}, a new
689 * {@code Font} is initialized with default values.
J. Duke319a3b92007-12-01 00:00:00 +0000690 * @see java.awt.font.TextAttribute
691 * @param attributes the attributes to assign to the new
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300692 * {@code Font}, or {@code null}
J. Duke319a3b92007-12-01 00:00:00 +0000693 */
694 public Font(Map<? extends Attribute, ?> attributes) {
695 initFromValues(AttributeValues.fromMap(attributes, RECOGNIZED_MASK));
696 }
697
698 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300699 * Creates a new {@code Font} from the specified {@code font}.
J. Duke319a3b92007-12-01 00:00:00 +0000700 * This constructor is intended for use by subclasses.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300701 * @param font from which to create this {@code Font}.
702 * @throws NullPointerException if {@code font} is null
J. Duke319a3b92007-12-01 00:00:00 +0000703 * @since 1.6
704 */
705 protected Font(Font font) {
706 if (font.values != null) {
707 initFromValues(font.getAttributeValues().clone());
708 } else {
709 this.name = font.name;
710 this.style = font.style;
711 this.size = font.size;
712 this.pointSize = font.pointSize;
713 }
714 this.font2DHandle = font.font2DHandle;
715 this.createdFont = font.createdFont;
716 }
717
718 /**
719 * Font recognizes all attributes except FONT.
720 */
721 private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL
722 & ~AttributeValues.getMask(EFONT);
723
724 /**
725 * These attributes are considered primary by the FONT attribute.
726 */
727 private static final int PRIMARY_MASK =
728 AttributeValues.getMask(EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE,
729 ETRANSFORM, ESUPERSCRIPT, ETRACKING);
730
731 /**
732 * These attributes are considered secondary by the FONT attribute.
733 */
734 private static final int SECONDARY_MASK =
735 RECOGNIZED_MASK & ~PRIMARY_MASK;
736
737 /**
738 * These attributes are handled by layout.
739 */
740 private static final int LAYOUT_MASK =
741 AttributeValues.getMask(ECHAR_REPLACEMENT, EFOREGROUND, EBACKGROUND,
742 EUNDERLINE, ESTRIKETHROUGH, ERUN_DIRECTION,
743 EBIDI_EMBEDDING, EJUSTIFICATION,
744 EINPUT_METHOD_HIGHLIGHT, EINPUT_METHOD_UNDERLINE,
745 ESWAP_COLORS, ENUMERIC_SHAPING, EKERNING,
Phil Raceb3d58352008-04-10 09:05:01 -0700746 ELIGATURES, ETRACKING, ESUPERSCRIPT);
J. Duke319a3b92007-12-01 00:00:00 +0000747
748 private static final int EXTRA_MASK =
749 AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH);
750
751 /**
752 * Initialize the standard Font fields from the values object.
753 */
754 private void initFromValues(AttributeValues values) {
755 this.values = values;
756 values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility
757
758 this.name = values.getFamily();
759 this.pointSize = values.getSize();
760 this.size = (int)(values.getSize() + 0.5);
761 if (values.getWeight() >= 2f) this.style |= BOLD; // not == 2f
762 if (values.getPosture() >= .2f) this.style |= ITALIC; // not == .2f
763
764 this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
765 this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
766 }
767
768 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300769 * Returns a {@code Font} appropriate to the attributes.
770 * If {@code attributes} contains a {@code FONT} attribute
771 * with a valid {@code Font} as its value, it will be
J. Duke319a3b92007-12-01 00:00:00 +0000772 * merged with any remaining attributes. See
773 * {@link java.awt.font.TextAttribute#FONT} for more
774 * information.
775 *
776 * @param attributes the attributes to assign to the new
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300777 * {@code Font}
778 * @return a new {@code Font} created with the specified
J. Duke319a3b92007-12-01 00:00:00 +0000779 * attributes
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300780 * @throws NullPointerException if {@code attributes} is null.
J. Duke319a3b92007-12-01 00:00:00 +0000781 * @since 1.2
782 * @see java.awt.font.TextAttribute
783 */
784 public static Font getFont(Map<? extends Attribute, ?> attributes) {
785 // optimize for two cases:
786 // 1) FONT attribute, and nothing else
787 // 2) attributes, but no FONT
788
789 // avoid turning the attributemap into a regular map for no reason
790 if (attributes instanceof AttributeMap &&
791 ((AttributeMap)attributes).getValues() != null) {
792 AttributeValues values = ((AttributeMap)attributes).getValues();
793 if (values.isNonDefault(EFONT)) {
794 Font font = values.getFont();
795 if (!values.anyDefined(SECONDARY_MASK)) {
796 return font;
797 }
798 // merge
799 values = font.getAttributeValues().clone();
800 values.merge(attributes, SECONDARY_MASK);
801 return new Font(values, font.name, font.style,
802 font.createdFont, font.font2DHandle);
803 }
804 return new Font(attributes);
805 }
806
807 Font font = (Font)attributes.get(TextAttribute.FONT);
808 if (font != null) {
809 if (attributes.size() > 1) { // oh well, check for anything else
810 AttributeValues values = font.getAttributeValues().clone();
811 values.merge(attributes, SECONDARY_MASK);
812 return new Font(values, font.name, font.style,
813 font.createdFont, font.font2DHandle);
814 }
815
816 return font;
817 }
818
819 return new Font(attributes);
820 }
821
822 /**
Phil Racec357cbe2009-01-05 11:28:43 -0800823 * Used with the byte count tracker for fonts created from streams.
824 * If a thread can create temp files anyway, no point in counting
825 * font bytes.
826 */
827 private static boolean hasTempPermission() {
828
829 if (System.getSecurityManager() == null) {
830 return true;
831 }
832 File f = null;
833 boolean hasPerm = false;
834 try {
Rob McKennac3a386e2012-04-11 17:47:56 -0700835 f = Files.createTempFile("+~JT", ".tmp").toFile();
Phil Racec357cbe2009-01-05 11:28:43 -0800836 f.delete();
837 f = null;
838 hasPerm = true;
839 } catch (Throwable t) {
840 /* inc. any kind of SecurityException */
841 }
842 return hasPerm;
843 }
844
Phil Racedd439c92016-03-22 14:46:48 -0700845
846 /**
847 * Returns a new array of {@code Font} decoded from the specified stream.
848 * The returned {@code Font[]} will have at least one element.
849 * <p>
850 * The explicit purpose of this variation on the
851 * {@code createFont(int, InputStream)} method is to support font
852 * sources which represent a TrueType/OpenType font collection and
853 * be able to return all individual fonts in that collection.
854 * Consequently this method will throw {@code FontFormatException}
855 * if the data source does not contain at least one TrueType/OpenType
856 * font. The same exception will also be thrown if any of the fonts in
857 * the collection does not contain the required font tables.
858 * <p>
859 * The condition "at least one", allows for the stream to represent
860 * a single OpenType/TrueType font. That is, it does not have to be
861 * a collection.
862 * Each {@code Font} element of the returned array is
863 * created with a point size of 1 and style {@link #PLAIN PLAIN}.
864 * This base font can then be used with the {@code deriveFont}
865 * methods in this class to derive new {@code Font} objects with
866 * varying sizes, styles, transforms and font features.
867 * <p>This method does not close the {@link InputStream}.
868 * <p>
869 * To make each {@code Font} available to Font constructors it
870 * must be registered in the {@code GraphicsEnvironment} by calling
871 * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
872 * @param fontStream an {@code InputStream} object representing the
873 * input data for the font or font collection.
874 * @return a new {@code Font[]}.
875 * @throws FontFormatException if the {@code fontStream} data does
876 * not contain the required font tables for any of the elements of
877 * the collection, or if it contains no fonts at all.
878 * @throws IOException if the {@code fontStream} cannot be completely read.
879 * @see GraphicsEnvironment#registerFont(Font)
880 * @since 9
881 */
882 public static Font[] createFonts(InputStream fontStream)
883 throws FontFormatException, IOException {
884
885 final int fontFormat = Font.TRUETYPE_FONT;
886 if (hasTempPermission()) {
887 return createFont0(fontFormat, fontStream, true, null);
888 }
889
890 // Otherwise, be extra conscious of pending temp file creation and
891 // resourcefully handle the temp file resources, among other things.
892 CreatedFontTracker tracker = CreatedFontTracker.getTracker();
893 boolean acquired = false;
894 try {
895 acquired = tracker.acquirePermit();
896 if (!acquired) {
897 throw new IOException("Timed out waiting for resources.");
898 }
899 return createFont0(fontFormat, fontStream, true, tracker);
900 } catch (InterruptedException e) {
901 throw new IOException("Problem reading font data.");
902 } finally {
903 if (acquired) {
904 tracker.releasePermit();
905 }
906 }
907 }
908
909 /* used to implement Font.createFont */
910 private Font(Font2D font2D) {
911
912 this.createdFont = true;
913 this.font2DHandle = font2D.handle;
914 this.name = font2D.getFontName(Locale.getDefault());
915 this.style = Font.PLAIN;
916 this.size = 1;
917 this.pointSize = 1f;
918 }
919
920 /**
921 * Returns a new array of {@code Font} decoded from the specified file.
922 * The returned {@code Font[]} will have at least one element.
923 * <p>
924 * The explicit purpose of this variation on the
925 * {@code createFont(int, File)} method is to support font
926 * sources which represent a TrueType/OpenType font collection and
927 * be able to return all individual fonts in that collection.
928 * Consequently this method will throw {@code FontFormatException}
929 * if the data source does not contain at least one TrueType/OpenType
930 * font. The same exception will also be thrown if any of the fonts in
931 * the collection does not contain the required font tables.
932 * <p>
933 * The condition "at least one", allows for the stream to represent
934 * a single OpenType/TrueType font. That is, it does not have to be
935 * a collection.
936 * Each {@code Font} element of the returned array is
937 * created with a point size of 1 and style {@link #PLAIN PLAIN}.
938 * This base font can then be used with the {@code deriveFont}
939 * methods in this class to derive new {@code Font} objects with
940 * varying sizes, styles, transforms and font features.
941 * <p>
942 * To make each {@code Font} available to Font constructors it
943 * must be registered in the {@code GraphicsEnvironment} by calling
944 * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
945 * @param fontFile a {@code File} object containing the
946 * input data for the font or font collection.
947 * @return a new {@code Font[]}.
948 * @throws FontFormatException if the {@code File} does
949 * not contain the required font tables for any of the elements of
950 * the collection, or if it contains no fonts at all.
951 * @throws IOException if the {@code fontFile} cannot be read.
952 * @see GraphicsEnvironment#registerFont(Font)
953 * @since 9
954 */
955 public static Font[] createFonts(File fontFile)
956 throws FontFormatException, IOException
957 {
958 int fontFormat = Font.TRUETYPE_FONT;
959 fontFile = checkFontFile(fontFormat, fontFile);
960 FontManager fm = FontManagerFactory.getInstance();
961 Font2D[] font2DArr =
962 fm.createFont2D(fontFile, fontFormat, true, false, null);
963 int num = font2DArr.length;
964 Font[] fonts = new Font[num];
965 for (int i = 0; i < num; i++) {
966 fonts[i] = new Font(font2DArr[i]);
967 }
968 return fonts;
969 }
970
Phil Racec357cbe2009-01-05 11:28:43 -0800971 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300972 * Returns a new {@code Font} using the specified font type
973 * and input data. The new {@code Font} is
J. Duke319a3b92007-12-01 00:00:00 +0000974 * created with a point size of 1 and style {@link #PLAIN PLAIN}.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300975 * This base font can then be used with the {@code deriveFont}
976 * methods in this class to derive new {@code Font} objects with
J. Duke319a3b92007-12-01 00:00:00 +0000977 * varying sizes, styles, transforms and font features. This
978 * method does not close the {@link InputStream}.
979 * <p>
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300980 * To make the {@code Font} available to Font constructors the
981 * returned {@code Font} must be registered in the
982 * {@code GraphicsEnvironment} by calling
J. Duke319a3b92007-12-01 00:00:00 +0000983 * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300984 * @param fontFormat the type of the {@code Font}, which is
J. Duke319a3b92007-12-01 00:00:00 +0000985 * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified.
986 * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300987 * @param fontStream an {@code InputStream} object representing the
J. Duke319a3b92007-12-01 00:00:00 +0000988 * input data for the font.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300989 * @return a new {@code Font} created with the specified font type.
990 * @throws IllegalArgumentException if {@code fontFormat} is not
991 * {@code TRUETYPE_FONT} or {@code TYPE1_FONT}.
992 * @throws FontFormatException if the {@code fontStream} data does
J. Duke319a3b92007-12-01 00:00:00 +0000993 * not contain the required font tables for the specified format.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +0300994 * @throws IOException if the {@code fontStream}
J. Duke319a3b92007-12-01 00:00:00 +0000995 * cannot be completely read.
996 * @see GraphicsEnvironment#registerFont(Font)
997 * @since 1.3
998 */
999 public static Font createFont(int fontFormat, InputStream fontStream)
1000 throws java.awt.FontFormatException, java.io.IOException {
1001
Jia-Hong Chen28011632013-03-29 10:01:19 -07001002 if (hasTempPermission()) {
Phil Racedd439c92016-03-22 14:46:48 -07001003 return createFont0(fontFormat, fontStream, false, null)[0];
Jia-Hong Chen28011632013-03-29 10:01:19 -07001004 }
1005
1006 // Otherwise, be extra conscious of pending temp file creation and
1007 // resourcefully handle the temp file resources, among other things.
1008 CreatedFontTracker tracker = CreatedFontTracker.getTracker();
1009 boolean acquired = false;
1010 try {
1011 acquired = tracker.acquirePermit();
1012 if (!acquired) {
1013 throw new IOException("Timed out waiting for resources.");
1014 }
Phil Racedd439c92016-03-22 14:46:48 -07001015 return createFont0(fontFormat, fontStream, false, tracker)[0];
Jia-Hong Chen28011632013-03-29 10:01:19 -07001016 } catch (InterruptedException e) {
1017 throw new IOException("Problem reading font data.");
1018 } finally {
1019 if (acquired) {
1020 tracker.releasePermit();
1021 }
1022 }
1023 }
1024
Phil Racedd439c92016-03-22 14:46:48 -07001025 private static Font[] createFont0(int fontFormat, InputStream fontStream,
1026 boolean allFonts,
1027 CreatedFontTracker tracker)
Jia-Hong Chen28011632013-03-29 10:01:19 -07001028 throws java.awt.FontFormatException, java.io.IOException {
1029
J. Duke319a3b92007-12-01 00:00:00 +00001030 if (fontFormat != Font.TRUETYPE_FONT &&
1031 fontFormat != Font.TYPE1_FONT) {
1032 throw new IllegalArgumentException ("font format not recognized");
1033 }
Phil Racec357cbe2009-01-05 11:28:43 -08001034 boolean copiedFontData = false;
Phil Racec357cbe2009-01-05 11:28:43 -08001035 try {
1036 final File tFile = AccessController.doPrivileged(
1037 new PrivilegedExceptionAction<File>() {
1038 public File run() throws IOException {
Rob McKennac3a386e2012-04-11 17:47:56 -07001039 return Files.createTempFile("+~JF", ".tmp").toFile();
Phil Racec357cbe2009-01-05 11:28:43 -08001040 }
1041 }
1042 );
Jia-Hong Chen28011632013-03-29 10:01:19 -07001043 if (tracker != null) {
1044 tracker.add(tFile);
1045 }
Phil Racec357cbe2009-01-05 11:28:43 -08001046
1047 int totalSize = 0;
Phil Racec357cbe2009-01-05 11:28:43 -08001048 try {
1049 final OutputStream outStream =
1050 AccessController.doPrivileged(
1051 new PrivilegedExceptionAction<OutputStream>() {
1052 public OutputStream run() throws IOException {
1053 return new FileOutputStream(tFile);
1054 }
1055 }
1056 );
Jia-Hong Chen28011632013-03-29 10:01:19 -07001057 if (tracker != null) {
1058 tracker.set(tFile, outStream);
Phil Racec357cbe2009-01-05 11:28:43 -08001059 }
1060 try {
1061 byte[] buf = new byte[8192];
1062 for (;;) {
1063 int bytesRead = fontStream.read(buf);
1064 if (bytesRead < 0) {
1065 break;
1066 }
1067 if (tracker != null) {
Oleg Pekhovskiy37047152011-12-19 15:21:35 +04001068 if (totalSize+bytesRead > CreatedFontTracker.MAX_FILE_SIZE) {
Phil Racec357cbe2009-01-05 11:28:43 -08001069 throw new IOException("File too big.");
1070 }
1071 if (totalSize+tracker.getNumBytes() >
Oleg Pekhovskiy37047152011-12-19 15:21:35 +04001072 CreatedFontTracker.MAX_TOTAL_BYTES)
Phil Racec357cbe2009-01-05 11:28:43 -08001073 {
1074 throw new IOException("Total files too big.");
1075 }
1076 totalSize += bytesRead;
1077 tracker.addBytes(bytesRead);
1078 }
1079 outStream.write(buf, 0, bytesRead);
1080 }
1081 /* don't close the input stream */
1082 } finally {
1083 outStream.close();
1084 }
1085 /* After all references to a Font2D are dropped, the file
1086 * will be removed. To support long-lived AppContexts,
1087 * we need to then decrement the byte count by the size
1088 * of the file.
1089 * If the data isn't a valid font, the implementation will
1090 * delete the tmp file and decrement the byte count
1091 * in the tracker object before returning from the
1092 * constructor, so we can set 'copiedFontData' to true here
1093 * without waiting for the results of that constructor.
1094 */
1095 copiedFontData = true;
Phil Racedd439c92016-03-22 14:46:48 -07001096 FontManager fm = FontManagerFactory.getInstance();
1097 Font2D[] font2DArr =
1098 fm.createFont2D(tFile, fontFormat, allFonts, true, tracker);
1099 int num = font2DArr.length;
1100 Font[] fonts = new Font[num];
1101 for (int i = 0; i < num; i++) {
1102 fonts[i] = new Font(font2DArr[i]);
1103 }
1104 return fonts;
Phil Racec357cbe2009-01-05 11:28:43 -08001105 } finally {
Jia-Hong Chen28011632013-03-29 10:01:19 -07001106 if (tracker != null) {
1107 tracker.remove(tFile);
1108 }
Phil Racec357cbe2009-01-05 11:28:43 -08001109 if (!copiedFontData) {
1110 if (tracker != null) {
1111 tracker.subBytes(totalSize);
1112 }
1113 AccessController.doPrivileged(
1114 new PrivilegedExceptionAction<Void>() {
1115 public Void run() {
1116 tFile.delete();
1117 return null;
1118 }
1119 }
1120 );
1121 }
1122 }
1123 } catch (Throwable t) {
1124 if (t instanceof FontFormatException) {
1125 throw (FontFormatException)t;
1126 }
1127 if (t instanceof IOException) {
1128 throw (IOException)t;
1129 }
1130 Throwable cause = t.getCause();
1131 if (cause instanceof FontFormatException) {
1132 throw (FontFormatException)cause;
1133 }
1134 throw new IOException("Problem reading font data.");
J. Duke319a3b92007-12-01 00:00:00 +00001135 }
1136 }
1137
1138 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001139 * Returns a new {@code Font} using the specified font type
1140 * and the specified font file. The new {@code Font} is
J. Duke319a3b92007-12-01 00:00:00 +00001141 * created with a point size of 1 and style {@link #PLAIN PLAIN}.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001142 * This base font can then be used with the {@code deriveFont}
1143 * methods in this class to derive new {@code Font} objects with
J. Duke319a3b92007-12-01 00:00:00 +00001144 * varying sizes, styles, transforms and font features.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001145 * @param fontFormat the type of the {@code Font}, which is
J. Duke319a3b92007-12-01 00:00:00 +00001146 * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is
1147 * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is
1148 * specified.
1149 * So long as the returned font, or its derived fonts are referenced
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001150 * the implementation may continue to access {@code fontFile}
J. Duke319a3b92007-12-01 00:00:00 +00001151 * to retrieve font data. Thus the results are undefined if the file
1152 * is changed, or becomes inaccessible.
1153 * <p>
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001154 * To make the {@code Font} available to Font constructors the
1155 * returned {@code Font} must be registered in the
1156 * {@code GraphicsEnvironment} by calling
J. Duke319a3b92007-12-01 00:00:00 +00001157 * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001158 * @param fontFile a {@code File} object representing the
J. Duke319a3b92007-12-01 00:00:00 +00001159 * input data for the font.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001160 * @return a new {@code Font} created with the specified font type.
1161 * @throws IllegalArgumentException if {@code fontFormat} is not
1162 * {@code TRUETYPE_FONT} or {@code TYPE1_FONT}.
1163 * @throws NullPointerException if {@code fontFile} is null.
1164 * @throws IOException if the {@code fontFile} cannot be read.
1165 * @throws FontFormatException if {@code fontFile} does
J. Duke319a3b92007-12-01 00:00:00 +00001166 * not contain the required font tables for the specified format.
1167 * @throws SecurityException if the executing code does not have
1168 * permission to read from the file.
1169 * @see GraphicsEnvironment#registerFont(Font)
1170 * @since 1.5
1171 */
1172 public static Font createFont(int fontFormat, File fontFile)
1173 throws java.awt.FontFormatException, java.io.IOException {
Phil Racec357cbe2009-01-05 11:28:43 -08001174
Phil Racedd439c92016-03-22 14:46:48 -07001175 fontFile = checkFontFile(fontFormat, fontFile);
1176 return new Font(fontFile, fontFormat, false, null);
1177 }
1178
1179 private static File checkFontFile(int fontFormat, File fontFile)
1180 throws FontFormatException, IOException {
1181
Phil Racec357cbe2009-01-05 11:28:43 -08001182 fontFile = new File(fontFile.getPath());
1183
J. Duke319a3b92007-12-01 00:00:00 +00001184 if (fontFormat != Font.TRUETYPE_FONT &&
1185 fontFormat != Font.TYPE1_FONT) {
1186 throw new IllegalArgumentException ("font format not recognized");
1187 }
1188 SecurityManager sm = System.getSecurityManager();
1189 if (sm != null) {
1190 FilePermission filePermission =
1191 new FilePermission(fontFile.getPath(), "read");
1192 sm.checkPermission(filePermission);
1193 }
1194 if (!fontFile.canRead()) {
1195 throw new IOException("Can't read " + fontFile);
1196 }
Phil Racedd439c92016-03-22 14:46:48 -07001197 return fontFile;
J. Duke319a3b92007-12-01 00:00:00 +00001198 }
1199
1200 /**
1201 * Returns a copy of the transform associated with this
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001202 * {@code Font}. This transform is not necessarily the one
J. Duke319a3b92007-12-01 00:00:00 +00001203 * used to construct the font. If the font has algorithmic
1204 * superscripting or width adjustment, this will be incorporated
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001205 * into the returned {@code AffineTransform}.
J. Duke319a3b92007-12-01 00:00:00 +00001206 * <p>
1207 * Typically, fonts will not be transformed. Clients generally
1208 * should call {@link #isTransformed} first, and only call this
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001209 * method if {@code isTransformed} returns true.
J. Duke319a3b92007-12-01 00:00:00 +00001210 *
1211 * @return an {@link AffineTransform} object representing the
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001212 * transform attribute of this {@code Font} object.
J. Duke319a3b92007-12-01 00:00:00 +00001213 */
1214 public AffineTransform getTransform() {
1215 /* The most common case is the identity transform. Most callers
1216 * should call isTransformed() first, to decide if they need to
1217 * get the transform, but some may not. Here we check to see
1218 * if we have a nonidentity transform, and only do the work to
1219 * fetch and/or compute it if so, otherwise we return a new
1220 * identity transform.
1221 *
1222 * Note that the transform is _not_ necessarily the same as
1223 * the transform passed in as an Attribute in a Map, as the
1224 * transform returned will also reflect the effects of WIDTH and
1225 * SUPERSCRIPT attributes. Clients who want the actual transform
1226 * need to call getRequestedAttributes.
1227 */
1228 if (nonIdentityTx) {
1229 AttributeValues values = getAttributeValues();
1230
1231 AffineTransform at = values.isNonDefault(ETRANSFORM)
1232 ? new AffineTransform(values.getTransform())
1233 : new AffineTransform();
1234
1235 if (values.getSuperscript() != 0) {
1236 // can't get ascent and descent here, recursive call to this fn,
1237 // so use pointsize
1238 // let users combine super- and sub-scripting
1239
1240 int superscript = values.getSuperscript();
1241
1242 double trans = 0;
1243 int n = 0;
1244 boolean up = superscript > 0;
1245 int sign = up ? -1 : 1;
1246 int ss = up ? superscript : -superscript;
1247
1248 while ((ss & 7) > n) {
1249 int newn = ss & 7;
1250 trans += sign * (ssinfo[newn] - ssinfo[n]);
1251 ss >>= 3;
1252 sign = -sign;
1253 n = newn;
1254 }
1255 trans *= pointSize;
1256 double scale = Math.pow(2./3., n);
1257
1258 at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
1259 at.scale(scale, scale);
1260
1261 // note on placement and italics
1262 // We preconcatenate the transform because we don't want to translate along
1263 // the italic angle, but purely perpendicular to the baseline. While this
1264 // looks ok for superscripts, it can lead subscripts to stack on each other
1265 // and bring the following text too close. The way we deal with potential
1266 // collisions that can occur in the case of italics is by adjusting the
1267 // horizontal spacing of the adjacent glyphvectors. Examine the italic
1268 // angle of both vectors, if one is non-zero, compute the minimum ascent
1269 // and descent, and then the x position at each for each vector along its
1270 // italic angle starting from its (offset) baseline. Compute the difference
1271 // between the x positions and use the maximum difference to adjust the
1272 // position of the right gv.
1273 }
1274
1275 if (values.isNonDefault(EWIDTH)) {
1276 at.scale(values.getWidth(), 1f);
1277 }
1278
1279 return at;
1280 }
1281
1282 return new AffineTransform();
1283 }
1284
1285 // x = r^0 + r^1 + r^2... r^n
1286 // rx = r^1 + r^2 + r^3... r^(n+1)
1287 // x - rx = r^0 - r^(n+1)
1288 // x (1 - r) = r^0 - r^(n+1)
1289 // x = (r^0 - r^(n+1)) / (1 - r)
1290 // x = (1 - r^(n+1)) / (1 - r)
1291
1292 // scale ratio is 2/3
1293 // trans = 1/2 of ascent * x
1294 // assume ascent is 3/4 of point size
1295
1296 private static final float[] ssinfo = {
1297 0.0f,
1298 0.375f,
1299 0.625f,
1300 0.7916667f,
1301 0.9027778f,
1302 0.9768519f,
1303 1.0262346f,
1304 1.0591564f,
1305 };
1306
1307 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001308 * Returns the family name of this {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00001309 *
1310 * <p>The family name of a font is font specific. Two fonts such as
1311 * Helvetica Italic and Helvetica Bold have the same family name,
1312 * <i>Helvetica</i>, whereas their font face names are
1313 * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
1314 * available family names may be obtained by using the
1315 * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1316 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001317 * <p>Use {@code getName} to get the logical name of the font.
1318 * Use {@code getFontName} to get the font face name of the font.
1319 * @return a {@code String} that is the family name of this
1320 * {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00001321 *
1322 * @see #getName
1323 * @see #getFontName
Henry Jenea9a7a82014-06-10 16:18:54 -07001324 * @since 1.1
J. Duke319a3b92007-12-01 00:00:00 +00001325 */
1326 public String getFamily() {
1327 return getFamily_NoClientCode();
1328 }
1329 // NOTE: This method is called by privileged threads.
1330 // We implement this functionality in a package-private
1331 // method to insure that it cannot be overridden by client
1332 // subclasses.
1333 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1334 final String getFamily_NoClientCode() {
1335 return getFamily(Locale.getDefault());
1336 }
1337
1338 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001339 * Returns the family name of this {@code Font}, localized for
J. Duke319a3b92007-12-01 00:00:00 +00001340 * the specified locale.
1341 *
1342 * <p>The family name of a font is font specific. Two fonts such as
1343 * Helvetica Italic and Helvetica Bold have the same family name,
1344 * <i>Helvetica</i>, whereas their font face names are
1345 * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
1346 * available family names may be obtained by using the
1347 * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1348 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001349 * <p>Use {@code getFontName} to get the font face name of the font.
J. Duke319a3b92007-12-01 00:00:00 +00001350 * @param l locale for which to get the family name
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001351 * @return a {@code String} representing the family name of the
J. Duke319a3b92007-12-01 00:00:00 +00001352 * font, localized for the specified locale.
1353 * @see #getFontName
1354 * @see java.util.Locale
1355 * @since 1.2
1356 */
1357 public String getFamily(Locale l) {
1358 if (l == null) {
1359 throw new NullPointerException("null locale doesn't mean default");
1360 }
1361 return getFont2D().getFamilyName(l);
1362 }
1363
1364 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001365 * Returns the postscript name of this {@code Font}.
1366 * Use {@code getFamily} to get the family name of the font.
1367 * Use {@code getFontName} to get the font face name of the font.
1368 * @return a {@code String} representing the postscript name of
1369 * this {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00001370 * @since 1.2
1371 */
1372 public String getPSName() {
1373 return getFont2D().getPostscriptName();
1374 }
1375
1376 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001377 * Returns the logical name of this {@code Font}.
1378 * Use {@code getFamily} to get the family name of the font.
1379 * Use {@code getFontName} to get the font face name of the font.
1380 * @return a {@code String} representing the logical name of
1381 * this {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00001382 * @see #getFamily
1383 * @see #getFontName
Henry Jenea9a7a82014-06-10 16:18:54 -07001384 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +00001385 */
1386 public String getName() {
1387 return name;
1388 }
1389
1390 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001391 * Returns the font face name of this {@code Font}. For example,
J. Duke319a3b92007-12-01 00:00:00 +00001392 * Helvetica Bold could be returned as a font face name.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001393 * Use {@code getFamily} to get the family name of the font.
1394 * Use {@code getName} to get the logical name of the font.
1395 * @return a {@code String} representing the font face name of
1396 * this {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00001397 * @see #getFamily
1398 * @see #getName
1399 * @since 1.2
1400 */
1401 public String getFontName() {
1402 return getFontName(Locale.getDefault());
1403 }
1404
1405 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001406 * Returns the font face name of the {@code Font}, localized
J. Duke319a3b92007-12-01 00:00:00 +00001407 * for the specified locale. For example, Helvetica Fett could be
1408 * returned as the font face name.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001409 * Use {@code getFamily} to get the family name of the font.
J. Duke319a3b92007-12-01 00:00:00 +00001410 * @param l a locale for which to get the font face name
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001411 * @return a {@code String} representing the font face name,
J. Duke319a3b92007-12-01 00:00:00 +00001412 * localized for the specified locale.
1413 * @see #getFamily
1414 * @see java.util.Locale
1415 */
1416 public String getFontName(Locale l) {
1417 if (l == null) {
1418 throw new NullPointerException("null locale doesn't mean default");
1419 }
1420 return getFont2D().getFontName(l);
1421 }
1422
1423 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001424 * Returns the style of this {@code Font}. The style can be
J. Duke319a3b92007-12-01 00:00:00 +00001425 * PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001426 * @return the style of this {@code Font}
J. Duke319a3b92007-12-01 00:00:00 +00001427 * @see #isPlain
1428 * @see #isBold
1429 * @see #isItalic
Henry Jenea9a7a82014-06-10 16:18:54 -07001430 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +00001431 */
1432 public int getStyle() {
1433 return style;
1434 }
1435
1436 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001437 * Returns the point size of this {@code Font}, rounded to
J. Duke319a3b92007-12-01 00:00:00 +00001438 * an integer.
1439 * Most users are familiar with the idea of using <i>point size</i> to
1440 * specify the size of glyphs in a font. This point size defines a
1441 * measurement between the baseline of one line to the baseline of the
1442 * following line in a single spaced text document. The point size is
1443 * based on <i>typographic points</i>, approximately 1/72 of an inch.
1444 * <p>
1445 * The Java(tm)2D API adopts the convention that one point is
1446 * equivalent to one unit in user coordinates. When using a
1447 * normalized transform for converting user space coordinates to
1448 * device space coordinates 72 user
1449 * space units equal 1 inch in device space. In this case one point
1450 * is 1/72 of an inch.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001451 * @return the point size of this {@code Font} in 1/72 of an
J. Duke319a3b92007-12-01 00:00:00 +00001452 * inch units.
1453 * @see #getSize2D
1454 * @see GraphicsConfiguration#getDefaultTransform
1455 * @see GraphicsConfiguration#getNormalizingTransform
Henry Jenea9a7a82014-06-10 16:18:54 -07001456 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +00001457 */
1458 public int getSize() {
1459 return size;
1460 }
1461
1462 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001463 * Returns the point size of this {@code Font} in
1464 * {@code float} value.
1465 * @return the point size of this {@code Font} as a
1466 * {@code float} value.
J. Duke319a3b92007-12-01 00:00:00 +00001467 * @see #getSize
1468 * @since 1.2
1469 */
1470 public float getSize2D() {
1471 return pointSize;
1472 }
1473
1474 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001475 * Indicates whether or not this {@code Font} object's style is
J. Duke319a3b92007-12-01 00:00:00 +00001476 * PLAIN.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001477 * @return {@code true} if this {@code Font} has a
Sergey Malenkovc500ed62013-10-29 17:01:06 +04001478 * PLAIN style;
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001479 * {@code false} otherwise.
J. Duke319a3b92007-12-01 00:00:00 +00001480 * @see java.awt.Font#getStyle
Henry Jenea9a7a82014-06-10 16:18:54 -07001481 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +00001482 */
1483 public boolean isPlain() {
1484 return style == 0;
1485 }
1486
1487 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001488 * Indicates whether or not this {@code Font} object's style is
J. Duke319a3b92007-12-01 00:00:00 +00001489 * BOLD.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001490 * @return {@code true} if this {@code Font} object's
J. Duke319a3b92007-12-01 00:00:00 +00001491 * style is BOLD;
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001492 * {@code false} otherwise.
J. Duke319a3b92007-12-01 00:00:00 +00001493 * @see java.awt.Font#getStyle
Henry Jenea9a7a82014-06-10 16:18:54 -07001494 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +00001495 */
1496 public boolean isBold() {
1497 return (style & BOLD) != 0;
1498 }
1499
1500 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001501 * Indicates whether or not this {@code Font} object's style is
J. Duke319a3b92007-12-01 00:00:00 +00001502 * ITALIC.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001503 * @return {@code true} if this {@code Font} object's
J. Duke319a3b92007-12-01 00:00:00 +00001504 * style is ITALIC;
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001505 * {@code false} otherwise.
J. Duke319a3b92007-12-01 00:00:00 +00001506 * @see java.awt.Font#getStyle
Henry Jenea9a7a82014-06-10 16:18:54 -07001507 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +00001508 */
1509 public boolean isItalic() {
1510 return (style & ITALIC) != 0;
1511 }
1512
1513 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001514 * Indicates whether or not this {@code Font} object has a
J. Duke319a3b92007-12-01 00:00:00 +00001515 * transform that affects its size in addition to the Size
1516 * attribute.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001517 * @return {@code true} if this {@code Font} object
J. Duke319a3b92007-12-01 00:00:00 +00001518 * has a non-identity AffineTransform attribute.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001519 * {@code false} otherwise.
J. Duke319a3b92007-12-01 00:00:00 +00001520 * @see java.awt.Font#getTransform
1521 * @since 1.4
1522 */
1523 public boolean isTransformed() {
1524 return nonIdentityTx;
1525 }
1526
1527 /**
1528 * Return true if this Font contains attributes that require extra
1529 * layout processing.
1530 * @return true if the font has layout attributes
1531 * @since 1.6
1532 */
1533 public boolean hasLayoutAttributes() {
1534 return hasLayoutAttributes;
1535 }
1536
1537 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001538 * Returns a {@code Font} object from the system properties list.
1539 * {@code nm} is treated as the name of a system property to be
1540 * obtained. The {@code String} value of this property is then
1541 * interpreted as a {@code Font} object according to the
1542 * specification of {@code Font.decode(String)}
J. Duke319a3b92007-12-01 00:00:00 +00001543 * If the specified property is not found, or the executing code does
1544 * not have permission to read the property, null is returned instead.
1545 *
1546 * @param nm the property name
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001547 * @return a {@code Font} object that the property name
J. Duke319a3b92007-12-01 00:00:00 +00001548 * describes, or null if no such property exists.
1549 * @throws NullPointerException if nm is null.
1550 * @since 1.2
1551 * @see #decode(String)
1552 */
1553 public static Font getFont(String nm) {
1554 return getFont(nm, null);
1555 }
1556
1557 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001558 * Returns the {@code Font} that the {@code str}
J. Duke319a3b92007-12-01 00:00:00 +00001559 * argument describes.
1560 * To ensure that this method returns the desired Font,
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001561 * format the {@code str} parameter in
J. Duke319a3b92007-12-01 00:00:00 +00001562 * one of these ways
Roger Riggse2a0a412013-12-03 16:20:44 -05001563 *
J. Duke319a3b92007-12-01 00:00:00 +00001564 * <ul>
1565 * <li><em>fontname-style-pointsize</em>
1566 * <li><em>fontname-pointsize</em>
1567 * <li><em>fontname-style</em>
1568 * <li><em>fontname</em>
1569 * <li><em>fontname style pointsize</em>
1570 * <li><em>fontname pointsize</em>
1571 * <li><em>fontname style</em>
1572 * <li><em>fontname</em>
1573 * </ul>
1574 * in which <i>style</i> is one of the four
1575 * case-insensitive strings:
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001576 * {@code "PLAIN"}, {@code "BOLD"}, {@code "BOLDITALIC"}, or
1577 * {@code "ITALIC"}, and pointsize is a positive decimal integer
J. Duke319a3b92007-12-01 00:00:00 +00001578 * representation of the point size.
1579 * For example, if you want a font that is Arial, bold, with
1580 * a point size of 18, you would call this method with:
1581 * "Arial-BOLD-18".
1582 * This is equivalent to calling the Font constructor :
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001583 * {@code new Font("Arial", Font.BOLD, 18);}
J. Duke319a3b92007-12-01 00:00:00 +00001584 * and the values are interpreted as specified by that constructor.
1585 * <p>
1586 * A valid trailing decimal field is always interpreted as the pointsize.
1587 * Therefore a fontname containing a trailing decimal value should not
1588 * be used in the fontname only form.
1589 * <p>
1590 * If a style name field is not one of the valid style strings, it is
1591 * interpreted as part of the font name, and the default style is used.
1592 * <p>
1593 * Only one of ' ' or '-' may be used to separate fields in the input.
1594 * The identified separator is the one closest to the end of the string
1595 * which separates a valid pointsize, or a valid style name from
1596 * the rest of the string.
1597 * Null (empty) pointsize and style fields are treated
1598 * as valid fields with the default value for that field.
1599 *<p>
1600 * Some font names may include the separator characters ' ' or '-'.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001601 * If {@code str} is not formed with 3 components, e.g. such that
1602 * {@code style} or {@code pointsize} fields are not present in
1603 * {@code str}, and {@code fontname} also contains a
J. Duke319a3b92007-12-01 00:00:00 +00001604 * character determined to be the separator character
1605 * then these characters where they appear as intended to be part of
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001606 * {@code fontname} may instead be interpreted as separators
J. Duke319a3b92007-12-01 00:00:00 +00001607 * so the font name may not be properly recognised.
1608 *
1609 * <p>
1610 * The default size is 12 and the default style is PLAIN.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001611 * If {@code str} does not specify a valid size, the returned
1612 * {@code Font} has a size of 12. If {@code str} does not
J. Duke319a3b92007-12-01 00:00:00 +00001613 * specify a valid style, the returned Font has a style of PLAIN.
1614 * If you do not specify a valid font name in
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001615 * the {@code str} argument, this method will return
J. Duke319a3b92007-12-01 00:00:00 +00001616 * a font with the family name "Dialog".
1617 * To determine what font family names are available on
1618 * your system, use the
1619 * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001620 * If {@code str} is {@code null}, a new {@code Font}
J. Duke319a3b92007-12-01 00:00:00 +00001621 * is returned with the family name "Dialog", a size of 12 and a
1622 * PLAIN style.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001623 * @param str the name of the font, or {@code null}
1624 * @return the {@code Font} object that {@code str}
1625 * describes, or a new default {@code Font} if
1626 * {@code str} is {@code null}.
J. Duke319a3b92007-12-01 00:00:00 +00001627 * @see #getFamily
Henry Jenea9a7a82014-06-10 16:18:54 -07001628 * @since 1.1
J. Duke319a3b92007-12-01 00:00:00 +00001629 */
1630 public static Font decode(String str) {
1631 String fontName = str;
1632 String styleName = "";
1633 int fontSize = 12;
1634 int fontStyle = Font.PLAIN;
1635
1636 if (str == null) {
1637 return new Font(DIALOG, fontStyle, fontSize);
1638 }
1639
1640 int lastHyphen = str.lastIndexOf('-');
1641 int lastSpace = str.lastIndexOf(' ');
1642 char sepChar = (lastHyphen > lastSpace) ? '-' : ' ';
1643 int sizeIndex = str.lastIndexOf(sepChar);
1644 int styleIndex = str.lastIndexOf(sepChar, sizeIndex-1);
1645 int strlen = str.length();
1646
1647 if (sizeIndex > 0 && sizeIndex+1 < strlen) {
1648 try {
1649 fontSize =
1650 Integer.valueOf(str.substring(sizeIndex+1)).intValue();
1651 if (fontSize <= 0) {
1652 fontSize = 12;
1653 }
1654 } catch (NumberFormatException e) {
1655 /* It wasn't a valid size, if we didn't also find the
1656 * start of the style string perhaps this is the style */
1657 styleIndex = sizeIndex;
1658 sizeIndex = strlen;
1659 if (str.charAt(sizeIndex-1) == sepChar) {
1660 sizeIndex--;
1661 }
1662 }
1663 }
1664
1665 if (styleIndex >= 0 && styleIndex+1 < strlen) {
1666 styleName = str.substring(styleIndex+1, sizeIndex);
1667 styleName = styleName.toLowerCase(Locale.ENGLISH);
1668 if (styleName.equals("bolditalic")) {
1669 fontStyle = Font.BOLD | Font.ITALIC;
1670 } else if (styleName.equals("italic")) {
1671 fontStyle = Font.ITALIC;
1672 } else if (styleName.equals("bold")) {
1673 fontStyle = Font.BOLD;
1674 } else if (styleName.equals("plain")) {
1675 fontStyle = Font.PLAIN;
1676 } else {
1677 /* this string isn't any of the expected styles, so
1678 * assume its part of the font name
1679 */
1680 styleIndex = sizeIndex;
1681 if (str.charAt(styleIndex-1) == sepChar) {
1682 styleIndex--;
1683 }
1684 }
1685 fontName = str.substring(0, styleIndex);
1686
1687 } else {
1688 int fontEnd = strlen;
1689 if (styleIndex > 0) {
1690 fontEnd = styleIndex;
1691 } else if (sizeIndex > 0) {
1692 fontEnd = sizeIndex;
1693 }
1694 if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) {
1695 fontEnd--;
1696 }
1697 fontName = str.substring(0, fontEnd);
1698 }
1699
1700 return new Font(fontName, fontStyle, fontSize);
1701 }
1702
1703 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001704 * Gets the specified {@code Font} from the system properties
1705 * list. As in the {@code getProperty} method of
1706 * {@code System}, the first
J. Duke319a3b92007-12-01 00:00:00 +00001707 * argument is treated as the name of a system property to be
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001708 * obtained. The {@code String} value of this property is then
1709 * interpreted as a {@code Font} object.
J. Duke319a3b92007-12-01 00:00:00 +00001710 * <p>
1711 * The property value should be one of the forms accepted by
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001712 * {@code Font.decode(String)}
J. Duke319a3b92007-12-01 00:00:00 +00001713 * If the specified property is not found, or the executing code does not
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001714 * have permission to read the property, the {@code font}
J. Duke319a3b92007-12-01 00:00:00 +00001715 * argument is returned instead.
1716 * @param nm the case-insensitive property name
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001717 * @param font a default {@code Font} to return if property
1718 * {@code nm} is not defined
1719 * @return the {@code Font} value of the property.
J. Duke319a3b92007-12-01 00:00:00 +00001720 * @throws NullPointerException if nm is null.
1721 * @see #decode(String)
1722 */
1723 public static Font getFont(String nm, Font font) {
1724 String str = null;
1725 try {
1726 str =System.getProperty(nm);
1727 } catch(SecurityException e) {
1728 }
1729 if (str == null) {
1730 return font;
1731 }
1732 return decode ( str );
1733 }
1734
1735 transient int hash;
1736 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001737 * Returns a hashcode for this {@code Font}.
1738 * @return a hashcode value for this {@code Font}.
Henry Jenea9a7a82014-06-10 16:18:54 -07001739 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +00001740 */
1741 public int hashCode() {
1742 if (hash == 0) {
1743 hash = name.hashCode() ^ style ^ size;
1744 /* It is possible many fonts differ only in transform.
1745 * So include the transform in the hash calculation.
1746 * nonIdentityTx is set whenever there is a transform in
1747 * 'values'. The tests for null are required because it can
1748 * also be set for other reasons.
1749 */
1750 if (nonIdentityTx &&
1751 values != null && values.getTransform() != null) {
1752 hash ^= values.getTransform().hashCode();
1753 }
1754 }
1755 return hash;
1756 }
1757
1758 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001759 * Compares this {@code Font} object to the specified
1760 * {@code Object}.
1761 * @param obj the {@code Object} to compare
1762 * @return {@code true} if the objects are the same
1763 * or if the argument is a {@code Font} object
J. Duke319a3b92007-12-01 00:00:00 +00001764 * describing the same font as this object;
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001765 * {@code false} otherwise.
Henry Jenea9a7a82014-06-10 16:18:54 -07001766 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +00001767 */
1768 public boolean equals(Object obj) {
1769 if (obj == this) {
1770 return true;
1771 }
1772
1773 if (obj != null) {
1774 try {
1775 Font font = (Font)obj;
1776 if (size == font.size &&
1777 style == font.style &&
1778 nonIdentityTx == font.nonIdentityTx &&
1779 hasLayoutAttributes == font.hasLayoutAttributes &&
1780 pointSize == font.pointSize &&
1781 name.equals(font.name)) {
1782
1783 /* 'values' is usually initialized lazily, except when
1784 * the font is constructed from a Map, or derived using
1785 * a Map or other values. So if only one font has
1786 * the field initialized we need to initialize it in
1787 * the other instance and compare.
1788 */
1789 if (values == null) {
1790 if (font.values == null) {
1791 return true;
1792 } else {
1793 return getAttributeValues().equals(font.values);
1794 }
1795 } else {
1796 return values.equals(font.getAttributeValues());
1797 }
1798 }
1799 }
1800 catch (ClassCastException e) {
1801 }
1802 }
1803 return false;
1804 }
1805
1806 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001807 * Converts this {@code Font} object to a {@code String}
J. Duke319a3b92007-12-01 00:00:00 +00001808 * representation.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001809 * @return a {@code String} representation of this
1810 * {@code Font} object.
Henry Jenea9a7a82014-06-10 16:18:54 -07001811 * @since 1.0
J. Duke319a3b92007-12-01 00:00:00 +00001812 */
1813 // NOTE: This method may be called by privileged threads.
1814 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1815 public String toString() {
1816 String strStyle;
1817
1818 if (isBold()) {
1819 strStyle = isItalic() ? "bolditalic" : "bold";
1820 } else {
1821 strStyle = isItalic() ? "italic" : "plain";
1822 }
1823
1824 return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" +
1825 strStyle + ",size=" + size + "]";
1826 } // toString()
1827
1828
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001829 /** Serialization support. A {@code readObject}
Pavel Rappo8be77ee2014-09-17 16:14:12 +04001830 * method is necessary because the constructor creates
J. Duke319a3b92007-12-01 00:00:00 +00001831 * the font's peer, and we can't serialize the peer.
1832 * Similarly the computed font "family" may be different
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001833 * at {@code readObject} time than at
1834 * {@code writeObject} time. An integer version is
J. Duke319a3b92007-12-01 00:00:00 +00001835 * written so that future versions of this class will be
1836 * able to recognize serialized output from this one.
1837 */
1838 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001839 * The {@code Font} Serializable Data Form.
J. Duke319a3b92007-12-01 00:00:00 +00001840 *
1841 * @serial
1842 */
1843 private int fontSerializedDataVersion = 1;
1844
1845 /**
1846 * Writes default serializable fields to a stream.
1847 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001848 * @param s the {@code ObjectOutputStream} to write
J. Duke319a3b92007-12-01 00:00:00 +00001849 * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
1850 * @see #readObject(java.io.ObjectInputStream)
1851 */
1852 private void writeObject(java.io.ObjectOutputStream s)
1853 throws java.lang.ClassNotFoundException,
1854 java.io.IOException
1855 {
1856 if (values != null) {
1857 synchronized(values) {
1858 // transient
1859 fRequestedAttributes = values.toSerializableHashtable();
1860 s.defaultWriteObject();
1861 fRequestedAttributes = null;
1862 }
1863 } else {
1864 s.defaultWriteObject();
1865 }
1866 }
1867
1868 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001869 * Reads the {@code ObjectInputStream}.
J. Duke319a3b92007-12-01 00:00:00 +00001870 * Unrecognized keys or values will be ignored.
1871 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001872 * @param s the {@code ObjectInputStream} to read
J. Duke319a3b92007-12-01 00:00:00 +00001873 * @serial
1874 * @see #writeObject(java.io.ObjectOutputStream)
1875 */
1876 private void readObject(java.io.ObjectInputStream s)
1877 throws java.lang.ClassNotFoundException,
1878 java.io.IOException
1879 {
1880 s.defaultReadObject();
1881 if (pointSize == 0) {
1882 pointSize = (float)size;
1883 }
1884
1885 // Handle fRequestedAttributes.
1886 // in 1.5, we always streamed out the font values plus
1887 // TRANSFORM, SUPERSCRIPT, and WIDTH, regardless of whether the
1888 // values were default or not. In 1.6 we only stream out
1889 // defined values. So, 1.6 streams in from a 1.5 stream,
1890 // it check each of these values and 'undefines' it if the
1891 // value is the default.
1892
1893 if (fRequestedAttributes != null) {
1894 values = getAttributeValues(); // init
1895 AttributeValues extras =
1896 AttributeValues.fromSerializableHashtable(fRequestedAttributes);
1897 if (!AttributeValues.is16Hashtable(fRequestedAttributes)) {
1898 extras.unsetDefault(); // if legacy stream, undefine these
1899 }
1900 values = getAttributeValues().merge(extras);
1901 this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
1902 this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
1903
1904 fRequestedAttributes = null; // don't need it any more
1905 }
1906 }
1907
1908 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001909 * Returns the number of glyphs in this {@code Font}. Glyph codes
1910 * for this {@code Font} range from 0 to
1911 * {@code getNumGlyphs()} - 1.
1912 * @return the number of glyphs in this {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00001913 * @since 1.2
1914 */
1915 public int getNumGlyphs() {
1916 return getFont2D().getNumGlyphs();
1917 }
1918
1919 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001920 * Returns the glyphCode which is used when this {@code Font}
J. Duke319a3b92007-12-01 00:00:00 +00001921 * does not have a glyph for a specified unicode code point.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001922 * @return the glyphCode of this {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00001923 * @since 1.2
1924 */
1925 public int getMissingGlyphCode() {
1926 return getFont2D().getMissingGlyphCode();
1927 }
1928
1929 /**
1930 * Returns the baseline appropriate for displaying this character.
1931 * <p>
1932 * Large fonts can support different writing systems, and each system can
1933 * use a different baseline.
1934 * The character argument determines the writing system to use. Clients
1935 * should not assume all characters use the same baseline.
1936 *
1937 * @param c a character used to identify the writing system
1938 * @return the baseline appropriate for the specified character.
1939 * @see LineMetrics#getBaselineOffsets
1940 * @see #ROMAN_BASELINE
1941 * @see #CENTER_BASELINE
1942 * @see #HANGING_BASELINE
1943 * @since 1.2
1944 */
1945 public byte getBaselineFor(char c) {
1946 return getFont2D().getBaselineFor(c);
1947 }
1948
1949 /**
1950 * Returns a map of font attributes available in this
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001951 * {@code Font}. Attributes include things like ligatures and
J. Duke319a3b92007-12-01 00:00:00 +00001952 * glyph substitution.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001953 * @return the attributes map of this {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00001954 */
1955 public Map<TextAttribute,?> getAttributes(){
1956 return new AttributeMap(getAttributeValues());
1957 }
1958
1959 /**
1960 * Returns the keys of all the attributes supported by this
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001961 * {@code Font}. These attributes can be used to derive other
J. Duke319a3b92007-12-01 00:00:00 +00001962 * fonts.
1963 * @return an array containing the keys of all the attributes
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001964 * supported by this {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00001965 * @since 1.2
1966 */
1967 public Attribute[] getAvailableAttributes() {
1968 // FONT is not supported by Font
1969
1970 Attribute attributes[] = {
1971 TextAttribute.FAMILY,
1972 TextAttribute.WEIGHT,
1973 TextAttribute.WIDTH,
1974 TextAttribute.POSTURE,
1975 TextAttribute.SIZE,
1976 TextAttribute.TRANSFORM,
1977 TextAttribute.SUPERSCRIPT,
1978 TextAttribute.CHAR_REPLACEMENT,
1979 TextAttribute.FOREGROUND,
1980 TextAttribute.BACKGROUND,
1981 TextAttribute.UNDERLINE,
1982 TextAttribute.STRIKETHROUGH,
1983 TextAttribute.RUN_DIRECTION,
1984 TextAttribute.BIDI_EMBEDDING,
1985 TextAttribute.JUSTIFICATION,
1986 TextAttribute.INPUT_METHOD_HIGHLIGHT,
1987 TextAttribute.INPUT_METHOD_UNDERLINE,
1988 TextAttribute.SWAP_COLORS,
1989 TextAttribute.NUMERIC_SHAPING,
1990 TextAttribute.KERNING,
1991 TextAttribute.LIGATURES,
1992 TextAttribute.TRACKING,
1993 };
1994
1995 return attributes;
1996 }
1997
1998 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03001999 * Creates a new {@code Font} object by replicating this
2000 * {@code Font} object and applying a new style and size.
2001 * @param style the style for the new {@code Font}
2002 * @param size the size for the new {@code Font}
2003 * @return a new {@code Font} object.
J. Duke319a3b92007-12-01 00:00:00 +00002004 * @since 1.2
2005 */
2006 public Font deriveFont(int style, float size){
2007 if (values == null) {
2008 return new Font(name, style, size, createdFont, font2DHandle);
2009 }
2010 AttributeValues newValues = getAttributeValues().clone();
2011 int oldStyle = (this.style != style) ? this.style : -1;
2012 applyStyle(style, newValues);
2013 newValues.setSize(size);
2014 return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
2015 }
2016
2017 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002018 * Creates a new {@code Font} object by replicating this
2019 * {@code Font} object and applying a new style and transform.
2020 * @param style the style for the new {@code Font}
2021 * @param trans the {@code AffineTransform} associated with the
2022 * new {@code Font}
2023 * @return a new {@code Font} object.
2024 * @throws IllegalArgumentException if {@code trans} is
2025 * {@code null}
J. Duke319a3b92007-12-01 00:00:00 +00002026 * @since 1.2
2027 */
2028 public Font deriveFont(int style, AffineTransform trans){
2029 AttributeValues newValues = getAttributeValues().clone();
2030 int oldStyle = (this.style != style) ? this.style : -1;
2031 applyStyle(style, newValues);
2032 applyTransform(trans, newValues);
2033 return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
2034 }
2035
2036 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002037 * Creates a new {@code Font} object by replicating the current
2038 * {@code Font} object and applying a new size to it.
2039 * @param size the size for the new {@code Font}.
2040 * @return a new {@code Font} object.
J. Duke319a3b92007-12-01 00:00:00 +00002041 * @since 1.2
2042 */
2043 public Font deriveFont(float size){
2044 if (values == null) {
2045 return new Font(name, style, size, createdFont, font2DHandle);
2046 }
2047 AttributeValues newValues = getAttributeValues().clone();
2048 newValues.setSize(size);
2049 return new Font(newValues, null, -1, createdFont, font2DHandle);
2050 }
2051
2052 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002053 * Creates a new {@code Font} object by replicating the current
2054 * {@code Font} object and applying a new transform to it.
2055 * @param trans the {@code AffineTransform} associated with the
2056 * new {@code Font}
2057 * @return a new {@code Font} object.
2058 * @throws IllegalArgumentException if {@code trans} is
2059 * {@code null}
J. Duke319a3b92007-12-01 00:00:00 +00002060 * @since 1.2
2061 */
2062 public Font deriveFont(AffineTransform trans){
2063 AttributeValues newValues = getAttributeValues().clone();
2064 applyTransform(trans, newValues);
2065 return new Font(newValues, null, -1, createdFont, font2DHandle);
2066 }
2067
2068 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002069 * Creates a new {@code Font} object by replicating the current
2070 * {@code Font} object and applying a new style to it.
2071 * @param style the style for the new {@code Font}
2072 * @return a new {@code Font} object.
J. Duke319a3b92007-12-01 00:00:00 +00002073 * @since 1.2
2074 */
2075 public Font deriveFont(int style){
2076 if (values == null) {
2077 return new Font(name, style, size, createdFont, font2DHandle);
2078 }
2079 AttributeValues newValues = getAttributeValues().clone();
2080 int oldStyle = (this.style != style) ? this.style : -1;
2081 applyStyle(style, newValues);
2082 return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
2083 }
2084
2085 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002086 * Creates a new {@code Font} object by replicating the current
2087 * {@code Font} object and applying a new set of font attributes
J. Duke319a3b92007-12-01 00:00:00 +00002088 * to it.
2089 *
2090 * @param attributes a map of attributes enabled for the new
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002091 * {@code Font}
2092 * @return a new {@code Font} object.
J. Duke319a3b92007-12-01 00:00:00 +00002093 * @since 1.2
2094 */
2095 public Font deriveFont(Map<? extends Attribute, ?> attributes) {
2096 if (attributes == null) {
2097 return this;
2098 }
2099 AttributeValues newValues = getAttributeValues().clone();
2100 newValues.merge(attributes, RECOGNIZED_MASK);
2101
2102 return new Font(newValues, name, style, createdFont, font2DHandle);
2103 }
2104
2105 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002106 * Checks if this {@code Font} has a glyph for the specified
J. Duke319a3b92007-12-01 00:00:00 +00002107 * character.
2108 *
2109 * <p> <b>Note:</b> This method cannot handle <a
2110 * href="../../java/lang/Character.html#supplementary"> supplementary
2111 * characters</a>. To support all Unicode characters, including
2112 * supplementary characters, use the {@link #canDisplay(int)}
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002113 * method or {@code canDisplayUpTo} methods.
J. Duke319a3b92007-12-01 00:00:00 +00002114 *
2115 * @param c the character for which a glyph is needed
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002116 * @return {@code true} if this {@code Font} has a glyph for this
2117 * character; {@code false} otherwise.
J. Duke319a3b92007-12-01 00:00:00 +00002118 * @since 1.2
2119 */
2120 public boolean canDisplay(char c){
2121 return getFont2D().canDisplay(c);
2122 }
2123
2124 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002125 * Checks if this {@code Font} has a glyph for the specified
J. Duke319a3b92007-12-01 00:00:00 +00002126 * character.
2127 *
2128 * @param codePoint the character (Unicode code point) for which a glyph
2129 * is needed.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002130 * @return {@code true} if this {@code Font} has a glyph for the
2131 * character; {@code false} otherwise.
J. Duke319a3b92007-12-01 00:00:00 +00002132 * @throws IllegalArgumentException if the code point is not a valid Unicode
2133 * code point.
2134 * @see Character#isValidCodePoint(int)
2135 * @since 1.5
2136 */
2137 public boolean canDisplay(int codePoint) {
2138 if (!Character.isValidCodePoint(codePoint)) {
2139 throw new IllegalArgumentException("invalid code point: " +
2140 Integer.toHexString(codePoint));
2141 }
2142 return getFont2D().canDisplay(codePoint);
2143 }
2144
2145 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002146 * Indicates whether or not this {@code Font} can display a
2147 * specified {@code String}. For strings with Unicode encoding,
J. Duke319a3b92007-12-01 00:00:00 +00002148 * it is important to know if a particular font can display the
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002149 * string. This method returns an offset into the {@code String}
2150 * {@code str} which is the first character this
2151 * {@code Font} cannot display without using the missing glyph
2152 * code. If the {@code Font} can display all characters, -1 is
J. Duke319a3b92007-12-01 00:00:00 +00002153 * returned.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002154 * @param str a {@code String} object
2155 * @return an offset into {@code str} that points
2156 * to the first character in {@code str} that this
2157 * {@code Font} cannot display; or {@code -1} if
2158 * this {@code Font} can display all characters in
2159 * {@code str}.
J. Duke319a3b92007-12-01 00:00:00 +00002160 * @since 1.2
2161 */
2162 public int canDisplayUpTo(String str) {
Masayoshi Okutsu66ca7602011-02-23 14:09:23 +09002163 Font2D font2d = getFont2D();
2164 int len = str.length();
2165 for (int i = 0; i < len; i++) {
2166 char c = str.charAt(i);
2167 if (font2d.canDisplay(c)) {
2168 continue;
2169 }
2170 if (!Character.isHighSurrogate(c)) {
2171 return i;
2172 }
2173 if (!font2d.canDisplay(str.codePointAt(i))) {
2174 return i;
2175 }
2176 i++;
2177 }
2178 return -1;
J. Duke319a3b92007-12-01 00:00:00 +00002179 }
2180
2181 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002182 * Indicates whether or not this {@code Font} can display
2183 * the characters in the specified {@code text}
2184 * starting at {@code start} and ending at
2185 * {@code limit}. This method is a convenience overload.
2186 * @param text the specified array of {@code char} values
J. Duke319a3b92007-12-01 00:00:00 +00002187 * @param start the specified starting offset (in
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002188 * {@code char}s) into the specified array of
2189 * {@code char} values
J. Duke319a3b92007-12-01 00:00:00 +00002190 * @param limit the specified ending offset (in
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002191 * {@code char}s) into the specified array of
2192 * {@code char} values
2193 * @return an offset into {@code text} that points
2194 * to the first character in {@code text} that this
2195 * {@code Font} cannot display; or {@code -1} if
2196 * this {@code Font} can display all characters in
2197 * {@code text}.
J. Duke319a3b92007-12-01 00:00:00 +00002198 * @since 1.2
2199 */
2200 public int canDisplayUpTo(char[] text, int start, int limit) {
Masayoshi Okutsu66ca7602011-02-23 14:09:23 +09002201 Font2D font2d = getFont2D();
2202 for (int i = start; i < limit; i++) {
2203 char c = text[i];
2204 if (font2d.canDisplay(c)) {
2205 continue;
2206 }
2207 if (!Character.isHighSurrogate(c)) {
2208 return i;
2209 }
2210 if (!font2d.canDisplay(Character.codePointAt(text, i, limit))) {
2211 return i;
2212 }
2213 i++;
J. Duke319a3b92007-12-01 00:00:00 +00002214 }
Masayoshi Okutsu66ca7602011-02-23 14:09:23 +09002215 return -1;
J. Duke319a3b92007-12-01 00:00:00 +00002216 }
2217
2218 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002219 * Indicates whether or not this {@code Font} can display the
2220 * text specified by the {@code iter} starting at
2221 * {@code start} and ending at {@code limit}.
J. Duke319a3b92007-12-01 00:00:00 +00002222 *
2223 * @param iter a {@link CharacterIterator} object
2224 * @param start the specified starting offset into the specified
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002225 * {@code CharacterIterator}.
J. Duke319a3b92007-12-01 00:00:00 +00002226 * @param limit the specified ending offset into the specified
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002227 * {@code CharacterIterator}.
2228 * @return an offset into {@code iter} that points
2229 * to the first character in {@code iter} that this
2230 * {@code Font} cannot display; or {@code -1} if
2231 * this {@code Font} can display all characters in
2232 * {@code iter}.
J. Duke319a3b92007-12-01 00:00:00 +00002233 * @since 1.2
2234 */
2235 public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
Masayoshi Okutsu66ca7602011-02-23 14:09:23 +09002236 Font2D font2d = getFont2D();
2237 char c = iter.setIndex(start);
2238 for (int i = start; i < limit; i++, c = iter.next()) {
2239 if (font2d.canDisplay(c)) {
2240 continue;
2241 }
2242 if (!Character.isHighSurrogate(c)) {
2243 return i;
2244 }
2245 char c2 = iter.next();
2246 // c2 could be CharacterIterator.DONE which is not a low surrogate.
2247 if (!Character.isLowSurrogate(c2)) {
2248 return i;
2249 }
2250 if (!font2d.canDisplay(Character.toCodePoint(c, c2))) {
2251 return i;
2252 }
2253 i++;
J. Duke319a3b92007-12-01 00:00:00 +00002254 }
Masayoshi Okutsu66ca7602011-02-23 14:09:23 +09002255 return -1;
J. Duke319a3b92007-12-01 00:00:00 +00002256 }
2257
2258 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002259 * Returns the italic angle of this {@code Font}. The italic angle
J. Duke319a3b92007-12-01 00:00:00 +00002260 * is the inverse slope of the caret which best matches the posture of this
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002261 * {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00002262 * @see TextAttribute#POSTURE
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002263 * @return the angle of the ITALIC style of this {@code Font}.
J. Duke319a3b92007-12-01 00:00:00 +00002264 */
2265 public float getItalicAngle() {
2266 return getItalicAngle(null);
2267 }
2268
2269 /* The FRC hints don't affect the value of the italic angle but
2270 * we need to pass them in to look up a strike.
2271 * If we can pass in ones already being used it can prevent an extra
2272 * strike from being allocated. Note that since italic angle is
2273 * a property of the font, the font transform is needed not the
2274 * device transform. Finally, this is private but the only caller of this
2275 * in the JDK - and the only likely caller - is in this same class.
2276 */
2277 private float getItalicAngle(FontRenderContext frc) {
J. Duke319a3b92007-12-01 00:00:00 +00002278 Object aa, fm;
2279 if (frc == null) {
2280 aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
2281 fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
2282 } else {
2283 aa = frc.getAntiAliasingHint();
2284 fm = frc.getFractionalMetricsHint();
2285 }
Phil Race88cfc252008-04-28 09:59:35 -07002286 return getFont2D().getItalicAngle(this, identityTx, aa, fm);
J. Duke319a3b92007-12-01 00:00:00 +00002287 }
2288
2289 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002290 * Checks whether or not this {@code Font} has uniform
2291 * line metrics. A logical {@code Font} might be a
J. Duke319a3b92007-12-01 00:00:00 +00002292 * composite font, which means that it is composed of different
2293 * physical fonts to cover different code ranges. Each of these
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002294 * fonts might have different {@code LineMetrics}. If the
2295 * logical {@code Font} is a single
J. Duke319a3b92007-12-01 00:00:00 +00002296 * font then the metrics would be uniform.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002297 * @return {@code true} if this {@code Font} has
2298 * uniform line metrics; {@code false} otherwise.
J. Duke319a3b92007-12-01 00:00:00 +00002299 */
2300 public boolean hasUniformLineMetrics() {
2301 return false; // REMIND always safe, but prevents caller optimize
2302 }
2303
Oleg Pekhovskiy37047152011-12-19 15:21:35 +04002304 private transient SoftReference<FontLineMetrics> flmref;
J. Duke319a3b92007-12-01 00:00:00 +00002305 private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
2306 FontLineMetrics flm = null;
2307 if (flmref == null
Oleg Pekhovskiy37047152011-12-19 15:21:35 +04002308 || (flm = flmref.get()) == null
J. Duke319a3b92007-12-01 00:00:00 +00002309 || !flm.frc.equals(frc)) {
2310
2311 /* The device transform in the frc is not used in obtaining line
2312 * metrics, although it probably should be: REMIND find why not?
2313 * The font transform is used but its applied in getFontMetrics, so
2314 * just pass identity here
2315 */
2316 float [] metrics = new float[8];
2317 getFont2D().getFontMetrics(this, identityTx,
2318 frc.getAntiAliasingHint(),
2319 frc.getFractionalMetricsHint(),
2320 metrics);
2321 float ascent = metrics[0];
2322 float descent = metrics[1];
2323 float leading = metrics[2];
2324 float ssOffset = 0;
2325 if (values != null && values.getSuperscript() != 0) {
2326 ssOffset = (float)getTransform().getTranslateY();
2327 ascent -= ssOffset;
2328 descent += ssOffset;
2329 }
2330 float height = ascent + descent + leading;
2331
2332 int baselineIndex = 0; // need real index, assumes roman for everything
2333 // need real baselines eventually
2334 float[] baselineOffsets = { 0, (descent/2f - ascent) / 2f, -ascent };
2335
2336 float strikethroughOffset = metrics[4];
2337 float strikethroughThickness = metrics[5];
2338
2339 float underlineOffset = metrics[6];
2340 float underlineThickness = metrics[7];
2341
2342 float italicAngle = getItalicAngle(frc);
2343
2344 if (isTransformed()) {
2345 AffineTransform ctx = values.getCharTransform(); // extract rotation
2346 if (ctx != null) {
2347 Point2D.Float pt = new Point2D.Float();
2348 pt.setLocation(0, strikethroughOffset);
2349 ctx.deltaTransform(pt, pt);
2350 strikethroughOffset = pt.y;
2351 pt.setLocation(0, strikethroughThickness);
2352 ctx.deltaTransform(pt, pt);
2353 strikethroughThickness = pt.y;
2354 pt.setLocation(0, underlineOffset);
2355 ctx.deltaTransform(pt, pt);
2356 underlineOffset = pt.y;
2357 pt.setLocation(0, underlineThickness);
2358 ctx.deltaTransform(pt, pt);
2359 underlineThickness = pt.y;
2360 }
2361 }
2362 strikethroughOffset += ssOffset;
2363 underlineOffset += ssOffset;
2364
2365 CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height,
2366 baselineIndex, baselineOffsets,
2367 strikethroughOffset, strikethroughThickness,
2368 underlineOffset, underlineThickness,
2369 ssOffset, italicAngle);
2370
2371 flm = new FontLineMetrics(0, cm, frc);
Oleg Pekhovskiy37047152011-12-19 15:21:35 +04002372 flmref = new SoftReference<FontLineMetrics>(flm);
J. Duke319a3b92007-12-01 00:00:00 +00002373 }
2374
2375 return (FontLineMetrics)flm.clone();
2376 }
2377
2378 /**
2379 * Returns a {@link LineMetrics} object created with the specified
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002380 * {@code String} and {@link FontRenderContext}.
2381 * @param str the specified {@code String}
2382 * @param frc the specified {@code FontRenderContext}
2383 * @return a {@code LineMetrics} object created with the
2384 * specified {@code String} and {@link FontRenderContext}.
J. Duke319a3b92007-12-01 00:00:00 +00002385 */
2386 public LineMetrics getLineMetrics( String str, FontRenderContext frc) {
2387 FontLineMetrics flm = defaultLineMetrics(frc);
2388 flm.numchars = str.length();
2389 return flm;
2390 }
2391
2392 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002393 * Returns a {@code LineMetrics} object created with the
J. Duke319a3b92007-12-01 00:00:00 +00002394 * specified arguments.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002395 * @param str the specified {@code String}
2396 * @param beginIndex the initial offset of {@code str}
2397 * @param limit the end offset of {@code str}
2398 * @param frc the specified {@code FontRenderContext}
2399 * @return a {@code LineMetrics} object created with the
J. Duke319a3b92007-12-01 00:00:00 +00002400 * specified arguments.
2401 */
2402 public LineMetrics getLineMetrics( String str,
2403 int beginIndex, int limit,
2404 FontRenderContext frc) {
2405 FontLineMetrics flm = defaultLineMetrics(frc);
2406 int numChars = limit - beginIndex;
2407 flm.numchars = (numChars < 0)? 0: numChars;
2408 return flm;
2409 }
2410
2411 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002412 * Returns a {@code LineMetrics} object created with the
J. Duke319a3b92007-12-01 00:00:00 +00002413 * specified arguments.
2414 * @param chars an array of characters
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002415 * @param beginIndex the initial offset of {@code chars}
2416 * @param limit the end offset of {@code chars}
2417 * @param frc the specified {@code FontRenderContext}
2418 * @return a {@code LineMetrics} object created with the
J. Duke319a3b92007-12-01 00:00:00 +00002419 * specified arguments.
2420 */
2421 public LineMetrics getLineMetrics(char [] chars,
2422 int beginIndex, int limit,
2423 FontRenderContext frc) {
2424 FontLineMetrics flm = defaultLineMetrics(frc);
2425 int numChars = limit - beginIndex;
2426 flm.numchars = (numChars < 0)? 0: numChars;
2427 return flm;
2428 }
2429
2430 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002431 * Returns a {@code LineMetrics} object created with the
J. Duke319a3b92007-12-01 00:00:00 +00002432 * specified arguments.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002433 * @param ci the specified {@code CharacterIterator}
2434 * @param beginIndex the initial offset in {@code ci}
2435 * @param limit the end offset of {@code ci}
2436 * @param frc the specified {@code FontRenderContext}
2437 * @return a {@code LineMetrics} object created with the
J. Duke319a3b92007-12-01 00:00:00 +00002438 * specified arguments.
2439 */
2440 public LineMetrics getLineMetrics(CharacterIterator ci,
2441 int beginIndex, int limit,
2442 FontRenderContext frc) {
2443 FontLineMetrics flm = defaultLineMetrics(frc);
2444 int numChars = limit - beginIndex;
2445 flm.numchars = (numChars < 0)? 0: numChars;
2446 return flm;
2447 }
2448
2449 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002450 * Returns the logical bounds of the specified {@code String} in
2451 * the specified {@code FontRenderContext}. The logical bounds
J. Duke319a3b92007-12-01 00:00:00 +00002452 * contains the origin, ascent, advance, and height, which includes
2453 * the leading. The logical bounds does not always enclose all the
2454 * text. For example, in some languages and in some fonts, accent
2455 * marks can be positioned above the ascent or below the descent.
2456 * To obtain a visual bounding box, which encloses all the text,
2457 * use the {@link TextLayout#getBounds() getBounds} method of
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002458 * {@code TextLayout}.
J. Duke319a3b92007-12-01 00:00:00 +00002459 * <p>Note: The returned bounds is in baseline-relative coordinates
2460 * (see {@link java.awt.Font class notes}).
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002461 * @param str the specified {@code String}
2462 * @param frc the specified {@code FontRenderContext}
J. Duke319a3b92007-12-01 00:00:00 +00002463 * @return a {@link Rectangle2D} that is the bounding box of the
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002464 * specified {@code String} in the specified
2465 * {@code FontRenderContext}.
J. Duke319a3b92007-12-01 00:00:00 +00002466 * @see FontRenderContext
2467 * @see Font#createGlyphVector
2468 * @since 1.2
2469 */
2470 public Rectangle2D getStringBounds( String str, FontRenderContext frc) {
2471 char[] array = str.toCharArray();
2472 return getStringBounds(array, 0, array.length, frc);
2473 }
2474
2475 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002476 * Returns the logical bounds of the specified {@code String} in
2477 * the specified {@code FontRenderContext}. The logical bounds
J. Duke319a3b92007-12-01 00:00:00 +00002478 * contains the origin, ascent, advance, and height, which includes
2479 * the leading. The logical bounds does not always enclose all the
2480 * text. For example, in some languages and in some fonts, accent
2481 * marks can be positioned above the ascent or below the descent.
2482 * To obtain a visual bounding box, which encloses all the text,
2483 * use the {@link TextLayout#getBounds() getBounds} method of
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002484 * {@code TextLayout}.
J. Duke319a3b92007-12-01 00:00:00 +00002485 * <p>Note: The returned bounds is in baseline-relative coordinates
2486 * (see {@link java.awt.Font class notes}).
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002487 * @param str the specified {@code String}
2488 * @param beginIndex the initial offset of {@code str}
2489 * @param limit the end offset of {@code str}
2490 * @param frc the specified {@code FontRenderContext}
2491 * @return a {@code Rectangle2D} that is the bounding box of the
2492 * specified {@code String} in the specified
2493 * {@code FontRenderContext}.
2494 * @throws IndexOutOfBoundsException if {@code beginIndex} is
2495 * less than zero, or {@code limit} is greater than the
2496 * length of {@code str}, or {@code beginIndex}
2497 * is greater than {@code limit}.
J. Duke319a3b92007-12-01 00:00:00 +00002498 * @see FontRenderContext
2499 * @see Font#createGlyphVector
2500 * @since 1.2
2501 */
2502 public Rectangle2D getStringBounds( String str,
2503 int beginIndex, int limit,
2504 FontRenderContext frc) {
2505 String substr = str.substring(beginIndex, limit);
2506 return getStringBounds(substr, frc);
2507 }
2508
2509 /**
2510 * Returns the logical bounds of the specified array of characters
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002511 * in the specified {@code FontRenderContext}. The logical
J. Duke319a3b92007-12-01 00:00:00 +00002512 * bounds contains the origin, ascent, advance, and height, which
2513 * includes the leading. The logical bounds does not always enclose
2514 * all the text. For example, in some languages and in some fonts,
2515 * accent marks can be positioned above the ascent or below the
2516 * descent. To obtain a visual bounding box, which encloses all the
2517 * text, use the {@link TextLayout#getBounds() getBounds} method of
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002518 * {@code TextLayout}.
J. Duke319a3b92007-12-01 00:00:00 +00002519 * <p>Note: The returned bounds is in baseline-relative coordinates
2520 * (see {@link java.awt.Font class notes}).
2521 * @param chars an array of characters
2522 * @param beginIndex the initial offset in the array of
2523 * characters
2524 * @param limit the end offset in the array of characters
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002525 * @param frc the specified {@code FontRenderContext}
2526 * @return a {@code Rectangle2D} that is the bounding box of the
J. Duke319a3b92007-12-01 00:00:00 +00002527 * specified array of characters in the specified
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002528 * {@code FontRenderContext}.
2529 * @throws IndexOutOfBoundsException if {@code beginIndex} is
2530 * less than zero, or {@code limit} is greater than the
2531 * length of {@code chars}, or {@code beginIndex}
2532 * is greater than {@code limit}.
J. Duke319a3b92007-12-01 00:00:00 +00002533 * @see FontRenderContext
2534 * @see Font#createGlyphVector
2535 * @since 1.2
2536 */
2537 public Rectangle2D getStringBounds(char [] chars,
2538 int beginIndex, int limit,
2539 FontRenderContext frc) {
2540 if (beginIndex < 0) {
2541 throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
2542 }
2543 if (limit > chars.length) {
2544 throw new IndexOutOfBoundsException("limit: " + limit);
2545 }
2546 if (beginIndex > limit) {
2547 throw new IndexOutOfBoundsException("range length: " +
2548 (limit - beginIndex));
2549 }
2550
2551 // this code should be in textlayout
2552 // quick check for simple text, assume GV ok to use if simple
2553
2554 boolean simple = values == null ||
2555 (values.getKerning() == 0 && values.getLigatures() == 0 &&
2556 values.getBaselineTransform() == null);
2557 if (simple) {
Roman Kennkeeb125532009-08-07 18:31:11 +02002558 simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
J. Duke319a3b92007-12-01 00:00:00 +00002559 }
2560
2561 if (simple) {
2562 GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
2563 limit - beginIndex, frc);
2564 return gv.getLogicalBounds();
2565 } else {
2566 // need char array constructor on textlayout
2567 String str = new String(chars, beginIndex, limit - beginIndex);
2568 TextLayout tl = new TextLayout(str, this, frc);
2569 return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
2570 tl.getAscent() + tl.getDescent() +
2571 tl.getLeading());
2572 }
2573 }
2574
2575 /**
2576 * Returns the logical bounds of the characters indexed in the
2577 * specified {@link CharacterIterator} in the
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002578 * specified {@code FontRenderContext}. The logical bounds
J. Duke319a3b92007-12-01 00:00:00 +00002579 * contains the origin, ascent, advance, and height, which includes
2580 * the leading. The logical bounds does not always enclose all the
2581 * text. For example, in some languages and in some fonts, accent
2582 * marks can be positioned above the ascent or below the descent.
2583 * To obtain a visual bounding box, which encloses all the text,
2584 * use the {@link TextLayout#getBounds() getBounds} method of
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002585 * {@code TextLayout}.
J. Duke319a3b92007-12-01 00:00:00 +00002586 * <p>Note: The returned bounds is in baseline-relative coordinates
2587 * (see {@link java.awt.Font class notes}).
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002588 * @param ci the specified {@code CharacterIterator}
2589 * @param beginIndex the initial offset in {@code ci}
2590 * @param limit the end offset in {@code ci}
2591 * @param frc the specified {@code FontRenderContext}
2592 * @return a {@code Rectangle2D} that is the bounding box of the
2593 * characters indexed in the specified {@code CharacterIterator}
2594 * in the specified {@code FontRenderContext}.
J. Duke319a3b92007-12-01 00:00:00 +00002595 * @see FontRenderContext
2596 * @see Font#createGlyphVector
2597 * @since 1.2
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002598 * @throws IndexOutOfBoundsException if {@code beginIndex} is
2599 * less than the start index of {@code ci}, or
2600 * {@code limit} is greater than the end index of
2601 * {@code ci}, or {@code beginIndex} is greater
2602 * than {@code limit}
J. Duke319a3b92007-12-01 00:00:00 +00002603 */
2604 public Rectangle2D getStringBounds(CharacterIterator ci,
2605 int beginIndex, int limit,
2606 FontRenderContext frc) {
2607 int start = ci.getBeginIndex();
2608 int end = ci.getEndIndex();
2609
2610 if (beginIndex < start) {
2611 throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
2612 }
2613 if (limit > end) {
2614 throw new IndexOutOfBoundsException("limit: " + limit);
2615 }
2616 if (beginIndex > limit) {
2617 throw new IndexOutOfBoundsException("range length: " +
2618 (limit - beginIndex));
2619 }
2620
2621 char[] arr = new char[limit - beginIndex];
2622
2623 ci.setIndex(beginIndex);
2624 for(int idx = 0; idx < arr.length; idx++) {
2625 arr[idx] = ci.current();
2626 ci.next();
2627 }
2628
2629 return getStringBounds(arr,0,arr.length,frc);
2630 }
2631
2632 /**
2633 * Returns the bounds for the character with the maximum
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002634 * bounds as defined in the specified {@code FontRenderContext}.
J. Duke319a3b92007-12-01 00:00:00 +00002635 * <p>Note: The returned bounds is in baseline-relative coordinates
2636 * (see {@link java.awt.Font class notes}).
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002637 * @param frc the specified {@code FontRenderContext}
2638 * @return a {@code Rectangle2D} that is the bounding box
J. Duke319a3b92007-12-01 00:00:00 +00002639 * for the character with the maximum bounds.
2640 */
2641 public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
2642 float [] metrics = new float[4];
2643
2644 getFont2D().getFontMetrics(this, frc, metrics);
2645
2646 return new Rectangle2D.Float(0, -metrics[0],
2647 metrics[3],
2648 metrics[0] + metrics[1] + metrics[2]);
2649 }
2650
2651 /**
2652 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2653 * mapping characters to glyphs one-to-one based on the
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002654 * Unicode cmap in this {@code Font}. This method does no other
J. Duke319a3b92007-12-01 00:00:00 +00002655 * processing besides the mapping of glyphs to characters. This
2656 * means that this method is not useful for some scripts, such
2657 * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2658 * shaping, or ligature substitution.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002659 * @param frc the specified {@code FontRenderContext}
2660 * @param str the specified {@code String}
2661 * @return a new {@code GlyphVector} created with the
2662 * specified {@code String} and the specified
2663 * {@code FontRenderContext}.
J. Duke319a3b92007-12-01 00:00:00 +00002664 */
2665 public GlyphVector createGlyphVector(FontRenderContext frc, String str)
2666 {
2667 return (GlyphVector)new StandardGlyphVector(this, str, frc);
2668 }
2669
2670 /**
2671 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2672 * mapping characters to glyphs one-to-one based on the
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002673 * Unicode cmap in this {@code Font}. This method does no other
J. Duke319a3b92007-12-01 00:00:00 +00002674 * processing besides the mapping of glyphs to characters. This
2675 * means that this method is not useful for some scripts, such
2676 * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2677 * shaping, or ligature substitution.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002678 * @param frc the specified {@code FontRenderContext}
J. Duke319a3b92007-12-01 00:00:00 +00002679 * @param chars the specified array of characters
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002680 * @return a new {@code GlyphVector} created with the
J. Duke319a3b92007-12-01 00:00:00 +00002681 * specified array of characters and the specified
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002682 * {@code FontRenderContext}.
J. Duke319a3b92007-12-01 00:00:00 +00002683 */
2684 public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars)
2685 {
2686 return (GlyphVector)new StandardGlyphVector(this, chars, frc);
2687 }
2688
2689 /**
2690 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2691 * mapping the specified characters to glyphs one-to-one based on the
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002692 * Unicode cmap in this {@code Font}. This method does no other
J. Duke319a3b92007-12-01 00:00:00 +00002693 * processing besides the mapping of glyphs to characters. This
2694 * means that this method is not useful for some scripts, such
2695 * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2696 * shaping, or ligature substitution.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002697 * @param frc the specified {@code FontRenderContext}
2698 * @param ci the specified {@code CharacterIterator}
2699 * @return a new {@code GlyphVector} created with the
2700 * specified {@code CharacterIterator} and the specified
2701 * {@code FontRenderContext}.
J. Duke319a3b92007-12-01 00:00:00 +00002702 */
2703 public GlyphVector createGlyphVector( FontRenderContext frc,
2704 CharacterIterator ci)
2705 {
2706 return (GlyphVector)new StandardGlyphVector(this, ci, frc);
2707 }
2708
2709 /**
2710 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2711 * mapping characters to glyphs one-to-one based on the
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002712 * Unicode cmap in this {@code Font}. This method does no other
J. Duke319a3b92007-12-01 00:00:00 +00002713 * processing besides the mapping of glyphs to characters. This
2714 * means that this method is not useful for some scripts, such
2715 * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2716 * shaping, or ligature substitution.
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002717 * @param frc the specified {@code FontRenderContext}
J. Duke319a3b92007-12-01 00:00:00 +00002718 * @param glyphCodes the specified integer array
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002719 * @return a new {@code GlyphVector} created with the
J. Duke319a3b92007-12-01 00:00:00 +00002720 * specified integer array and the specified
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002721 * {@code FontRenderContext}.
J. Duke319a3b92007-12-01 00:00:00 +00002722 */
2723 public GlyphVector createGlyphVector( FontRenderContext frc,
2724 int [] glyphCodes)
2725 {
2726 return (GlyphVector)new StandardGlyphVector(this, glyphCodes, frc);
2727 }
2728
2729 /**
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002730 * Returns a new {@code GlyphVector} object, performing full
J. Duke319a3b92007-12-01 00:00:00 +00002731 * layout of the text if possible. Full layout is required for
2732 * complex text, such as Arabic or Hindi. Support for different
2733 * scripts depends on the font and implementation.
2734 * <p>
2735 * Layout requires bidi analysis, as performed by
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002736 * {@code Bidi}, and should only be performed on text that
J. Duke319a3b92007-12-01 00:00:00 +00002737 * has a uniform direction. The direction is indicated in the
2738 * flags parameter,by using LAYOUT_RIGHT_TO_LEFT to indicate a
2739 * right-to-left (Arabic and Hebrew) run direction, or
2740 * LAYOUT_LEFT_TO_RIGHT to indicate a left-to-right (English)
2741 * run direction.
2742 * <p>
2743 * In addition, some operations, such as Arabic shaping, require
2744 * context, so that the characters at the start and limit can have
2745 * the proper shapes. Sometimes the data in the buffer outside
2746 * the provided range does not have valid data. The values
2747 * LAYOUT_NO_START_CONTEXT and LAYOUT_NO_LIMIT_CONTEXT can be
2748 * added to the flags parameter to indicate that the text before
2749 * start, or after limit, respectively, should not be examined
2750 * for context.
2751 * <p>
2752 * All other values for the flags parameter are reserved.
2753 *
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002754 * @param frc the specified {@code FontRenderContext}
J. Duke319a3b92007-12-01 00:00:00 +00002755 * @param text the text to layout
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002756 * @param start the start of the text to use for the {@code GlyphVector}
2757 * @param limit the limit of the text to use for the {@code GlyphVector}
J. Duke319a3b92007-12-01 00:00:00 +00002758 * @param flags control flags as described above
Alexander Stepanov73fb68a2016-01-11 17:51:54 +03002759 * @return a new {@code GlyphVector} representing the text between
J. Duke319a3b92007-12-01 00:00:00 +00002760 * start and limit, with glyphs chosen and positioned so as to best represent
2761 * the text
2762 * @throws ArrayIndexOutOfBoundsException if start or limit is
2763 * out of bounds
2764 * @see java.text.Bidi
2765 * @see #LAYOUT_LEFT_TO_RIGHT
2766 * @see #LAYOUT_RIGHT_TO_LEFT
2767 * @see #LAYOUT_NO_START_CONTEXT
2768 * @see #LAYOUT_NO_LIMIT_CONTEXT
2769 * @since 1.4
2770 */
2771 public GlyphVector layoutGlyphVector(FontRenderContext frc,
2772 char[] text,
2773 int start,
2774 int limit,
2775 int flags) {
2776
2777 GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines
2778 StandardGlyphVector gv = gl.layout(this, frc, text,
2779 start, limit-start, flags, null);
2780 GlyphLayout.done(gl);
2781 return gv;
2782 }
2783
2784 /**
2785 * A flag to layoutGlyphVector indicating that text is left-to-right as
2786 * determined by Bidi analysis.
2787 */
2788 public static final int LAYOUT_LEFT_TO_RIGHT = 0;
2789
2790 /**
2791 * A flag to layoutGlyphVector indicating that text is right-to-left as
2792 * determined by Bidi analysis.
2793 */
2794 public static final int LAYOUT_RIGHT_TO_LEFT = 1;
2795
2796 /**
2797 * A flag to layoutGlyphVector indicating that text in the char array
2798 * before the indicated start should not be examined.
2799 */
2800 public static final int LAYOUT_NO_START_CONTEXT = 2;
2801
2802 /**
2803 * A flag to layoutGlyphVector indicating that text in the char array
2804 * after the indicated limit should not be examined.
2805 */
2806 public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
2807
2808
2809 private static void applyTransform(AffineTransform trans, AttributeValues values) {
2810 if (trans == null) {
2811 throw new IllegalArgumentException("transform must not be null");
2812 }
2813 values.setTransform(trans);
2814 }
2815
2816 private static void applyStyle(int style, AttributeValues values) {
2817 // WEIGHT_BOLD, WEIGHT_REGULAR
2818 values.setWeight((style & BOLD) != 0 ? 2f : 1f);
2819 // POSTURE_OBLIQUE, POSTURE_REGULAR
2820 values.setPosture((style & ITALIC) != 0 ? .2f : 0f);
2821 }
2822
2823 /*
2824 * Initialize JNI field and method IDs
2825 */
2826 private static native void initIDs();
2827}