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