ICU-2259 Changes for canonical equivalence porcessing.

X-SVN-Rev: 15130
This commit is contained in:
Eric Mader 2004-05-03 21:13:13 +00:00
parent 4c9e98ac06
commit 6884636181
19 changed files with 2188 additions and 410 deletions

View File

@ -13,6 +13,7 @@
#include "OpenTypeLayoutEngine.h" #include "OpenTypeLayoutEngine.h"
#include "ArabicLayoutEngine.h" #include "ArabicLayoutEngine.h"
#include "ScriptAndLanguageTags.h" #include "ScriptAndLanguageTags.h"
#include "CharSubstitutionFilter.h"
#include "GlyphSubstitutionTables.h" #include "GlyphSubstitutionTables.h"
#include "GlyphDefinitionTables.h" #include "GlyphDefinitionTables.h"
@ -25,33 +26,6 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
class CharSubstitutionFilter : public UMemory, public LEGlyphFilter
{
private:
const LEFontInstance *fFontInstance;
CharSubstitutionFilter(const CharSubstitutionFilter &other); // forbid copying of this class
CharSubstitutionFilter &operator=(const CharSubstitutionFilter &other); // forbid copying of this class
public:
CharSubstitutionFilter(const LEFontInstance *fontInstance);
~CharSubstitutionFilter();
le_bool accept(LEGlyphID glyph) const;
};
CharSubstitutionFilter::CharSubstitutionFilter(const LEFontInstance *fontInstance)
: fFontInstance(fontInstance)
{
// nothing to do
}
CharSubstitutionFilter::~CharSubstitutionFilter()
{
// nothing to do
}
le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
{ {
return fFontInstance->canDisplay((LEUnicode) glyph); return fFontInstance->canDisplay((LEUnicode) glyph);

View File

@ -98,7 +98,7 @@ protected:
* @param offset - the index of the first character to process * @param offset - the index of the first character to process
* @param count - the number of characters to process * @param count - the number of characters to process
* @param max - the number of characters in the input context * @param max - the number of characters in the input context
* @param rightToLeft - TRUE if the characters are in a right to left directional run * @param rightToLeft - <code>TRUE</code> if the characters are in a right to left directional run
* *
* Output parameters: * Output parameters:
* @param outChars - the output character arrayt * @param outChars - the output character arrayt
@ -122,7 +122,7 @@ protected:
* @param chars - the input character context * @param chars - the input character context
* @param offset - the offset of the first character to process * @param offset - the offset of the first character to process
* @param count - the number of characters to process * @param count - the number of characters to process
* @param reverse - TRUE if the glyphs in the glyph array have been reordered * @param reverse - <code>TRUE</code> if the glyphs in the glyph array have been reordered
* @param glyphs - the input glyph array * @param glyphs - the input glyph array
* @param glyphCount - the number of glyphs * @param glyphCount - the number of glyphs
* @param positions - the position array, will be updated as needed * @param positions - the position array, will be updated as needed
@ -132,7 +132,7 @@ protected:
*/ */
virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphStorage &glyphStorage, LEErrorCode &success); virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphStorage &glyphStorage, LEErrorCode &success);
// static void adjustMarkGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool rightToLeft, LEGlyphStorage &glyphStorage, LEErrorCode &success); // static void adjustMarkGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool rightToLeft, LEGlyphStorage &glyphStorage, LEErrorCode &success);
private: private:
@ -210,12 +210,10 @@ protected:
* @param chars - the input character context * @param chars - the input character context
* @param offset - the offset of the first character to be mapped * @param offset - the offset of the first character to be mapped
* @param count - the number of characters to be mapped * @param count - the number of characters to be mapped
* @param reverse - if TRUE, the output will be in reverse order * @param reverse - if <code>TRUE</code>, the output will be in reverse order
* @param mirror - if TRUE, do character mirroring * @param mirror - if <code>TRUE</code>, do character mirroring
* @param glyphStorage - the glyph storage object. Glyph and char index arrays will be updated.
* *
* Output parameters:
* @param glyphs - the glyph array
* @param charIndices - the character index array
* @param success - set to an error code if the operation fails * @param success - set to an error code if the operation fails
* *
* @internal * @internal
@ -231,10 +229,8 @@ protected:
* @param chars - the input character context * @param chars - the input character context
* @param offset - the offset of the first character to process * @param offset - the offset of the first character to process
* @param count - the number of characters to process * @param count - the number of characters to process
* @param reverse - TRUE if the glyphs in the glyph array have been reordered * @param reverse - <code>TRUE</code> if the glyphs in the glyph array have been reordered
* @param glyphs - the input glyph array * @param glyphStorage - the glyph storage object. The glyph positions will be updated as needed.
* @param glyphCount - the number of glyphs
* @param positions - the position array, will be updated as needed
* @param success - output parameter set to an error code if the operation fails * @param success - output parameter set to an error code if the operation fails
* *
* @internal * @internal

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
/*
*
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
*
*/
#ifndef __CANONSHAPING_H
#define __CANONSHAPING_H
#include "LETypes.h"
U_NAMESPACE_BEGIN
class CanonShaping /* not : public UObject because all members are static */
{
public:
static const le_uint8 glyphSubstitutionTable[];
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,81 @@
/*
*
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
*
*/
#ifndef __CHARSUBSTITUTIONFILTER_H
#define __CHARSUBSTITUTIONFILTER_H
#include "LETypes.h"
#include "LEGlyphFilter.h"
U_NAMESPACE_BEGIN
class LEFontInstance;
/**
* This filter is used by character-based GSUB processors. It
* accepts only those characters which the given font can display.
*
* @internal
*/
class CharSubstitutionFilter : public UMemory, public LEGlyphFilter
{
private:
/**
* Holds the font which is used to test the characters.
*
* @internal
*/
const LEFontInstance *fFontInstance;
/**
* The copy constructor. Not allowed!
*
* @internal
*/
CharSubstitutionFilter(const CharSubstitutionFilter &other); // forbid copying of this class
/**
* The replacement operator. Not allowed!
*
* @internal
*/
CharSubstitutionFilter &operator=(const CharSubstitutionFilter &other); // forbid copying of this class
public:
/**
* The constructor.
*
* @param fontInstance - the font to use to test the characters.
*
* @internal
*/
CharSubstitutionFilter(const LEFontInstance *fontInstance);
/**
* The destructor.
*
* @internal
*/
~CharSubstitutionFilter();
/**
* This method is used to test if a particular
* character can be displayed by the filter's
* font.
*
* @param glyph - the Unicode character code to be tested
*
* @return TRUE if the filter's font can display this character.
*
* @internal
*/
le_bool accept(LEGlyphID glyph) const;
};
U_NAMESPACE_END
#endif

View File

@ -171,8 +171,6 @@ le_bool GlyphIterator::hasCursiveLastExitPoint() const
LEGlyphID GlyphIterator::getCurrGlyphID() const LEGlyphID GlyphIterator::getCurrGlyphID() const
{ {
LEErrorCode success = LE_NO_ERROR;
if (direction < 0) { if (direction < 0) {
if (position <= nextLimit || position >= prevLimit) { if (position <= nextLimit || position >= prevLimit) {
return 0xFFFF; return 0xFFFF;
@ -188,8 +186,6 @@ LEGlyphID GlyphIterator::getCurrGlyphID() const
LEGlyphID GlyphIterator::getCursiveLastGlyphID() const LEGlyphID GlyphIterator::getCursiveLastGlyphID() const
{ {
LEErrorCode success = LE_NO_ERROR;
if (direction < 0) { if (direction < 0) {
if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) { if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) {
return 0xFFFF; return 0xFFFF;

View File

@ -108,12 +108,11 @@ protected:
* @param offset - the index of the first character to process * @param offset - the index of the first character to process
* @param count - the number of characters to process * @param count - the number of characters to process
* @param max - the number of characters in the input context * @param max - the number of characters in the input context
* @param rightToLeft - TRUE if the characters are in a right to left directional run * @param rightToLeft - <code>TRUE</code> if the characters are in a right to left directional run
* @param glyphStorage - the glyph storage object. The glyph and character index arrays will be set.
* the auxillary data array will be set to the feature tags.
* *
* Output parameters: * Output parameters:
* @param outChars - the output character arrayt
* @param charIndices - the output character index array
* @param featureTags - the output feature tag array
* @param success - set to an error code if the operation fails * @param success - set to an error code if the operation fails
* *
* @return the output character count * @return the output character count
@ -137,12 +136,11 @@ protected:
* @param offset - the index of the first character to process * @param offset - the index of the first character to process
* @param count - the number of characters to process * @param count - the number of characters to process
* @param max - the number of characters in the input context * @param max - the number of characters in the input context
* @param rightToLeft - TRUE if the characters are in a right to left directional run * @param rightToLeft - <code>TRUE</code> if the characters are in a right to left directional run
* @param featureTags - the feature tag array * @param featureTags - the feature tag array
* @param glyphStorage - the glyph storage object. The glyph and char index arrays will be set.
* *
* Output parameters: * Output parameters:
* @param glyphs - the output glyph index array
* @param charIndices - the output character index array
* @param success - set to an error code if the operation fails * @param success - set to an error code if the operation fails
* *
* @return the number of glyphs in the output glyph index array * @return the number of glyphs in the output glyph index array

View File

@ -66,7 +66,7 @@ class LEGlyphStorage;
* methods with some default behavior such as returning constant values, or using the * methods with some default behavior such as returning constant values, or using the
* values from the first subfont. * values from the first subfont.
* *
* @draft ICU 2.6 * @draft ICU 3.0
*/ */
class U_LAYOUT_API LEFontInstance : public UObject class U_LAYOUT_API LEFontInstance : public UObject
{ {
@ -167,7 +167,7 @@ public:
* *
* @param ch - the character to be tested * @param ch - the character to be tested
* *
* @return TRUE if the font can render ch. * @return <code>TRUE</code> if the font can render ch.
* *
* @draft ICU 2.6 * @draft ICU 2.6
*/ */
@ -190,7 +190,7 @@ public:
* @param chars - the character array * @param chars - the character array
* @param offset - the index of the first character * @param offset - the index of the first character
* @param count - the number of characters * @param count - the number of characters
* @param reverse - if TRUE, store the glyph indices in reverse order. * @param reverse - if <code>TRUE</code>, store the glyph indices in reverse order.
* @param mapper - the character mapper. * @param mapper - the character mapper.
* @param glyphStorage - the object which contains the output glyph array * @param glyphStorage - the object which contains the output glyph array
* *
@ -252,7 +252,7 @@ public:
* @param pointNumber - the number of the point * @param pointNumber - the number of the point
* @param point - the point's X and Y pixel values will be stored here * @param point - the point's X and Y pixel values will be stored here
* *
* @return TRUE if the point coordinates could be stored. * @return <code>TRUE</code> if the point coordinates could be stored.
* *
* @stable ICU 2.8 * @stable ICU 2.8
*/ */

View File

@ -17,128 +17,128 @@ LEGlyphStorage::LEGlyphStorage()
: fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL), : fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL),
fAuxData(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0) fAuxData(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0)
{ {
// nothing else to do! // nothing else to do!
} }
LEGlyphStorage::~LEGlyphStorage() LEGlyphStorage::~LEGlyphStorage()
{ {
reset(); reset();
} }
void LEGlyphStorage::reset() void LEGlyphStorage::reset()
{ {
fGlyphCount = 0; fGlyphCount = 0;
if (fPositions != NULL) { if (fPositions != NULL) {
LE_DELETE_ARRAY(fPositions); LE_DELETE_ARRAY(fPositions);
fPositions = NULL; fPositions = NULL;
} }
if (fAuxData != NULL) { if (fAuxData != NULL) {
LE_DELETE_ARRAY(fAuxData); LE_DELETE_ARRAY(fAuxData);
fAuxData = NULL; fAuxData = NULL;
} }
if (fInsertionList != NULL) { if (fInsertionList != NULL) {
delete fInsertionList; delete fInsertionList;
fInsertionList = NULL; fInsertionList = NULL;
} }
if (fCharIndices != NULL) { if (fCharIndices != NULL) {
LE_DELETE_ARRAY(fCharIndices); LE_DELETE_ARRAY(fCharIndices);
fCharIndices = NULL; fCharIndices = NULL;
} }
if (fGlyphs != NULL) { if (fGlyphs != NULL) {
LE_DELETE_ARRAY(fGlyphs); LE_DELETE_ARRAY(fGlyphs);
fGlyphs = NULL; fGlyphs = NULL;
} }
} }
// FIXME: This might get called more than once, for various reasons. Is // FIXME: This might get called more than once, for various reasons. Is
// testing for pre-existing glyph and charIndices arrays good enough? // testing for pre-existing glyph and charIndices arrays good enough?
void LEGlyphStorage::allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success) void LEGlyphStorage::allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return; return;
} }
if (initialGlyphCount <= 0) { if (initialGlyphCount <= 0) {
success = LE_ILLEGAL_ARGUMENT_ERROR; success = LE_ILLEGAL_ARGUMENT_ERROR;
return; return;
} }
if (fGlyphs == NULL) { if (fGlyphs == NULL) {
fGlyphCount = initialGlyphCount; fGlyphCount = initialGlyphCount;
fGlyphs = LE_NEW_ARRAY(LEGlyphID, fGlyphCount); fGlyphs = LE_NEW_ARRAY(LEGlyphID, fGlyphCount);
if (fGlyphs == NULL) { if (fGlyphs == NULL) {
success = LE_MEMORY_ALLOCATION_ERROR; success = LE_MEMORY_ALLOCATION_ERROR;
return; return;
} }
} }
if (fCharIndices == NULL) { if (fCharIndices == NULL) {
fCharIndices = LE_NEW_ARRAY(le_int32, fGlyphCount); fCharIndices = LE_NEW_ARRAY(le_int32, fGlyphCount);
if (fCharIndices == NULL) { if (fCharIndices == NULL) {
LE_DELETE_ARRAY(fGlyphs); LE_DELETE_ARRAY(fGlyphs);
fGlyphs = NULL; fGlyphs = NULL;
success = LE_MEMORY_ALLOCATION_ERROR; success = LE_MEMORY_ALLOCATION_ERROR;
return; return;
} }
// Initialize the charIndices array // Initialize the charIndices array
le_int32 i, count = fGlyphCount, dir = 1, out = 0; le_int32 i, count = fGlyphCount, dir = 1, out = 0;
if (rightToLeft) { if (rightToLeft) {
out = fGlyphCount - 1; out = fGlyphCount - 1;
dir = -1; dir = -1;
} }
for (i = 0; i < count; i += 1, out += dir) { for (i = 0; i < count; i += 1, out += dir) {
fCharIndices[out] = i; fCharIndices[out] = i;
} }
} }
if (fInsertionList == NULL) { if (fInsertionList == NULL) {
// FIXME: check this for failure? // FIXME: check this for failure?
fInsertionList = new LEInsertionList(rightToLeft); fInsertionList = new LEInsertionList(rightToLeft);
} }
} }
// FIXME: do we want to initialize the positions to [0, 0]? // FIXME: do we want to initialize the positions to [0, 0]?
le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success) le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return -1; return -1;
} }
fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1)); fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1));
if (fPositions == NULL) { if (fPositions == NULL) {
success = LE_MEMORY_ALLOCATION_ERROR; success = LE_MEMORY_ALLOCATION_ERROR;
return -1; return -1;
} }
return fGlyphCount; return fGlyphCount;
} }
// FIXME: do we want to initialize the aux data to NULL? // FIXME: do we want to initialize the aux data to NULL?
le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success) le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return -1; return -1;
} }
fAuxData = LE_NEW_ARRAY(void *, fGlyphCount); fAuxData = LE_NEW_ARRAY(void *, fGlyphCount);
if (fAuxData == NULL) { if (fAuxData == NULL) {
success = LE_MEMORY_ALLOCATION_ERROR; success = LE_MEMORY_ALLOCATION_ERROR;
return -1; return -1;
} }
return fGlyphCount; return fGlyphCount;
} }
void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
@ -220,7 +220,7 @@ void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
if (fGlyphs == NULL) { if (fGlyphs == NULL) {
success = LE_NO_LAYOUT_ERROR; success = LE_NO_LAYOUT_ERROR;
return; return;
} }
LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount); LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount);
@ -228,78 +228,78 @@ void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return 0xFFFF; return 0xFFFF;
} }
if (fGlyphs == NULL) { if (fGlyphs == NULL) {
success = LE_NO_LAYOUT_ERROR; success = LE_NO_LAYOUT_ERROR;
return 0xFFFF; return 0xFFFF;
} }
if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return 0xFFFF; return 0xFFFF;
} }
return fGlyphs[glyphIndex]; return fGlyphs[glyphIndex];
} }
void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success) void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return; return;
} }
if (fGlyphs == NULL) { if (fGlyphs == NULL) {
success = LE_NO_LAYOUT_ERROR; success = LE_NO_LAYOUT_ERROR;
return; return;
} }
if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return; return;
} }
fGlyphs[glyphIndex] = glyphID; fGlyphs[glyphIndex] = glyphID;
} }
le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return -1; return -1;
} }
if (fCharIndices == NULL) { if (fCharIndices == NULL) {
success = LE_NO_LAYOUT_ERROR; success = LE_NO_LAYOUT_ERROR;
return -1; return -1;
} }
if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return -1; return -1;
} }
return fCharIndices[glyphIndex]; return fCharIndices[glyphIndex];
} }
void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success) void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return; return;
} }
if (fCharIndices == NULL) { if (fCharIndices == NULL) {
success = LE_NO_LAYOUT_ERROR; success = LE_NO_LAYOUT_ERROR;
return; return;
} }
if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return; return;
} }
fCharIndices[glyphIndex] = charIndex; fCharIndices[glyphIndex] = charIndex;
} }
void LEGlyphStorage::getAuxData(void *auxData[], LEErrorCode &success) const void LEGlyphStorage::getAuxData(void *auxData[], LEErrorCode &success) const
@ -315,7 +315,7 @@ void LEGlyphStorage::getAuxData(void *auxData[], LEErrorCode &success) const
if (fAuxData == NULL) { if (fAuxData == NULL) {
success = LE_NO_LAYOUT_ERROR; success = LE_NO_LAYOUT_ERROR;
return; return;
} }
LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount); LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount);
@ -323,40 +323,40 @@ void LEGlyphStorage::getAuxData(void *auxData[], LEErrorCode &success) const
void *LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const void *LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return NULL; return NULL;
} }
if (fAuxData == NULL) { if (fAuxData == NULL) {
success = LE_NO_LAYOUT_ERROR; success = LE_NO_LAYOUT_ERROR;
return NULL; return NULL;
} }
if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return NULL; return NULL;
} }
return fAuxData[glyphIndex]; return fAuxData[glyphIndex];
} }
void LEGlyphStorage::setAuxData(le_int32 glyphIndex, void *auxData, LEErrorCode &success) void LEGlyphStorage::setAuxData(le_int32 glyphIndex, void *auxData, LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return; return;
} }
if (fAuxData == NULL) { if (fAuxData == NULL) {
success = LE_NO_LAYOUT_ERROR; success = LE_NO_LAYOUT_ERROR;
return; return;
} }
if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return; return;
} }
fAuxData[glyphIndex] = auxData; fAuxData[glyphIndex] = auxData;
} }
void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const
@ -400,186 +400,186 @@ void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, L
void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success) void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return; return;
} }
if (glyphIndex < 0 || glyphIndex > fGlyphCount) { if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return; return;
} }
fPositions[glyphIndex * 2] = x; fPositions[glyphIndex * 2] = x;
fPositions[glyphIndex * 2 + 1] = y; fPositions[glyphIndex * 2 + 1] = y;
} }
void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success) void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return; return;
} }
if (glyphIndex < 0 || glyphIndex > fGlyphCount) { if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return; return;
} }
fPositions[glyphIndex * 2] += xAdjust; fPositions[glyphIndex * 2] += xAdjust;
fPositions[glyphIndex * 2 + 1] += yAdjust; fPositions[glyphIndex * 2 + 1] += yAdjust;
} }
void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from) void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from)
{ {
if (fGlyphs != NULL) { if (fGlyphs != NULL) {
LE_DELETE_ARRAY(fGlyphs); LE_DELETE_ARRAY(fGlyphs);
} }
fGlyphs = from.fGlyphs; fGlyphs = from.fGlyphs;
from.fGlyphs = NULL; from.fGlyphs = NULL;
if (fInsertionList != NULL) { if (fInsertionList != NULL) {
delete fInsertionList; delete fInsertionList;
} }
fInsertionList = from.fInsertionList; fInsertionList = from.fInsertionList;
from.fInsertionList = NULL; from.fInsertionList = NULL;
} }
void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from) void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from)
{ {
if (fCharIndices != NULL) { if (fCharIndices != NULL) {
LE_DELETE_ARRAY(fCharIndices); LE_DELETE_ARRAY(fCharIndices);
} }
fCharIndices = from.fCharIndices; fCharIndices = from.fCharIndices;
from.fCharIndices = NULL; from.fCharIndices = NULL;
} }
void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from) void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from)
{ {
if (fPositions != NULL) { if (fPositions != NULL) {
LE_DELETE_ARRAY(fPositions); LE_DELETE_ARRAY(fPositions);
} }
fPositions = from.fPositions; fPositions = from.fPositions;
from.fPositions = NULL; from.fPositions = NULL;
} }
void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from) void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from)
{ {
if (fAuxData != NULL) { if (fAuxData != NULL) {
LE_DELETE_ARRAY(fAuxData); LE_DELETE_ARRAY(fAuxData);
} }
fAuxData = from.fAuxData; fAuxData = from.fAuxData;
from.fAuxData = NULL; from.fAuxData = NULL;
} }
void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from) void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from)
{ {
fGlyphCount = from.fGlyphCount; fGlyphCount = from.fGlyphCount;
} }
void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount) void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount)
{ {
fGlyphCount = newGlyphCount; fGlyphCount = newGlyphCount;
} }
// FIXME: add error checking? // FIXME: add error checking?
LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount) LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount)
{ {
return fInsertionList->insert(atIndex, insertCount); return fInsertionList->insert(atIndex, insertCount);
} }
le_int32 LEGlyphStorage::applyInsertions() le_int32 LEGlyphStorage::applyInsertions()
{ {
le_int32 growAmount = fInsertionList->getGrowAmount(); le_int32 growAmount = fInsertionList->getGrowAmount();
if (growAmount == 0) { if (growAmount == 0) {
return fGlyphCount; return fGlyphCount;
} }
le_int32 newGlyphCount = fGlyphCount + growAmount; le_int32 newGlyphCount = fGlyphCount + growAmount;
fGlyphs = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs, newGlyphCount); fGlyphs = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs, newGlyphCount);
fCharIndices = (le_int32 *) LE_GROW_ARRAY(fCharIndices, newGlyphCount); fCharIndices = (le_int32 *) LE_GROW_ARRAY(fCharIndices, newGlyphCount);
if (fAuxData != NULL) { if (fAuxData != NULL) {
fAuxData = (void **) LE_GROW_ARRAY(fAuxData, newGlyphCount); fAuxData = (void **) LE_GROW_ARRAY(fAuxData, newGlyphCount);
} }
fSrcIndex = fGlyphCount - 1; fSrcIndex = fGlyphCount - 1;
fDestIndex = newGlyphCount - 1; fDestIndex = newGlyphCount - 1;
#if 0 #if 0
// If the current position is at the end of the array // If the current position is at the end of the array
// update it to point to the end of the new array. The // update it to point to the end of the new array. The
// insertion callback will handle all other cases. // insertion callback will handle all other cases.
// FIXME: this is left over from GlyphIterator, but there's no easy // FIXME: this is left over from GlyphIterator, but there's no easy
// way to implement this here... it seems that GlyphIterator doesn't // way to implement this here... it seems that GlyphIterator doesn't
// really need it 'cause the insertions don't get applied until after a // really need it 'cause the insertions don't get applied until after a
// complete pass over the glyphs, after which the iterator gets reset anyhow... // complete pass over the glyphs, after which the iterator gets reset anyhow...
// probably better to just document that for LEGlyphStorage and GlyphIterator... // probably better to just document that for LEGlyphStorage and GlyphIterator...
if (position == glyphCount) { if (position == glyphCount) {
position = newGlyphCount; position = newGlyphCount;
} }
#endif #endif
fInsertionList->applyInsertions(this); fInsertionList->applyInsertions(this);
fInsertionList->reset(); fInsertionList->reset();
return fGlyphCount = newGlyphCount; return fGlyphCount = newGlyphCount;
} }
le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[]) le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[])
{ {
#if 0 #if 0
// if the current position is within the block we're shifting // if the current position is within the block we're shifting
// it needs to be updated to the current glyph's // it needs to be updated to the current glyph's
// new location. // new location.
// FIXME: this is left over from GlyphIterator, but there's no easy // FIXME: this is left over from GlyphIterator, but there's no easy
// way to implement this here... it seems that GlyphIterator doesn't // way to implement this here... it seems that GlyphIterator doesn't
// really need it 'cause the insertions don't get applied until after a // really need it 'cause the insertions don't get applied until after a
// complete pass over the glyphs, after which the iterator gets reset anyhow... // complete pass over the glyphs, after which the iterator gets reset anyhow...
// probably better to just document that for LEGlyphStorage and GlyphIterator... // probably better to just document that for LEGlyphStorage and GlyphIterator...
if (position >= atPosition && position <= fSrcIndex) { if (position >= atPosition && position <= fSrcIndex) {
position += fDestIndex - fSrcIndex; position += fDestIndex - fSrcIndex;
} }
#endif #endif
if (fAuxData != NULL) { if (fAuxData != NULL) {
le_int32 src = fSrcIndex, dest = fDestIndex; le_int32 src = fSrcIndex, dest = fDestIndex;
while (src > atPosition) { while (src > atPosition) {
fAuxData[dest--] = fAuxData[src--]; fAuxData[dest--] = fAuxData[src--];
} }
for (le_int32 i = count - 1; i >= 0; i -= 1) { for (le_int32 i = count - 1; i >= 0; i -= 1) {
fAuxData[dest--] = fAuxData[atPosition]; fAuxData[dest--] = fAuxData[atPosition];
} }
} }
while (fSrcIndex > atPosition) { while (fSrcIndex > atPosition) {
fGlyphs[fDestIndex] = fGlyphs[fSrcIndex]; fGlyphs[fDestIndex] = fGlyphs[fSrcIndex];
fCharIndices[fDestIndex] = fCharIndices[fSrcIndex]; fCharIndices[fDestIndex] = fCharIndices[fSrcIndex];
fDestIndex -= 1; fDestIndex -= 1;
fSrcIndex -= 1; fSrcIndex -= 1;
} }
for (le_int32 i = count - 1; i >= 0; i -= 1) { for (le_int32 i = count - 1; i >= 0; i -= 1) {
fGlyphs[fDestIndex] = newGlyphs[i]; fGlyphs[fDestIndex] = newGlyphs[i];
fCharIndices[fDestIndex] = fCharIndices[atPosition]; fCharIndices[fDestIndex] = fCharIndices[atPosition];
fDestIndex -= 1; fDestIndex -= 1;
} }
// the source glyph we're pointing at // the source glyph we're pointing at
// just got replaced by the insertion // just got replaced by the insertion
fSrcIndex -= 1; fSrcIndex -= 1;
return FALSE; return FALSE;
} }
U_NAMESPACE_END U_NAMESPACE_END

