diff options
Diffstat (limited to 'Build/source/libs/icu/icu-xetex/layout/LEGlyphStorage.cpp')
-rw-r--r-- | Build/source/libs/icu/icu-xetex/layout/LEGlyphStorage.cpp | 649 |
1 files changed, 649 insertions, 0 deletions
diff --git a/Build/source/libs/icu/icu-xetex/layout/LEGlyphStorage.cpp b/Build/source/libs/icu/icu-xetex/layout/LEGlyphStorage.cpp new file mode 100644 index 00000000000..1b595159a11 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/layout/LEGlyphStorage.cpp @@ -0,0 +1,649 @@ +/* + ********************************************************************** + * Copyright (C) 1998-2006, International Business Machines + * Corporation and others. All Rights Reserved. + ********************************************************************** + */ + +#include "LETypes.h" +#include "LEInsertionList.h" +#include "LEGlyphStorage.h" + +U_NAMESPACE_BEGIN + +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage) + +LEInsertionCallback::~LEInsertionCallback() +{ + // nothing to do... +} + +LEGlyphStorage::LEGlyphStorage() + : fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL), + fAuxData(NULL), fAuxParam(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0) +{ + // nothing else to do! +} + +LEGlyphStorage::~LEGlyphStorage() +{ + reset(); +} + +void LEGlyphStorage::reset() +{ + fGlyphCount = 0; + + if (fPositions != NULL) { + LE_DELETE_ARRAY(fPositions); + fPositions = NULL; + } + + if (fAuxData != NULL) { + LE_DELETE_ARRAY(fAuxData); + fAuxData = NULL; + } + + if (fAuxParam != NULL) { + LE_DELETE_ARRAY(fAuxParam); + fAuxParam = NULL; + } + + if (fInsertionList != NULL) { + delete fInsertionList; + fInsertionList = NULL; + } + + if (fCharIndices != NULL) { + LE_DELETE_ARRAY(fCharIndices); + fCharIndices = 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 (initialGlyphCount <= 0) { + success = LE_ILLEGAL_ARGUMENT_ERROR; + return; + } + + if (fGlyphs == NULL) { + fGlyphCount = initialGlyphCount; + fGlyphs = LE_NEW_ARRAY(LEGlyphID, fGlyphCount); + + if (fGlyphs == NULL) { + success = LE_MEMORY_ALLOCATION_ERROR; + return; + } + } + + 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; + } + + // Initialize the charIndices array + le_int32 i, count = fGlyphCount, dir = 1, out = 0; + + if (rightToLeft) { + out = fGlyphCount - 1; + dir = -1; + } + + for (i = 0; i < count; i += 1, out += dir) { + fCharIndices[out] = i; + } + } + + 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 (fPositions != NULL) { + success = LE_INTERNAL_ERROR; + return -1; + } + + fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1)); + + if (fPositions == NULL) { + success = LE_MEMORY_ALLOCATION_ERROR; + return -1; + } + + 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 (fAuxData != NULL || fAuxParam != NULL) { + success = LE_INTERNAL_ERROR; + return -1; + } + + fAuxData = LE_NEW_ARRAY(le_uint32, fGlyphCount); + fAuxParam = LE_NEW_ARRAY(void *, fGlyphCount); + + if (fAuxData == NULL || fAuxParam == NULL) { + success = LE_MEMORY_ALLOCATION_ERROR; + return -1; + } + + return fGlyphCount; +} + +void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const +{ + le_int32 i; + + if (LE_FAILURE(success)) { + return; + } + + if (charIndices == NULL) { + success = LE_ILLEGAL_ARGUMENT_ERROR; + return; + } + + if (fCharIndices == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + for (i = 0; i < fGlyphCount; i += 1) { + charIndices[i] = fCharIndices[i] + indexBase; + } +} + +void LEGlyphStorage::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + return; + } + + if (charIndices == NULL) { + success = LE_ILLEGAL_ARGUMENT_ERROR; + return; + } + + if (fCharIndices == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + LE_ARRAY_COPY(charIndices, fCharIndices, fGlyphCount); +} + +// Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits +void LEGlyphStorage::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const +{ + le_int32 i; + + if (LE_FAILURE(success)) { + return; + } + + if (glyphs == NULL) { + success = LE_ILLEGAL_ARGUMENT_ERROR; + return; + } + + if (fGlyphs == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + for (i = 0; i < fGlyphCount; i += 1) { + glyphs[i] = fGlyphs[i] | extraBits; + } +} + +void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + return; + } + + if (glyphs == NULL) { + success = LE_ILLEGAL_ARGUMENT_ERROR; + return; + } + + if (fGlyphs == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount); +} + +LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + 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; + } + + return fGlyphs[glyphIndex]; +} + +void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success) +{ + if (LE_FAILURE(success)) { + return; + } + + if (fGlyphs == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return; + } + + fGlyphs[glyphIndex] = glyphID; +} + +le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + 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; + } + + return fCharIndices[glyphIndex]; +} + +void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success) +{ + if (LE_FAILURE(success)) { + return; + } + + if (fCharIndices == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return; + } + + fCharIndices[glyphIndex] = charIndex; +} + +void LEGlyphStorage::getAuxData(le_uint32 auxData[], LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + return; + } + + if (auxData == NULL) { + success = LE_ILLEGAL_ARGUMENT_ERROR; + return; + } + + if (fAuxData == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount); +} + +le_uint32 LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + return 0; + } + + if (fAuxData == NULL) { + success = LE_NO_LAYOUT_ERROR; + return 0; + } + + if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return 0; + } + + return fAuxData[glyphIndex]; +} + +void *LEGlyphStorage::getAuxParam(le_int32 glyphIndex, LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + return NULL; + } + + if (fAuxParam == NULL) { + success = LE_NO_LAYOUT_ERROR; + return NULL; + } + + if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return NULL; + } + + return fAuxParam[glyphIndex]; +} + +void LEGlyphStorage::setAuxData(le_int32 glyphIndex, le_uint32 auxData, void *auxParam, LEErrorCode &success) +{ + if (LE_FAILURE(success)) { + return; + } + + if (fAuxData == NULL || fAuxParam == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return; + } + + fAuxData[glyphIndex] = auxData; + fAuxParam[glyphIndex] = auxParam; +} + +void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + return; + } + + if (positions == NULL) { + success = LE_ILLEGAL_ARGUMENT_ERROR; + return; + } + + if (fPositions == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + LE_ARRAY_COPY(positions, fPositions, fGlyphCount * 2 + 2); +} + +void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + return; + } + + if (glyphIndex < 0 || glyphIndex > fGlyphCount) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return; + } + + if (fPositions == NULL) { + success = LE_NO_LAYOUT_ERROR; + return; + } + + x = fPositions[glyphIndex * 2]; + y = fPositions[glyphIndex * 2 + 1]; +} + +void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success) +{ + 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; +} + +void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success) +{ + 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; +} + +void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from) +{ + if (fGlyphs != NULL) { + LE_DELETE_ARRAY(fGlyphs); + } + + fGlyphs = from.fGlyphs; + from.fGlyphs = NULL; + + if (fInsertionList != NULL) { + delete fInsertionList; + } + + fInsertionList = from.fInsertionList; + from.fInsertionList = NULL; +} + +void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from) +{ + if (fCharIndices != NULL) { + LE_DELETE_ARRAY(fCharIndices); + } + + fCharIndices = from.fCharIndices; + from.fCharIndices = NULL; +} + +void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from) +{ + if (fPositions != NULL) { + LE_DELETE_ARRAY(fPositions); + } + + fPositions = from.fPositions; + from.fPositions = NULL; +} + +void LEGlyphStorage::adoptAuxDataArrays(LEGlyphStorage &from) +{ + if (fAuxData != NULL) { + LE_DELETE_ARRAY(fAuxData); + } + + if (fAuxParam != NULL) { + LE_DELETE_ARRAY(fAuxParam); + } + + fAuxData = from.fAuxData; + from.fAuxData = NULL; + fAuxParam = from.fAuxParam; + from.fAuxParam = NULL; +} + +void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from) +{ + fGlyphCount = from.fGlyphCount; +} + +void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount) +{ + fGlyphCount = newGlyphCount; +} + +// FIXME: add error checking? +LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount) +{ + return fInsertionList->insert(atIndex, insertCount); +} + +le_int32 LEGlyphStorage::applyInsertions() +{ + le_int32 growAmount = fInsertionList->getGrowAmount(); + + if (growAmount == 0) { + return fGlyphCount; + } + + le_int32 newGlyphCount = fGlyphCount + growAmount; + + fGlyphs = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs, newGlyphCount); + fCharIndices = (le_int32 *) LE_GROW_ARRAY(fCharIndices, newGlyphCount); + + if (fAuxData != NULL) { + fAuxData = (le_uint32 *) LE_GROW_ARRAY(fAuxData, newGlyphCount); + } + + if (fAuxParam != NULL) { + fAuxParam = (void **) LE_GROW_ARRAY(fAuxParam, newGlyphCount); + } + + 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. + // 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; + } +#endif + + fInsertionList->applyInsertions(this); + + fInsertionList->reset(); + + 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. + // 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; + } +#endif + + if (fAuxData != NULL) { + le_int32 src = fSrcIndex, dest = fDestIndex; + + while (src > atPosition) { + fAuxData[dest--] = fAuxData[src--]; + } + + for (le_int32 i = count - 1; i >= 0; i -= 1) { + fAuxData[dest--] = fAuxData[atPosition]; + } + } + + if (fAuxParam != NULL) { + le_int32 src = fSrcIndex, dest = fDestIndex; + + while (src > atPosition) { + fAuxParam[dest--] = fAuxParam[src--]; + } + + for (le_int32 i = count - 1; i >= 0; i -= 1) { + fAuxParam[dest--] = fAuxParam[atPosition]; + } + } + + while (fSrcIndex > atPosition) { + fGlyphs[fDestIndex] = fGlyphs[fSrcIndex]; + fCharIndices[fDestIndex] = fCharIndices[fSrcIndex]; + + fDestIndex -= 1; + fSrcIndex -= 1; + } + + for (le_int32 i = count - 1; i >= 0; i -= 1) { + fGlyphs[fDestIndex] = newGlyphs[i]; + fCharIndices[fDestIndex] = fCharIndices[atPosition]; + + fDestIndex -= 1; + } + + // the source glyph we're pointing at + // just got replaced by the insertion + fSrcIndex -= 1; + + return FALSE; +} + +U_NAMESPACE_END + |