[sword-cvs] icu-sword/source/layoutex/layout ParagraphLayout.h,NONE,1.1 RunArrays.h,NONE,1.1

sword@www.crosswire.org sword@www.crosswire.org
Tue, 9 Sep 2003 19:42:29 -0700


Update of /usr/local/cvsroot/icu-sword/source/layoutex/layout
In directory www:/tmp/cvs-serv19862/source/layoutex/layout

Added Files:
	ParagraphLayout.h RunArrays.h 
Log Message:
ICU 2.6 commit

--- NEW FILE: ParagraphLayout.h ---
/*
 **********************************************************************
 *   Copyright (C) 2002-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 */

#ifndef __PARAGRAPHLAYOUT_H

#define __PARAGRAPHLAYOUT_H

/*
 * ParagraphLayout doesn't make much sense without
 * BreakIterator...
 */
#include "unicode/uscript.h"
#if ! UCONFIG_NO_BREAK_ITERATION

#include "layout/LETypes.h"
#include "layout/LEFontInstance.h"
#include "layout/LayoutEngine.h"
#include "unicode/ubidi.h"
#include "unicode/brkiter.h"

#include "layout/RunArrays.h"

U_NAMESPACE_BEGIN

/**
 * ParagraphLayout.
 *
 * The <code>ParagraphLayout</code> object will analyze the text into runs of text in the
 * same font, script and direction, and will create a <code>LayoutEngine</code> object for each run.
 * The <code>LayoutEngine</code> will transform the characters into glyph codes in visual order.
 *
 * Clients can use this to break a paragraph into lines, and to display the glyphs in each line.
 *
 */
class U_LAYOUTEX_API ParagraphLayout : public UObject
{
public:
    class VisualRun;

    /**
     * This class represents a single line of text in a <code>ParagraphLayout</code>. They
     * can only be created by calling <code>ParagraphLayout::nextLine()</code>. Each line
     * consists of multiple visual runs, represented by <code>ParagraphLayout::VisualRun</code>
     * objects.
     *
     * @see ParagraphLayout
     * @see ParagraphLayout::VisualRun
     *
     * @draft ICU 2.6
     */
    class U_LAYOUTEX_API Line : public UObject
    {
    public:
        /**
         * The constructor is private since these objects can only be
         * created by <code>ParagraphLayout</code>. However, it is the
         * clients responsibility to destroy the objects, so the destructor
         * is public.
        *
        * @draft ICU 2.6
         */
        ~Line();

        /**
         * Count the number of visual runs in the line.
         *
         * @return the number of visual runs.
         *
         * @draft ICU 2.6
         */
        le_int32 countRuns() const;

        /**
         * Get the ascent of the line. This is the maximum ascent
         * of all the fonts on the line.
         *
         * @return the ascent of the line.
         *
         * @draft ICU 2.6
         */
        le_int32 getAscent() const;

        /**
         * Get the descent of the line. This is the maximum descent
         * of all the fonts on the line.
         *
         * @return the descent of the line.
         *
         * @draft ICU 2.6
         */
        le_int32 getDescent() const;

        /**
         * Get the leading of the line. This is the maximum leading
         * of all the fonts on the line.
         *
         * @return the leading of the line.
         *
         * @draft ICU 2.6
         */
        le_int32 getLeading() const;
    
        /**
         * Get a <code>ParagraphLayout::VisualRun</code> object for a given
         * visual run in the line.
         *
         * @param runIndex is the index of the run, in visual order.
         *
         * @return the <code>ParagraphLayout::VisualRun</code> object representing the
         *         visual run. This object is owned by the <code>Line</code> object which
         *         created it, and will remain valid for as long as the <code>Line</code>
         *         object is valid.
         *
         * @see ParagraphLayout::VisualRun
         *
         * @draft ICU 2.6
         */
        const VisualRun *getVisualRun(le_int32 runIndex) const;

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

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

    private:

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

        friend class ParagraphLayout;

        le_int32 fAscent;
        le_int32 fDescent;
        le_int32 fLeading;

        le_int32 fRunCount;
        le_int32 fRunCapacity;

        VisualRun **fRuns;

        Line();
		Line(const Line &other);
		Line &operator=(const Line & /*other*/) { return *this; };

        void computeMetrics();

        void append(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount,
                    const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[]);
    };