View File

@ -13,19 +13,78 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
class LEGlyphStorage : public UObject, protected LEInsertionCallback /**
* 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:
le_int32 fGlyphCount; /**
* The number of entries in the per-glyph arrays.
*
* @internal
*/
le_int32 fGlyphCount;
LEGlyphID *fGlyphs; /**
le_int32 *fCharIndices; * The glyph ID array.
float *fPositions; *
void **fAuxData; * @internal
*/
LEGlyphID *fGlyphs;
/**
* The char indices array.
*
* @internal
*/
le_int32 *fCharIndices;
LEInsertionList *fInsertionList; /**
le_int32 fSrcIndex; * The glyph positions array.
le_int32 fDestIndex; *
* @internal
*/
float *fPositions;
/**
* The auxillary data array.
*
* @internal
*/
void **fAuxData;
/**
* The insertion list, used to grow the above arrays.
*
* @internal
*/
LEInsertionList *fInsertionList;
/**
* The source index while growing the data arrays.
*
* @internal
*/
le_int32 fSrcIndex;
/**
* The destination index used while growing the data arrays.
*
* @internal
*/
le_int32 fDestIndex;
/** /**
* The address of this static class variable serves as this class's ID * The address of this static class variable serves as this class's ID
@ -34,19 +93,39 @@ private:
static const char fgClassID; static const char fgClassID;
protected: protected:
virtual le_bool applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[]); /**
* 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: public:
// allocates glyphs, charIndices... /**
// call allocatePositions() or allocateAuxData() to allocat those. * Allocates an empty <code>LEGlyphStorage</code> object. You must call
LEGlyphStorage(); * <code>allocateGlyphArray, allocatePositions and allocateAuxData</code>
~LEGlyphStorage(); * to allocate the data.
*/
LEGlyphStorage();
/** /**
* This method returns the number of glyphs in the glyph array. Note * The destructor. This will deallocate all of the arrays.
* that the number of glyphs will be greater than or equal to the number */
* of characters used to create the LayoutEngine. ~LEGlyphStorage();
/**
* This method returns the number of glyphs in the glyph array.
* *
* @return the number of glyphs in the glyph array * @return the number of glyphs in the glyph array
* *
@ -137,45 +216,264 @@ public:
*/ */
void getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const; void getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const;
void allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success); /**
* This method allocates the glyph array, the char indices array and the insertion list. You
// allocate the given data array, return the size? (it's just the glyph count, * must call this method before using the object. This method also initializes the char indices
// so maybe we don't need to return it?) * array.
le_int32 allocatePositions(LEErrorCode &success); *
le_int32 allocateAuxData(LEErrorCode &success); * @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.
void getAuxData(void *auxData[], LEErrorCode &success) const; * @param success set to an error code if the storage cannot be allocated of if the initial
* glyph count is not positive.
LEGlyphID getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const; *
le_int32 getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const; * @draft ICU 3.0
*/
void *getAuxData(le_int32 glyphIndex, LEErrorCode &success) const; // or "getAuxDatum"? void allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success);
void setAuxData(le_int32 glyphIndex, void *auxData, LEErrorCode &success); // or "setAuxDatum"?
LEGlyphID &operator[](le_int32 glyphIndex) const;
// return value is address of storage for new glyphs...
LEGlyphID *insertGlyphs(le_int32 atIndex, le_int32 insertCount);
// return value is new glyph count.
le_int32 applyInsertions();
void setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success);
void setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success);
void setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success);
void adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success);
void adoptGlyphArray(LEGlyphStorage &from);
void adoptCharIndicesArray(LEGlyphStorage &from);
void adoptPositionArray(LEGlyphStorage &from);
void adoptAuxDataArray(LEGlyphStorage &from);
void adoptGlyphCount(LEGlyphStorage &from);
void adoptGlyphCount(le_int32 newGlyphCount);
/** /**
* This method frees the glyph, character index and position arrays * This method allocates the storage for the glyph positions. It allocates one extra X, Y
* so that the LayoutEngine can be reused to layout a different * position pair for the position just after the last glyph.
* characer array. (This method is also called by the destructor) *
* @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 * @draft ICU 3.0
*/ */
@ -198,7 +496,7 @@ public:
inline LEGlyphID &LEGlyphStorage::operator[](le_int32 glyphIndex) const inline LEGlyphID &LEGlyphStorage::operator[](le_int32 glyphIndex) const
{ {
return fGlyphs[glyphIndex]; return fGlyphs[glyphIndex];
} }

