Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.text;
027
028import java.io.FilePermission;
029import java.io.InputStream;
030import java.net.URL;
031import java.net.URLConnection;
032import java.util.List;
033
034import com.sun.javafx.beans.annotations.Default;
035import com.sun.javafx.tk.Toolkit;
036
037/**
038 * <p>The {@code Font} class represents fonts, which are used to render text on
039 * screen.
040 * <p>
041 * The size of a {@code Font} is described as being specified in points
042 * which are a real world measurement of approximately 1/72 inch.
043 * <p>
044 * Given that fonts scale with the rendering transform as determined
045 * by the transform attributes of a {@code Node} using the {@code Font}
046 * and its ancestors, the size will actually be relative to the local
047 * coordinate space of the node, which should provide coordinates
048 * similar to the size of a point if no scaling transforms are present
049 * in the environment of the node.
050 * Note that the real world distances specified by the default coordinate
051 * system only approximate point sizes as a rule of thumb and are typically
052 * defaulted to screen pixels for most displays.
053 * <p>
054 * For more information see {@link javafx.scene.Node} for more information
055 * on the default coordinate system 
056 */
057public final class Font {
058
059    private static final String DEFAULT_FAMILY = "System";
060    private static final String DEFAULT_FULLNAME = "System Regular";
061
062    /**
063     * The default font for this platform. This is used whenever a font is not
064     * specifically set on a Text node or overridden by CSS.
065     */
066    private static float defaultSystemFontSize = -1;
067    private static float getDefaultSystemFontSize() {
068        if (defaultSystemFontSize == -1) {
069            defaultSystemFontSize =
070                Toolkit.getToolkit().getFontLoader().getSystemFontSize();
071        }
072        return defaultSystemFontSize;
073    }
074
075    private static Font DEFAULT;
076    /**
077     * Gets the default font which will be from the family "System",
078     * and typically the style "Regular", and be of a size consistent
079     * with the user's desktop environment, to the extent that can
080     * be determined.
081     * @return the default font.
082     */
083    public static synchronized Font getDefault() {
084        if (DEFAULT == null) {
085            DEFAULT = new Font(DEFAULT_FULLNAME, getDefaultSystemFontSize());
086        }
087        return DEFAULT;
088    }
089
090    /**
091     * Gets all the font families installed on the user's system, including any
092     * application fonts or SDK fonts. This call has performance considerations
093     * as looking up all of the fonts may be an expensive operation the
094     * first time.
095     */
096    public static List<String> getFamilies() {
097        return Toolkit.getToolkit().getFontLoader().getFamilies();
098    }
099
100    /**
101     * Gets the names of all fonts that are installed on the users system,
102     * including any application fonts and SDK fonts.
103     * This call has performance considerations as
104     * looking up all of the fonts may be an expensive operation the first time.
105     */
106    public static List<String> getFontNames() {
107        return Toolkit.getToolkit().getFontLoader().getFontNames();
108    }
109
110    /**
111     * Gets the names of all fonts in the specified font family that are 
112     * installed on the users system, including any application fonts
113     * and SDK fonts.
114     * This call has performance considerations as looking up all of the
115     * fonts may be an expensive operation the first time.
116     */
117    public static List<String> getFontNames(String family) {
118        return Toolkit.getToolkit().getFontLoader().getFontNames(family);
119    }
120
121    /**
122     * Searches for an appropriate font based on the font family name and
123     * weight and posture style. This method is not guaranteed to return
124     * a specific font, but does its best to find one that fits the
125     * specified requirements.
126     * <p>
127     * A null or empty value for family allows the implementation to
128     * select any suitable font.
129     *
130     * @param family The family of the font
131     * @param weight The weight of the font
132     * @param posture The posture or posture of the font
133     * @param size The point size of the font. This can be a fractional value,
134     * but must not be negative. If the size is < 0 the default size will be
135     * used.
136     */
137    public static Font font(String family, FontWeight weight,
138                            FontPosture posture, double size) {
139
140        String fam =
141            (family == null || "".equals(family)) ? DEFAULT_FAMILY : family;
142        double sz = size < 0 ? getDefaultSystemFontSize() : size;
143        return Toolkit.getToolkit().getFontLoader().font(fam, weight, posture, (float)sz);
144    }
145
146    /**
147     * Searches for an appropriate font based on the font family name and weight
148     * style. This method is not guaranteed to return a specific font, but does
149     * its best to find one that fits the specified requirements.
150     * A null or empty  value for family allows the implementation
151     * to select any suitable font.
152     *
153     * @param family The family of the font
154     * @param weight The weight of the font
155     * @param size The point size of the font. This can be a fractional value,
156     * but must not be negative. If the size is < 0 the default size will be
157     * used.
158     */
159    public static Font font(String family, FontWeight weight, double size) {
160        return font(family, weight, null, size);
161    }
162
163    /**
164     * Searches for an appropriate font based on the font family name and posture
165     * style. This method is not guaranteed to return a specific font, but does
166     * its best to find one that fits the specified requirements. A null or empty
167     * value for family allows the implementation to select any suitable font.
168     *
169     * @param family The family of the font
170     * @param posture The posture or posture of the font
171     * @param size The point size of the font. This can be a fractional value,
172     * but must not be negative. If the size is < 0 the default size will be
173     * used.
174     */
175    public static Font font(String family, FontPosture posture, double size) {
176        return font(family, null, posture, size);
177    }
178
179    /**
180     * Searches for an appropriate font based on the font family name and size.
181     * This method is not guaranteed to return a specific font, but does
182     * its best to find one that fits the specified requirements. A null or empty
183     * value for family allows the implementation to select any suitable font.
184     *
185     * @param family The family of the font
186     * @param size The point size of the font. This can be a fractional value,
187     * but must not be negative. If the size is < 0 the default size will be
188     * used.
189     */
190    public static Font font(String family, double size) {
191        return font(family, null, null, size);
192    }
193
194    /**
195     * The full font name. This name includes both the family name
196     * and the style variant within that family. For example, for a plain
197     * Arial font this would be "Arial Regular" and for a bolded
198     * Arial font this would be "Arial Bold". The precise name to use when
199     * loading a font is defined within each font file as the full font name.
200     * For example, "Proxima Nova ExtraCondensed Bold Italic" would refer to a
201     * specific Proxima Nova font.
202     * A null or empty name allows the implementation to select any suitable
203     * font.
204     * <p>
205     * There is a single unified way to load all of application supplied
206     * (via <code>Font.loadFont()</code>, JavaFX runtime delivered fonts,
207     * and system installed fonts. Simply create the font by specifying
208     * the full name of the font you want to load. 
209     * If the specific font cannot be located, then a fallback or default
210     * font will be used. The "name" will be updated to reflect the actual name
211     * of the font being used. A load failure condition can be discovered by
212     * checking the name of the Font with the name you tried to load.
213     * <p>
214     * Note that if you wish to locate a font by font family and style
215     * then you can use one of the {@link #font} factory methods defined in
216     * this class.
217     *
218     * @defaultValue empty string
219     */
220    public final String getName() { return name; }
221    private String name;
222
223    /**
224     * Returns the family of this font.
225     * @return The family of this font.
226     */
227    public final String getFamily() { return family; }
228    private String family;
229
230    /**
231     * The font specified string describing the style within the font family.
232     * @return The style name of this font.
233     */
234    public final String getStyle() { return style; }
235    private String style;
236
237    /**
238     * The point size for this font. This may be a fractional value such as
239     * {@code 11.5}. If the specified value is < 0 the default size will be
240     * used.
241     *
242     * @defaultValue 12
243     */
244    public final double getSize() { return size; }
245    private double size;
246
247    /**
248     * The cached hash code, used to improve performance in situations where
249     * we cache fonts, such as in the CSS routines.
250     */
251    private int hash = 0;
252
253    /**
254     * Constructs a font using the default face "System".
255     * The underlying font used is determined by the implementation
256     * based on the typical UI font for the current UI environment.
257     *
258     * @param size the font size to use
259     */
260    public Font(double size) {
261        this(null, size);
262    }
263
264    
265    /**
266     * Constructs a font using the specified full face name and size
267     * @param name full name of the font.
268     * @param size the font size to use
269     */
270    public Font(String name, double size) {
271        this.name = name;
272        this.size = size;
273
274        if (name == null || "".equals(name)) this.name = DEFAULT_FULLNAME;
275        if (size < 0f) this.size = getDefaultSystemFontSize();
276        // if a search was done based on family + style information, then the
277        // native font has already been located and specified. Likewise if the
278        // Font was created based on an existing native font. If however a Font
279        // was created directly in FX, then we need to find the native font
280        // to use. This call will also set the family and style by invoking
281        // the impl_setNativeFont callback method.
282        Toolkit.getToolkit().getFontLoader().loadFont(this);
283    }
284
285    /**
286     * Private constructor for internal implementation
287     * 
288     * @param f native font
289     * @param family font family name
290     * @param name font full name
291     * @param style style string
292     * @param size font size
293     */
294    private Font(Object f, String family, String name, String style, double size) {
295        this.nativeFont = f;
296        this.family = family;
297        this.name = name;
298        this.style = style;
299        this.size = size;
300    }
301
302    /**
303     * Loads a font resource from the specified URL. If the load is successful
304     * such that the location is readable, and it represents a supported
305     * font format then a <code>Font</code> object will be returned.
306     * <p>
307     * Any failure such as a malformed URL being unable to locate or read
308     * from the resource, or if it doesn't represent a font, will result in
309     * a <code>null</code> return. It is the application's responsibility
310     * to check this before use.
311     * <p>
312     * On a successful (non-null) return the font will be registered
313     * with the FX graphics system for creation by available constructors
314     * and factory methods, and the application should use it in this
315     * manner rather than calling this method again, which would
316     * repeat the overhead of downloading and installing the font.
317     * <p>
318     * The font <code>size</code> parameter is a convenience so that in
319     * typical usage the application can directly use the returned (non-null)
320     * font rather than needing to create one via a constructor. Invalid sizes
321     * are those <=0 and will result in a default size.
322     * <p>
323     * If the URL represents a local disk file, then no copying is performed
324     * and the font file is required to persist for the lifetime of the
325     * application. Updating the file in any manner will result
326     * in unspecified and likely undesired behaviours.
327     * 
328     * @param urlStr from which to load the font, specified as a String.
329     * @param size of the returned font.
330     * @return the Font, or null if the font cannot be created.
331     */
332    public static Font loadFont(String urlStr, double size) {
333        URL url = null;
334        try {
335            url = new URL(urlStr); // null string arg. is caught here.
336        } catch (Exception e) {
337            return null;
338        }
339        if (size <= 0) {
340            size = getDefaultSystemFontSize();
341        }
342        // Now lets parse the URL and decide if its a file,
343        // or a remote URL from which we need to read.
344        if (url.getProtocol().equals("file")) {
345            String path = url.getFile();
346            // The URL path may have a leading "/", when obtained
347            // via ClassLoader. This can cause problems on Windows.
348            // Getting the path from a File fixes this.
349            path = new java.io.File(path).getPath();
350            try {
351                SecurityManager sm = System.getSecurityManager();
352                if (sm != null) {
353                    FilePermission filePermission =
354                        new FilePermission(path, "read");
355                    sm.checkPermission(filePermission);
356                }
357            } catch (Exception e) {
358                return null;
359            }
360            return Toolkit.getToolkit().getFontLoader().loadFont(path, size);
361        }
362        Font font = null;
363        URLConnection connection = null;
364        InputStream in = null;
365        try {
366            connection = url.openConnection();
367            in = connection.getInputStream();
368            font = Toolkit.getToolkit().getFontLoader().loadFont(in, size);
369        } catch (Exception e) {
370            return null;
371        } finally {
372            try {
373                if (in != null) {
374                    in.close();
375                }
376            } catch (Exception e) {
377            }
378        }
379        return font;
380    }
381
382    /**
383     * Loads a font resource from the specified input stream.
384     * If the load is successful such that the stream can be
385     * fully read, and it represents a supported font format then a
386     * <code>Font</code> object will be returned.
387     * <p>
388     * Any failure such as abbreviated input, or an unsupported font format
389     * will result in a <code>null</code> return. It is the application's
390     * responsibility to check this before use.
391     * <p>
392     * On a successful (non-null) return the font will be registered
393     * with the FX graphics system for creation by available constructors
394     * and factory methods, and the application should use it in this
395     * manner rather than calling this method again, which would
396     * repeat the overhead of re-reading and installing the font.
397     * <p>
398     * The font <code>size</code> parameter is a convenience so that in
399     * typical usage the application can directly use the returned (non-null)
400     * font rather than needing to create one via a constructor. Invalid sizes
401     * are those <=0 and will result in a default size.
402     * <p>
403     * This method does not close the input stream.
404     * @param in stream from which to load the font.
405     * @param size of the returned font.
406     * @return the Font, or null if the font cannot be created.
407     */
408    public static Font loadFont(InputStream in, double size) {
409        if (size <= 0) {
410            size = getDefaultSystemFontSize();
411        }
412        return Toolkit.getToolkit().getFontLoader().loadFont(in, size);
413    }
414    
415    /**
416     * Converts this {@code Font} object to a {@code String} representation.
417     * The String representation is for informational use only and will change.
418     * Do not use this string representation for any programmatic purpose.
419     */
420    @Override public String toString() {
421        StringBuilder builder = new StringBuilder("Font[name=");
422        builder = builder.append(name);
423        builder = builder.append(", family=").append(family);
424        builder = builder.append(", style=").append(style);
425        builder = builder.append(", size=").append(size);
426        builder = builder.append("]");
427        return builder.toString();
428    }
429
430    /**
431     * Indicates whether some other object is "equal to" this one.
432     * @param obj the reference object with which to compare.
433     * @return {@code true} if this object is equal to the {@code obj} argument; {@code false} otherwise.
434     */
435    @Override public boolean equals(Object obj) {
436        if (obj == this) return true;
437        if (obj instanceof Font) {
438            Font other = (Font)obj;
439            return (name == null ? other.name == null : name.equals(other.name))
440                && size == other.size;
441        }
442        return false;
443    }
444
445    /**
446     * Returns a hash code for this {@code Font} object.
447     * @return a hash code for this {@code Font} object.
448     */ 
449    @Override public int hashCode() {
450        if (hash == 0) {
451            long bits = 17L;
452            bits = 37L * bits + name.hashCode();
453            bits = 37L * bits + Double.doubleToLongBits(size);
454            hash = (int) (bits ^ (bits >> 32));
455        }
456        return hash;
457    }
458
459    private Object nativeFont;
460
461    /**
462     * @treatAsPrivate implementation detail
463     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
464     */
465    @Deprecated
466    public Object impl_getNativeFont() { return nativeFont; }
467
468    /**
469     * @treatAsPrivate implementation detail
470     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
471     */
472    @Deprecated
473    public void impl_setNativeFont(Object f, String nam, String fam, String styl) {
474        nativeFont = f;
475        name = nam;
476        family = fam;
477        style = styl;
478    }
479
480    /**
481     * @treatAsPrivate implementation detail
482     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
483     */
484    @Deprecated
485    public static Font impl_NativeFont(Object f, String name, String family,
486                                       String style, double size) {
487        Font retFont = new Font( f, family, name, style, size);
488        return retFont;
489    }
490}