00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef U_COMMON_IMPLEMENTATION
00019 # define U_COMMON_IMPLEMENTATION
00020 #endif
00021
00022 #include "cmemory.h"
00023 #include "unicode/utypes.h"
00024 #include "unicode/ustring.h"
00025 #include "unicode/uchar.h"
00026 #include "unicode/ubidi.h"
00027 #include "ubidiimp.h"
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 static void
00082 setTrailingWSStart(UBiDi *pBiDi);
00083
00084 static void
00085 getSingleRun(UBiDi *pBiDi, UBiDiLevel level);
00086
00087 static void
00088 reorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel);
00089
00090 static UBool
00091 prepareReorder(const UBiDiLevel *levels, UTextOffset length,
00092 UTextOffset *indexMap,
00093 UBiDiLevel *pMinLevel, UBiDiLevel *pMaxLevel);
00094
00095
00096
00097 U_CAPI void U_EXPORT2
00098 ubidi_setLine(const UBiDi *pParaBiDi,
00099 UTextOffset start, UTextOffset limit,
00100 UBiDi *pLineBiDi,
00101 UErrorCode *pErrorCode) {
00102 UTextOffset length;
00103
00104
00105 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
00106 return;
00107 } else if(pParaBiDi==NULL || pLineBiDi==NULL) {
00108 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00109 return;
00110 } else if(start<0 || start>limit || limit>pParaBiDi->length) {
00111 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
00112 return;
00113 }
00114
00115
00116 pLineBiDi->text=pParaBiDi->text+start;
00117 length=pLineBiDi->length=limit-start;
00118 pLineBiDi->paraLevel=pParaBiDi->paraLevel;
00119
00120 pLineBiDi->runs=NULL;
00121 pLineBiDi->flags=0;
00122
00123 if(length>0) {
00124 pLineBiDi->dirProps=pParaBiDi->dirProps+start;
00125 pLineBiDi->levels=pParaBiDi->levels+start;
00126 pLineBiDi->runCount=-1;
00127
00128 if(pParaBiDi->direction!=UBIDI_MIXED) {
00129
00130 pLineBiDi->direction=pParaBiDi->direction;
00131
00132
00133
00134
00135
00136
00137 if(pParaBiDi->trailingWSStart<=start) {
00138 pLineBiDi->trailingWSStart=0;
00139 } else if(pParaBiDi->trailingWSStart<limit) {
00140 pLineBiDi->trailingWSStart=pParaBiDi->trailingWSStart-start;
00141 } else {
00142 pLineBiDi->trailingWSStart=length;
00143 }
00144 } else {
00145 const UBiDiLevel *levels=pLineBiDi->levels;
00146 UTextOffset i, trailingWSStart;
00147 UBiDiLevel level;
00148
00149 setTrailingWSStart(pLineBiDi);
00150 trailingWSStart=pLineBiDi->trailingWSStart;
00151
00152
00153 if(trailingWSStart==0) {
00154
00155 pLineBiDi->direction=(UBiDiDirection)(pLineBiDi->paraLevel&1);
00156 } else {
00157
00158 level=(UBiDiLevel)(levels[0]&1);
00159
00160
00161 if(trailingWSStart<length && (pLineBiDi->paraLevel&1)!=level) {
00162
00163 pLineBiDi->direction=UBIDI_MIXED;
00164 } else {
00165
00166 i=1;
00167 for(;;) {
00168 if(i==trailingWSStart) {
00169
00170 pLineBiDi->direction=(UBiDiDirection)level;
00171 break;
00172 } else if((levels[i]&1)!=level) {
00173 pLineBiDi->direction=UBIDI_MIXED;
00174 break;
00175 }
00176 ++i;
00177 }
00178 }
00179 }
00180
00181 switch(pLineBiDi->direction) {
00182 case UBIDI_LTR:
00183
00184 pLineBiDi->paraLevel=(UBiDiLevel)((pLineBiDi->paraLevel+1)&~1);
00185
00186
00187 pLineBiDi->trailingWSStart=0;
00188 break;
00189 case UBIDI_RTL:
00190
00191 pLineBiDi->paraLevel|=1;
00192
00193
00194 pLineBiDi->trailingWSStart=0;
00195 break;
00196 default:
00197 break;
00198 }
00199 }
00200 } else {
00201
00202 pLineBiDi->direction=pLineBiDi->paraLevel&1 ? UBIDI_RTL : UBIDI_LTR;
00203 pLineBiDi->trailingWSStart=pLineBiDi->runCount=0;
00204
00205 pLineBiDi->dirProps=NULL;
00206 pLineBiDi->levels=NULL;
00207 }
00208 return;
00209 }
00210
00211 U_CAPI UBiDiLevel U_EXPORT2
00212 ubidi_getLevelAt(const UBiDi *pBiDi, UTextOffset charIndex) {
00213
00214 if(pBiDi==NULL || charIndex<0 || pBiDi->length<=charIndex) {
00215 return 0;
00216 } else if(pBiDi->direction!=UBIDI_MIXED || charIndex>=pBiDi->trailingWSStart) {
00217 return pBiDi->paraLevel;
00218 } else {
00219 return pBiDi->levels[charIndex];
00220 }
00221 }
00222
00223 U_CAPI const UBiDiLevel * U_EXPORT2
00224 ubidi_getLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
00225 UTextOffset start, length;
00226
00227 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
00228 return NULL;
00229 } else if(pBiDi==NULL || (length=pBiDi->length)<=0) {
00230 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00231 return NULL;
00232 }
00233
00234 if((start=pBiDi->trailingWSStart)==length) {
00235
00236 return pBiDi->levels;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 if(getLevelsMemory(pBiDi, length)) {
00248 UBiDiLevel *levels=pBiDi->levelsMemory;
00249
00250 if(start>0 && levels!=pBiDi->levels) {
00251 uprv_memcpy(levels, pBiDi->levels, start);
00252 }
00253 uprv_memset(levels+start, pBiDi->paraLevel, length-start);
00254
00255
00256 pBiDi->trailingWSStart=length;
00257 return pBiDi->levels=levels;
00258 } else {
00259
00260 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00261 return NULL;
00262 }
00263 }
00264
00265 U_CAPI void U_EXPORT2
00266 ubidi_getLogicalRun(const UBiDi *pBiDi, UTextOffset logicalStart,
00267 UTextOffset *pLogicalLimit, UBiDiLevel *pLevel) {
00268 UTextOffset length;
00269
00270 if(pBiDi==NULL || logicalStart<0 || (length=pBiDi->length)<=logicalStart) {
00271 return;
00272 }
00273
00274 if(pBiDi->direction!=UBIDI_MIXED || logicalStart>=pBiDi->trailingWSStart) {
00275 if(pLogicalLimit!=NULL) {
00276 *pLogicalLimit=length;
00277 }
00278 if(pLevel!=NULL) {
00279 *pLevel=pBiDi->paraLevel;
00280 }
00281 } else {
00282 UBiDiLevel *levels=pBiDi->levels;
00283 UBiDiLevel level=levels[logicalStart];
00284
00285
00286 length=pBiDi->trailingWSStart;
00287 while(++logicalStart<length && level==levels[logicalStart]) {}
00288
00289 if(pLogicalLimit!=NULL) {
00290 *pLogicalLimit=logicalStart;
00291 }
00292 if(pLevel!=NULL) {
00293 *pLevel=level;
00294 }
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 static void
00310 setTrailingWSStart(UBiDi *pBiDi) {
00311
00312
00313 const DirProp *dirProps=pBiDi->dirProps;
00314 UBiDiLevel *levels=pBiDi->levels;
00315 UTextOffset start=pBiDi->length;
00316 UBiDiLevel paraLevel=pBiDi->paraLevel;
00317
00318
00319 while(start>0 && DIRPROP_FLAG(dirProps[start-1])&MASK_WS) {
00320 --start;
00321 }
00322
00323
00324 while(start>0 && levels[start-1]==paraLevel) {
00325 --start;
00326 }
00327
00328 pBiDi->trailingWSStart=start;
00329 }
00330
00331
00332
00333 U_CAPI UTextOffset U_EXPORT2
00334 ubidi_countRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) {
00335 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
00336 return -1;
00337 } else if(pBiDi==NULL || (pBiDi->runCount<0 && !ubidi_getRuns(pBiDi))) {
00338 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00339 return -1;
00340 } else {
00341 return pBiDi->runCount;
00342 }
00343 }
00344
00345 U_CAPI UBiDiDirection U_EXPORT2
00346 ubidi_getVisualRun(UBiDi *pBiDi, UTextOffset runIndex,
00347 UTextOffset *pLogicalStart, UTextOffset *pLength) {
00348 if( pBiDi==NULL || runIndex<0 ||
00349 (pBiDi->runCount==-1 && !ubidi_getRuns(pBiDi)) ||
00350 runIndex>=pBiDi->runCount
00351 ) {
00352 return UBIDI_LTR;
00353 } else {
00354 UTextOffset start=pBiDi->runs[runIndex].logicalStart;
00355 if(pLogicalStart!=NULL) {
00356 *pLogicalStart=GET_INDEX(start);
00357 }
00358 if(pLength!=NULL) {
00359 if(runIndex>0) {
00360 *pLength=pBiDi->runs[runIndex].visualLimit-
00361 pBiDi->runs[runIndex-1].visualLimit;
00362 } else {
00363 *pLength=pBiDi->runs[0].visualLimit;
00364 }
00365 }
00366 return (UBiDiDirection)GET_ODD_BIT(start);
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 U_CFUNC UBool
00380 ubidi_getRuns(UBiDi *pBiDi) {
00381 if(pBiDi->direction!=UBIDI_MIXED) {
00382
00383 getSingleRun(pBiDi, pBiDi->paraLevel);
00384 } else {
00385
00386 UTextOffset length=pBiDi->length, limit;
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 limit=pBiDi->trailingWSStart;
00400 if(limit==0) {
00401
00402 getSingleRun(pBiDi, pBiDi->paraLevel);
00403 } else {
00404 UBiDiLevel *levels=pBiDi->levels;
00405 UTextOffset i, runCount;
00406 UBiDiLevel level=UBIDI_DEFAULT_LTR;
00407
00408
00409 runCount=0;
00410 for(i=0; i<limit; ++i) {
00411
00412 if(levels[i]!=level) {
00413 ++runCount;
00414 level=levels[i];
00415 }
00416 }
00417
00418
00419
00420
00421
00422 if(runCount==1 && limit==length) {
00423
00424 getSingleRun(pBiDi, levels[0]);
00425 } else {
00426
00427 Run *runs;
00428 UTextOffset runIndex, start;
00429 UBiDiLevel minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1, maxLevel=0;
00430
00431
00432 if(limit<length) {
00433 ++runCount;
00434 }
00435
00436
00437 if(getRunsMemory(pBiDi, runCount)) {
00438 runs=pBiDi->runsMemory;
00439 } else {
00440 return FALSE;
00441 }
00442
00443
00444
00445
00446 runIndex=0;
00447
00448
00449 i=0;
00450 do {
00451
00452 start=i;
00453 level=levels[i];
00454 if(level<minLevel) {
00455 minLevel=level;
00456 }
00457 if(level>maxLevel) {
00458 maxLevel=level;
00459 }
00460
00461
00462 while(++i<limit && levels[i]==level) {}
00463
00464
00465 runs[runIndex].logicalStart=start;
00466 runs[runIndex].visualLimit=i-start;
00467 ++runIndex;
00468 } while(i<limit);
00469
00470 if(limit<length) {
00471
00472 runs[runIndex].logicalStart=limit;
00473 runs[runIndex].visualLimit=length-limit;
00474 if(pBiDi->paraLevel<minLevel) {
00475 minLevel=pBiDi->paraLevel;
00476 }
00477 }
00478
00479
00480 pBiDi->runs=runs;
00481 pBiDi->runCount=runCount;
00482
00483 reorderLine(pBiDi, minLevel, maxLevel);
00484
00485
00486 ADD_ODD_BIT_FROM_LEVEL(runs[0].logicalStart, levels[runs[0].logicalStart]);
00487 limit=runs[0].visualLimit;
00488 for(i=1; i<runIndex; ++i) {
00489 ADD_ODD_BIT_FROM_LEVEL(runs[i].logicalStart, levels[runs[i].logicalStart]);
00490 limit=runs[i].visualLimit+=limit;
00491 }
00492
00493
00494 if(runIndex<runCount) {
00495 ADD_ODD_BIT_FROM_LEVEL(runs[i].logicalStart, pBiDi->paraLevel);
00496 runs[runIndex].visualLimit+=limit;
00497 }
00498 }
00499 }
00500 }
00501 return TRUE;
00502 }
00503
00504
00505 static void
00506 getSingleRun(UBiDi *pBiDi, UBiDiLevel level) {
00507
00508 pBiDi->runs=pBiDi->simpleRuns;
00509 pBiDi->runCount=1;
00510
00511
00512 pBiDi->runs[0].logicalStart=MAKE_INDEX_ODD_PAIR(0, level);
00513 pBiDi->runs[0].visualLimit=pBiDi->length;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 static void
00550 reorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel) {
00551 Run *runs;
00552 UBiDiLevel *levels;
00553 UTextOffset firstRun, endRun, limitRun, runCount,
00554 temp;
00555
00556
00557 if(maxLevel<=(minLevel|1)) {
00558 return;
00559 }
00560
00561
00562
00563
00564
00565
00566 ++minLevel;
00567
00568 runs=pBiDi->runs;
00569 levels=pBiDi->levels;
00570 runCount=pBiDi->runCount;
00571
00572
00573 if(pBiDi->trailingWSStart<pBiDi->length) {
00574 --runCount;
00575 }
00576
00577 while(--maxLevel>=minLevel) {
00578 firstRun=0;
00579
00580
00581 for(;;) {
00582
00583
00584 while(firstRun<runCount && levels[runs[firstRun].logicalStart]<maxLevel) {
00585 ++firstRun;
00586 }
00587 if(firstRun>=runCount) {
00588 break;
00589 }
00590
00591
00592 for(limitRun=firstRun; ++limitRun<runCount && levels[runs[limitRun].logicalStart]>=maxLevel;) {}
00593
00594
00595 endRun=limitRun-1;
00596 while(firstRun<endRun) {
00597 temp=runs[firstRun].logicalStart;
00598 runs[firstRun].logicalStart=runs[endRun].logicalStart;
00599 runs[endRun].logicalStart=temp;
00600
00601 temp=runs[firstRun].visualLimit;
00602 runs[firstRun].visualLimit=runs[endRun].visualLimit;
00603 runs[endRun].visualLimit=temp;
00604
00605 ++firstRun;
00606 --endRun;
00607 }
00608
00609 if(limitRun==runCount) {
00610 break;
00611 } else {
00612 firstRun=limitRun+1;
00613 }
00614 }
00615 }
00616
00617
00618 if(!(minLevel&1)) {
00619 firstRun=0;
00620
00621
00622 if(pBiDi->trailingWSStart==pBiDi->length) {
00623 --runCount;
00624 }
00625
00626
00627 while(firstRun<runCount) {
00628 temp=runs[firstRun].logicalStart;
00629 runs[firstRun].logicalStart=runs[runCount].logicalStart;
00630 runs[runCount].logicalStart=temp;
00631
00632 temp=runs[firstRun].visualLimit;
00633 runs[firstRun].visualLimit=runs[runCount].visualLimit;
00634 runs[runCount].visualLimit=temp;
00635
00636 ++firstRun;
00637 --runCount;
00638 }
00639 }
00640 }
00641
00642
00643
00644 U_CAPI void U_EXPORT2
00645 ubidi_reorderLogical(const UBiDiLevel *levels, UTextOffset length, UTextOffset *indexMap) {
00646 UTextOffset start, limit, sumOfSosEos;
00647 UBiDiLevel minLevel, maxLevel;
00648
00649 if(indexMap==NULL || !prepareReorder(levels, length, indexMap, &minLevel, &maxLevel)) {
00650 return;
00651 }
00652
00653
00654 if(minLevel==maxLevel && (minLevel&1)==0) {
00655 return;
00656 }
00657
00658
00659 minLevel|=1;
00660
00661
00662 do {
00663 start=0;
00664
00665
00666 for(;;) {
00667
00668
00669 while(start<length && levels[start]<maxLevel) {
00670 ++start;
00671 }
00672 if(start>=length) {
00673 break;
00674 }
00675
00676
00677 for(limit=start; ++limit<length && levels[limit]>=maxLevel;) {}
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 sumOfSosEos=start+limit-1;
00691
00692
00693 do {
00694 indexMap[start]=sumOfSosEos-indexMap[start];
00695 } while(++start<limit);
00696
00697
00698 if(limit==length) {
00699 break;
00700 } else {
00701 start=limit+1;
00702 }
00703 }
00704 } while(--maxLevel>=minLevel);
00705 }
00706
00707 U_CAPI void U_EXPORT2
00708 ubidi_reorderVisual(const UBiDiLevel *levels, UTextOffset length, UTextOffset *indexMap) {
00709 UTextOffset start, end, limit, temp;
00710 UBiDiLevel minLevel, maxLevel;
00711
00712 if(indexMap==NULL || !prepareReorder(levels, length, indexMap, &minLevel, &maxLevel)) {
00713 return;
00714 }
00715
00716
00717 if(minLevel==maxLevel && (minLevel&1)==0) {
00718 return;
00719 }
00720
00721
00722 minLevel|=1;
00723
00724
00725 do {
00726 start=0;
00727
00728
00729 for(;;) {
00730
00731
00732 while(start<length && levels[start]<maxLevel) {
00733 ++start;
00734 }
00735 if(start>=length) {
00736 break;
00737 }
00738
00739
00740 for(limit=start; ++limit<length && levels[limit]>=maxLevel;) {}
00741
00742
00743
00744
00745
00746
00747
00748 end=limit-1;
00749 while(start<end) {
00750 temp=indexMap[start];
00751 indexMap[start]=indexMap[end];
00752 indexMap[end]=temp;
00753
00754 ++start;
00755 --end;
00756 }
00757
00758 if(limit==length) {
00759 break;
00760 } else {
00761 start=limit+1;
00762 }
00763 }
00764 } while(--maxLevel>=minLevel);
00765 }
00766
00767 static UBool
00768 prepareReorder(const UBiDiLevel *levels, UTextOffset length,
00769 UTextOffset *indexMap,
00770 UBiDiLevel *pMinLevel, UBiDiLevel *pMaxLevel) {
00771 UTextOffset start;
00772 UBiDiLevel level, minLevel, maxLevel;
00773
00774 if(levels==NULL || length<=0) {
00775 return FALSE;
00776 }
00777
00778
00779 minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1;
00780 maxLevel=0;
00781 for(start=length; start>0;) {
00782 level=levels[--start];
00783 if(level>UBIDI_MAX_EXPLICIT_LEVEL+1) {
00784 return FALSE;
00785 }
00786 if(level<minLevel) {
00787 minLevel=level;
00788 }
00789 if(level>maxLevel) {
00790 maxLevel=level;
00791 }
00792 }
00793 *pMinLevel=minLevel;
00794 *pMaxLevel=maxLevel;
00795
00796
00797 for(start=length; start>0;) {
00798 --start;
00799 indexMap[start]=start;
00800 }
00801
00802 return TRUE;
00803 }
00804
00805
00806
00807 U_CAPI UTextOffset U_EXPORT2
00808 ubidi_getVisualIndex(UBiDi *pBiDi, UTextOffset logicalIndex, UErrorCode *pErrorCode) {
00809 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
00810 return 0;
00811 } else if(pBiDi==NULL) {
00812 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00813 return 0;
00814 } else if(logicalIndex<0 || pBiDi->length<=logicalIndex) {
00815 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
00816 return 0;
00817 } else {
00818
00819 switch(pBiDi->direction) {
00820 case UBIDI_LTR:
00821 return logicalIndex;
00822 case UBIDI_RTL:
00823 return pBiDi->length-logicalIndex-1;
00824 default:
00825 if(pBiDi->runCount<0 && !ubidi_getRuns(pBiDi)) {
00826 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00827 return 0;
00828 } else {
00829 Run *runs=pBiDi->runs;
00830 UTextOffset i, visualStart=0, offset, length;
00831
00832
00833 for(i=0;; ++i) {
00834 length=runs[i].visualLimit-visualStart;
00835 offset=logicalIndex-GET_INDEX(runs[i].logicalStart);
00836 if(offset>=0 && offset<length) {
00837 if(IS_EVEN_RUN(runs[i].logicalStart)) {
00838
00839 return visualStart+offset;
00840 } else {
00841
00842 return visualStart+length-offset-1;
00843 }
00844 }
00845 visualStart+=length;
00846 }
00847 }
00848 }
00849 }
00850 }
00851
00852 U_CAPI UTextOffset U_EXPORT2
00853 ubidi_getLogicalIndex(UBiDi *pBiDi, UTextOffset visualIndex, UErrorCode *pErrorCode) {
00854 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
00855 return 0;
00856 } else if(pBiDi==NULL) {
00857 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00858 return 0;
00859 } else if(visualIndex<0 || pBiDi->length<=visualIndex) {
00860 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
00861 return 0;
00862 } else {
00863
00864 switch(pBiDi->direction) {
00865 case UBIDI_LTR:
00866 return visualIndex;
00867 case UBIDI_RTL:
00868 return pBiDi->length-visualIndex-1;
00869 default:
00870 if(pBiDi->runCount<0 && !ubidi_getRuns(pBiDi)) {
00871 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00872 return 0;
00873 } else {
00874 Run *runs=pBiDi->runs;
00875 UTextOffset i, runCount=pBiDi->runCount, start;
00876
00877 if(runCount<=10) {
00878
00879 for(i=0; visualIndex>=runs[i].visualLimit; ++i) {}
00880 } else {
00881
00882 UTextOffset begin=0, limit=runCount;
00883
00884
00885 for(;;) {
00886 i=(begin+limit)/2;
00887 if(visualIndex>=runs[i].visualLimit) {
00888 begin=i+1;
00889 } else if(i==0 || visualIndex>=runs[i-1].visualLimit) {
00890 break;
00891 } else {
00892 limit=i;
00893 }
00894 }
00895 }
00896
00897 start=runs[i].logicalStart;
00898 if(IS_EVEN_RUN(start)) {
00899
00900
00901 if(i>0) {
00902 visualIndex-=runs[i-1].visualLimit;
00903 }
00904 return GET_INDEX(start)+visualIndex;
00905 } else {
00906
00907 return GET_INDEX(start)+runs[i].visualLimit-visualIndex-1;
00908 }
00909 }
00910 }
00911 }
00912 }
00913
00914 U_CAPI void U_EXPORT2
00915 ubidi_getLogicalMap(UBiDi *pBiDi, UTextOffset *indexMap, UErrorCode *pErrorCode) {
00916 UBiDiLevel *levels;
00917
00918
00919 if((levels=(UBiDiLevel *)ubidi_getLevels(pBiDi, pErrorCode))==NULL) {
00920
00921 } else if(indexMap==NULL) {
00922 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00923 } else {
00924 ubidi_reorderLogical(levels, pBiDi->length, indexMap);
00925 }
00926 }
00927
00928 U_CAPI void U_EXPORT2
00929 ubidi_getVisualMap(UBiDi *pBiDi, UTextOffset *indexMap, UErrorCode *pErrorCode) {
00930
00931 if(ubidi_countRuns(pBiDi, pErrorCode)<=0) {
00932
00933 } else if(indexMap==NULL) {
00934 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00935 } else {
00936
00937 Run *runs=pBiDi->runs, *runsLimit=runs+pBiDi->runCount;
00938 UTextOffset logicalStart, visualStart, visualLimit;
00939
00940 visualStart=0;
00941 for(; runs<runsLimit; ++runs) {
00942 logicalStart=runs->logicalStart;
00943 visualLimit=runs->visualLimit;
00944 if(IS_EVEN_RUN(logicalStart)) {
00945 do {
00946 *indexMap++ = logicalStart++;
00947 } while(++visualStart<visualLimit);
00948 } else {
00949 REMOVE_ODD_BIT(logicalStart);
00950 logicalStart+=visualLimit-visualStart;
00951 do {
00952 *indexMap++ = --logicalStart;
00953 } while(++visualStart<visualLimit);
00954 }
00955
00956 }
00957 }
00958 }
00959
00960 U_CAPI void U_EXPORT2
00961 ubidi_invertMap(const UTextOffset *srcMap, UTextOffset *destMap, UTextOffset length) {
00962 if(srcMap!=NULL && destMap!=NULL) {
00963 srcMap+=length;
00964 while(length>0) {
00965 destMap[*--srcMap]=--length;
00966 }
00967 }
00968 }