View File

@ -14,24 +14,107 @@ U_NAMESPACE_BEGIN
struct InsertionRecord; struct InsertionRecord;
/**
* This class encapsulates the callback used by <code>LEInsertionList</code>
* to apply an insertion from the insertion list.
*
* @internal
*/
class LEInsertionCallback class LEInsertionCallback
{ {
public: public:
virtual le_bool applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[]) = 0; /**
* 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 class LEInsertionList : public UObject
{ {
public: public:
LEInsertionList(le_bool rightToLeft); /**
~LEInsertionList(); * 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);
LEGlyphID *insert(le_int32 position, le_int32 count); /**
le_int32 getGrowAmount(); * The destructor.
*/
~LEInsertionList();
le_bool applyInsertions(LEInsertionCallback *callback); /**
* 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);
void reset(); /**
* 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. * ICU "poor man's RTTI", returns a UClassID for the actual class.
@ -55,11 +138,36 @@ private:
*/ */
static const char fgClassID; static const char fgClassID;
InsertionRecord *head; /**
InsertionRecord *tail; * The head of the insertion list.
*
* @internal
*/
InsertionRecord *head;
le_int32 growAmount; /**
le_bool append; * The tail of the insertion list.
*
* @internal
*/
InsertionRecord *tail;
/**
* The total number of new glyphs on the insertion list.
*
* @internal
*/
le_int32 growAmount;
/**
* Set to <code>TRUE</code> if the glyphs are in right
* to left order. Since we want the rightmost insertion
* to be first on the list, we need to append the
* insertions in this case. Otherwise they're prepended.
*
* @internal
*/
le_bool append;
}; };
U_NAMESPACE_END U_NAMESPACE_END

