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 "ArabicLayoutEngine.h"
#include "ScriptAndLanguageTags.h"
#include "CharSubstitutionFilter.h"
#include "GlyphSubstitutionTables.h"
#include "GlyphDefinitionTables.h"
@ -25,33 +26,6 @@
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
{
return fFontInstance->canDisplay((LEUnicode) glyph);

View File

@ -98,7 +98,7 @@ protected:
* @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 rightToLeft - <code>TRUE</code> if the characters are in a right to left directional run
*
* Output parameters:
* @param outChars - the output character arrayt
@ -122,7 +122,7 @@ protected:
* @param chars - the input character context
* @param offset - the offset of the first character 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 glyphCount - the number of glyphs
* @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);
// 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:
@ -210,12 +210,10 @@ protected:
* @param chars - the input character context
* @param offset - the offset of the first character to be mapped
* @param count - the number of characters to be mapped
* @param reverse - if TRUE, the output will be in reverse order
* @param mirror - if TRUE, do character mirroring
* @param reverse - if <code>TRUE</code>, the output will be in reverse order
* @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
*
* @internal
@ -231,10 +229,8 @@ protected:
* @param chars - the input character context
* @param offset - the offset of the first character to process
* @param count - the number of characters to process
* @param reverse - TRUE if the glyphs in the glyph array have been reordered
* @param glyphs - the input glyph array
* @param glyphCount - the number of glyphs
* @param positions - the position array, will be updated as needed
* @param reverse - <code>TRUE</code> if the glyphs in the glyph array have been reordered
* @param glyphStorage - the glyph storage object. The glyph positions will be updated as needed.
* @param success - output parameter set to an error code if the operation fails
*
* @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
{
LEErrorCode success = LE_NO_ERROR;
if (direction < 0) {
if (position <= nextLimit || position >= prevLimit) {
return 0xFFFF;
@ -188,8 +186,6 @@ LEGlyphID GlyphIterator::getCurrGlyphID() const
LEGlyphID GlyphIterator::getCursiveLastGlyphID() const
{
LEErrorCode success = LE_NO_ERROR;
if (direction < 0) {
if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) {
return 0xFFFF;

View File

@ -108,12 +108,11 @@ protected:
* @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 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:
* @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
*
* @return the output character count
@ -137,12 +136,11 @@ protected:
* @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 rightToLeft - <code>TRUE</code> if the characters are in a right to left directional run
* @param featureTags - the feature tag array
* @param glyphStorage - the glyph storage object. The glyph and char index arrays will be set.
*
* 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
*
* @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
* values from the first subfont.
*
* @draft ICU 2.6
* @draft ICU 3.0
*/
class U_LAYOUT_API LEFontInstance : public UObject
{
@ -167,7 +167,7 @@ public:
*
* @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
*/
@ -190,7 +190,7 @@ public:
* @param chars - the character array
* @param offset - the index of the first character
* @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 glyphStorage - the object which contains the output glyph array
*
@ -252,7 +252,7 @@ public:
* @param pointNumber - the number of the point
* @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
*/

View File

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

View File

@ -13,19 +13,78 @@
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:
le_int32 fGlyphCount;
/**
* The number of entries in the per-glyph arrays.
*
* @internal
*/
le_int32 fGlyphCount;
LEGlyphID *fGlyphs;
le_int32 *fCharIndices;
float *fPositions;
void **fAuxData;
/**
* The glyph ID array.
*
* @internal
*/
LEGlyphID *fGlyphs;
/**
* The char indices array.
*
* @internal
*/
le_int32 *fCharIndices;
LEInsertionList *fInsertionList;
le_int32 fSrcIndex;
le_int32 fDestIndex;
/**
* The glyph positions array.
*
* @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
@ -34,19 +93,39 @@ private:
static const char fgClassID;
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:
// allocates glyphs, charIndices...
// call allocatePositions() or allocateAuxData() to allocat those.
LEGlyphStorage();
~LEGlyphStorage();
/**
* Allocates an empty <code>LEGlyphStorage</code> object. You must call
* <code>allocateGlyphArray, allocatePositions and allocateAuxData</code>
* to allocate the data.
*/
LEGlyphStorage();
/**
* This method returns the number of glyphs in the glyph array. Note
* that the number of glyphs will be greater than or equal to the number
* of characters used to create the LayoutEngine.
* 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
*
@ -137,45 +216,264 @@ public:
*/
void getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const;
void allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success);
// allocate the given data array, return the size? (it's just the glyph count,
// so maybe we don't need to return it?)
le_int32 allocatePositions(LEErrorCode &success);
le_int32 allocateAuxData(LEErrorCode &success);
void getAuxData(void *auxData[], LEErrorCode &success) const;
LEGlyphID getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const;
le_int32 getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const;
void *getAuxData(le_int32 glyphIndex, LEErrorCode &success) const; // or "getAuxDatum"?
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 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 frees the glyph, character index and position arrays
* so that the LayoutEngine can be reused to layout a different
* characer array. (This method is also called by the destructor)
* 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
*/
@ -198,7 +496,7 @@ public:
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;
/**
* This class encapsulates the callback used by <code>LEInsertionList</code>
* to apply an insertion from the insertion list.
*
* @internal
*/
class LEInsertionCallback
{
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
{
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.
@ -55,11 +138,36 @@ private:
*/
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

View File

@ -12,11 +12,13 @@
#include "LayoutEngine.h"
#include "ArabicLayoutEngine.h"
#include "CanonShaping.h"
#include "HanLayoutEngine.h"
#include "IndicLayoutEngine.h"
#include "ThaiLayoutEngine.h"
#include "GXLayoutEngine.h"
#include "ScriptAndLanguageTags.h"
#include "CharSubstitutionFilter.h"
#include "LEGlyphStorage.h"
@ -92,8 +94,26 @@ LEGlyphFilter::~LEGlyphFilter()
// nothing to do
}
CharSubstitutionFilter::CharSubstitutionFilter(const LEFontInstance *fontInstance)
: fFontInstance(fontInstance)
{
// nothing to do
}
CharSubstitutionFilter::~CharSubstitutionFilter()
{
// nothing to do
}
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)
: 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);
}
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,
LEGlyphStorage &glyphStorage, LEErrorCode &success)
@ -150,7 +219,15 @@ le_int32 LayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, l
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();
}

View File

@ -65,7 +65,7 @@ class LEGlyphStorage;
class U_LAYOUT_API LayoutEngine : public UObject {
protected:
/**
* The number of glyphs in the output
* The object which holds the glyph storage
*
* @internal
*/
@ -122,6 +122,31 @@ protected:
*/
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
* 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 max - the number of characters in the context.
* @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:
* @param glyphs - the glyph index array
* @param charIndices - the character index array
* @param success - set to an error code if the operation fails
*
* @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.
*
* Input parameters:
* @param glyphs - the input glyph array
* @param glyphCount - the number of glyphs in the glyph array
* @param glyphStorage - the object which holds the per-glyph storage. The glyph position array will be set.
* @param x - the starting X position
* @param y - the starting Y position
*
* Output parameters:
* @param positions - the output X and Y positions (two entries per glyph)
* @param success - set to an error code if the operation fails
*
* @internal
*/
@ -181,15 +203,11 @@ protected:
* @param chars - the input character context
* @param offset - the offset of the first character to process
* @param count - the number of characters to process
* @param reverse - TRUE if the glyphs in the glyph array have been reordered
* @param glyphs - the input glyph array
* @param glyphCount - the number of glyphs
* @param positions - the position array, will be updated as needed
* @param reverse - <code>TRUE</code> if the glyphs in the glyph array have been reordered
* @param glyphStorage - the object which holds the per-glyph storage. The glyph positions will be
* adjusted as needed.
* @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
*/
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 offset - the offset of the first character to be mapped
* @param count - the number of characters to be mapped
* @param reverse - if TRUE, the output will be in reverse order
* @param mirror - if TRUE, do character mirroring
*
* Output parameters:
* @param glyphs - the glyph array
* @param charIndices - the character index array
* @param reverse - if <code>TRUE</code>, the output will be in reverse order
* @param mirror - if <code>TRUE</code>, do character mirroring
* @param glyphStorage - the object which holds the per-glyph storage. The glyph and char
* indices arrays will be filled in.
* @param success - set to an error code if the operation fails
*
* @see LEFontInstance
@ -241,11 +257,9 @@ protected:
* This is a convenience method that forces the advance width of mark
* glyphs to be zero, which is required for proper selection and highlighting.
*
* @param glyphs - the glyph array
* @param glyphCount - the number of glyphs
* @param reverse - TRUE if the glyph array has been reordered
* @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 positions - the glyph position array - updated as required
* @param success - output parameter set to an error code if the operation fails
*
* @see LEGlyphFilter
@ -254,6 +268,25 @@ protected:
*/
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);

View File

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

View File

@ -18,6 +18,18 @@ U_NAMESPACE_BEGIN
le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const
{
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_uint16 seqCount = SWAPW(sequenceCount);
@ -32,12 +44,25 @@ le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, co
} else if (glyphCount == 1) {
TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]);
if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, substitute))) {
glyphIterator->setCurrGlyphID(substitute);
if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute))) {
return 0;
}
glyphIterator->setCurrGlyphID(substitute);
return 1;
} 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);
le_int32 insert = 0, direction = 1;