    /**
     * This object represents a single visual run in a line of text in
     * a paragraph. A visual run is text which is in the same font, 
     * script, and direction. The text is represented by an array of
     * <code>LEGlyphIDs</code>, an array of (x, y) glyph positions and
     * a table which maps indices into the glyph array to indices into
     * the original character array which was used to create the paragraph.
     *
     * These objects are only created by <code>ParagraphLayout::Line<code> objects,
     * so their constructors and destructors are private.
     *
     * @see ParagraphLayout::Line
     *
     * @draft ICU 2.6
     */
    class U_LAYOUTEX_API VisualRun : public UObject
    {
    public:
        /**
         * Get the <code>LEFontInstance</code> object which
         * represents the font of the visual run. This will always
         * be a non-composite font.
         *
         * @return the <code>LEFontInstance</code> object which represents the
         *         font of the visual run.
         *
         * @see LEFontInstance
         *
         * @draft ICU 2.6
         */
        const LEFontInstance *getFont() const;

        /**
         * Get the direction of the visual run.
         *
         * @return the direction of the run. This will be UBIDI_LTR if the
         *         run is left-to-right and UBIDI_RTL if the line is right-to-left.
         *
         * @draft ICU 2.6
         */
        UBiDiDirection getDirection() const;

        /**
         * Get the number of glyphs in the visual run.
         *
         * @return the number of glyphs.
         *
         * @draft ICU 2.6
         */
        le_int32 getGlyphCount() const;

        /**
         * Get the glyphs in the visual run. Glyphs with the values <code>0xFFFE</code> and
         * <code>0xFFFF</code> should be ignored.
         *
         * @return the address of the array of glyphs for this visual run. The storage
         *         is owned by the <code>VisualRun</code> object and must not be deleted.
         *         It will remain valid as long as the <code>VisualRun</code> object is valid.
         *
         * @draft ICU 2.6
         */
        const LEGlyphID *getGlyphs() const;

        /**
         * Get the (x, y) positions of the glyphs in the visual run. To simplify storage
         * management, the x and y positions are stored in a single array with the x positions
         * at even offsets in the array and the corresponding y position in the following odd offset.
         * There is an extra (x, y) pair at the end of the array which represents the advance of
         * the final glyph in the run.
         *
         * @return the address of the array of glyph positions for this visual run. The storage
         *         is owned by the <code>VisualRun</code> object and must not be deleted.
         *         It will remain valid as long as the <code>VisualRun</code> object is valid.
         *
         * @draft ICU 2.6
         */
        const float *getPositions() const;

        /**
         * Get the glyph-to-character map for this visual run. This maps the indices into
         * the glyph array to indices into the character array used to create the paragraph.
         *
         * @return the address of the character-to-glyph map for this visual run. The storage
         *         is owned by the <code>VisualRun</code> object and must not be deleted.
         *         It will remain valid as long as the <code>VisualRun</code> object is valid.
         *
         * @draft ICU 2.6
         */
        const le_int32 *getGlyphToCharMap() const;

        /**
         * A convenience method which returns the ascent value for the font
         * associated with this run.
         *
         * @return the ascent value of this run's font.
         *
         * @draft ICU 2.6
         */
        le_int32 getAscent() const;

        /**
         * A convenience method which returns the descent value for the font
         * associated with this run.
         *
         * @return the descent value of this run's font.
         *
         * @draft ICU 2.6
         */
        le_int32 getDescent() const;

        /**
         * A convenience method which returns the leading value for the font
         * associated with this run.
         *
         * @return the leading value of this run's font.
         *
         * @draft ICU 2.6
         */
        le_int32 getLeading() const;

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

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

    private:

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

        const LEFontInstance *fFont;
        const UBiDiDirection  fDirection;

        const le_int32 fGlyphCount;

        const LEGlyphID *fGlyphs;
        const float     *fPositions;
        const le_int32  *fGlyphToCharMap;

        friend class Line;

        VisualRun();
		VisualRun(const VisualRun &other);
		VisualRun &operator=(const VisualRun &other) { return *this; };

        VisualRun(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount,
                  const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[]);

        ~VisualRun();
    };