View File

@ -12,11 +12,13 @@
#include "LayoutEngine.h" #include "LayoutEngine.h"
#include "ArabicLayoutEngine.h" #include "ArabicLayoutEngine.h"
#include "CanonShaping.h"
#include "HanLayoutEngine.h" #include "HanLayoutEngine.h"
#include "IndicLayoutEngine.h" #include "IndicLayoutEngine.h"
#include "ThaiLayoutEngine.h" #include "ThaiLayoutEngine.h"
#include "GXLayoutEngine.h" #include "GXLayoutEngine.h"
#include "ScriptAndLanguageTags.h" #include "ScriptAndLanguageTags.h"
#include "CharSubstitutionFilter.h"
#include "LEGlyphStorage.h" #include "LEGlyphStorage.h"
@ -92,8 +94,26 @@ LEGlyphFilter::~LEGlyphFilter()
// nothing to do // nothing to do
} }
CharSubstitutionFilter::CharSubstitutionFilter(const LEFontInstance *fontInstance)
: fFontInstance(fontInstance)
{
// nothing to do
}
CharSubstitutionFilter::~CharSubstitutionFilter()
{
// nothing to do
}
const char LayoutEngine::fgClassID=0; const char LayoutEngine::fgClassID=0;
const LETag emptyTag = 0x00000000;
const LETag ccmpFeatureTag = LE_CCMP_FEATURE_TAG;
const LETag canonFeatures[] = {ccmpFeatureTag, emptyTag};
LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode) LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
: fGlyphStorage(NULL), fFontInstance(fontInstance), fScriptCode(scriptCode), fLanguageCode(languageCode) : fGlyphStorage(NULL), fFontInstance(fontInstance), fScriptCode(scriptCode), fLanguageCode(languageCode)
{ {
@ -137,6 +157,55 @@ void LayoutEngine::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEE
fGlyphStorage->getGlyphPosition(glyphIndex, x, y, success); fGlyphStorage->getGlyphPosition(glyphIndex, x, y, success);
} }
le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
if (LE_FAILURE(success)) {
return 0;
}
if (offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
success = LE_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
const GlyphSubstitutionTableHeader *canonGSUBTable = (GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
LETag scriptTag = OpenTypeLayoutEngine::getScriptTag(fScriptCode);
LETag langSysTag = OpenTypeLayoutEngine::getLangSysTag(fLanguageCode);
le_int32 i, dir = 1, out = 0, outCharCount = count;
if (rightToLeft) {
out = count - 1;
dir = -1;
}
if (canonGSUBTable->coversScript(scriptTag)) {
CharSubstitutionFilter *substitutionFilter = new CharSubstitutionFilter(fFontInstance);
glyphStorage.allocateGlyphArray(count, rightToLeft, success);
glyphStorage.allocateAuxData(success);
if (LE_FAILURE(success)) {
return 0;
}
for (i = 0; i < count; i += 1, out += dir) {
glyphStorage[i] = (LEGlyphID) chars[offset + i];
glyphStorage.setAuxData(i, (void *) canonFeatures, success);
}
outCharCount = canonGSUBTable->process(glyphStorage, rightToLeft, scriptTag, langSysTag, NULL, substitutionFilter, NULL);
outChars = LE_NEW_ARRAY(LEUnicode, outCharCount);
for (i = 0; i < outCharCount; i += 1) {
outChars[i] = (LEUnicode) LE_GET_GLYPH(glyphStorage[i]);
}
delete substitutionFilter;
}
return outCharCount;
}
le_int32 LayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, le_int32 LayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
LEGlyphStorage &glyphStorage, LEErrorCode &success) LEGlyphStorage &glyphStorage, LEErrorCode &success)
@ -150,7 +219,15 @@ le_int32 LayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, l
return 0; return 0;
} }
mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success); LEUnicode *outChars = NULL;
le_int32 outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, glyphStorage, success);
if (outChars != NULL) {
mapCharsToGlyphs(outChars, 0, outCharCount, rightToLeft, rightToLeft, glyphStorage, success);
LE_DELETE_ARRAY(outChars); // FIXME: a subclass may have allocated this, in which case this delete might not work...
} else {
mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success);
}
return glyphStorage.getGlyphCount(); return glyphStorage.getGlyphCount();
} }

