/*
 * %W% %E%
 *
 * (C) Copyright IBM Corp. 1998 - 2003 - All Rights Reserved
 *
 */

#ifndef __SCRIPTCOMPOSITEFONTINSTANCE_H
#define __SCRIPTCOMPOSITEFONTINSTANCE_H

#include "layout/LETypes.h"
#include "layout/LEFontInstance.h"

#include "FontMap.h"

// U_NAMESPACE_BEGIN

class ScriptCompositeFontInstance : public LEFontInstance
{
public:

    ScriptCompositeFontInstance(FontMap *fontMap);

    virtual ~ScriptCompositeFontInstance();

      /**
     * Get a physical font which can render the given text. For composite fonts,
     * if there is no single physical font which can render all of the text,
     * return a physical font which can render an initial substring of the text,
     * and set the <code>offset</code> parameter to the end of that substring.
     *
     * Internally, the LayoutEngine works with runs of text all in the same
     * font and script, so it is best to call this method with text which is
     * in a single script, passing the script code in as a hint. If you don't
     * know the script of the text, you can use zero, which is the script code
     * for characters used in more than one script.
     *
     * The default implementation of this method is intended for instances of
     * <code>LEFontInstance</code> which represent a physical font. It returns
     * <code>this</code> and indicates that the entire string can be rendered.
     *
     * This method will return a valid <code>LEFontInstance</code> unless you
     * have passed illegal parameters, or an internal error has been encountered. 
     * For composite fonts, it may return the warning <code>LE_NO_SUBFONT_WARNING</code>
     * to indicate that the returned font may not be able to render all of
     * the text. Whenever a valid font is returned, the <code>offset</code> parameter
     * will be advanced by at least one.
     *
     * Subclasses which implement composite fonts must override this method.
     * Where it makes sense, they should use the script code as a hint to render
     * characters from the COMMON script in the font which is used for the given
     * script. For example, if the input text is a series of Arabic words separated
     * by spaces, and the script code passed in is <code>arabScriptCode</code> you
     * should return the font used for Arabic characters for all of the input text,
     * including the spaces. If, on the other hand, the input text contains characters
     * which cannot be rendered by the font used for Arabic characters, but which can
     * be rendered by another font, you should return that font for those characters.
     *
     * @param chars   - the array of Unicode characters.
     * @param offset  - a pointer to the starting offset in the text. On exit this
     *                  will be set the the limit offset of the text which can be
     *                  rendered using the returned font.
     * @param limit   - the limit offset for the input text.
     * @param script  - the script hint.
     * @param success - set to an error code if the arguments are illegal, or no font
     *                  can be returned for some reason. May also be set to
     *                  <code>LE_NO_SUBFONT_WARNING</code> if the subfont which
     *                  was returned cannot render all of the text.
     *
     * @return an <code>LEFontInstance</code> for the sub font which can render the characters, or
     *         <code>NULL</code> if there is an error.
     *
     * @see LEScripts.h
     *
     * @draft ICU 2.6
     */
    virtual const LEFontInstance *getSubFont(const LEUnicode chars[], le_int32 *offset, le_int32 limit, le_int32 script, LEErrorCode &success) const;

    /**
     * This method maps a single character to a glyph index, using the
     * font's charcter to glyph map.
     *
     * @param ch - the character
     *
     * @return the glyph index
     *
     * @draft ICU 2.6
     */
    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch) const;

    virtual const void *getFontTable(LETag tableTag) const;

    virtual le_int32 getUnitsPerEM() const;

    virtual le_int32 getAscent() const;

    virtual le_int32 getDescent() const;

    virtual le_int32 getLeading() const;

    virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const;

    virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const;

    float getXPixelsPerEm() const;

    float getYPixelsPerEm() const;

    float getScaleFactorX() const;

    float getScaleFactorY() const;

    /**
     * ICU "poor man's RTTI", returns a UClassID for the actual class.
     *
     * @draft ICU 2.2
     */
    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }

    /**
     * ICU "poor man's RTTI", returns a UClassID for this class.
     *
     * @draft ICU 2.2
     */
    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }

protected:
    FontMap *fFontMap;

private:

    /**
     * The address of this static class variable serves as this class's ID
     * for ICU "poor man's RTTI".
     */
    static const char fgClassID;
};

inline const void *ScriptCompositeFontInstance::getFontTable(LETag tableTag) const
{
    return NULL;
}

// Can't get units per EM without knowing which sub-font, so
// return a value that will make units == points
inline le_int32 ScriptCompositeFontInstance::getUnitsPerEM() const
{
    return 1;
}

inline le_int32 ScriptCompositeFontInstance::getAscent() const
{
    return fFontMap->getAscent();
}

inline le_int32 ScriptCompositeFontInstance::getDescent() const
{
    return fFontMap->getDescent();
}

inline le_int32 ScriptCompositeFontInstance::getLeading() const
{
    return fFontMap->getLeading();
}

inline float ScriptCompositeFontInstance::getXPixelsPerEm() const
{
    return fFontMap->getPointSize();
}

inline float ScriptCompositeFontInstance::getYPixelsPerEm() const
{
    return fFontMap->getPointSize();
}

// Can't get a scale factor without knowing the sub-font, so
// return 1.0.
inline float ScriptCompositeFontInstance::getScaleFactorX() const
{
    return 1.0;
}

// Can't get a scale factor without knowing the sub-font, so
// return 1.0
inline float ScriptCompositeFontInstance::getScaleFactorY() const
{
    return 1.0;
}

// U_NAMESPACE_END
#endif
