1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 1998-2004, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 * 9 * Created on Dec 3, 2003 10 * 11 ******************************************************************************* 12 */ 13 package com.ibm.icu.dev.tool.layout; 14 15 import com.ibm.icu.lang.UCharacter; 16 import com.ibm.icu.lang.UProperty; 17 18 public class ArabicShaping { 19 20 // arabic shaping type code 21 22 // shaping bit masks 23 static final int MASK_SHAPE_RIGHT = 1; // if this bit set, shapes to right 24 static final int MASK_SHAPE_LEFT = 2; // if this bit set, shapes to left 25 static final int MASK_TRANSPARENT = 4; // if this bit set, is transparent (ignore other bits) 26 static final int MASK_NOSHAPE = 8; // if this bit set, don't shape this char, i.e. tatweel 27 28 // shaping values 29 public static final int VALUE_NONE = 0; 30 public static final int VALUE_RIGHT = MASK_SHAPE_RIGHT; 31 public static final int VALUE_LEFT = MASK_SHAPE_LEFT; 32 public static final int VALUE_DUAL = MASK_SHAPE_RIGHT | MASK_SHAPE_LEFT; 33 public static final int VALUE_TRANSPARENT = MASK_TRANSPARENT; 34 public static final int VALUE_NOSHAPE_DUAL = MASK_NOSHAPE | VALUE_DUAL; 35 public static final int VALUE_NOSHAPE_NONE = MASK_NOSHAPE; 36 getShapeType(char ch)37 public static int getShapeType(char ch) 38 { 39 int tt = UCharacter.getIntPropertyValue(ch, UProperty.JOINING_TYPE); 40 41 switch(tt) { 42 case UCharacter.JoiningType.JOIN_CAUSING: 43 return VALUE_NOSHAPE_DUAL; 44 45 case UCharacter.JoiningType.LEFT_JOINING: 46 return VALUE_LEFT; 47 48 case UCharacter.JoiningType.RIGHT_JOINING: 49 return VALUE_RIGHT; 50 51 case UCharacter.JoiningType.DUAL_JOINING: 52 return VALUE_DUAL; 53 54 case UCharacter.JoiningType.TRANSPARENT: 55 return VALUE_TRANSPARENT; 56 57 case UCharacter.JoiningType.NON_JOINING: 58 default: 59 return VALUE_NOSHAPE_NONE; 60 } 61 } 62 63 /* 64 * Chars in logical order. 65 * leftType is shaping code of char to logical left of range 66 * rightType is shaping code of char to logical right of range 67 */ 68 shape(char[] chars, int leftType, int rightType, ClassTable isolClassTable)69 public static void shape(char[] chars, int leftType, int rightType, ClassTable isolClassTable) { 70 // iterate in logical order from left to right 71 // 72 // the effective right char is the most recently encountered 73 // non-transparent char 74 // 75 // four boolean states: 76 // the effective right char shapes 77 // the effective right char causes right shaping 78 // the current char shapes 79 // the current char causes left shaping 80 // 81 // if both cause shaping, then 82 // right += 2 (isolate to initial, or final to medial) 83 // cur += 1 (isolate to final) 84 85 // ern is effective right logical index 86 int ern = -1; 87 88 boolean rightShapes = false; 89 boolean rightCauses = (rightType & MASK_SHAPE_LEFT) != 0; 90 91 for (int n = 0; n < chars.length; n++) { 92 char c = chars[n]; 93 int t = getShapeType(c); 94 95 if ((t & MASK_TRANSPARENT) != 0) { 96 continue; 97 } 98 99 boolean curShapes = (t & MASK_NOSHAPE) == 0; 100 boolean curCauses = (t & MASK_SHAPE_RIGHT) != 0; 101 102 if (rightCauses && curCauses) { 103 if (rightShapes) { 104 chars[ern] += 2; 105 } 106 107 if (curShapes) { 108 chars[n] = (char) (isolClassTable.getGlyphClassID(c) + 1); 109 } 110 } else { 111 if (curShapes) { 112 chars[n] = (char) isolClassTable.getGlyphClassID(c); 113 } 114 } 115 116 rightShapes = curShapes; 117 rightCauses = (t & MASK_SHAPE_LEFT) != 0; 118 ern = n; 119 } 120 121 if (rightShapes && rightCauses && (leftType & MASK_SHAPE_RIGHT) != 0) { 122 chars[ern] += 2; 123 } 124 } 125 } 126