View File

@ -65,7 +65,7 @@ class LEGlyphStorage;
class U_LAYOUT_API LayoutEngine : public UObject { class U_LAYOUT_API LayoutEngine : public UObject {
protected: protected:
/** /**
* The number of glyphs in the output * The object which holds the glyph storage
* *
* @internal * @internal
*/ */
@ -122,6 +122,31 @@ protected:
*/ */
LayoutEngine(); LayoutEngine();
/**
* This method does any required pre-processing to the input characters. It
* may generate output characters that differ from the input charcters due to
* insertions, deletions, or reorderings. In such cases, it will also generate an
* output character index array reflecting these changes.
*
* Subclasses must override this method.
*
* Input parameters:
* @param chars - the input character context
* @param offset - the index of the first character to process
* @param count - the number of characters to process
* @param max - the number of characters in the input context
* @param rightToLeft - TRUE if the characters are in a right to left directional run
* @param outChars - the output character array, if different from the input
* @param glyphStorege - the object that holds the per-glyph storage. The character index array may be set.
* @param success - set to an error code if the operation fails
*
* @return the output character count (input character count if no change)
*
* @internal
*/
virtual le_int32 characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success);
/** /**
* This method does the glyph processing. It converts an array of characters * This method does the glyph processing. It converts an array of characters
* into an array of glyph indices and character indices. The characters to be * into an array of glyph indices and character indices. The characters to be
@ -138,10 +163,10 @@ protected:
* @param count - the number of characters to process * @param count - the number of characters to process
* @param max - the number of characters in the context. * @param max - the number of characters in the context.
* @param rightToLeft - TRUE if the text is in a right to left directional run * @param rightToLeft - TRUE if the text is in a right to left directional run
* @param glyphStorage - the object which holds the per-glyph storage. The glyph and char indices arrays
* will be set.
* *
* Output parameters: * Output parameters:
* @param glyphs - the glyph index array
* @param charIndices - the character index array
* @param success - set to an error code if the operation fails * @param success - set to an error code if the operation fails
* *
* @return the number of glyphs in the glyph index array * @return the number of glyphs in the glyph index array
@ -156,13 +181,10 @@ protected:
* is not expected that many subclasses will override this method. * is not expected that many subclasses will override this method.
* *
* Input parameters: * Input parameters:
* @param glyphs - the input glyph array * @param glyphStorage - the object which holds the per-glyph storage. The glyph position array will be set.
* @param glyphCount - the number of glyphs in the glyph array
* @param x - the starting X position * @param x - the starting X position
* @param y - the starting Y position * @param y - the starting Y position
* * @param success - set to an error code if the operation fails
* Output parameters:
* @param positions - the output X and Y positions (two entries per glyph)
* *
* @internal * @internal
*/ */
@ -181,15 +203,11 @@ protected:
* @param chars - the input character context * @param chars - the input character context
* @param offset - the offset of the first character to process * @param offset - the offset of the first character to process
* @param count - the number of characters to process * @param count - the number of characters to process
* @param reverse - TRUE if the glyphs in the glyph array have been reordered * @param reverse - <code>TRUE</code> if the glyphs in the glyph array have been reordered
* @param glyphs - the input glyph array * @param glyphStorage - the object which holds the per-glyph storage. The glyph positions will be
* @param glyphCount - the number of glyphs * adjusted as needed.
* @param positions - the position array, will be updated as needed
* @param success - output parameter set to an error code if the operation fails * @param success - output parameter set to an error code if the operation fails
* *
* Note: the positions are passed as a plain array because this method should
* not need to reallocate them.
*
* @internal * @internal
*/ */
virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool /*reverse*/, LEGlyphStorage &glyphStorage, LEErrorCode &success); virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool /*reverse*/, LEGlyphStorage &glyphStorage, LEErrorCode &success);
@ -223,12 +241,10 @@ protected:
* @param chars - the input character context * @param chars - the input character context
* @param offset - the offset of the first character to be mapped * @param offset - the offset of the first character to be mapped
* @param count - the number of characters to be mapped * @param count - the number of characters to be mapped
* @param reverse - if TRUE, the output will be in reverse order * @param reverse - if <code>TRUE</code>, the output will be in reverse order
* @param mirror - if TRUE, do character mirroring * @param mirror - if <code>TRUE</code>, do character mirroring
* * @param glyphStorage - the object which holds the per-glyph storage. The glyph and char
* Output parameters: * indices arrays will be filled in.
* @param glyphs - the glyph array
* @param charIndices - the character index array
* @param success - set to an error code if the operation fails * @param success - set to an error code if the operation fails
* *
* @see LEFontInstance * @see LEFontInstance
@ -241,11 +257,9 @@ protected:
* This is a convenience method that forces the advance width of mark * This is a convenience method that forces the advance width of mark
* glyphs to be zero, which is required for proper selection and highlighting. * glyphs to be zero, which is required for proper selection and highlighting.
* *
* @param glyphs - the glyph array * @param glyphStorage - the object containing the per-glyph storage. The positions array will be modified.
* @param glyphCount - the number of glyphs * @param reverse - <code>TRUE</code> if the glyph array has been reordered
* @param reverse - TRUE if the glyph array has been reordered
* @param markFilter - used to identify mark glyphs * @param markFilter - used to identify mark glyphs
* @param positions - the glyph position array - updated as required
* @param success - output parameter set to an error code if the operation fails * @param success - output parameter set to an error code if the operation fails
* *
* @see LEGlyphFilter * @see LEGlyphFilter
@ -254,6 +268,25 @@ protected:
*/ */
static void adjustMarkGlyphs(LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success); static void adjustMarkGlyphs(LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success);
/**
* This is a convenience method that forces the advance width of mark
* glyphs to be zero, which is required for proper selection and highlighting.
* This method uses the input characters to identify marks. This is required in
* cases where the font does not contain enough information to identify them based
* on the glyph IDs.
*
* @param chars - the array of input characters
* @param charCount - the number of input characers
* @param glyphStorage - the object containing the per-glyph storage. The positions array will be modified.
* @param reverse - <code>TRUE</code> if the glyph array has been reordered
* @param markFilter - used to identify mark glyphs
* @param success - output parameter set to an error code if the operation fails
*
* @see LEGlyphFilter
*
* @internal
*/
static void adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount, le_bool reverse, LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success); static void adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount, le_bool reverse, LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success);

