diff -r e8e63152f320 -r 2a9601315dfc javauis/lcdui_qt/src/javax/microedition/lcdui/Font.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/lcdui_qt/src/javax/microedition/lcdui/Font.java Mon May 03 12:27:20 2010 +0300 @@ -0,0 +1,672 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ +package javax.microedition.lcdui; + +import java.util.Enumeration; +import java.util.Hashtable; + +import org.eclipse.ercp.swt.mobile.MobileShell; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.internal.qt.graphics.FontUtils; +import org.eclipse.swt.widgets.*; + +/** + * Implementation of LCDUI Font class. + */ +public final class Font { + + /** + * System font face. + * + * @value for FACE_SYSTEM is 0. + */ + public static final int FACE_SYSTEM = 0; + + /** + * Monospace font face. + * + * @value for FACE_MONOSPACE is 32. + */ + public static final int FACE_MONOSPACE = 32; + + /** + * Proportional font face. + * + * @value for FACE_PROPORTIONAL is 64. + */ + public static final int FACE_PROPORTIONAL = 64; + + /** + * Plain font style. + * + * @value for STYLE_PLAIN is 0. + */ + public static final int STYLE_PLAIN = 0; + + /** + * Bold font style. + * + * @value for STYLE_BOLD is 1. + */ + public static final int STYLE_BOLD = 1; + + /** + * Italic font style. + * + * @value for STYLE_ITALIC is 2. + */ + public static final int STYLE_ITALIC = 2; + + /** + * Underlined font style. + * + * @value for STYLE_UNDERLINED is 4. + */ + public static final int STYLE_UNDERLINED = 4; + + /** + * Small font size. + * + * @value for SIZE_SMALL is 8. + */ + public static final int SIZE_SMALL = 8; + + /** + * Medium font size. + * + * @value for SIZE_MEDIUM is 0. + */ + public static final int SIZE_MEDIUM = 0; + + /** + * Large font size. + * + * @value for SIZE_LARGE is 16. + */ + public static final int SIZE_LARGE = 16; + + /** + * Font specifier for default input text drawing. + * + * @value for FONT_INPUT_TEXT is 1. + */ + public static final int FONT_INPUT_TEXT = 1; + + /** + * Font specifier for default Item and Screen drawing. + * + * @value for FONT_STATIC_TEXT is 0. + */ + public static final int FONT_STATIC_TEXT = 0; + + private static final int STYLE_ALL = STYLE_PLAIN | STYLE_BOLD + | STYLE_ITALIC | STYLE_UNDERLINED; + + private static final String FONTDATA_CONST = "|-1|-1|-1|-1|-1|-1|1|"; + + /** + * Lookup table which stores LCDUI fonts based on FontData keys. + */ + private static Hashtable fontTable = new Hashtable(); + private static FontUtils fontUtils; + private static int[] tempFontRect = new int[4]; + private static FontData eswtTempFontData; + private static FontData eswtSystemFontData; + private int eswtTempFontAscent; + private int eswtTempFontHeight; + private int eswtTempFontWidth; + + // Instance members. + + private org.eclipse.swt.graphics.Font eswtFont; + private int face; + private int style; + private int size; + + /** + * Disposes all fonts created. + */ + static void disposeFonts() { + for (Enumeration e = fontTable.elements(); e.hasMoreElements();) { + Font font = (Font) e.nextElement(); + font.eswtFont.dispose(); + } + fontTable.clear(); + } + + /** + * LCDUI Font --> eSWT Font + */ + static org.eclipse.swt.graphics.Font getESWTFont(Font font) { + if (font != null) { + return font.eswtFont; + } + return null; + } + + /** + * eSWT Font --> LCDUI Font + */ + static Font getFont(final org.eclipse.swt.graphics.Font font) { + if (font != null) { + FontData fd = getFontData(font); + return getFont(fd); + } + return null; + } + + /** + * Returns default font. + * + * @return default system font. + */ + public static Font getDefaultFont() { + return getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM); + } + + /** + * Request specified Font. + * + * @param specifier font specifier + * @return the font + */ + public static Font getFont(int specifier) { + if (specifier == FONT_INPUT_TEXT || specifier == FONT_STATIC_TEXT) { + return getFont(getFontData(specifier)); + } + else { + throw new IllegalArgumentException( + MsgRepository.FONT_EXCEPTION_INVALID_SPECIFIER); + } + } + + /** + * Request Font based on parameters. + * + * @param face font face + * @param style font style + * @param size font size + * @return the font + */ + public static Font getFont(int face, int style, int size) { + if (face != FACE_SYSTEM && face != FACE_MONOSPACE + && face != FACE_PROPORTIONAL) { + throw new IllegalArgumentException( + MsgRepository.FONT_EXCEPTION_INVALID_FACE); + } + if (style < STYLE_PLAIN || style > STYLE_ALL) { + throw new IllegalArgumentException( + MsgRepository.FONT_EXCEPTION_INVALID_STYLE); + } + if (size != SIZE_SMALL && size != SIZE_MEDIUM && size != SIZE_LARGE) { + throw new IllegalArgumentException( + MsgRepository.FONT_EXCEPTION_INVALID_SIZE); + } + FontData fd = getFontData(face, style, size); + Font font = getFont(fd); + // We must handle underlining separately because it is not part of + // eSWT's style. + if ((style & Font.STYLE_UNDERLINED) == Font.STYLE_UNDERLINED) { + font.style |= Font.STYLE_UNDERLINED; + } + return font; + } + + /** + * Request freesized Font. + * + * @param face font face + * @param style font style + * @param height font height + * @return the font + */ + static Font getFreeSizedFont(int face, int style, int height) { + if (face != FACE_SYSTEM && face != FACE_MONOSPACE + && face != FACE_PROPORTIONAL) { + throw new IllegalArgumentException( + MsgRepository.FONT_EXCEPTION_INVALID_FACE); + } + if (style < STYLE_PLAIN || style > STYLE_ALL) { + throw new IllegalArgumentException( + MsgRepository.FONT_EXCEPTION_INVALID_STYLE); + } + if (height < 0) { + throw new IllegalArgumentException( + MsgRepository.FONT_EXCEPTION_INVALID_SIZE); + } + FontData fd = getFontData(face, style, height); + Font font = getFont(fd); + // We must handle underlining separately because it is not part of + // eSWT's style. + if ((style & Font.STYLE_UNDERLINED) == Font.STYLE_UNDERLINED) { + font.style |= Font.STYLE_UNDERLINED; + } + return font; + } + + /** + * Lookup or create a font based on given FontData. + * + * @param fontdata font's data + * @return a font + */ + private static Font getFont(FontData fontdata) { + Font ret = null; + if (fontdata != null) { + if (fontTable.containsKey(fontdata)) { + ret = (Font) fontTable.get(fontdata); + } + else { + ret = new Font(fontdata); + } + } + return ret; + } + + /** + * Constructor (private).
+ * + * @param reqFD the requested eSWT FontData + */ + private Font(final FontData reqFD) { + ESWTUIThreadRunner.syncExec(new Runnable() { + public void run() { + eswtFont = new org.eclipse.swt.graphics.Font(ESWTUIThreadRunner + .getInstance().getDisplay(), reqFD); + } + }); + // get FontData info from resulted Font, because resulting FontData + // might be different than the requested one + FontData resFD = getFontData(eswtFont); + this.face = mapFontNameToFace(resFD.getName()); + this.style = mapESWTStyleToStyle(resFD.getStyle()); + this.size = mapHeightToSize(resFD.getHeight()); + fontTable.put(resFD, this); + } + + /** + * Return font's style. + * + * @return style + */ + public int getStyle() { + return style; + } + + /** + * Return font's size. + * + * @return size + */ + public int getSize() { + return size; + } + + /** + * Return font's face. + * + * @return face + */ + public int getFace() { + return face; + } + + /** + * Checks if the font is plain styled. + * + * @return true if the font is plain, false otherwise + */ + public boolean isPlain() { + return (style == Font.STYLE_PLAIN); + } + + /** + * Checks if the font is bold styled. + * + * @return true if the font is bold, false otherwise + */ + public boolean isBold() { + return ((style & Font.STYLE_BOLD) == Font.STYLE_BOLD); + } + + /** + * Checks if the font is italic styled. + * + * @return true if the font is italic, false otherwise + */ + public boolean isItalic() { + return ((style & Font.STYLE_ITALIC) == Font.STYLE_ITALIC); + } + + /** + * Checks if the font is underlined styled. + * + * @return true if the font is underlined, false otherwise. + */ + public boolean isUnderlined() { + return ((style & Font.STYLE_UNDERLINED) == Font.STYLE_UNDERLINED); + } + + /** + * Return font's height. + * + * @return height + */ + public int getHeight() { + if (eswtTempFontHeight == 0) { + ESWTUIThreadRunner.safeSyncExec(new Runnable() { + public void run() { + FontUtils fu = eswtGetFontUtils(eswtFont); + eswtTempFontHeight = fu.getAscent() + fu.getDescent(); + } + }); + } + return eswtTempFontHeight; + } + + /** + * The position of the baseline from the top of the font in pixels. + * + * @return the baseline position + */ + public int getBaselinePosition() { + if (eswtTempFontAscent == 0) { + ESWTUIThreadRunner.safeSyncExec(new Runnable() { + public void run() { + eswtTempFontAscent = eswtGetFontUtils(eswtFont).getAscent(); + } + }); + } + return eswtTempFontAscent; + } + + /** + * Returns the width of the given character in pixels. + * + * @param c the character + * @return the width + */ + public int charWidth(char c) { + return stringWidth(String.valueOf(c)); + } + + /** + * Returns the width of the given character array's region in pixels. + * + * @param c characters + * @param offset starting position + * @param length the length + * @return the width + */ + public int charsWidth(char[] c, int offset, int length) { + return stringWidth(new String(c, offset, length)); + } + + /** + * Returns string width in pixels. + * + * @param string the string + * @return the width + */ + public int stringWidth(String string) { + if (string == null) { + throw new NullPointerException( + MsgRepository.FONT_EXCEPTION_NULL_STRING); + } + final String finalString = string; + eswtTempFontWidth = 0; + ESWTUIThreadRunner.safeSyncExec(new Runnable() { + public void run() { + eswtGetFontUtils(eswtFont).getBoundingRect(tempFontRect, finalString); + eswtTempFontWidth = tempFontRect[2]; + } + }); + return eswtTempFontWidth; + } + + /** + * Get the static FontUtils instance setup with given font. + */ + private static FontUtils eswtGetFontUtils(org.eclipse.swt.graphics.Font font) { + if (fontUtils == null) { + fontUtils = new FontUtils(font.handle); + } + else { + fontUtils.setFont(font.handle); + } + return fontUtils; + } + + /** + * Returns sub-string width in pixels. + * + * @param string the string + * @param offset starting position + * @param length the length + * @return the width of the specified region + */ + public int substringWidth(String string, int offset, int length) { + return stringWidth(string.substring(offset, offset + length)); + } + + /** + * Get FontData of a eSWT control. + * + * @param control eSWT control + * @return FontData + */ + private static FontData getFontData(final int specifier) { + ESWTUIThreadRunner.syncExec(new Runnable() { + public void run() { + Control control = null; + MobileShell shell = new MobileShell(ESWTUIThreadRunner + .getInstance().getDisplay(), SWT.NONE); + if (specifier == FONT_INPUT_TEXT) { + control = new Text(shell, SWT.NONE); + } + else { + control = new Label(shell, SWT.NONE); + } + eswtTempFontData = control.getFont().getFontData()[0]; + control.dispose(); + shell.dispose(); + } + }); + return eswtTempFontData; + } + + /** + * Get FontData of a eSWT font. + * + * @param font eSWT font + * @return FontData + */ + private static FontData getFontData( + final org.eclipse.swt.graphics.Font font) { + ESWTUIThreadRunner.syncExec(new Runnable() { + public void run() { + eswtTempFontData = font.getFontData()[0]; + } + }); + return eswtTempFontData; + } + + /** + * Construct FontData with the given specifiers. + * + * @return FontData + */ + private static FontData getFontData(final int face, final int style, + final int size) { + ESWTUIThreadRunner.syncExec(new Runnable() { + public void run() { + int underlined = 0; + if ((style & Font.STYLE_UNDERLINED) == Font.STYLE_UNDERLINED) { + underlined = 1; + } + /* FontData constructor format: + * version|name|height|style|underline| + * overline|strike|stretch|pitch|qt-style|weight|strategy| + */ + StringBuffer sb = new StringBuffer(); + sb.append("1|"); // version + sb.append(mapFaceToFontName(face)); // family name + sb.append("|"); + sb.append(mapSizeToHeight(size)); // height + sb.append("|"); + sb.append(mapStyleToESWTStyle(style)); // style + sb.append("|QT|1|");//Qt version 2 string for extra formats + sb.append((new Integer(underlined).toString())); // underline + sb.append(FONTDATA_CONST); + eswtTempFontData = new FontData(sb.toString()); + } + }); + return eswtTempFontData; + } + + /** + * Returns System default font's FontData instance. + * + * @return system FontData + */ + private static FontData getSystemFontData() { + if (eswtSystemFontData == null) { + ESWTUIThreadRunner.syncExec(new Runnable() { + public void run() { + eswtSystemFontData = ESWTUIThreadRunner.getInstance() + .getDisplay().getSystemFont().getFontData()[0]; + } + }); + } + return eswtSystemFontData; + } + + /** + * Get eSWT font name from LCDUI face parameter. + * + * @param face font's face type + * @return font name + */ + private static String mapFaceToFontName(int face) { + // TODO: how to map face values to names + switch (face) { + case Font.FACE_MONOSPACE: + case Font.FACE_PROPORTIONAL: + case Font.FACE_SYSTEM: + default: + return getSystemFontData().getName(); + } + } + + /** + * Get face of a given eSWT font name. + * + * @param eswtFontName font's name + * @return font face + */ + private static int mapFontNameToFace(String eswtFontName) { + // TODO: how to map names to face values + if (eswtFontName.equals(getSystemFontData().getName())) { + return Font.FACE_SYSTEM; + } + else { + // Font.FACE_MONOSPACE: + // Font.FACE_PROPORTIONAL: + return 0; + } + } + + /** + * Get eSWT font height from LCDUI size parameter.
+ * 0 maps to system's default font size, others map directly. + * + * @param size font's size + * @return font height + */ + private static int mapSizeToHeight(int size) { + //retreive the system default height + int defHeight = getSystemFontData().getHeight(); + + if (size == Font.SIZE_SMALL) { + //calculate the small size height as a ratio of system default medium size and round off the value to an integer + return (int)Math.floor( (defHeight * ( 3f/4 )) + 0.5f ); + } + else if (size == Font.SIZE_LARGE) { + //calculate the large height as a ratio of system default medium size and round off the value to an integer + return (int)Math.floor( (defHeight * ( 4.5f/4 )) + 0.5f ); + } + else { + //return the system default height for medium size which is generally 12 but 7 in symbian for qt + return defHeight; + } + } + + /** + * Get LCDUI size from eSWT font height + * + * @param height font's height + * @return font size + */ + private static int mapHeightToSize(int height) { + int defHeight = getSystemFontData().getHeight(); + if (height < defHeight) { + return Font.SIZE_SMALL; + } + else if (height > defHeight) { + return Font.SIZE_LARGE; + } + else { + return Font.SIZE_MEDIUM; + } + } + + /** + * Return eSWT style. + * + * @param style Font's LCDUI style. + * @return Font's eSWT style. + */ + private static int mapStyleToESWTStyle(int style) { + int retStyle = SWT.NORMAL; + if ((style & Font.STYLE_BOLD) == Font.STYLE_BOLD) { + retStyle |= SWT.BOLD; + } + if ((style & Font.STYLE_ITALIC) == Font.STYLE_ITALIC) { + retStyle |= SWT.ITALIC; + } + return retStyle; + } + + /** + * Return LCDUI style. + * + * @param eswtStyle Font's eSWT style. + * @return Font's LCDUI style. + */ + private static int mapESWTStyleToStyle(int eswtStyle) { + int retStyle = Font.STYLE_PLAIN; + if ((eswtStyle & SWT.BOLD) != 0) { + retStyle |= Font.STYLE_BOLD; + } + if ((eswtStyle & SWT.ITALIC) != 0) { + retStyle |= Font.STYLE_ITALIC; + } + return retStyle; + } + +}