Bug 12450 fixed: xlfont() did not return font names as specified int the doc
[scilab.git] / scilab / modules / renderer / src / java / org / scilab / modules / renderer / utils / textRendering / FontManager.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2007 - INRIA - Jean-Baptiste Silvy
4  * Copyright (C) 2008 - INRIA - Allan CORNET
5  * desc : Singleton class used to set font of text objects
6  *
7  * This file must be used under the terms of the CeCILL.
8  * This source file is licensed as described in the file COPYING, which
9  * you should have received as part of this distribution.  The terms
10  * are also available at
11  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
12  *
13  */
14
15
16 package org.scilab.modules.renderer.utils.textRendering;
17
18 import java.io.FileInputStream;
19 import java.io.File;
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 import java.awt.Font;
23 import java.awt.FontFormatException;
24 import java.awt.GraphicsEnvironment;
25 import java.util.ArrayList;
26
27 /**
28  * Singleton class used to set font of text objects.
29  * @author Jean-Baptiste Silvy
30  */
31 public class FontManager {
32
33     private static final String SCIDIR = System.getenv("SCI");
34     private static final float[] INTERVALS = {3.0f, 4.0f, 5.0f};
35     private static final float[] FIRST_POLY = {2.0f, 8.0f};
36     private static final float[] SECOND_POLY = {4.0f, 2.0f};
37     private static final float[] THIRD_POLY = {6.0f, -6.0f};
38     private static final float[] FOURTH_POLY = {10.0f, -26.0f};
39
40     private static final float SIX = 6.0f;
41
42     private static final float[] INV_INTERVALS = {14.0f, 18.0f, 24.0f};
43     private static final float[] INV_FIRST_POLY = {0.5f, -4.0f};
44     private static final float[] INV_SECOND_POLY = {0.25f, -0.5f};
45     private static final float[] INV_THIRD_POLY = {1.0f / SIX, 1.0f};
46     private static final float[] INV_FOURTH_POLY = {0.1f, 2.6f};
47
48
49     // logical awt fonts
50     // JRE Java guaranteed: "Dialog", "DialogInput",
51     // "Monospaced","Serif", "SansSerif", "Symbol", "Lucida"
52     // Scilab 4.x fonts --> fonts with JRE 1.5 or more
53     // Times            --> Serif
54     // Helvetica        --> SansSerif
55     // Courier          --> Monospaced
56     // Symbol           --> Scilab Symbols font
57
58     private static final String MONOSPACED = "Monospaced";
59     private static final String SANSSERIF = "SansSerif";
60     private static final String SERIF = "Serif";
61     private static final String SCILABSYMBOLSFONT = "ScilabSymbols";
62     private static final String SYMBOLSFONTPATH = "/thirdparty/fonts/scilabsymbols.ttf";
63     private static final Font DEFAULT_FONT = new Font("Default", Font.PLAIN, 1);
64
65     /** Singleton instance. */
66     private static FontManager sciFontManager;
67
68     /**
69      * A list of fonts.
70      */
71     private static class FontList extends ArrayList<Font> {
72
73         private static final long serialVersionUID = 1L;
74
75         /**
76          * Default constructor.
77          */
78         public FontList() {
79             super();
80         }
81     }
82
83     private static FontList sciFonts;
84
85     /**
86      * Default constructor.
87      * Should not be called.
88      */
89     protected FontManager() {
90         if (sciFontManager == null) {
91             initializeFontManager();
92         }
93     }
94
95     /**
96      * Get the font manager instance
97      * @return the only instance of fontmanager.
98      */
99     public static FontManager getSciFontManager() {
100         if (sciFontManager == null) {
101             sciFontManager = new FontManager();
102         }
103
104         return sciFontManager;
105     }
106
107     /**
108      * Convert sciab font size to awt font size.
109      * We use a degree 2 polygon to compute this.
110      * We use canonical form of the polygon so the inverse function is easy to compute
111      * Tthe equivalence list is (0 => 8, 1 => 10, 2 => 12, 3 => 14, 4 => 18, 5 => 24).
112      * @param sciSize scilab size
113      * @return awt size
114      */
115     public static float scilabSizeToAwtSize(double sciSize) {
116         float sciSizef = (float) sciSize;
117         // f(x) = | 2x + 8 if x < 3
118         //        | 4x + 2 if 3 < x < 4
119         //        | 6x - 6 if 4 < x
120         if (sciSizef < INTERVALS[0]) {
121             return FIRST_POLY[0] * sciSizef + FIRST_POLY[1];
122         } else if (sciSizef < INTERVALS[1]) {
123             return SECOND_POLY[0] * sciSizef + SECOND_POLY[1];
124         } else if (sciSizef < INTERVALS[2]) {
125             return THIRD_POLY[0] * sciSizef + THIRD_POLY[1];
126         } else {
127             return FOURTH_POLY[0] * sciSizef + FOURTH_POLY[1];
128         }
129     }
130
131     /**
132      * Inverse of scilabSizeToAwtSize function
133      * @param size size of a AWT font
134      * @return corresponding size in Scilab
135      */
136     public static double awtSizeToScilabSize(float size) {
137         // sqrt(|x - c| / a) - b
138         if (size < INV_INTERVALS[0]) {
139             return INV_FIRST_POLY[0] * size + INV_FIRST_POLY[1];
140         } else if (size < INV_INTERVALS[1]) {
141             return INV_SECOND_POLY[0] * size + INV_SECOND_POLY[1];
142         } else if (size < INV_INTERVALS[2]) {
143             return INV_THIRD_POLY[0] * size + INV_THIRD_POLY[1];
144         } else {
145             return INV_FOURTH_POLY[0] * size + INV_FOURTH_POLY[1];
146         }
147     }
148
149     /**
150      * Get a font from its index in Scilab.
151      * @param fontIndex scilab index of the font.
152      * @return font corresponding to the index with size 1.
153      */
154     public final Font getFontFromIndex(int fontIndex) {
155         if (fontIndex >= 0 && fontIndex < sciFonts.size()) {
156             return sciFonts.get(fontIndex);
157         } else if (fontIndex < 0) {
158             return sciFonts.get(0);
159         } else {
160             return sciFonts.get(sciFonts.size() - 1);
161         }
162     }
163
164     /**
165      * Get a font from its index in Scilab.
166      * @param fontIndex scilab index of the font.
167      * @param fontSize size of the font (scilab size).
168      * @return font corresponding to the index.
169      */
170     public final Font getFontFromIndex(int fontIndex, double fontSize) {
171         Font res = getFontFromIndex(fontIndex);
172         return res.deriveFont(scilabSizeToAwtSize(fontSize));
173     }
174     /**
175      * Add a new font in the font list.
176      * @param newFont font to add to the list
177      * @return index of added font.
178      */
179     public final int addFont(Font newFont) {
180         sciFonts.add(newFont);
181         return sciFonts.size() - 1;
182     }
183
184     /**
185      * Replace a font in the font list by a new one.
186      * @param index index of the font to replace
187      * @param newFont font to add in the font list.
188      * @return index of the added font or -1 if an error occurred.
189      */
190     public final int changeFont(int index, Font newFont) {
191         int nbFonts = sciFonts.size();
192         if (index > nbFonts) {
193             // we need to add fonts until index
194             for (int i = nbFonts; i < index; i++) {
195                 addFont(DEFAULT_FONT);
196             }
197             return addFont(newFont);
198         } else if (index == nbFonts) {
199             // add a new Font
200             return addFont(newFont);
201         } else {
202             sciFonts.set(index, newFont);
203             return index;
204         }
205
206     }
207
208     /**
209      * Create a new font knowing its name and size.
210      * @param fontName Name of the font.
211      * @return new font.
212      */
213     protected final Font createFont(String fontName) {
214         // size must be applied after.
215         // by default, we use PLAIN font.
216         return new Font(fontName, Font.PLAIN, 1);
217     }
218
219     /**
220      * Load scilab symbols font
221      * @return font.
222      */
223     protected final Font loadScilabSymbolFont() {
224         return loadFont(SCIDIR + SYMBOLSFONTPATH);
225     }
226
227     /**
228      * load a font from filename
229      * @param fontFileName filename of the font.
230      * @return font.
231      */
232     protected final Font loadFont(String fontFileName) {
233         Font loadedFont;
234         FileInputStream in;
235         File f = new File(fontFileName);
236         try {
237             in = new FileInputStream(f);
238         } catch (FileNotFoundException e) {
239             loadedFont = DEFAULT_FONT;
240             return loadedFont;
241         }
242
243         try {
244             loadedFont = Font.createFont(Font.TRUETYPE_FONT, in);
245         } catch (IOException e) {
246             loadedFont = DEFAULT_FONT;
247         } catch (FontFormatException ffe) {
248             loadedFont = DEFAULT_FONT;
249         }
250
251         return loadedFont;
252     }
253
254     /**
255      * Create a new font knowing its name and size.
256      * @param fontName Name of the font.
257      * @param isBold wether the font is bold or not.
258      * @param isItalic wether the font is in italic or not.
259      * @return new font.
260      */
261     protected final Font createFont(String fontName, boolean isBold, boolean isItalic) {
262         int style;
263         if (isBold && isItalic) {
264             style = Font.BOLD | Font.ITALIC;
265         } else if (isBold) {
266             style = Font.BOLD;
267         } else if (isItalic) {
268             style = Font.ITALIC;
269         } else {
270             style = Font.PLAIN;
271         }
272         return new Font(fontName, style, 1);
273     }
274
275     /**
276      * Add a new font from its font name.
277      * @param fontName name of the font to add.
278      * @return index of the added font.
279      */
280     public final int addFont(String fontName) {
281         return addFont(createFont(fontName));
282     }
283
284     /**
285      * Add a new font from its font name.
286      * @param fontName name of the font to add.
287      * @param isBold wether the font is bold or not.
288      * @param isItalic wether the font is in italic or not.
289      * @return index of the added font.
290      */
291     public final int addFont(String fontName, boolean isBold, boolean isItalic) {
292         return addFont(createFont(fontName, isBold, isItalic));
293     }
294
295     /**
296      * Add a new font from its filename.
297      * @param fontFilename  filename of the font to add.
298      * @return index of the added font.
299      */
300     public final int addFontFromFilename(String fontFilename) {
301         return addFont(loadFont(fontFilename));
302     }
303
304     /**
305      * Replace a font in the font list by a new one.
306      * @param index index of the font to replace
307      * @param fontName Name of the font.
308      * @return index of the added font or -1 if an error occurred.
309      */
310
311     public final int changeFont(int index, String fontName) {
312         return changeFont(index, createFont(fontName));
313     }
314
315     /**
316     * Replace a font in the font list by a new one loaded from a file.
317     * @param index index of the font to replace
318     * @param fontFilename  filename of the font
319     * @return index of the added font or -1 if an error occurred.
320     */
321     public final int changeFontFromFilename(int index, String fontFilename) {
322         return changeFont(index, loadFont(fontFilename));
323     }
324
325     /**
326      * Replace a font in the font list by a new one.
327      * @param index index of the font to replace
328      * @param fontName Name of the font.
329      * @param isBold wether the font is bold or not.
330      * @param isItalic wether the font is in italic or not.
331      * @return index of the added font or -1 if an error occurred.
332      */
333     public final int changeFont(int index, String fontName, boolean isBold, boolean isItalic) {
334         return changeFont(index, createFont(fontName, isBold, isItalic));
335     }
336
337     /**
338      * Get the list of all fonts available.
339      * @return Names of the available fonts.
340      */
341     public final String[] getAvailableFontsName() {
342         return GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
343     }
344
345     /**
346      * Get the size of list of all fonts available.
347      * @return size.
348      */
349     public final int getSizeAvailableFontsName() {
350         return GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames().length;
351     }
352
353     /**
354      * Check if fontname is available
355      * @param fontname Name of the font.
356      * @return true or false.
357      */
358     public final boolean isAvailableFontName(String fontname) {
359         int i = getSizeAvailableFontsName();
360         String[] availableFontsName = getAvailableFontsName();
361         for (i = 0; i < availableFontsName.length; i++) {
362             if (fontname.compareTo(availableFontsName[i]) == 0) {
363                 return true;
364             }
365         }
366         return false;
367     }
368
369     /**
370      * returns fontnames installed (used) by scilab
371      * @return fonts name
372      */
373     public final String[] getInstalledFontsName() {
374         int nbFonts = sciFonts.size();
375         String[] fontnames = new String[nbFonts];
376
377         for (int i = 0; i < nbFonts; i++) {
378             Font res = getFontFromIndex(i);
379             fontnames[i] = res.getFamily();
380             if (res.isBold()) {
381                 fontnames[i] += " Bold";
382             }
383             if (res.isItalic()) {
384                 fontnames[i] += " Italic";
385             }
386         }
387
388         return fontnames;
389     }
390
391     /**
392      * Returns number of fonts installed.
393      * @return number of fonts installed.
394      */
395     public final int getSizeInstalledFontsName() {
396         return sciFonts.size();
397     }
398
399     /**
400      * initializeFontManager
401      */
402     public final void initializeFontManager() {
403         sciFonts = new FontList();
404         // set default font
405         /* Fonts order in Scilab 4.x for compatibility */
406         /* Courrier --> Monospaced
407           Symbol --> Symbol
408           Times --> Serif
409           Times Italic --> Serif Italic
410           Times Bold --> Serif Bold
411           Times Bold Italic --> Serif Bold Italic
412           Helvetica --> SansSerif
413           Helvetica Italic --> SansSerif Italic
414           Helvetica Bold --> SansSerif Bold
415           Helveticas Bold Italic --> SansSerif bold Italic
416         */
417
418         sciFonts.add(createFont(MONOSPACED));             /* scilab font_style 0 */
419         /* Symbols font */                               /* scilab font_style 1 */
420         /* on scilab 4.x a --> alpha (symbol) */
421         /* with java , symbols are not ascii codes , but unicodes */
422         /* if font exists on system, we use else we try to load scilab symbols font (truetype) */
423         if (isAvailableFontName(SCILABSYMBOLSFONT)) {
424             sciFonts.add(createFont(SCILABSYMBOLSFONT));
425         } else {
426             sciFonts.add(loadScilabSymbolFont());
427         }
428         sciFonts.add(createFont(SERIF));                  /* scilab font_style 2 */
429         sciFonts.add(createFont(SERIF, false, true));     /* scilab font_style 3 */
430         sciFonts.add(createFont(SERIF, true, false));     /* scilab font_style 4 */
431         sciFonts.add(createFont(SERIF, true, true));      /* scilab font_style 5 */
432         sciFonts.add(createFont(SANSSERIF));              /* scilab font_style 6 */
433         sciFonts.add(createFont(SANSSERIF, false, true)); /* scilab font_style 7 */
434         sciFonts.add(createFont(SANSSERIF, true, false)); /* scilab font_style 8 */
435         sciFonts.add(createFont(SANSSERIF, true, true));  /* scilab font_style 9 */
436         sciFonts.add(createFont(SANSSERIF, true, true));  /* scilab font_style 10 */
437     }
438 }