View File

@ -77,6 +77,7 @@ AlternateSubstSubtables.o \
AnchorTables.o \ AnchorTables.o \
ArabicLigatureData.o \ ArabicLigatureData.o \
ArabicShaping.o \ ArabicShaping.o \
CanonData.o \
ClassDefinitionTables.o \ ClassDefinitionTables.o \
ContextualSubstSubtables.o \ ContextualSubstSubtables.o \
CoverageTables.o \ CoverageTables.o \

View File

@ -18,6 +18,18 @@ U_NAMESPACE_BEGIN
le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const
{ {
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
// If there's a filter, we only want to do the
// substitution if the *input* glyphs doesn't
// exist.
//
// FIXME: is this always the right thing to do?
// FIXME: should this only be done for a non-zero
// glyphCount?
if (filter != NULL && filter->accept(glyph)) {
return 0;
}
le_int32 coverageIndex = getGlyphCoverage(glyph); le_int32 coverageIndex = getGlyphCoverage(glyph);
le_uint16 seqCount = SWAPW(sequenceCount); le_uint16 seqCount = SWAPW(sequenceCount);
@ -32,12 +44,25 @@ le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, co
} else if (glyphCount == 1) { } else if (glyphCount == 1) {
TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]); TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]);
if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, substitute))) { if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute))) {
glyphIterator->setCurrGlyphID(substitute); return 0;
} }
glyphIterator->setCurrGlyphID(substitute);
return 1; return 1;
} else { } else {
// If there's a filter, make sure all of the output glyphs
// exist.
if (filter != NULL) {
for (le_int32 i = 0; i < glyphCount; i += 1) {
TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]);
if (! filter->accept(substitute)) {
return 0;
}
}
}
LEGlyphID *newGlyphs = glyphIterator->insertGlyphs(glyphCount); LEGlyphID *newGlyphs = glyphIterator->insertGlyphs(glyphCount);
le_int32 insert = 0, direction = 1; le_int32 insert = 0, direction = 1;

