001: /*
002: *******************************************************************************
003: * Copyright (C) 1998-2004, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: *
007: * Created on Dec 3, 2003
008: *
009: *******************************************************************************
010: */
011: package com.ibm.icu.dev.tool.layout;
012:
013: import com.ibm.icu.lang.UCharacter;
014: import com.ibm.icu.lang.UProperty;
015:
016: public class ArabicShaping {
017:
018: // arabic shaping type code
019:
020: // shaping bit masks
021: static final int MASK_SHAPE_RIGHT = 1; // if this bit set, shapes to right
022: static final int MASK_SHAPE_LEFT = 2; // if this bit set, shapes to left
023: static final int MASK_TRANSPARENT = 4; // if this bit set, is transparent (ignore other bits)
024: static final int MASK_NOSHAPE = 8; // if this bit set, don't shape this char, i.e. tatweel
025:
026: // shaping values
027: public static final int VALUE_NONE = 0;
028: public static final int VALUE_RIGHT = MASK_SHAPE_RIGHT;
029: public static final int VALUE_LEFT = MASK_SHAPE_LEFT;
030: public static final int VALUE_DUAL = MASK_SHAPE_RIGHT
031: | MASK_SHAPE_LEFT;
032: public static final int VALUE_TRANSPARENT = MASK_TRANSPARENT;
033: public static final int VALUE_NOSHAPE_DUAL = MASK_NOSHAPE
034: | VALUE_DUAL;
035: public static final int VALUE_NOSHAPE_NONE = MASK_NOSHAPE;
036:
037: public static int getShapeType(char ch) {
038: int tt = UCharacter.getIntPropertyValue(ch,
039: UProperty.JOINING_TYPE);
040:
041: switch (tt) {
042: case UCharacter.JoiningType.JOIN_CAUSING:
043: return VALUE_NOSHAPE_DUAL;
044:
045: case UCharacter.JoiningType.LEFT_JOINING:
046: return VALUE_LEFT;
047:
048: case UCharacter.JoiningType.RIGHT_JOINING:
049: return VALUE_RIGHT;
050:
051: case UCharacter.JoiningType.DUAL_JOINING:
052: return VALUE_DUAL;
053:
054: case UCharacter.JoiningType.TRANSPARENT:
055: return VALUE_TRANSPARENT;
056:
057: case UCharacter.JoiningType.NON_JOINING:
058: default:
059: return VALUE_NOSHAPE_NONE;
060: }
061: }
062:
063: /*
064: * Chars in logical order.
065: * leftType is shaping code of char to logical left of range
066: * rightType is shaping code of char to logical right of range
067: */
068:
069: public static void shape(char[] chars, int leftType, int rightType,
070: ClassTable isolClassTable) {
071: // iterate in logical order from left to right
072: //
073: // the effective right char is the most recently encountered
074: // non-transparent char
075: //
076: // four boolean states:
077: // the effective right char shapes
078: // the effective right char causes right shaping
079: // the current char shapes
080: // the current char causes left shaping
081: //
082: // if both cause shaping, then
083: // right += 2 (isolate to initial, or final to medial)
084: // cur += 1 (isolate to final)
085:
086: // ern is effective right logical index
087: int ern = -1;
088:
089: boolean rightShapes = false;
090: boolean rightCauses = (rightType & MASK_SHAPE_LEFT) != 0;
091:
092: for (int n = 0; n < chars.length; n++) {
093: char c = chars[n];
094: int t = getShapeType(c);
095:
096: if ((t & MASK_TRANSPARENT) != 0) {
097: continue;
098: }
099:
100: boolean curShapes = (t & MASK_NOSHAPE) == 0;
101: boolean curCauses = (t & MASK_SHAPE_RIGHT) != 0;
102:
103: if (rightCauses && curCauses) {
104: if (rightShapes) {
105: chars[ern] += 2;
106: }
107:
108: if (curShapes) {
109: chars[n] = (char) (isolClassTable
110: .getGlyphClassID(c) + 1);
111: }
112: } else {
113: if (curShapes) {
114: chars[n] = (char) isolClassTable.getGlyphClassID(c);
115: }
116: }
117:
118: rightShapes = curShapes;
119: rightCauses = (t & MASK_SHAPE_LEFT) != 0;
120: ern = n;
121: }
122:
123: if (rightShapes && rightCauses
124: && (leftType & MASK_SHAPE_RIGHT) != 0) {
125: chars[ern] += 2;
126: }
127: }
128: }
|