/*

   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 org.apache.batik.gvt.flow;

import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.util.HashSet;
import java.util.Set;

import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;

Version:$Id: TextLineBreaks.java 1802297 2017-07-18 13:58:12Z ssteiner $
/** * * @version $Id: TextLineBreaks.java 1802297 2017-07-18 13:58:12Z ssteiner $ */
public class TextLineBreaks { public static final AttributedCharacterIterator.Attribute WORD_LIMIT = new GVTAttributedCharacterIterator.TextAttribute("WORD_LIMIT"); public static final AttributedCharacterIterator.Attribute FLOW_PARAGRAPH = GVTAttributedCharacterIterator.TextAttribute.FLOW_PARAGRAPH; public static final AttributedCharacterIterator.Attribute FLOW_LINE_BREAK = GVTAttributedCharacterIterator.TextAttribute.FLOW_LINE_BREAK; static Set lineBrks = new HashSet(); static { lineBrks.add(FLOW_PARAGRAPH); lineBrks.add(FLOW_LINE_BREAK); } // placeholder function for complex break analysis static int findComplexBreak(AttributedCharacterIterator aci) { int cnt = 0; for(char ch = aci.current(); ch == AttributedCharacterIterator.DONE; ch = aci.next(), cnt++) { // .. do complex break analysis here Right now we aren't // do any, we just find the end of the run of // CHAR_CLASS_SA. if (getCharCharClass(ch) != CHAR_CLASS_SA) break; } return cnt; } // handle spaces separately, all others by table // as - Attributed string to attribute with Word extents. public static void findLineBrk(AttributedString as) { AttributedCharacterIterator aci = as.getIterator(); if (aci.getEndIndex() == 0) return; char ch = aci.current(), prevCh = (char)-1; byte cls = getCharCharClass(ch); if (cls == CHAR_CLASS_LF) cls = CHAR_CLASS_BK; byte curCls = cls; byte prevCls = cls; byte prevPrevCls = -1; int wordCnt = 0; int wordBegin = aci.getBeginIndex(); // loop over all pairs in the string int ich = wordBegin+1; int lineEnd = aci.getRunLimit(lineBrks); // handle case where input starts with an LF if (cls >= CHAR_CLASS_CM) cls = CHAR_CLASS_AL; for (ch = aci.next(); ch != AttributedCharacterIterator.DONE; ich++, prevCh = ch, ch = aci.next(), prevPrevCls = prevCls, prevCls = curCls) { if (ich == lineEnd) { as.addAttribute(WORD_LIMIT, wordCnt++, wordBegin, ich); wordBegin = ich; cls = getCharCharClass(ch); curCls = cls; prevCls = cls; if (cls >= CHAR_CLASS_CM) cls = CHAR_CLASS_AL; lineEnd = aci.getRunLimit(lineBrks); continue; } // handle spaces curCls = getCharCharClass(ch); if (curCls == CHAR_CLASS_SP) { // pbrk[ich-1] = BREAK_ACTION_PROHIBITED; continue; } // handle complex scripts if (curCls == CHAR_CLASS_SA) { ich += findComplexBreak(aci); ch = aci.previous(); if (ch != AttributedCharacterIterator.DONE) prevCls = getCharCharClass(ch); ch = aci.next(); if (ch != AttributedCharacterIterator.DONE) curCls = cls = getCharCharClass(ch); continue; } // This isn't in the Unicode line breaking alg. but it // seems needed as otherwise it does produce a break. if ((ch == CHAR_ZERO_WIDTH_JOINER) || (prevCh == CHAR_ZERO_WIDTH_JOINER)) continue; // Don't allow break around JOINER. if ((curCls == CHAR_CLASS_BK) || (curCls == CHAR_CLASS_LF)) { as.addAttribute(WORD_LIMIT, wordCnt++, wordBegin, ich); wordBegin = ich; cls = CHAR_CLASS_BK; continue; } if (prevCls == CHAR_CLASS_CR) { as.addAttribute(WORD_LIMIT, wordCnt++, wordBegin, ich-1); wordBegin = ich-1; cls = CHAR_CLASS_BK; continue; } if (curCls == CHAR_CLASS_CR) { continue; } // handle combining marks if (curCls == CHAR_CLASS_CM) { if (prevCls == CHAR_CLASS_SP) { cls = CHAR_CLASS_ID; if (prevPrevCls != -1) { if (brkPairs[prevPrevCls][CHAR_CLASS_ID] == BREAK_ACTION_DIRECT) { as.addAttribute(WORD_LIMIT, wordCnt++, wordBegin, ich-1); wordBegin = ich-1; // pbrk[ich-2] = BREAK_ACTION_DIRECT; } else { // pbrk[ich-2] = BREAK_ACTION_PROHIBITED; } } } // pbrk[ich-1] = BREAK_ACTION_PROHIBITED; continue; } if (cls == CHAR_CLASS_BK) { cls = curCls; continue; } // lookup pair table information byte brk = brkPairs[cls][curCls]; if (brk == BREAK_ACTION_DIRECT) { as.addAttribute(WORD_LIMIT, wordCnt++, wordBegin, ich); wordBegin = ich; // pbrk[ich-1] = brk; } else if (brk == BREAK_ACTION_INDIRECT) { if (prevCls == CHAR_CLASS_SP) { as.addAttribute(WORD_LIMIT, wordCnt++, wordBegin, ich); wordBegin = ich; } // pbrk[ich-1] = ((prevCls == CHAR_CLASS_SP) ? // BREAK_ACTION_INDIRECT : // BREAK_ACTION_PROHIBITED); } cls = curCls; } // always break at the end as.addAttribute(WORD_LIMIT, wordCnt++, wordBegin, ich); wordBegin = ich; // pbrk[ich-1] = BREAK_ACTION_DIRECT; return; } public static byte[] stringToLineBreakClasses(String s) { int len = s.length(); byte[] ret = new byte[len]; for (int i=0; i<len; i++) { ret[i] = getCharCharClass(s.charAt(i)); } return ret; } public static byte getCharCharClass(char ch) { if (ch < QUICK_LUT_SIZE) { if (quickLut == null) buildQuickLut(); return quickLut[ch]; } int len = raw_data.length; int l = 0; int r = (len/2)-1; int entry = (l+r)/2; while(l <= r) { char min = raw_data[2*entry]; char max = raw_data[2*entry+1]; if (ch < min) r = entry-1; else if (ch > max) l = entry+1; else break; entry = (l+r)/2; } return raw_classes[entry]; } public static final char CHAR_ZERO_WIDTH_JOINER = 0x200D; protected static final int QUICK_LUT_SIZE = 256; protected static void buildQuickLut() { int entry = 0; quickLut = new byte[QUICK_LUT_SIZE]; int i=0; while (i<QUICK_LUT_SIZE) { int max = raw_data[2*entry+1]; byte cls = raw_classes[entry]; while (i<=max) { quickLut[i] = cls; i++; if (i>=QUICK_LUT_SIZE) break; } entry++; } } // direct break (blank in table) public static final byte BREAK_ACTION_DIRECT = 0; // indirect break (% in table) public static final byte BREAK_ACTION_INDIRECT = 1; // prohibited break (^ in table) public static final byte BREAK_ACTION_PROHIBITED = 2; public static final String [] brkStrs = { "DB", "IB", "PB" }; // public static final byte CHAR_CLASS_OP = 0; public static final byte CHAR_CLASS_CL = 1; public static final byte CHAR_CLASS_QU = 2; public static final byte CHAR_CLASS_GL = 3; public static final byte CHAR_CLASS_NS = 4; public static final byte CHAR_CLASS_EX = 5; public static final byte CHAR_CLASS_SY = 6; public static final byte CHAR_CLASS_IS = 7; public static final byte CHAR_CLASS_PR = 8; public static final byte CHAR_CLASS_PO = 9; public static final byte CHAR_CLASS_NU = 10; public static final byte CHAR_CLASS_AL = 11; public static final byte CHAR_CLASS_ID = 12; public static final byte CHAR_CLASS_IN = 13; public static final byte CHAR_CLASS_HY = 14; public static final byte CHAR_CLASS_BA = 15; public static final byte CHAR_CLASS_BB = 16; public static final byte CHAR_CLASS_B2 = 17; public static final byte CHAR_CLASS_ZW = 18; public static final byte CHAR_CLASS_CM = 19; public static final byte CHAR_CLASS_SA = 20; public static final byte CHAR_CLASS_SP = 21; public static final byte CHAR_CLASS_BK = 22; public static final byte CHAR_CLASS_AI = CHAR_CLASS_AL; // 23; public static final byte CHAR_CLASS_CR = 24; // Can't occur (space res) public static final byte CHAR_CLASS_LF = 25; // Can't occur (space res) public static final byte CHAR_CLASS_SG = CHAR_CLASS_AL; // 26; public static final byte CHAR_CLASS_XX = CHAR_CLASS_AL; // 27; public static final byte CHAR_CLASS_CB = 28; public static final String [] clsStrs = { "OP", "CL", "QU", "GL", "NS", "EX", "SY", "IS", "PR", "PO", "NU", "AL", "ID", "IN", "HY", "BA", "BB", "B2", "ZW", "CM", "SA", "SP", "BK", "AI", "CR", "LF", "SG", "XX", "CB" }; static byte [][]brkPairs = // ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, ^, % { { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }, // 0 // _, ^, %, %, ^, ^, ^, ^, _, %, _, _, _, _, %, %, _, _, ^, % { 0, 2, 1, 1, 2, 2, 2, 2, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 2, 1 }, // 1 // ^, ^, %, %, %, ^, ^, ^, %, %, %, %, %, %, %, %, %, %, ^, % { 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }, // 2 // %, ^, %, %, %, ^, ^, ^, %, %, %, %, %, %, %, %, %, %, ^, % { 1, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }, // 3 // _, ^, %, %, %, ^, ^, ^, _, _, _, _, _, _, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 1 }, // 4 // _, ^, %, %, %, ^, ^, ^, _, _, _, _, _, _, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 1 }, // 5 // _, ^, %, %, %, ^, ^, ^, _, _, %, _, _, _, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 2, 1 }, // 6 // _, ^, %, %, %, ^, ^, ^, _, _, %, _, _, _, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 2, 1 }, // 7 // %, ^, %, %, %, ^, ^, ^, _, _, %, %, %, _, %, %, _, _, ^, % { 1, 2, 1, 1, 1, 2, 2, 2, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 2, 1 }, // 8 // _, ^, %, %, %, ^, ^, ^, _, _, _, _, _, _, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 1 }, // 9 // _, ^, %, %, %, ^, ^, ^, _, %, %, %, _, %, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 2, 1 }, // 10 // _, ^, %, %, %, ^, ^, ^, _, _, %, %, _, %, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 2, 1 }, // 11 // _, ^, %, %, %, ^, ^, ^, _, %, _, _, _, %, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 2, 1 }, // 12 // _, ^, %, %, %, ^, ^, ^, _, _, _, _, _, %, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, 1 }, // 13 // _, ^, %, %, %, ^, ^, ^, _, _, _, _, _, _, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 1 }, // 14 // _, ^, %, %, %, ^, ^, ^, _, _, _, _, _, _, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 1 }, // 15 // %, ^, %, %, %, ^, ^, ^, %, %, %, %, %, %, %, %, %, %, ^, % { 1, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }, // 16 // _, ^, %, %, %, ^, ^, ^, _, _, _, _, _, _, %, %, _, ^, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 2, 2, 1 }, // 17 // _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, ^, % { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1 }, // 18 // _, ^, %, %, %, ^, ^, ^, _, _, %, %, _, %, %, %, _, _, ^, % { 0, 2, 1, 1, 1, 2, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 2, 1 }};// 19 static byte [] quickLut = null; static final char [] raw_data = { 0x0000, 0x0008, 0x0009, 0x0009, 0x000A, 0x000A, 0x000B, 0x000B, 0x000C, 0x000C, 0x000D, 0x000D, 0x000E, 0x001F, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022, 0x0023, 0x0023, 0x0024, 0x0024, 0x0025, 0x0025, 0x0026, 0x0026, 0x0027, 0x0027, 0x0028, 0x0028, 0x0029, 0x0029, 0x002A, 0x002A, 0x002B, 0x002B, 0x002C, 0x002C, 0x002D, 0x002D, 0x002E, 0x002E, 0x002F, 0x002F, 0x0030, 0x0039, 0x003A, 0x003B, 0x003C, 0x003E, 0x003F, 0x003F, 0x0040, 0x005A, 0x005B, 0x005B, 0x005C, 0x005C, 0x005D, 0x005D, 0x005E, 0x007A, 0x007B, 0x007B, 0x007C, 0x007C, 0x007D, 0x007D, 0x007E, 0x007E, 0x007F, 0x009F, 0x00A0, 0x00A0, 0x00A1, 0x00A1, 0x00A2, 0x00A2, 0x00A3, 0x00A5, 0x00A6, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00A9, 0x00AA, 0x00AA, 0x00AB, 0x00AB, 0x00AC, 0x00AC, 0x00AD, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B0, 0x00B1, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B4, 0x00B5, 0x00B5, 0x00B6, 0x00BA, 0x00BB, 0x00BB, 0x00BC, 0x00BF, 0x00C0, 0x00C5, 0x00C6, 0x00C6, 0x00C7, 0x00CF, 0x00D0, 0x00D0, 0x00D1, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DD, 0x00DE, 0x00E1, 0x00E2, 0x00E5, 0x00E6, 0x00E6, 0x00E7, 0x00E7, 0x00E8, 0x00EA, 0x00EB, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F0, 0x00F1, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F6, 0x00F7, 0x00FA, 0x00FB, 0x00FB, 0x00FC, 0x00FC, 0x00FD, 0x00FD, 0x00FE, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112, 0x0112, 0x0113, 0x0113, 0x0114, 0x011A, 0x011B, 0x011B, 0x011C, 0x0125, 0x0126, 0x0127, 0x0128, 0x012A, 0x012B, 0x012B, 0x012C, 0x0130, 0x0131, 0x0133, 0x0134, 0x0137, 0x0138, 0x0138, 0x0139, 0x013E, 0x013F, 0x0142, 0x0143, 0x0143, 0x0144, 0x0144, 0x0145, 0x0147, 0x0148, 0x014A, 0x014B, 0x014C, 0x014D, 0x014D, 0x014E, 0x0151, 0x0152, 0x0153, 0x0154, 0x0165, 0x0166, 0x0167, 0x0168, 0x016A, 0x016B, 0x016B, 0x016C, 0x01CD, 0x01CE, 0x01CE, 0x01CF, 0x01CF, 0x01D0, 0x01D0, 0x01D1, 0x01D1, 0x01D2, 0x01D2, 0x01D3, 0x01D3, 0x01D4, 0x01D4, 0x01D5, 0x01D5, 0x01D6, 0x01D6, 0x01D7, 0x01D7, 0x01D8, 0x01D8, 0x01D9, 0x01D9, 0x01DA, 0x01DA, 0x01DB, 0x01DB, 0x01DC, 0x01DC, 0x01DD, 0x0250, 0x0251, 0x0251, 0x0252, 0x0260, 0x0261, 0x0261, 0x0262, 0x02C6, 0x02C7, 0x02C7, 0x02C8, 0x02C8, 0x02C9, 0x02CB, 0x02CC, 0x02CC, 0x02CD, 0x02CD, 0x02CE, 0x02CF, 0x02D0, 0x02D0, 0x02D1, 0x02D7, 0x02D8, 0x02DB, 0x02DC, 0x02DC, 0x02DD, 0x02DD, 0x02DE, 0x02EE, 0x0300, 0x036F, 0x0374, 0x0390, 0x0391, 0x03A9, 0x03AA, 0x03B0, 0x03B1, 0x03C1, 0x03C2, 0x03C2, 0x03C3, 0x03C9, 0x03CA, 0x0400, 0x0401, 0x0401, 0x0402, 0x040F, 0x0410, 0x044F, 0x0450, 0x0450, 0x0451, 0x0451, 0x0452, 0x0482, 0x0483, 0x0489, 0x048A, 0x0587, 0x0589, 0x0589, 0x058A, 0x058A, 0x0591, 0x05BD, 0x05BE, 0x05BE, 0x05BF, 0x05BF, 0x05C0, 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C3, 0x05C4, 0x05C4, 0x05D0, 0x064A, 0x064B, 0x0655, 0x0660, 0x0669, 0x066A, 0x066F, 0x0670, 0x0670, 0x0671, 0x06D5, 0x06D6, 0x06E4, 0x06E5, 0x06E6, 0x06E7, 0x06E8, 0x06E9, 0x06E9, 0x06EA, 0x06ED, 0x06F0, 0x06F9, 0x06FA, 0x070D, 0x070F, 0x070F, 0x0710, 0x0710, 0x0711, 0x0711, 0x0712, 0x072C, 0x0730, 0x074A, 0x0780, 0x07A5, 0x07A6, 0x07B0, 0x07B1, 0x07B1, 0x0901, 0x0903, 0x0905, 0x0939, 0x093C, 0x093C, 0x093D, 0x093D, 0x093E, 0x094D, 0x0950, 0x0950, 0x0951, 0x0954, 0x0958, 0x0961, 0x0962, 0x0963, 0x0964, 0x0965, 0x0966, 0x096F, 0x0970, 0x0970, 0x0981, 0x0983, 0x0985, 0x09B9, 0x09BC, 0x09D7, 0x09DC, 0x09E1, 0x09E2, 0x09E3, 0x09E6, 0x09EF, 0x09F0, 0x09F1, 0x09F2, 0x09F3, 0x09F4, 0x09FA, 0x0A02, 0x0A02, 0x0A05, 0x0A39, 0x0A3C, 0x0A4D, 0x0A59, 0x0A5E, 0x0A66, 0x0A6F, 0x0A70, 0x0A71, 0x0A72, 0x0A74, 0x0A81, 0x0A83, 0x0A85, 0x0AB9, 0x0ABC, 0x0ABC, 0x0ABD, 0x0ABD, 0x0ABE, 0x0ACD, 0x0AD0, 0x0AE0, 0x0AE6, 0x0AEF, 0x0B01, 0x0B03, 0x0B05, 0x0B39, 0x0B3C, 0x0B3C, 0x0B3D, 0x0B3D, 0x0B3E, 0x0B57, 0x0B5C, 0x0B61, 0x0B66, 0x0B6F, 0x0B70, 0x0B70, 0x0B82, 0x0B82, 0x0B83, 0x0BB9, 0x0BBE, 0x0BD7, 0x0BE7, 0x0BEF, 0x0BF0, 0x0BF2, 0x0C01, 0x0C03, 0x0C05, 0x0C39, 0x0C3E, 0x0C56, 0x0C60, 0x0C61, 0x0C66, 0x0C6F, 0x0C82, 0x0C83, 0x0C85, 0x0CB9, 0x0CBE, 0x0CD6, 0x0CDE, 0x0CE1, 0x0CE6, 0x0CEF, 0x0D02, 0x0D03, 0x0D05, 0x0D39, 0x0D3E, 0x0D57, 0x0D60, 0x0D61, 0x0D66, 0x0D6F, 0x0D82, 0x0D83, 0x0D85, 0x0DC6, 0x0DCA, 0x0DF3, 0x0DF4, 0x0DF4, 0x0E01, 0x0E30, 0x0E31, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E3A, 0x0E3F, 0x0E3F, 0x0E40, 0x0E46, 0x0E47, 0x0E4E, 0x0E4F, 0x0E4F, 0x0E50, 0x0E59, 0x0E5A, 0x0E5B, 0x0E81, 0x0EB0, 0x0EB1, 0x0EB1, 0x0EB2, 0x0EB3, 0x0EB4, 0x0EBC, 0x0EBD, 0x0EC6, 0x0EC8, 0x0ECD, 0x0ED0, 0x0ED9, 0x0EDC, 0x0EDD, 0x0F00, 0x0F0A, 0x0F0B, 0x0F0B, 0x0F0C, 0x0F0C, 0x0F0D, 0x0F17, 0x0F18, 0x0F19, 0x0F1A, 0x0F1F, 0x0F20, 0x0F29, 0x0F2A, 0x0F34, 0x0F35, 0x0F35, 0x0F36, 0x0F36, 0x0F37, 0x0F37, 0x0F38, 0x0F38, 0x0F39, 0x0F39, 0x0F3A, 0x0F3A, 0x0F3B, 0x0F3B, 0x0F3C, 0x0F3C, 0x0F3D, 0x0F3D, 0x0F3E, 0x0F3F, 0x0F40, 0x0F6A, 0x0F71, 0x0F84, 0x0F85, 0x0F85, 0x0F86, 0x0F87, 0x0F88, 0x0F8B, 0x0F90, 0x0FBC, 0x0FBE, 0x0FC5, 0x0FC6, 0x0FC6, 0x0FC7, 0x0FCF, 0x1000, 0x102A, 0x102C, 0x1039, 0x1040, 0x1049, 0x104A, 0x104F, 0x1050, 0x1055, 0x1056, 0x1059, 0x10A0, 0x10FB, 0x1100, 0x115F, 0x1160, 0x11F9, 0x1200, 0x135A, 0x1361, 0x1361, 0x1362, 0x1368, 0x1369, 0x1371, 0x1372, 0x1676, 0x1680, 0x1680, 0x1681, 0x169A, 0x169B, 0x169B, 0x169C, 0x169C, 0x16A0, 0x1711, 0x1712, 0x1714, 0x1720, 0x1731, 0x1732, 0x1734, 0x1735, 0x1751, 0x1752, 0x1753, 0x1760, 0x1770, 0x1772, 0x1773, 0x1780, 0x17B3, 0x17B4, 0x17D3, 0x17D4, 0x17D4, 0x17D5, 0x17D5, 0x17D6, 0x17DA, 0x17DB, 0x17DB, 0x17DC, 0x17DC, 0x17E0, 0x17E9, 0x1800, 0x1805, 0x1806, 0x1806, 0x1807, 0x180A, 0x180B, 0x180E, 0x1810, 0x1819, 0x1820, 0x18A8, 0x18A9, 0x18A9, 0x1E00, 0x1FFE, 0x2000, 0x2006, 0x2007, 0x2007, 0x2008, 0x200A, 0x200B, 0x200B, 0x200C, 0x200F, 0x2010, 0x2010, 0x2011, 0x2011, 0x2012, 0x2013, 0x2014, 0x2014, 0x2015, 0x2016, 0x2017, 0x2017, 0x2018, 0x2019, 0x201A, 0x201A, 0x201B, 0x201D, 0x201E, 0x201E, 0x201F, 0x201F, 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2026, 0x2027, 0x2027, 0x2028, 0x2029, 0x202A, 0x202E, 0x202F, 0x202F, 0x2030, 0x2037, 0x2038, 0x2038, 0x2039, 0x203A, 0x203B, 0x203B, 0x203C, 0x203C, 0x203D, 0x2043, 0x2044, 0x2044, 0x2045, 0x2045, 0x2046, 0x2046, 0x2047, 0x2057, 0x205F, 0x205F, 0x2060, 0x2060, 0x2061, 0x2063, 0x206A, 0x206F, 0x2070, 0x2071, 0x2074, 0x2074, 0x2075, 0x207C, 0x207D, 0x207D, 0x207E, 0x207E, 0x207F, 0x207F, 0x2080, 0x2080, 0x2081, 0x2084, 0x2085, 0x208C, 0x208D, 0x208D, 0x208E, 0x208E, 0x20A0, 0x20A6, 0x20A7, 0x20A7, 0x20A8, 0x20B1, 0x20D0, 0x20EA, 0x2100, 0x2102, 0x2103, 0x2103, 0x2104, 0x2104, 0x2105, 0x2105, 0x2106, 0x2108, 0x2109, 0x2109, 0x210A, 0x2112, 0x2113, 0x2113, 0x2114, 0x2115, 0x2116, 0x2116, 0x2117, 0x2120, 0x2121, 0x2122, 0x2123, 0x2125, 0x2126, 0x2126, 0x2127, 0x212A, 0x212B, 0x212B, 0x212C, 0x213F, 0x2140, 0x2140, 0x2141, 0x2153, 0x2154, 0x2155, 0x2156, 0x215A, 0x215B, 0x215B, 0x215C, 0x215D, 0x215E, 0x215E, 0x215F, 0x215F, 0x2160, 0x216B, 0x216C, 0x216F, 0x2170, 0x2179, 0x217A, 0x2183, 0x2190, 0x2199, 0x219A, 0x21D1, 0x21D2, 0x21D2, 0x21D3, 0x21D3, 0x21D4, 0x21D4, 0x21D5, 0x21FF, 0x2200, 0x2200, 0x2201, 0x2201, 0x2202, 0x2203, 0x2204, 0x2206, 0x2207, 0x2208, 0x2209, 0x220A, 0x220B, 0x220B, 0x220C, 0x220E, 0x220F, 0x220F, 0x2210, 0x2210, 0x2211, 0x2211, 0x2212, 0x2213, 0x2214, 0x2214, 0x2215, 0x2215, 0x2216, 0x2219, 0x221A, 0x221A, 0x221B, 0x221C, 0x221D, 0x2220, 0x2221, 0x2222, 0x2223, 0x2223, 0x2224, 0x2224, 0x2225, 0x2225, 0x2226, 0x2226, 0x2227, 0x222C, 0x222D, 0x222D, 0x222E, 0x222E, 0x222F, 0x2233, 0x2234, 0x2237, 0x2238, 0x223B, 0x223C, 0x223D, 0x223E, 0x2247, 0x2248, 0x2248, 0x2249, 0x224B, 0x224C, 0x224C, 0x224D, 0x2251, 0x2252, 0x2252, 0x2253, 0x225F, 0x2260, 0x2261, 0x2262, 0x2263, 0x2264, 0x2267, 0x2268, 0x2269, 0x226A, 0x226B, 0x226C, 0x226D, 0x226E, 0x226F, 0x2270, 0x2281, 0x2282, 0x2283, 0x2284, 0x2285, 0x2286, 0x2287, 0x2288, 0x2294, 0x2295, 0x2295, 0x2296, 0x2298, 0x2299, 0x2299, 0x229A, 0x22A4, 0x22A5, 0x22A5, 0x22A6, 0x22BE, 0x22BF, 0x22BF, 0x22C0, 0x2311, 0x2312, 0x2312, 0x2313, 0x2328, 0x2329, 0x2329, 0x232A, 0x232A, 0x232B, 0x23B3, 0x23B4, 0x23B4, 0x23B5, 0x23B5, 0x23B6, 0x23B6, 0x23B7, 0x244A, 0x2460, 0x24BF, 0x24C0, 0x24CF, 0x24D0, 0x24E9, 0x24EA, 0x24EA, 0x24EB, 0x254B, 0x254C, 0x254F, 0x2550, 0x2574, 0x2575, 0x257F, 0x2580, 0x258F, 0x2590, 0x2591, 0x2592, 0x2595, 0x2596, 0x259F, 0x25A0, 0x25A1, 0x25A2, 0x25A2, 0x25A3, 0x25A9, 0x25AA, 0x25B1, 0x25B2, 0x25B3, 0x25B4, 0x25B5, 0x25B6, 0x25B7, 0x25B8, 0x25BB, 0x25BC, 0x25BD, 0x25BE, 0x25BF, 0x25C0, 0x25C1, 0x25C2, 0x25C5, 0x25C6, 0x25C8, 0x25C9, 0x25CA, 0x25CB, 0x25CB, 0x25CC, 0x25CD, 0x25CE, 0x25D1, 0x25D2, 0x25E1, 0x25E2, 0x25E5, 0x25E6, 0x25EE, 0x25EF, 0x25EF, 0x25F0, 0x2604, 0x2605, 0x2606, 0x2607, 0x2608, 0x2609, 0x2609, 0x260A, 0x260D, 0x260E, 0x260F, 0x2610, 0x2613, 0x2616, 0x2617, 0x2619, 0x261B, 0x261C, 0x261C, 0x261D, 0x261D, 0x261E, 0x261E, 0x261F, 0x263F, 0x2640, 0x2640, 0x2641, 0x2641, 0x2642, 0x2642, 0x2643, 0x265F, 0x2660, 0x2661, 0x2662, 0x2662, 0x2663, 0x2665, 0x2666, 0x2666, 0x2667, 0x266A, 0x266B, 0x266B, 0x266C, 0x266D, 0x266E, 0x266E, 0x266F, 0x266F, 0x2670, 0x275A, 0x275B, 0x275E, 0x2761, 0x2761, 0x2762, 0x2763, 0x2764, 0x2767, 0x2768, 0x2768, 0x2769, 0x2769, 0x276A, 0x276A, 0x276B, 0x276B, 0x276C, 0x276C, 0x276D, 0x276D, 0x276E, 0x276E, 0x276F, 0x276F, 0x2770, 0x2770, 0x2771, 0x2771, 0x2772, 0x2772, 0x2773, 0x2773, 0x2774, 0x2774, 0x2775, 0x2775, 0x2776, 0x27E5, 0x27E6, 0x27E6, 0x27E7, 0x27E7, 0x27E8, 0x27E8, 0x27E9, 0x27E9, 0x27EA, 0x27EA, 0x27EB, 0x27EB, 0x27F0, 0x2982, 0x2983, 0x2983, 0x2984, 0x2984, 0x2985, 0x2985, 0x2986, 0x2986, 0x2987, 0x2987, 0x2988, 0x2988, 0x2989, 0x2989, 0x298A, 0x298A, 0x298B, 0x298B, 0x298C, 0x298C, 0x298D, 0x298D, 0x298E, 0x298E, 0x298F, 0x298F, 0x2990, 0x2990, 0x2991, 0x2991, 0x2992, 0x2992, 0x2993, 0x2993, 0x2994, 0x2994, 0x2995, 0x2995, 0x2996, 0x2996, 0x2997, 0x2997, 0x2998, 0x2998, 0x2999, 0x29D7, 0x29D8, 0x29D8, 0x29D9, 0x29D9, 0x29DA, 0x29DA, 0x29DB, 0x29DB, 0x29DC, 0x29FB, 0x29FC, 0x29FC, 0x29FD, 0x29FD, 0x29FE, 0x2AFF, 0x2E80, 0x3000, 0x3001, 0x3002, 0x3003, 0x3004, 0x3005, 0x3005, 0x3006, 0x3007, 0x3008, 0x3008, 0x3009, 0x3009, 0x300A, 0x300A, 0x300B, 0x300B, 0x300C, 0x300C, 0x300D, 0x300D, 0x300E, 0x300E, 0x300F, 0x300F, 0x3010, 0x3010, 0x3011, 0x3011, 0x3012, 0x3013, 0x3014, 0x3014, 0x3015, 0x3015, 0x3016, 0x3016, 0x3017, 0x3017, 0x3018, 0x3018, 0x3019, 0x3019, 0x301A, 0x301A, 0x301B, 0x301B, 0x301C, 0x301C, 0x301D, 0x301D, 0x301E, 0x301F, 0x3020, 0x3029, 0x302A, 0x302F, 0x3030, 0x303A, 0x303B, 0x303C, 0x303D, 0x303F, 0x3041, 0x3041, 0x3042, 0x3042, 0x3043, 0x3043, 0x3044, 0x3044, 0x3045, 0x3045, 0x3046, 0x3046, 0x3047, 0x3047, 0x3048, 0x3048, 0x3049, 0x3049, 0x304A, 0x3062, 0x3063, 0x3063, 0x3064, 0x3082, 0x3083, 0x3083, 0x3084, 0x3084, 0x3085, 0x3085, 0x3086, 0x3086, 0x3087, 0x3087, 0x3088, 0x308D, 0x308E, 0x308E, 0x308F, 0x3094, 0x3095, 0x3096, 0x3099, 0x309A, 0x309B, 0x309E, 0x309F, 0x309F, 0x30A0, 0x30A1, 0x30A2, 0x30A2, 0x30A3, 0x30A3, 0x30A4, 0x30A4, 0x30A5, 0x30A5, 0x30A6, 0x30A6, 0x30A7, 0x30A7, 0x30A8, 0x30A8, 0x30A9, 0x30A9, 0x30AA, 0x30C2, 0x30C3, 0x30C3, 0x30C4, 0x30E2, 0x30E3, 0x30E3, 0x30E4, 0x30E4, 0x30E5, 0x30E5, 0x30E6, 0x30E6, 0x30E7, 0x30E7, 0x30E8, 0x30ED, 0x30EE, 0x30EE, 0x30EF, 0x30F4, 0x30F5, 0x30F6, 0x30F7, 0x30FA, 0x30FB, 0x30FB, 0x30FC, 0x30FC, 0x30FD, 0x30FD, 0x30FE, 0x31B7, 0x31F0, 0x31FF, 0x3200, 0xD7A3, 0xD800, 0xDFFF, 0xE000, 0xF8FF, 0xF900, 0xFA6A, 0xFB00, 0xFB1D, 0xFB1E, 0xFB1E, 0xFB1F, 0xFD3D, 0xFD3E, 0xFD3E, 0xFD3F, 0xFD3F, 0xFD50, 0xFDFB, 0xFDFC, 0xFDFC, 0xFE00, 0xFE23, 0xFE30, 0xFE34, 0xFE35, 0xFE35, 0xFE36, 0xFE36, 0xFE37, 0xFE37, 0xFE38, 0xFE38, 0xFE39, 0xFE39, 0xFE3A, 0xFE3A, 0xFE3B, 0xFE3B, 0xFE3C, 0xFE3C, 0xFE3D, 0xFE3D, 0xFE3E, 0xFE3E, 0xFE3F, 0xFE3F, 0xFE40, 0xFE40, 0xFE41, 0xFE41, 0xFE42, 0xFE42, 0xFE43, 0xFE43, 0xFE44, 0xFE44, 0xFE45, 0xFE4F, 0xFE50, 0xFE50, 0xFE51, 0xFE51, 0xFE52, 0xFE52, 0xFE54, 0xFE55, 0xFE56, 0xFE57, 0xFE58, 0xFE58, 0xFE59, 0xFE59, 0xFE5A, 0xFE5A, 0xFE5B, 0xFE5B, 0xFE5C, 0xFE5C, 0xFE5D, 0xFE5D, 0xFE5E, 0xFE5E, 0xFE5F, 0xFE68, 0xFE69, 0xFE69, 0xFE6A, 0xFE6A, 0xFE6B, 0xFE6B, 0xFE70, 0xFEFC, 0xFEFF, 0xFEFF, 0xFF01, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF04, 0xFF05, 0xFF05, 0xFF06, 0xFF07, 0xFF08, 0xFF08, 0xFF09, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0C, 0xFF0D, 0xFF0D, 0xFF0E, 0xFF0E, 0xFF0F, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1E, 0xFF1F, 0xFF1F, 0xFF20, 0xFF3A, 0xFF3B, 0xFF3B, 0xFF3C, 0xFF3C, 0xFF3D, 0xFF3D, 0xFF3E, 0xFF5A, 0xFF5B, 0xFF5B, 0xFF5C, 0xFF5C, 0xFF5D, 0xFF5D, 0xFF5E, 0xFF5E, 0xFF5F, 0xFF5F, 0xFF60, 0xFF61, 0xFF62, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF65, 0xFF66, 0xFF66, 0xFF67, 0xFF70, 0xFF71, 0xFF9D, 0xFF9E, 0xFF9F, 0xFFA0, 0xFFDC, 0xFFE0, 0xFFE0, 0xFFE1, 0xFFE1, 0xFFE2, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE8, 0xFFEE, 0xFFF9, 0xFFFB, 0xFFFC, 0xFFFC, 0xFFFD, 0xFFFF, }; static final byte [] raw_classes = { CHAR_CLASS_CM, CHAR_CLASS_BA, CHAR_CLASS_LF, CHAR_CLASS_CM, CHAR_CLASS_BK, CHAR_CLASS_CR, CHAR_CLASS_CM, CHAR_CLASS_SP, CHAR_CLASS_EX, CHAR_CLASS_QU, CHAR_CLASS_AL, CHAR_CLASS_PR, CHAR_CLASS_PO, CHAR_CLASS_AL, CHAR_CLASS_QU, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_PR, CHAR_CLASS_IS, CHAR_CLASS_HY, CHAR_CLASS_IS, CHAR_CLASS_SY, CHAR_CLASS_NU, CHAR_CLASS_IS, CHAR_CLASS_AL, CHAR_CLASS_EX, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_PR, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_BA, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_GL, CHAR_CLASS_AI, CHAR_CLASS_PO, CHAR_CLASS_PR, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_QU, CHAR_CLASS_AL, CHAR_CLASS_BA, CHAR_CLASS_AL, CHAR_CLASS_PO, CHAR_CLASS_PR, CHAR_CLASS_AI, CHAR_CLASS_BB, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_QU, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_BB, CHAR_CLASS_AI, CHAR_CLASS_BB, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_IS, CHAR_CLASS_BA, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_PR, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_SA, CHAR_CLASS_CM, CHAR_CLASS_SA, CHAR_CLASS_CM, CHAR_CLASS_PR, CHAR_CLASS_SA, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_NS, CHAR_CLASS_SA, CHAR_CLASS_CM, CHAR_CLASS_SA, CHAR_CLASS_CM, CHAR_CLASS_SA, CHAR_CLASS_CM, CHAR_CLASS_NU, CHAR_CLASS_SA, CHAR_CLASS_AL, CHAR_CLASS_BA, CHAR_CLASS_GL, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_SA, CHAR_CLASS_CM, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_SA, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_ID, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_BA, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_BA, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_SA, CHAR_CLASS_CM, CHAR_CLASS_NS, CHAR_CLASS_BA, CHAR_CLASS_NS, CHAR_CLASS_PR, CHAR_CLASS_AL, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_BB, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_NU, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_BA, CHAR_CLASS_GL, CHAR_CLASS_BA, CHAR_CLASS_ZW, CHAR_CLASS_CM, CHAR_CLASS_BA, CHAR_CLASS_GL, CHAR_CLASS_BA, CHAR_CLASS_B2, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_QU, CHAR_CLASS_OP, CHAR_CLASS_QU, CHAR_CLASS_OP, CHAR_CLASS_QU, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_IN, CHAR_CLASS_BA, CHAR_CLASS_BK, CHAR_CLASS_CM, CHAR_CLASS_GL, CHAR_CLASS_PO, CHAR_CLASS_AL, CHAR_CLASS_QU, CHAR_CLASS_AI, CHAR_CLASS_NS, CHAR_CLASS_AL, CHAR_CLASS_NS, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_BA, CHAR_CLASS_GL, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_PR, CHAR_CLASS_PO, CHAR_CLASS_PR, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_PO, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_PO, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_PR, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_PO, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_PR, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_QU, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_AI, CHAR_CLASS_AL, CHAR_CLASS_QU, CHAR_CLASS_AL, CHAR_CLASS_EX, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_ID, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_NS, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_CM, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_CM, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_SG, CHAR_CLASS_XX, CHAR_CLASS_ID, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_AL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_AL, CHAR_CLASS_PO, CHAR_CLASS_CM, CHAR_CLASS_ID, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_CL, CHAR_CLASS_NS, CHAR_CLASS_EX, CHAR_CLASS_ID, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_PR, CHAR_CLASS_PO, CHAR_CLASS_ID, CHAR_CLASS_AL, CHAR_CLASS_GL, CHAR_CLASS_EX, CHAR_CLASS_ID, CHAR_CLASS_PR, CHAR_CLASS_PO, CHAR_CLASS_ID, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_NS, CHAR_CLASS_ID, CHAR_CLASS_EX, CHAR_CLASS_ID, CHAR_CLASS_OP, CHAR_CLASS_ID, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_OP, CHAR_CLASS_ID, CHAR_CLASS_CL, CHAR_CLASS_ID, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_OP, CHAR_CLASS_CL, CHAR_CLASS_NS, CHAR_CLASS_AL, CHAR_CLASS_NS, CHAR_CLASS_AL, CHAR_CLASS_NS, CHAR_CLASS_AL, CHAR_CLASS_PO, CHAR_CLASS_PR, CHAR_CLASS_ID, CHAR_CLASS_PR, CHAR_CLASS_AL, CHAR_CLASS_CM, CHAR_CLASS_CB, CHAR_CLASS_AI }; }