Bug 1157727 - Part 0: Preliminary cleanup, remove a bunch of #ifdef'd dead code from nsBidi.cpp. r=smontagu

This commit is contained in:
Jonathan Kew 2015-11-25 12:01:03 +00:00
Родитель e0e31b84fb
Коммит 65a70aed66
3 изменённых файлов: 28 добавлений и 1049 удалений

Просмотреть файл

@ -138,9 +138,6 @@ static Flags flagO[2]={ DIRPROP_FLAG(LRO), DIRPROP_FLAG(RLO) };
nsBidi::nsBidi()
{
Init();
mMayAllocateText=true;
mMayAllocateRuns=true;
}
nsBidi::~nsBidi()
@ -174,14 +171,11 @@ void nsBidi::Init()
mLevelsMemory=nullptr;
mRunsMemory=nullptr;
mIsolatesMemory=nullptr;
mMayAllocateText=false;
mMayAllocateRuns=false;
}
/*
* We are allowed to allocate memory if aMemory==nullptr or
* aMayAllocate==true for each array that we need.
* We are allowed to allocate memory if aMemory==nullptr
* for each array that we need.
* We also try to grow and shrink memory as needed if we
* allocate it.
*
@ -192,29 +186,22 @@ void nsBidi::Init()
* which we know we don't need any more;
* is this the best way to do this??
*/
bool nsBidi::GetMemory(void **aMemory, size_t *aSize, bool aMayAllocate, size_t aSizeNeeded)
bool nsBidi::GetMemory(void **aMemory, size_t *aSize, size_t aSizeNeeded)
{
/* check for existing memory */
if(*aMemory==nullptr) {
/* we need to allocate memory */
if(!aMayAllocate) {
return false;
*aMemory=malloc(aSizeNeeded);
if (*aMemory!=nullptr) {
*aSize=aSizeNeeded;
return true;
} else {
*aMemory=malloc(aSizeNeeded);
if (*aMemory!=nullptr) {
*aSize=aSizeNeeded;
return true;
} else {
*aSize=0;
return false;
}
*aSize=0;
return false;
}
} else {
/* there is some memory, is it enough or too much? */
if(aSizeNeeded>*aSize && !aMayAllocate) {
/* not enough memory, and we must not allocate */
return false;
} else if(aSizeNeeded!=*aSize && aMayAllocate) {
if(aSizeNeeded!=*aSize) {
/* we may try to grow or shrink */
void *memory=realloc(*aMemory, aSizeNeeded);
@ -248,7 +235,7 @@ void nsBidi::Free()
/* SetPara ------------------------------------------------------------ */
nsresult nsBidi::SetPara(const char16_t *aText, int32_t aLength,
nsBidiLevel aParaLevel, nsBidiLevel *aEmbeddingLevels)
nsBidiLevel aParaLevel)
{
nsBidiDirection direction;
@ -302,22 +289,12 @@ nsresult nsBidi::SetPara(const char16_t *aText, int32_t aLength,
return NS_ERROR_OUT_OF_MEMORY;
}
/* are explicit levels specified? */
if(aEmbeddingLevels==nullptr) {
/* no: determine explicit levels according to the (Xn) rules */\
if(GETLEVELSMEMORY(aLength)) {
mLevels=mLevelsMemory;
ResolveExplicitLevels(&direction);
} else {
return NS_ERROR_OUT_OF_MEMORY;
}
/* determine explicit levels according to the (Xn) rules */
if(GETLEVELSMEMORY(aLength)) {
mLevels=mLevelsMemory;
ResolveExplicitLevels(&direction);
} else {
/* set BN for all explicit codes, check that all levels are aParaLevel..NSBIDI_MAX_EXPLICIT_LEVEL */
mLevels=aEmbeddingLevels;
nsresult rv = CheckExplicitLevels(&direction);
if(NS_FAILED(rv)) {
return rv;
}
return NS_ERROR_OUT_OF_MEMORY;
}
/* allocate isolate memory */
@ -327,7 +304,7 @@ nsresult nsBidi::SetPara(const char16_t *aText, int32_t aLength,
if (mIsolateCount * sizeof(Isolate) <= mIsolatesSize) {
mIsolates = mIsolatesMemory;
} else {
if (GETINITIALISOLATESMEMORY(mIsolateCount)) {
if (GETISOLATESMEMORY(mIsolateCount)) {
mIsolates = mIsolatesMemory;
} else {
return NS_ERROR_OUT_OF_MEMORY;
@ -368,7 +345,7 @@ nsresult nsBidi::SetPara(const char16_t *aText, int32_t aLength,
* Examples for "insignificant" ones are empty embeddings
* LRE-PDF, LRE-RLE-PDF-PDF, etc.
*/
if(aEmbeddingLevels==nullptr && !(mFlags&DIRPROP_FLAG_MULTI_RUNS)) {
if(!(mFlags&DIRPROP_FLAG_MULTI_RUNS)) {
ResolveImplicitLevels(0, aLength,
GET_LR_FROM_LEVEL(mParaLevel),
GET_LR_FROM_LEVEL(mParaLevel));
@ -850,63 +827,6 @@ void nsBidi::ResolveExplicitLevels(nsBidiDirection *aDirection)
*aDirection = direction;
}
/*
* Use a pre-specified embedding levels array:
*
* Adjust the directional properties for overrides (->LEVEL_OVERRIDE),
* ignore all explicit codes (X9),
* and check all the preset levels.
*
* Recalculate the flags to have them reflect the real properties
* after taking the explicit embeddings into account.
*/
nsresult nsBidi::CheckExplicitLevels(nsBidiDirection *aDirection)
{
const DirProp *dirProps=mDirProps;
DirProp dirProp;
nsBidiLevel *levels=mLevels;
int32_t isolateCount = 0;
int32_t i, length=mLength;
Flags flags=0; /* collect all directionalities in the text */
nsBidiLevel level, paraLevel=mParaLevel;
mIsolateCount = 0;
for(i=0; i<length; ++i) {
level=levels[i];
dirProp = dirProps[i];
if (dirProp == LRI || dirProp == RLI) {
isolateCount++;
if (isolateCount > mIsolateCount) {
mIsolateCount = isolateCount;
}
} else if (dirProp == PDI) {
isolateCount--;
}
if(level&NSBIDI_LEVEL_OVERRIDE) {
/* keep the override flag in levels[i] but adjust the flags */
level&=~NSBIDI_LEVEL_OVERRIDE; /* make the range check below simpler */
flags|=DIRPROP_FLAG_O(level);
} else {
/* set the flags */
flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG(dirProp);
}
if(level<paraLevel || NSBIDI_MAX_EXPLICIT_LEVEL<level) {
/* level out of bounds */
*aDirection = NSBIDI_LTR;
return NS_ERROR_INVALID_ARG;
}
}
if(flags&MASK_EMBEDDING) {
flags|=DIRPROP_FLAG_LR(mParaLevel);
}
/* determine if the text is mixed-directional or single-directional */
mFlags=flags;
*aDirection = DirectionFromFlags(flags);
return NS_OK;
}
/* determine if the text is mixed-directional or single-directional */
nsBidiDirection nsBidi::DirectionFromFlags(Flags aFlags)
{
@ -1334,252 +1254,6 @@ nsresult nsBidi::GetParaLevel(nsBidiLevel* aParaLevel)
*aParaLevel = mParaLevel;
return NS_OK;
}
#ifdef FULL_BIDI_ENGINE
/* -------------------------------------------------------------------------- */
nsresult nsBidi::GetLength(int32_t* aLength)
{
*aLength = mLength;
return NS_OK;
}
/*
* General remarks about the functions in this section:
*
* These functions deal with the aspects of potentially mixed-directional
* text in a single paragraph or in a line of a single paragraph
* which has already been processed according to
* the Unicode 6.3 Bidi algorithm as defined in
* http://www.unicode.org/unicode/reports/tr9/ , version 28,
* also described in The Unicode Standard, Version 6.3.0 .
*
* This means that there is a nsBidi object with a levels
* and a dirProps array.
* paraLevel and direction are also set.
* Only if the length of the text is zero, then levels==dirProps==nullptr.
*
* The overall directionality of the paragraph
* or line is used to bypass the reordering steps if possible.
* Even purely RTL text does not need reordering there because
* the getLogical/VisualIndex() functions can compute the
* index on the fly in such a case.
*
* The implementation of the access to same-level-runs and of the reordering
* do attempt to provide better performance and less memory usage compared to
* a direct implementation of especially rule (L2) with an array of
* one (32-bit) integer per text character.
*
* Here, the levels array is scanned as soon as necessary, and a vector of
* same-level-runs is created. Reordering then is done on this vector.
* For each run of text positions that were resolved to the same level,
* only 8 bytes are stored: the first text position of the run and the visual
* position behind the run after reordering.
* One sign bit is used to hold the directionality of the run.
* This is inefficient if there are many very short runs. If the average run
* length is <2, then this uses more memory.
*
* In a further attempt to save memory, the levels array is never changed
* after all the resolution rules (Xn, Wn, Nn, In).
* Many functions have to consider the field trailingWSStart:
* if it is less than length, then there is an implicit trailing run
* at the paraLevel,
* which is not reflected in the levels array.
* This allows a line nsBidi object to use the same levels array as
* its paragraph parent object.
*
* When a nsBidi object is created for a line of a paragraph, then the
* paragraph's levels and dirProps arrays are reused by way of setting
* a pointer into them, not by copying. This again saves memory and forbids to
* change the now shared levels for (L1).
*/
nsresult nsBidi::SetLine(const nsBidi* aParaBidi, int32_t aStart, int32_t aLimit)
{
nsBidi* pParent = (nsBidi*)aParaBidi;
int32_t length;
/* check the argument values */
if(pParent==nullptr) {
return NS_ERROR_INVALID_POINTER;
} else if(aStart < 0 || aStart >= aLimit || aLimit > pParent->mLength) {
return NS_ERROR_INVALID_ARG;
}
/* set members from our aParaBidi parent */
length = mLength = aLimit - aStart;
mParaLevel=pParent->mParaLevel;
mRuns=nullptr;
mFlags=0;
mDirProps=pParent->mDirProps+aStart;
mLevels=pParent->mLevels+aStart;
mRunCount=-1;
if(pParent->mDirection!=NSBIDI_MIXED) {
/* the parent is already trivial */
mDirection=pParent->mDirection;
/*
* The parent's levels are all either
* implicitly or explicitly ==paraLevel;
* do the same here.
*/
if(pParent->mTrailingWSStart<=aStart) {
mTrailingWSStart=0;
} else if(pParent->mTrailingWSStart<aLimit) {
mTrailingWSStart=pParent->mTrailingWSStart-aStart;
} else {
mTrailingWSStart=length;
}
} else {
const nsBidiLevel *levels=mLevels;
int32_t i, trailingWSStart;
nsBidiLevel level;
SetTrailingWSStart();
trailingWSStart=mTrailingWSStart;
/* recalculate pLineBidi->direction */
if(trailingWSStart==0) {
/* all levels are at paraLevel */
mDirection=(nsBidiDirection)(mParaLevel&1);
} else {
/* get the level of the first character */
level=levels[0]&1;
/* if there is anything of a different level, then the line is mixed */
if(trailingWSStart<length && (mParaLevel&1)!=level) {
/* the trailing WS is at paraLevel, which differs from levels[0] */
mDirection=NSBIDI_MIXED;
} else {
/* see if levels[1..trailingWSStart-1] have the same direction as levels[0] and paraLevel */
i=1;
for(;;) {
if(i==trailingWSStart) {
/* the direction values match those in level */
mDirection=(nsBidiDirection)level;
break;
} else if((levels[i]&1)!=level) {
mDirection=NSBIDI_MIXED;
break;
}
++i;
}
}
}
switch(mDirection) {
case NSBIDI_LTR:
/* make sure paraLevel is even */
mParaLevel=(mParaLevel+1)&~1;
/* all levels are implicitly at paraLevel (important for GetLevels()) */
mTrailingWSStart=0;
break;
case NSBIDI_RTL:
/* make sure paraLevel is odd */
mParaLevel|=1;
/* all levels are implicitly at paraLevel (important for GetLevels()) */
mTrailingWSStart=0;
break;
default:
break;
}
}
return NS_OK;
}
/* handle trailing WS (L1) -------------------------------------------------- */
/*
* SetTrailingWSStart() sets the start index for a trailing
* run of WS in the line. This is necessary because we do not modify
* the paragraph's levels array that we just point into.
* Using trailingWSStart is another form of performing (L1).
*
* To make subsequent operations easier, we also include the run
* before the WS if it is at the paraLevel - we merge the two here.
*/
void nsBidi::SetTrailingWSStart() {
/* mDirection!=NSBIDI_MIXED */
const DirProp *dirProps=mDirProps;
nsBidiLevel *levels=mLevels;
int32_t start=mLength;
nsBidiLevel paraLevel=mParaLevel;
/* go backwards across all WS, BN, explicit codes */
while(start>0 && DIRPROP_FLAG(dirProps[start-1])&MASK_WS) {
--start;
}
/* if the WS run can be merged with the previous run then do so here */
while(start>0 && levels[start-1]==paraLevel) {
--start;
}
mTrailingWSStart=start;
}
nsresult nsBidi::GetLevelAt(int32_t aCharIndex, nsBidiLevel* aLevel)
{
/* return paraLevel if in the trailing WS run, otherwise the real level */
if(aCharIndex<0 || mLength<=aCharIndex) {
*aLevel = 0;
} else if(mDirection!=NSBIDI_MIXED || aCharIndex>=mTrailingWSStart) {
*aLevel = mParaLevel;
} else {
*aLevel = mLevels[aCharIndex];
}
return NS_OK;
}
nsresult nsBidi::GetLevels(nsBidiLevel** aLevels)
{
int32_t start, length;
length = mLength;
if(length<=0) {
*aLevels = nullptr;
return NS_ERROR_INVALID_ARG;
}
start = mTrailingWSStart;
if(start==length) {
/* the current levels array reflects the WS run */
*aLevels = mLevels;
return NS_OK;
}
/*
* After the previous if(), we know that the levels array
* has an implicit trailing WS run and therefore does not fully
* reflect itself all the levels.
* This must be a nsBidi object for a line, and
* we need to create a new levels array.
*/
if(GETLEVELSMEMORY(length)) {
nsBidiLevel *levels=mLevelsMemory;
if(start>0 && levels!=mLevels) {
memcpy(levels, mLevels, start);
}
memset(levels+start, mParaLevel, length-start);
/* this new levels array is set for the line and reflects the WS run */
mTrailingWSStart=length;
*aLevels=mLevels=levels;
return NS_OK;
} else {
/* out of memory */
*aLevels = nullptr;
return NS_ERROR_OUT_OF_MEMORY;
}
}
#endif // FULL_BIDI_ENGINE
nsresult nsBidi::GetCharTypeAt(int32_t aCharIndex, nsCharType* pType)
{
@ -2038,454 +1712,3 @@ bool nsBidi::PrepareReorder(const nsBidiLevel *aLevels, int32_t aLength,
return true;
}
#ifdef FULL_BIDI_ENGINE
/* API functions for logical<->visual mapping ------------------------------- */
nsresult nsBidi::GetVisualIndex(int32_t aLogicalIndex, int32_t* aVisualIndex) {
int32_t visualIndex = NSBIDI_MAP_NOWHERE;
if(aLogicalIndex<0 || mLength<=aLogicalIndex) {
return NS_ERROR_INVALID_ARG;
} else {
/* we can do the trivial cases without the runs array */
switch(mDirection) {
case NSBIDI_LTR:
*aVisualIndex = aLogicalIndex;
return NS_OK;
case NSBIDI_RTL:
*aVisualIndex = mLength-aLogicalIndex-1;
return NS_OK;
default:
if(mRunCount<0 && !GetRuns()) {
return NS_ERROR_OUT_OF_MEMORY;
} else {
Run *runs=mRuns;
int32_t i, visualStart=0, offset, length;
/* linear search for the run, search on the visual runs */
for (i = 0; i < mRunCount; ++i) {
length=runs[i].visualLimit-visualStart;
offset=aLogicalIndex-GET_INDEX(runs[i].logicalStart);
if(offset>=0 && offset<length) {
if(IS_EVEN_RUN(runs[i].logicalStart)) {
/* LTR */
visualIndex = visualStart + offset;
} else {
/* RTL */
visualIndex = visualStart + length - offset - 1;
}
break;
}
visualStart+=length;
}
if (i >= mRunCount) {
*aVisualIndex = NSBIDI_MAP_NOWHERE;
return NS_OK;
}
}
}
}
*aVisualIndex = visualIndex;
return NS_OK;
}
nsresult nsBidi::GetLogicalIndex(int32_t aVisualIndex, int32_t *aLogicalIndex)
{
if(aVisualIndex<0 || mLength<=aVisualIndex) {
return NS_ERROR_INVALID_ARG;
}
/* we can do the trivial cases without the runs array */
if (mDirection == NSBIDI_LTR) {
*aLogicalIndex = aVisualIndex;
return NS_OK;
} else if (mDirection == NSBIDI_RTL) {
*aLogicalIndex = mLength - aVisualIndex - 1;
return NS_OK;
}
if(mRunCount<0 && !GetRuns()) {
return NS_ERROR_OUT_OF_MEMORY;
}
Run *runs=mRuns;
int32_t i, runCount=mRunCount, start;
if(runCount<=10) {
/* linear search for the run */
for(i=0; aVisualIndex>=runs[i].visualLimit; ++i) {}
} else {
/* binary search for the run */
int32_t start=0, limit=runCount;
/* the middle if() will guaranteed find the run, we don't need a loop limit */
for(;;) {
i=(start+limit)/2;
if(aVisualIndex>=runs[i].visualLimit) {
start=i+1;
} else if(i==0 || aVisualIndex>=runs[i-1].visualLimit) {
break;
} else {
limit=i;
}
}
}
start=runs[i].logicalStart;
if(IS_EVEN_RUN(start)) {
/* LTR */
/* the offset in runs[i] is aVisualIndex-runs[i-1].visualLimit */
if(i>0) {
aVisualIndex-=runs[i-1].visualLimit;
}
*aLogicalIndex = GET_INDEX(start)+aVisualIndex;
return NS_OK;
} else {
/* RTL */
*aLogicalIndex = GET_INDEX(start)+runs[i].visualLimit-aVisualIndex-1;
return NS_OK;
}
}
nsresult nsBidi::GetLogicalMap(int32_t *aIndexMap)
{
nsresult rv;
/* CountRuns() checks for VALID_PARA_OR_LINE */
rv = CountRuns(nullptr);
if(NS_FAILED(rv)) {
return rv;
} else if(aIndexMap==nullptr) {
return NS_ERROR_INVALID_ARG;
} else {
/* fill a logical-to-visual index map using the runs[] */
int32_t visualStart, visualLimit, j;
int32_t logicalStart;
Run *runs = mRuns;
if (mLength <= 0) {
return NS_OK;
}
visualStart = 0;
for (j = 0; j < mRunCount; ++j) {
logicalStart = GET_INDEX(runs[j].logicalStart);
visualLimit = runs[j].visualLimit;
if (IS_EVEN_RUN(runs[j].logicalStart)) {
do { /* LTR */
aIndexMap[logicalStart++] = visualStart++;
} while (visualStart < visualLimit);
} else {
logicalStart += visualLimit-visualStart; /* logicalLimit */
do { /* RTL */
aIndexMap[--logicalStart] = visualStart++;
} while (visualStart < visualLimit);
}
/* visualStart==visualLimit; */
}
}
return NS_OK;
}
nsresult nsBidi::GetVisualMap(int32_t *aIndexMap)
{
int32_t* runCount=nullptr;
nsresult rv;
if(aIndexMap==nullptr) {
return NS_ERROR_INVALID_ARG;
}
/* CountRuns() checks all of its and our arguments */
rv = CountRuns(runCount);
if(NS_FAILED(rv)) {
return rv;
} else {
/* fill a visual-to-logical index map using the runs[] */
Run *runs=mRuns, *runsLimit=runs+mRunCount;
int32_t logicalStart, visualStart, visualLimit;
visualStart=0;
for(; runs<runsLimit; ++runs) {
logicalStart=runs->logicalStart;
visualLimit=runs->visualLimit;
if(IS_EVEN_RUN(logicalStart)) {
do { /* LTR */
*aIndexMap++ = logicalStart++;
} while(++visualStart<visualLimit);
} else {
REMOVE_ODD_BIT(logicalStart);
logicalStart+=visualLimit-visualStart; /* logicalLimit */
do { /* RTL */
*aIndexMap++ = --logicalStart;
} while(++visualStart<visualLimit);
}
/* visualStart==visualLimit; */
}
return NS_OK;
}
}
/* reorder a line based on a levels array (L2) ------------------------------ */
nsresult nsBidi::ReorderLogical(const nsBidiLevel *aLevels, int32_t aLength, int32_t *aIndexMap)
{
int32_t start, limit, sumOfSosEos;
nsBidiLevel minLevel, maxLevel;
if(aIndexMap==nullptr ||
!PrepareReorder(aLevels, aLength, aIndexMap, &minLevel, &maxLevel)) {
return NS_OK;
}
/* nothing to do? */
if(minLevel==maxLevel && (minLevel&1)==0) {
return NS_OK;
}
/* reorder only down to the lowest odd level */
minLevel|=1;
/* loop maxLevel..minLevel */
do {
start=0;
/* loop for all sequences of levels to reorder at the current maxLevel */
for(;;) {
/* look for a sequence of levels that are all at >=maxLevel */
/* look for the first index of such a sequence */
while(start<aLength && aLevels[start]<maxLevel) {
++start;
}
if(start>=aLength) {
break; /* no more such sequences */
}
/* look for the limit of such a sequence (the index behind it) */
for(limit=start; ++limit<aLength && aLevels[limit]>=maxLevel;) {}
/*
* sos=start of sequence, eos=end of sequence
*
* The closed (inclusive) interval from sos to eos includes all the logical
* and visual indexes within this sequence. They are logically and
* visually contiguous and in the same range.
*
* For each run, the new visual index=sos+eos-old visual index;
* we pre-add sos+eos into sumOfSosEos ->
* new visual index=sumOfSosEos-old visual index;
*/
sumOfSosEos=start+limit-1;
/* reorder each index in the sequence */
do {
aIndexMap[start]=sumOfSosEos-aIndexMap[start];
} while(++start<limit);
/* start==limit */
if(limit==aLength) {
break; /* no more such sequences */
} else {
start=limit+1;
}
}
} while(--maxLevel>=minLevel);
return NS_OK;
}
nsresult nsBidi::InvertMap(const int32_t *aSrcMap, int32_t *aDestMap, int32_t aLength)
{
if(aSrcMap!=nullptr && aDestMap!=nullptr && aLength > 0) {
const int32_t *pi;
int32_t destLength = -1, count = 0;
/* find highest value and count positive indexes in srcMap */
pi = aSrcMap + aLength;
while (pi > aSrcMap) {
if (*--pi > destLength) {
destLength = *pi;
}
if (*pi >= 0) {
count++;
}
}
destLength++; /* add 1 for origin 0 */
if (count < destLength) {
/* we must fill unmatched destMap entries with -1 */
memset(aDestMap, 0xFF, destLength * sizeof(int32_t));
}
pi = aSrcMap + aLength;
while (aLength > 0) {
if (*--pi >= 0) {
aDestMap[*pi] = --aLength;
} else {
--aLength;
}
}
}
return NS_OK;
}
int32_t nsBidi::doWriteReverse(const char16_t *src, int32_t srcLength,
char16_t *dest, uint16_t options) {
/*
* RTL run -
*
* RTL runs need to be copied to the destination in reverse order
* of code points, not code units, to keep Unicode characters intact.
*
* The general strategy for this is to read the source text
* in backward order, collect all code units for a code point
* (and optionally following combining characters, see below),
* and copy all these code units in ascending order
* to the destination for this run.
*
* Several options request whether combining characters
* should be kept after their base characters,
* whether Bidi control characters should be removed, and
* whether characters should be replaced by their mirror-image
* equivalent Unicode characters.
*/
int32_t i, j, destSize;
uint32_t c;
/* optimize for several combinations of options */
switch(options&(NSBIDI_REMOVE_BIDI_CONTROLS|NSBIDI_DO_MIRRORING|NSBIDI_KEEP_BASE_COMBINING)) {
case 0:
/*
* With none of the "complicated" options set, the destination
* run will have the same length as the source run,
* and there is no mirroring and no keeping combining characters
* with their base characters.
*/
destSize=srcLength;
/* preserve character integrity */
do {
/* i is always after the last code unit known to need to be kept in this segment */
i=srcLength;
/* collect code units for one base character */
UTF_BACK_1(src, 0, srcLength);
/* copy this base character */
j=srcLength;
do {
*dest++=src[j++];
} while(j<i);
} while(srcLength>0);
break;
case NSBIDI_KEEP_BASE_COMBINING:
/*
* Here, too, the destination
* run will have the same length as the source run,
* and there is no mirroring.
* We do need to keep combining characters with their base characters.
*/
destSize=srcLength;
/* preserve character integrity */
do {
/* i is always after the last code unit known to need to be kept in this segment */
i=srcLength;
/* collect code units and modifier letters for one base character */
do {
UTF_PREV_CHAR(src, 0, srcLength, c);
} while(srcLength>0 && GetBidiCat(c) == eCharType_DirNonSpacingMark);
/* copy this "user character" */
j=srcLength;
do {
*dest++=src[j++];
} while(j<i);
} while(srcLength>0);
break;
default:
/*
* With several "complicated" options set, this is the most
* general and the slowest copying of an RTL run.
* We will do mirroring, remove Bidi controls, and
* keep combining characters with their base characters
* as requested.
*/
if(!(options&NSBIDI_REMOVE_BIDI_CONTROLS)) {
i=srcLength;
} else {
/* we need to find out the destination length of the run,
which will not include the Bidi control characters */
int32_t length=srcLength;
char16_t ch;
i=0;
do {
ch=*src++;
if (!IsBidiControl((uint32_t)ch)) {
++i;
}
} while(--length>0);
src-=srcLength;
}
destSize=i;
/* preserve character integrity */
do {
/* i is always after the last code unit known to need to be kept in this segment */
i=srcLength;
/* collect code units for one base character */
UTF_PREV_CHAR(src, 0, srcLength, c);
if(options&NSBIDI_KEEP_BASE_COMBINING) {
/* collect modifier letters for this base character */
while(srcLength>0 && GetBidiCat(c) == eCharType_DirNonSpacingMark) {
UTF_PREV_CHAR(src, 0, srcLength, c);
}
}
if(options&NSBIDI_REMOVE_BIDI_CONTROLS && IsBidiControl(c)) {
/* do not copy this Bidi control character */
continue;
}
/* copy this "user character" */
j=srcLength;
if(options&NSBIDI_DO_MIRRORING) {
/* mirror only the base character */
c = GetMirroredChar(c);
int32_t k=0;
UTF_APPEND_CHAR_UNSAFE(dest, k, c);
dest+=k;
j+=k;
}
while(j<i) {
*dest++=src[j++];
}
} while(srcLength>0);
break;
} /* end of switch */
return destSize;
}
nsresult nsBidi::WriteReverse(const char16_t *aSrc, int32_t aSrcLength, char16_t *aDest, uint16_t aOptions, int32_t *aDestSize)
{
if( aSrc==nullptr || aSrcLength<0 ||
aDest==nullptr
) {
return NS_ERROR_INVALID_ARG;
}
/* do input and output overlap? */
if( aSrc>=aDest && aSrc<aDest+aSrcLength ||
aDest>=aSrc && aDest<aSrc+aSrcLength
) {
return NS_ERROR_INVALID_ARG;
}
if(aSrcLength>0) {
*aDestSize = doWriteReverse(aSrc, aSrcLength, aDest, aOptions);
}
return NS_OK;
}
#endif // FULL_BIDI_ENGINE

Просмотреть файл

@ -49,14 +49,6 @@
* It holds an embedding level and indicates the visual direction
* by its bit 0 (even/odd value).<p>
*
* It can also hold non-level values for the
* <code>aParaLevel</code> and <code>aEmbeddingLevels</code>
* arguments of <code>SetPara</code>; there:
* <ul>
* <li>bit 7 of an <code>aEmbeddingLevels[]</code>
* value indicates whether the using application is
* specifying the level of a character to <i>override</i> whatever the
* Bidi implementation would resolve it to.</li>
* <li><code>aParaLevel</code> can be set to the
* pseudo-level values <code>NSBIDI_DEFAULT_LTR</code>
* and <code>NSBIDI_DEFAULT_RTL</code>.</li></ul>
@ -130,61 +122,23 @@ enum nsBidiDirection {
typedef enum nsBidiDirection nsBidiDirection;
/* miscellaneous definitions ------------------------------------------------ */
/** option flags for WriteReverse() */
/**
* option bit for WriteReverse():
* keep combining characters after their base characters in RTL runs
*
* @see WriteReverse
*/
#define NSBIDI_KEEP_BASE_COMBINING 1
/**
* option bit for WriteReverse():
* replace characters with the "mirrored" property in RTL runs
* by their mirror-image mappings
*
* @see WriteReverse
*/
#define NSBIDI_DO_MIRRORING 2
/**
* option bit for WriteReverse():
* remove Bidi control characters
*
* @see WriteReverse
*/
#define NSBIDI_REMOVE_BIDI_CONTROLS 8
/* helper macros for each allocated array member */
#define GETDIRPROPSMEMORY(length) \
GetMemory((void **)&mDirPropsMemory, &mDirPropsSize, \
mMayAllocateText, (length))
(length))
#define GETLEVELSMEMORY(length) \
GetMemory((void **)&mLevelsMemory, &mLevelsSize, \
mMayAllocateText, (length))
(length))
#define GETRUNSMEMORY(length) \
GetMemory((void **)&mRunsMemory, &mRunsSize, \
mMayAllocateRuns, (length)*sizeof(Run))
(length)*sizeof(Run))
/* additional macros used by constructor - always allow allocation */
#define GETINITIALDIRPROPSMEMORY(length) \
GetMemory((void **)&mDirPropsMemory, &mDirPropsSize, \
true, (length))
#define GETINITIALLEVELSMEMORY(length) \
GetMemory((void **)&mLevelsMemory, &mLevelsSize, \
true, (length))
#define GETINITIALRUNSMEMORY(length) \
GetMemory((void **)&mRunsMemory, &mRunsSize, \
true, (length)*sizeof(Run))
#define GETINITIALISOLATESMEMORY(length) \
GetMemory((void **)&mIsolatesMemory, &mIsolatesSize, \
true, (length)*sizeof(Isolate))
#define GETISOLATESMEMORY(length) \
GetMemory((void **)&mIsolatesMemory, &mIsolatesSize, \
(length)*sizeof(Isolate))
/*
* Sometimes, bit values are more appropriate
@ -505,28 +459,8 @@ public:
* the desired default is used (0 for LTR or 1 for RTL).
* Any other value between 0 and <code>NSBIDI_MAX_EXPLICIT_LEVEL</code> is also valid,
* with odd levels indicating RTL.
*
* @param aEmbeddingLevels (in) may be used to preset the embedding and override levels,
* ignoring characters like LRE and PDF in the text.
* A level overrides the directional property of its corresponding
* (same index) character if the level has the
* <code>NSBIDI_LEVEL_OVERRIDE</code> bit set.<p>
* Except for that bit, it must be
* <code>aParaLevel<=aEmbeddingLevels[]<=NSBIDI_MAX_EXPLICIT_LEVEL</code>.<p>
* <strong>Caution: </strong>A copy of this pointer, not of the levels,
* will be stored in the <code>nsBidi</code> object;
* the <code>aEmbeddingLevels</code> array must not be
* deallocated before the <code>nsBidi</code> object is destroyed or reused,
* and the <code>aEmbeddingLevels</code>
* should not be modified to avoid unexpected results on subsequent Bidi operations.
* However, the <code>SetPara</code> and
* <code>SetLine</code> functions may modify some or all of the levels.<p>
* After the <code>nsBidi</code> object is reused or destroyed, the caller
* must take care of the deallocation of the <code>aEmbeddingLevels</code> array.<p>
* <strong>The <code>aEmbeddingLevels</code> array must be
* at least <code>aLength</code> long.</strong>
*/
nsresult SetPara(const char16_t *aText, int32_t aLength, nsBidiLevel aParaLevel, nsBidiLevel *aEmbeddingLevels);
nsresult SetPara(const char16_t *aText, int32_t aLength, nsBidiLevel aParaLevel);
/**
* Get the directionality of the text.
@ -548,73 +482,6 @@ public:
*/
nsresult GetParaLevel(nsBidiLevel* aParaLevel);
#ifdef FULL_BIDI_ENGINE
/**
* <code>SetLine</code> sets an <code>nsBidi</code> to
* contain the reordering information, especially the resolved levels,
* for all the characters in a line of text. This line of text is
* specified by referring to an <code>nsBidi</code> object representing
* this information for a paragraph of text, and by specifying
* a range of indexes in this paragraph.<p>
* In the new line object, the indexes will range from 0 to <code>aLimit-aStart</code>.<p>
*
* This is used after calling <code>SetPara</code>
* for a paragraph, and after line-breaking on that paragraph.
* It is not necessary if the paragraph is treated as a single line.<p>
*
* After line-breaking, rules (L1) and (L2) for the treatment of
* trailing WS and for reordering are performed on
* an <code>nsBidi</code> object that represents a line.<p>
*
* <strong>Important:</strong> the line <code>nsBidi</code> object shares data with
* <code>aParaBidi</code>.
* You must destroy or reuse this object before <code>aParaBidi</code>.
* In other words, you must destroy or reuse the <code>nsBidi</code> object for a line
* before the object for its parent paragraph.
*
* @param aParaBidi is the parent paragraph object.
*
* @param aStart is the line's first index into the paragraph text.
*
* @param aLimit is just behind the line's last index into the paragraph text
* (its last index +1).<br>
* It must be <code>0<=aStart<=aLimit<=</code>paragraph length.
*
* @see SetPara
*/
nsresult SetLine(const nsBidi* aParaBidi, int32_t aStart, int32_t aLimit);
/**
* Get the length of the text.
*
* @param aLength receives the length of the text that the nsBidi object was created for.
*/
nsresult GetLength(int32_t* aLength);
/**
* Get the level for one character.
*
* @param aCharIndex the index of a character.
*
* @param aLevel receives the level for the character at aCharIndex.
*
* @see nsBidiLevel
*/
nsresult GetLevelAt(int32_t aCharIndex, nsBidiLevel* aLevel);
/**
* Get an array of levels for each character.<p>
*
* Note that this function may allocate memory under some
* circumstances, unlike <code>GetLevelAt</code>.
*
* @param aLevels receives a pointer to the levels array for the text,
* or <code>nullptr</code> if an error occurs.
*
* @see nsBidiLevel
*/
nsresult GetLevels(nsBidiLevel** aLevels);
#endif // FULL_BIDI_ENGINE
/**
* Get the bidirectional type for one character.
*
@ -707,92 +574,6 @@ public:
*/
nsresult GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart, int32_t* aLength, nsBidiDirection* aDirection);
#ifdef FULL_BIDI_ENGINE
/**
* Get the visual position from a logical text position.
* If such a mapping is used many times on the same
* <code>nsBidi</code> object, then calling
* <code>GetLogicalMap</code> is more efficient.<p>
*
* Note that in right-to-left runs, this mapping places
* modifier letters before base characters and second surrogates
* before first ones.
*
* @param aLogicalIndex is the index of a character in the text.
*
* @param aVisualIndex will receive the visual position of this character.
*
* @see GetLogicalMap
* @see GetLogicalIndex
*/
nsresult GetVisualIndex(int32_t aLogicalIndex, int32_t* aVisualIndex);
/**
* Get the logical text position from a visual position.
* If such a mapping is used many times on the same
* <code>nsBidi</code> object, then calling
* <code>GetVisualMap</code> is more efficient.<p>
*
* This is the inverse function to <code>GetVisualIndex</code>.
*
* @param aVisualIndex is the visual position of a character.
*
* @param aLogicalIndex will receive the index of this character in the text.
*
* @see GetVisualMap
* @see GetVisualIndex
*/
nsresult GetLogicalIndex(int32_t aVisualIndex, int32_t* aLogicalIndex);
/**
* Get a logical-to-visual index map (array) for the characters in the nsBidi
* (paragraph or line) object.
*
* @param aIndexMap is a pointer to an array of <code>GetLength</code>
* indexes which will reflect the reordering of the characters.
* The array does not need to be initialized.<p>
* The index map will result in <code>aIndexMap[aLogicalIndex]==aVisualIndex</code>.<p>
*
* @see GetVisualMap
* @see GetVisualIndex
*/
nsresult GetLogicalMap(int32_t *aIndexMap);
/**
* Get a visual-to-logical index map (array) for the characters in the nsBidi
* (paragraph or line) object.
*
* @param aIndexMap is a pointer to an array of <code>GetLength</code>
* indexes which will reflect the reordering of the characters.
* The array does not need to be initialized.<p>
* The index map will result in <code>aIndexMap[aVisualIndex]==aLogicalIndex</code>.<p>
*
* @see GetLogicalMap
* @see GetLogicalIndex
*/
nsresult GetVisualMap(int32_t *aIndexMap);
/**
* This is a convenience function that does not use a nsBidi object.
* It is intended to be used for when an application has determined the levels
* of objects (character sequences) and just needs to have them reordered (L2).
* This is equivalent to using <code>GetLogicalMap</code> on a
* <code>nsBidi</code> object.
*
* @param aLevels is an array with <code>aLength</code> levels that have been determined by
* the application.
*
* @param aLength is the number of levels in the array, or, semantically,
* the number of objects to be reordered.
* It must be <code>aLength>0</code>.
*
* @param aIndexMap is a pointer to an array of <code>aLength</code>
* indexes which will reflect the reordering of the characters.
* The array does not need to be initialized.<p>
* The index map will result in <code>aIndexMap[aLogicalIndex]==aVisualIndex</code>.
*/
static nsresult ReorderLogical(const nsBidiLevel *aLevels, int32_t aLength, int32_t *aIndexMap);
#endif // FULL_BIDI_ENGINE
/**
* This is a convenience function that does not use a nsBidi object.
* It is intended to be used for when an application has determined the levels
@ -814,22 +595,6 @@ public:
*/
static nsresult ReorderVisual(const nsBidiLevel *aLevels, int32_t aLength, int32_t *aIndexMap);
#ifdef FULL_BIDI_ENGINE
/**
* Invert an index map.
* The one-to-one index mapping of the first map is inverted and written to
* the second one.
*
* @param aSrcMap is an array with <code>aLength</code> indexes
* which define the original mapping.
*
* @param aDestMap is an array with <code>aLength</code> indexes
* which will be filled with the inverse mapping.
*
* @param aLength is the length of each array.
*/
nsresult InvertMap(const int32_t *aSrcMap, int32_t *aDestMap, int32_t aLength);
#endif // FULL_BIDI_ENGINE
/**
* Reverse a Right-To-Left run of Unicode text.
*
@ -883,9 +648,6 @@ protected:
Run* mRunsMemory;
Isolate* mIsolatesMemory;
/** indicators for whether memory may be allocated after construction */
bool mMayAllocateText, mMayAllocateRuns;
DirProp* mDirProps;
nsBidiLevel* mLevels;
@ -924,7 +686,7 @@ private:
void Init();
bool GetMemory(void **aMemory, size_t* aSize, bool aMayAllocate, size_t aSizeNeeded);
bool GetMemory(void **aMemory, size_t* aSize, size_t aSizeNeeded);
void Free();
@ -932,8 +694,6 @@ private:
void ResolveExplicitLevels(nsBidiDirection *aDirection);
nsresult CheckExplicitLevels(nsBidiDirection *aDirection);
nsBidiDirection DirectionFromFlags(Flags aFlags);
void ProcessPropertySeq(LevState *pLevState, uint8_t _prop, int32_t start, int32_t limit);
@ -951,10 +711,6 @@ private:
void ReorderLine(nsBidiLevel aMinLevel, nsBidiLevel aMaxLevel);
static bool PrepareReorder(const nsBidiLevel *aLevels, int32_t aLength, int32_t *aIndexMap, nsBidiLevel *aMinLevel, nsBidiLevel *aMaxLevel);
int32_t doWriteReverse(const char16_t *src, int32_t srcLength,
char16_t *dest, uint16_t options);
};
#endif // _nsBidi_h_

Просмотреть файл

@ -208,7 +208,7 @@ struct BidiParagraphData {
nsresult SetPara()
{
return mBidiEngine->SetPara(mBuffer.get(), BufferLength(),
mParaLevel, nullptr);
mParaLevel);
}
/**
@ -2012,7 +2012,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText,
nsAutoString textBuffer(aText, aLength);
nsresult rv = aBidiEngine->SetPara(aText, aLength, aBaseLevel, nullptr);
nsresult rv = aBidiEngine->SetPara(aText, aLength, aBaseLevel);
if (NS_FAILED(rv))
return rv;