src/java.desktop/share/classes/java/awt/font/NumericShaper.java

Print this page




  72  *     NumericShaper.getContextualShaper(NumericShaper.ARABIC |
  73  *                                         NumericShaper.TAMIL,
  74  *                                       NumericShaper.EUROPEAN);
  75  * shaper.shape(text, start, count);
  76  * </pre></blockquote>
  77  *
  78  * <p><b>Bit mask- and enum-based Unicode ranges</b></p>
  79  *
  80  * <p>This class supports two different programming interfaces to
  81  * represent Unicode ranges for script-specific digits: bit
  82  * mask-based ones, such as {@link #ARABIC NumericShaper.ARABIC}, and
  83  * enum-based ones, such as {@link NumericShaper.Range#ARABIC}.
  84  * Multiple ranges can be specified by ORing bit mask-based constants,
  85  * such as:
  86  * <blockquote><pre>
  87  * NumericShaper.ARABIC | NumericShaper.TAMIL
  88  * </pre></blockquote>
  89  * or creating a {@code Set} with the {@link NumericShaper.Range}
  90  * constants, such as:
  91  * <blockquote><pre>
  92  * EnumSet.of(NumericShaper.Scirpt.ARABIC, NumericShaper.Range.TAMIL)
  93  * </pre></blockquote>
  94  * The enum-based ranges are a super set of the bit mask-based ones.
  95  *
  96  * <p>If the two interfaces are mixed (including serialization),
  97  * Unicode range values are mapped to their counterparts where such
  98  * mapping is possible, such as {@code NumericShaper.Range.ARABIC}
  99  * from/to {@code NumericShaper.ARABIC}.  If any unmappable range
 100  * values are specified, such as {@code NumericShaper.Range.BALINESE},
 101  * those ranges are ignored.
 102  *
 103  * <p><b>Decimal Digits Precedence</b></p>
 104  *
 105  * <p>A Unicode range may have more than one set of decimal digits. If
 106  * multiple decimal digits sets are specified for the same Unicode
 107  * range, one of the sets will take precedence as follows.
 108  *
 109  * <table border=1 cellspacing=3 cellpadding=0 summary="NumericShaper constants precedence.">
 110  *    <tr>
 111  *       <th class="TableHeadingColor">Unicode Range</th>
 112  *       <th class="TableHeadingColor"><code>NumericShaper</code> Constants</th>


 458     public static final int LAO = 1<<13;
 459 
 460     /** Identifies the TIBETAN range and decimal base. */
 461     public static final int TIBETAN = 1<<14;
 462 
 463     /** Identifies the MYANMAR range and decimal base. */
 464     public static final int MYANMAR = 1<<15;
 465 
 466     /** Identifies the ETHIOPIC range and decimal base. */
 467     public static final int ETHIOPIC = 1<<16;
 468 
 469     /** Identifies the KHMER range and decimal base. */
 470     public static final int KHMER = 1<<17;
 471 
 472     /** Identifies the MONGOLIAN range and decimal base. */
 473     public static final int MONGOLIAN = 1<<18;
 474 
 475     /** Identifies all ranges, for full contextual shaping.
 476      *
 477      * <p>This constant specifies all of the bit mask-based
 478      * ranges. Use {@code EmunSet.allOf(NumericShaper.Range.class)} to
 479      * specify all of the enum-based ranges.
 480      */
 481     public static final int ALL_RANGES = 0x0007ffff;
 482 
 483     private static final int EUROPEAN_KEY = 0;
 484     private static final int ARABIC_KEY = 1;
 485     private static final int EASTERN_ARABIC_KEY = 2;
 486     private static final int DEVANAGARI_KEY = 3;
 487     private static final int BENGALI_KEY = 4;
 488     private static final int GURMUKHI_KEY = 5;
 489     private static final int GUJARATI_KEY = 6;
 490     private static final int ORIYA_KEY = 7;
 491     private static final int TAMIL_KEY = 8;
 492     private static final int TELUGU_KEY = 9;
 493     private static final int KANNADA_KEY = 10;
 494     private static final int MALAYALAM_KEY = 11;
 495     private static final int THAI_KEY = 12;
 496     private static final int LAO_KEY = 13;
 497     private static final int TIBETAN_KEY = 14;
 498     private static final int MYANMAR_KEY = 15;


1051         if (defaultContext == null) {
1052             throw new NullPointerException();
1053         }
1054         NumericShaper shaper = new NumericShaper(defaultContext, ranges);
1055         shaper.mask = CONTEXTUAL_MASK;
1056         return shaper;
1057     }
1058 
1059     /**
1060      * Private constructor.
1061      */
1062     private NumericShaper(int key, int mask) {
1063         this.key = key;
1064         this.mask = mask;
1065     }
1066 
1067     private NumericShaper(Range defaultContext, Set<Range> ranges) {
1068         shapingRange = defaultContext;
1069         rangeSet = EnumSet.copyOf(ranges); // throws NPE if ranges is null.
1070 
1071         // Give precedance to EASTERN_ARABIC if both ARABIC and
1072         // EASTERN_ARABIC are specified.
1073         if (rangeSet.contains(Range.EASTERN_ARABIC)
1074             && rangeSet.contains(Range.ARABIC)) {
1075             rangeSet.remove(Range.ARABIC);
1076         }
1077 
1078         // As well as the above case, give precedance to TAI_THAM_THAM if both
1079         // TAI_THAM_HORA and TAI_THAM_THAM are specified.
1080         if (rangeSet.contains(Range.TAI_THAM_THAM)
1081             && rangeSet.contains(Range.TAI_THAM_HORA)) {
1082             rangeSet.remove(Range.TAI_THAM_HORA);
1083         }
1084 
1085         rangeArray = rangeSet.toArray(new Range[rangeSet.size()]);
1086         if (rangeArray.length > BSEARCH_THRESHOLD) {
1087             // sort rangeArray for binary search
1088             Arrays.sort(rangeArray,
1089                         new Comparator<Range>() {
1090                             public int compare(Range s1, Range s2) {
1091                                 return s1.base > s2.base ? 1 : s1.base == s2.base ? 0 : -1;
1092                             }
1093                         });
1094         }
1095     }
1096 
1097     /**
1098      * Converts the digits in the text that occur between start and




  72  *     NumericShaper.getContextualShaper(NumericShaper.ARABIC |
  73  *                                         NumericShaper.TAMIL,
  74  *                                       NumericShaper.EUROPEAN);
  75  * shaper.shape(text, start, count);
  76  * </pre></blockquote>
  77  *
  78  * <p><b>Bit mask- and enum-based Unicode ranges</b></p>
  79  *
  80  * <p>This class supports two different programming interfaces to
  81  * represent Unicode ranges for script-specific digits: bit
  82  * mask-based ones, such as {@link #ARABIC NumericShaper.ARABIC}, and
  83  * enum-based ones, such as {@link NumericShaper.Range#ARABIC}.
  84  * Multiple ranges can be specified by ORing bit mask-based constants,
  85  * such as:
  86  * <blockquote><pre>
  87  * NumericShaper.ARABIC | NumericShaper.TAMIL
  88  * </pre></blockquote>
  89  * or creating a {@code Set} with the {@link NumericShaper.Range}
  90  * constants, such as:
  91  * <blockquote><pre>
  92  * EnumSet.of(NumericShaper.Range.ARABIC, NumericShaper.Range.TAMIL)
  93  * </pre></blockquote>
  94  * The enum-based ranges are a super set of the bit mask-based ones.
  95  *
  96  * <p>If the two interfaces are mixed (including serialization),
  97  * Unicode range values are mapped to their counterparts where such
  98  * mapping is possible, such as {@code NumericShaper.Range.ARABIC}
  99  * from/to {@code NumericShaper.ARABIC}.  If any unmappable range
 100  * values are specified, such as {@code NumericShaper.Range.BALINESE},
 101  * those ranges are ignored.
 102  *
 103  * <p><b>Decimal Digits Precedence</b></p>
 104  *
 105  * <p>A Unicode range may have more than one set of decimal digits. If
 106  * multiple decimal digits sets are specified for the same Unicode
 107  * range, one of the sets will take precedence as follows.
 108  *
 109  * <table border=1 cellspacing=3 cellpadding=0 summary="NumericShaper constants precedence.">
 110  *    <tr>
 111  *       <th class="TableHeadingColor">Unicode Range</th>
 112  *       <th class="TableHeadingColor"><code>NumericShaper</code> Constants</th>


 458     public static final int LAO = 1<<13;
 459 
 460     /** Identifies the TIBETAN range and decimal base. */
 461     public static final int TIBETAN = 1<<14;
 462 
 463     /** Identifies the MYANMAR range and decimal base. */
 464     public static final int MYANMAR = 1<<15;
 465 
 466     /** Identifies the ETHIOPIC range and decimal base. */
 467     public static final int ETHIOPIC = 1<<16;
 468 
 469     /** Identifies the KHMER range and decimal base. */
 470     public static final int KHMER = 1<<17;
 471 
 472     /** Identifies the MONGOLIAN range and decimal base. */
 473     public static final int MONGOLIAN = 1<<18;
 474 
 475     /** Identifies all ranges, for full contextual shaping.
 476      *
 477      * <p>This constant specifies all of the bit mask-based
 478      * ranges. Use {@code EnumSet.allOf(NumericShaper.Range.class)} to
 479      * specify all of the enum-based ranges.
 480      */
 481     public static final int ALL_RANGES = 0x0007ffff;
 482 
 483     private static final int EUROPEAN_KEY = 0;
 484     private static final int ARABIC_KEY = 1;
 485     private static final int EASTERN_ARABIC_KEY = 2;
 486     private static final int DEVANAGARI_KEY = 3;
 487     private static final int BENGALI_KEY = 4;
 488     private static final int GURMUKHI_KEY = 5;
 489     private static final int GUJARATI_KEY = 6;
 490     private static final int ORIYA_KEY = 7;
 491     private static final int TAMIL_KEY = 8;
 492     private static final int TELUGU_KEY = 9;
 493     private static final int KANNADA_KEY = 10;
 494     private static final int MALAYALAM_KEY = 11;
 495     private static final int THAI_KEY = 12;
 496     private static final int LAO_KEY = 13;
 497     private static final int TIBETAN_KEY = 14;
 498     private static final int MYANMAR_KEY = 15;


1051         if (defaultContext == null) {
1052             throw new NullPointerException();
1053         }
1054         NumericShaper shaper = new NumericShaper(defaultContext, ranges);
1055         shaper.mask = CONTEXTUAL_MASK;
1056         return shaper;
1057     }
1058 
1059     /**
1060      * Private constructor.
1061      */
1062     private NumericShaper(int key, int mask) {
1063         this.key = key;
1064         this.mask = mask;
1065     }
1066 
1067     private NumericShaper(Range defaultContext, Set<Range> ranges) {
1068         shapingRange = defaultContext;
1069         rangeSet = EnumSet.copyOf(ranges); // throws NPE if ranges is null.
1070 
1071         // Give precedence to EASTERN_ARABIC if both ARABIC and
1072         // EASTERN_ARABIC are specified.
1073         if (rangeSet.contains(Range.EASTERN_ARABIC)
1074             && rangeSet.contains(Range.ARABIC)) {
1075             rangeSet.remove(Range.ARABIC);
1076         }
1077 
1078         // As well as the above case, give precedence to TAI_THAM_THAM if both
1079         // TAI_THAM_HORA and TAI_THAM_THAM are specified.
1080         if (rangeSet.contains(Range.TAI_THAM_THAM)
1081             && rangeSet.contains(Range.TAI_THAM_HORA)) {
1082             rangeSet.remove(Range.TAI_THAM_HORA);
1083         }
1084 
1085         rangeArray = rangeSet.toArray(new Range[rangeSet.size()]);
1086         if (rangeArray.length > BSEARCH_THRESHOLD) {
1087             // sort rangeArray for binary search
1088             Arrays.sort(rangeArray,
1089                         new Comparator<Range>() {
1090                             public int compare(Range s1, Range s2) {
1091                                 return s1.base > s2.base ? 1 : s1.base == s2.base ? 0 : -1;
1092                             }
1093                         });
1094         }
1095     }
1096 
1097     /**
1098      * Converts the digits in the text that occur between start and