    /**
     * Construct a <code>ParagraphLayout</code> object for a styled paragraph. The paragraph is specified
     * as runs of text all in the same font. An <code>LEFontInstance</code> object and a limit offset
     * are specified for each font run. The limit offset is the offset of the character immediately
     * after the font run.
     *
     * Clients can optionally specify directional runs and / or script runs. If these aren't specified
     * they will be computed.
     *
     * @param chars is an array of the characters in the paragraph
     *
     * @param count is the number of characters in the paragraph.
     *
     * @param fontRuns a pointer to a <code>FontRuns</code> object representing the font runs.
     *
     * @param levelRuns is a pointer to a <code>ValueRuns</code> object representing the directional levels.
     *        If this pointer in <code>NULL</code> the levels will be determined by running the Unicde
     *        Bidi algorithm.
     *
     * @param scriptRuns is a pointer to a <code>ValueRuns</code> object representing script runs.
     *        If this pointer in <code>NULL</code> the script runs will be determined using the
     *        Unicode code points.
     *
     * @param localeRuns is a pointer to a <code>LocaleRuns</code> object representing locale runs.
     *        The <code>Locale</code> objects are used to determind the language of the text. If this
     *        pointer is <code>NULL</code> the default locale will be used for all of the text. 
     *
     * @param paragraphLevel is the directionality of the paragraph, as in the UBiDi object.
     *
     * @param vertical is <code>true</code> if the paragraph should be set vertically.
     *
     * @see ubidi.h
     * @see LEFontInstance.h
     * @see LayoutEngine.h
     * @see RunArrays.h
     *
     * @draft ICU 2.6
     */
    ParagraphLayout(const LEUnicode chars[], le_int32 count,
                    const FontRuns *fontRuns,
                    const ValueRuns *levelRuns,
                    const ValueRuns *scriptRuns,
                    const LocaleRuns *localeRuns,
                    UBiDiLevel paragraphLevel, le_bool vertical);

    /**
     * The destructor. Virtual so that it works correctly with
     * sublcasses.
     *
     * @draft ICU 2.6
     */
    ~ParagraphLayout();

    // Note: the following is #if 0'd out because there's no good
    // way to implement it without either calling layoutEngineFactory()
    // or duplicating the logic there...
#if 0
    /**
     * Examine the given styled paragraph and determine if it contains any text which
     * requires complex processing. (i.e. that cannot be correctly rendered by
     * just mapping the characters to glyphs and rendering them in order)
     *
     * @param chars is an array of the characters in the paragraph
     *
     * @param count is the number of characters in the paragraph.
     *
     * @param fontRuns is a pointer to a <code>FontRuns</code> object representing the font runs.
     *
     * @return <code>true</code> if the paragraph contains complex text.
     *
     * @draft ICU 2.6
     */
    static le_bool isComplex(const LEUnicode chars[], le_int32 count, const FontRuns *fontRuns);
#else
    /**
     * Examine the given text and determine if it contains characters in any
     * script which requires complex processing to be rendered correctly.
     *
     * @param chars is an array of the characters in the paragraph
     *
     * @param count is the number of characters in the paragraph.
     *
     * @return <code>true</code> if any of the text requires complex processing.
     *
     * @draft ICU 2.6
     */
    static le_bool isComplex(const LEUnicode chars[], le_int32 count);

#endif

    /**
     * Return the resolved paragraph level. This is useful for those cases
     * where the bidi analysis has determined the level based on the first
     * strong character in the paragraph.
     *
     * @return the resolved paragraph level.
     *
     * @draft ICU 2.6
     */
    UBiDiLevel getParagraphLevel();

    /**
     * Return the directionality of the text in the paragraph.
     *
     * @return <code>UBIDI_LTR</code> if the text is all left to right,
     *         <code>UBIDI_RTL</code> if the text is all right to left,
     *         or <code>UBIDI_MIXED</code> if the text has mixed direction.
     *
     * @draft ICU 2.6
     */
    UBiDiDirection getTextDirection();

    /**
     * Return the max ascent value for all the fonts
     * in the paragraph.
     *
     * @return the ascent value.
     *
     * @draft ICU 2.6
     */
    virtual le_int32 getAscent() const;

    /**
     * Return the max descent value for all the fonts
     * in the paragraph.
     *
     * @return the decent value.
     *
     * @draft ICU 2.6
     */
    virtual le_int32 getDescent() const;

    /**
     * Return the max leading value for all the fonts
     * in the paragraph.
     *
     * @return the leading value.
     *
     * @draft ICU 2.6
     */
    virtual le_int32 getLeading() const;

    /**
     * Reset line breaking to start from the beginning of the paragraph.
     *
     *
     * @draft ICU 2.6
     */
    void reflow();

    /**
     * Return a <code>ParagraphLayout::Line</code> object which represents next line
     * in the paragraph. The width of the line is specified each time so that it can
     * be varied to support arbitrary paragraph shapes.
     *
     * @param width is the width of the line. If <code>width</code> is less than or equal
     *              to zero, a <code>ParagraphLayout::Line</code> object representing the
     *              rest of the paragraph will be returned.
     *
     * @return a <code>ParagraphLayout::Line</code> object which represents the line. The caller
     *         is responsible for deleting the object. Returns <code>NULL</code> if there are no
	 *         more lines in the paragraph.
     *
     * @see ParagraphLayout::Line
     *
     * @draft ICU 2.6
     */
    Line *nextLine(float width);

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

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

private:


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

