diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:28:47 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:28:47 -0800 |
commit | adc854b798c1cfe3bfd4c27d68d5cee38ca617da (patch) | |
tree | 6aed8b4923ca428942cbaa7e848d50237a3d31e0 /awt-kernel/src/main/java | |
parent | 1c0fed63c71ddb230f3b304aac12caffbedf2f21 (diff) | |
download | libcore-adc854b798c1cfe3bfd4c27d68d5cee38ca617da.zip libcore-adc854b798c1cfe3bfd4c27d68d5cee38ca617da.tar.gz libcore-adc854b798c1cfe3bfd4c27d68d5cee38ca617da.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'awt-kernel/src/main/java')
7 files changed, 1968 insertions, 0 deletions
diff --git a/awt-kernel/src/main/java/java/awt/font/NumericShaper.java b/awt-kernel/src/main/java/java/awt/font/NumericShaper.java new file mode 100644 index 0000000..e8ea693 --- /dev/null +++ b/awt-kernel/src/main/java/java/awt/font/NumericShaper.java @@ -0,0 +1,885 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @author Ilya S. Okomin + * @version $Revision$ + */ +package java.awt.font; + +import java.io.IOException; +import java.io.Serializable; + +// BEGIN android-deleted +//import org.apache.harmony.awt.internal.nls.Messages; +// END android-deleted +import org.apache.harmony.misc.HashCode; + + +/** + * The Class NumericShaper provides methods to convert latin character codes + * to unicode character codes. + * For tables of the character codes used, + * see <a href="http://www.unicode.org/Public/UNIDATA/">unicode.org</a>. + */ +public final class NumericShaper implements Serializable { + + /** The Constant serialVersionUID. */ + private static final long serialVersionUID = -8022764705923730308L; + + /** + * The Constant EUROPEAN indicates the latin and extended range, + * and latin decimal base. + */ + public static final int EUROPEAN = 1; + + /** The Constant ARABIC indicates the ARABIC range and decimal base. */ + public static final int ARABIC = 2; + + /** + * The Constant EASTERN_ARABIC indicates the ARABIC range and + * ARABIC_EXTENDED decimal base. + */ + public static final int EASTERN_ARABIC = 4; + + /** + * The Constant DEVANAGARI indicates the DEVANAGARI range and + * decimal base. + */ + public static final int DEVANAGARI = 8; + + /** The Constant BENGALI indicates the BENGALI range and decimal base. */ + public static final int BENGALI = 16; + + /** The Constant GURMUKHI indicates the GURMUKHI range and decimal base. */ + public static final int GURMUKHI = 32; + + /** The Constant GUJARATI indicates the GUJARATI range and decimal base. */ + public static final int GUJARATI = 64; + + /** The Constant ORIYA indicates the ORIYA range and decimal base. */ + public static final int ORIYA = 128; + + /** The Constant TAMIL indicates the TAMIL range and decimal base. */ + public static final int TAMIL = 256; + + /** The Constant TELUGU indicates the TELUGU range and decimal base. */ + public static final int TELUGU = 512; + + /** The Constant KANNADA indicates the KANNADA range and decimal base. */ + public static final int KANNADA = 1024; + + /** + * The Constant MALAYALAM indicates the MALAYALAM range and decimal base. + */ + public static final int MALAYALAM = 2048; + + /** The Constant THAI indicates the THAI range and decimal base. */ + public static final int THAI = 4096; + + /** The Constant LAO indicates the LAO range and decimal base. */ + public static final int LAO = 8192; + + /** The Constant TIBETAN indicates the TIBETAN range and decimal base. */ + public static final int TIBETAN = 16384; + + /** The Constant MYANMAR indicates the MYANMAR range and decimal base. */ + public static final int MYANMAR = 32768; + + /** + * The Constant ETHIOPIC indicates the ETHIOPIC range and decimal base. + */ + public static final int ETHIOPIC = 65536; + + /** The Constant KHMER indicates the KHMER range and decimal base. */ + public static final int KHMER = 131072; + + /** + * The Constant MONGOLIAN indicates the MONGOLIAN range and + * decimal base. + */ + public static final int MONGOLIAN = 262144; + + /** The Constant ALL_RANGES indicates all ranges. */ + public static final int ALL_RANGES = 524287; + + /* Further one can find the set of script indices. + * Index is the power you need the 2 to raise to to get corresponding + * range constant value. Also script ranges, context names and digits low + * ranges are indexed with these indices. + */ + + // Index of the EUROPEAN range + /** The Constant INDEX_EUROPEAN. */ + private static final int INDEX_EUROPEAN = 0; + + // Index of the ARABIC range + /** The Constant INDEX_ARABIC. */ + private static final int INDEX_ARABIC = 1; + + // Index of the EASTERN_ARABIC range + /** The Constant INDEX_EASTERN_ARABIC. */ + private static final int INDEX_EASTERN_ARABIC = 2; + + // Index of the DEVANAGARI range + /** The Constant INDEX_DEVANAGARI. */ + private static final int INDEX_DEVANAGARI = 3; + + // Index of the BENGALI range + /** The Constant INDEX_BENGALI. */ + private static final int INDEX_BENGALI = 4; + + // Index of the GURMUKHI range + /** The Constant INDEX_GURMUKHI. */ + private static final int INDEX_GURMUKHI = 5; + + // Index of the GUJARTI range + /** The Constant INDEX_GUJARATI. */ + private static final int INDEX_GUJARATI = 6; + + // Index of the ORIYA range + /** The Constant INDEX_ORIYA. */ + private static final int INDEX_ORIYA = 7; + + // Index of the TAMIL range + /** The Constant INDEX_TAMIL. */ + private static final int INDEX_TAMIL = 8; + + // Index of the TELUGU range + /** The Constant INDEX_TELUGU. */ + private static final int INDEX_TELUGU = 9; + + // Index of the KANNADA range + /** The Constant INDEX_KANNADA. */ + private static final int INDEX_KANNADA = 10; + + // Index of the MALAYALAM range + /** The Constant INDEX_MALAYALAM. */ + private static final int INDEX_MALAYALAM = 11; + + // Index of the THAI range + /** The Constant INDEX_THAI. */ + private static final int INDEX_THAI = 12; + + // Index of the LAO range + /** The Constant INDEX_LAO. */ + private static final int INDEX_LAO = 13; + + // Index of the TIBETAN range + /** The Constant INDEX_TIBETAN. */ + private static final int INDEX_TIBETAN = 14; + + // Index of the MYANMAR range + /** The Constant INDEX_MYANMAR. */ + private static final int INDEX_MYANMAR = 15; + + // Index of the ETHIOPIC range + /** The Constant INDEX_ETHIOPIC. */ + private static final int INDEX_ETHIOPIC = 16; + + // Index of the KHMER range + /** The Constant INDEX_KHMER. */ + private static final int INDEX_KHMER = 17; + + // Index of the MONGOLIAN range + /** The Constant INDEX_MONGOLIAN. */ + private static final int INDEX_MONGOLIAN = 18; + + // Maximum index that range can't exceed + /** The Constant MAX_INDEX. */ + private static final int MAX_INDEX = 19; + + /* + * Scripts ranges array. Array represents ranges as pairs of + * lowest and highest range bounds. + * Data is taken from the UnicodeData.txt file from + * http://www.unicode.org/Public/UNIDATA/ + */ + /** The scripts ranges. */ + private final int[] scriptsRanges = { + 0x0000, 0x024F, // EUROPEAN (basic latin + latin-1 + extended) + 0x0600, 0x06FF, // ARABIC + 0x0600, 0x06FF, // EASTERN_ARABIC (XXX: diff with ARABIC ? ) + 0x0900, 0x097F, // DEVANAGARI + 0x0980, 0x09FF, // BENGALI + 0x0A00, 0x0A7F, // GURMUKHI + 0x0A80, 0x0AFF, // GUJARATI + 0x0B00, 0x0B7F, // ORIYA + 0x0B80, 0x0BFF, // TAMIL + 0x0C00, 0x0C7F, // TELUGU + 0x0C80, 0x0CFF, // KANNADA + 0x0D00, 0x0D7F, // MALAYALAM + 0x0E00, 0x0E7F, // THAI + 0x0E80, 0x0EFF, // LAO + 0x0F00, 0x0FFF, // TIBETAN + 0x1000, 0x109F, // MYANMAR + 0x1200, 0x137F, // ETHIOPIC + 0x1780, 0x17FF, // KHMER + 0x1800, 0x18AF // MONGOLIAN + }; + + /* + * Digit low ranges values decreased by 0x0030. Each low range + * value decreased by 0x0030 for easy obtaing unicode value of the + * context dependent digit. European digits starts from 0x0030 hence + * context dependent unicode digit value equals to + * digitsLowRanges[script index] + european digit char unicode value. + * !! the only exception is ETHIOPIC script where there is no '0' digit + * Data is taken from the UnicodeData.txt file from + * http://www.unicode.org/Public/UNIDATA/ + */ + /** The digits low ranges. */ + private final int[] digitsLowRanges = { + 0x0000, // EUROPEAN + 0x0630, // ARABIC + 0x0630, // EASTERN_ARABIC + 0x0936, // DEVANAGARI + 0x09B6, // BENGALI + 0x0A36, // GURMUKHI + 0x0AB6, // GUJARATI + 0x0B36, // ORIYA + 0x0BB6, // TAMIL + 0x0C36, // TELUGU + 0x0CB6, // KANNADA + 0x0D36, // MALAYALAM + 0x0E20, // THAI + 0x0EA0, // LAO + 0x0EF0, // TIBETAN + 0x1010, // MYANMAR + 0x1338, // ETHIOPIC - (low range-1) no ETHIOPIC '0' DIGIT! + 0x17B0, // KHMER + 0x17E0 // MONGOLIAN + }; + + // Set of context names used in toString method + /** The contexts. */ + private final String[] contexts = { + "EUROPEAN", //$NON-NLS-1$ + "ARABIC", //$NON-NLS-1$ + "EASTERN_ARABIC", //$NON-NLS-1$ + "DEVANAGARI", //$NON-NLS-1$ + "BENGALI", //$NON-NLS-1$ + "GURMUKHI", //$NON-NLS-1$ + "GUJARATI", //$NON-NLS-1$ + "ORIYA", //$NON-NLS-1$ + "TAMIL", //$NON-NLS-1$ + "TELUGU", //$NON-NLS-1$ + "KANNADA", //$NON-NLS-1$ + "MALAYALAM", //$NON-NLS-1$ + "THAI", //$NON-NLS-1$ + "LAO", //$NON-NLS-1$ + "TIBETAN", //$NON-NLS-1$ + "MYANMAR", //$NON-NLS-1$ + "ETHIOPIC", //$NON-NLS-1$ + "KHMER", //$NON-NLS-1$ + "MONGOLIAN" //$NON-NLS-1$ + }; + + /* + * Strong characters flags array is to determine if the + * unicode bidirectional category of the character is strong, + * according to Unicode specification. If the bit with index equals to + * character's unicode value is 1 - the character is strong. + * This array was generated using UnicodeData.txt file from + * http://www.unicode.org/Public/UNIDATA/ + */ + + /** The Constant STRONG_TEXT_FLAGS. */ + private static final int[] STRONG_TEXT_FLAGS = { 0, 0, 134217726, 134217726, + 0, 69207040, -8388609, -8388609, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -65533, -1, -1, -100663297, 196611, 16415, 0, 0, 0, + 67108864, -10432, -5, -32769, -4194305, -1, -1, -1, -1, -1017, -1, + -32769, 67108863, 65535, -131072, -25165825, -2, 767, 1073741824, + -65463, 2033663, -939513841, 134217726, 2047, -73728, -1, -1, + 541065215, -67059616, -180225, 65535, -8192, 16383, -1, 131135, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, -469762049, -16703999, 537001971, + -417812, -473563649, -1333765759, 133431235, -423960, -1016201729, + 1577058305, 1900480, -278552, -470942209, 72193, 65475, -417812, + 1676541439, -1333782143, 262083, -700594200, -1006647528, 8396230, + 524224, -139282, 66059775, 30, 65475, -139284, -470811137, + 1080036831, 65475, -139284, -1006633473, 8396225, 65475, -58720276, + 805044223, -16547713, 1835008, -2, 917503, 268402815, 0, -17816170, + 537783470, 872349791, 0, -50331649, -1050673153, -257, -2147481601, + 3872, -1073741824, 237503, 0, -1, 16914171, 16777215, 0, 0, -1, + -65473, 536870911, -1, -1, -2080374785, -1, -1, -249, -1, 67108863, + -1, -1, 1031749119, -1, -49665, 2134769663, -8388803, -1, + -12713985, -1, 134217727, 536870911, 65535, -1, -1, 2097151, -2, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 8388607, 134217726, -1, -1, 131071, 253951, 6553599, 262143, + 122879, -1, -1065353217, 401605055, 1023, 67043328, -1, -1, + 16777215, -1, 511, 0, 0, 536870911, 33226872, -64, 2047999, -1, + -64513, 67044351, 0, -830472193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, 0, 0, + -1, -1, -1, -1, 268435455, -1, -1, 67108863, 1061158911, -1, + -1426112705, 1073741823, -1, 1608515583, 265232348, 534519807, + 49152, 27648, 0, -2147352576, 2031616, 0, 0, 0, 1043332228, + -201605808, 992, -1, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -4194304, -1, 134217727, 2097152, 0, 0, 0, 0, 0, 0, 0, -268435456, + -1, -1, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4096, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + -32769, 2147483647, 0, -1, -1, -1, 31, -1, -65473, -1, 32831, + 8388607, 2139062143, 2139062143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 224, 524157950, -2, -1, -528482305, -2, -1, + -134217729, -32, -122881, -1, -1, -32769, 16777215, 0, -65536, + 536870911, -1, 15, -1879048193, -1, 131071, -61441, 2147483647, -1, + -1, -1, -125829121, -1, -1, 1073741823, 2147483647, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2097152, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 134217728, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 8191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2117, 159, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2147483648, 1, 0, 0, -2147483648, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -2147483648, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2147483648, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -49153, -1, -63489, -1, -1, 67108863, 0, + -1594359681, 1602223615, -37, -1, -1, 262143, -524288, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 1073741823, -65536, -1, -196609, -1, + 255, 536805376, 0, 0, 0, -2162688, -1, -1, -1, 536870911, 0, + 134217726, 134217726, -64, -1, 2147483647, 486341884, 0 + + }; + + // index of context range (Serialization support) + /** The key. */ + private int key; + + // flag, true if shaping contextual (Serialization support) + /** The mask. */ + private int mask; + + // ranges to be shaped + /** The ranges. */ + private int fRanges; + + // index of the default context + /** The default context index. */ + private int fDefaultContextIndex; + + // flag if NumericShaper shapes contextually + /** The contextual. */ + private boolean fContextual; + + // uses for non-context dependent case only + /** The single range index. */ + private int fSingleRangeIndex; + + /** + * Creates NumericShaper with specified parameters. + * + * @param ranges specified ranges to be shaped + * @param defaultContext default context range + * @param isContextual specifies if the instance is contextual + */ + private NumericShaper(int ranges, int defaultContext, boolean isContextual){ + this.fRanges = ranges; + this.fDefaultContextIndex = getIndexFromRange(defaultContext); + this.fContextual = isContextual; + + if (!fContextual){ + fSingleRangeIndex = getIndexFromRange(ranges); + } + } + + /** + * Returns script index of the specified context range. + * + * @param range specified range + * + * @return one of the script indices according to the specified range. + */ + private int getIndexFromRange(int range){ + if (range == 0){ + // BEGIN android-changed + throwRange(range); + // END android-changed + } + + int index = 0; + while (index < MAX_INDEX){ + if (range == (1 << index)){ + return index; + } + index++; + } + + // BEGIN android-changed + throwRange(range); + return -1; // Never executed; quiets the compiler. + // END android-changed + } + + /** + * Returns range corresponding to the specified script index. + * + * @param index specified script index + * + * @return one of the range constants according to the specified script index. + */ + private int getRangeFromIndex(int index){ + if (index < 0 || index >= MAX_INDEX){ + // BEGIN android-changed + throwRange(index); + // END android-changed + } + + return 1 << index; + } + + // BEGIN android-added + /** + * Throws a standard "out of range" exception. + * + * @param value the bogus value + */ + private static void throwRange(int value) { + throw new IllegalArgumentException( + "Illegal range argument value: " + value); + } + // END android-added + + /** + * Returns a hash code of this NumericShaper. + * + * @return a hash code of this NumericShaper. + */ + @Override + public int hashCode() { + HashCode hash = new HashCode(); + + hash.append(fRanges); + hash.append(fDefaultContextIndex); + hash.append(fContextual); + + return hash.hashCode(); + + } + + /** + * Compares this NumericShaper object with the specified Object. + * + * @param obj the Object to be compared. + * + * @return true, if this NumericShaper object is equal to + * the specified Object, false otherwise. + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (obj == this) { + return true; + } + + try { + NumericShaper ns = (NumericShaper)obj; + return (fRanges == ns.fRanges && + fDefaultContextIndex == ns.fDefaultContextIndex && + fContextual == ns.fContextual); + } catch (ClassCastException e){ + } + + return false; + } + + /** + * Returns a string representation of this NumericShaper. + * + * @return the string representation of this NumericShaper. + */ + @Override + public String toString() { + /* !! There is no description in the documentation what this method must + * return. Thus format of toString method is based on 1.5 release + * behavior and can be obtained using next test sample: + * + * // Simple shapers toString format + * System.out.println(NumericShaper.getShaper(NumericShaper.EASTERN_ARABIC)); + * + * // Context shapers with default context toString format + * System.out.println(NumericShaper.getContextualShaper( + * NumericShaper.ARABIC | NumericShaper.TAMIL)); + * + * // Context shapers with context + * System.out.println(NumericShaper.getContextualShaper( + * NumericShaper.ARABIC | NumericShaper.TAMIL, + * NumericShaper.EASTERN_ARABIC)); + */ + StringBuffer sb = new StringBuffer(super.toString()); + + sb.append("[contextual:"); //$NON-NLS-1$ + sb.append(fContextual); + + if (fContextual){ + sb.append(", context:"); //$NON-NLS-1$ + sb.append(contexts[fDefaultContextIndex]); + } + + sb.append(", range(s): "); //$NON-NLS-1$ + if (fContextual) { + int index = 0; + boolean isFirst = true; + while (index < MAX_INDEX){ + if ((fRanges & (1 << index)) != 0){ + if (isFirst){ + isFirst = false; + } else { + sb.append(", "); //$NON-NLS-1$ + } + sb.append(contexts[index]); + } + index++; + } + } else { + sb.append(contexts[fSingleRangeIndex]); + } + sb.append("]"); //$NON-NLS-1$ + + return sb.toString(); + } + + /** + * Gets the NumericShaper for the specified unicode ranges + * and default unicode range. The defaultContext parameter + * is used as the starting context (which indicates the + * language/script being used). The OR logical operation + * should be used for multiple ranges: + * NumericShaper.DEVANAGARI | NumericShaper.BENGALI. + * The NumericShaper returned by this method is contextual + * in that it supports multiple character ranges, depending + * on the context. + * + * @param ranges the unicode ranges. + * @param defaultContext the default, starting context. + * + * @return the NumericShaper for the specified ranges. + */ + public static NumericShaper getContextualShaper(int ranges, + int defaultContext) { + ranges &= ALL_RANGES; + defaultContext &= ALL_RANGES; + return new NumericShaper(ranges, defaultContext, true); + } + + /** + * Gets the NumericShaper for the specified unicode ranges. + * The OR logical operation should be used for multiple ranges: + * NumericShaper.DEVANAGARI | NumericShaper.BENGALI. + * The NumericShaper returned by this method is contextual + * in that it supports multiple character ranges, depending + * on the context. + * + * @param ranges the unicode ranges. + * + * @return the NumericShaper for the specified ranges. + */ + public static NumericShaper getContextualShaper(int ranges) { + ranges &= ALL_RANGES; + return new NumericShaper(ranges, EUROPEAN, true); + } + + /** + * Gets the masks for all of the ranges supported by this NumericShaper, + * packed into an int value using the logical OR logical operation + * for multiple ranges: + * NumericShaper.DEVANAGARI | NumericShaper.BENGALI. + * + * @return all ranges of this NumericShaper. + */ + public int getRanges() { + return fRanges; + } + + /** + * Gets a NumericShaper for the specified unicode range. + * The NumericShaper supports only a single range and + * hence is not contextual. + * + * @param singleRange the specified unicode single range. + * + * @return the NumericShaper for the specified unicode range. + */ + public static NumericShaper getShaper(int singleRange) { + singleRange &= ALL_RANGES; + return new NumericShaper(singleRange, EUROPEAN, false); + } + + /** + * Checks if this NumericShaper is contextual (supporting + * multiple script ranges) or not. + * + * @return true, if this NumericShaper is contextual, false otherwise. + */ + public boolean isContextual() { + return fContextual; + } + + /** + * Transforms the encoding of the text, starting from the character + * at index start and transforming count characters, + * using the specified context. + * + * @param text the text to be shaped. + * @param start the start offset of the text. + * @param count the number of characters to be shaped. + * @param context the context to be used for shaping. + */ + public void shape(char[] text, int start, int count, int context) { + if (isContextual()){ + contextualShape(text, start, count, getIndexFromRange(context)); + } else { + nonContextualShape(text, start, count); + } + } + + /** + * Transforms the encoding of the text, starting from the character + * at index start and transforming count characters. + * + * @param text the text to be shaped. + * @param start the start offset of the text. + * @param count the number of characters to be shaped. + */ + public void shape(char[] text, int start, int count) { + if (isContextual()){ + contextualShape(text, start, count, fDefaultContextIndex); + } else { + nonContextualShape(text, start, count); + } + } + + /** + * Converts count of digits of the given array of characters from the start + * index using specified context. This method is applied for the contextual + * shaping, if the shaper instance is not contextual use nonContextualShape + * method. + * + * @param text an array of chars + * @param start index of the first character to convert + * @param count a number of characters to convert + * @param contextIndex index of the script index to use in shaper + */ + private void contextualShape(char[] text, int start, int count, + int contextIndex){ + char maxDigit = (char)0x0039; + char minDigit = (char)0x0030; + + int currIndex; + if (((1 << contextIndex) & fRanges) == 0 ){ + currIndex = INDEX_EUROPEAN; + } else { + currIndex = contextIndex; + } + + for (int ind = start; ind < start + count; ind++){ + if (minDigit <= text[ind] && text[ind] <= maxDigit){ + if (currIndex != INDEX_ETHIOPIC || text[ind] != '0'){ + text[ind] = (char)(digitsLowRanges[currIndex] + text[ind]); + } + } else { + if(isCharStrong(text[ind])){ + int index = getCharIndex(text[ind]); + if (currIndex != index){ + if (((1 << index) & fRanges) != 0){ + currIndex = index; + } else { + currIndex = INDEX_EUROPEAN; + } + } + } + } + } + + } + + /** + * Converts count of digits of the given array of characters from the start + * index. Method is applied for non-contextual shaper. + * + * @param text an array of chars + * @param start index of the first character to convert + * @param count a number of characters to convert + */ + private void nonContextualShape(char[] text, int start, int count){ + char maxDigit = (char)0x0039; + char minDigit = (char)((fRanges == ETHIOPIC) ? 0x0031 : 0x0030); + for (int ind = start; ind < start + count; ind++){ + if (minDigit <= text[ind] && text[ind] <= maxDigit){ + text[ind] = (char)(digitsLowRanges[fSingleRangeIndex] + text[ind]); + } + } + + } + + /** + * Returns the index of the script of the specified char. + * + * @param ch specified unicode character + * + * @return script index corresponding to the given char + */ + private int getCharIndex(char ch){ + int index = INDEX_EUROPEAN; + for (int i=0; i < MAX_INDEX; i++){ + int j = i * 2; + if (scriptsRanges[j] <= ch && ch <= scriptsRanges[j+1]){ + return i; + } + } + + return index; + } + + /** + * Returns true if the bidirectional category of the character + * is strong. + * + * @param chr the chr + * + * @return true, if the character is strong, false otherwise + */ + private boolean isCharStrong(int chr) { + return (STRONG_TEXT_FLAGS[chr >> 5] & (1 << (chr % 32))) != 0; + } + + /** + * Updates all private serialized fields for object to be correctly serialized + * according to the serialized form of this class mentioned in the + * documentation. + */ + private void updateRangesFields(){ + fRanges = (mask & ~(1 << 31)); + fContextual = ((mask &(1 << 31)) != 0); + if (fContextual){ + fRanges = (mask & ~(1 << 31)); + fDefaultContextIndex = key; + } else { + fRanges = mask; + fSingleRangeIndex = key; + } + } + + /** + * Updates private fields for object after deserialization + * according to the serialized form of this class mentioned in the + * documentation. + */ + private void updateKeyMaskFields(){ + mask = fRanges; + if (fContextual){ + mask |= (1 << 31); + key = fDefaultContextIndex; + } else{ + key = fSingleRangeIndex; + } + } + + /** + * Write object. + * + * @param out the out + * + * @throws IOException Signals that an I/O exception has occurred. + */ + private void writeObject(java.io.ObjectOutputStream out) + throws IOException{ + updateKeyMaskFields(); + out.defaultWriteObject(); + } + + /** + * Read object. + * + * @param in the in + * + * @throws IOException Signals that an I/O exception has occurred. + * @throws ClassNotFoundException the class not found exception + */ + private void readObject(java.io.ObjectInputStream in) + throws IOException, ClassNotFoundException{ + in.defaultReadObject(); + updateRangesFields(); + } + +} + diff --git a/awt-kernel/src/main/java/java/awt/font/TextAttribute.java b/awt-kernel/src/main/java/java/awt/font/TextAttribute.java new file mode 100644 index 0000000..aa1394a --- /dev/null +++ b/awt-kernel/src/main/java/java/awt/font/TextAttribute.java @@ -0,0 +1,301 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @author Ilya S. Okomin + * @version $Revision$ + */ +package java.awt.font; + +import java.io.InvalidObjectException; +import java.text.AttributedCharacterIterator.Attribute; +import java.util.HashMap; +import java.util.Map; + +// BEGIN android-deleted +//import org.apache.harmony.awt.internal.nls.Messages; +// END android-deleted + +/** + * The TextAttribute class defines attribute keys and attribute values + * for text rendering. Each TextAttributes should have the following + * information: + * <ul> + * <li>key name;</li> + * <li>valid values;</li> + * <li>relevant constants;</li> + * <li>default action if the attribute is absent;</li> + * <li>default action's description.</li> + * </ul> + */ +public final class TextAttribute extends Attribute { + + /** The Constant serialVersionUID. */ + private static final long serialVersionUID = 7744112784117861702L; + + // set of available text attributes + /** The Constant attrMap. */ + private static final Map<String, TextAttribute> attrMap = new HashMap<String, TextAttribute>(); + + /** + * Instantiates a new TextAttribute with the specified name. + * + * @param name the name of TextAttribute. + */ + protected TextAttribute(String name) { + super(name); + attrMap.put(name, this); + } + + /** + * Resolves the instance being deserialized. + * + * @return the Object. + * + * @throws InvalidObjectException the InvalidObjectException. + */ + @Override + protected Object readResolve() throws InvalidObjectException { + TextAttribute result = attrMap.get(this.getName()); + if (result != null) { + return result; + } + // BEGIN android-changed + throw new InvalidObjectException("Unknown attribute name"); + // END android-changed + } + + /** + * The BACKGROUND text attribute. + */ + public static final TextAttribute BACKGROUND = new TextAttribute("background"); //$NON-NLS-1$ + + /** The BIDI_EMBEDDING text attribute key. */ + public static final TextAttribute BIDI_EMBEDDING = new TextAttribute("bidi_embedding"); //$NON-NLS-1$ + + /** The CHAR_REPLACEMENT text attribute key. */ + public static final TextAttribute CHAR_REPLACEMENT = new TextAttribute("char_replacement"); //$NON-NLS-1$ + + /** The FAMILY text attribute key. */ + public static final TextAttribute FAMILY = new TextAttribute("family"); //$NON-NLS-1$ + + /** The FONT text attribute key. */ + public static final TextAttribute FONT = new TextAttribute("font"); //$NON-NLS-1$ + + /** The FOREGROUND text attribute key. */ + public static final TextAttribute FOREGROUND = new TextAttribute("foreground"); //$NON-NLS-1$ + + /** The INPUT_METHOD_HIGHLIGHT text attribute key. */ + public static final TextAttribute INPUT_METHOD_HIGHLIGHT = new TextAttribute( + "input method highlight"); //$NON-NLS-1$ + + /** The INPUT_METHOD_UNDERLINE text attribute key. */ + public static final TextAttribute INPUT_METHOD_UNDERLINE = new TextAttribute( + "input method underline"); //$NON-NLS-1$ + + /** The JUSTIFICATION text attribute key. */ + public static final TextAttribute JUSTIFICATION = new TextAttribute("justification"); //$NON-NLS-1$ + + /** The Constant JUSTIFICATION_indicates the full requested width. */ + public static final Float JUSTIFICATION_FULL = new Float(1.0f); + + /** + * The Constant JUSTIFICATION_NONE indicates that line is not + * allowed for justification. + */ + public static final Float JUSTIFICATION_NONE = new Float(0.0f); + + /** The NUMERIC_SHAPING text attribute. */ + public static final TextAttribute NUMERIC_SHAPING = new TextAttribute("numeric_shaping"); //$NON-NLS-1$ + + /** The POSTURE text attribute. */ + public static final TextAttribute POSTURE = new TextAttribute("posture"); //$NON-NLS-1$ + + /** The Constant POSTURE_REGULAR indicates regular posture. */ + public static final Float POSTURE_REGULAR = new Float(0.0f); + + /** The Constant POSTURE_OBLIQUE indicates italic posture. */ + public static final Float POSTURE_OBLIQUE = new Float(0.20f); + + /** The RUN_DIRECTION text attribute. */ + public static final TextAttribute RUN_DIRECTION = new TextAttribute("run_direction"); //$NON-NLS-1$ + + /** + * The Constant RUN_DIRECTION_LTR indicates left-to-right run + * direction. + */ + public static final Boolean RUN_DIRECTION_LTR = new Boolean(false); + + /** + * The Constant RUN_DIRECTION_RTL indicates right-to-left run + * direction. + */ + public static final Boolean RUN_DIRECTION_RTL = new Boolean(true); + + /** The SIZE text attribute. */ + public static final TextAttribute SIZE = new TextAttribute("size"); //$NON-NLS-1$ + + /** The STRIKETHROUGH text attribute. */ + public static final TextAttribute STRIKETHROUGH = new TextAttribute("strikethrough"); //$NON-NLS-1$ + + /** The Constant STRIKETHROUGH_ON indicates a single strikethrough. */ + public static final Boolean STRIKETHROUGH_ON = new Boolean(true); + + /** The SUPERSCRIPT text attribute. */ + public static final TextAttribute SUPERSCRIPT = new TextAttribute("superscript"); //$NON-NLS-1$ + + /** The Constant SUPERSCRIPT_SUB indicates a standard subscript. */ + public static final Integer SUPERSCRIPT_SUB = new Integer(-1); + + /** The Constant SUPERSCRIPT_SUPER indicates a standard superscript. */ + public static final Integer SUPERSCRIPT_SUPER = new Integer(1); + + /** The SWAP_COLORS text attribute. */ + public static final TextAttribute SWAP_COLORS = new TextAttribute("swap_colors"); //$NON-NLS-1$ + + /** + * The Constant SWAP_COLORS_ON indicates a swap of foreground + * and background. + */ + public static final Boolean SWAP_COLORS_ON = new Boolean(true); + + /** The TRANSFORM text attribute. */ + public static final TextAttribute TRANSFORM = new TextAttribute("transform"); //$NON-NLS-1$ + + /** The Constant UNDERLINE text attribute. */ + public static final TextAttribute UNDERLINE = new TextAttribute("underline"); //$NON-NLS-1$ + + /** + * The Constant UNDERLINE_ON indicates a standard underline + * at the roman baseline for roman text. + */ + public static final Integer UNDERLINE_ON = new Integer(0); + + /** + * The Constant UNDERLINE_LOW_ONE_PIXEL indicates a single + * pixel solid low underline. + */ + public static final Integer UNDERLINE_LOW_ONE_PIXEL = new Integer(1); + + /** + * The Constant UNDERLINE_LOW_TWO_PIXEL indicates a double + * pixel solid low underline. + */ + public static final Integer UNDERLINE_LOW_TWO_PIXEL = new Integer(2); + + /** + * The Constant UNDERLINE_LOW_DOTTED indicates a + * single pixel dotted low underline. + */ + public static final Integer UNDERLINE_LOW_DOTTED = new Integer(3); + + /** + * The Constant UNDERLINE_LOW_GRAY indicates double pixel + * gray low underline. + */ + public static final Integer UNDERLINE_LOW_GRAY = new Integer(4); + + /** + * The Constant UNDERLINE_LOW_DASHED indicates single pixel dashed + * low underline. + */ + public static final Integer UNDERLINE_LOW_DASHED = new Integer(5); + + /** The WEIGHT text attribute. */ + public static final TextAttribute WEIGHT = new TextAttribute("weight"); //$NON-NLS-1$ + + /** + * The Constant WEIGHT_EXTRA_LIGHT indicates the lightest + * predefined weight. + */ + public static final Float WEIGHT_EXTRA_LIGHT = new Float(0.5f); + + /** + * The Constant WEIGHT_LIGHT indicates the standard light weight. + */ + public static final Float WEIGHT_LIGHT = new Float(0.75f); + + /** + * The Constant WEIGHT_DEMILIGHT indicates an intermediate weight + * between LIGHT and STANDARD. + */ + public static final Float WEIGHT_DEMILIGHT = new Float(0.875f); + + /** + * The Constant WEIGHT_REGULAR indicates the standart weight. + */ + public static final Float WEIGHT_REGULAR = new Float(1.0f); + + /** + * The Constant WEIGHT_SEMIBOLD indicates a semi weight + * of REGULAR. + */ + public static final Float WEIGHT_SEMIBOLD = new Float(1.25f); + + /** The Constant WEIGHT_MEDIUM indicates average weight + * between the REGULAR and BOLD. */ + public static final Float WEIGHT_MEDIUM = new Float(1.5f); + + /** The Constant WEIGHT_DEMIBOLD indicates + * a lighter weight than BOLD. */ + public static final Float WEIGHT_DEMIBOLD = new Float(1.75f); + + /** The Constant WEIGHT_BOLD indicates the standard bold weight. */ + public static final Float WEIGHT_BOLD = new Float(2.0f); + + /** The Constant WEIGHT_HEAVY indicates a heavier weight than BOLD. */ + public static final Float WEIGHT_HEAVY = new Float(2.25f); + + /** The Constant WEIGHT_EXTRABOLD indicates an extra heavy weight. */ + public static final Float WEIGHT_EXTRABOLD = new Float(2.5f); + + /** + * The Constant WEIGHT_ULTRABOLD indicates the heaviest predefined + * weight. + */ + public static final Float WEIGHT_ULTRABOLD = new Float(2.75f); + + /** The WIDTH text attribute. */ + public static final TextAttribute WIDTH = new TextAttribute("width"); //$NON-NLS-1$ + + /** + * The Constant WIDTH_CONDENSED indicates the most condensed + * predefined width. + */ + public static final Float WIDTH_CONDENSED = new Float(0.75f); + + /** + * The Constant WIDTH_SEMI_CONDENSED indicates + * a semi condensed width. + */ + public static final Float WIDTH_SEMI_CONDENSED = new Float(0.875f); + + /** + * The Constant WIDTH_REGULAR indicates the standard width. + */ + public static final Float WIDTH_REGULAR = new Float(1.0f); + + /** + * The Constant WIDTH_SEMI_EXTENDED indicates semi extended width. + */ + public static final Float WIDTH_SEMI_EXTENDED = new Float(1.25f); + + /** + * The Constant WIDTH_EXTENDED indicates extended width. + */ + public static final Float WIDTH_EXTENDED = new Float(1.5f); + +} diff --git a/awt-kernel/src/main/java/java/beans/IndexedPropertyChangeEvent.java b/awt-kernel/src/main/java/java/beans/IndexedPropertyChangeEvent.java new file mode 100644 index 0000000..5bd4b2e --- /dev/null +++ b/awt-kernel/src/main/java/java/beans/IndexedPropertyChangeEvent.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package java.beans; + +/** + * A type of {@link PropertyChangeEvent} that indicates that an indexed property + * has changed. + * + * @since Android 1.0 + */ +public class IndexedPropertyChangeEvent extends PropertyChangeEvent { + + private static final long serialVersionUID = -320227448495806870L; + + private final int index; + + /** + * Creates a new property changed event with an indication of the property + * index. + * + * @param source + * the changed bean. + * @param propertyName + * the changed property, or <code>null</code> to indicate an + * unspecified set of the properties has changed. + * @param oldValue + * the previous value of the property, or <code>null</code> if + * the <code>propertyName</code> is <code>null</code> or the + * previous value is unknown. + * @param newValue + * the new value of the property, or <code>null</code> if the + * <code>propertyName</code> is <code>null</code> or the new + * value is unknown.. + * @param index + * the index of the property. + */ + public IndexedPropertyChangeEvent(Object source, String propertyName, + Object oldValue, Object newValue, int index) { + super(source, propertyName, oldValue, newValue); + this.index = index; + } + + /** + * Answer the index of the property that was changed in this event. + * + * @return the property element index. + */ + public int getIndex() { + return index; + } +} diff --git a/awt-kernel/src/main/java/java/beans/PropertyChangeEvent.java b/awt-kernel/src/main/java/java/beans/PropertyChangeEvent.java new file mode 100644 index 0000000..04caed8 --- /dev/null +++ b/awt-kernel/src/main/java/java/beans/PropertyChangeEvent.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.beans; + +import java.util.EventObject; + +/** + * An event that indicates that a constraint or a boundary of a property has + * changed. + * + * @since Android 1.0 + */ +public class PropertyChangeEvent extends EventObject { + + private static final long serialVersionUID = 7042693688939648123L; + + String propertyName; + + Object oldValue; + + Object newValue; + + Object propagationId; + + /** + * The constructor used to create a new {@code PropertyChangeEvent}. + * + * @param source + * the changed bean. + * @param propertyName + * the changed property, or <code>null</code> to indicate an + * unspecified set of the properties has changed. + * @param oldValue + * the previous value of the property, or <code>null</code> if + * the <code>propertyName</code> is <code>null</code> or the + * previous value is unknown. + * @param newValue + * the new value of the property, or <code>null</code> if the + * <code>propertyName</code> is <code>null</code> or the new + * value is unknown. + */ + public PropertyChangeEvent(Object source, String propertyName, + Object oldValue, Object newValue) { + super(source); + + this.propertyName = propertyName; + this.oldValue = oldValue; + this.newValue = newValue; + } + + /** + * Returns the name of the property that has changed. If an unspecified set + * of properties has changed it returns null. + * + * @return the name of the property that has changed, or null. + */ + public String getPropertyName() { + return propertyName; + } + + /** + * Sets the propagationId object. + * + * @see #getPropagationId() + */ + public void setPropagationId(Object propagationId) { + this.propagationId = propagationId; + } + + /** + * Returns the propagationId object. This is reserved for future use. Beans + * 1.0 demands that a listener receiving this property and then sending its + * own PropertyChangeEvent sets the received propagationId on the new + * PropertyChangeEvent's propagationId field. + * + * @return the propagationId object. + */ + public Object getPropagationId() { + return propagationId; + } + + /** + * Returns the old value that the property had. If the old value is unknown + * this method returns null. + * + * @return the old property value or null. + */ + public Object getOldValue() { + return oldValue; + } + + /** + * Returns the new value that the property now has. If the new value is + * unknown this method returns null. + * + * @return the old property value or null. + */ + public Object getNewValue() { + return newValue; + } +} diff --git a/awt-kernel/src/main/java/java/beans/PropertyChangeListener.java b/awt-kernel/src/main/java/java/beans/PropertyChangeListener.java new file mode 100644 index 0000000..2515792 --- /dev/null +++ b/awt-kernel/src/main/java/java/beans/PropertyChangeListener.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.beans; + +import java.util.EventListener; + +/** + * A PropertyChangeListener can subscribe with a event source. Whenever that + * source raises a PropertyChangeEvent this listener will get notified. + * + * @since Android 1.0 + */ +public interface PropertyChangeListener extends EventListener { + + /** + * The source bean calls this method when an event is raised. + * + * @param event + * the {@link PropertyChangeEvent} object which contains the name + * and the old and new value of the property that has changed. + */ + public void propertyChange(PropertyChangeEvent event); +} diff --git a/awt-kernel/src/main/java/java/beans/PropertyChangeListenerProxy.java b/awt-kernel/src/main/java/java/beans/PropertyChangeListenerProxy.java new file mode 100644 index 0000000..d27e4eb --- /dev/null +++ b/awt-kernel/src/main/java/java/beans/PropertyChangeListenerProxy.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.beans; + +import java.util.EventListenerProxy; + +/** + * The implementation of this listener proxy just delegates the received events + * to its listener. + * + * @since Android 1.0 + */ +public class PropertyChangeListenerProxy extends EventListenerProxy implements + PropertyChangeListener { + + String propertyName; + + /** + * Creates a new listener proxy that associates a listener with a property + * name. + * + * @param propertyName + * the name of the associated property. + * @param listener + * the listener to delegate incoming events to. + */ + public PropertyChangeListenerProxy(String propertyName, + PropertyChangeListener listener) { + super(listener); + this.propertyName = propertyName; + } + + /** + * Returns the name of the property associated with this listener proxy. + * + * @return the name of the associated property. + */ + public String getPropertyName() { + return propertyName; + } + + public void propertyChange(PropertyChangeEvent event) { + PropertyChangeListener listener = (PropertyChangeListener) getListener(); + listener.propertyChange(event); + } +} diff --git a/awt-kernel/src/main/java/java/beans/PropertyChangeSupport.java b/awt-kernel/src/main/java/java/beans/PropertyChangeSupport.java new file mode 100644 index 0000000..9225d95 --- /dev/null +++ b/awt-kernel/src/main/java/java/beans/PropertyChangeSupport.java @@ -0,0 +1,501 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.beans; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * This utility class + * + */ +public class PropertyChangeSupport implements Serializable { + + private static final long serialVersionUID = 6401253773779951803l; + + private transient Object sourceBean; + + private transient List<PropertyChangeListener> allPropertiesChangeListeners = + new ArrayList<PropertyChangeListener>(); + + private transient Map<String, List<PropertyChangeListener>> + selectedPropertiesChangeListeners = + new HashMap<String, List<PropertyChangeListener>>(); + + // fields for serialization compatibility + private Hashtable<String, List<PropertyChangeListener>> children; + + private Object source; + + private int propertyChangeSupportSerializedDataVersion = 1; + + /** + * Creates a new instance that uses the source bean as source for any event. + * + * @param sourceBean + * the bean used as source for all events. + */ + public PropertyChangeSupport(Object sourceBean) { + if (sourceBean == null) { + throw new NullPointerException(); + } + this.sourceBean = sourceBean; + } + + /** + * Fires a {@link PropertyChangeEvent} with the given name, old value and + * new value. As source the bean used to initialize this instance is used. + * If the old value and the new value are not null and equal the event will + * not be fired. + * + * @param propertyName + * the name of the property + * @param oldValue + * the old value of the property + * @param newValue + * the new value of the property + */ + public void firePropertyChange(String propertyName, Object oldValue, + Object newValue) { + PropertyChangeEvent event = createPropertyChangeEvent(propertyName, + oldValue, newValue); + doFirePropertyChange(event); + } + + /** + * Fires an {@link IndexedPropertyChangeEvent} with the given name, old + * value, new value and index. As source the bean used to initialize this + * instance is used. If the old value and the new value are not null and + * equal the event will not be fired. + * + * @param propertyName + * the name of the property + * @param index + * the index + * @param oldValue + * the old value of the property + * @param newValue + * the new value of the property + */ + public void fireIndexedPropertyChange(String propertyName, int index, + Object oldValue, Object newValue) { + + // nulls and equals check done in doFire... + doFirePropertyChange(new IndexedPropertyChangeEvent(sourceBean, + propertyName, oldValue, newValue, index)); + } + + /** + * Removes the listener from the specific property. This only happens if it + * was registered to this property. Nothing happens if it was not + * registered with this property or if the property name or the listener is + * null. + * + * @param propertyName + * the property name the listener is listening to + * @param listener + * the listener to remove + */ + public synchronized void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + if ((propertyName != null) && (listener != null)) { + List<PropertyChangeListener> listeners = + selectedPropertiesChangeListeners.get(propertyName); + + if (listeners != null) { + listeners.remove(listener); + } + } + } + + /** + * Adds a listener to a specific property. Nothing happens if the property + * name or the listener is null. + * + * @param propertyName + * the name of the property + * @param listener + * the listener to register for the property with the given name + */ + public synchronized void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + if ((listener != null) && (propertyName != null)) { + List<PropertyChangeListener> listeners = + selectedPropertiesChangeListeners.get(propertyName); + + if (listeners == null) { + listeners = new ArrayList<PropertyChangeListener>(); + selectedPropertiesChangeListeners.put(propertyName, listeners); + } + + // RI compatibility + if (listener instanceof PropertyChangeListenerProxy) { + PropertyChangeListenerProxy proxy = + (PropertyChangeListenerProxy) listener; + + listeners.add(new PropertyChangeListenerProxy( + proxy.getPropertyName(), + (PropertyChangeListener) proxy.getListener())); + } else { + listeners.add(listener); + } + } + } + + /** + * Returns an array of listeners that registered to the property with the + * given name. If the property name is null an empty array is returned. + * + * @param propertyName + * the name of the property whose listeners should be returned + * @return the array of listeners to the property with the given name. + */ + public synchronized PropertyChangeListener[] getPropertyChangeListeners( + String propertyName) { + List<PropertyChangeListener> listeners = null; + + if (propertyName != null) { + listeners = selectedPropertiesChangeListeners.get(propertyName); + } + + return (listeners == null) ? new PropertyChangeListener[] {} + : listeners.toArray( + new PropertyChangeListener[listeners.size()]); + } + + /** + * Fires a property change of a boolean property with the given name. If the + * old value and the new value are not null and equal the event will not be + * fired. + * + * @param propertyName + * the property name + * @param oldValue + * the old value + * @param newValue + * the new value + */ + public void firePropertyChange(String propertyName, boolean oldValue, + boolean newValue) { + PropertyChangeEvent event = createPropertyChangeEvent(propertyName, + oldValue, newValue); + doFirePropertyChange(event); + } + + /** + * Fires a property change of a boolean property with the given name. If the + * old value and the new value are not null and equal the event will not be + * fired. + * + * @param propertyName + * the property name + * @param index + * the index of the changed property + * @param oldValue + * the old value + * @param newValue + * the new value + */ + public void fireIndexedPropertyChange(String propertyName, int index, + boolean oldValue, boolean newValue) { + + if (oldValue != newValue) { + fireIndexedPropertyChange(propertyName, index, Boolean + .valueOf(oldValue), Boolean.valueOf(newValue)); + } + } + + /** + * Fires a property change of an integer property with the given name. If + * the old value and the new value are not null and equal the event will not + * be fired. + * + * @param propertyName + * the property name + * @param oldValue + * the old value + * @param newValue + * the new value + */ + public void firePropertyChange(String propertyName, int oldValue, + int newValue) { + PropertyChangeEvent event = createPropertyChangeEvent(propertyName, + oldValue, newValue); + doFirePropertyChange(event); + } + + /** + * Fires a property change of an integer property with the given name. If + * the old value and the new value are not null and equal the event will not + * be fired. + * + * @param propertyName + * the property name + * @param index + * the index of the changed property + * @param oldValue + * the old value + * @param newValue + * the new value + */ + public void fireIndexedPropertyChange(String propertyName, int index, + int oldValue, int newValue) { + + if (oldValue != newValue) { + fireIndexedPropertyChange(propertyName, index, + new Integer(oldValue), new Integer(newValue)); + } + } + + /** + * Returns true if there are listeners registered to the property with the + * given name. + * + * @param propertyName + * the name of the property + * @return true if there are listeners registered to that property, false + * otherwise. + */ + public synchronized boolean hasListeners(String propertyName) { + boolean result = allPropertiesChangeListeners.size() > 0; + if (!result && (propertyName != null)) { + List<PropertyChangeListener> listeners = + selectedPropertiesChangeListeners.get(propertyName); + if (listeners != null) { + result = listeners.size() > 0; + } + } + return result; + } + + /** + * removes a property change listener that was registered to all properties. + * + * @param listener + * the listener to remove + */ + public synchronized void removePropertyChangeListener( + PropertyChangeListener listener) { + if (listener != null) { + if (listener instanceof PropertyChangeListenerProxy) { + String name = ((PropertyChangeListenerProxy) listener) + .getPropertyName(); + PropertyChangeListener lst = (PropertyChangeListener) + ((PropertyChangeListenerProxy) listener).getListener(); + + removePropertyChangeListener(name, lst); + } else { + allPropertiesChangeListeners.remove(listener); + } + } + } + + /** + * Registers a listener with all properties. + * + * @param listener + * the listener to register + */ + public synchronized void addPropertyChangeListener( + PropertyChangeListener listener) { + if (listener != null) { + if (listener instanceof PropertyChangeListenerProxy) { + String name = ((PropertyChangeListenerProxy) listener) + .getPropertyName(); + PropertyChangeListener lst = (PropertyChangeListener) + ((PropertyChangeListenerProxy) listener).getListener(); + addPropertyChangeListener(name, lst); + } else { + allPropertiesChangeListeners.add(listener); + } + } + } + + /** + * Returns an array with the listeners that registered to all properties. + * + * @return the array of listeners + */ + public synchronized PropertyChangeListener[] getPropertyChangeListeners() { + ArrayList<PropertyChangeListener> result = + new ArrayList<PropertyChangeListener>( + allPropertiesChangeListeners); + + for (String propertyName : selectedPropertiesChangeListeners.keySet()) { + List<PropertyChangeListener> selectedListeners = + selectedPropertiesChangeListeners.get(propertyName); + + if (selectedListeners != null) { + + for (PropertyChangeListener listener : selectedListeners) { + result.add(new PropertyChangeListenerProxy(propertyName, + listener)); + } + } + } + + return result.toArray(new PropertyChangeListener[result.size()]); + } + + private void writeObject(ObjectOutputStream oos) throws IOException { + List<PropertyChangeListener> allSerializedPropertiesChangeListeners = + new ArrayList<PropertyChangeListener>(); + + for (PropertyChangeListener pcl : allPropertiesChangeListeners) { + if (pcl instanceof Serializable) { + allSerializedPropertiesChangeListeners.add(pcl); + } + } + + Map<String, List<PropertyChangeListener>> + selectedSerializedPropertiesChangeListeners = + new HashMap<String, List<PropertyChangeListener>>(); + + for (String propertyName : selectedPropertiesChangeListeners.keySet()) { + List<PropertyChangeListener> keyValues = + selectedPropertiesChangeListeners.get(propertyName); + + if (keyValues != null) { + List<PropertyChangeListener> serializedPropertiesChangeListeners + = new ArrayList<PropertyChangeListener>(); + + for (PropertyChangeListener pcl : keyValues) { + if (pcl instanceof Serializable) { + serializedPropertiesChangeListeners.add(pcl); + } + } + + if (!serializedPropertiesChangeListeners.isEmpty()) { + selectedSerializedPropertiesChangeListeners.put( + propertyName, serializedPropertiesChangeListeners); + } + } + } + + children = new Hashtable<String, List<PropertyChangeListener>>( + selectedSerializedPropertiesChangeListeners); + children.put("", allSerializedPropertiesChangeListeners); //$NON-NLS-1$ + oos.writeObject(children); + + Object source = null; + if (sourceBean instanceof Serializable) { + source = sourceBean; + } + oos.writeObject(source); + + oos.writeInt(propertyChangeSupportSerializedDataVersion); + } + + @SuppressWarnings("unchecked") + private void readObject(ObjectInputStream ois) throws IOException, + ClassNotFoundException { + children = (Hashtable<String, List<PropertyChangeListener>>) ois + .readObject(); + + selectedPropertiesChangeListeners = new HashMap<String, List<PropertyChangeListener>>( + children); + allPropertiesChangeListeners = selectedPropertiesChangeListeners + .remove(""); //$NON-NLS-1$ + if (allPropertiesChangeListeners == null) { + allPropertiesChangeListeners = new ArrayList<PropertyChangeListener>(); + } + + sourceBean = ois.readObject(); + propertyChangeSupportSerializedDataVersion = ois.readInt(); + } + + /** + * Fires a property change event to all listeners of that property. + * + * @param event + * the event to fire + */ + public void firePropertyChange(PropertyChangeEvent event) { + doFirePropertyChange(event); + } + + private PropertyChangeEvent createPropertyChangeEvent(String propertyName, + Object oldValue, Object newValue) { + return new PropertyChangeEvent(sourceBean, propertyName, oldValue, + newValue); + } + + private PropertyChangeEvent createPropertyChangeEvent(String propertyName, + boolean oldValue, boolean newValue) { + return new PropertyChangeEvent(sourceBean, propertyName, oldValue, + newValue); + } + + private PropertyChangeEvent createPropertyChangeEvent(String propertyName, + int oldValue, int newValue) { + return new PropertyChangeEvent(sourceBean, propertyName, oldValue, + newValue); + } + + private void doFirePropertyChange(PropertyChangeEvent event) { + String propertyName = event.getPropertyName(); + Object oldValue = event.getOldValue(); + Object newValue = event.getNewValue(); + + if ((newValue != null) && (oldValue != null) + && newValue.equals(oldValue)) { + return; + } + + /* + * Copy the listeners collections so they can be modified while we fire + * events. + */ + + // Listeners to all property change events + PropertyChangeListener[] listensToAll; + // Listens to a given property change + PropertyChangeListener[] listensToOne = null; + synchronized (this) { + listensToAll = allPropertiesChangeListeners + .toArray(new PropertyChangeListener[allPropertiesChangeListeners + .size()]); + + List<PropertyChangeListener> listeners = selectedPropertiesChangeListeners + .get(propertyName); + if (listeners != null) { + listensToOne = listeners + .toArray(new PropertyChangeListener[listeners.size()]); + } + } + + // Fire the listeners + for (PropertyChangeListener listener : listensToAll) { + listener.propertyChange(event); + } + if (listensToOne != null) { + for (PropertyChangeListener listener : listensToOne) { + listener.propertyChange(event); + } + } + } + +} |