(I origially sent this proposal to the wrong list; sorry if you've
already seen this)
The main part of this proposal is to add a class to the ICU LayoutEngine
which encapsulates all of the per-glyph storage. This proposal also
includes the class LEInsertionList, which is used to support dynamic
growing of the per-glyph arrays. Finally, the proposal includes a change
to LEFontInstance::mapCharsToGlyphs to use the new LEGlyphStorage class.
Eric Mader
IBM GCoC - San José
5600 Cottle Road M/S 50-2/B11
San Jose, CA 95193
LEGlyphStorage.h:
----------------------------------------------------------------------------------------------------
/*
**********************************************************************
* Copyright (C) 1998-2004, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
#ifndef __LEGLYPHSTORAGE_H
#define __LEGLYPHSTORAGE_H
#include "LETypes.h"
#include "LEInsertionList.h"
U_NAMESPACE_BEGIN
/**
* This class encapsulates the per-glyph storage used by the ICU
LayoutEngine.
* For each glyph it holds the glyph ID, the index of the backing store
character
* which produced the glyph, the X and Y position of the glyph and an
auxillary data
* pointer.
*
* The storage is growable using the <code>LEInsertionList</code> class.
*
*
* @see LEInsertionList.h
*
* @draft ICU 3.0
*/
class U_LAYOUT_API LEGlyphStorage : public UObject, protected
LEInsertionCallback
{
private:
/*
* [Private members not shown]
*/
protected:
/**
* This implements <code>LEInsertionCallback</code>. The
<code>LEInsertionList</code>
* will call this method once for each insertion.
*
* @param atPosition the position of the insertion
* @param count the number of glyphs being inserted
* @param newGlyphs the address of the new glyph IDs
*
* @return <code>true</code> if <code>LEInsertionList</code> should
stop
* processing the insertion list after this insertion.
*
* @see LEInsertionList.h
*
* @draft ICU 3.0
*/
virtual le_bool applyInsertion(le_int32 atPosition, le_int32 count,
LEGlyphID newGlyphs[]);
public:
/**
* Allocates an empty <code>LEGlyphStorage</code> object. You must call
* <code>allocateGlyphArray, allocatePositions and
allocateAuxData</code>
* to allocate the data.
*/
LEGlyphStorage();
/**
* The destructor. This will deallocate all of the arrays.
*/
~LEGlyphStorage();
/**
* This method returns the number of glyphs in the glyph array.
*
* @return the number of glyphs in the glyph array
*
* @draft ICU 3.0
*/
le_int32 getGlyphCount() const
{
return fGlyphCount;
};
/**
* This method copies the glyph array into a caller supplied array.
* The caller must ensure that the array is large enough to hold all
* the glyphs.
*
* @param glyphs - the destiniation glyph array
* @param success - set to an error code if the operation fails
*
* @draft ICU 3.0
*/
void getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const;
/**
* This method copies the glyph array into a caller supplied array,
* ORing in extra bits. (This functionality is needed by the JDK,
* which uses 32 bits pre glyph idex, with the high 16 bits encoding
* the composite font slot number)
*
* @param glyphs - the destination (32 bit) glyph array
* @param extraBits - this value will be ORed with each glyph index
* @param success - set to an error code if the operation fails
*
* @draft ICU 3.0
*/
void getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode
&success) const;
/**
* This method copies the character index array into a caller
supplied array.
* The caller must ensure that the array is large enough to hold a
* character index for each glyph.
*
* @param charIndices - the destiniation character index array
* @param success - set to an error code if the operation fails
*
* @draft ICU 3.0
*/
void getCharIndices(le_int32 charIndices[], LEErrorCode &success)
const;
/**
* This method copies the character index array into a caller
supplied array.
* The caller must ensure that the array is large enough to hold a
* character index for each glyph.
*
* @param charIndices - the destiniation character index array
* @param indexBase - an offset which will be added to each index
* @param success - set to an error code if the operation fails
*
* @draft ICU 3.0
*/
void getCharIndices(le_int32 charIndices[], le_int32 indexBase,
LEErrorCode &success) const;
/**
* This method copies the position array into a caller supplied array.
* The caller must ensure that the array is large enough to hold an
* X and Y position for each glyph, plus an extra X and Y for the
* advance of the last glyph.
*
* @param glyphs - the destiniation position array
* @param success - set to an error code if the operation fails
*
* @draft ICU 3.0
*/
void getGlyphPositions(float positions[], LEErrorCode &success) const;
/**
* This method returns the X and Y position of the glyph at
* the given index.
*
* Input parameters:
* @param glyphIndex - the index of the glyph
*
* Output parameters:
* @param x - the glyph's X position
* @param y - the glyph's Y position
* @param success - set to an error code if the operation fails
*
* @draft ICU 3.0
*/
void getGlyphPosition(le_int32 glyphIndex, float &x, float &y,
LEErrorCode &success) const;
/**
* This method allocates the glyph array, the char indices array
and the insertion list. You
* must call this method before using the object. This method also
initializes the char indices
* array.
*
* @param initialGlyphCount the initial size of the glyph and char
indices arrays.
* @param rightToLeft <code>true</code> if the original input text
is right to left.
* @param success set to an error code if the storage cannot be
allocated of if the initial
* glyph count is not positive.
*
* @draft ICU 3.0
*/
void allocateGlyphArray(le_int32 initialGlyphCount, le_bool
rightToLeft, LEErrorCode &success);
/**
* This method allocates the storage for the glyph positions. It
allocates one extra X, Y
* position pair for the position just after the last glyph.
*
* @param success set to an error code if the positions array
cannot be allocated.
*
* @return the number of X, Y position pairs allocated.
*
* @draft ICU 3.0
*/
le_int32 allocatePositions(LEErrorCode &success);
/**
* This method allocates the storage for the auxillary glyph data.
*
* @param success set to an error code if the aulillary data array
cannot be allocated.
*
* @return the size of the auxillary data array.
*
* @draft ICU 3.0
*/
le_int32 allocateAuxData(LEErrorCode &success);
/**
* Copy the entire auxillary data array.
*
* @param auxData the auxillary data array will be copied to this
address
* @param success set to an error code if the data cannot be copied
*
* @draft ICU 3.0
*/
void getAuxData(void *auxData[], LEErrorCode &success) const;
/**
* Get the glyph ID for a particular glyph.
*
* @param glyphIndex the index into the glyph array
* @param success set to an error code if the glyph ID cannot be
retrieved.
*
* @return the glyph ID
*
* @draft ICU 3.0
*/
LEGlyphID getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const;
/**
* Get the char index for a particular glyph.
*
* @param glyphIndex the index into the glyph array
* @param success set to an error code if the char index cannot be
retrieved.
*
* @return the character index
*
* @draft ICU 3.0
*/
le_int32 getCharIndex(le_int32 glyphIndex, LEErrorCode &success)
const;
/**
* Get the auxillary data for a particular glyph.
*
* @param glyphIndex the index into the glyph array
* @param success set to an error code if the auxillary data cannot
be retrieved.
*
* @return the auxillary data
*
* @draft ICU 3.0
*/
void *getAuxData(le_int32 glyphIndex, LEErrorCode &success) const;
/**
* This operator allows direct access to the glyph array
* using the index operator.
*
* @param glyphIndex the index into the glyph array
*
* @return a reference to the given location in the glyph array
*
* @draft ICU 3.0
*/
LEGlyphID &operator[](le_int32 glyphIndex) const;
/**
* Call this method to replace a single glyph in the glyph array
* with multiple glyphs. This method uses the
<code>LEInsertionList</code>
* to do the insertion. It returns the address of storage where the new
* glyph IDs can be stored. They will not actually be inserted into the
* glyph array until <code>applyInsertions</code> is called.
*
* @param atIndex the index of the glyph to be replaced
* @param insertCount the number of glyphs to replace it with
*
* @return the address at which to store the replacement glyphs.
*
* @see LEInsetionList.h
*
* @draft ICU 3.0
*/
LEGlyphID *insertGlyphs(le_int32 atIndex, le_int32 insertCount);
/**
* This method causes all of the glyph insertions recorded by
* <code>insertGlyphs</code> to be applied to the glyph array. The
* new slots in the char indices and the auxillary data arrays
* will be filled in with the values for the glyph being replaced.
*
* @return the new size of the glyph array
*
* @see LEInsertionList.h
*
* @draft ICU 3.0
*/
le_int32 applyInsertions();
/**
* Set the glyph ID for a particular glyph.
*
* @param glyphIndex the index of the glyph
* @param glyphID the new glyph ID
* @param success will be set to an error code if the glyph ID
cannot be set.
*
* @draft ICU 3.0
*/
void setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode
&success);
/**
* Set the char index for a particular glyph.
*
* @param glyphIndex the index of the glyph
* @param charIndex the new char index
* @param success will be set to an error code if the char index
cannot be set.
*
* @draft ICU 3.0
*/
void setCharIndex(le_int32 glyphIndex, le_int32 charIndex,
LEErrorCode &success);
/**
* Set the X, Y position for a particular glyph.
*
* @param glyphIndex the index of the glyph
* @param x the new X position
* @param y the new Y position
* @param success will be set to an error code if the position
cannot be set.
*
* @draft ICU 3.0
*/
void setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode
&success);
/**
* Adjust the X, Y position for a particular glyph.
*
* @param glyphIndex the index of the glyph
* @param xAdjust the adjustment to the glyph's X position
* @param yAdjust the adjustment to the glyph's Y position
* @param success will be set to an error code if the glyph's
position cannot be adjusted.
*
* @draft ICU 3.0
*/
void adjustPosition(le_int32 glyphIndex, float xAdjust, float
yAdjust, LEErrorCode &success);
/**
* Set the auxillary data for a particular glyph.
*
* @param glyphIndex the index of the glyph
* @param auxData the new auxillary data
* @param success will be set to an error code if the auxillary
data cannot be set.
*
* @draft ICU 3.0
*/
void setAuxData(le_int32 glyphIndex, void *auxData, LEErrorCode
&success);
/**
* Delete the glyph array and replace it with the one
* in <code>from</code>. Set the glyph array pointer
* in <code>from</code> to <code>NULL</code>.
*
* @param from the <code>LEGlyphStorage</code> object from which
* to get the new glyph array.
*
* @draft ICU 3.0
*/
void adoptGlyphArray(LEGlyphStorage &from);
/**
* Delete the char indices array and replace it with the one
* in <code>from</code>. Set the char indices array pointer
* in <code>from</code> to <code>NULL</code>.
*
* @param from the <code>LEGlyphStorage</code> object from which
* to get the new char indices array.
*
* @draft ICU 3.0
*/
void adoptCharIndicesArray(LEGlyphStorage &from);
/**
* Delete the position array and replace it with the one
* in <code>from</code>. Set the position array pointer
* in <code>from</code> to <code>NULL</code>.
*
* @param from the <code>LEGlyphStorage</code> object from which
* to get the new position array.
*
* @draft ICU 3.0
*/
void adoptPositionArray(LEGlyphStorage &from);
/**
* Delete the auxillary data array and replace it with the one
* in <code>from</code>. Set the auxillary data array pointer
* in <code>from</code> to <code>NULL</code>.
*
* @param from the <code>LEGlyphStorage</code> object from which
* to get the new auxillary data array.
*
* @draft ICU 3.0
*/
void adoptAuxDataArray(LEGlyphStorage &from);
/**
* Change the glyph count of this object to be the same
* as the one in <code>from</code>.
*
* @param from the <code>LEGlyphStorage</code> object from which
* to get the new glyph count.
*
* @draft ICU 3.0
*/
void adoptGlyphCount(LEGlyphStorage &from);
/**
* Change the glyph count of this object to the given value.
*
* @param newGlyphCount the new glyph count.
*
* @draft ICU 3.0
*/
void adoptGlyphCount(le_int32 newGlyphCount);
/**
* This method frees the glyph, character index, position and
* auxillary data arrays so that the LayoutEngine can be reused
* to layout a different characer array. (This method is also called
* by the destructor)
*
* @draft ICU 3.0
*/
void reset();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @darft ICU 3.0
*/
virtual inline UClassID getDynamicClassID() const { return
getStaticClassID(); }
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @draft ICU 3.0
*/
static inline UClassID getStaticClassID() { return
(UClassID)&fgClassID; }
};
inline LEGlyphID &LEGlyphStorage::operator[](le_int32 glyphIndex) const
{
return fGlyphs[glyphIndex];
}
U_NAMESPACE_END
#endif
LEInertionList.h:
----------------------------------------------------------------------------------------------------
/*
**********************************************************************
* Copyright (C) 1998-2004, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
#ifndef __LEINSERTIONLIST_H
#define __LEINSERTIONLIST_H
#include "LETypes.h"
U_NAMESPACE_BEGIN
struct InsertionRecord;
/**
* This class encapsulates the callback used by
<code>LEInsertionList</code>
* to apply an insertion from the insertion list.
*
* @internal
*/
class LEInsertionCallback
{
public:
/**
* This method will be called by
<code>LEInsertionList::applyInsertions</code> for each
* entry on the insertion list.
*
* @param atPosition the position of the insertion
* @param count the number of glyphs to insert
* @param newGlyphs the address of the glyphs to insert
*
* @return <code>TRUE</code> if
<code>LEInsertions::applyInsertions</code> should
* stop after applying this insertion.
*
* @internal
*/
virtual le_bool applyInsertion(le_int32 atPosition, le_int32 count,
LEGlyphID newGlyphs[]) = 0;
};
/**
* This class is used to keep track of insertions to an array of
* <code>LEGlyphIDs</code>. The insertions are kept on a linked
* list of <code>InsertionRecords</code> so that the glyph array
* doesn't have to be grown for each insertion. The insertions are
* stored on the list from leftmost to rightmost to make it easier
* to do the insertions.
*
* The insertions are applied to the array by calling the
* <code>applyInsertions</code> method, which calls a client
* supplied <code>LEInsertionCallback</code> object to actually
* apply the individual insertions.
*
* @internal
*/
class LEInsertionList : public UObject
{
public:
/**
* Construct an empty insertion list.
*
* @param rightToLeft <code>TRUE</code> if the glyphs are stored
* in the array in right to left order.
*
* @internal
*/
LEInsertionList(le_bool rightToLeft);
/**
* The destructor.
*/
~LEInsertionList();
/**
* Add an entry to the insertion list.
*
* @param position the glyph at this position in the array will be
* replaced by the new glyphs.
* @param count the number of new glyphs
*
* @return the address of an array in which to store the new
glyphs. This will
* <em>not</em> be in the glyph array.
*
* @internal
*/
LEGlyphID *insert(le_int32 position, le_int32 count);
/**
* Return the number of new glyphs that have been inserted.
*
* @return the number of new glyphs which have been inserted
*
* @internal
*/
le_int32 getGrowAmount();
/**
* Call the <code>LEInsertionCallback</code> once for each
* entry on the insertion list.
*
* @param callback the <code>LEInsertionCallback</code> to call for
each insertion.
*
* @return <code>TRUE</code> if <code>callback</code> returned
<code>TRUE</code> to
* terminate the insertion list processing.
*
* @internal
*/
le_bool applyInsertions(LEInsertionCallback *callback);
/**
* Empty the insertion list and free all associated
* storage.
*
* @internal
*/
void reset();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual inline UClassID getDynamicClassID() const { return
getStaticClassID(); }
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static inline UClassID getStaticClassID() { return
(UClassID)&fgClassID; }
private:
/*
* [private members not shown]
*/
};
U_NAMESPACE_END
#endif
Change to LEFontInstance.h:
----------------------------------------------------------------------------------------------------
/**
* This method maps an array of character codes to an array of glyph
* indices, using the font's character to glyph map.
*
* The default implementation iterates over all of the characters
and calls
* <code>mapCharToGlyph(ch, mapper)</code> on each one. It also
handles surrogate
* characters, storing the glyph ID for the high surrogate, and a
deleted glyph (0xFFFF)
* for the low surrogate.
*
* Most sublcasses will not need to implement this method.
*
* @param chars - the character array
* @param offset - the index of the first character
* @param count - the number of characters
* @param reverse - if <code>TRUE</code>, store the glyph indices
in reverse order.
* @param mapper - the character mapper.
* @param glyphStorage - the object which contains the output glyph
array
*
* @see LECharMapper
*
* @draft ICU 3.0
*/
virtual void mapCharsToGlyphs(const LEUnicode chars[], le_int32
offset, le_int32 count, le_bool reverse, const LECharMapper *mapper,
LEGlyphStorage &glyphStorage) const;
|