    struct StyleRunInfo
    {
          LayoutEngine   *engine;
    const LEFontInstance *font;
    const Locale         *locale;
          LEGlyphID      *glyphs;
          float          *positions;
          UScriptCode     script;
          UBiDiLevel      level;
          le_int32        runBase;
          le_int32        runLimit;
          le_int32        glyphBase;
          le_int32        glyphCount;
    };

    ParagraphLayout() {};
    ParagraphLayout(const ParagraphLayout & /*other*/) : UObject( ){};
    ParagraphLayout &operator=(const ParagraphLayout & /*other*/) { return *this; };

    void computeLevels(UBiDiLevel paragraphLevel);

    Line *computeVisualRuns();
    void appendRun(Line *line, le_int32 run, le_int32 firstChar, le_int32 lastChar);

    void computeScripts();

    void computeLocales();

    void computeSubFonts(const FontRuns *fontRuns);

    void computeMetrics();

    le_int32 getLanguageCode(const Locale *locale);

    le_int32 getCharRun(le_int32 charIndex);

    static le_bool isComplex(UScriptCode script);

    le_int32 previousBreak(le_int32 charIndex);


    const LEUnicode *fChars;
          le_int32   fCharCount;

    const FontRuns   *fFontRuns;
    const ValueRuns  *fLevelRuns;
    const ValueRuns  *fScriptRuns;
    const LocaleRuns *fLocaleRuns;

          le_bool fVertical;
          le_bool fClientLevels;
          le_bool fClientScripts;
          le_bool fClientLocales;

          UBiDiLevel *fEmbeddingLevels;

          le_int32 fAscent;
          le_int32 fDescent;
          le_int32 fLeading;

          le_int32 *fGlyphToCharMap;
          le_int32 *fCharToGlyphMap;
          float    *fGlyphWidths;
          le_int32  fGlyphCount;

          UBiDi *fParaBidi;
          UBiDi *fLineBidi;

          le_int32     *fStyleRunLimits;
          le_int32     *fStyleIndices;
          StyleRunInfo *fStyleRunInfo;
          le_int32      fStyleRunCount;

          BreakIterator *fBreakIterator;
          le_int32       fLineStart;
          le_int32       fLineEnd;

          le_int32       fFirstVisualRun;
          le_int32       fLastVisualRun;
          float          fVisualRunLastX;
          float          fVisualRunLastY;
};

inline UBiDiLevel ParagraphLayout::getParagraphLevel()
{
    return ubidi_getParaLevel(fParaBidi);
}

inline UBiDiDirection ParagraphLayout::getTextDirection()
{
    return ubidi_getDirection(fParaBidi);
}

inline void ParagraphLayout::reflow()
{
    fLineEnd = 0;
}

inline ParagraphLayout::Line::Line()
    : UObject(), fAscent(0), fDescent(0), fLeading(0), fRunCount(0), fRunCapacity(0), fRuns(NULL)
{
    // nothing else to do
}

inline ParagraphLayout::Line::Line(const Line & /*other*/)
    : UObject(), fAscent(0), fDescent(0), fLeading(0), fRunCount(0), fRunCapacity(0), fRuns(NULL)
{
    // nothing else to do
}

inline le_int32 ParagraphLayout::Line::countRuns() const
{
    return fRunCount;
}

inline const LEFontInstance *ParagraphLayout::VisualRun::getFont() const
{
    return fFont;
}

inline UBiDiDirection ParagraphLayout::VisualRun::getDirection() const
{
    return fDirection;
}

inline le_int32 ParagraphLayout::VisualRun::getGlyphCount() const
{
    return fGlyphCount;
}

inline const LEGlyphID *ParagraphLayout::VisualRun::getGlyphs() const
{
    return fGlyphs;
}

inline const float *ParagraphLayout::VisualRun::getPositions() const
{
    return fPositions;
}

inline const le_int32 *ParagraphLayout::VisualRun::getGlyphToCharMap() const
{
    return fGlyphToCharMap;
}

inline le_int32 ParagraphLayout::VisualRun::getAscent() const
{
    return fFont->getAscent();
}

inline le_int32 ParagraphLayout::VisualRun::getDescent() const
{
    return fFont->getDescent();
}

inline le_int32 ParagraphLayout::VisualRun::getLeading() const
{
    return fFont->getLeading();
}

inline ParagraphLayout::VisualRun::VisualRun()
    : UObject(), fFont(NULL), fDirection(UBIDI_LTR), fGlyphCount(0), fGlyphs(NULL), fPositions(NULL), fGlyphToCharMap(NULL)
{
    // nothing
}

