001 package com.sptci.echo2.style;
002
003 import java.util.Map;
004 import java.util.concurrent.ConcurrentHashMap;
005
006 import nextapp.echo2.app.Extent;
007
008 /**
009 * A custom font class to use in styles. This class by default uses
010 * {@link #TYPEFACE} as the {@link nextapp.echo2.app.Font.Typeface} and ensures
011 * consistent font typeface across the application. It is recomended that you
012 * use the {@link #getInstance} method or its overloaded derivatives to avoid
013 * replication across sessions.
014 *
015 * <p>The following shows the recommended way to use this class:</p>
016 * <pre>
017 * import com.sptci.echo2.style.Extent;
018 * import com.sptci.echo2.style.Font;
019 *
020 * ...
021 * Font normalFont = Font.getInstance();
022 * Font largeFont = Font.getInstance( Extent.getInstance( 14 ) );
023 * Font boldFont = Font.getInstance( Font.BOLD );
024 * </pre>
025 *
026 * <p>© Copyright 2006 Sans Pareil Technologies, Inc.</p>
027 * @author Rakesh Vidyadharan 2006-11-06
028 * @version $Id: Font.java 3334 2007-06-08 16:25:49Z rakesh $
029 */
030 public class Font extends nextapp.echo2.app.Font
031 {
032 /**
033 * The application wide default typeface.
034 */
035 public static final Typeface TYPEFACE =
036 new Typeface( "Helvetica", new Typeface( "Verdana", TIMES_ROMAN ) );
037
038 /**
039 * The default font size to use.
040 */
041 public static final Extent SIZE =
042 com.sptci.echo2.style.Extent.getInstance( 12, Extent.PX );
043
044 /**
045 * The default font style to use.
046 */
047 public static final int STYLE = Font.PLAIN;
048
049 /**
050 * The cache of reusable font instances. A nested map structure is used
051 * to allow for future management based upon {@link
052 * nextapp.echo2.app.Font.Typeface} values.
053 */
054 protected static final Map<String,Map<String,Font>> cache =
055 new ConcurrentHashMap<String,Map<String,Font>>();
056
057 /**
058 * The nested map used to store the fonts for the default {@link #TYPEFACE}.
059 */
060 protected static final Map<String,Font> defaultCache = getMap( getKey( TYPEFACE ) );
061
062 /**
063 * Create a new instance of the font using the defaults for style
064 * and size.
065 *
066 * @deprecated Use {@link #getInstance()} instead.
067 */
068 @Deprecated public Font()
069 {
070 this( STYLE, SIZE );
071 }
072
073 /**
074 * Create a new instance of the font using the specified style and
075 * default size.
076 *
077 * @deprecated Use {@link #getInstance( int )} instead.
078 * @param style The style to use for the font. Styles are usually
079 * specified using the constants in the {@link nextapp.echo2.app.Font}
080 * class.
081 */
082 @Deprecated public Font( final int style )
083 {
084 this( style, SIZE );
085 }
086
087 /**
088 * Create a new instance of the font using the specified size and
089 * default style.
090 *
091 * @deprecated Use {@link #getInstance( Extent )} instead.
092 * @param size The font size to use.
093 */
094 @Deprecated public Font( final Extent size )
095 {
096 this( STYLE, size );
097 }
098
099 /**
100 * Create a new instance of the font using the specified style and
101 * size.
102 *
103 * @deprecated Use {@link #getInstance( int, Extent )} instead.
104 * @param style The style to use for the font. Styles are usually
105 * specified using the constants in the {@link nextapp.echo2.app.Font}
106 * class.
107 * @param size The font size to use.
108 */
109 @Deprecated public Font( final int style, final Extent size )
110 {
111 super( TYPEFACE, style, size );
112 }
113
114 /**
115 * Create a new instance of the font using the specified typeface chain,
116 * style and size.
117 *
118 * @deprecated Use {@link #getInstance( Font.Typeface, int, Extent )} instead.
119 * @param typeface The typeface chain to use for the font.
120 * @param style The style to use for the font. Styles are usually
121 * specified using the constants in the {@link nextapp.echo2.app.Font}
122 * class.
123 * @param size The font size to use.
124 */
125 @Deprecated public Font( final Typeface typeface, final int style,
126 final Extent size )
127 {
128 super( typeface, style, size );
129 }
130
131 /**
132 * Factory method to use to retrieve the cached default font instance.
133 *
134 * @see #getInstance( int, Extent )
135 */
136 public static Font getInstance()
137 {
138 return getInstance( STYLE, SIZE );
139 }
140
141 /**
142 * Factory method to use to retrieve a cached font instance.
143 *
144 * <p><b>Note:</b> This method can be refactored to delegate to {@link
145 * #getInstance( Font.Typeface, Extent )}, however has been left as a separate
146 * implementation to avoid the lookup process involved in {@link
147 * #getKey}.</p>
148 *
149 * @see #getKey( Extent )
150 * @see #defaultCache
151 * @param size The font size to use.
152 */
153 public static Font getInstance( final Extent size )
154 {
155 final String key = getKey( size );
156 Font font = defaultCache.get( key );
157
158 if ( font == null )
159 {
160 font = new Font( size );
161 defaultCache.put( key, font );
162 }
163
164 return font;
165 }
166
167 /**
168 * Factory method to use to retrieve a cached font instance.
169 *
170 * @see #getInstance( int, Extent )
171 * @param style The style to use for the font. Styles are usually
172 * specified using the constants in the {@link nextapp.echo2.app.Font}
173 * class.
174 */
175 public static Font getInstance( final int style )
176 {
177 return getInstance( style, SIZE );
178 }
179
180 /**
181 * Factory method to use to retrieve a cached font instance.
182 *
183 * <p><b>Note:</b> This method can be refactored to delegate to {@link
184 * #getInstance( Font.Typeface, int, Extent )}, however has been left as a
185 * separate implementation to avoid the normalisation process involved in
186 * {@link #getKey}.</p>
187 *
188 * @see #getKey( int, Extent )
189 * @see #defaultCache
190 * @param style The style to use for the font. Styles are usually
191 * specified using the constants in the {@link nextapp.echo2.app.Font}
192 * class.
193 * @param size The font size to use.
194 */
195 public static Font getInstance( final int style, final Extent size )
196 {
197 final String key = getKey( style, size );
198 Font font = defaultCache.get( key );
199
200 if ( font == null )
201 {
202 font = new Font( style, size );
203 defaultCache.put( key, font );
204 }
205
206 return font;
207 }
208
209 /**
210 * Factory method to use to retrieve a cached font instance.
211 *
212 * @deprecated Warning, you are creating a non-standard font.
213 * @see #getKey( Font.Typeface )
214 * @see #getKey( Extent )
215 * @see #getMap
216 * @param typeface The typeface chain to use for the font.
217 * @param size The font size to use.
218 */
219 public static Font getInstance( final Typeface typeface, final Extent size )
220 {
221 final Map<String,Font> map = getMap( getKey( typeface ) );
222 final String key = getKey( size );
223 Font font = map.get( key );
224
225 if ( font == null )
226 {
227 font = new Font( size );
228 map.put( key, font );
229 }
230
231 return font;
232 }
233
234 /**
235 * Factory method to use to retrieve a cached font instance.
236 *
237 * @deprecated Warning, you are creating a non-standard font.
238 * @param typeface The typeface chain to use for the font.
239 * @param style The style to use for the font. Styles are usually
240 * specified using the constants in the {@link nextapp.echo2.app.Font}
241 * class.
242 * @param size The font size to use.
243 */
244 public static Font getInstance( final Typeface typeface, final int style,
245 final Extent size )
246 {
247 final Map<String,Font> map = getMap( getKey( typeface ) );
248 final String key = getKey( style, size );
249 Font font = map.get( key );
250
251 if ( font == null )
252 {
253 font = new Font( style, size );
254 map.put( key, font );
255 }
256
257 return font;
258 }
259
260 /**
261 * Return a key for the extent specified.
262 *
263 * @param size The extent whose key is to be returned.
264 * @return The normalised key for the extent.
265 */
266 protected static String getKey( final Extent size )
267 {
268 return size.toString();
269 }
270
271 /**
272 * Return a key for the style and extent specified.
273 *
274 * @param style The style to use for the font.
275 * @param size The extent whose key is to be returned.
276 * @return The normalised key for the extent.
277 */
278 protected static String getKey( final int style, final Extent size )
279 {
280 final StringBuilder builder = new StringBuilder();
281 builder.append( style ).append( "::" ).append( size.toString() );
282 return builder.toString();
283 }
284
285 /**
286 * Return a key for the {@link nextapp.echo2.app.Font.Typeface}
287 * chain.
288 *
289 * @param typeface The typeface whose key chain is to be returned.
290 * @return The key for the typeface chain.
291 */
292 protected static String getKey( final Typeface typeface )
293 {
294 final StringBuilder builder = new StringBuilder();
295 Typeface tf = typeface;
296 builder.append( tf.getName() ).append( "," );
297
298 while( ( tf = tf.getAlternate() ) != null )
299 {
300 builder.append( tf.getName() ).append( "," );
301 }
302
303 return builder.toString();
304 }
305
306 /**
307 * Return the embedded {@link java.util.Map} value in {@link #cache}.
308 *
309 * @param typeface The key for the {@link nextapp.echo2.app.Font.Typeface}.
310 * @return The embedded map.
311 */
312 protected static Map<String,Font> getMap( String typeface )
313 {
314 Map<String,Font> map = cache.get( typeface );
315
316 if ( map == null )
317 {
318 map = new ConcurrentHashMap<String,Font>();
319 cache.put( typeface, map );
320 }
321
322 return map;
323 }
324 }