1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)****************************************************************************** 3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Copyright (C) 1999-2010, International Business Machines 5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Corporation and others. All Rights Reserved. 6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)****************************************************************************** 8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* file name: ubidiln.c 9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* encoding: US-ASCII 10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* tab size: 8 (not used) 11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* indentation:4 12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* created on: 1999aug06 14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* created by: Markus W. Scherer, updated by Matitiahu Allouche 15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*/ 16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h" 18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h" 19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ustring.h" 20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uchar.h" 21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ubidi.h" 22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ubidiimp.h" 23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uassert.h" 24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * General remarks about the functions in this file: 27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * These functions deal with the aspects of potentially mixed-directional 29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * text in a single paragraph or in a line of a single paragraph 30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * which has already been processed according to 31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * the Unicode 3.0 BiDi algorithm as defined in 32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * http://www.unicode.org/unicode/reports/tr9/ , version 13, 33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * also described in The Unicode Standard, Version 4.0.1 . 34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This means that there is a UBiDi object with a levels 36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * and a dirProps array. 37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * paraLevel and direction are also set. 38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Only if the length of the text is zero, then levels==dirProps==NULL. 39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The overall directionality of the paragraph 41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * or line is used to bypass the reordering steps if possible. 42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Even purely RTL text does not need reordering there because 43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * the ubidi_getLogical/VisualIndex() functions can compute the 44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * index on the fly in such a case. 45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The implementation of the access to same-level-runs and of the reordering 47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * do attempt to provide better performance and less memory usage compared to 48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * a direct implementation of especially rule (L2) with an array of 49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * one (32-bit) integer per text character. 50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Here, the levels array is scanned as soon as necessary, and a vector of 52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * same-level-runs is created. Reordering then is done on this vector. 53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * For each run of text positions that were resolved to the same level, 54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * only 8 bytes are stored: the first text position of the run and the visual 55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * position behind the run after reordering. 56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * One sign bit is used to hold the directionality of the run. 57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This is inefficient if there are many very short runs. If the average run 58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * length is <2, then this uses more memory. 59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * In a further attempt to save memory, the levels array is never changed 61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * after all the resolution rules (Xn, Wn, Nn, In). 62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Many functions have to consider the field trailingWSStart: 63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * if it is less than length, then there is an implicit trailing run 64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * at the paraLevel, 65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * which is not reflected in the levels array. 66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This allows a line UBiDi object to use the same levels array as 67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * its paragraph parent object. 68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * When a UBiDi object is created for a line of a paragraph, then the 70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * paragraph's levels and dirProps arrays are reused by way of setting 71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * a pointer into them, not by copying. This again saves memory and forbids to 72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * change the now shared levels for (L1). 73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* handle trailing WS (L1) -------------------------------------------------- */ 76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * setTrailingWSStart() sets the start index for a trailing 79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * run of WS in the line. This is necessary because we do not modify 80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * the paragraph's levels array that we just point into. 81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Using trailingWSStart is another form of performing (L1). 82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * To make subsequent operations easier, we also include the run 84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * before the WS if it is at the paraLevel - we merge the two here. 85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This function is called only from ubidi_setLine(), so pBiDi->paraLevel is 87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * set correctly for the line even when contextual multiple paragraphs. 88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void 90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)setTrailingWSStart(UBiDi *pBiDi) { 91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* pBiDi->direction!=UBIDI_MIXED */ 92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const DirProp *dirProps=pBiDi->dirProps; 94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel *levels=pBiDi->levels; 95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t start=pBiDi->length; 96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel paraLevel=pBiDi->paraLevel; 97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* If the line is terminated by a block separator, all preceding WS etc... 99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) are already set to paragraph level. 100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Setting trailingWSStart to pBidi->length will avoid changing the 101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) level of B chars from 0 to paraLevel in ubidi_getLevels when 102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) orderParagraphsLTR==TRUE. 103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(NO_CONTEXT_RTL(dirProps[start-1])==B) { 105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->trailingWSStart=start; /* currently == pBiDi->length */ 106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* go backwards across all WS, BN, explicit codes */ 109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(start>0 && DIRPROP_FLAG_NC(dirProps[start-1])&MASK_WS) { 110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --start; 111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* if the WS run can be merged with the previous run then do so here */ 114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(start>0 && levels[start-1]==paraLevel) { 115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --start; 116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->trailingWSStart=start; 119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* ubidi_setLine ------------------------------------------------------------ */ 122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_setLine(const UBiDi *pParaBiDi, 125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t start, int32_t limit, 126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDi *pLineBiDi, 127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode *pErrorCode) { 128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t length; 129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* check the argument values */ 131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode); 132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_VOID_IF_NOT_VALID_PARA(pParaBiDi, *pErrorCode); 133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_VOID_IF_BAD_RANGE(start, 0, limit, *pErrorCode); 134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_VOID_IF_BAD_RANGE(limit, 0, pParaBiDi->length+1, *pErrorCode); 135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pLineBiDi==NULL) { 136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(ubidi_getParagraph(pParaBiDi, start, NULL, NULL, NULL, pErrorCode) != 140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ubidi_getParagraph(pParaBiDi, limit-1, NULL, NULL, NULL, pErrorCode)) { 141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* the line crosses a paragraph boundary */ 142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* set the values in pLineBiDi from its pParaBiDi parent */ 147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->pParaBiDi=NULL; /* mark unfinished setLine */ 148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->text=pParaBiDi->text+start; 149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=pLineBiDi->length=limit-start; 150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->resultLength=pLineBiDi->originalLength=length; 151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->paraLevel=GET_PARALEVEL(pParaBiDi, start); 152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->paraCount=pParaBiDi->paraCount; 153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->runs=NULL; 154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->flags=0; 155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->reorderingMode=pParaBiDi->reorderingMode; 156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->reorderingOptions=pParaBiDi->reorderingOptions; 157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->controlCount=0; 158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pParaBiDi->controlCount>0) { 159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t j; 160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=start; j<limit; j++) { 161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_BIDI_CONTROL_CHAR(pParaBiDi->text[j])) { 162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->controlCount++; 163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->resultLength-=pLineBiDi->controlCount; 166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->dirProps=pParaBiDi->dirProps+start; 169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->levels=pParaBiDi->levels+start; 170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->runCount=-1; 171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pParaBiDi->direction!=UBIDI_MIXED) { 173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* the parent is already trivial */ 174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->direction=pParaBiDi->direction; 175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The parent's levels are all either 178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * implicitly or explicitly ==paraLevel; 179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * do the same here. 180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pParaBiDi->trailingWSStart<=start) { 182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->trailingWSStart=0; 183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if(pParaBiDi->trailingWSStart<limit) { 184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->trailingWSStart=pParaBiDi->trailingWSStart-start; 185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->trailingWSStart=length; 187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UBiDiLevel *levels=pLineBiDi->levels; 190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t i, trailingWSStart; 191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel level; 192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) setTrailingWSStart(pLineBiDi); 194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trailingWSStart=pLineBiDi->trailingWSStart; 195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* recalculate pLineBiDi->direction */ 197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(trailingWSStart==0) { 198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* all levels are at paraLevel */ 199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->direction=(UBiDiDirection)(pLineBiDi->paraLevel&1); 200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* get the level of the first character */ 202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) level=(UBiDiLevel)(levels[0]&1); 203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* if there is anything of a different level, then the line is mixed */ 205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(trailingWSStart<length && (pLineBiDi->paraLevel&1)!=level) { 206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* the trailing WS is at paraLevel, which differs from levels[0] */ 207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->direction=UBIDI_MIXED; 208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* see if levels[1..trailingWSStart-1] have the same direction as levels[0] and paraLevel */ 210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) i=1; 211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(;;) { 212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(i==trailingWSStart) { 213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* the direction values match those in level */ 214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->direction=(UBiDiDirection)level; 215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if((levels[i]&1)!=level) { 217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->direction=UBIDI_MIXED; 218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++i; 221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) switch(pLineBiDi->direction) { 226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case UBIDI_LTR: 227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* make sure paraLevel is even */ 228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->paraLevel=(UBiDiLevel)((pLineBiDi->paraLevel+1)&~1); 229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */ 231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->trailingWSStart=0; 232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case UBIDI_RTL: 234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* make sure paraLevel is odd */ 235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->paraLevel|=1; 236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */ 238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->trailingWSStart=0; 239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) default: 241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pLineBiDi->pParaBiDi=pParaBiDi; /* mark successful setLine */ 245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI UBiDiLevel U_EXPORT2 249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_getLevelAt(const UBiDi *pBiDi, int32_t charIndex) { 250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* return paraLevel if in the trailing WS run, otherwise the real level */ 251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(!IS_VALID_PARA_OR_LINE(pBiDi) || charIndex<0 || pBiDi->length<=charIndex) { 252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if(pBiDi->direction!=UBIDI_MIXED || charIndex>=pBiDi->trailingWSStart) { 254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return GET_PARALEVEL(pBiDi, charIndex); 255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return pBiDi->levels[charIndex]; 257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI const UBiDiLevel * U_EXPORT2 261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_getLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) { 262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t start, length; 263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, NULL); 265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, NULL); 266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if((length=pBiDi->length)<=0) { 267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if((start=pBiDi->trailingWSStart)==length) { 271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* the current levels array reflects the WS run */ 272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return pBiDi->levels; 273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * After the previous if(), we know that the levels array 277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * has an implicit trailing WS run and therefore does not fully 278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * reflect itself all the levels. 279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This must be a UBiDi object for a line, and 280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * we need to create a new levels array. 281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(getLevelsMemory(pBiDi, length)) { 283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel *levels=pBiDi->levelsMemory; 284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(start>0 && levels!=pBiDi->levels) { 286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memcpy(levels, pBiDi->levels, start); 287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* pBiDi->paraLevel is ok even if contextual multiple paragraphs, 289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) since pBidi is a line object */ 290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memset(levels+start, pBiDi->paraLevel, length-start); 291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* this new levels array is set for the line and reflects the WS run */ 293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->trailingWSStart=length; 294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return pBiDi->levels=levels; 295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* out of memory */ 297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_MEMORY_ALLOCATION_ERROR; 298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_getLogicalRun(const UBiDi *pBiDi, int32_t logicalPosition, 304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t *pLogicalLimit, UBiDiLevel *pLevel) { 305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode errorCode; 306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t runCount, visualStart, logicalLimit, logicalFirst, i; 307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run iRun; 308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) errorCode=U_ZERO_ERROR; 310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_VOID_IF_BAD_RANGE(logicalPosition, 0, pBiDi->length, errorCode); 311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* ubidi_countRuns will check VALID_PARA_OR_LINE */ 312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runCount=ubidi_countRuns((UBiDi *)pBiDi, &errorCode); 313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(errorCode)) { 314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* this is done based on runs rather than on levels since levels have 317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) a special interpretation when UBIDI_REORDER_RUNS_ONLY 318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart=logicalLimit=0; 320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) iRun=pBiDi->runs[0]; 321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; i<runCount; i++) { 323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) iRun = pBiDi->runs[i]; 324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalFirst=GET_INDEX(iRun.logicalStart); 325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalLimit=logicalFirst+iRun.visualLimit-visualStart; 326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if((logicalPosition>=logicalFirst) && 327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (logicalPosition<logicalLimit)) { 328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart = iRun.visualLimit; 331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pLogicalLimit) { 333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pLogicalLimit=logicalLimit; 334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pLevel) { 336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->reorderingMode==UBIDI_REORDER_RUNS_ONLY) { 337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pLevel=(UBiDiLevel)GET_ODD_BIT(iRun.logicalStart); 338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if(pBiDi->direction!=UBIDI_MIXED || logicalPosition>=pBiDi->trailingWSStart) { 340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pLevel=GET_PARALEVEL(pBiDi, logicalPosition); 341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pLevel=pBiDi->levels[logicalPosition]; 343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* runs API functions ------------------------------------------------------- */ 348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2 350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_countRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) { 351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1); 352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1); 353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ubidi_getRuns(pBiDi, pErrorCode); 354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(*pErrorCode)) { 355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return -1; 356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return pBiDi->runCount; 358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI UBiDiDirection U_EXPORT2 361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_getVisualRun(UBiDi *pBiDi, int32_t runIndex, 362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t *pLogicalStart, int32_t *pLength) 363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t start; 365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode errorCode = U_ZERO_ERROR; 366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, errorCode, UBIDI_LTR); 367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ubidi_getRuns(pBiDi, &errorCode); 368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(errorCode)) { 369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return UBIDI_LTR; 370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_BAD_RANGE(runIndex, 0, pBiDi->runCount, errorCode, UBIDI_LTR); 372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) start=pBiDi->runs[runIndex].logicalStart; 374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pLogicalStart!=NULL) { 375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pLogicalStart=GET_INDEX(start); 376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pLength!=NULL) { 378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(runIndex>0) { 379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pLength=pBiDi->runs[runIndex].visualLimit- 380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runs[runIndex-1].visualLimit; 381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pLength=pBiDi->runs[0].visualLimit; 383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return (UBiDiDirection)GET_ODD_BIT(start); 386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* in trivial cases there is only one trivial run; called by ubidi_getRuns() */ 389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void 390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)getSingleRun(UBiDi *pBiDi, UBiDiLevel level) { 391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* simple, single-run case */ 392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runs=pBiDi->simpleRuns; 393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runCount=1; 394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* fill and reorder the single run */ 396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runs[0].logicalStart=MAKE_INDEX_ODD_PAIR(0, level); 397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runs[0].visualLimit=pBiDi->length; 398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runs[0].insertRemove=0; 399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* reorder the runs array (L2) ---------------------------------------------- */ 402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Reorder the same-level runs in the runs array. 405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Here, runCount>1 and maxLevel>=minLevel>=paraLevel. 406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * All the visualStart fields=logical start before reordering. 407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The "odd" bits are not set yet. 408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Reordering with this data structure lends itself to some handy shortcuts: 410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Since each run is moved but not modified, and since at the initial maxLevel 412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * each sequence of same-level runs consists of only one run each, we 413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * don't need to do anything there and can predecrement maxLevel. 414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * In many simple cases, the reordering is thus done entirely in the 415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * index mapping. 416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Also, reordering occurs only down to the lowest odd level that occurs, 417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * which is minLevel|1. However, if the lowest level itself is odd, then 418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * in the last reordering the sequence of the runs at this level or higher 419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * will be all runs, and we don't need the elaborate loop to search for them. 420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This is covered by ++minLevel instead of minLevel|=1 followed 421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * by an extra reorder-all after the reorder-some loop. 422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * About a trailing WS run: 423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Such a run would need special treatment because its level is not 424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * reflected in levels[] if this is not a paragraph object. 425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Instead, all characters from trailingWSStart on are implicitly at 426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * paraLevel. 427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * However, for all maxLevel>paraLevel, this run will never be reordered 428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * and does not need to be taken into account. maxLevel==paraLevel is only reordered 429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * if minLevel==paraLevel is odd, which is done in the extra segment. 430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This means that for the main reordering loop we don't need to consider 431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * this run and can --runCount. If it is later part of the all-runs 432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * reordering, then runCount is adjusted accordingly. 433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void 435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)reorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel) { 436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run *runs, tempRun; 437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel *levels; 438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t firstRun, endRun, limitRun, runCount; 439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* nothing to do? */ 441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(maxLevel<=(minLevel|1)) { 442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Reorder only down to the lowest odd level 447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * and reorder at an odd minLevel in a separate, simpler loop. 448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * See comments above for why minLevel is always incremented. 449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++minLevel; 451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs=pBiDi->runs; 453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) levels=pBiDi->levels; 454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runCount=pBiDi->runCount; 455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* do not include the WS run at paraLevel<=old minLevel except in the simple loop */ 457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->trailingWSStart<pBiDi->length) { 458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --runCount; 459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(--maxLevel>=minLevel) { 462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) firstRun=0; 463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* loop for all sequences of runs */ 465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(;;) { 466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for a sequence of runs that are all at >=maxLevel */ 467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for the first run of such a sequence */ 468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(firstRun<runCount && levels[runs[firstRun].logicalStart]<maxLevel) { 469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++firstRun; 470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(firstRun>=runCount) { 472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; /* no more such runs */ 473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for the limit run of such a sequence (the run behind it) */ 476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(limitRun=firstRun; ++limitRun<runCount && levels[runs[limitRun].logicalStart]>=maxLevel;) {} 477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* Swap the entire sequence of runs from firstRun to limitRun-1. */ 479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) endRun=limitRun-1; 480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(firstRun<endRun) { 481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) tempRun = runs[firstRun]; 482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[firstRun]=runs[endRun]; 483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[endRun]=tempRun; 484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++firstRun; 485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --endRun; 486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(limitRun==runCount) { 489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; /* no more such runs */ 490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) firstRun=limitRun+1; 492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* now do maxLevel==old minLevel (==odd!), see above */ 497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(!(minLevel&1)) { 498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) firstRun=0; 499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* include the trailing WS run in this complete reordering */ 501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->trailingWSStart==pBiDi->length) { 502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --runCount; 503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* Swap the entire sequence of all runs. (endRun==runCount) */ 506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(firstRun<runCount) { 507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) tempRun=runs[firstRun]; 508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[firstRun]=runs[runCount]; 509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[runCount]=tempRun; 510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++firstRun; 511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --runCount; 512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* compute the runs array --------------------------------------------------- */ 517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t getRunFromLogicalIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode) { 519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run *runs=pBiDi->runs; 520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t runCount=pBiDi->runCount, visualStart=0, i, length, logicalStart; 521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; i<runCount; i++) { 523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=runs[i].visualLimit-visualStart; 524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalStart=GET_INDEX(runs[i].logicalStart); 525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if((logicalIndex>=logicalStart) && (logicalIndex<(logicalStart+length))) { 526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return i; 527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart+=length; 529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* we should never get here */ 531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(FALSE); 532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode = U_INVALID_STATE_ERROR; 533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Compute the runs array from the levels array. 538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * After ubidi_getRuns() returns TRUE, runCount is guaranteed to be >0 539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * and the runs are reordered. 540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Odd-level runs have visualStart on their visual right edge and 541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * they progress visually to the left. 542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * If option UBIDI_OPTION_INSERT_MARKS is set, insertRemove will contain the 543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * sum of appropriate LRM/RLM_BEFORE/AFTER flags. 544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * If option UBIDI_OPTION_REMOVE_CONTROLS is set, insertRemove will contain the 545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * negative number of BiDi control characters within this run. 546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CFUNC UBool 548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_getRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) { 549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This method returns immediately if the runs are already set. This 551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * includes the case of length==0 (handled in setPara).. 552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (pBiDi->runCount>=0) { 554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return TRUE; 555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->direction!=UBIDI_MIXED) { 558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* simple, single-run case - this covers length==0 */ 559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* pBiDi->paraLevel is ok even for contextual multiple paragraphs */ 560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) getSingleRun(pBiDi, pBiDi->paraLevel); 561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else /* UBIDI_MIXED, length>0 */ { 562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* mixed directionality */ 563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t length=pBiDi->length, limit; 564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel *levels=pBiDi->levels; 565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t i, runCount; 566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel level=UBIDI_DEFAULT_LTR; /* initialize with no valid level */ 567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * If there are WS characters at the end of the line 569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * and the run preceding them has a level different from 570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * paraLevel, then they will form their own run at paraLevel (L1). 571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Count them separately. 572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * We need some special treatment for this in order to not 573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * modify the levels array which a line UBiDi object shares 574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * with its paragraph parent and its other line siblings. 575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * In other words, for the trailing WS, it may be 576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * levels[]!=paraLevel but we have to treat it like it were so. 577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) limit=pBiDi->trailingWSStart; 579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* count the runs, there is at least one non-WS run, and limit>0 */ 580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runCount=0; 581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; i<limit; ++i) { 582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* increment runCount at the start of each run */ 583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(levels[i]!=level) { 584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++runCount; 585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) level=levels[i]; 586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 590f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * We don't need to see if the last run can be merged with a trailing 591f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * WS run because setTrailingWSStart() would have done that. 592f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 593f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(runCount==1 && limit==length) { 594f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* There is only one non-WS run and no trailing WS-run. */ 595f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) getSingleRun(pBiDi, levels[0]); 596f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else /* runCount>1 || limit<length */ { 597f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* allocate and set the runs */ 598f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run *runs; 599f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t runIndex, start; 600f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1, maxLevel=0; 601f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 602f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* now, count a (non-mergeable) WS run */ 603f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(limit<length) { 604f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++runCount; 605f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 606f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 607f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* runCount>1 */ 608f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(getRunsMemory(pBiDi, runCount)) { 609f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs=pBiDi->runsMemory; 610f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 611f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 612f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 613f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 614f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* set the runs */ 615f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* FOOD FOR THOUGHT: this could be optimized, e.g.: 616f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 464->444, 484->444, 575->555, 595->555 617f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * However, that would take longer. Check also how it would 618f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * interact with BiDi control removal and inserting Marks. 619f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 620f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runIndex=0; 621f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 622f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* search for the run limits and initialize visualLimit values with the run lengths */ 623f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) i=0; 624f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) do { 625f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* prepare this run */ 626f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) start=i; 627f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) level=levels[i]; 628f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(level<minLevel) { 629f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) minLevel=level; 630f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 631f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(level>maxLevel) { 632f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) maxLevel=level; 633f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 634f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 635f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for the run limit */ 636f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(++i<limit && levels[i]==level) {} 637f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 638f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* i is another run limit */ 639f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[runIndex].logicalStart=start; 640f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[runIndex].visualLimit=i-start; 641f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[runIndex].insertRemove=0; 642f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++runIndex; 643f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } while(i<limit); 644f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 645f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(limit<length) { 646f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* there is a separate WS run */ 647f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[runIndex].logicalStart=limit; 648f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[runIndex].visualLimit=length-limit; 649f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* For the trailing WS run, pBiDi->paraLevel is ok even 650f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if contextual multiple paragraphs. */ 651f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->paraLevel<minLevel) { 652f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) minLevel=pBiDi->paraLevel; 653f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 654f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 655f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 656f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* set the object fields */ 657f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runs=runs; 658f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runCount=runCount; 659f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 660f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) reorderLine(pBiDi, minLevel, maxLevel); 661f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 662f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* now add the direction flags and adjust the visualLimit's to be just that */ 663f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* this loop will also handle the trailing WS run */ 664f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) limit=0; 665f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; i<runCount; ++i) { 666f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ADD_ODD_BIT_FROM_LEVEL(runs[i].logicalStart, levels[runs[i].logicalStart]); 667f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) limit+=runs[i].visualLimit; 668f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs[i].visualLimit=limit; 669f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 670f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 671f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* Set the "odd" bit for the trailing WS run. */ 672f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* For a RTL paragraph, it will be the *first* run in visual order. */ 673f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* For the trailing WS run, pBiDi->paraLevel is ok even if 674f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) contextual multiple paragraphs. */ 675f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(runIndex<runCount) { 676f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t trailingRun = ((pBiDi->paraLevel & 1) != 0)? 0 : runIndex; 677f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 678f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ADD_ODD_BIT_FROM_LEVEL(runs[trailingRun].logicalStart, pBiDi->paraLevel); 679f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 680f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 681f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 682f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 683f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* handle insert LRM/RLM BEFORE/AFTER run */ 684f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->insertPoints.size>0) { 685f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Point *point, *start=pBiDi->insertPoints.points, 686f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *limit=start+pBiDi->insertPoints.size; 687f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t runIndex; 688f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(point=start; point<limit; point++) { 689f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runIndex=getRunFromLogicalIndex(pBiDi, point->pos, pErrorCode); 690f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runs[runIndex].insertRemove|=point->flag; 691f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 692f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 693f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 694f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* handle remove BiDi control characters */ 695f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->controlCount>0) { 696f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t runIndex; 697f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UChar *start=pBiDi->text, *limit=start+pBiDi->length, *pu; 698f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(pu=start; pu<limit; pu++) { 699f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_BIDI_CONTROL_CHAR(*pu)) { 700f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runIndex=getRunFromLogicalIndex(pBiDi, (int32_t)(pu-start), pErrorCode); 701f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pBiDi->runs[runIndex].insertRemove--; 702f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 703f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 704f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 705f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 706f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return TRUE; 707f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 708f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 709f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static UBool 710f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)prepareReorder(const UBiDiLevel *levels, int32_t length, 711f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t *indexMap, 712f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel *pMinLevel, UBiDiLevel *pMaxLevel) { 713f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t start; 714f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel level, minLevel, maxLevel; 715f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 716f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(levels==NULL || length<=0) { 717f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 718f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 719f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 720f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* determine minLevel and maxLevel */ 721f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1; 722f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) maxLevel=0; 723f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(start=length; start>0;) { 724f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) level=levels[--start]; 725f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(level>UBIDI_MAX_EXPLICIT_LEVEL+1) { 726f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 727f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 728f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(level<minLevel) { 729f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) minLevel=level; 730f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 731f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(level>maxLevel) { 732f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) maxLevel=level; 733f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 734f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 735f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pMinLevel=minLevel; 736f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pMaxLevel=maxLevel; 737f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 738f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* initialize the index map */ 739f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(start=length; start>0;) { 740f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --start; 741f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[start]=start; 742f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 743f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 744f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return TRUE; 745f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 746f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 747f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* reorder a line based on a levels array (L2) ------------------------------ */ 748f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 749f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 750f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_reorderLogical(const UBiDiLevel *levels, int32_t length, int32_t *indexMap) { 751f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t start, limit, sumOfSosEos; 752f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel minLevel = 0, maxLevel = 0; 753f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 754f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(indexMap==NULL || !prepareReorder(levels, length, indexMap, &minLevel, &maxLevel)) { 755f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 756f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 757f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 758f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* nothing to do? */ 759f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(minLevel==maxLevel && (minLevel&1)==0) { 760f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 761f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 762f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 763f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* reorder only down to the lowest odd level */ 764f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) minLevel|=1; 765f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 766f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* loop maxLevel..minLevel */ 767f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) do { 768f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) start=0; 769f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 770f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* loop for all sequences of levels to reorder at the current maxLevel */ 771f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(;;) { 772f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for a sequence of levels that are all at >=maxLevel */ 773f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for the first index of such a sequence */ 774f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(start<length && levels[start]<maxLevel) { 775f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++start; 776f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 777f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(start>=length) { 778f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; /* no more such sequences */ 779f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 780f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 781f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for the limit of such a sequence (the index behind it) */ 782f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(limit=start; ++limit<length && levels[limit]>=maxLevel;) {} 783f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 784f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 785f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * sos=start of sequence, eos=end of sequence 786f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 787f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The closed (inclusive) interval from sos to eos includes all the logical 788f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * and visual indexes within this sequence. They are logically and 789f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * visually contiguous and in the same range. 790f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 791f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * For each run, the new visual index=sos+eos-old visual index; 792f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * we pre-add sos+eos into sumOfSosEos -> 793f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * new visual index=sumOfSosEos-old visual index; 794f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 795f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) sumOfSosEos=start+limit-1; 796f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 797f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* reorder each index in the sequence */ 798f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) do { 799f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[start]=sumOfSosEos-indexMap[start]; 800f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } while(++start<limit); 801f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 802f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* start==limit */ 803f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(limit==length) { 804f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; /* no more such sequences */ 805f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 806f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) start=limit+1; 807f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 808f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 809f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } while(--maxLevel>=minLevel); 810f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 811f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 812f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 813f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_reorderVisual(const UBiDiLevel *levels, int32_t length, int32_t *indexMap) { 814f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t start, end, limit, temp; 815f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBiDiLevel minLevel = 0, maxLevel = 0; 816f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 817f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(indexMap==NULL || !prepareReorder(levels, length, indexMap, &minLevel, &maxLevel)) { 818f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 819f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 820f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 821f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* nothing to do? */ 822f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(minLevel==maxLevel && (minLevel&1)==0) { 823f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 824f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 825f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 826f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* reorder only down to the lowest odd level */ 827f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) minLevel|=1; 828f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 829f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* loop maxLevel..minLevel */ 830f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) do { 831f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) start=0; 832f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 833f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* loop for all sequences of levels to reorder at the current maxLevel */ 834f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(;;) { 835f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for a sequence of levels that are all at >=maxLevel */ 836f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for the first index of such a sequence */ 837f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(start<length && levels[start]<maxLevel) { 838f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++start; 839f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 840f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(start>=length) { 841f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; /* no more such runs */ 842f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 843f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 844f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* look for the limit of such a sequence (the index behind it) */ 845f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(limit=start; ++limit<length && levels[limit]>=maxLevel;) {} 846f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 847f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 848f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Swap the entire interval of indexes from start to limit-1. 849f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * We don't need to swap the levels for the purpose of this 850f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * algorithm: the sequence of levels that we look at does not 851f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * move anyway. 852f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 853f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) end=limit-1; 854f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(start<end) { 855f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) temp=indexMap[start]; 856f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[start]=indexMap[end]; 857f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[end]=temp; 858f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 859f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ++start; 860f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --end; 861f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 862f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 863f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(limit==length) { 864f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; /* no more such sequences */ 865f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 866f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) start=limit+1; 867f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 868f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 869f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } while(--maxLevel>=minLevel); 870f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 871f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 872f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* API functions for logical<->visual mapping ------------------------------- */ 873f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 874f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2 875f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_getVisualIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode) { 876f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t visualIndex=UBIDI_MAP_NOWHERE; 877f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1); 878f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1); 879f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_BAD_RANGE(logicalIndex, 0, pBiDi->length, *pErrorCode, -1); 880f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 881f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* we can do the trivial cases without the runs array */ 882f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) switch(pBiDi->direction) { 883f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case UBIDI_LTR: 884f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualIndex=logicalIndex; 885f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 886f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case UBIDI_RTL: 887f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualIndex=pBiDi->length-logicalIndex-1; 888f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 889f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) default: 890f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(!ubidi_getRuns(pBiDi, pErrorCode)) { 891f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_MEMORY_ALLOCATION_ERROR; 892f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return -1; 893f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 894f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run *runs=pBiDi->runs; 895f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t i, visualStart=0, offset, length; 896f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 897f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* linear search for the run, search on the visual runs */ 898f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; i<pBiDi->runCount; ++i) { 899f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=runs[i].visualLimit-visualStart; 900f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) offset=logicalIndex-GET_INDEX(runs[i].logicalStart); 901f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(offset>=0 && offset<length) { 902f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_EVEN_RUN(runs[i].logicalStart)) { 903f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* LTR */ 904f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualIndex=visualStart+offset; 905f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 906f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* RTL */ 907f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualIndex=visualStart+length-offset-1; 908f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 909f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; /* exit for loop */ 910f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 911f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart+=length; 912f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 913f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(i>=pBiDi->runCount) { 914f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return UBIDI_MAP_NOWHERE; 915f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 916f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 917f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 918f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 919f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->insertPoints.size>0) { 920f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* add the number of added marks until the calculated visual index */ 921f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run *runs=pBiDi->runs; 922f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t i, length, insertRemove; 923f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t visualStart=0, markFound=0; 924f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; ; i++, visualStart+=length) { 925f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=runs[i].visualLimit-visualStart; 926f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) insertRemove=runs[i].insertRemove; 927f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove & (LRM_BEFORE|RLM_BEFORE)) { 928f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound++; 929f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 930f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* is it the run containing the visual index? */ 931f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(visualIndex<runs[i].visualLimit) { 932f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return visualIndex+markFound; 933f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 934f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove & (LRM_AFTER|RLM_AFTER)) { 935f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound++; 936f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 937f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 938f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 939f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if(pBiDi->controlCount>0) { 940f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* subtract the number of controls until the calculated visual index */ 941f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run *runs=pBiDi->runs; 942f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t i, j, start, limit, length, insertRemove; 943f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t visualStart=0, controlFound=0; 944f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UChar uchar=pBiDi->text[logicalIndex]; 945f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* is the logical index pointing to a control ? */ 946f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_BIDI_CONTROL_CHAR(uchar)) { 947f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return UBIDI_MAP_NOWHERE; 948f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 949f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* loop on runs */ 950f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; ; i++, visualStart+=length) { 951f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=runs[i].visualLimit-visualStart; 952f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) insertRemove=runs[i].insertRemove; 953f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* calculated visual index is beyond this run? */ 954f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(visualIndex>=runs[i].visualLimit) { 955f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) controlFound-=insertRemove; 956f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) continue; 957f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 958f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* calculated visual index must be within current run */ 959f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove==0) { 960f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return visualIndex-controlFound; 961f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 962f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_EVEN_RUN(runs[i].logicalStart)) { 963f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* LTR: check from run start to logical index */ 964f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) start=runs[i].logicalStart; 965f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) limit=logicalIndex; 966f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 967f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* RTL: check from logical index to run end */ 968f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) start=logicalIndex+1; 969f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) limit=GET_INDEX(runs[i].logicalStart)+length; 970f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 971f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=start; j<limit; j++) { 972f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uchar=pBiDi->text[j]; 973f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_BIDI_CONTROL_CHAR(uchar)) { 974f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) controlFound++; 975f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 976f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 977f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return visualIndex-controlFound; 978f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 979f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 980f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 981f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return visualIndex; 982f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 983f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 984f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2 985f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_getLogicalIndex(UBiDi *pBiDi, int32_t visualIndex, UErrorCode *pErrorCode) { 986f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run *runs; 987f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t i, runCount, start; 988f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1); 989f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1); 990f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_IF_BAD_RANGE(visualIndex, 0, pBiDi->resultLength, *pErrorCode, -1); 991f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* we can do the trivial cases without the runs array */ 992f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->insertPoints.size==0 && pBiDi->controlCount==0) { 993f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->direction==UBIDI_LTR) { 994f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return visualIndex; 995f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 996f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if(pBiDi->direction==UBIDI_RTL) { 997f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return pBiDi->length-visualIndex-1; 998f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 999f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1000f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(!ubidi_getRuns(pBiDi, pErrorCode)) { 1001f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_MEMORY_ALLOCATION_ERROR; 1002f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return -1; 1003f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1004f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1005f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs=pBiDi->runs; 1006f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runCount=pBiDi->runCount; 1007f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->insertPoints.size>0) { 1008f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* handle inserted LRM/RLM */ 1009f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t markFound=0, insertRemove; 1010f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t visualStart=0, length; 1011f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs=pBiDi->runs; 1012f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* subtract number of marks until visual index */ 1013f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; ; i++, visualStart+=length) { 1014f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=runs[i].visualLimit-visualStart; 1015f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) insertRemove=runs[i].insertRemove; 1016f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) { 1017f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(visualIndex<=(visualStart+markFound)) { 1018f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return UBIDI_MAP_NOWHERE; 1019f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1020f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound++; 1021f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1022f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* is adjusted visual index within this run? */ 1023f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(visualIndex<(runs[i].visualLimit+markFound)) { 1024f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualIndex-=markFound; 1025f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 1026f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1027f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove&(LRM_AFTER|RLM_AFTER)) { 1028f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(visualIndex==(visualStart+length+markFound)) { 1029f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return UBIDI_MAP_NOWHERE; 1030f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1031f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound++; 1032f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1033f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1034f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1035f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if(pBiDi->controlCount>0) { 1036f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* handle removed BiDi control characters */ 1037f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t controlFound=0, insertRemove, length; 1038f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t logicalStart, logicalEnd, visualStart=0, j, k; 1039f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UChar uchar; 1040f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool evenRun; 1041f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* add number of controls until visual index */ 1042f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; ; i++, visualStart+=length) { 1043f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=runs[i].visualLimit-visualStart; 1044f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) insertRemove=runs[i].insertRemove; 1045f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* is adjusted visual index beyond current run? */ 1046f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(visualIndex>=(runs[i].visualLimit-controlFound+insertRemove)) { 1047f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) controlFound-=insertRemove; 1048f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) continue; 1049f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1050f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* adjusted visual index is within current run */ 1051f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove==0) { 1052f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualIndex+=controlFound; 1053f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 1054f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1055f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* count non-control chars until visualIndex */ 1056f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalStart=runs[i].logicalStart; 1057f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) evenRun=IS_EVEN_RUN(logicalStart); 1058f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) REMOVE_ODD_BIT(logicalStart); 1059f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalEnd=logicalStart+length-1; 1060f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=0; j<length; j++) { 1061f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) k= evenRun ? logicalStart+j : logicalEnd-j; 1062f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uchar=pBiDi->text[k]; 1063f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_BIDI_CONTROL_CHAR(uchar)) { 1064f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) controlFound++; 1065f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1066f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if((visualIndex+controlFound)==(visualStart+j)) { 1067f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 1068f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1069f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1070f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualIndex+=controlFound; 1071f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 1072f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1073f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1074f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* handle all cases */ 1075f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(runCount<=10) { 1076f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* linear search for the run */ 1077f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; visualIndex>=runs[i].visualLimit; ++i) {} 1078f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 1079f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* binary search for the run */ 1080f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t begin=0, limit=runCount; 1081f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1082f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* the middle if() is guaranteed to find the run, we don't need a loop limit */ 1083f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(;;) { 1084f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) i=(begin+limit)/2; 1085f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(visualIndex>=runs[i].visualLimit) { 1086f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) begin=i+1; 1087f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if(i==0 || visualIndex>=runs[i-1].visualLimit) { 1088f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 1089f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 1090f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) limit=i; 1091f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1092f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1093f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1094f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1095f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) start=runs[i].logicalStart; 1096f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_EVEN_RUN(start)) { 1097f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* LTR */ 1098f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* the offset in runs[i] is visualIndex-runs[i-1].visualLimit */ 1099f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(i>0) { 1100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualIndex-=runs[i-1].visualLimit; 1101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return start+visualIndex; 1103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 1104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* RTL */ 1105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return GET_INDEX(start)+runs[i].visualLimit-visualIndex-1; 1106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 1110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) { 1111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode); 1112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* ubidi_countRuns() checks for VALID_PARA_OR_LINE */ 1113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ubidi_countRuns(pBiDi, pErrorCode); 1114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(*pErrorCode)) { 1115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* no op */ 1116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if(indexMap==NULL) { 1117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 1119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* fill a logical-to-visual index map using the runs[] */ 1120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t visualStart, visualLimit, i, j, k; 1121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t logicalStart, logicalLimit; 1122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run *runs=pBiDi->runs; 1123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (pBiDi->length<=0) { 1124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 1125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (pBiDi->length>pBiDi->resultLength) { 1127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memset(indexMap, 0xFF, pBiDi->length*sizeof(int32_t)); 1128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart=0; 1131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=0; j<pBiDi->runCount; ++j) { 1132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalStart=GET_INDEX(runs[j].logicalStart); 1133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualLimit=runs[j].visualLimit; 1134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_EVEN_RUN(runs[j].logicalStart)) { 1135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) do { /* LTR */ 1136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[logicalStart++]=visualStart++; 1137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } while(visualStart<visualLimit); 1138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 1139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalStart+=visualLimit-visualStart; /* logicalLimit */ 1140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) do { /* RTL */ 1141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[--logicalStart]=visualStart++; 1142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } while(visualStart<visualLimit); 1143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* visualStart==visualLimit; */ 1145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->insertPoints.size>0) { 1148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t markFound=0, runCount=pBiDi->runCount; 1149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t length, insertRemove; 1150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart=0; 1151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* add number of marks found until each index */ 1152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; i<runCount; i++, visualStart+=length) { 1153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=runs[i].visualLimit-visualStart; 1154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) insertRemove=runs[i].insertRemove; 1155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) { 1156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound++; 1157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(markFound>0) { 1159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalStart=GET_INDEX(runs[i].logicalStart); 1160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalLimit=logicalStart+length; 1161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=logicalStart; j<logicalLimit; j++) { 1162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[j]+=markFound; 1163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove&(LRM_AFTER|RLM_AFTER)) { 1166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound++; 1167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if(pBiDi->controlCount>0) { 1171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t controlFound=0, runCount=pBiDi->runCount; 1172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t length, insertRemove; 1173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool evenRun; 1174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UChar uchar; 1175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart=0; 1176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* subtract number of controls found until each index */ 1177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; i<runCount; i++, visualStart+=length) { 1178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=runs[i].visualLimit-visualStart; 1179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) insertRemove=runs[i].insertRemove; 1180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* no control found within previous runs nor within this run */ 1181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if((controlFound-insertRemove)==0) { 1182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) continue; 1183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalStart=runs[i].logicalStart; 1185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) evenRun=IS_EVEN_RUN(logicalStart); 1186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) REMOVE_ODD_BIT(logicalStart); 1187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalLimit=logicalStart+length; 1188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* if no control within this run */ 1189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove==0) { 1190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=logicalStart; j<logicalLimit; j++) { 1191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[j]-=controlFound; 1192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) continue; 1194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=0; j<length; j++) { 1196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) k= evenRun ? logicalStart+j : logicalLimit-j-1; 1197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uchar=pBiDi->text[k]; 1198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_BIDI_CONTROL_CHAR(uchar)) { 1199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) controlFound++; 1200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[k]=UBIDI_MAP_NOWHERE; 1201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) continue; 1202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[k]-=controlFound; 1204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 1211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_getVisualMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) { 1212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode); 1213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(indexMap==NULL) { 1214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 1216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* ubidi_countRuns() checks for VALID_PARA_OR_LINE */ 1218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ubidi_countRuns(pBiDi, pErrorCode); 1219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_SUCCESS(*pErrorCode)) { 1220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* fill a visual-to-logical index map using the runs[] */ 1221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Run *runs=pBiDi->runs, *runsLimit=runs+pBiDi->runCount; 1222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t logicalStart, visualStart, visualLimit, *pi=indexMap; 1223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (pBiDi->resultLength<=0) { 1225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 1226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart=0; 1228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(; runs<runsLimit; ++runs) { 1229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalStart=runs->logicalStart; 1230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualLimit=runs->visualLimit; 1231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(IS_EVEN_RUN(logicalStart)) { 1232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) do { /* LTR */ 1233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pi++ = logicalStart++; 1234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } while(++visualStart<visualLimit); 1235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 1236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) REMOVE_ODD_BIT(logicalStart); 1237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalStart+=visualLimit-visualStart; /* logicalLimit */ 1238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) do { /* RTL */ 1239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pi++ = --logicalStart; 1240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } while(++visualStart<visualLimit); 1241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* visualStart==visualLimit; */ 1243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pBiDi->insertPoints.size>0) { 1246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t markFound=0, runCount=pBiDi->runCount; 1247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t insertRemove, i, j, k; 1248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs=pBiDi->runs; 1249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* count all inserted marks */ 1250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; i<runCount; i++) { 1251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) insertRemove=runs[i].insertRemove; 1252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) { 1253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound++; 1254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove&(LRM_AFTER|RLM_AFTER)) { 1256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound++; 1257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* move back indexes by number of preceding marks */ 1260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) k=pBiDi->resultLength; 1261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=runCount-1; i>=0 && markFound>0; i--) { 1262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) insertRemove=runs[i].insertRemove; 1263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove&(LRM_AFTER|RLM_AFTER)) { 1264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[--k]= UBIDI_MAP_NOWHERE; 1265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound--; 1266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart= i>0 ? runs[i-1].visualLimit : 0; 1268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=runs[i].visualLimit-1; j>=visualStart && markFound>0; j--) { 1269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[--k]=indexMap[j]; 1270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) { 1272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[--k]= UBIDI_MAP_NOWHERE; 1273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) markFound--; 1274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if(pBiDi->controlCount>0) { 1278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t runCount=pBiDi->runCount, logicalEnd; 1279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t insertRemove, length, i, j, k, m; 1280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UChar uchar; 1281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool evenRun; 1282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) runs=pBiDi->runs; 1283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualStart=0; 1284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* move forward indexes by number of preceding controls */ 1285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) k=0; 1286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(i=0; i<runCount; i++, visualStart+=length) { 1287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length=runs[i].visualLimit-visualStart; 1288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) insertRemove=runs[i].insertRemove; 1289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* if no control found yet, nothing to do in this run */ 1290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if((insertRemove==0)&&(k==visualStart)) { 1291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) k+=length; 1292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) continue; 1293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* if no control in this run */ 1295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(insertRemove==0) { 1296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) visualLimit=runs[i].visualLimit; 1297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=visualStart; j<visualLimit; j++) { 1298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[k++]=indexMap[j]; 1299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) continue; 1301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalStart=runs[i].logicalStart; 1303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) evenRun=IS_EVEN_RUN(logicalStart); 1304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) REMOVE_ODD_BIT(logicalStart); 1305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) logicalEnd=logicalStart+length-1; 1306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(j=0; j<length; j++) { 1307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) m= evenRun ? logicalStart+j : logicalEnd-j; 1308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uchar=pBiDi->text[m]; 1309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(!IS_BIDI_CONTROL_CHAR(uchar)) { 1310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) indexMap[k++]=m; 1311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 1319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ubidi_invertMap(const int32_t *srcMap, int32_t *destMap, int32_t length) { 1320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(srcMap!=NULL && destMap!=NULL && length>0) { 1321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const int32_t *pi; 1322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t destLength=-1, count=0; 1323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* find highest value and count positive indexes in srcMap */ 1324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pi=srcMap+length; 1325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(pi>srcMap) { 1326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(*--pi>destLength) { 1327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) destLength=*pi; 1328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(*pi>=0) { 1330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) count++; 1331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) destLength++; /* add 1 for origin 0 */ 1334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(count<destLength) { 1335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* we must fill unmatched destMap entries with -1 */ 1336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memset(destMap, 0xFF, destLength*sizeof(int32_t)); 1337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pi=srcMap+length; 1339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while(length>0) { 1340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(*--pi>=0) { 1341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) destMap[*pi]=--length; 1342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 1343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --length; 1344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1348