JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
FontFactory.java
Go to the documentation of this file.
1/**
2 * Copyright 2010-2024 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.graph.font;
29
30import java.io.BufferedInputStream;
31import java.io.File;
32import java.io.FileInputStream;
33import java.io.IOException;
34import java.io.InputStream;
35import java.security.PrivilegedAction;
36
37import com.jogamp.common.net.Uri;
38import com.jogamp.common.util.IOUtil;
39import com.jogamp.common.util.PropertyAccess;
40import com.jogamp.common.util.ReflectionUtil;
41import com.jogamp.common.util.SecurityUtil;
42import com.jogamp.common.util.cache.TempJarCache;
43
44import jogamp.graph.font.FontConstructor;
45import jogamp.graph.font.SymbolsFontLoader;
46import jogamp.graph.font.UbuntuFontLoader;
47
48/**
49 * The optional property <i>jogamp.graph.font.ctor</i>
50 * allows user to specify the {@link FontConstructor} implementation.
51 * <p>
52 * Default {@link FontConstructor} is {@link jogamp.graph.font.typecast.TypecastFontConstructor},
53 * i.e. using our internal <i>typecast</i> branch.
54 * </p>
55 */
56public class FontFactory {
57 private static final String FontConstructorPropKey = "jogamp.graph.font.ctor";
58 private static final String DefaultFontConstructor = "jogamp.graph.font.typecast.TypecastFontConstructor";
59
60 /** Ubuntu is the default font family, {@value} */
61 public static final int UBUNTU = 0;
62
63 /** Symbols is the default symbol font family and contains rounded material symbol fonts, {@value} */
64 public static final int SYMBOLS = 10;
65
66 private static final FontConstructor fontConstr;
67
68 static {
69 /**
70 * For example:
71 * "jogamp.graph.font.typecast.TypecastFontFactory" (default)
72 * "jogamp.graph.font.ttf.TTFFontImpl"
73 */
74 String fontImplName = PropertyAccess.getProperty(FontConstructorPropKey, true);
75 if(null == fontImplName) {
76 fontImplName = DefaultFontConstructor;
77 }
78 fontConstr = (FontConstructor) ReflectionUtil.createInstance(fontImplName, FontFactory.class.getClassLoader());
79 }
80
81 public static final FontSet getDefault() {
82 return get(UBUNTU);
83 }
84
85 public static final FontSet get(final int font) {
86 switch (font) {
87 case SYMBOLS:
88 return SymbolsFontLoader.get();
89 default:
90 return UbuntuFontLoader.get();
91 }
92 }
93
94 /**
95 * Creates a Font instance.
96 * @param file font file
97 * @return the new Font instance
98 * @throws IOException
99 */
100 public static final Font get(final File file) throws IOException {
101 return fontConstr.create(file);
102 }
103
104 /**
105 * Creates a Font instance based on a determinated font stream with its given length
106 * of the font segment.
107 * <p>
108 * No explicit stream copy is performed as in {@link #get(InputStream, boolean)}
109 * due to the known {@code streamLen}.
110 * </p>
111 * @param stream font stream
112 * @param streamLen length of the font segment within this font stream
113 * @param closeStream {@code true} to close the {@code stream}
114 * @return the new Font instance
115 * @throws IOException
116 */
117 public static final Font get(final InputStream stream, final int streamLen, final boolean closeStream) throws IOException {
118 try {
119 return fontConstr.create(stream, streamLen);
120 } finally {
121 if( closeStream ) {
122 stream.close();
123 }
124 }
125 }
126
127 /**
128 * Creates a Font instance based on an undeterminated font stream length.
129 * <p>
130 * The font stream is temporarily copied into a temp file
131 * to gather it's size and to gain random access.
132 * The temporary file will be deleted at exit.
133 * </p>
134 * @param stream dedicated font stream
135 * @param closeStream {@code true} to close the {@code stream}
136 * @return the new Font instance
137 * @throws IOException
138 */
139 public static final Font get(final InputStream stream, final boolean closeStream) throws IOException {
140 final IOException[] ioe = { null };
141 final int[] streamLen = { 0 };
142 final File tempFile[] = { null };
143
144 final InputStream bis = SecurityUtil.doPrivileged(new PrivilegedAction<InputStream>() {
145 @Override
146 public InputStream run() {
147 InputStream bis = null;
148 try {
149 tempFile[0] = IOUtil.createTempFile( "jogl.font", ".ttf", false);
150 streamLen[0] = IOUtil.copyStream2File(stream, tempFile[0]);
151 if( 0 == streamLen[0] ) {
152 throw new IOException("Font stream has zero bytes");
153 }
154 bis = new BufferedInputStream(new FileInputStream(tempFile[0]), streamLen[0]);
155 } catch (final IOException e) {
156 ioe[0] = e;
157 if( null != tempFile[0] ) {
158 tempFile[0].delete();
159 tempFile[0] = null;
160 }
161 streamLen[0] = 0;
162 } finally {
163 if( closeStream ) {
164 IOUtil.close(stream, ioe, System.err);
165 }
166 }
167 return bis;
168 } });
169 if( null != ioe[0] ) {
170 throw ioe[0];
171 }
172 if( null == bis ) {
173 throw new IOException("Could not cache font stream"); // should not be reached
174 }
175 try {
176 return fontConstr.create(bis, streamLen[0]);
177 } finally {
178 if( null != bis ) {
179 bis.close();
180 }
181 if( null != tempFile[0] ) {
182 SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
183 @Override
184 public Object run() {
185 tempFile[0].delete();
186 return null;
187 } } );
188 }
189 }
190 }
191
192 public static final Font get(final Class<?> context, final String fname, final boolean useTempJarCache) throws IOException {
193 InputStream stream = null;
194 if( useTempJarCache ) {
195 try {
196 final Uri uri = TempJarCache.getResourceUri(fname);
197 stream = null != uri ? uri.toURL().openConnection().getInputStream() : null;
198 } catch (final Exception e) {
199 throw new IOException(e);
200 }
201 } else {
202 stream = IOUtil.getResource(fname, context.getClassLoader(), context).getInputStream();
203 }
204 if( null != stream ) {
205 return FontFactory.get ( stream, true ) ;
206 }
207 return null;
208 }
209
210 public static boolean isPrintableChar( final char c ) {
211 if( Character.isWhitespace(c) ) {
212 return true;
213 }
214 if( 0 == c || Character.isISOControl(c) ) {
215 return false;
216 }
217 final Character.UnicodeBlock block = Character.UnicodeBlock.of( c );
218 return block != null && block != Character.UnicodeBlock.SPECIALS;
219 }
220
221 /** Returns {@link FontSet#getDefault() default} {@link Font} of {@link #getDefault() default} {@link FontSet} or {@code null} if n/a */
222 public static Font getDefaultFont() {
223 try {
224 return getDefault().getDefault();
225 } catch(final IOException ioe) {
226 ioe.printStackTrace();
227 return null;
228 }
229 }
230
231 /** Returns the default symbols {@link Font} or {@code null} if n/a */
232 public static Font getSymbolsFont() {
233 try {
234 return get(SYMBOLS).getDefault();
235 } catch(final IOException ioe) {
236 ioe.printStackTrace();
237 return null;
238 }
239 }
240
241 /** Returns registered fallback {@link Font}, maybe {@code null}. See {@link #setFallbackFont(Font)}. */
242 public static synchronized Font getFallbackFont() {
243 return fallbackFont;
244 }
245 /** Registers given {@link Font} as the default fallback font. */
246 public static synchronized void setFallbackFont(final Font f) { fallbackFont = f; }
247 private static Font fallbackFont = null;
248}
The optional property jogamp.graph.font.ctor allows user to specify the FontConstructor implementatio...
static synchronized void setFallbackFont(final Font f)
Registers given Font as the default fallback font.
static final FontSet getDefault()
static synchronized Font getFallbackFont()
Returns registered fallback Font, maybe null.
static final int SYMBOLS
Symbols is the default symbol font family and contains rounded material symbol fonts,...
static final int UBUNTU
Ubuntu is the default font family, {@value}.
static Font getDefaultFont()
Returns default Font of default FontSet or null if n/a.
static Font getSymbolsFont()
Returns the default symbols Font or null if n/a.
static boolean isPrintableChar(final char c)
Font getDefault()
Returns the family FAMILY_REGULAR with STYLE_NONE as retrieved with get(int, int).
Interface wrapper for font implementation.
Definition: Font.java:60