View File

@ -26,9 +26,21 @@ U_NAMESPACE_BEGIN
const char OpenTypeLayoutEngine::fgClassID=0; const char OpenTypeLayoutEngine::fgClassID=0;
const LETag emptyTag = 0x00000000;
const LETag ccmpFeatureTag = LE_CCMP_FEATURE_TAG;
const LETag ligaFeatureTag = LE_LIGA_FEATURE_TAG;
const LETag cligFeatureTag = LE_CLIG_FEATURE_TAG;
const LETag kernFeatureTag = LE_KERN_FEATURE_TAG;
const LETag markFeatureTag = LE_MARK_FEATURE_TAG;
const LETag mkmkFeatureTag = LE_MKMK_FEATURE_TAG;
const LETag defaultFeatures[] = {ccmpFeatureTag, ligaFeatureTag, cligFeatureTag, kernFeatureTag, markFeatureTag, mkmkFeatureTag, emptyTag};
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
const GlyphSubstitutionTableHeader *gsubTable) const GlyphSubstitutionTableHeader *gsubTable)
: LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureOrder(NULL), : LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureList(defaultFeatures), fFeatureOrder(NULL),
fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL)
{ {
static le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG; static le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG;
@ -89,8 +101,8 @@ void OpenTypeLayoutEngine::setScriptAndLanguageTags()
fLangSysTag = getLangSysTag(fLanguageCode); fLangSysTag = getLangSysTag(fLanguageCode);
} }
le_int32 OpenTypeLayoutEngine::characterProcessing(const LEUnicode /*chars*/[], le_int32 offset, le_int32 count, le_int32 max, le_bool /*rightToLeft*/, le_int32 OpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
LEUnicode *&/*outChars*/, LEGlyphStorage &glyphStorage, LEErrorCode &success) LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return 0; return 0;
@ -101,7 +113,19 @@ le_int32 OpenTypeLayoutEngine::characterProcessing(const LEUnicode /*chars*/[],
return 0; return 0;
} }
return count; le_int32 outCharCount = LayoutEngine::characterProcessing(chars, offset, count, max, rightToLeft, outChars, glyphStorage, success);
if (LE_FAILURE(success)) {
return 0;
}
glyphStorage.allocateAuxData(success);
for (le_int32 i = 0; i < outCharCount; i += 1) {
glyphStorage.setAuxData(i, (void *) fFeatureList, success);
}
return outCharCount;
} }
// Input: characters, tags // Input: characters, tags
@ -160,17 +184,18 @@ le_int32 OpenTypeLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 o
return 0; return 0;
} }
outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, fakeGlyphStorage, success); outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, fakeGlyphStorage, success);
if (outChars != NULL) { if (outChars != NULL) {
fakeGlyphCount = glyphProcessing(outChars, 0, outCharCount, outCharCount, rightToLeft, fakeGlyphStorage, success); fakeGlyphCount = glyphProcessing(outChars, 0, outCharCount, outCharCount, rightToLeft, fakeGlyphStorage, success);
LE_DELETE_ARRAY(outChars); // FIXME: a subclass may have allocated this, in which case this delete might not work...
//adjustGlyphs(outChars, 0, outCharCount, rightToLeft, fakeGlyphs, fakeGlyphCount); //adjustGlyphs(outChars, 0, outCharCount, rightToLeft, fakeGlyphs, fakeGlyphCount);
} else { } else {
fakeGlyphCount = glyphProcessing(chars, offset, count, max, rightToLeft, fakeGlyphStorage, success); fakeGlyphCount = glyphProcessing(chars, offset, count, max, rightToLeft, fakeGlyphStorage, success);
//adjustGlyphs(chars, offset, count, rightToLeft, fakeGlyphs, fakeGlyphCount); //adjustGlyphs(chars, offset, count, rightToLeft, fakeGlyphs, fakeGlyphCount);
} }
outGlyphCount = glyphPostProcessing(fakeGlyphStorage, glyphStorage, success); outGlyphCount = glyphPostProcessing(fakeGlyphStorage, glyphStorage, success);
return outGlyphCount; return outGlyphCount;
} }