inline ParagraphLayout::VisualRun::VisualRun(const VisualRun &other)
    : UObject(), fFont(NULL), fDirection(UBIDI_LTR), fGlyphCount(0), fGlyphs(NULL), fPositions(NULL), fGlyphToCharMap(NULL)
{
    // nothing
}

inline ParagraphLayout::VisualRun::VisualRun(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount,
                                             const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[])
    : fFont(font), fDirection(direction), fGlyphCount(glyphCount),
      fGlyphs(glyphs), fPositions(positions), fGlyphToCharMap(glyphToCharMap)
{
    // nothing else needs to be done!
}

inline ParagraphLayout::VisualRun::~VisualRun()
{
    LE_DELETE_ARRAY(fGlyphToCharMap);
    LE_DELETE_ARRAY(fPositions);
    LE_DELETE_ARRAY(fGlyphs);
}

U_NAMESPACE_END
#endif
#endif

--- NEW FILE: RunArrays.h ---
/*
 **********************************************************************
 *   Copyright (C) 2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 */

#ifndef __RUNARRAYS_H

#define __RUNARRAYS_H

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

#include "unicode/utypes.h"
#include "unicode/locid.h"

U_NAMESPACE_BEGIN

/**
 * The initial size of an array if it is unspecified.
 *
 * @draft ICU 2.6
 */
#define INITIAL_CAPACITY 16

/**
 * When an array needs to grow, it will double in size until
 * it becomes this large, then it will grow by this amount.
 *
 * @draft ICU 2.6
 */
#define CAPACITY_GROW_LIMIT 128

/**
 * The <code>RunArray</code> class is a base class for building classes
 * which represent data that is associated with runs of text. This class
 * maintains an array of limit indices into the text, subclasses
 * provide one or more arrays of data.
 *
 * @draft ICU 2.6
 */
class U_LAYOUTEX_API RunArray : public UObject
{
public:
    /**
     * Construct a <code>RunArray</code> object from a pre-existing
     * array of limit indices.
     *
     * @param limits is an array of limit indices.
     *
     * @param count is the number of entries in the limit array.
     *
     * @draft ICU 2.6
     */
    RunArray(const le_int32 *limits, le_int32 count);

    /**
     * Construct an empty <code>RunArray</code> object. Clients can add limit
     * indices array using the <code>add</code> method.
     *
     * @param initialCapacity is the initial size of the limit indices array. If
     *        this value is zero, no array will be allocated.
     *
     * @see add
     *
     * @draft ICU 2.6
     */
    RunArray(le_int32 initalCapacity);

    /**
     * The destructor; virtual so that subclass destructors are invoked as well.
     *
     * @draft ICU 2.6
     */
    virtual ~RunArray();

    /**
     * Get the number of entries in the limit indices array.
     *
     * @return the number of entries in the limit indices array.
     *
     * @draft ICU 2.6
     */
    le_int32 getCount() const;

    /**
     * Get the last limit index. This is the number of characters in
     * the text.
     *
     * @return the last limit index.
     *
     * @draft ICU 2.6
     */
    le_int32 getLimit() const;

    /**
     * Get the limit index for a particular run of text.
     *
     * @param run is the run. This is an index into the limit index array.
     *
     * @return the limit index for the run, or -1 if <code>run</code> is out of bounds.
     *
     * @draft ICU 2.6
     */
    le_int32 getLimit(le_int32 run) const;

    /**
     * Add a limit index to the limit indices array and return the run index
     * where it was stored. If the array does not exist, it will be created by
     * calling the <code>init</code> method. If it is full, it will be grown by
     * calling the <code>grow</code> method.
     *
     * If the <code>RunArray</code> object was created with a client-supplied
     * limit indices array, this method will return a run index of -1.
     *
     * Subclasses should not override this method. Rather they should provide
     * a new <code>add</code> method which takes a limit index along with whatever
     * other data they implement. The new <code>add</code> method should
     * first call this method to grow the data arrays, and use the return value
     * to store the data in their own arrays.
     *
     * @param limit is the limit index to add to the array.
     *
     * @return the run index where the limit index was stored, or -1 if the limit index cannt be stored.
     *
     * @see init
     * @see grow
     *
     * @draft ICU 2.6
     */
    le_int32 add(le_int32 limit);

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

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

protected:
    /**
     * Create a data array with the given initial size. This method will be
     * called by the <code>add</code> method if there is no limit indices
     * array. Subclasses which override this method must also call it from
     * the overriding method to create the limit indices array.
     *
     * @param capacity is the initial size of the data array.
     *
     * @see add
     *
     * @draft ICU 2.6
     */
    virtual void init(le_int32 capacity);

