/*
 * Copyright (c) 2006-2008 MiniMe. Code released under The MIT/X Window System
 * License. Full license text can be found in license.txt
 */
package minime;

import java.io.*;
import java.util.*;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

/**
 * The Font class represents fonts and font metrics.Fonts can be created by
 * applications.It can handle string,including ddraws string and calculate width
 * occupied by string based on font. A Font's attributes are style, size, and
 * face, they are the same to javax.microedition.lcdui.Font.
 * 
 * @author aaa
 * 
 */
public class Font
{
    private javax.microedition.lcdui.Font jfont;
    private int height;

    /**
     * Constructs a new Font instance with given specified face, size and
     * style.This attributes are the same to javax.microedition.lcdui.Font.
     * 
     * @param face
     *            one of Portability.FACE_SYSTEM, Portability.FACE_MONOSPACE, or
     *            Portability.FACE_PROPORTIONAL
     * @param style
     *            Portability.STYLE_PLAIN, or a combination of
     *            Portability.STYLE_BOLD, Portability.STYLE_ITALIC, and
     *            Portability.STYLE_UNDERLINED
     * @param size
     *            one of Portability.SIZE_SMALL, Portability.SIZE_MEDIUM, or
     *            Portability.SIZE_LARGE
     */
    public Font(int face, int style, int size)
    {
        jfont = javax.microedition.lcdui.Font.getFont(face, style, size);
        height = jfont.getHeight();
    }

    /**
     * Gets the standard height of a line of text in this font. This value includes 
     * sufficient spacing to ensure that lines of text painted this distance from 
     * anchor point to anchor point are spaced as intended by the font designer and 
     * the device. This extra space (leading) occurs below the text. 
     * 
     * @return standard height of a line of text in this font (a non-negative value)
     */
    public int getHeight()
    {
        return height;
    }

    /**
     * Gets the advance width of the specified character in this Font. The advance 
     * width is the horizontal distance that would be occupied if ch were to be drawn 
     * using this Font, including inter-character spacing following ch necessary for 
     * proper positioning of subsequent text. 
     * 
     * @param c 
     *              the character to be measured 
     * @return the total advance width (a non-negative value)
     */
    public int getCharWidth(char c)
    {
        if (jfont != null)
        {
            return jfont.charWidth(c);
        }
        else
        {
            return 0;
        }
    }

    /**
     * Draws the characters using this Font at x and y coordinates by graphics object, 
     * starting at the specified offset and for the specified number of characters (length). 
     * 
     * @param g
     *              the Graphics object to be used for drawing characters.
     * @param x     
     *              the x coordinate of string to be drawn.
     * @param y     
     *              the y coordinate of string to be drawn.
     * @param textChars
     *              the array of characters
     * @param startOffset
     *              the index of the first character to be drawn
     * @param count
     *              the number of characters to be drawn
     */
    public void drawChars(Graphics g, int x, int y, char[] textChars, int startOffset, int count)
    {
        if (jfont != null)
        {
            javax.microedition.lcdui.Font f = g.getFont();
            g.setFont(jfont);
            g.drawChars(textChars, startOffset, count, x, y, Graphics.TOP | Graphics.LEFT);
            g.setFont(f);
            return;
        }
    }


    /**
     * Gets the total advance width for showing the specified String in this Font.
     * The advance width is the horizontal distance that would be occupied if str 
     * were to be drawn using this Font, including inter-character spacing following 
     * str necessary for proper positioning of subsequent text. If string is null,
     * then return 0;
     * 
     * @param str
     *              the String to be measured 
     * @return the total advance width 
     */
    public final int getStringWidth(String str)
    {
        if (null == str)
        {
            return 0;
        }
        return getCharsWidth(str.toCharArray());
    }

    /**
     * Returns the total advance width of the characters in textChars in this Font. 
     * The advance width is the horizontal distance that would be occupied if the 
     * characters were to be drawn using this Font, including inter-character spacing 
     * following the characters necessary for proper positioning of subsequent text. 
     * 
     * @param textChars 
     *              the array of characters
     * @return the width of the character range 
     */
    public final int getCharsWidth(char[] textChars)
    {
        return getCharsWidth(textChars, 0, textChars.length);
    }

    /**
     * Returns the advance width of the characters in textChars, starting at the specified offset 
     * and for the specified number of characters (length). The advance width is the 
     * horizontal distance that would be occupied if the characters were to be drawn using 
     * this Font, including inter-character spacing following the characters necessary for 
     * proper positioning of subsequent text. 
     * 
     * The offset and length parameters must specify a valid range of characters within the
     *  character array textChars. The offset parameter must be within the range 
     *  [0..(textChars.length)], inclusive. The length parameter must be a non-negative 
     *  integer such that (offset + length) <= textChars.length.
     *  
     * @param textChars
     *              the array of characters
     * @param startOffset
     *              the index of the first character to measure
     * @param textLength
     *              the number of characters to measure 
     * @return  the width of the character range 
     */
    public final int getCharsWidth(char[] textChars, int startOffset, int textLength)
    {
        int width = 0;
        if (jfont != null)
            width = jfont.charsWidth(textChars, startOffset, textLength);
        return width;
    }

    /**
     * Counts the number of characters in string in given maxWidth in this Font.
     * 
     * @param s
     *              the String to be counted
     * @param maxWidth
     *              the max width the string occupied space
     * @return the number of characters.
     */
    public final int countChars(String s, int maxWidth)
    {
        int width = 0;
        int cnt = 0;
        char[] chars = s.toCharArray();
        while (cnt < chars.length)
        { // if jfont is not null, get width from library function directory,
            // or accumulate all chars's width
            cnt++;
            if (jfont != null)
                width = jfont.substringWidth(s, 0, cnt);

            if (width > maxWidth)
            {
                cnt--;
                break;
            }
        }
        return cnt;
    }

    /**
     * Draws the string using this Font at x and y coordinates by graphics object
     * 
     * @param g
     *              the Graphics object to be used for drawing characters.
     * @param x     
     *              the x coordinate of string to be drawn.
     * @param y     
     *              the y coordinate of string to be drawn.
     * @param s 
     *              the string to be drawn
     */
    public final void drawString(Graphics g, int x, int y, String s)
    {
        if (null == s)
        {
            s = "<NULL>";
        }
        char[] ca = s.toCharArray();
        drawChars(g, x, y, ca, 0, ca.length);
    }
    
    public final void drawString(Graphics g, int x, int y, char[]ca, int startIndex, int length)
    {
        if (null == ca)
        {
            ca = "<NULL>".toCharArray();
        }
        drawChars(g, x, y, ca, startIndex, length);
    }

    /**
     * Draws the specified String using this font and the current color. The x,y 
     * position is the position of the anchor point.
     * 
     * The offset and len parameters must specify a valid range of characters within 
     * the string str. The offset parameter must be within the range [0..(str.length())], 
     * inclusive. The len parameter must be a non-negative integer such that (offset + 
     * len) <= str.length().
     * 
     * @param g
     *            the Graphics object to be used
     * @param x
     *            the x coordinate of the string to be drawn
     * @param y
     *            the y coordinate of the string to be drawn
     * @param s
     *            the String to be drawn
     * @param startOffset
     *            zero-based index of first character in the substring
     * @param len
     *            length of the substring
     */
    public final void drawSubString(Graphics g, int x, int y, String s, int startOffset, int len)
    {
        String subStr = s.substring(startOffset, len + startOffset);
        drawString(g, x, y, subStr);
    }
}