View File

@ -149,6 +149,14 @@ private:
static const char fgClassID; static const char fgClassID;
protected: protected:
/**
* A list of "default" features. The default characterProcessing method
* will apply all of these tags to every glyph.
*
* @internal
*/
const LETag *fFeatureList;
/** /**
* A list of tags in the order in which the features in * A list of tags in the order in which the features in
* the font should be applied, as opposed to using the * the font should be applied, as opposed to using the
@ -206,7 +214,7 @@ protected:
/** /**
* This method does the OpenType character processing. It assigns the OpenType feature * This method does the OpenType character processing. It assigns the OpenType feature
* tags to the characters, and may generate output characters that differ from the input * tags to the characters, and may generate output characters that differ from the input
* charcters dueto insertions, deletions, or reorderings. In such cases, it will also * charcters due to insertions, deletions, or reorderings. In such cases, it will also
* generate an output character index array reflecting these changes. * generate an output character index array reflecting these changes.
* *
* Subclasses must override this method. * Subclasses must override this method.

View File

@ -99,11 +99,10 @@ protected:
* @param offset - the index of the first character to process * @param offset - the index of the first character to process
* @param count - the number of characters to process * @param count - the number of characters to process
* @param max - the number of characters in the input context * @param max - the number of characters in the input context
* @param rightToLeft - TRUE if the text is in a right to left directional run * @param rightToLeft - <code>TRUE</code> if the text is in a right to left directional run
* @param glyphStorage - the glyph storage object. The glyph and char index arrays will be set.
* *
* Output parameters: * Output parameters:
* @param glyphs - the glyph index array
* @param charIndices - the character index array
* @param success - set to an error code if the operation fails * @param success - set to an error code if the operation fails
* *
* @return the number of glyphs in the glyph index array * @return the number of glyphs in the glyph index array

View File

@ -163,6 +163,9 @@
<File <File
RelativePath=".\ArabicShaping.cpp"> RelativePath=".\ArabicShaping.cpp">
</File> </File>
<File
RelativePath=".\CanonData.cpp">
</File>
<File <File
RelativePath=".\ClassDefinitionTables.cpp"> RelativePath=".\ClassDefinitionTables.cpp">
</File> </File>
@ -365,6 +368,12 @@
<File <File
RelativePath=".\AttachmentPosnSubtables.h"> RelativePath=".\AttachmentPosnSubtables.h">
</File> </File>
<File
RelativePath=".\CanonShaping.h">
</File>
<File
RelativePath=".\CharSubstitutionFilter.h">
</File>
<File <File
RelativePath=".\ClassDefinitionTables.h"> RelativePath=".\ClassDefinitionTables.h">
</File> </File>
@ -511,9 +520,41 @@
</File> </File>
<File <File
RelativePath=".\LEGlyphStorage.h"> RelativePath=".\LEGlyphStorage.h">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\layout
"
Outputs="..\..\include\layout\$(InputFileName)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\layout
"
Outputs="..\..\include\layout\$(InputFileName)"/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath=".\LEInsertionList.h"> RelativePath=".\LEInsertionList.h">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\layout
"
Outputs="..\..\include\layout\$(InputFileName)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\layout
"
Outputs="..\..\include\layout\$(InputFileName)"/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath=".\LELanguages.h"> RelativePath=".\LELanguages.h">