    /**
     * Grow a data array to the given initial size. This method will be
     * called by the <code>add</code> method if the limit indices
     * array is full. Subclasses which override this method must also call it from
     * the overriding method to grow the limit indices array.
     *
     * @param capacity is the initial size of the data array.
     *
     * @see add
     *
     * @draft ICU 2.6
     */
    virtual void grow(le_int32 capacity);

    /**
     * Set by the constructors to indicate whether
     * or not the client supplied the data arrays.
     * If they were supplied by the client, the 
     * <code>add</code> method won't change the arrays
     * and the destructor won't delete them.
     *
     * @draft ICU 2.6
     */
    le_bool fClientArrays;

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

    le_int32 ensureCapacity();

	RunArray();
	RunArray(const RunArray & /*other*/);
	RunArray &operator=(const RunArray & /*other*/) { return *this; };

    const le_int32 *fLimits;
          le_int32  fCount;
          le_int32  fCapacity;
};

inline RunArray::RunArray()
	: UObject(), fClientArrays(false), fLimits(NULL), fCount(0), fCapacity(0)
{
	// nothing else to do...
}

inline RunArray::RunArray(const RunArray & /*other*/)
	: UObject(), fClientArrays(false), fLimits(NULL), fCount(0), fCapacity(0)
{
	// nothing else to do...
}

inline RunArray::RunArray(const le_int32 *limits, le_int32 count)
    : UObject(), fClientArrays(true), fLimits(limits), fCount(count), fCapacity(count)
{
    // nothing else to do...
}

inline RunArray::RunArray(le_int32 initialCapacity)
    : fClientArrays(false), fLimits(NULL), fCount(0), fCapacity(initialCapacity)
{
    if (initialCapacity > 0) {
        fLimits = LE_NEW_ARRAY(le_int32, fCapacity);
    }
}

inline RunArray::~RunArray()
{
    if (! fClientArrays) {
        LE_DELETE_ARRAY(fLimits);
        fLimits = NULL;
    }
}

inline le_int32 RunArray::getCount() const
{
    return fCount;
}

inline le_int32 RunArray::getLimit(le_int32 run) const
{
    if (run < 0 || run >= fCount) {
        return -1;
    }

    return fLimits[run];
}

inline le_int32 RunArray::getLimit() const
{
    return getLimit(fCount - 1);
}

/**
 * The <code>FontRuns</code> class associates pointers to <code>LEFontInstance</code>
 * objects with runs of text.
 *
 * @draft ICU 2.6
 */
class U_LAYOUTEX_API FontRuns : public RunArray
{
public:
    /**
     * Construct a <code>FontRuns</code> object from pre-existing arrays of fonts
     * and limit indices.
     *
     * @param fonts is the address of an array of pointers to <code>LEFontInstance</code> objects.
     *
     * @param limits is the address of an array of limit indices.
     *
     * @param count is the number of entries in the two arrays.
     *
     * @draft ICU 2.6
     */
    FontRuns(const LEFontInstance **fonts, const le_int32 *limits, le_int32 count);

    /**
     * Construct an empty <code>FontRuns</code> object. Clients can add font and limit
     * indices arrays using the <code>add</code> method.
     *
     * @param initialCapacity is the initial size of the font and limit indices arrays. If
     *        this value is zero, no arrays will be allocated.
     *
     * @see add
     *
     * @draft ICU 2.6
     */
    FontRuns(le_int32 initialCapacity);

    /**
     * The destructor; virtual so that subclass destructors are invoked as well.
     *
     * @draft ICU 2.6
     */
    virtual ~FontRuns();

    /**
     * Get the <code>LEFontInstance</code> object assoicated with the given run
     * of text. Use <code>RunArray::getLimit(run)</code> to get the corresponding
     * limit index.
     *
     * @param run is the index into the font and limit indices arrays.
     *
     * @return the <code>LEFontInstance</code> associated with the given text run.
     *
     * @see RunArray::getLimit
     *
     * @draft ICU 2.6
     */
    const LEFontInstance *getFont(le_int32 run) const;


    /**
     * Add an <code>LEFontInstance</code> and limit index pair to the data arrays and return
     * the run index where the data was stored. This  method calls
     * <code>RunArray::add(limit)</code> which will create or grow the arrays as needed.
     *
     * If the <code>FontRuns</code> object was created with a client-supplied
     * font and limit indices arrays, this method will return a run index of -1.
     *
     * Subclasses should not override this method. Rather they should provide a new <code>add</code>
     * method which takes a font and a limit index along with whatever other data they implement.
     * The new <code>add</code> method should first call this method to grow the font and limit indices
     * arrays, and use the returned run index to store data their own arrays.
     *
     * @param font is the address of the <code>LEFontInstance</code> to add
     *
     * @param limit is the limit index to add
     *
     * @return the run index where the font and limit index were stored, or -1 if the data cannot be stored.
     *
     * @draft ICU 2.6
     */
    le_int32 add(const LEFontInstance *font, le_int32 limit);

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

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

protected:
    virtual void init(le_int32 capacity);
    virtual void grow(le_int32 capacity);

private:

	FontRuns();
	FontRuns(const FontRuns &other);
	FontRuns &operator=(const FontRuns & /*other*/) { return *this; };

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

    const LEFontInstance **fFonts;
};

inline FontRuns::FontRuns()
	: RunArray(0), fFonts(NULL)
{
	// nothing else to do...
}

inline FontRuns::FontRuns(const FontRuns & /*other*/)
	: RunArray(0), fFonts(NULL)
{
	// nothing else to do...
}

inline FontRuns::FontRuns(const LEFontInstance **fonts, const le_int32 *limits, le_int32 count)
    : RunArray(limits, count), fFonts(fonts)
{
    // nothing else to do...
}

inline FontRuns::FontRuns(le_int32 initialCapacity)
    : RunArray(initialCapacity), fFonts(NULL)
{
    if (initialCapacity > 0) {
        fFonts = LE_NEW_ARRAY(const LEFontInstance *, initialCapacity);
    }
}

inline FontRuns::~FontRuns()
{
    if (! fClientArrays) {
        LE_DELETE_ARRAY(fFonts);
        fFonts = NULL;
    }
}

/**
 * The <code>LocaleRuns</code> class associates pointers to <code>Locale</code>
 * objects with runs of text.
 *
 * @draft ICU 2.6
 */
class U_LAYOUTEX_API LocaleRuns : public RunArray
{
public:
    /**
     * Construct a <code>LocaleRuns</code> object from pre-existing arrays of locales
     * and limit indices.
     *
     * @param locales is the address of an array of pointers to <code>Locale</code> objects.
     *
     * @param limits is the address of an array of limit indices.
     *
     * @param count is the number of entries in the two arrays.
     *
     * @draft ICU 2.6
     */
    LocaleRuns(const Locale **locales, const le_int32 *limits, le_int32 count);

    /**
     * Construct an empty <code>LocaleRuns</code> object. Clients can add locale and limit
     * indices arrays using the <code>add</code> method.
     *
     * @param initialCapacity is the initial size of the locale and limit indices arrays. If
     *        this value is zero, no arrays will be allocated.
     *
     * @see add
     *
     * @draft ICU 2.6
     */
    LocaleRuns(le_int32 initialCapacity);

    /**
     * The destructor; virtual so that subclass destructors are invoked as well.
     *
     * @draft ICU 2.6
     */
    virtual ~LocaleRuns();

    /**
     * Get the <code>Locale</code> object assoicated with the given run
     * of text. Use <code>RunArray::getLimit(run)</code> to get the corresponding
     * limit index.
     *
     * @param run is the index into the font and limit indices arrays.
     *
     * @return the <code>Locale</code> associated with the given text run.
     *
     * @see RunArray::getLimit
     *
     * @draft ICU 2.6
     */
    const Locale *getLocale(le_int32 run) const;


    /**
     * Add a <code>Locale</code> and limit index pair to the data arrays and return
     * the run index where the data was stored. This  method calls
     * <code>RunArray::add(limit)</code> which will create or grow the arrays as needed.
     *
     * If the <code>LocaleRuns</code> object was created with a client-supplied
     * locale and limit indices arrays, this method will return a run index of -1.
     *
     * Subclasses should not override this method. Rather they should provide a new <code>add</code>
     * method which takes a locale and a limit index along with whatever other data they implement.
     * The new <code>add</code> method should first call this method to grow the font and limit indices
     * arrays, and use the returned run index to store data their own arrays.
     *
     * @param locale is the address of the <code>Locale</code> to add
     *
     * @param limit is the limit index to add
     *
     * @return the run index where the locale and limit index were stored, or -1 if the data cannot be stored.
     *
     * @draft ICU 2.6
     */
    le_int32 add(const Locale *locale, le_int32 limit);

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

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

protected:
    virtual void init(le_int32 capacity);
    virtual void grow(le_int32 capacity);

private:

	LocaleRuns();
	LocaleRuns(const LocaleRuns &other);
	LocaleRuns &operator=(const LocaleRuns & /*other*/) { return *this; };

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

    const Locale **fLocales;
};

