Bidi.java revision 6e42190c7f7d7cf3d8b787c918de0d797c6ddbba
151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project 36e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (C) Copyright IBM Corp. 1999-2003 - All Rights Reserved 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The original version of this source code and documentation is 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * copyrighted and owned by IBM. These materials are provided 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under terms of a License Agreement between IBM and Sun. 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This technology is protected by multiple US and International 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * patents. This notice and attribution to IBM may not be removed. 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.text; 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This class implements the Unicode Bidirectional Algorithm. 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A Bidi object provides information on the bidirectional reordering of the text 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * used to create it. This is required, for example, to properly display Arabic 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or Hebrew text. These languages are inherently mixed directional, as they order 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * numbers from left-to-right while ordering most other text from right-to-left. 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Once created, a Bidi object can be queried to see if the text it represents is 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * all left-to-right or all right-to-left. Such objects are very lightweight and 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this text is relatively easy to process. 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If there are multiple runs of text, information about the runs can be accessed 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by indexing to get the start, limit, and level of a run. The level represents 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * both the direction and the 'nesting level' of a directional run. Odd levels 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are right-to-left, while even levels are left-to-right. So for example level 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 0 represents left-to-right text, while level 1 represents right-to-left text, and 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * level 2 represents left-to-right text embedded in a right-to-left run. 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic final class Bidi { 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Constant indicating base direction is left-to-right. */ 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int DIRECTION_LEFT_TO_RIGHT = 0; 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Constant indicating base direction is right-to-left. */ 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int DIRECTION_RIGHT_TO_LEFT = 1; 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Constant indicating that the base direction depends on the first strong 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * directional character in the text according to the Unicode 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Bidirectional Algorithm. If no strong directional character is present, 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the base direction is left-to-right. 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int DIRECTION_DEFAULT_LEFT_TO_RIGHT = -2; 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Constant indicating that the base direction depends on the first strong 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * directional character in the text according to the Unicode 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Bidirectional Algorithm. If no strong directional character is present, 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the base direction is right-to-left. 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = -1; 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 846ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera private static int translateConstToIcu(int javaInt) { 856ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera switch (javaInt) { 866ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera case DIRECTION_DEFAULT_LEFT_TO_RIGHT: 876ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return android.icu.text.Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT; 886ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera case DIRECTION_DEFAULT_RIGHT_TO_LEFT: 896ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return android.icu.text.Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT; 906ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera case DIRECTION_LEFT_TO_RIGHT: 916ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return android.icu.text.Bidi.DIRECTION_LEFT_TO_RIGHT; 926ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera case DIRECTION_RIGHT_TO_LEFT: 936ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return android.icu.text.Bidi.DIRECTION_RIGHT_TO_LEFT; 946ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // If the parameter was unrecognized use LEFT_TO_RIGHT. 956ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera default: 966ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return android.icu.text.Bidi.DIRECTION_LEFT_TO_RIGHT; 976ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 986ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 996ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera 1006ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera private android.icu.text.Bidi bidiBase; 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create Bidi from the given paragraph of text and base direction. 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param paragraph a paragraph of text 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param flags a collection of flags that control the algorithm. The 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * algorithm understands the flags DIRECTION_LEFT_TO_RIGHT, DIRECTION_RIGHT_TO_LEFT, 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DIRECTION_DEFAULT_LEFT_TO_RIGHT, and DIRECTION_DEFAULT_RIGHT_TO_LEFT. 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Other values are reserved. 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Bidi(String paragraph, int flags) { 1116ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera this((paragraph == null ? null : paragraph.toCharArray()), 0, null, 0, 1126ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera (paragraph == null ? 0 : paragraph.length()), flags); 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create Bidi from the given paragraph of text. 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The RUN_DIRECTION attribute in the text, if present, determines the base 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * direction (left-to-right or right-to-left). If not present, the base 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * direction is computes using the Unicode Bidirectional Algorithm, defaulting to left-to-right 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if there are no strong directional characters in the text. This attribute, if 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * present, must be applied to all the text in the paragraph. 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The BIDI_EMBEDDING attribute in the text, if present, represents embedding level 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * information. Negative values from -1 to -62 indicate overrides at the absolute value 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the level. Positive values from 1 to 62 indicate embeddings. Where values are 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * zero or not defined, the base embedding level as determined by the base direction 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is assumed. 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The NUMERIC_SHAPING attribute in the text, if present, converts European digits to 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * other decimal digits before running the bidi algorithm. This attribute, if present, 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * must be applied to all the text in the paragraph. 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param paragraph a paragraph of text with optional character and paragraph attribute information 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.awt.font.TextAttribute#BIDI_EMBEDDING 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.awt.font.TextAttribute#NUMERIC_SHAPING 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.awt.font.TextAttribute#RUN_DIRECTION 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Bidi(AttributedCharacterIterator paragraph) { 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (paragraph == null) { 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("paragraph is null"); 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 1456ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera this.bidiBase = new android.icu.text.Bidi(paragraph); 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create Bidi from the given text, embedding, and direction information. 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The embeddings array may be null. If present, the values represent embedding level 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * information. Negative values from -1 to -61 indicate overrides at the absolute value 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the level. Positive values from 1 to 61 indicate embeddings. Where values are 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * zero, the base embedding level as determined by the base direction is assumed. 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param text an array containing the paragraph of text to process. 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param textStart the index into the text array of the start of the paragraph. 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param embeddings an array containing embedding values for each character in the paragraph. 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This can be null, in which case it is assumed that there is no external embedding information. 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param embStart the index into the embedding array of the start of the paragraph. 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param paragraphLength the length of the paragraph in the text and embeddings arrays. 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param flags a collection of flags that control the algorithm. The 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * algorithm understands the flags DIRECTION_LEFT_TO_RIGHT, DIRECTION_RIGHT_TO_LEFT, 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DIRECTION_DEFAULT_LEFT_TO_RIGHT, and DIRECTION_DEFAULT_RIGHT_TO_LEFT. 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Other values are reserved. 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Bidi(char[] text, int textStart, byte[] embeddings, int embStart, int paragraphLength, int flags) { 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (text == null) { 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("text is null"); 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (paragraphLength < 0) { 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("bad length: " + paragraphLength); 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (textStart < 0 || paragraphLength > text.length - textStart) { 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("bad range: " + textStart + 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " length: " + paragraphLength + 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " for text of length: " + text.length); 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (embeddings != null && (embStart < 0 || paragraphLength > embeddings.length - embStart)) { 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("bad range: " + embStart + 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " length: " + paragraphLength + 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " for embeddings of length: " + text.length); 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 1836ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera bidiBase = new android.icu.text.Bidi(text, textStart, embeddings, embStart, 1846ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera paragraphLength, translateConstToIcu(flags)); 1856ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 1866ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera 1876ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera private Bidi(android.icu.text.Bidi bidiBase) { 1886ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera this.bidiBase = bidiBase; 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a Bidi object representing the bidi information on a line of text within 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the paragraph represented by the current Bidi. This call is not required if the 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * entire paragraph fits on one line. 1956e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param lineStart the offset from the start of the paragraph to the start of the line. 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param lineLimit the offset from the start of the paragraph to the limit of the line. 1986e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * @return a {@code Bidi} object 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Bidi createLineBidi(int lineStart, int lineLimit) { 2016ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera if (lineStart < 0 || lineLimit < 0 || lineStart > lineLimit || lineLimit > getLength()) { 2026ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera throw new IllegalArgumentException("Invalid ranges (start=" + lineStart + ", " + 2036ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera "limit=" + lineLimit + ", length=" + getLength() + ")"); 2046ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2066ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // In the special case where the start and end positions are the same, we return a new bidi 2076ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // instance which is empty. Note that the default constructor for an empty ICU4J bidi 2086ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // instance is not the same as passing in empty values. This way allows one to call 2096ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // .getLength() for example and return a correct value instead of an IllegalStateException 2106ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // being thrown, which happens in the case of using the empty constructor. 2116ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera if (lineStart == lineLimit) { 2126ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return new Bidi(new android.icu.text.Bidi(new char[] {}, 0, new byte[] {}, 0, 0, 2136ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera translateConstToIcu(DIRECTION_LEFT_TO_RIGHT))); 2146ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 2156ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera 2166ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return new Bidi(bidiBase.createLineBidi(lineStart, lineLimit)); 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return true if the line is not left-to-right or right-to-left. This means it either has mixed runs of left-to-right 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and right-to-left text, or the base direction differs from the direction of the only run of text. 2226e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return true if the line is not left-to-right or right-to-left. 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isMixed() { 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return bidiBase.isMixed(); 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return true if the line is all left-to-right text and the base direction is left-to-right. 2316e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return true if the line is all left-to-right text and the base direction is left-to-right 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isLeftToRight() { 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return bidiBase.isLeftToRight(); 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return true if the line is all right-to-left text, and the base direction is right-to-left. 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return true if the line is all right-to-left text, and the base direction is right-to-left 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isRightToLeft() { 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return bidiBase.isRightToLeft(); 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the length of text in the line. 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the length of text in the line 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getLength() { 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return bidiBase.getLength(); 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return true if the base direction is left-to-right. 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return true if the base direction is left-to-right 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean baseIsLeftToRight() { 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return bidiBase.baseIsLeftToRight(); 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the base level (0 if left-to-right, 1 if right-to-left). 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the base level 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getBaseLevel() { 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return bidiBase.getParaLevel(); 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 2716e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * Return the resolved level of the character at offset. If offset is 2726e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * {@literal <} 0 or ≥ the length of the line, return the base direction 2736e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * level. 2746e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param offset the index of the character for which to return the level 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the resolved level of the character at offset 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getLevelAt(int offset) { 2796ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera try { 2806ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return bidiBase.getLevelAt(offset); 2816ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } catch (IllegalArgumentException e) { 2826ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return getBaseLevel(); 2836ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the number of level runs. 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the number of level runs 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getRunCount() { 2916ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera int runCount = bidiBase.countRuns(); 2926ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return (runCount == 0 ? 1 : runCount); 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the level of the nth logical run in this line. 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param run the index of the run, between 0 and <code>getRunCount()</code> 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the level of the run 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getRunLevel(int run) { 3016ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // Paper over a the ICU4J behaviour of strictly enforcing run must be strictly less than 3026ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // the number of runs. Done to maintain compatibility with previous C implementation. 3036ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera if (run == getRunCount()) { 3046ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return getBaseLevel(); 3056ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 3066ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return (bidiBase.countRuns() == 0 ? bidiBase.getBaseLevel() : bidiBase.getRunLevel(run)); 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the index of the character at the start of the nth logical run in this line, as 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * an offset from the start of the line. 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param run the index of the run, between 0 and <code>getRunCount()</code> 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the start of the run 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getRunStart(int run) { 3166ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // Paper over a the ICU4J behaviour of strictly enforcing run must be strictly less than 3176ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // the number of runs. Done to maintain compatibility with previous C implementation. 3186ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera if (run == getRunCount()) { 3196ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return getBaseLevel(); 3206ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 3216ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return (bidiBase.countRuns() == 0 ? 0 : bidiBase.getRunStart(run)); 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the index of the character past the end of the nth logical run in this line, as 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * an offset from the start of the line. For example, this will return the length 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the line for the last run on the line. 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param run the index of the run, between 0 and <code>getRunCount()</code> 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return limit the limit of the run 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getRunLimit(int run) { 3326ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // Paper over a the ICU4J behaviour of strictly enforcing run must be strictly less than 3336ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera // the number of runs. Done to maintain compatibility with previous C implementation. 3346ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera if (run == getRunCount()) { 3356ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return getBaseLevel(); 3366ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 3376ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return (bidiBase.countRuns() == 0 ? bidiBase.getLength() : bidiBase.getRunLimit(run)); 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return true if the specified text requires bidi analysis. If this returns false, 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the text will display left-to-right. Clients can then avoid constructing a Bidi object. 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Text in the Arabic Presentation Forms area of Unicode is presumed to already be shaped 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and ordered for display, and so will not cause this function to return true. 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param text the text containing the characters to test 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param start the start of the range of characters to test 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param limit the limit of the range of characters to test 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return true if the range of characters requires bidi analysis 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static boolean requiresBidi(char[] text, int start, int limit) { 3526ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera if (0 > start || start > limit || limit > text.length) { 3536ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera throw new IllegalArgumentException("Value start " + start + 3546ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera " is out of range 0 to " + limit); 3556ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 3566ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return android.icu.text.Bidi.requiresBidi(text, start, limit); 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Reorder the objects in the array into visual order based on their levels. 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This is a utility function to use when you have a collection of objects 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * representing runs of text in logical order, each run containing text 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * at a single level. The elements at <code>index</code> from 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>objectStart</code> up to <code>objectStart + count</code> 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the objects array will be reordered into visual order assuming 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * each run of text has the level indicated by the corresponding element 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the levels array (at <code>index - objectStart + levelStart</code>). 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param levels an array representing the bidi level of each object 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param levelStart the start position in the levels array 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param objects the array of objects to be reordered into visual order 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param objectStart the start position in the objects array 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param count the number of objects to reorder 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static void reorderVisually(byte[] levels, int levelStart, Object[] objects, int objectStart, int count) { 3766ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera if (0 > levelStart || levels.length <= levelStart) { 3776ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera throw new IllegalArgumentException("Value levelStart " + 3786ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera levelStart + " is out of range 0 to " + 3796ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera (levels.length-1)); 3806ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 3816ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera if (0 > objectStart || objects.length <= objectStart) { 3826ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera throw new IllegalArgumentException("Value objectStart " + 3836ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera levelStart + " is out of range 0 to " + 3846ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera (objects.length-1)); 3856ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 3866ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera if (0 > count || objects.length < (objectStart+count)) { 3876ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera throw new IllegalArgumentException("Value count " + 3886ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera levelStart + " is out of range 0 to " + 3896ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera (objects.length - objectStart)); 3906ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera } 3916ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera android.icu.text.Bidi.reorderVisually(levels, levelStart, objects, objectStart, count); 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Display the bidi internal state, used in debugging. 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String toString() { 3986ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera return getClass().getName() 3996ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera + "[direction: " + bidiBase.getDirection() + " baseLevel: " + bidiBase.getBaseLevel() 4006ec7166ad3bf227db0752d80dd2a2b27ea262919Shubham Ajmera + " length: " + bidiBase.getLength() + " runs: " + bidiBase.getRunCount() + "]"; 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 403