< prev index next >

jdk/src/java.base/share/classes/sun/text/bidi/BidiLine.java

Print this page


   1 /*
   2  * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */

  25 /*
  26  *******************************************************************************
  27  * (C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved         *
  28  *                                                                             *
  29  * The original version of this source code and documentation is copyrighted   *
  30  * and owned by IBM, These materials are provided under terms of a License     *
  31  * Agreement between IBM and Sun. This technology is protected by multiple     *
  32  * US and International patents. This notice and attribution to IBM may not    *
  33  * to removed.                                                                 *
  34  *******************************************************************************
  35  */
  36 /* Written by Simon Montagu, Matitiahu Allouche
  37  * (ported from C code written by Markus W. Scherer)
  38  */
  39 
  40 package sun.text.bidi;
  41 
  42 import java.text.Bidi;
  43 import java.util.Arrays;
  44 
  45 public final class BidiLine {
  46 
  47     /*
  48      * General remarks about the functions in this file:
  49      *
  50      * These functions deal with the aspects of potentially mixed-directional
  51      * text in a single paragraph or in a line of a single paragraph
  52      * which has already been processed according to
  53      * the Unicode 3.0 Bidi algorithm as defined in
  54      * http://www.unicode.org/unicode/reports/tr9/ , version 13,
  55      * also described in The Unicode Standard, Version 4.0.1 .
  56      *
  57      * This means that there is a Bidi object with a levels
  58      * and a dirProps array.
  59      * paraLevel and direction are also set.
  60      * Only if the length of the text is zero, then levels==dirProps==NULL.
  61      *
  62      * The overall directionality of the paragraph
  63      * or line is used to bypass the reordering steps if possible.
  64      * Even purely RTL text does not need reordering there because
  65      * the getLogical/VisualIndex() methods can compute the


 105      * To make subsequent operations easier, we also include the run
 106      * before the WS if it is at the paraLevel - we merge the two here.
 107      *
 108      * This method is called only from setLine(), so paraLevel is
 109      * set correctly for the line even when contextual multiple paragraphs.
 110      */
 111 
 112     static void setTrailingWSStart(BidiBase bidiBase)
 113     {
 114         byte[] dirProps = bidiBase.dirProps;
 115         byte[] levels = bidiBase.levels;
 116         int start = bidiBase.length;
 117         byte paraLevel = bidiBase.paraLevel;
 118 
 119         /* If the line is terminated by a block separator, all preceding WS etc...
 120            are already set to paragraph level.
 121            Setting trailingWSStart to pBidi->length will avoid changing the
 122            level of B chars from 0 to paraLevel in getLevels when
 123            orderParagraphsLTR==TRUE
 124         */
 125         if (BidiBase.NoContextRTL(dirProps[start - 1]) == BidiBase.B) {
 126             bidiBase.trailingWSStart = start;   /* currently == bidiBase.length */
 127             return;
 128         }
 129         /* go backwards across all WS, BN, explicit codes */
 130         while (start > 0 &&
 131                 (BidiBase.DirPropFlagNC(dirProps[start - 1]) & BidiBase.MASK_WS) != 0) {
 132             --start;
 133         }
 134 
 135         /* if the WS run can be merged with the previous run then do so here */
 136         while (start > 0 && levels[start - 1] == paraLevel) {
 137             --start;
 138         }
 139 
 140         bidiBase.trailingWSStart=start;
 141     }
 142 
 143     public static Bidi setLine(Bidi bidi, BidiBase paraBidi,
 144                                Bidi newBidi, BidiBase newBidiBase,
 145                                int start, int limit) {
 146         int length;
 147 
 148         BidiBase lineBidi = newBidiBase;
 149 
 150         /* set the values in lineBidi from its paraBidi parent */
 151         /* class members are already initialized to 0 */
 152         // lineBidi.paraBidi = null;        /* mark unfinished setLine */
 153         // lineBidi.flags = 0;
 154         // lineBidi.controlCount = 0;
 155 
 156         length = lineBidi.length = lineBidi.originalLength =
 157                 lineBidi.resultLength = limit - start;
 158 
 159         lineBidi.text = new char[length];
 160         System.arraycopy(paraBidi.text, start, lineBidi.text, 0, length);
 161         lineBidi.paraLevel = paraBidi.GetParaLevelAt(start);
 162         lineBidi.paraCount = paraBidi.paraCount;
 163         lineBidi.runs = new BidiRun[0];


 164         if (paraBidi.controlCount > 0) {
 165             int j;
 166             for (j = start; j < limit; j++) {
 167                 if (BidiBase.IsBidiControlChar(paraBidi.text[j])) {
 168                     lineBidi.controlCount++;
 169                 }
 170             }
 171             lineBidi.resultLength -= lineBidi.controlCount;
 172         }
 173         /* copy proper subset of DirProps */
 174         lineBidi.getDirPropsMemory(length);
 175         lineBidi.dirProps = lineBidi.dirPropsMemory;
 176         System.arraycopy(paraBidi.dirProps, start, lineBidi.dirProps, 0,
 177                          length);
 178         /* copy proper subset of Levels */
 179         lineBidi.getLevelsMemory(length);
 180         lineBidi.levels = lineBidi.levelsMemory;
 181         System.arraycopy(paraBidi.levels, start, lineBidi.levels, 0,
 182                          length);
 183         lineBidi.runCount = -1;


 189             /*
 190              * The parent's levels are all either
 191              * implicitly or explicitly ==paraLevel;
 192              * do the same here.
 193              */
 194             if (paraBidi.trailingWSStart <= start) {
 195                 lineBidi.trailingWSStart = 0;
 196             } else if (paraBidi.trailingWSStart < limit) {
 197                 lineBidi.trailingWSStart = paraBidi.trailingWSStart - start;
 198             } else {
 199                 lineBidi.trailingWSStart = length;
 200             }
 201         } else {
 202             byte[] levels = lineBidi.levels;
 203             int i, trailingWSStart;
 204             byte level;
 205 
 206             setTrailingWSStart(lineBidi);
 207             trailingWSStart = lineBidi.trailingWSStart;
 208 
 209             /* recalculate lineBidi.direction */
 210             if (trailingWSStart == 0) {
 211                 /* all levels are at paraLevel */
 212                 lineBidi.direction = (byte)(lineBidi.paraLevel & 1);
 213             } else {
 214                 /* get the level of the first character */
 215                 level = (byte)(levels[0] & 1);
 216 
 217                 /* if there is anything of a different level, then the line
 218                    is mixed */
 219                 if (trailingWSStart < length &&
 220                     (lineBidi.paraLevel & 1) != level) {
 221                     /* the trailing WS is at paraLevel, which differs from
 222                        levels[0] */
 223                     lineBidi.direction = BidiBase.MIXED;
 224                 } else {
 225                     /* see if levels[1..trailingWSStart-1] have the same
 226                        direction as levels[0] and paraLevel */
 227                     for (i = 1; ; i++) {
 228                         if (i == trailingWSStart) {
 229                             /* the direction values match those in level */


 243                     lineBidi.paraLevel = (byte)
 244                         ((lineBidi.paraLevel + 1) & ~1);
 245 
 246                     /* all levels are implicitly at paraLevel (important for
 247                        getLevels()) */
 248                     lineBidi.trailingWSStart = 0;
 249                     break;
 250                 case Bidi.DIRECTION_RIGHT_TO_LEFT:
 251                     /* make sure paraLevel is odd */
 252                     lineBidi.paraLevel |= 1;
 253 
 254                     /* all levels are implicitly at paraLevel (important for
 255                        getLevels()) */
 256                     lineBidi.trailingWSStart = 0;
 257                     break;
 258                 default:
 259                     break;
 260             }
 261         }
 262 
 263         newBidiBase.paraBidi = paraBidi; /* mark successful setLine */

 264         return newBidi;
 265     }
 266 
 267     static byte getLevelAt(BidiBase bidiBase, int charIndex)
 268     {
 269         /* return paraLevel if in the trailing WS run, otherwise the real level */
 270         if (bidiBase.direction != BidiBase.MIXED || charIndex >= bidiBase.trailingWSStart) {
 271             return bidiBase.GetParaLevelAt(charIndex);
 272         } else {
 273             return bidiBase.levels[charIndex];
 274         }
 275     }
 276 
 277     static byte[] getLevels(BidiBase bidiBase)
 278     {
 279         int start = bidiBase.trailingWSStart;
 280         int length = bidiBase.length;
 281 
 282         if (start != length) {
 283             /* the current levels array does not reflect the WS run */


 286              * has an implicit trailing WS run and therefore does not fully
 287              * reflect itself all the levels.
 288              * This must be a Bidi object for a line, and
 289              * we need to create a new levels array.
 290              */
 291             /* bidiBase.paraLevel is ok even if contextual multiple paragraphs,
 292                since bidiBase is a line object                                     */
 293             Arrays.fill(bidiBase.levels, start, length, bidiBase.paraLevel);
 294 
 295             /* this new levels array is set for the line and reflects the WS run */
 296             bidiBase.trailingWSStart = length;
 297         }
 298         if (length < bidiBase.levels.length) {
 299             byte[] levels = new byte[length];
 300             System.arraycopy(bidiBase.levels, 0, levels, 0, length);
 301             return levels;
 302         }
 303         return bidiBase.levels;
 304     }
 305 
 306     static BidiRun getLogicalRun(BidiBase bidiBase, int logicalPosition)
 307     {
 308         /* this is done based on runs rather than on levels since levels have
 309            a special interpretation when REORDER_RUNS_ONLY
 310          */
 311         BidiRun newRun = new BidiRun(), iRun;
 312         getRuns(bidiBase);
 313         int runCount = bidiBase.runCount;
 314         int visualStart = 0, logicalLimit = 0;
 315         iRun = bidiBase.runs[0];
 316 
 317         for (int i = 0; i < runCount; i++) {
 318             iRun = bidiBase.runs[i];
 319             logicalLimit = iRun.start + iRun.limit - visualStart;
 320             if ((logicalPosition >= iRun.start) &&
 321                 (logicalPosition < logicalLimit)) {
 322                 break;
 323             }
 324             visualStart = iRun.limit;
 325         }
 326         newRun.start = iRun.start;
 327         newRun.limit = logicalLimit;
 328         newRun.level = iRun.level;
 329         return newRun;
 330     }
 331 
 332     /* in trivial cases there is only one trivial run; called by getRuns() */
 333     private static void getSingleRun(BidiBase bidiBase, byte level) {
 334         /* simple, single-run case */
 335         bidiBase.runs = bidiBase.simpleRuns;
 336         bidiBase.runCount = 1;
 337 
 338         /* fill and reorder the single run */
 339         bidiBase.runs[0] = new BidiRun(0, bidiBase.length, level);
 340     }
 341 
 342     /* reorder the runs array (L2) ---------------------------------------------- */
 343 
 344     /*
 345      * Reorder the same-level runs in the runs array.
 346      * Here, runCount>1 and maxLevel>=minLevel>=paraLevel.
 347      * All the visualStart fields=logical start before reordering.
 348      * The "odd" bits are not set yet.
 349      *


 485      * If option OPTION_REMOVE_CONTROLS is set, insertRemove will contain the
 486      * negative number of BiDi control characters within this run.
 487      */
 488     static void getRuns(BidiBase bidiBase) {
 489         /*
 490          * This method returns immediately if the runs are already set. This
 491          * includes the case of length==0 (handled in setPara)..
 492          */
 493         if (bidiBase.runCount >= 0) {
 494             return;
 495         }
 496         if (bidiBase.direction != BidiBase.MIXED) {
 497             /* simple, single-run case - this covers length==0 */
 498             /* bidiBase.paraLevel is ok even for contextual multiple paragraphs */
 499             getSingleRun(bidiBase, bidiBase.paraLevel);
 500         } else /* BidiBase.MIXED, length>0 */ {
 501             /* mixed directionality */
 502             int length = bidiBase.length, limit;
 503             byte[] levels = bidiBase.levels;
 504             int i, runCount;
 505             byte level = BidiBase.INTERNAL_LEVEL_DEFAULT_LTR;   /* initialize with no valid level */
 506             /*
 507              * If there are WS characters at the end of the line
 508              * and the run preceding them has a level different from
 509              * paraLevel, then they will form their own run at paraLevel (L1).
 510              * Count them separately.
 511              * We need some special treatment for this in order to not
 512              * modify the levels array which a line Bidi object shares
 513              * with its paragraph parent and its other line siblings.
 514              * In other words, for the trailing WS, it may be
 515              * levels[]!=paraLevel but we have to treat it like it were so.
 516              */
 517             limit = bidiBase.trailingWSStart;
 518             /* count the runs, there is at least one non-WS run, and limit>0 */
 519             runCount = 0;
 520             for (i = 0; i < limit; ++i) {
 521                 /* increment runCount at the start of each run */
 522                 if (levels[i] != level) {
 523                     ++runCount;
 524                     level = levels[i];
 525                 }


 634                     bidiBase.runs[runIndex].insertRemove--;
 635                 }
 636             }
 637         }
 638     }
 639 
 640     static int[] prepareReorder(byte[] levels, byte[] pMinLevel, byte[] pMaxLevel)
 641     {
 642         int start;
 643         byte level, minLevel, maxLevel;
 644 
 645         if (levels == null || levels.length <= 0) {
 646             return null;
 647         }
 648 
 649         /* determine minLevel and maxLevel */
 650         minLevel = BidiBase.MAX_EXPLICIT_LEVEL + 1;
 651         maxLevel = 0;
 652         for (start = levels.length; start>0; ) {
 653             level = levels[--start];
 654             if (level > BidiBase.MAX_EXPLICIT_LEVEL + 1) {
 655                 return null;
 656             }
 657             if (level < minLevel) {
 658                 minLevel = level;
 659             }
 660             if (level > maxLevel) {
 661                 maxLevel = level;
 662             }
 663         }
 664         pMinLevel[0] = minLevel;
 665         pMaxLevel[0] = maxLevel;
 666 
 667         /* initialize the index map */
 668         int[] indexMap = new int[levels.length];
 669         for (start = levels.length; start > 0; ) {
 670             --start;
 671             indexMap[start] = start;
 672         }
 673 
 674         return indexMap;


   1 /*
   2  * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27 *******************************************************************************
  28 *   Copyright (C) 2001-2014, International Business Machines
  29 *   Corporation and others.  All Rights Reserved.
  30 *******************************************************************************
  31 */





  32 /* Written by Simon Montagu, Matitiahu Allouche
  33  * (ported from C code written by Markus W. Scherer)
  34  */
  35 
  36 package sun.text.bidi;
  37 
  38 import java.text.Bidi;
  39 import java.util.Arrays;
  40 
  41 final class BidiLine {
  42 
  43     /*
  44      * General remarks about the functions in this file:
  45      *
  46      * These functions deal with the aspects of potentially mixed-directional
  47      * text in a single paragraph or in a line of a single paragraph
  48      * which has already been processed according to
  49      * the Unicode 3.0 Bidi algorithm as defined in
  50      * http://www.unicode.org/unicode/reports/tr9/ , version 13,
  51      * also described in The Unicode Standard, Version 4.0.1 .
  52      *
  53      * This means that there is a Bidi object with a levels
  54      * and a dirProps array.
  55      * paraLevel and direction are also set.
  56      * Only if the length of the text is zero, then levels==dirProps==NULL.
  57      *
  58      * The overall directionality of the paragraph
  59      * or line is used to bypass the reordering steps if possible.
  60      * Even purely RTL text does not need reordering there because
  61      * the getLogical/VisualIndex() methods can compute the


 101      * To make subsequent operations easier, we also include the run
 102      * before the WS if it is at the paraLevel - we merge the two here.
 103      *
 104      * This method is called only from setLine(), so paraLevel is
 105      * set correctly for the line even when contextual multiple paragraphs.
 106      */
 107 
 108     static void setTrailingWSStart(BidiBase bidiBase)
 109     {
 110         byte[] dirProps = bidiBase.dirProps;
 111         byte[] levels = bidiBase.levels;
 112         int start = bidiBase.length;
 113         byte paraLevel = bidiBase.paraLevel;
 114 
 115         /* If the line is terminated by a block separator, all preceding WS etc...
 116            are already set to paragraph level.
 117            Setting trailingWSStart to pBidi->length will avoid changing the
 118            level of B chars from 0 to paraLevel in getLevels when
 119            orderParagraphsLTR==TRUE
 120         */
 121         if (dirProps[start - 1] == BidiBase.B) {
 122             bidiBase.trailingWSStart = start;   /* currently == bidiBase.length */
 123             return;
 124         }
 125         /* go backwards across all WS, BN, explicit codes */
 126         while (start > 0 &&
 127                 (BidiBase.DirPropFlag(dirProps[start - 1]) & BidiBase.MASK_WS) != 0) {
 128             --start;
 129         }
 130 
 131         /* if the WS run can be merged with the previous run then do so here */
 132         while (start > 0 && levels[start - 1] == paraLevel) {
 133             --start;
 134         }
 135 
 136         bidiBase.trailingWSStart=start;
 137     }
 138 
 139     static Bidi setLine(BidiBase paraBidi,
 140                               Bidi newBidi, BidiBase lineBidi,
 141                               int start, int limit) {
 142         int length;
 143 


 144         /* set the values in lineBidi from its paraBidi parent */
 145         /* class members are already initialized to 0 */
 146         // lineBidi.paraBidi = null;        /* mark unfinished setLine */
 147         // lineBidi.flags = 0;
 148         // lineBidi.controlCount = 0;
 149 
 150         length = lineBidi.length = lineBidi.originalLength =
 151                 lineBidi.resultLength = limit - start;
 152 
 153         lineBidi.text = new char[length];
 154         System.arraycopy(paraBidi.text, start, lineBidi.text, 0, length);
 155         lineBidi.paraLevel = paraBidi.GetParaLevelAt(start);
 156         lineBidi.paraCount = paraBidi.paraCount;
 157         lineBidi.runs = new BidiRun[0];
 158         lineBidi.reorderingMode = paraBidi.reorderingMode;
 159         lineBidi.reorderingOptions = paraBidi.reorderingOptions;
 160         if (paraBidi.controlCount > 0) {
 161             int j;
 162             for (j = start; j < limit; j++) {
 163                 if (BidiBase.IsBidiControlChar(paraBidi.text[j])) {
 164                     lineBidi.controlCount++;
 165                 }
 166             }
 167             lineBidi.resultLength -= lineBidi.controlCount;
 168         }
 169         /* copy proper subset of DirProps */
 170         lineBidi.getDirPropsMemory(length);
 171         lineBidi.dirProps = lineBidi.dirPropsMemory;
 172         System.arraycopy(paraBidi.dirProps, start, lineBidi.dirProps, 0,
 173                          length);
 174         /* copy proper subset of Levels */
 175         lineBidi.getLevelsMemory(length);
 176         lineBidi.levels = lineBidi.levelsMemory;
 177         System.arraycopy(paraBidi.levels, start, lineBidi.levels, 0,
 178                          length);
 179         lineBidi.runCount = -1;


 185             /*
 186              * The parent's levels are all either
 187              * implicitly or explicitly ==paraLevel;
 188              * do the same here.
 189              */
 190             if (paraBidi.trailingWSStart <= start) {
 191                 lineBidi.trailingWSStart = 0;
 192             } else if (paraBidi.trailingWSStart < limit) {
 193                 lineBidi.trailingWSStart = paraBidi.trailingWSStart - start;
 194             } else {
 195                 lineBidi.trailingWSStart = length;
 196             }
 197         } else {
 198             byte[] levels = lineBidi.levels;
 199             int i, trailingWSStart;
 200             byte level;
 201 
 202             setTrailingWSStart(lineBidi);
 203             trailingWSStart = lineBidi.trailingWSStart;
 204 
 205             /* recalculate lineBidiBase.direction */
 206             if (trailingWSStart == 0) {
 207                 /* all levels are at paraLevel */
 208                 lineBidi.direction = (byte)(lineBidi.paraLevel & 1);
 209             } else {
 210                 /* get the level of the first character */
 211                 level = (byte)(levels[0] & 1);
 212 
 213                 /* if there is anything of a different level, then the line
 214                    is mixed */
 215                 if (trailingWSStart < length &&
 216                     (lineBidi.paraLevel & 1) != level) {
 217                     /* the trailing WS is at paraLevel, which differs from
 218                        levels[0] */
 219                     lineBidi.direction = BidiBase.MIXED;
 220                 } else {
 221                     /* see if levels[1..trailingWSStart-1] have the same
 222                        direction as levels[0] and paraLevel */
 223                     for (i = 1; ; i++) {
 224                         if (i == trailingWSStart) {
 225                             /* the direction values match those in level */


 239                     lineBidi.paraLevel = (byte)
 240                         ((lineBidi.paraLevel + 1) & ~1);
 241 
 242                     /* all levels are implicitly at paraLevel (important for
 243                        getLevels()) */
 244                     lineBidi.trailingWSStart = 0;
 245                     break;
 246                 case Bidi.DIRECTION_RIGHT_TO_LEFT:
 247                     /* make sure paraLevel is odd */
 248                     lineBidi.paraLevel |= 1;
 249 
 250                     /* all levels are implicitly at paraLevel (important for
 251                        getLevels()) */
 252                     lineBidi.trailingWSStart = 0;
 253                     break;
 254                 default:
 255                     break;
 256             }
 257         }
 258 
 259         lineBidi.paraBidi = paraBidi;     /* mark successful setLine */
 260 
 261         return newBidi;
 262     }
 263 
 264     static byte getLevelAt(BidiBase bidiBase, int charIndex)
 265     {
 266         /* return paraLevel if in the trailing WS run, otherwise the real level */
 267         if (bidiBase.direction != BidiBase.MIXED || charIndex >= bidiBase.trailingWSStart) {
 268             return bidiBase.GetParaLevelAt(charIndex);
 269         } else {
 270             return bidiBase.levels[charIndex];
 271         }
 272     }
 273 
 274     static byte[] getLevels(BidiBase bidiBase)
 275     {
 276         int start = bidiBase.trailingWSStart;
 277         int length = bidiBase.length;
 278 
 279         if (start != length) {
 280             /* the current levels array does not reflect the WS run */


 283              * has an implicit trailing WS run and therefore does not fully
 284              * reflect itself all the levels.
 285              * This must be a Bidi object for a line, and
 286              * we need to create a new levels array.
 287              */
 288             /* bidiBase.paraLevel is ok even if contextual multiple paragraphs,
 289                since bidiBase is a line object                                     */
 290             Arrays.fill(bidiBase.levels, start, length, bidiBase.paraLevel);
 291 
 292             /* this new levels array is set for the line and reflects the WS run */
 293             bidiBase.trailingWSStart = length;
 294         }
 295         if (length < bidiBase.levels.length) {
 296             byte[] levels = new byte[length];
 297             System.arraycopy(bidiBase.levels, 0, levels, 0, length);
 298             return levels;
 299         }
 300         return bidiBase.levels;
 301     }
 302 
 303     static BidiRun getVisualRun(BidiBase bidiBase, int runIndex) {
 304         int start = bidiBase.runs[runIndex].start;
 305         int limit;
 306         byte level = bidiBase.runs[runIndex].level;
 307 
 308         if (runIndex > 0) {
 309             limit = start +
 310                     bidiBase.runs[runIndex].limit -
 311                     bidiBase.runs[runIndex - 1].limit;
 312         } else {
 313             limit = start + bidiBase.runs[0].limit;








 314         }
 315         return new BidiRun(start, limit, level);



 316     }
 317 
 318     /* in trivial cases there is only one trivial run; called by getRuns() */
 319     private static void getSingleRun(BidiBase bidiBase, byte level) {
 320         /* simple, single-run case */
 321         bidiBase.runs = bidiBase.simpleRuns;
 322         bidiBase.runCount = 1;
 323 
 324         /* fill and reorder the single run */
 325         bidiBase.runs[0] = new BidiRun(0, bidiBase.length, level);
 326     }
 327 
 328     /* reorder the runs array (L2) ---------------------------------------------- */
 329 
 330     /*
 331      * Reorder the same-level runs in the runs array.
 332      * Here, runCount>1 and maxLevel>=minLevel>=paraLevel.
 333      * All the visualStart fields=logical start before reordering.
 334      * The "odd" bits are not set yet.
 335      *


 471      * If option OPTION_REMOVE_CONTROLS is set, insertRemove will contain the
 472      * negative number of BiDi control characters within this run.
 473      */
 474     static void getRuns(BidiBase bidiBase) {
 475         /*
 476          * This method returns immediately if the runs are already set. This
 477          * includes the case of length==0 (handled in setPara)..
 478          */
 479         if (bidiBase.runCount >= 0) {
 480             return;
 481         }
 482         if (bidiBase.direction != BidiBase.MIXED) {
 483             /* simple, single-run case - this covers length==0 */
 484             /* bidiBase.paraLevel is ok even for contextual multiple paragraphs */
 485             getSingleRun(bidiBase, bidiBase.paraLevel);
 486         } else /* BidiBase.MIXED, length>0 */ {
 487             /* mixed directionality */
 488             int length = bidiBase.length, limit;
 489             byte[] levels = bidiBase.levels;
 490             int i, runCount;
 491             byte level = -1;    /* initialize with no valid level */
 492             /*
 493              * If there are WS characters at the end of the line
 494              * and the run preceding them has a level different from
 495              * paraLevel, then they will form their own run at paraLevel (L1).
 496              * Count them separately.
 497              * We need some special treatment for this in order to not
 498              * modify the levels array which a line Bidi object shares
 499              * with its paragraph parent and its other line siblings.
 500              * In other words, for the trailing WS, it may be
 501              * levels[]!=paraLevel but we have to treat it like it were so.
 502              */
 503             limit = bidiBase.trailingWSStart;
 504             /* count the runs, there is at least one non-WS run, and limit>0 */
 505             runCount = 0;
 506             for (i = 0; i < limit; ++i) {
 507                 /* increment runCount at the start of each run */
 508                 if (levels[i] != level) {
 509                     ++runCount;
 510                     level = levels[i];
 511                 }


 620                     bidiBase.runs[runIndex].insertRemove--;
 621                 }
 622             }
 623         }
 624     }
 625 
 626     static int[] prepareReorder(byte[] levels, byte[] pMinLevel, byte[] pMaxLevel)
 627     {
 628         int start;
 629         byte level, minLevel, maxLevel;
 630 
 631         if (levels == null || levels.length <= 0) {
 632             return null;
 633         }
 634 
 635         /* determine minLevel and maxLevel */
 636         minLevel = BidiBase.MAX_EXPLICIT_LEVEL + 1;
 637         maxLevel = 0;
 638         for (start = levels.length; start>0; ) {
 639             level = levels[--start];
 640             if (level < 0 || level > (BidiBase.MAX_EXPLICIT_LEVEL + 1)) {
 641                 return null;
 642             }
 643             if (level < minLevel) {
 644                 minLevel = level;
 645             }
 646             if (level > maxLevel) {
 647                 maxLevel = level;
 648             }
 649         }
 650         pMinLevel[0] = minLevel;
 651         pMaxLevel[0] = maxLevel;
 652 
 653         /* initialize the index map */
 654         int[] indexMap = new int[levels.length];
 655         for (start = levels.length; start > 0; ) {
 656             --start;
 657             indexMap[start] = start;
 658         }
 659 
 660         return indexMap;


< prev index next >