ICU-3181 No real code changes. Shuffle code around to allow the compiler to inline functions more easily

X-SVN-Rev: 12874
This commit is contained in:
George Rhoten 2003-08-19 20:56:31 +00:00
parent cd057e3c4f
commit 01a5ebcb3d
2 changed files with 399 additions and 440 deletions

View file

@ -107,28 +107,6 @@
* (L1) is not necessary in adjustWSLevels().
*/
/* prototypes --------------------------------------------------------------- */
static void
getDirProps(UBiDi *pBiDi, const UChar *text);
static UBiDiDirection
resolveExplicitLevels(UBiDi *pBiDi);
static UBiDiDirection
checkExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode);
static UBiDiDirection
directionFromFlags(Flags flags);
static void
resolveImplicitLevels(UBiDi *pBiDi,
int32_t start, int32_t limit,
DirProp sor, DirProp eor);
static void
adjustWSLevels(UBiDi *pBiDi);
/* to avoid some conditional statements, use tiny constant arrays */
static const Flags flagLR[2]={ DIRPROP_FLAG(L), DIRPROP_FLAG(R) };
static const Flags flagE[2]={ DIRPROP_FLAG(LRE), DIRPROP_FLAG(RLE) };
@ -281,199 +259,6 @@ ubidi_isInverse(UBiDi *pBiDi) {
}
}
/* ubidi_setPara ------------------------------------------------------------ */
U_CAPI void U_EXPORT2
ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels,
UErrorCode *pErrorCode) {
UBiDiDirection direction;
/* check the argument values */
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
return;
} else if(pBiDi==NULL || text==NULL ||
((UBIDI_MAX_EXPLICIT_LEVEL<paraLevel) && !IS_DEFAULT_LEVEL(paraLevel)) ||
length<-1
) {
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
return;
}
if(length==-1) {
length=u_strlen(text);
}
/* initialize the UBiDi structure */
pBiDi->text=text;
pBiDi->length=length;
pBiDi->paraLevel=paraLevel;
pBiDi->direction=UBIDI_LTR;
pBiDi->trailingWSStart=length; /* the levels[] will reflect the WS run */
pBiDi->dirProps=NULL;
pBiDi->levels=NULL;
pBiDi->runs=NULL;
if(length==0) {
/*
* For an empty paragraph, create a UBiDi object with the paraLevel and
* the flags and the direction set but without allocating zero-length arrays.
* There is nothing more to do.
*/
if(IS_DEFAULT_LEVEL(paraLevel)) {
pBiDi->paraLevel&=1;
}
if(paraLevel&1) {
pBiDi->flags=DIRPROP_FLAG(R);
pBiDi->direction=UBIDI_RTL;
} else {
pBiDi->flags=DIRPROP_FLAG(L);
pBiDi->direction=UBIDI_LTR;
}
pBiDi->runCount=0;
return;
}
pBiDi->runCount=-1;
/*
* Get the directional properties,
* the flags bit-set, and
* determine the partagraph level if necessary.
*/
if(getDirPropsMemory(pBiDi, length)) {
pBiDi->dirProps=pBiDi->dirPropsMemory;
getDirProps(pBiDi, text);
} else {
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
return;
}
/* are explicit levels specified? */
if(embeddingLevels==NULL) {
/* no: determine explicit levels according to the (Xn) rules */\
if(getLevelsMemory(pBiDi, length)) {
pBiDi->levels=pBiDi->levelsMemory;
direction=resolveExplicitLevels(pBiDi);
} else {
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
return;
}
} else {
/* set BN for all explicit codes, check that all levels are paraLevel..UBIDI_MAX_EXPLICIT_LEVEL */
pBiDi->levels=embeddingLevels;
direction=checkExplicitLevels(pBiDi, pErrorCode);
if(U_FAILURE(*pErrorCode)) {
return;
}
}
/*
* The steps after (X9) in the UBiDi algorithm are performed only if
* the paragraph text has mixed directionality!
*/
pBiDi->direction=direction;
switch(direction) {
case UBIDI_LTR:
/* make sure paraLevel is even */
pBiDi->paraLevel=(UBiDiLevel)((pBiDi->paraLevel+1)&~1);
/* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
pBiDi->trailingWSStart=0;
break;
case UBIDI_RTL:
/* make sure paraLevel is odd */
pBiDi->paraLevel|=1;
/* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
pBiDi->trailingWSStart=0;
break;
default:
/*
* If there are no external levels specified and there
* are no significant explicit level codes in the text,
* then we can treat the entire paragraph as one run.
* Otherwise, we need to perform the following rules on runs of
* the text with the same embedding levels. (X10)
* "Significant" explicit level codes are ones that actually
* affect non-BN characters.
* Examples for "insignificant" ones are empty embeddings
* LRE-PDF, LRE-RLE-PDF-PDF, etc.
*/
if(embeddingLevels==NULL && !(pBiDi->flags&DIRPROP_FLAG_MULTI_RUNS)) {
resolveImplicitLevels(pBiDi, 0, length,
GET_LR_FROM_LEVEL(pBiDi->paraLevel),
GET_LR_FROM_LEVEL(pBiDi->paraLevel));
} else {
/* sor, eor: start and end types of same-level-run */
UBiDiLevel *levels=pBiDi->levels;
int32_t start, limit=0;
UBiDiLevel level, nextLevel;
DirProp sor, eor;
/* determine the first sor and set eor to it because of the loop body (sor=eor there) */
level=pBiDi->paraLevel;
nextLevel=levels[0];
if(level<nextLevel) {
eor=GET_LR_FROM_LEVEL(nextLevel);
} else {
eor=GET_LR_FROM_LEVEL(level);
}
do {
/* determine start and limit of the run (end points just behind the run) */
/* the values for this run's start are the same as for the previous run's end */
sor=eor;
start=limit;
level=nextLevel;
/* search for the limit of this run */
while(++limit<length && levels[limit]==level) {}
/* get the correct level of the next run */
if(limit<length) {
nextLevel=levels[limit];
} else {
nextLevel=pBiDi->paraLevel;
}
/* determine eor from max(level, nextLevel); sor is last run's eor */
if((level&~UBIDI_LEVEL_OVERRIDE)<(nextLevel&~UBIDI_LEVEL_OVERRIDE)) {
eor=GET_LR_FROM_LEVEL(nextLevel);
} else {
eor=GET_LR_FROM_LEVEL(level);
}
/* if the run consists of overridden directional types, then there
are no implicit types to be resolved */
if(!(level&UBIDI_LEVEL_OVERRIDE)) {
resolveImplicitLevels(pBiDi, start, limit, sor, eor);
} else {
/* remove the UBIDI_LEVEL_OVERRIDE flags */
do {
levels[start++]&=~UBIDI_LEVEL_OVERRIDE;
} while(start<limit);
}
} while(limit<length);
}
/* reset the embedding levels for some non-graphic characters (L1), (X9) */
adjustWSLevels(pBiDi);
/* for "inverse BiDi", ubidi_getRuns() modifies the levels of numeric runs following RTL runs */
if(pBiDi->isInverse) {
if(!ubidi_getRuns(pBiDi)) {
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
return;
}
}
break;
}
}
/* perform (P2)..(P3) ------------------------------------------------------- */
/*
@ -544,6 +329,19 @@ getDirProps(UBiDi *pBiDi, const UChar *text) {
/* perform (X1)..(X9) ------------------------------------------------------- */
/* determine if the text is mixed-directional or single-directional */
static UBiDiDirection
directionFromFlags(Flags flags) {
/* if the text contains AN and neutrals, then some neutrals may become RTL */
if(!(flags&MASK_RTL || ((flags&DIRPROP_FLAG(AN)) && (flags&MASK_POSSIBLE_N)))) {
return UBIDI_LTR;
} else if(!(flags&MASK_LTR)) {
return UBIDI_RTL;
} else {
return UBIDI_MIXED;
}
}
/*
* Resolve the explicit levels as specified by explicit embedding codes.
* Recalculate the flags to have them reflect the real properties
@ -596,7 +394,6 @@ getDirProps(UBiDi *pBiDi, const UChar *text) {
*
* This implementation assumes that UBIDI_MAX_EXPLICIT_LEVEL is odd.
*/
static UBiDiDirection
resolveExplicitLevels(UBiDi *pBiDi) {
const DirProp *dirProps=pBiDi->dirProps;
@ -788,19 +585,6 @@ checkExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
return directionFromFlags(flags);
}
/* determine if the text is mixed-directional or single-directional */
static UBiDiDirection
directionFromFlags(Flags flags) {
/* if the text contains AN and neutrals, then some neutrals may become RTL */
if(!(flags&MASK_RTL || ((flags&DIRPROP_FLAG(AN)) && (flags&MASK_POSSIBLE_N)))) {
return UBIDI_LTR;
} else if(!(flags&MASK_LTR)) {
return UBIDI_RTL;
} else {
return UBIDI_MIXED;
}
}
/* perform rules (Wn), (Nn), and (In) on a run of the text ------------------ */
/*
@ -1211,7 +995,198 @@ adjustWSLevels(UBiDi *pBiDi) {
}
}
/* -------------------------------------------------------------------------- */
/* ubidi_setPara ------------------------------------------------------------ */
U_CAPI void U_EXPORT2
ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels,
UErrorCode *pErrorCode) {
UBiDiDirection direction;
/* check the argument values */
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
return;
} else if(pBiDi==NULL || text==NULL ||
((UBIDI_MAX_EXPLICIT_LEVEL<paraLevel) && !IS_DEFAULT_LEVEL(paraLevel)) ||
length<-1
) {
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
return;
}
if(length==-1) {
length=u_strlen(text);
}
/* initialize the UBiDi structure */
pBiDi->text=text;
pBiDi->length=length;
pBiDi->paraLevel=paraLevel;
pBiDi->direction=UBIDI_LTR;
pBiDi->trailingWSStart=length; /* the levels[] will reflect the WS run */
pBiDi->dirProps=NULL;
pBiDi->levels=NULL;
pBiDi->runs=NULL;
if(length==0) {
/*
* For an empty paragraph, create a UBiDi object with the paraLevel and
* the flags and the direction set but without allocating zero-length arrays.
* There is nothing more to do.
*/
if(IS_DEFAULT_LEVEL(paraLevel)) {
pBiDi->paraLevel&=1;
}
if(paraLevel&1) {
pBiDi->flags=DIRPROP_FLAG(R);
pBiDi->direction=UBIDI_RTL;
} else {
pBiDi->flags=DIRPROP_FLAG(L);
pBiDi->direction=UBIDI_LTR;
}
pBiDi->runCount=0;
return;
}
pBiDi->runCount=-1;
/*
* Get the directional properties,
* the flags bit-set, and
* determine the partagraph level if necessary.
*/
if(getDirPropsMemory(pBiDi, length)) {
pBiDi->dirProps=pBiDi->dirPropsMemory;
getDirProps(pBiDi, text);
} else {
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
return;
}
/* are explicit levels specified? */
if(embeddingLevels==NULL) {
/* no: determine explicit levels according to the (Xn) rules */\
if(getLevelsMemory(pBiDi, length)) {
pBiDi->levels=pBiDi->levelsMemory;
direction=resolveExplicitLevels(pBiDi);
} else {
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
return;
}
} else {
/* set BN for all explicit codes, check that all levels are paraLevel..UBIDI_MAX_EXPLICIT_LEVEL */
pBiDi->levels=embeddingLevels;
direction=checkExplicitLevels(pBiDi, pErrorCode);
if(U_FAILURE(*pErrorCode)) {
return;
}
}
/*
* The steps after (X9) in the UBiDi algorithm are performed only if
* the paragraph text has mixed directionality!
*/
pBiDi->direction=direction;
switch(direction) {
case UBIDI_LTR:
/* make sure paraLevel is even */
pBiDi->paraLevel=(UBiDiLevel)((pBiDi->paraLevel+1)&~1);
/* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
pBiDi->trailingWSStart=0;
break;
case UBIDI_RTL:
/* make sure paraLevel is odd */
pBiDi->paraLevel|=1;
/* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
pBiDi->trailingWSStart=0;
break;
default:
/*
* If there are no external levels specified and there
* are no significant explicit level codes in the text,
* then we can treat the entire paragraph as one run.
* Otherwise, we need to perform the following rules on runs of
* the text with the same embedding levels. (X10)
* "Significant" explicit level codes are ones that actually
* affect non-BN characters.
* Examples for "insignificant" ones are empty embeddings
* LRE-PDF, LRE-RLE-PDF-PDF, etc.
*/
if(embeddingLevels==NULL && !(pBiDi->flags&DIRPROP_FLAG_MULTI_RUNS)) {
resolveImplicitLevels(pBiDi, 0, length,
GET_LR_FROM_LEVEL(pBiDi->paraLevel),
GET_LR_FROM_LEVEL(pBiDi->paraLevel));
} else {
/* sor, eor: start and end types of same-level-run */
UBiDiLevel *levels=pBiDi->levels;
int32_t start, limit=0;
UBiDiLevel level, nextLevel;
DirProp sor, eor;
/* determine the first sor and set eor to it because of the loop body (sor=eor there) */
level=pBiDi->paraLevel;
nextLevel=levels[0];
if(level<nextLevel) {
eor=GET_LR_FROM_LEVEL(nextLevel);
} else {
eor=GET_LR_FROM_LEVEL(level);
}
do {
/* determine start and limit of the run (end points just behind the run) */
/* the values for this run's start are the same as for the previous run's end */
sor=eor;
start=limit;
level=nextLevel;
/* search for the limit of this run */
while(++limit<length && levels[limit]==level) {}
/* get the correct level of the next run */
if(limit<length) {
nextLevel=levels[limit];
} else {
nextLevel=pBiDi->paraLevel;
}
/* determine eor from max(level, nextLevel); sor is last run's eor */
if((level&~UBIDI_LEVEL_OVERRIDE)<(nextLevel&~UBIDI_LEVEL_OVERRIDE)) {
eor=GET_LR_FROM_LEVEL(nextLevel);
} else {
eor=GET_LR_FROM_LEVEL(level);
}
/* if the run consists of overridden directional types, then there
are no implicit types to be resolved */
if(!(level&UBIDI_LEVEL_OVERRIDE)) {
resolveImplicitLevels(pBiDi, start, limit, sor, eor);
} else {
/* remove the UBIDI_LEVEL_OVERRIDE flags */
do {
levels[start++]&=~UBIDI_LEVEL_OVERRIDE;
} while(start<limit);
}
} while(limit<length);
}
/* reset the embedding levels for some non-graphic characters (L1), (X9) */
adjustWSLevels(pBiDi);
/* for "inverse BiDi", ubidi_getRuns() modifies the levels of numeric runs following RTL runs */
if(pBiDi->isInverse) {
if(!ubidi_getRuns(pBiDi)) {
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
return;
}
}
break;
}
}
U_CAPI UBiDiDirection U_EXPORT2
ubidi_getDirection(const UBiDi *pBiDi) {

View file

@ -76,21 +76,38 @@
* change the now shared levels for (L1).
*/
/* prototypes --------------------------------------------------------------- */
/* 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.
*/
static void
setTrailingWSStart(UBiDi *pBiDi);
setTrailingWSStart(UBiDi *pBiDi) {
/* pBiDi->direction!=UBIDI_MIXED */
static void
getSingleRun(UBiDi *pBiDi, UBiDiLevel level);
const DirProp *dirProps=pBiDi->dirProps;
UBiDiLevel *levels=pBiDi->levels;
int32_t start=pBiDi->length;
UBiDiLevel paraLevel=pBiDi->paraLevel;
static void
reorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel);
/* go backwards across all WS, BN, explicit codes */
while(start>0 && DIRPROP_FLAG(dirProps[start-1])&MASK_WS) {
--start;
}
static UBool
prepareReorder(const UBiDiLevel *levels, int32_t length,
int32_t *indexMap,
UBiDiLevel *pMinLevel, UBiDiLevel *pMaxLevel);
/* if the WS run can be merged with the previous run then do so here */
while(start>0 && levels[start-1]==paraLevel) {
--start;
}
pBiDi->trailingWSStart=start;
}
/* ubidi_setLine ------------------------------------------------------------ */
@ -295,39 +312,6 @@ ubidi_getLogicalRun(const UBiDi *pBiDi, int32_t logicalStart,
}
}
/* 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.
*/
static void
setTrailingWSStart(UBiDi *pBiDi) {
/* pBiDi->direction!=UBIDI_MIXED */
const DirProp *dirProps=pBiDi->dirProps;
UBiDiLevel *levels=pBiDi->levels;
int32_t start=pBiDi->length;
UBiDiLevel paraLevel=pBiDi->paraLevel;
/* 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;
}
pBiDi->trailingWSStart=start;
}
/* runs API functions ------------------------------------------------------- */
U_CAPI int32_t U_EXPORT2
@ -367,6 +351,144 @@ ubidi_getVisualRun(UBiDi *pBiDi, int32_t runIndex,
}
}
/* in trivial cases there is only one trivial run; called by ubidi_getRuns() */
static void
getSingleRun(UBiDi *pBiDi, UBiDiLevel level) {
/* simple, single-run case */
pBiDi->runs=pBiDi->simpleRuns;
pBiDi->runCount=1;
/* fill and reorder the single run */
pBiDi->runs[0].logicalStart=MAKE_INDEX_ODD_PAIR(0, level);
pBiDi->runs[0].visualLimit=pBiDi->length;
}
/* reorder the runs array (L2) ---------------------------------------------- */
/*
* Reorder the same-level runs in the runs array.
* Here, runCount>1 and maxLevel>=minLevel>=paraLevel.
* All the visualStart fields=logical start before reordering.
* The "odd" bits are not set yet.
*
* Reordering with this data structure lends itself to some handy shortcuts:
*
* Since each run is moved but not modified, and since at the initial maxLevel
* each sequence of same-level runs consists of only one run each, we
* don't need to do anything there and can predecrement maxLevel.
* In many simple cases, the reordering is thus done entirely in the
* index mapping.
* Also, reordering occurs only down to the lowest odd level that occurs,
* which is minLevel|1. However, if the lowest level itself is odd, then
* in the last reordering the sequence of the runs at this level or higher
* will be all runs, and we don't need the elaborate loop to search for them.
* This is covered by ++minLevel instead of minLevel|=1 followed
* by an extra reorder-all after the reorder-some loop.
* About a trailing WS run:
* Such a run would need special treatment because its level is not
* reflected in levels[] if this is not a paragraph object.
* Instead, all characters from trailingWSStart on are implicitly at
* paraLevel.
* However, for all maxLevel>paraLevel, this run will never be reordered
* and does not need to be taken into account. maxLevel==paraLevel is only reordered
* if minLevel==paraLevel is odd, which is done in the extra segment.
* This means that for the main reordering loop we don't need to consider
* this run and can --runCount. If it is later part of the all-runs
* reordering, then runCount is adjusted accordingly.
*/
static void
reorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel) {
Run *runs;
UBiDiLevel *levels;
int32_t firstRun, endRun, limitRun, runCount,
temp;
/* nothing to do? */
if(maxLevel<=(minLevel|1)) {
return;
}
/*
* Reorder only down to the lowest odd level
* and reorder at an odd minLevel in a separate, simpler loop.
* See comments above for why minLevel is always incremented.
*/
++minLevel;
runs=pBiDi->runs;
levels=pBiDi->levels;
runCount=pBiDi->runCount;
/* do not include the WS run at paraLevel<=old minLevel except in the simple loop */
if(pBiDi->trailingWSStart<pBiDi->length) {
--runCount;
}
while(--maxLevel>=minLevel) {
firstRun=0;
/* loop for all sequences of runs */
for(;;) {
/* look for a sequence of runs that are all at >=maxLevel */
/* look for the first run of such a sequence */
while(firstRun<runCount && levels[runs[firstRun].logicalStart]<maxLevel) {
++firstRun;
}
if(firstRun>=runCount) {
break; /* no more such runs */
}
/* look for the limit run of such a sequence (the run behind it) */
for(limitRun=firstRun; ++limitRun<runCount && levels[runs[limitRun].logicalStart]>=maxLevel;) {}
/* Swap the entire sequence of runs from firstRun to limitRun-1. */
endRun=limitRun-1;
while(firstRun<endRun) {
temp=runs[firstRun].logicalStart;
runs[firstRun].logicalStart=runs[endRun].logicalStart;
runs[endRun].logicalStart=temp;
temp=runs[firstRun].visualLimit;
runs[firstRun].visualLimit=runs[endRun].visualLimit;
runs[endRun].visualLimit=temp;
++firstRun;
--endRun;
}
if(limitRun==runCount) {
break; /* no more such runs */
} else {
firstRun=limitRun+1;
}
}
}
/* now do maxLevel==old minLevel (==odd!), see above */
if(!(minLevel&1)) {
firstRun=0;
/* include the trailing WS run in this complete reordering */
if(pBiDi->trailingWSStart==pBiDi->length) {
--runCount;
}
/* Swap the entire sequence of all runs. (endRun==runCount) */
while(firstRun<runCount) {
temp=runs[firstRun].logicalStart;
runs[firstRun].logicalStart=runs[runCount].logicalStart;
runs[runCount].logicalStart=temp;
temp=runs[firstRun].visualLimit;
runs[firstRun].visualLimit=runs[runCount].visualLimit;
runs[runCount].visualLimit=temp;
++firstRun;
--runCount;
}
}
}
/* compute the runs array --------------------------------------------------- */
/*
@ -505,142 +627,42 @@ ubidi_getRuns(UBiDi *pBiDi) {
return TRUE;
}
/* in trivial cases there is only one trivial run; called by ubidi_getRuns() */
static void
getSingleRun(UBiDi *pBiDi, UBiDiLevel level) {
/* simple, single-run case */
pBiDi->runs=pBiDi->simpleRuns;
pBiDi->runCount=1;
static UBool
prepareReorder(const UBiDiLevel *levels, int32_t length,
int32_t *indexMap,
UBiDiLevel *pMinLevel, UBiDiLevel *pMaxLevel) {
int32_t start;
UBiDiLevel level, minLevel, maxLevel;
/* fill and reorder the single run */
pBiDi->runs[0].logicalStart=MAKE_INDEX_ODD_PAIR(0, level);
pBiDi->runs[0].visualLimit=pBiDi->length;
}
/* reorder the runs array (L2) ---------------------------------------------- */
/*
* Reorder the same-level runs in the runs array.
* Here, runCount>1 and maxLevel>=minLevel>=paraLevel.
* All the visualStart fields=logical start before reordering.
* The "odd" bits are not set yet.
*
* Reordering with this data structure lends itself to some handy shortcuts:
*
* Since each run is moved but not modified, and since at the initial maxLevel
* each sequence of same-level runs consists of only one run each, we
* don't need to do anything there and can predecrement maxLevel.
* In many simple cases, the reordering is thus done entirely in the
* index mapping.
* Also, reordering occurs only down to the lowest odd level that occurs,
* which is minLevel|1. However, if the lowest level itself is odd, then
* in the last reordering the sequence of the runs at this level or higher
* will be all runs, and we don't need the elaborate loop to search for them.
* This is covered by ++minLevel instead of minLevel|=1 followed
* by an extra reorder-all after the reorder-some loop.
* About a trailing WS run:
* Such a run would need special treatment because its level is not
* reflected in levels[] if this is not a paragraph object.
* Instead, all characters from trailingWSStart on are implicitly at
* paraLevel.
* However, for all maxLevel>paraLevel, this run will never be reordered
* and does not need to be taken into account. maxLevel==paraLevel is only reordered
* if minLevel==paraLevel is odd, which is done in the extra segment.
* This means that for the main reordering loop we don't need to consider
* this run and can --runCount. If it is later part of the all-runs
* reordering, then runCount is adjusted accordingly.
*/
static void
reorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel) {
Run *runs;
UBiDiLevel *levels;
int32_t firstRun, endRun, limitRun, runCount,
temp;
/* nothing to do? */
if(maxLevel<=(minLevel|1)) {
return;
if(levels==NULL || length<=0) {
return FALSE;
}
/*
* Reorder only down to the lowest odd level
* and reorder at an odd minLevel in a separate, simpler loop.
* See comments above for why minLevel is always incremented.
*/
++minLevel;
runs=pBiDi->runs;
levels=pBiDi->levels;
runCount=pBiDi->runCount;
/* do not include the WS run at paraLevel<=old minLevel except in the simple loop */
if(pBiDi->trailingWSStart<pBiDi->length) {
--runCount;
}
while(--maxLevel>=minLevel) {
firstRun=0;
/* loop for all sequences of runs */
for(;;) {
/* look for a sequence of runs that are all at >=maxLevel */
/* look for the first run of such a sequence */
while(firstRun<runCount && levels[runs[firstRun].logicalStart]<maxLevel) {
++firstRun;
}
if(firstRun>=runCount) {
break; /* no more such runs */
}
/* look for the limit run of such a sequence (the run behind it) */
for(limitRun=firstRun; ++limitRun<runCount && levels[runs[limitRun].logicalStart]>=maxLevel;) {}
/* Swap the entire sequence of runs from firstRun to limitRun-1. */
endRun=limitRun-1;
while(firstRun<endRun) {
temp=runs[firstRun].logicalStart;
runs[firstRun].logicalStart=runs[endRun].logicalStart;
runs[endRun].logicalStart=temp;
temp=runs[firstRun].visualLimit;
runs[firstRun].visualLimit=runs[endRun].visualLimit;
runs[endRun].visualLimit=temp;
++firstRun;
--endRun;
}
if(limitRun==runCount) {
break; /* no more such runs */
} else {
firstRun=limitRun+1;
}
/* determine minLevel and maxLevel */
minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1;
maxLevel=0;
for(start=length; start>0;) {
level=levels[--start];
if(level>UBIDI_MAX_EXPLICIT_LEVEL+1) {
return FALSE;
}
if(level<minLevel) {
minLevel=level;
}
if(level>maxLevel) {
maxLevel=level;
}
}
*pMinLevel=minLevel;
*pMaxLevel=maxLevel;
/* now do maxLevel==old minLevel (==odd!), see above */
if(!(minLevel&1)) {
firstRun=0;
/* include the trailing WS run in this complete reordering */
if(pBiDi->trailingWSStart==pBiDi->length) {
--runCount;
}
/* Swap the entire sequence of all runs. (endRun==runCount) */
while(firstRun<runCount) {
temp=runs[firstRun].logicalStart;
runs[firstRun].logicalStart=runs[runCount].logicalStart;
runs[runCount].logicalStart=temp;
temp=runs[firstRun].visualLimit;
runs[firstRun].visualLimit=runs[runCount].visualLimit;
runs[runCount].visualLimit=temp;
++firstRun;
--runCount;
}
/* initialize the index map */
for(start=length; start>0;) {
--start;
indexMap[start]=start;
}
return TRUE;
}
/* reorder a line based on a levels array (L2) ------------------------------ */
@ -768,44 +790,6 @@ ubidi_reorderVisual(const UBiDiLevel *levels, int32_t length, int32_t *indexMap)
} while(--maxLevel>=minLevel);
}
static UBool
prepareReorder(const UBiDiLevel *levels, int32_t length,
int32_t *indexMap,
UBiDiLevel *pMinLevel, UBiDiLevel *pMaxLevel) {
int32_t start;
UBiDiLevel level, minLevel, maxLevel;
if(levels==NULL || length<=0) {
return FALSE;
}
/* determine minLevel and maxLevel */
minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1;
maxLevel=0;
for(start=length; start>0;) {
level=levels[--start];
if(level>UBIDI_MAX_EXPLICIT_LEVEL+1) {
return FALSE;
}
if(level<minLevel) {
minLevel=level;
}
if(level>maxLevel) {
maxLevel=level;
}
}
*pMinLevel=minLevel;
*pMaxLevel=maxLevel;
/* initialize the index map */
for(start=length; start>0;) {
--start;
indexMap[start]=start;
}
return TRUE;
}
/* API functions for logical<->visual mapping ------------------------------- */
U_CAPI int32_t U_EXPORT2