javauis/lcdui_qt/src/javax/microedition/lcdui/Font.java
changeset 21 2a9601315dfc
child 23 98ccebc37403
--- /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 <code>Font</code> 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).<br>
+     *
+     * @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.<br>
+     * 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;
+    }
+
+}