mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
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:
parent
cd057e3c4f
commit
01a5ebcb3d
2 changed files with 399 additions and 440 deletions
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue