151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.awt.font; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ObjectOutputStream; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Arrays; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Comparator; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.EnumSet; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Set; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The <code>NumericShaper</code> class is used to convert Latin-1 (European) 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * digits to other Unicode decimal digits. Users of this class will 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * primarily be people who wish to present data using 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * national digit shapes, but find it more convenient to represent the 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * data internally using Latin-1 (European) digits. This does not 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * interpret the deprecated numeric shape selector character (U+206E). 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Instances of <code>NumericShaper</code> are typically applied 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as attributes to text with the 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link TextAttribute#NUMERIC_SHAPING NUMERIC_SHAPING} attribute 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the <code>TextAttribute</code> class. 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For example, this code snippet causes a <code>TextLayout</code> to 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * shape European digits to Arabic in an Arabic context:<br> 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre> 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Map map = new HashMap(); 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * map.put(TextAttribute.NUMERIC_SHAPING, 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.getContextualShaper(NumericShaper.ARABIC)); 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FontRenderContext frc = ...; 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TextLayout layout = new TextLayout(text, map, frc); 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * layout.draw(g2d, x, y); 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote> 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <br> 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It is also possible to perform numeric shaping explicitly using instances 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of <code>NumericShaper</code>, as this code snippet demonstrates:<br> 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre> 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * char[] text = ...; 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * // shape all EUROPEAN digits (except zero) to ARABIC digits 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper shaper = NumericShaper.getShaper(NumericShaper.ARABIC); 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * shaper.shape(text, start, count); 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * // shape European digits to ARABIC digits if preceding text is Arabic, or 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * // shape European digits to TAMIL digits if preceding text is Tamil, or 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * // leave European digits alone if there is no preceding text, or 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * // preceding text is neither Arabic nor Tamil 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper shaper = 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.getContextualShaper(NumericShaper.ARABIC | 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.TAMIL, 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.EUROPEAN); 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * shaper.shape(text, start, count); 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote> 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p><b>Bit mask- and enum-based Unicode ranges</b></p> 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>This class supports two different programming interfaces to 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * represent Unicode ranges for script-specific digits: bit 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * mask-based ones, such as {@link #ARABIC NumericShaper.ARABIC}, and 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * enum-based ones, such as {@link NumericShaper.Range#ARABIC}. 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Multiple ranges can be specified by ORing bit mask-based constants, 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * such as: 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre> 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.ARABIC | NumericShaper.TAMIL 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote> 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or creating a {@code Set} with the {@link NumericShaper.Range} 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * constants, such as: 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre> 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EnumSet.of(NumericShaper.Scirpt.ARABIC, NumericShaper.Range.TAMIL) 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote> 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The enum-based ranges are a super set of the bit mask-based ones. 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>If the two interfaces are mixed (including serialization), 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Unicode range values are mapped to their counterparts where such 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * mapping is possible, such as {@code NumericShaper.Range.ARABIC} 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * from/to {@code NumericShaper.ARABIC}. If any unmappable range 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * values are specified, such as {@code NumericShaper.Range.BALINESE}, 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * those ranges are ignored. 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p><b>Decimal Digits Precedence</b></p> 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>A Unicode range may have more than one set of decimal digits. If 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * multiple decimal digits sets are specified for the same Unicode 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * range, one of the sets will take precedence as follows. 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <table border=1 cellspacing=3 cellpadding=0 summary="NumericShaper constants precedence."> 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <th class="TableHeadingColor">Unicode Range</th> 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <th class="TableHeadingColor"><code>NumericShaper</code> Constants</th> 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <th class="TableHeadingColor">Precedence</th> 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </tr> 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td rowspan="2">Arabic</td> 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>{@link NumericShaper#ARABIC NumericShaper.ARABIC}<br> 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link NumericShaper#EASTERN_ARABIC NumericShaper.EASTERN_ARABIC}</td> 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>{@link NumericShaper#EASTERN_ARABIC NumericShaper.EASTERN_ARABIC}</td> 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </tr> 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>{@link NumericShaper.Range#ARABIC}<br> 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link NumericShaper.Range#EASTERN_ARABIC}</td> 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>{@link NumericShaper.Range#EASTERN_ARABIC}</td> 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </tr> 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Tai Tham</td> 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>{@link NumericShaper.Range#TAI_THAM_HORA}<br> 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link NumericShaper.Range#TAI_THAM_THAM}</td> 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>{@link NumericShaper.Range#TAI_THAM_THAM}</td> 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </tr> 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </table> 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic final class NumericShaper implements java.io.Serializable { 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A {@code NumericShaper.Range} represents a Unicode range of a 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * script having its own decimal digits. For example, the {@link 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.Range#THAI} range has the Thai digits, THAI DIGIT 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ZERO (U+0E50) to THAI DIGIT NINE (U+0E59). 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The <code>Range</code> enum replaces the traditional bit 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * mask-based values (e.g., {@link NumericShaper#ARABIC}), and 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * supports more Unicode ranges than the bit mask-based ones. For 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * example, the following code using the bit mask: 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre> 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.getContextualShaper(NumericShaper.ARABIC | 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.TAMIL, 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.EUROPEAN); 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote> 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * can be written using this enum as: 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre> 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.getContextualShaper(EnumSet.of( 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.Range.ARABIC, 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.Range.TAMIL), 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.Range.EUROPEAN); 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote> 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.7 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static enum Range { 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The order of EUROPEAN to MOGOLIAN must be consistent 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // with the bitmask-based constants. 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Latin (European) range with the Latin (ASCII) digits. 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski EUROPEAN ('\u0030', '\u0000', '\u0300'), 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Arabic range with the Arabic-Indic digits. 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ARABIC ('\u0660', '\u0600', '\u0780'), 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Arabic range with the Eastern Arabic-Indic digits. 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski EASTERN_ARABIC ('\u06f0', '\u0600', '\u0780'), 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Devanagari range with the Devanagari digits. 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DEVANAGARI ('\u0966', '\u0900', '\u0980'), 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Bengali range with the Bengali digits. 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BENGALI ('\u09e6', '\u0980', '\u0a00'), 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Gurmukhi range with the Gurmukhi digits. 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski GURMUKHI ('\u0a66', '\u0a00', '\u0a80'), 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Gujarati range with the Gujarati digits. 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski GUJARATI ('\u0ae6', '\u0b00', '\u0b80'), 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Oriya range with the Oriya digits. 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ORIYA ('\u0b66', '\u0b00', '\u0b80'), 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Tamil range with the Tamil digits. 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TAMIL ('\u0be6', '\u0b80', '\u0c00'), 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Telugu range with the Telugu digits. 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TELUGU ('\u0c66', '\u0c00', '\u0c80'), 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Kannada range with the Kannada digits. 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski KANNADA ('\u0ce6', '\u0c80', '\u0d00'), 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Malayalam range with the Malayalam digits. 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski MALAYALAM ('\u0d66', '\u0d00', '\u0d80'), 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Thai range with the Thai digits. 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski THAI ('\u0e50', '\u0e00', '\u0e80'), 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Lao range with the Lao digits. 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski LAO ('\u0ed0', '\u0e80', '\u0f00'), 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Tibetan range with the Tibetan digits. 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TIBETAN ('\u0f20', '\u0f00', '\u1000'), 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Myanmar range with the Myanmar digits. 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski MYANMAR ('\u1040', '\u1000', '\u1080'), 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Ethiopic range with the Ethiopic digits. Ethiopic 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * does not have a decimal digit 0 so Latin (European) 0 is 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * used. 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ETHIOPIC ('\u1369', '\u1200', '\u1380') { 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski @Override 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char getNumericBase() { return 1; } 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }, 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Khmer range with the Khmer digits. 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski KHMER ('\u17e0', '\u1780', '\u1800'), 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Mongolian range with the Mongolian digits. 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski MONGOLIAN ('\u1810', '\u1800', '\u1900'), 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The order of EUROPEAN to MOGOLIAN must be consistent 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // with the bitmask-based constants. 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The N'Ko range with the N'Ko digits. 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski NKO ('\u07c0', '\u07c0', '\u0800'), 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Myanmar range with the Myanmar Shan digits. 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski MYANMAR_SHAN ('\u1090', '\u1000', '\u10a0'), 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Limbu range with the Limbu digits. 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski LIMBU ('\u1946', '\u1900', '\u1950'), 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The New Tai Lue range with the New Tai Lue digits. 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski NEW_TAI_LUE ('\u19d0', '\u1980', '\u19e0'), 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Balinese range with the Balinese digits. 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BALINESE ('\u1b50', '\u1b00', '\u1b80'), 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Sundanese range with the Sundanese digits. 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SUNDANESE ('\u1bb0', '\u1b80', '\u1bc0'), 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Lepcha range with the Lepcha digits. 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski LEPCHA ('\u1c40', '\u1c00', '\u1c50'), 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Ol Chiki range with the Ol Chiki digits. 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski OL_CHIKI ('\u1c50', '\u1c50', '\u1c80'), 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Vai range with the Vai digits. 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski VAI ('\ua620', '\ua500', '\ua640'), 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Saurashtra range with the Saurashtra digits. 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SAURASHTRA ('\ua8d0', '\ua880', '\ua8e0'), 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Kayah Li range with the Kayah Li digits. 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski KAYAH_LI ('\ua900', '\ua900', '\ua930'), 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Cham range with the Cham digits. 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CHAM ('\uaa50', '\uaa00', '\uaa60'), 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Tai Tham Hora range with the Tai Tham Hora digits. 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TAI_THAM_HORA ('\u1a80', '\u1a20', '\u1ab0'), 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Tai Tham Tham range with the Tai Tham Tham digits. 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TAI_THAM_THAM ('\u1a90', '\u1a20', '\u1ab0'), 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Javanese range with the Javanese digits. 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski JAVANESE ('\ua9d0', '\ua980', '\ua9e0'), 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Meetei Mayek range with the Meetei Mayek digits. 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski MEETEI_MAYEK ('\uabf0', '\uabc0', '\uac00'); 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int toRangeIndex(Range script) { 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = script.ordinal(); 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index < NUM_KEYS ? index : -1; 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Range indexToRange(int index) { 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index < NUM_KEYS ? Range.values()[index] : null; 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int toRangeMask(Set<Range> ranges) { 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int m = 0; 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (Range range : ranges) { 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = range.ordinal(); 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (index < NUM_KEYS) { 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski m |= 1 << index; 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return m; 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Set<Range> maskToRangeSet(int mask) { 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Set<Range> set = EnumSet.noneOf(Range.class); 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Range[] a = Range.values(); 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < NUM_KEYS; i++) { 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((mask & (1 << i)) != 0) { 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski set.add(a[i]); 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return set; 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // base character of range digits 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final int base; 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Unicode range 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final int start, // inclusive 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski end; // exclusive 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Range(int base, int start, int end) { 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.base = base - ('0' + getNumericBase()); 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.start = start; 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.end = end; 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int getDigitBase() { 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return base; 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char getNumericBase() { 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return 0; 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean inRange(int c) { 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return start <= c && c < end; 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** index of context for contextual shaping - values range from 0 to 18 */ 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int key; 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** flag indicating whether to shape contextually (high bit) and which 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * digit ranges to shape (bits 0-18) 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int mask; 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The context {@code Range} for contextual shaping or the {@code 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Range} for non-contextual shaping. {@code null} for the bit 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * mask-based API. 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.7 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Range shapingRange; 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@code Set<Range>} indicating which Unicode ranges to 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * shape. {@code null} for the bit mask-based API. 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private transient Set<Range> rangeSet; 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * rangeSet.toArray() value. Sorted by Range.base when the number 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of elements is greater then BSEARCH_THRESHOLD. 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private transient Range[] rangeArray; 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If more than BSEARCH_THRESHOLD ranges are specified, binary search is used. 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int BSEARCH_THRESHOLD = 3; 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long serialVersionUID = -8022764705923730308L; 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the Latin-1 (European) and extended range, and 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Latin-1 (European) decimal base. 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int EUROPEAN = 1<<0; 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the ARABIC range and decimal base. */ 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int ARABIC = 1<<1; 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the ARABIC range and ARABIC_EXTENDED decimal base. */ 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int EASTERN_ARABIC = 1<<2; 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the DEVANAGARI range and decimal base. */ 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int DEVANAGARI = 1<<3; 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the BENGALI range and decimal base. */ 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int BENGALI = 1<<4; 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the GURMUKHI range and decimal base. */ 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int GURMUKHI = 1<<5; 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the GUJARATI range and decimal base. */ 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int GUJARATI = 1<<6; 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the ORIYA range and decimal base. */ 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int ORIYA = 1<<7; 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the TAMIL range and decimal base. */ 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // TAMIL DIGIT ZERO was added in Unicode 4.1 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int TAMIL = 1<<8; 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the TELUGU range and decimal base. */ 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int TELUGU = 1<<9; 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the KANNADA range and decimal base. */ 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int KANNADA = 1<<10; 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the MALAYALAM range and decimal base. */ 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int MALAYALAM = 1<<11; 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the THAI range and decimal base. */ 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int THAI = 1<<12; 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the LAO range and decimal base. */ 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int LAO = 1<<13; 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the TIBETAN range and decimal base. */ 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int TIBETAN = 1<<14; 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the MYANMAR range and decimal base. */ 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int MYANMAR = 1<<15; 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the ETHIOPIC range and decimal base. */ 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int ETHIOPIC = 1<<16; 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the KHMER range and decimal base. */ 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int KHMER = 1<<17; 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies the MONGOLIAN range and decimal base. */ 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int MONGOLIAN = 1<<18; 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Identifies all ranges, for full contextual shaping. 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>This constant specifies all of the bit mask-based 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ranges. Use {@code EmunSet.allOf(NumericShaper.Range.class)} to 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specify all of the enum-based ranges. 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final int ALL_RANGES = 0x0007ffff; 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int EUROPEAN_KEY = 0; 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int ARABIC_KEY = 1; 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int EASTERN_ARABIC_KEY = 2; 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int DEVANAGARI_KEY = 3; 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int BENGALI_KEY = 4; 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int GURMUKHI_KEY = 5; 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int GUJARATI_KEY = 6; 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int ORIYA_KEY = 7; 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int TAMIL_KEY = 8; 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int TELUGU_KEY = 9; 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int KANNADA_KEY = 10; 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int MALAYALAM_KEY = 11; 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int THAI_KEY = 12; 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int LAO_KEY = 13; 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int TIBETAN_KEY = 14; 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int MYANMAR_KEY = 15; 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int ETHIOPIC_KEY = 16; 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int KHMER_KEY = 17; 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int MONGOLIAN_KEY = 18; 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int NUM_KEYS = MONGOLIAN_KEY + 1; // fixed 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int CONTEXTUAL_MASK = 1<<31; 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final char[] bases = { 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0030' - '\u0030', // EUROPEAN 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0660' - '\u0030', // ARABIC-INDIC 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u06f0' - '\u0030', // EXTENDED ARABIC-INDIC (EASTERN_ARABIC) 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0966' - '\u0030', // DEVANAGARI 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u09e6' - '\u0030', // BENGALI 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0a66' - '\u0030', // GURMUKHI 50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0ae6' - '\u0030', // GUJARATI 50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0b66' - '\u0030', // ORIYA 50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0be6' - '\u0030', // TAMIL - zero was added in Unicode 4.1 50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0c66' - '\u0030', // TELUGU 50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0ce6' - '\u0030', // KANNADA 51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0d66' - '\u0030', // MALAYALAM 51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0e50' - '\u0030', // THAI 51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0ed0' - '\u0030', // LAO 51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0f20' - '\u0030', // TIBETAN 51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u1040' - '\u0030', // MYANMAR 51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u1369' - '\u0031', // ETHIOPIC - no zero 51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u17e0' - '\u0030', // KHMER 51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u1810' - '\u0030', // MONGOLIAN 51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // some ranges adjoin or overlap, rethink if we want to do a binary search on this 52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final char[] contexts = { 52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0000', '\u0300', // 'EUROPEAN' (really latin-1 and extended) 52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0600', '\u0780', // ARABIC 52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0600', '\u0780', // EASTERN_ARABIC -- note overlap with arabic 52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0900', '\u0980', // DEVANAGARI 52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0980', '\u0a00', // BENGALI 52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0a00', '\u0a80', // GURMUKHI 52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0a80', '\u0b00', // GUJARATI 53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0b00', '\u0b80', // ORIYA 53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0b80', '\u0c00', // TAMIL 53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0c00', '\u0c80', // TELUGU 53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0c80', '\u0d00', // KANNADA 53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0d00', '\u0d80', // MALAYALAM 53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0e00', '\u0e80', // THAI 53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0e80', '\u0f00', // LAO 53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u0f00', '\u1000', // TIBETAN 53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u1000', '\u1080', // MYANMAR 53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u1200', '\u1380', // ETHIOPIC - note missing zero 54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u1780', '\u1800', // KHMER 54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\u1800', '\u1900', // MONGOLIAN 54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '\uffff', 54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // assume most characters are near each other so probing the cache is infrequent, 54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and a linear probe is ok. 54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int ctCache = 0; 54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int ctCacheLimit = contexts.length - 2; 55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // warning, synchronize access to this as it modifies state 55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int getContextKey(char c) { 55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c < contexts[ctCache]) { 55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (ctCache > 0 && c < contexts[ctCache]) --ctCache; 55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c >= contexts[ctCache + 1]) { 55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (ctCache < ctCacheLimit && c >= contexts[ctCache + 1]) ++ctCache; 55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // if we're not in a known range, then return EUROPEAN as the range key 56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (ctCache & 0x1) == 0 ? (ctCache / 2) : EUROPEAN_KEY; 56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // cache for the NumericShaper.Range version 56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private transient volatile Range currentRange = Range.EUROPEAN; 56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Range rangeForCodePoint(final int codepoint) { 56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (currentRange.inRange(codepoint)) { 56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return currentRange; 56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski final Range[] ranges = rangeArray; 57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ranges.length > BSEARCH_THRESHOLD) { 57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int lo = 0; 57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int hi = ranges.length - 1; 57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (lo <= hi) { 57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int mid = (lo + hi) / 2; 57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Range range = ranges[mid]; 57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (codepoint < range.start) { 57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hi = mid - 1; 58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (codepoint >= range.end) { 58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lo = mid + 1; 58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski currentRange = range; 58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return range; 58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < ranges.length; i++) { 58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ranges[i].inRange(codepoint)) { 59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ranges[i]; 59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Range.EUROPEAN; 59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A range table of strong directional characters (types L, R, AL). 59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Even (left) indexes are starts of ranges of non-strong-directional (or undefined) 60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * characters, odd (right) indexes are starts of ranges of strong directional 60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * characters. 60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int[] strongTable = { 60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0000, 0x0041, 60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x005b, 0x0061, 60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x007b, 0x00aa, 60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x00ab, 0x00b5, 60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x00b6, 0x00ba, 60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x00bb, 0x00c0, 61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x00d7, 0x00d8, 61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x00f7, 0x00f8, 61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x02b9, 0x02bb, 61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x02c2, 0x02d0, 61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x02d2, 0x02e0, 61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x02e5, 0x02ee, 61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x02ef, 0x0370, 61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0374, 0x0376, 61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x037e, 0x0386, 61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0387, 0x0388, 62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x03f6, 0x03f7, 62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0483, 0x048a, 62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x058a, 0x05be, 62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x05bf, 0x05c0, 62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x05c1, 0x05c3, 62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x05c4, 0x05c6, 62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x05c7, 0x05d0, 62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0600, 0x0608, 62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0609, 0x060b, 62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x060c, 0x060d, 63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x060e, 0x061b, 63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x064b, 0x066d, 63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0670, 0x0671, 63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x06d6, 0x06e5, 63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x06e7, 0x06ee, 63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x06f0, 0x06fa, 63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x070f, 0x0710, 63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0711, 0x0712, 63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0730, 0x074d, 63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x07a6, 0x07b1, 64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x07eb, 0x07f4, 64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x07f6, 0x07fa, 64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0816, 0x081a, 64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x081b, 0x0824, 64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0825, 0x0828, 64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0829, 0x0830, 64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0859, 0x085e, 64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0900, 0x0903, 64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x093a, 0x093b, 64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x093c, 0x093d, 65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0941, 0x0949, 65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x094d, 0x094e, 65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0951, 0x0958, 65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0962, 0x0964, 65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0981, 0x0982, 65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x09bc, 0x09bd, 65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x09c1, 0x09c7, 65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x09cd, 0x09ce, 65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x09e2, 0x09e6, 65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x09f2, 0x09f4, 66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x09fb, 0x0a03, 66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0a3c, 0x0a3e, 66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0a41, 0x0a59, 66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0a70, 0x0a72, 66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0a75, 0x0a83, 66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0abc, 0x0abd, 66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0ac1, 0x0ac9, 66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0acd, 0x0ad0, 66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0ae2, 0x0ae6, 66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0af1, 0x0b02, 67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0b3c, 0x0b3d, 67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0b3f, 0x0b40, 67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0b41, 0x0b47, 67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0b4d, 0x0b57, 67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0b62, 0x0b66, 67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0b82, 0x0b83, 67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0bc0, 0x0bc1, 67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0bcd, 0x0bd0, 67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0bf3, 0x0c01, 67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0c3e, 0x0c41, 68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0c46, 0x0c58, 68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0c62, 0x0c66, 68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0c78, 0x0c7f, 68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0cbc, 0x0cbd, 68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0ccc, 0x0cd5, 68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0ce2, 0x0ce6, 68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0d41, 0x0d46, 68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0d4d, 0x0d4e, 68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0d62, 0x0d66, 68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0dca, 0x0dcf, 69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0dd2, 0x0dd8, 69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0e31, 0x0e32, 69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0e34, 0x0e40, 69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0e47, 0x0e4f, 69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0eb1, 0x0eb2, 69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0eb4, 0x0ebd, 69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0ec8, 0x0ed0, 69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0f18, 0x0f1a, 69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0f35, 0x0f36, 69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0f37, 0x0f38, 70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0f39, 0x0f3e, 70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0f71, 0x0f7f, 70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0f80, 0x0f85, 70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0f86, 0x0f88, 70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0f8d, 0x0fbe, 70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x0fc6, 0x0fc7, 70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x102d, 0x1031, 70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1032, 0x1038, 70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1039, 0x103b, 70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x103d, 0x103f, 71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1058, 0x105a, 71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x105e, 0x1061, 71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1071, 0x1075, 71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1082, 0x1083, 71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1085, 0x1087, 71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x108d, 0x108e, 71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x109d, 0x109e, 71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x135d, 0x1360, 71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1390, 0x13a0, 71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1400, 0x1401, 72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1680, 0x1681, 72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x169b, 0x16a0, 72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1712, 0x1720, 72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1732, 0x1735, 72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1752, 0x1760, 72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1772, 0x1780, 72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x17b7, 0x17be, 72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x17c6, 0x17c7, 72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x17c9, 0x17d4, 72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x17db, 0x17dc, 73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x17dd, 0x17e0, 73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x17f0, 0x1810, 73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x18a9, 0x18aa, 73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1920, 0x1923, 73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1927, 0x1929, 73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1932, 0x1933, 73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1939, 0x1946, 73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x19de, 0x1a00, 73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1a17, 0x1a19, 73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1a56, 0x1a57, 74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1a58, 0x1a61, 74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1a62, 0x1a63, 74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1a65, 0x1a6d, 74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1a73, 0x1a80, 74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1b00, 0x1b04, 74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1b34, 0x1b35, 74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1b36, 0x1b3b, 74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1b3c, 0x1b3d, 74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1b42, 0x1b43, 74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1b6b, 0x1b74, 75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1b80, 0x1b82, 75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1ba2, 0x1ba6, 75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1ba8, 0x1baa, 75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1be6, 0x1be7, 75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1be8, 0x1bea, 75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1bed, 0x1bee, 75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1bef, 0x1bf2, 75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1c2c, 0x1c34, 75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1c36, 0x1c3b, 75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1cd0, 0x1cd3, 76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1cd4, 0x1ce1, 76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1ce2, 0x1ce9, 76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1ced, 0x1cee, 76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1dc0, 0x1e00, 76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1fbd, 0x1fbe, 76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1fbf, 0x1fc2, 76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1fcd, 0x1fd0, 76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1fdd, 0x1fe0, 76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1fed, 0x1ff2, 76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1ffd, 0x200e, 77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2010, 0x2071, 77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2074, 0x207f, 77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2080, 0x2090, 77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x20a0, 0x2102, 77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2103, 0x2107, 77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2108, 0x210a, 77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2114, 0x2115, 77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2116, 0x2119, 77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x211e, 0x2124, 77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2125, 0x2126, 78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2127, 0x2128, 78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2129, 0x212a, 78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x212e, 0x212f, 78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x213a, 0x213c, 78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2140, 0x2145, 78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x214a, 0x214e, 78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2150, 0x2160, 78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2189, 0x2336, 78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x237b, 0x2395, 78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2396, 0x249c, 79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x24ea, 0x26ac, 79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x26ad, 0x2800, 79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2900, 0x2c00, 79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2ce5, 0x2ceb, 79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2cef, 0x2d00, 79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2d7f, 0x2d80, 79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x2de0, 0x3005, 79751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x3008, 0x3021, 79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x302a, 0x3031, 79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x3036, 0x3038, 80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x303d, 0x3041, 80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x3099, 0x309d, 80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x30a0, 0x30a1, 80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x30fb, 0x30fc, 80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x31c0, 0x31f0, 80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x321d, 0x3220, 80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x3250, 0x3260, 80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x327c, 0x327f, 80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x32b1, 0x32c0, 80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x32cc, 0x32d0, 81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x3377, 0x337b, 81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x33de, 0x33e0, 81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x33ff, 0x3400, 81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x4dc0, 0x4e00, 81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa490, 0xa4d0, 81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa60d, 0xa610, 81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa66f, 0xa680, 81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa6f0, 0xa6f2, 81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa700, 0xa722, 81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa788, 0xa789, 82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa802, 0xa803, 82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa806, 0xa807, 82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa80b, 0xa80c, 82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa825, 0xa827, 82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa828, 0xa830, 82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa838, 0xa840, 82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa874, 0xa880, 82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa8c4, 0xa8ce, 82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa8e0, 0xa8f2, 82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa926, 0xa92e, 83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa947, 0xa952, 83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa980, 0xa983, 83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa9b3, 0xa9b4, 83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa9b6, 0xa9ba, 83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xa9bc, 0xa9bd, 83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaa29, 0xaa2f, 83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaa31, 0xaa33, 83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaa35, 0xaa40, 83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaa43, 0xaa44, 83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaa4c, 0xaa4d, 84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaab0, 0xaab1, 84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaab2, 0xaab5, 84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaab7, 0xaab9, 84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaabe, 0xaac0, 84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xaac1, 0xaac2, 84551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xabe5, 0xabe6, 84651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xabe8, 0xabe9, 84751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xabed, 0xabf0, 84851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xfb1e, 0xfb1f, 84951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xfb29, 0xfb2a, 85051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xfd3e, 0xfd50, 85151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xfdfd, 0xfe70, 85251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xfeff, 0xff21, 85351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xff3b, 0xff41, 85451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xff5b, 0xff66, 85551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xffe0, 0x10000, 85651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x10101, 0x10102, 85751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x10140, 0x101d0, 85851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x101fd, 0x10280, 85951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1091f, 0x10920, 86051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x10a01, 0x10a10, 86151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x10a38, 0x10a40, 86251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x10b39, 0x10b40, 86351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x10e60, 0x11000, 86451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x11001, 0x11002, 86551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x11038, 0x11047, 86651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x11052, 0x11066, 86751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x11080, 0x11082, 86851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x110b3, 0x110b7, 86951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x110b9, 0x110bb, 87051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d167, 0x1d16a, 87151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d173, 0x1d183, 87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d185, 0x1d18c, 87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d1aa, 0x1d1ae, 87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d200, 0x1d360, 87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d6db, 0x1d6dc, 87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d715, 0x1d716, 87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d74f, 0x1d750, 87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d789, 0x1d78a, 87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d7c3, 0x1d7c4, 88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1d7ce, 0x1f110, 88151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1f300, 0x1f48c, 88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1f48d, 0x1f524, 88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x1f525, 0x20000, 88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0xe0001, 0xf0000, 88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 0x10fffe, 0x10ffff // sentinel 88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // use a binary search with a cache 89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 89151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private transient volatile int stCache = 0; 89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean isStrongDirectional(char c) { 89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int cachedIndex = stCache; 89551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c < strongTable[cachedIndex]) { 89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cachedIndex = search(c, strongTable, 0, cachedIndex); 89751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c >= strongTable[cachedIndex + 1]) { 89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cachedIndex = search(c, strongTable, cachedIndex + 1, 89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski strongTable.length - cachedIndex - 1); 90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean val = (cachedIndex & 0x1) == 1; 90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stCache = cachedIndex; 90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return val; 90451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 90551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 90651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int getKeyFromMask(int mask) { 90751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int key = 0; 90851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (key < NUM_KEYS && ((mask & (1<<key)) == 0)) { 90951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ++key; 91051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 91151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (key == NUM_KEYS || ((mask & ~(1<<key)) != 0)) { 91251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("invalid shaper: " + Integer.toHexString(mask)); 91351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 91451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return key; 91551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 91651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 91751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 91851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a shaper for the provided unicode range. All 91951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Latin-1 (EUROPEAN) digits are converted 92051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to the corresponding decimal unicode digits. 92151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param singleRange the specified Unicode range 92251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a non-contextual numeric shaper 92351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if the range is not a single range 92451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 92551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static NumericShaper getShaper(int singleRange) { 92651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int key = getKeyFromMask(singleRange); 92751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new NumericShaper(key, singleRange); 92851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 92951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 93051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 93151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a shaper for the provided Unicode 93251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * range. All Latin-1 (EUROPEAN) digits are converted to the 93351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * corresponding decimal digits of the specified Unicode range. 93451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 93551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param singleRange the Unicode range given by a {@link 93651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper.Range} constant. 93751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a non-contextual {@code NumericShaper}. 93851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NullPointerException if {@code singleRange} is {@code null} 93951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.7 94051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 94151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static NumericShaper getShaper(Range singleRange) { 94251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new NumericShaper(singleRange, EnumSet.of(singleRange)); 94351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 94451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 94551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 94651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a contextual shaper for the provided unicode range(s). 94751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Latin-1 (EUROPEAN) digits are converted to the decimal digits 94851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * corresponding to the range of the preceding text, if the 94951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * range is one of the provided ranges. Multiple ranges are 95051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * represented by or-ing the values together, such as, 95151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>NumericShaper.ARABIC | NumericShaper.THAI</code>. The 95251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * shaper assumes EUROPEAN as the starting context, that is, if 95351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EUROPEAN digits are encountered before any strong directional 95451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * text in the string, the context is presumed to be EUROPEAN, and 95551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * so the digits will not shape. 95651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param ranges the specified Unicode ranges 95751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a shaper for the specified ranges 95851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 95951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static NumericShaper getContextualShaper(int ranges) { 96051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ranges |= CONTEXTUAL_MASK; 96151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new NumericShaper(EUROPEAN_KEY, ranges); 96251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 96351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 96451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 96551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a contextual shaper for the provided Unicode 96651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * range(s). The Latin-1 (EUROPEAN) digits are converted to the 96751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * decimal digits corresponding to the range of the preceding 96851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * text, if the range is one of the provided ranges. 96951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 97051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The shaper assumes EUROPEAN as the starting context, that 97151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is, if EUROPEAN digits are encountered before any strong 97251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * directional text in the string, the context is presumed to be 97351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EUROPEAN, and so the digits will not shape. 97451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 97551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param ranges the specified Unicode ranges 97651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a contextual shaper for the specified ranges 97751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NullPointerException if {@code ranges} is {@code null}. 97851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.7 97951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 98051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static NumericShaper getContextualShaper(Set<Range> ranges) { 98151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski NumericShaper shaper = new NumericShaper(Range.EUROPEAN, ranges); 98251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shaper.mask = CONTEXTUAL_MASK; 98351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return shaper; 98451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 98551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 98651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 98751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a contextual shaper for the provided unicode range(s). 98851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Latin-1 (EUROPEAN) digits will be converted to the decimal digits 98951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * corresponding to the range of the preceding text, if the 99051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * range is one of the provided ranges. Multiple ranges are 99151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * represented by or-ing the values together, for example, 99251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>NumericShaper.ARABIC | NumericShaper.THAI</code>. The 99351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * shaper uses defaultContext as the starting context. 99451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param ranges the specified Unicode ranges 99551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param defaultContext the starting context, such as 99651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>NumericShaper.EUROPEAN</code> 99751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a shaper for the specified Unicode ranges. 99851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if the specified 99951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>defaultContext</code> is not a single valid range. 100051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 100151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static NumericShaper getContextualShaper(int ranges, int defaultContext) { 100251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int key = getKeyFromMask(defaultContext); 100351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ranges |= CONTEXTUAL_MASK; 100451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new NumericShaper(key, ranges); 100551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 100651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 100751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 100851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a contextual shaper for the provided Unicode range(s). 100951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Latin-1 (EUROPEAN) digits will be converted to the decimal 101051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * digits corresponding to the range of the preceding text, if the 101151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * range is one of the provided ranges. The shaper uses {@code 101251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * defaultContext} as the starting context. 101351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 101451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param ranges the specified Unicode ranges 101551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param defaultContext the starting context, such as 101651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@code NumericShaper.Range.EUROPEAN} 101751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a contextual shaper for the specified Unicode ranges. 101851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NullPointerException 101951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if {@code ranges} or {@code defaultContext} is {@code null} 102051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.7 102151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 102251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static NumericShaper getContextualShaper(Set<Range> ranges, 102351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Range defaultContext) { 102451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (defaultContext == null) { 102551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NullPointerException(); 102651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 102751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski NumericShaper shaper = new NumericShaper(defaultContext, ranges); 102851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shaper.mask = CONTEXTUAL_MASK; 102951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return shaper; 103051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 103151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 103251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 103351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private constructor. 103451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 103551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private NumericShaper(int key, int mask) { 103651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.key = key; 103751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.mask = mask; 103851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 103951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 104051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private NumericShaper(Range defaultContext, Set<Range> ranges) { 104151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapingRange = defaultContext; 104251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski rangeSet = EnumSet.copyOf(ranges); // throws NPE if ranges is null. 104351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 104451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Give precedance to EASTERN_ARABIC if both ARABIC and 104551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // EASTERN_ARABIC are specified. 104651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet.contains(Range.EASTERN_ARABIC) 104751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && rangeSet.contains(Range.ARABIC)) { 104851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski rangeSet.remove(Range.ARABIC); 104951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 105051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 105151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // As well as the above case, give precedance to TAI_THAM_THAM if both 105251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // TAI_THAM_HORA and TAI_THAM_THAM are specified. 105351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet.contains(Range.TAI_THAM_THAM) 105451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && rangeSet.contains(Range.TAI_THAM_HORA)) { 105551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski rangeSet.remove(Range.TAI_THAM_HORA); 105651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 105751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 105851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski rangeArray = rangeSet.toArray(new Range[rangeSet.size()]); 105951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeArray.length > BSEARCH_THRESHOLD) { 106051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // sort rangeArray for binary search 106151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Arrays.sort(rangeArray, 106251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new Comparator<Range>() { 106351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int compare(Range s1, Range s2) { 106451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return s1.base > s2.base ? 1 : s1.base == s2.base ? 0 : -1; 106551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 106651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }); 106751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 106851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 106951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 107051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 107151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Converts the digits in the text that occur between start and 107251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * start + count. 107351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param text an array of characters to convert 107451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param start the index into <code>text</code> to start 107551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * converting 107651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param count the number of characters in <code>text</code> 107751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to convert 107851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IndexOutOfBoundsException if start or start + count is 107951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * out of bounds 108051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NullPointerException if text is null 108151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 108251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void shape(char[] text, int start, int count) { 108351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkParams(text, start, count); 108451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isContextual()) { 108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet == null) { 108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeContextually(text, start, count, key); 108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeContextually(text, start, count, shapingRange); 108951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 109051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 109151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeNonContextually(text, start, count); 109251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 109351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 109451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 109551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 109651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Converts the digits in the text that occur between start and 109751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * start + count, using the provided context. 109851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Context is ignored if the shaper is not a contextual shaper. 109951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param text an array of characters 110051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param start the index into <code>text</code> to start 110151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * converting 110251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param count the number of characters in <code>text</code> 110351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to convert 110451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param context the context to which to convert the 110551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * characters, such as <code>NumericShaper.EUROPEAN</code> 110651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IndexOutOfBoundsException if start or start + count is 110751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * out of bounds 110851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NullPointerException if text is null 110951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if this is a contextual shaper 111051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and the specified <code>context</code> is not a single valid 111151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * range. 111251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 111351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void shape(char[] text, int start, int count, int context) { 111451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkParams(text, start, count); 111551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isContextual()) { 111651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int ctxKey = getKeyFromMask(context); 111751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet == null) { 111851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeContextually(text, start, count, ctxKey); 111951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 112051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeContextually(text, start, count, Range.values()[ctxKey]); 112151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 112251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 112351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeNonContextually(text, start, count); 112451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 112551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 112651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 112751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 112851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Converts the digits in the text that occur between {@code 112951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * start} and {@code start + count}, using the provided {@code 113051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * context}. {@code Context} is ignored if the shaper is not a 113151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * contextual shaper. 113251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 113351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param text a {@code char} array 113451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param start the index into {@code text} to start converting 113551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param count the number of {@code char}s in {@code text} 113651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to convert 113751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param context the context to which to convert the characters, 113851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * such as {@code NumericShaper.Range.EUROPEAN} 113951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IndexOutOfBoundsException 114051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if {@code start} or {@code start + count} is out of bounds 114151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws NullPointerException 114251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if {@code text} or {@code context} is null 114351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.7 114451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 114551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void shape(char[] text, int start, int count, Range context) { 114651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkParams(text, start, count); 114751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (context == null) { 114851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NullPointerException("context is null"); 114951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 115051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 115151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isContextual()) { 115251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet != null) { 115351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeContextually(text, start, count, context); 115451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 115551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int key = Range.toRangeIndex(context); 115651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (key >= 0) { 115751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeContextually(text, start, count, key); 115851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 115951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeContextually(text, start, count, shapingRange); 116051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 116151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 116251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 116351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski shapeNonContextually(text, start, count); 116451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 116551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 116651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 116751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void checkParams(char[] text, int start, int count) { 116851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (text == null) { 116951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NullPointerException("text is null"); 117051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 117151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((start < 0) 117251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski || (start > text.length) 117351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski || ((start + count) < 0) 117451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski || ((start + count) > text.length)) { 117551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IndexOutOfBoundsException( 117651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "bad start or count for text of length " + text.length); 117751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 117851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 117951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 118051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 118151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a <code>boolean</code> indicating whether or not 118251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this shaper shapes contextually. 118351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if this shaper is contextual; 118451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>false</code> otherwise. 118551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 118651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isContextual() { 118751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (mask & CONTEXTUAL_MASK) != 0; 118851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 118951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 119051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 119151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns an <code>int</code> that ORs together the values for 119251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * all the ranges that will be shaped. 119351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 119451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For example, to check if a shaper shapes to Arabic, you would use the 119551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * following: 119651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote> 119751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>if ((shaper.getRanges() & shaper.ARABIC) != 0) { ... </code> 119851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </blockquote> 119951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 120051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Note that this method supports only the bit mask-based 120151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ranges. Call {@link #getRangeSet()} for the enum-based ranges. 120251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 120351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the values for all the ranges to be shaped. 120451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 120551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getRanges() { 120651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return mask & ~CONTEXTUAL_MASK; 120751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 120851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 120951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 121051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a {@code Set} representing all the Unicode ranges in 121151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this {@code NumericShaper} that will be shaped. 121251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 121351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return all the Unicode ranges to be shaped. 121451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.7 121551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 121651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Set<Range> getRangeSet() { 121751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet != null) { 121851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return EnumSet.copyOf(rangeSet); 121951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 122051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Range.maskToRangeSet(mask); 122151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 122251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 122351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 122451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Perform non-contextual shaping. 122551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 122651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void shapeNonContextually(char[] text, int start, int count) { 122751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int base; 122851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char minDigit = '0'; 122951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (shapingRange != null) { 123051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski base = shapingRange.getDigitBase(); 123151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minDigit += shapingRange.getNumericBase(); 123251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 123351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski base = bases[key]; 123451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (key == ETHIOPIC_KEY) { 123551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minDigit++; // Ethiopic doesn't use decimal zero 123651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 123751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 123851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = start, e = start + count; i < e; ++i) { 123951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = text[i]; 124051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c >= minDigit && c <= '\u0039') { 124151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski text[i] = (char)(c + base); 124251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 124351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 124451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 124551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 124651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 124751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Perform contextual shaping. 124851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Synchronized to protect caches used in getContextKey. 124951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 125051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private synchronized void shapeContextually(char[] text, int start, int count, int ctxKey) { 125151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 125251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // if we don't support this context, then don't shape 125351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((mask & (1<<ctxKey)) == 0) { 125451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ctxKey = EUROPEAN_KEY; 125551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 125651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int lastkey = ctxKey; 125751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 125851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int base = bases[ctxKey]; 125951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char minDigit = ctxKey == ETHIOPIC_KEY ? '1' : '0'; // Ethiopic doesn't use decimal zero 126051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 126151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (NumericShaper.class) { 126251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = start, e = start + count; i < e; ++i) { 126351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = text[i]; 126451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c >= minDigit && c <= '\u0039') { 126551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski text[i] = (char)(c + base); 126651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 126751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 126851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isStrongDirectional(c)) { 126951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int newkey = getContextKey(c); 127051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (newkey != lastkey) { 127151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastkey = newkey; 127251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 127351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ctxKey = newkey; 127451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (((mask & EASTERN_ARABIC) != 0) && 127551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (ctxKey == ARABIC_KEY || 127651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ctxKey == EASTERN_ARABIC_KEY)) { 127751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ctxKey = EASTERN_ARABIC_KEY; 127851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (((mask & ARABIC) != 0) && 127951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (ctxKey == ARABIC_KEY || 128051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ctxKey == EASTERN_ARABIC_KEY)) { 128151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ctxKey = ARABIC_KEY; 128251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if ((mask & (1<<ctxKey)) == 0) { 128351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ctxKey = EUROPEAN_KEY; 128451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 128551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 128651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski base = bases[ctxKey]; 128751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 128851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minDigit = ctxKey == ETHIOPIC_KEY ? '1' : '0'; // Ethiopic doesn't use decimal zero 128951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 129051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 129151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 129251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 129351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 129451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 129551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void shapeContextually(char[] text, int start, int count, Range ctxKey) { 129651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // if we don't support the specified context, then don't shape. 129751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ctxKey == null || !rangeSet.contains(ctxKey)) { 129851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ctxKey = Range.EUROPEAN; 129951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 130051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 130151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Range lastKey = ctxKey; 130251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int base = ctxKey.getDigitBase(); 130351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char minDigit = (char)('0' + ctxKey.getNumericBase()); 130451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski final int end = start + count; 130551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = start; i < end; ++i) { 130651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = text[i]; 130751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c >= minDigit && c <= '9') { 130851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski text[i] = (char)(c + base); 130951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 131051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 131151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isStrongDirectional(c)) { 131251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ctxKey = rangeForCodePoint(c); 131351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ctxKey != lastKey) { 131451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastKey = ctxKey; 131551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski base = ctxKey.getDigitBase(); 131651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minDigit = (char)('0' + ctxKey.getNumericBase()); 131751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 131851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 131951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 132051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 132151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 132251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 132351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a hash code for this shaper. 132451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return this shaper's hash code. 132551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.lang.Object#hashCode 132651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 132751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int hashCode() { 132851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int hash = mask; 132951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet != null) { 133051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Use the CONTEXTUAL_MASK bit only for the enum-based 133151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // NumericShaper. A deserialized NumericShaper might have 133251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // bit masks. 133351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hash &= CONTEXTUAL_MASK; 133451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hash ^= rangeSet.hashCode(); 133551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 133651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return hash; 133751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 133851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 133951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 134051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns {@code true} if the specified object is an instance of 134151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>NumericShaper</code> and shapes identically to this one, 134251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * regardless of the range representations, the bit mask or the 134351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * enum. For example, the following code produces {@code "true"}. 134451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre> 134551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper ns1 = NumericShaper.getShaper(NumericShaper.ARABIC); 134651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NumericShaper ns2 = NumericShaper.getShaper(NumericShaper.Range.ARABIC); 134751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * System.out.println(ns1.equals(ns2)); 134851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote> 134951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 135051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param o the specified object to compare to this 135151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>NumericShaper</code> 135251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if <code>o</code> is an instance 135351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of <code>NumericShaper</code> and shapes in the same way; 135451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>false</code> otherwise. 135551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.lang.Object#equals(java.lang.Object) 135651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 135751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean equals(Object o) { 135851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (o != null) { 135951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 136051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski NumericShaper rhs = (NumericShaper)o; 136151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet != null) { 136251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rhs.rangeSet != null) { 136351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return isContextual() == rhs.isContextual() 136451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && rangeSet.equals(rhs.rangeSet) 136551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && shapingRange == rhs.shapingRange; 136651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 136751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return isContextual() == rhs.isContextual() 136851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && rangeSet.equals(Range.maskToRangeSet(rhs.mask)) 136951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && shapingRange == Range.indexToRange(rhs.key); 137051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (rhs.rangeSet != null) { 137151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Set<Range> rset = Range.maskToRangeSet(mask); 137251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Range srange = Range.indexToRange(key); 137351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return isContextual() == rhs.isContextual() 137451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && rset.equals(rhs.rangeSet) 137551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && srange == rhs.shapingRange; 137651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 137751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return rhs.mask == mask && rhs.key == key; 137851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 137951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski catch (ClassCastException e) { 138051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 138151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 138251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 138351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 138451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 138551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 138651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a <code>String</code> that describes this shaper. This method 138751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is used for debugging purposes only. 138851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>String</code> describing this shaper. 138951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 139051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String toString() { 139151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuilder buf = new StringBuilder(super.toString()); 139251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 139351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf.append("[contextual:").append(isContextual()); 139451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 139551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String[] keyNames = null; 139651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isContextual()) { 139751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf.append(", context:"); 139851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf.append(shapingRange == null ? Range.values()[key] : shapingRange); 139951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 140051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 140151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet == null) { 140251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf.append(", range(s): "); 140351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean first = true; 140451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < NUM_KEYS; ++i) { 140551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((mask & (1 << i)) != 0) { 140651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (first) { 140751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski first = false; 140851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 140951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf.append(", "); 141051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 141151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf.append(Range.values()[i]); 141251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 141351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 141451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 141551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf.append(", range set: ").append(rangeSet); 141651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 141751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf.append(']'); 141851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 141951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buf.toString(); 142051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 142151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 142251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 142351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the index of the high bit in value (assuming le, actually 142451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * power of 2 >= value). value must be positive. 142551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 142651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int getHighBit(int value) { 142751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value <= 0) { 142851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -32; 142951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 143051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 143151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int bit = 0; 143251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 143351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value >= 1 << 16) { 143451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value >>= 16; 143551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bit += 16; 143651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 143751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 143851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value >= 1 << 8) { 143951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value >>= 8; 144051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bit += 8; 144151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 144251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 144351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value >= 1 << 4) { 144451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value >>= 4; 144551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bit += 4; 144651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 144751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 144851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value >= 1 << 2) { 144951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value >>= 2; 145051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bit += 2; 145151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 145251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 145351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value >= 1 << 1) { 145451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bit += 1; 145551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 145651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 145751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return bit; 145851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 145951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 146051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 146151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * fast binary search over subrange of array. 146251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 146351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int search(int value, int[] array, int start, int length) 146451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 146551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int power = 1 << getHighBit(length); 146651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int extra = length - power; 146751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int probe = power; 146851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = start; 146951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 147051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value >= array[index + extra]) { 147151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski index += extra; 147251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 147351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 147451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (probe > 1) { 147551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski probe >>= 1; 147651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 147751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value >= array[index + probe]) { 147851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski index += probe; 147951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 148051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 148151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 148251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index; 148351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 148451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 148551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 148651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Converts the {@code NumericShaper.Range} enum-based parameters, 148751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if any, to the bit mask-based counterparts and writes this 148851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object to the {@code stream}. Any enum constants that have no 148951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * bit mask-based counterparts are ignored in the conversion. 149051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 149151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param stream the output stream to write to 149251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an I/O error occurs while writing to {@code stream} 149351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.7 149451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 149551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeObject(ObjectOutputStream stream) throws IOException { 149651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (shapingRange != null) { 149751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = Range.toRangeIndex(shapingRange); 149851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (index >= 0) { 149951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski key = index; 150051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 150151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 150251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rangeSet != null) { 150351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski mask |= Range.toRangeMask(rangeSet); 150451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 150551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stream.defaultWriteObject(); 150651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 150751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 1508