View File

@ -26,9 +26,21 @@ U_NAMESPACE_BEGIN
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,
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)
{
static le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG;
@ -89,8 +101,8 @@ void OpenTypeLayoutEngine::setScriptAndLanguageTags()
fLangSysTag = getLangSysTag(fLanguageCode);
}
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)
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)
{
if (LE_FAILURE(success)) {
return 0;
@ -101,7 +113,19 @@ le_int32 OpenTypeLayoutEngine::characterProcessing(const LEUnicode /*chars*/[],
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
@ -160,17 +184,18 @@ le_int32 OpenTypeLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 o
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) {
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);
} else {
fakeGlyphCount = glyphProcessing(chars, offset, count, max, rightToLeft, fakeGlyphStorage, success);
//adjustGlyphs(chars, offset, count, rightToLeft, fakeGlyphs, fakeGlyphCount);
}
outGlyphCount = glyphPostProcessing(fakeGlyphStorage, glyphStorage, success);
outGlyphCount = glyphPostProcessing(fakeGlyphStorage, glyphStorage, success);
return outGlyphCount;
}

View File

@ -149,6 +149,14 @@ private:
static const char fgClassID;
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
* 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
* 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.
*
* Subclasses must override this method.

View File

@ -99,11 +99,10 @@ protected:
* @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 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:
* @param glyphs - the glyph index array
* @param charIndices - the character index array
* @param success - set to an error code if the operation fails
*
* @return the number of glyphs in the glyph index array

View File

@ -163,6 +163,9 @@
<File
RelativePath=".\ArabicShaping.cpp">
</File>
<File
RelativePath=".\CanonData.cpp">
</File>
<File
RelativePath=".\ClassDefinitionTables.cpp">
</File>
@ -365,6 +368,12 @@
<File
RelativePath=".\AttachmentPosnSubtables.h">
</File>
<File
RelativePath=".\CanonShaping.h">
</File>
<File
RelativePath=".\CharSubstitutionFilter.h">
</File>
<File
RelativePath=".\ClassDefinitionTables.h">
</File>
@ -511,9 +520,41 @@
</File>
<File
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
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
RelativePath=".\LELanguages.h">