/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 1998, 1999 Wabasoft <www.wabasoft.com> * * Copyright (C) 2000-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.ui.font; import totalcross.Launcher; import totalcross.sys.Settings; import totalcross.util.Hashtable; /** * Font is the character font used when drawing text on a surface. * Fonts can be antialiased, and usually range from size 7 to 38. * In OpenGL platforms, they are 8bpp antialiased fonts ranging up indefinedly. * <ol> * <li> To see if the font you created is installed in the target device, query its name after * the creation. If the font is not found, its name is changed to match the default font. * <li> You may create new fonts based on the TrueType fonts using the tool tc.tools.FontGenerator. * <li> There are two font sets: the one before TotalCross 1.3, and the one after TotalCross 1.3. The font set is * choosen using Settings.useNewFont. * <li> The default font size is based in the device's DPI. This allows the font to have the same physical size * in inches on different devices. * <li> In JavaSE you can choose the default font size passing <code>/fontsize <size></code> as argument, * before the application's name. * </ol> */ public final class Font { /** Read only field that contains the font's name. Note that changing this directly will have no effect. */ public String name; /** Read only field that contains the font's style. Note that changing this directly will have no effect. For bold fonts, style == 1. */ public int style; /** Read only field that contains the font's size. Note that changing this directly will have no effect. */ public int size; // HOOK VARIABLES - can't be private - guich@350_20 public Object hv_UserFont; public FontMetrics fm; /** The default font name. If a specified font is not found, this one is used instead. */ public static final String DEFAULT = "TCFont"; /** The minimum font size: 7. */ public static int MIN_FONT_SIZE = 7; /** The maximum font size: 48 for Windows32, unlimited for OpenGL platforms (the number here will be 80, * since this is the size that the base font was created; you can specify something higher, but it will use * upscaling, which usually results in a smooth font). */ public static int MAX_FONT_SIZE = Settings.WIN32.equals(Settings.platform) ? 48 : 80; /** For internal use only. */ public static int baseChar = ' '; /** Returns the default font size, based on the screen's size. */ public static int getDefaultFontSize() { int fontSize = Settings.onJavaSE ? returnUserSize() : -1; if (fontSize != -1) return fontSize; // determine fonts as if we were in portrait mode int w,h; w = Math.min(Settings.screenWidth,Settings.screenHeight); h = Math.max(Settings.screenWidth,Settings.screenHeight); if (Settings.isWindowsDevice()) // flsobral@tc126_49: with the exception of WindowsCE and WinMo, the font size is now based on the screen resolution for all platforms to better support small phones and tablets. fontSize = Settings.screenWidth >= 480 ? 28 : Settings.screenWidth >= 320 ? 18 : 14; // added this exception to get the right font when running in the WM phone in landscape mode else if (Settings.WINDOWSPHONE.equals(Settings.platform) || (Settings.WIN32.equals(Settings.platform) && Settings.windowFont == Settings.WINDOWFONT_DEFAULT)) fontSize = Settings.deviceFontHeight; else if (Settings.ANDROID.equals(Settings.platform)) // guich@tc126_69 fontSize = 20 * Settings.deviceFontHeight / 14; else if (Settings.isIOS() && Settings.deviceFontHeight != 0) fontSize = Settings.deviceFontHeight; else switch (w) { // some predefined device screen sizes case 480: case 360: case 320: if (h < 240) fontSize = 13; else if(h == 240) fontSize = 14; else fontSize = 18; break; case 640: case 240: case 220: case 200: fontSize = 12; break; default : if (w >= 600 || h >= 800) // bigger font for tablets, final value will be 26 if the device is fingerTouch fontSize = 23; else fontSize = 9; // guich@tc123_13: pk doesn't like to have a size=20 for above 640 } if (fontSize < MIN_FONT_SIZE) fontSize = MIN_FONT_SIZE; else if (!Settings.isOpenGL && fontSize > MAX_FONT_SIZE) fontSize = MAX_FONT_SIZE; return fontSize; } private static int returnUserSize() // guich@tc130: allow user to set the font size throught the Launcher { return Launcher.userFontSize; } /** A normal-sized font */ public static final int NORMAL_SIZE = getDefaultFontSize(); /** A big-sized font (2 above the normal size) */ public static final int BIG_SIZE = NORMAL_SIZE+2; /** When the vm draws a character and founds the tab char, it will draw a set of spaces. * You can define the number of spaces that will be drawn setting this field. * It defaults to 3, but you can change at any time. */ public static int TAB_SIZE = 3; private static Hashtable htFonts = new Hashtable(13); private Font(String name, boolean boldStyle, int size) // guich@580_10 { if (size == 0) throw new RuntimeException("Font size cannot be 0!"); this.name = name; this.style = boldStyle ? 1 : 0; this.size = size; fontCreate(); fm = new FontMetrics(this); // guich@450_36: get out fontmetrics at once. } /** * Gets the instance of the default font, with the given style and size. * @param boldStyle If true, a bold font is used. Otherwise, a plain font is used. * @param size If you want a text bigger than the standard size, use Font.NORMAL_SIZE+x; or if you want * a text smaller than the standard size, use Font.NORMAL_SIZE-x. Size is adjusted to be in the range * <code>Font.MIN_FONT_SIZE ... Font.MAX_FONT_SIZE</code>. That is, passing a value out of the bounds * won't throw an exception, will only use the minimum default size if the size passed is less than it or * use the maximum default size if the size passed is greater than it. */ public static Font getFont(boolean boldStyle, int size) // guich@580_10 { return getFont(DEFAULT, boldStyle, size); } /** * Gets the instance of a font of the given name, style and size. Font styles are defined * in this class. Font.DEFAULT will be used if the font is not installed on the device. * This method can be used to check if the created font is in fact installed on the device. * @param name Font.DEFAULT is the default font. You must install other fonts if you want to use them. * @param boldStyle If true, a bold font is used. Otherwise, a plain font is used. * @param size If you want a text bigger than the standard size, use Font.NORMAL_SIZE+x; or if you want * a text smaller than the standard size, use Font.NORMAL_SIZE-x. Size is adjusted to be in the range * <code>Font.MIN_FONT_SIZE ... Font.MAX_FONT_SIZE</code>. That is, passing a value out of the bounds won't throw an exception, * will only use the minimum default size if the size passed is less than it or use the maximum default size if the size passed is * greater than it. */ public static Font getFont(String name, boolean boldStyle, int size) // guich@580_10 { char st = boldStyle ? 'B' : 'P'; String key = name+'$'+st+size; Font f = baseChar == ' ' ? (Font)htFonts.get(key) : null; if (f == null) htFonts.put(key, f = new Font(name, boldStyle, size)); return f; } /** Returns this font as Bold */ public Font asBold() { return getFont(name,true,size); // guich@450_36: cache the bolded font - guich@580_10: cached now in the Hashtable. } /** Returns a font with the size changed with that delta. * The new size is thisFont.size+delta. * delta can be positive or negative. The new size won't pass the minimum nor the maximum sizes. * @since TotalCross 1.3 */ public Font adjustedBy(int delta) { return getFont(name,style == 1, size + delta); } /** Returns a font with the size changed with that delta and the given bold style. * The new size is thisFont.size+delta. * delta can be positive or negative. The new size won't pass the minimum nor the maximum sizes. * @since TotalCross 1.3 */ public Font adjustedBy(int delta, boolean bold) { return getFont(name,bold, size + delta); } /** Returns if this font is bold. * @since TotalCross 1.53 */ public boolean isBold() { return style == 1; } ///// Native methods native void fontCreate4D(); void fontCreate() { hv_UserFont = Launcher.instance.getFont(this, (char)baseChar); } /** Used internally. */ public void removeFromCache() { char st = style==1 ? 'B' : 'P'; String key = name+'$'+st+size; htFonts.remove(key); } public void removeFromCache4D() { } }