001 package echopoint.util;
002 /*
003 * This file is part of the Echo Point Project. This project is a collection
004 * of Components that have extended the Echo Web Application Framework.
005 *
006 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
007 *
008 * The contents of this file are subject to the Mozilla Public License Version
009 * 1.1 (the "License"); you may not use this file except in compliance with
010 * the License. You may obtain a copy of the License at
011 * http://www.mozilla.org/MPL/
012 *
013 * Software distributed under the License is distributed on an "AS IS" basis,
014 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
015 * for the specific language governing rights and limitations under the
016 * License.
017 *
018 * Alternatively, the contents of this file may be used under the terms of
019 * either the GNU General Public License Version 2 or later (the "GPL"), or
020 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
021 * in which case the provisions of the GPL or the LGPL are applicable instead
022 * of those above. If you wish to allow use of your version of this file only
023 * under the terms of either the GPL or the LGPL, and not to allow others to
024 * use your version of this file under the terms of the MPL, indicate your
025 * decision by deleting the provisions above and replace them with the notice
026 * and other provisions required by the GPL or the LGPL. If you do not delete
027 * the provisions above, a recipient may use your version of this file under
028 * the terms of any one of the MPL, the GPL or the LGPL.
029 */
030
031 import java.util.Collections;
032 import java.util.HashMap;
033 import java.util.Map;
034
035 import nextapp.echo.app.Component;
036 import nextapp.echo.app.Extent;
037 import nextapp.echo.app.Font;
038
039 import echopoint.util.collections.ConcurrentReaderHashMap;
040
041 /**
042 * A utility to class to help with Font manipulation
043 *
044 * @author Brad Baker
045 */
046 public class FontKit {
047
048 /* our static cache of Font objects by Font String representation */
049 private static Map fontMap = new ConcurrentReaderHashMap();
050
051 private static final Map FONTSTYLE_TEXT_TO_CONSTANT;
052 static {
053 Map constantMap = new HashMap();
054 constantMap.put("PLAIN", new Integer(Font.PLAIN));
055 constantMap.put("FONT.PLAIN", new Integer(Font.PLAIN));
056 constantMap.put("BOLD", new Integer(Font.BOLD));
057 constantMap.put("FONT.BOLD", new Integer(Font.BOLD));
058 constantMap.put("ITALIC", new Integer(Font.ITALIC));
059 constantMap.put("FONT.ITALIC", new Integer(Font.ITALIC));
060 constantMap.put("LINETHROUGH", new Integer(Font.LINE_THROUGH));
061 constantMap.put("FONT.LINETHROUGH", new Integer(Font.LINE_THROUGH));
062 constantMap.put("OVERLINE", new Integer(Font.OVERLINE));
063 constantMap.put("FONT.OVERLINE", new Integer(Font.OVERLINE));
064 constantMap.put("UNDERLINE", new Integer(Font.UNDERLINE));
065 constantMap.put("FONT.UNDERLINE", new Integer(Font.UNDERLINE));
066 FONTSTYLE_TEXT_TO_CONSTANT = Collections.unmodifiableMap(constantMap);
067 }
068
069
070 private static final Map TYPEFACE_TEXT_TO_CONSTANT;
071 static {
072 Map constantMap = new HashMap();
073 constantMap.put("HELVETICA", Font.HELVETICA);
074 constantMap.put("ARIAL", Font.ARIAL);
075 constantMap.put("VERDANA", Font.VERDANA);
076 constantMap.put("TIMES", Font.TIMES);
077 constantMap.put("TIMES ROMAN", Font.TIMES_ROMAN);
078 constantMap.put("TIMES NEW ROMAN", Font.TIMES_NEW_ROMAN);
079 constantMap.put("COURIER", Font.COURIER);
080 constantMap.put("COURIER NEW", Font.COURIER_NEW);
081 TYPEFACE_TEXT_TO_CONSTANT = Collections.unmodifiableMap(constantMap);
082 }
083
084
085 /** not instantiable */
086 private FontKit() {
087 }
088
089 /**
090 * Creates an AWT font object from a Echo font object. This is
091 * useful for drawing on AWT images.
092 *
093 * @param echoFont - the nextapp.echo2.app.Font object to convert
094 * @param awtDefaultFont - a default AWT font to use if the conversion cant be done.
095 * @return - a new java.awt.Font object base don echoFont.
096 */
097 public static java.awt.Font makeAwtFont(Font echoFont, java.awt.Font awtDefaultFont) {
098 if (echoFont == null)
099 return awtDefaultFont;
100 else {
101 int size = echoFont.getSize() == null ? 12 : echoFont.getSize().getValue();
102 int style = 0;
103 if (echoFont.isBold())
104 style |= java.awt.Font.BOLD;
105 if (echoFont.isItalic())
106 style |= java.awt.Font.ITALIC;
107 if (echoFont.isUnderline());
108 if (style == 0)
109 style = java.awt.Font.PLAIN;
110
111 return new java.awt.Font(echoFont.getTypeface().getName(), style, size);
112 }
113 }
114
115 /**
116 * Makes a W3C CSS font string in the special format
117 * <p>
118 * <i>fontstyle</i>, <i>fontsize</i>, <i>fontnames</i>
119 * <p>
120 * @param font - the font to represent as a W3C CSS string
121 * @return the W3C CSS string represenation
122 */
123 public static String makeCSSFont(Font font) {
124 StringBuffer sb = new StringBuffer();
125 if (font.isBold())
126 sb.append("bold ");
127 if (font.isItalic())
128 sb.append("italic ");
129 if (font.isUnderline())
130 sb.append("underline ");
131
132 sb.append(font.getSize());
133 sb.append(" ");
134
135 int i = 0;
136 Font.Typeface face = font.getTypeface();
137 while (face != null) {
138 if (i > 0)
139 sb.append(", ");
140 sb.append("'");
141 sb.append(face.getName());
142 sb.append("'");
143 face = face.getAlternate();
144 i++;
145 }
146 return sb.toString();
147 }
148
149 /**
150 * Adds bold to a Component's font.
151 * <p>
152 * If the component has no font, a <code>findFont</code> is performed and
153 * the result is set in as the font.
154 * <p>
155 * @see FontKit#addBold(Font)
156 *
157 * @param c - the component in question
158 */
159 public static void addBold(Component c) {
160 Font font = findFont(c);
161 font = addBold(font);
162 c.setFont(font);
163 }
164
165 /**
166 * Adds italic to a Component's font.
167 * <p>
168 * If the component has no font, a <code>findFont</code> is performed and
169 * the result is set in as the font.
170 * <p>
171 * @see FontKit#addItalic(Font)
172 *
173 * @param c - the component in question
174 */
175 public static void addItalic(Component c) {
176 Font font = findFont(c);
177 c.setFont(addItalic(font));
178 }
179
180 /**
181 * Adds underline to a Component's font.
182 * <p>
183 * If the component has no font, a <code>findFont</code> is performed and
184 * the result is set in as the font.
185 * <p>
186 * @see FontKit#addUnderline(Font)
187 *
188 * @param c - the component in question
189 */
190 public static void addUnderline(Component c) {
191 Font font = findFont(c);
192 c.setFont(addUnderline(font));
193 }
194
195 /**
196 * Adds the specified <code>style</code> to a Component's font.
197 * <p>
198 * If the component has no font, a <code>findFont</code> is performed and
199 * the result is set in as the font.
200 * <p>
201 * @see FontKit#addStyle(Font, int)
202 *
203 * @param c - the component in question
204 */
205 public static void addStyle(Component c, int style) {
206 Font font = findFont(c);
207 c.setFont(addStyle(font,style));
208 }
209
210 /**
211 * Sets a component's font smaller or large by the specified
212 * delta amount.
213 * <p>
214 * If the component has no font, a <code>findFont</code> is performed and
215 * the result is set in as the font.
216 * <p>
217 * @see FontKit#addSize(Font, int)
218 *
219 * @param c - the component in question
220 * @param sizeDelta - a positive or negative delta amount
221 */
222 public static void addSize(Component c, int sizeDelta) {
223 Font font = findFont(c);
224 c.setFont(addSize(font,sizeDelta));
225 }
226
227 /**
228 * Sets Component's font to bold.
229 * <p>
230 * If the component has no font, a <code>findFont</code> is performed and
231 * the result is set in as the font.
232 * <p>
233 * @see FontKit#setStyle(Font, int)
234 *
235 * @param c - the component in question
236 */
237 public static void setBold(Component c) {
238 Font font = findFont(c);
239 c.setFont(setStyle(font, Font.BOLD));
240 }
241
242 /**
243 * Sets Component's font to italic.
244 * <p>
245 * If the component has no font, a <code>findFont</code> is performed and
246 * the result is set in as the font.
247 * <p>
248 * @see FontKit#setStyle(Font, int)
249 *
250 * @param c - the component in question
251 */
252 public static void setItalic(Component c) {
253 Font font = findFont(c);
254 c.setFont(setStyle(font, Font.ITALIC));
255 }
256
257 /**
258 * Sets Component's font to underline.
259 * <p>
260 * If the component has no font, a <code>findFont</code> is performed and
261 * the result is set in as the font.
262 * <p>
263 * @see FontKit#setStyle(Font, int)
264 *
265 * @param c - the component in question
266 */
267 public static void setUnderline(Component c) {
268 Font font = findFont(c);
269 c.setFont(setStyle(font, Font.UNDERLINE));
270 }
271
272
273 /**
274 * Sets the size of a Component's font.
275 * <p>
276 * If the component has no font, a <code>findFont</code> is performed and
277 * the result is set in as the font.
278 * <p>
279 * @see FontKit#setSize(Font, int)
280 *
281 * @param c - the component in question
282 * @param size - the new font size
283 */
284 public static void setSize(Component c, int size) {
285 Font font = findFont(c);
286 c.setFont(addSize(font,size));
287 }
288
289
290
291 /**
292 * Searchs the heirarchy tree of the component and finds the first
293 * non null Font object. It will return <code>Font(Font.SANS_SERIF,Font.PLAIN,new Extent(10,Extent.PT)</code>
294 * if no ancestor components have a Font set.
295 *
296 */
297 public static Font findFont(Component comp) {
298 while (comp != null) {
299 Font fnt = comp.getFont();
300 if (fnt != null)
301 return fnt;
302 comp = comp.getParent();
303 }
304 return new Font(Font.SANS_SERIF,Font.PLAIN,new Extent(10,Extent.PT));
305 }
306
307 /**
308 * Returns the Font value of the given Font string representation.
309 * <p>
310 * The allowable forms are : <p>
311 * - fontName,fontStyle,fontSize<br>
312 * - font( fontName, fontStyle, fontSize)<br>
313 * <p>
314 * where
315 * <p>
316 * fontName - eg. Verdana or 'Times New Roman'.
317 * If multiple font names are specified or there is
318 * white space in the font name, then it must be enclosed
319 * in single quotes and commas eg. 'Verdana, Times New Roman, Tahoma'.
320 * <br>
321 * fontStyle - PLAIN|BOLD|ITALIC|UNDERLINE|OVERLINE|LINETHROUGH or nothing! (this is case insenstive)
322 * <br>
323 * fontSize - an integer size value or an Extent value. (In the case where
324 * only an integer is specified, the default Extent units
325 * are points (pt).
326 * <p>
327 * Examples :<br>
328 * <blockquote><pre>
329 * Verdana,,9 - is a legal font string
330 * Verdana,PLAIN,9 - is a legal font string
331 * Verdana,plain,9 - is a legal font string
332 * Verdana,plain,9em - is a legal font string
333 * Verdana,plain,9pt - is a legal font string
334 * Verdana,bold|italic,9 - is a legal font string
335 * 'Times New Roman',plain,9 - is a legal font string
336 * 'Verdana, Times New Roman',plain,9 - is a legal font string
337 *
338 * font(Verdana,,9) - is a legal font string
339 * font(Verdana,PLAIN,9pt) - is a legal font string
340 * font(Verdana,plain,9) - is a legal font string
341 * font(Verdana,bold|italic,9em) - is a legal font string
342 * font('Verdana, Times New Roman',plain,9) - is a legal font string
343 *
344 * Verdana, 3, 9 - is an ILLEGAL font string
345 * Verdana, Times New Roman,PLAIN,9 - is an ILLEGAL font string
346 * font(Verdana, 3, 9) - is an ILLEGAL font string
347 * font(Verdana, Times New Roman,PLAIN,9) - is an ILLEGAL font string
348 * </pre></blockquote>
349 * <p>
350 * The results of this operations is cached in a global static
351 * cache, so that Font objects can be re-used. This is okay
352 * since Font objects are immutable once created.
353 *
354 * @param fontString - the font string in question
355 * @return a new Font object
356 * @throws IllegalArgumentException - if the fontString is in an invalid format
357 */
358 public static Font makeFont(String fontString) {
359 if (fontString == null)
360 throw new IllegalArgumentException("The fontString must be non null");
361
362 Font font = _getCachedFont(fontString);
363 if (font != null)
364 return font;
365
366 if (! isFont(fontString))
367 throw new IllegalArgumentException("The font string is invalid : " + fontString);
368
369 int index = 0;
370 String tokens[] = TokenizerKit.tokenize(fontString, "(,)|");
371 if (fontString.indexOf("font(") == 0)
372 index = 1;
373
374 // font names
375 String fontName = tokens[index].trim();
376 Font.Typeface fontNameVal = makeTypeface(fontName);
377
378 // font styles
379 int fontStyleVal = 0;
380 String fontStyleString = tokens[++index];
381 for (int i = index; i < tokens.length; i++) {
382 fontStyleString = tokens[i].trim();
383 if (_isInteger(fontStyleString) || ExtentKit.isExtent(fontStyleString))
384 break;
385 String arr[] = TokenizerKit.tokenize(fontStyleString,"|");
386 for (int j = 0; j < arr.length; j++) {
387 fontStyleString = arr[j].trim();
388 int k = _getFontStyle(fontStyleString);
389 if (k >= 0) {
390 fontStyleVal |= k;
391 }
392 }
393 }
394
395 // font size
396 String fontSize = fontStyleString;
397 Font newFont;
398 if (ExtentKit.isExtent(fontSize)) {
399 newFont = new Font(fontNameVal, fontStyleVal, ExtentKit.makeExtent(fontSize));
400 } else {
401 int fontSizeVal = Integer.parseInt(fontSize);
402 newFont = new Font(fontNameVal, fontStyleVal, new Extent(fontSizeVal,Extent.PT));
403 }
404 return _putCachedFont(fontString, newFont);
405 }
406
407 /**
408 * Shortcut synonym for makeFont(fontString);
409 * <p>
410 * @see FontKit#makeFont(String)
411 */
412 public static Font font(String fontString) {
413 return makeFont(fontString);
414 }
415
416 /**
417 * Returns true if the <code>fontString</code> is a valid
418 * representation of a Font value.
419 * <p>
420 * The allowable forms are : <p>
421 * - fontName,fontStyle,fontSize<br>
422 * - font( fontName, fontStyle, fontSize)<br>
423 * <p>
424 * where
425 * <p>
426 * fontName - eg. Verdana or 'Times New Roman'.
427 * If multiple font names are specified or there is
428 * white space in the font name, then it must be enclosed
429 * in single quotes and commas eg. 'Verdana, Times New Roman, Tahoma'.
430 * <br>
431 * fontStyle - PLAIN|BOLD|ITALIC|UNDERLINE|OVERLINE|LINETHROUGH or nothing! (this is case insenstive)
432 * <br>
433 * fontSize - an integer size value or an Extent value. (In the case where
434 * only an integer is specified, the default Extent units
435 * are points (pt).
436 * <p>
437 * Examples :<br>
438 * <blockquote><pre>
439 * Verdana,,9 - is a legal font string
440 * Verdana,PLAIN,9 - is a legal font string
441 * Verdana,plain,9 - is a legal font string
442 * Verdana,bold|italic,9 - is a legal font string
443 * 'Times New Roman',plain,9 - is a legal font string
444 * 'Verdana, Times New Roman',plain,9 - is a legal font string
445 *
446 * font(Verdana,,9) - is a legal font string
447 * font(Verdana,PLAIN,9) - is a legal font string
448 * font(Verdana,plain,9) - is a legal font string
449 * font(Verdana,bold|italic,9) - is a legal font string
450 * font('Verdana, Times New Roman',plain,9) - is a legal font string
451 *
452 * Verdana, 3, 9 - is an ILLEGAL font string
453 * Verdana, Times New Roman,PLAIN,9 - is an ILLEGAL font string
454 * font(Verdana, 3, 9) - is an ILLEGAL font string
455 * font(Verdana, Times New Roman,PLAIN,9) - is an ILLEGAL font string
456 * </pre></blockquote>
457 *
458 * @param fontString - the font string representation to check
459 * @return true if the string is in the correct format
460 */
461 public static boolean isFont(String fontString) {
462 if (fontString == null)
463 return false;
464
465 int index = 0;
466 String tokens[] = TokenizerKit.tokenize(fontString, "(,)|");
467 if (fontString.indexOf("font(") == 0)
468 index = 1;
469
470 if (tokens.length < 2)
471 return false;
472
473 // font name is ok. Technically anything is OK
474
475 // font styles
476 String font = tokens[++index];
477 for (;index < tokens.length; index++) {
478 font = tokens[index].trim();
479 if (_isInteger(font) || ExtentKit.isExtent(font))
480 break;
481 String arr[] = TokenizerKit.tokenize(font,"|");
482 for (int i = 0; i < arr.length; i++) {
483 font = arr[i].trim();
484 if (_getFontStyle(font) == -1) {
485 return false;
486 }
487 }
488 }
489 // font size
490 String fontSize = font;
491 if (! ExtentKit.isExtent(fontSize)) {
492 if (!_isInteger(fontSize))
493 return false;
494 }
495
496 if (index != tokens.length-1)
497 return false;
498
499 return true;
500 }
501
502 /**
503 * This will return a Font.Typeface object by first rtying to match
504 * the names against System provided ones and failing that it will
505 * create a font.Typeface for you.
506 * <p>
507 * Multi named type faces must be encluded in spaces.
508 * <p>
509 * Valid typeface name forms are :
510 * <pre>
511 * 'Font1, Font 2, Font2'
512 * 'Font1'
513 * Font1
514 * <pre>
515 *
516 * @param typeFaceNames - the name(s) of the intended typeface
517 */
518 public static Font.Typeface makeTypeface(String typeFaceNames) {
519 if (typeFaceNames.charAt(0) == '\'' && typeFaceNames.charAt(typeFaceNames.length()-1) == '\'') {
520 typeFaceNames = typeFaceNames.substring(1,typeFaceNames.length()-1);
521 }
522 String[] tokens = TokenizerKit.tokenizeStrict(typeFaceNames,",");
523 if (tokens.length == 0)
524 return null;
525 Font.Typeface typeFace;
526 typeFace = getSystemTypeface(tokens[0].toUpperCase());
527 //
528 // if we have only one token and it matches a System
529 // Typeface, then we will go with it
530 if (tokens.length == 1 && typeFace != null) {
531 return typeFace;
532 } else {
533 if (_exactMatchingTypeFace(typeFace,tokens)) {
534 return typeFace;
535 } else {
536 typeFace = null;
537 for (int i = tokens.length-1; i >= 0; i--) {
538 typeFace = new Font.Typeface(tokens[i],typeFace);
539 }
540 return typeFace;
541 }
542 }
543 }
544
545 /*
546 * Returns true if the type face provided exactly matches the list of font names
547 */
548 private static boolean _exactMatchingTypeFace(Font.Typeface typeFace, String[] fontNames) {
549 if (typeFace == null)
550 return false;
551 int i = 0;
552 while (typeFace != null) {
553 if (i >= fontNames.length)
554 return false;
555 if (! fontNames[i].equalsIgnoreCase(typeFace.getName())) {
556 return false;
557 }
558 typeFace = typeFace.getAlternate();
559 i++;
560 }
561 return true;
562 }
563
564 /*
565 * Gets a Font from the cache if its matches the font string
566 * It may be null if is not been cached. The strings are
567 * always stored in lower case for consistency
568 */
569 private static Font _getCachedFont(String fontString) {
570 fontString = fontString.trim().toLowerCase();
571 Font font = (Font) fontMap.get(fontString);
572 return font;
573 }
574
575 /*
576 * Puts a Font into the shared cache and then returns it
577 */
578 private static Font _putCachedFont(String fontString, Font font) {
579 fontString = fontString.trim().toLowerCase();
580 fontMap.put(fontString, font);
581 return font;
582 }
583
584
585 /*
586 * Well is it an integer?
587 */
588 private static boolean _isInteger(String propertyValue) {
589 try {
590 Integer.parseInt(propertyValue.trim());
591 } catch (NumberFormatException nfe) {
592 return false;
593 }
594 return true;
595 }
596
597 /**
598 * Makes a string representation of a font in the format
599 * <p>
600 * font(fontName, fontStyle, fontSize)
601 * <p>
602 * where :
603 * <p>
604 * fontName - is a font name such as 'Verdana' or 'Times New Roman'.
605 * fontStyle - PLAIN|BOLD|ITALIC|UNDERLINE
606 * fontSize - an integer size value or an Extent value. (In the case where
607 * only an integer is specified, the default Extent units
608 * are points (pt).
609 *
610 * @param font - the font to make into a String representation
611 * @return the string representation of the font
612 */
613 public static String makeFontString(Font font) {
614 return _buildFontString(font.getTypeface(),_getStyle(font),font.getSize());
615 }
616
617 /**
618 * Returns one the standard Echo Font.Typefaces if the name string
619 * matches the first Typeface in the chain.
620 *
621 * @param name - the font typeface name to match.
622 * @return a TypeFace of null if a system one cannot be found
623 */
624 public static Font.Typeface getSystemTypeface(String name) {
625 if (TYPEFACE_TEXT_TO_CONSTANT.containsKey(name.toUpperCase())) {
626 return (Font.Typeface) TYPEFACE_TEXT_TO_CONSTANT.get(name.toUpperCase());
627 } else {
628 return null;
629 }
630 }
631
632
633 /*
634 * Returns a font style integer value of -1 if it cant be found
635 */
636 private static int _getFontStyle(String styleName) {
637 Integer styleInt = (Integer) FONTSTYLE_TEXT_TO_CONSTANT.get(styleName.toUpperCase());
638 if (styleInt == null)
639 return -1;
640 return styleInt.intValue();
641 }
642
643 /*
644 * Builds a Font string from the given font attributes, This
645 * can then be used for font caching etc.. as well as returned
646 * as a Font String representation
647 * */
648 private static String _buildFontString(Font.Typeface typeFace, int style, Extent sizeExtent) {
649 StringBuffer sb = new StringBuffer();
650 sb.append("font(");
651
652 int i = 0;
653 while (typeFace != null) {
654 if (i > 0)
655 sb.append(", ");
656 else
657 sb.append("'");
658
659 sb.append(typeFace.getName());
660 i++;
661 typeFace = typeFace.getAlternate();
662 if (typeFace == null)
663 sb.append("'");
664 }
665
666 boolean isplain = true;
667 boolean needsOr = false;
668 sb.append(",");
669 if ((style & Font.BOLD) == Font.BOLD) {
670 if (needsOr) sb.append("|");
671 sb.append("BOLD");
672 needsOr = true;
673 isplain = false;
674 }
675 if ((style & Font.ITALIC) == Font.ITALIC) {
676 if (needsOr) sb.append("|");
677 sb.append("ITALIC");
678 needsOr = true;
679 isplain = false;
680 }
681 if ((style & Font.UNDERLINE) == Font.UNDERLINE) {
682 if (needsOr) sb.append("|");
683 sb.append("UNDERLINE");
684 needsOr = true;
685 isplain = false;
686 }
687 if ((style & Font.OVERLINE) == Font.OVERLINE) {
688 if (needsOr) sb.append("|");
689 sb.append("OVERLINE");
690 needsOr = true;
691 isplain = false;
692 }
693 if ((style & Font.LINE_THROUGH) == Font.LINE_THROUGH) {
694 if (needsOr) sb.append("|");
695 sb.append("LINETHROUGH");
696 needsOr = true;
697 isplain = false;
698 }
699 if (isplain)
700 sb.append("PLAIN");
701
702 if (sizeExtent != null) {
703 sb.append(",");
704 sb.append(sizeExtent.toString());
705 }
706 sb.append(")");
707 return sb.toString();
708 }
709
710 /*
711 * Builds a Font object from a valid font string, which is
712 * then cached in our global Font cache.
713 */
714 private static Font _buildFontObj(Font.Typeface typeface, int style, Extent sizeExtent) {
715 String fontString = _buildFontString(typeface,style,sizeExtent);
716 return makeFont(fontString);
717 }
718
719
720 /*
721 * Adds style bits to an exisitng font
722 */
723 static private int _addFontStyle(Font font, int newStyle) {
724 int style = Font.PLAIN;
725 if (font.isBold())
726 style |= Font.BOLD;
727 if (font.isItalic())
728 style |= Font.ITALIC;
729 if (font.isUnderline())
730 style |= Font.UNDERLINE;
731
732 style |= newStyle;
733 return style;
734 }
735
736 /*
737 * Returns the style bits of the font.
738 */
739 static private int _getStyle(Font font) {
740 return _addFontStyle(font,0);
741 }
742
743 /**
744 * Adds the Font.BOLD attribute to an exisitng Font object
745 * and returns a new Font.
746 * <p>
747 * @param font - the font in question
748 * @return - a new Font object
749 */
750 public static Font addBold(Font font) {
751 return addStyle(font,Font.BOLD);
752 }
753
754 /**
755 * Adds the Font.ITALIC attribute to an exisitng Font object
756 * and returns a new Font.
757 * <p>
758 * @param font - the font in question
759 * @return - a new Font object
760 */
761 public static Font addItalic(Font font) {
762 if (font == null)
763 return null;
764 return addStyle(font,Font.ITALIC);
765 }
766
767 /**
768 * Adds the Font.UNDERLINE attribute to an exisitng Font object
769 * and returns a new Font.
770 * <p>
771 * @param font - the font in question
772 * @return - a new Font object
773 */
774 public static Font addUnderline(Font font) {
775 return addStyle(font,Font.UNDERLINE);
776 }
777
778 /**
779 * Adds the specified <code>style</code> to the Font
780 * and returns a new Font.
781 * <p>
782 * @param font - the font in question
783 * @param style - the new font style to added to the font
784 * @return - a new Font object
785 */
786 public static Font addStyle(Font font, int style) {
787 if (font == null)
788 return null;
789 return _buildFontObj(font.getTypeface(),_addFontStyle(font, style),font.getSize());
790 }
791
792 /**
793 * Makes a font smaller or larger by adding the specified amount to
794 * its current font size. The Font is made smaller if a negative
795 * value is used.
796 *
797 * @param font - the font in question
798 * @param sizeDelta - the size delta to add to the current size
799 * @return - a new Font object
800 *
801 */
802 public static Font addSize(Font font, int sizeDelta) {
803 if (font == null)
804 return null;
805 Extent now = font.getSize();
806 if (now != null)
807 now = new Extent(now.getValue()+sizeDelta, now.getUnits());
808 return _buildFontObj(font.getTypeface(),_getStyle(font),now);
809 }
810
811 /**
812 * Returns a new Font object, based on <code>font</code>, that
813 * has the specified <code>size</code>.
814 *
815 * @param font - the font to use as a template
816 * @param size - the new size
817 * @return a new Font object with the new size
818 */
819 public static Font setSize(Font font, int size) {
820 if (font == null)
821 return null;
822 Extent now = font.getSize();
823 if (now != null)
824 now = new Extent(size, now.getUnits());
825 return _buildFontObj(font.getTypeface(),_getStyle(font),now);
826 }
827
828 /**
829 * Returns a new Font object, based on <code>font</code>, that
830 * has the specified <code>style</code>.
831 *
832 * @param font - the font to use as a template
833 * @param style - the new style
834 * @return a new Font object with the new style
835 */
836 public static Font setStyle(Font font, int style) {
837 if (font == null)
838 return null;
839 return _buildFontObj(font.getTypeface(),style,font.getSize());
840 }
841
842 /**
843 * Returns a new Font object, based on <code>font</code>, that
844 * has the specified <code>typeFace</code>.
845 *
846 * @param font - the font to use as a template
847 * @param typeFace - the new TypeFace to use
848 * @return a new Font object with the new font names
849 */
850 public static Font setNames(Font font, Font.Typeface typeFace) {
851 if (font == null)
852 return null;
853 return _buildFontObj(typeFace,_getStyle(font),font.getSize());
854 }
855
856 /**
857 * Returns a new Font object, based on <code>font</code>, that
858 * has the specified <code>fontName</code>.
859 * <p>
860 * If <code>fontName</code> has whitespace in it, then
861 * you need to surround it in single quotes.
862 *
863 * @param font - the font to use as a template
864 * @param fontName - the new font name to use
865 * @return a new Font object with the new font name
866 */
867 public static Font setName(Font font, String fontName) {
868 if (font == null)
869 return null;
870 Font.Typeface typeFace = makeTypeface(fontName);
871 return _buildFontObj(typeFace,_getStyle(font),font.getSize());
872 }
873 }