inline LocaleRuns::LocaleRuns()
	: RunArray(0), fLocales(NULL)
{
	// nothing else to do...
}

inline LocaleRuns::LocaleRuns(const LocaleRuns & /*other*/)
	: RunArray(0), fLocales(NULL)
{
	// nothing else to do...
}

inline LocaleRuns::LocaleRuns(const Locale **locales, const le_int32 *limits, le_int32 count)
    : RunArray(limits, count), fLocales(locales)
{
    // nothing else to do...
}

inline LocaleRuns::LocaleRuns(le_int32 initialCapacity)
    : RunArray(initialCapacity), fLocales(NULL)
{
    if (initialCapacity > 0) {
        fLocales = LE_NEW_ARRAY(const Locale *, initialCapacity);
    }
}

inline LocaleRuns::~LocaleRuns()
{
    if (! fClientArrays) {
        LE_DELETE_ARRAY(fLocales);
        fLocales = NULL;
    }
}

/**
 * The <code>ValueRuns</code> class associates integer values with runs of text.
 *
 * @draft ICU 2.6
 */
class U_LAYOUTEX_API ValueRuns : public RunArray
{
public:
    /**
     * Construct a <code>ValueRuns</code> object from pre-existing arrays of values
     * and limit indices.
     *
     * @param values is the address of an array of integer.
     *
     * @param limits is the address of an array of limit indices.
     *
     * @param count is the number of entries in the two arrays.
     *
     * @draft ICU 2.6
     */
    ValueRuns(const le_int32 *values, const le_int32 *limits, le_int32 count);

    /**
     * Construct an empty <code>ValueRuns</code> object. Clients can add value and limit
     * indices arrays using the <code>add</code> method.
     *
     * @param initialCapacity is the initial size of the value and limit indices arrays. If
     *        this value is zero, no arrays will be allocated.
     *
     * @see add
     *
     * @draft ICU 2.6
     */
    ValueRuns(le_int32 initialCapacity);

    /**
     * The destructor; virtual so that subclass destructors are invoked as well.
     *
     * @draft ICU 2.6
     */
    virtual ~ValueRuns();

    /**
     * Get the integer value assoicated with the given run
     * of text. Use <code>RunArray::getLimit(run)</code> to get the corresponding
     * limit index.
     *
     * @param run is the index into the font and limit indices arrays.
     *
     * @return the integer value associated with the given text run.
     *
     * @see RunArray::getLimit
     *
     * @draft ICU 2.6
     */
    le_int32 getValue(le_int32 run) const;


    /**
     * Add an integer value and limit index pair to the data arrays and return
     * the run index where the data was stored. This  method calls
     * <code>RunArray::add(limit)</code> which will create or grow the arrays as needed.
     *
     * If the <code>ValueRuns</code> object was created with a client-supplied
     * font and limit indices arrays, this method will return a run index of -1.
     *
     * Subclasses should not override this method. Rather they should provide a new <code>add</code>
     * method which takes an integer value and a limit index along with whatever other data they implement.
     * The new <code>add</code> method should first call this method to grow the font and limit indices
     * arrays, and use the returned run index to store data their own arrays.
     *
     * @param value is the integer value to add
     *
     * @param limit is the limit index to add
     *
     * @return the run index where the value and limit index were stored, or -1 if the data cannot be stored.
     *
     * @draft ICU 2.6
     */
    le_int32 add(le_int32 value, le_int32 limit);

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

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

protected:
    virtual void init(le_int32 capacity);
    virtual void grow(le_int32 capacity);

private:

	ValueRuns();
	ValueRuns(const ValueRuns &other);
	ValueRuns &operator=(const ValueRuns & /*other*/) { return *this; };

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

    const le_int32 *fValues;
};

inline ValueRuns::ValueRuns()
	: RunArray(0), fValues(NULL)
{
	// nothing else to do...
}

inline ValueRuns::ValueRuns(const ValueRuns & /*other*/)
	: RunArray(0), fValues(NULL)
{
	// nothing else to do...
}

inline ValueRuns::ValueRuns(const le_int32 *values, const le_int32 *limits, le_int32 count)
    : RunArray(limits, count), fValues(values)
{
    // nothing else to do...
}

inline ValueRuns::ValueRuns(le_int32 initialCapacity)
    : RunArray(initialCapacity), fValues(NULL)
{
    if (initialCapacity > 0) {
        fValues = LE_NEW_ARRAY(le_int32, initialCapacity);
    }
}

inline ValueRuns::~ValueRuns()
{
    if (! fClientArrays) {
        LE_DELETE_ARRAY(fValues);
        fValues = NULL;
    }
}

U_NAMESPACE_END
#endif