1 // 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html#License 3 /** 4 ******************************************************************************* 5 * Copyright (C) 2002-2010, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 */ 9 10 package com.ibm.icu.dev.tool.layout; 11 12 import java.util.Vector; 13 14 import com.ibm.icu.text.UTF16; 15 16 /** 17 * @author Owner 18 * 19 * To change the template for this generated type comment go to 20 * Window>Preferences>Java>Code Generation>Code and Comments 21 */ 22 public class DecompTable implements LookupSubtable 23 { 24 static class DecompEntry 25 { 26 private int composed; 27 private int[] decomp; 28 29 DecompEntry(int composedChar, String decomposition) 30 { 31 int decompCount = UTF16.countCodePoint(decomposition); 32 33 composed = composedChar; 34 decomp = new int[decompCount]; 35 36 int out = 0, cp; 37 38 for (int in = 0; in < decomposition.length(); in += UTF16.getCharCount(cp)) { 39 cp = UTF16.charAt(decomposition, in); 40 decomp[out++] = cp; 41 } 42 } 43 44 public int getComposedCharacter() 45 { 46 return composed; 47 } 48 49 public int[] getDecomposition() 50 { 51 return decomp; 52 } 53 54 public int getDecompositionCount() 55 { 56 return decomp.length; 57 } 58 59 public int getDecomposedCharacter(int i) 60 { 61 if (i >= 0 && i < decomp.length) { 62 return decomp[i]; 63 } 64 65 return -1; 66 } 67 68 public int compareTo(DecompEntry that) 69 { 70 return this.composed - that.composed; 71 } 72 73 // 74 // Straight insertion sort from Knuth vol. III, pg. 81 75 // 76 public static void sort(DecompEntry[] table, Vector decompVector) 77 { 78 for (int j = 0; j < table.length; j += 1) { 79 int i; 80 DecompEntry v = (DecompEntry) decompVector.elementAt(j); 81 82 for (i = j - 1; i >= 0; i -= 1) { 83 if (v.compareTo(table[i]) >= 0) { 84 break; 85 } 86 87 table[i + 1] = table[i]; 88 } 89 90 table[i + 1] = v; 91 } 92 } 93 } 94 95 private Vector decompVector; 96 private DecompEntry[] decompEntries; 97 private int snapshotSize; 98 99 public DecompTable() 100 { 101 decompVector = new Vector(); 102 decompEntries = null; 103 snapshotSize = -1; 104 } 105 106 public void add(int composed, String decomposition) 107 { 108 DecompEntry entry = new DecompEntry(composed, decomposition); 109 110 decompVector.addElement(entry); 111 } 112 113 public int getComposedCharacter(int i) 114 { 115 if (i < 0 || i > decompEntries.length) { 116 return -1; 117 } 118 119 return decompEntries[i].getComposedCharacter(); 120 } 121 122 public int getDecompositionCount(int i) 123 { 124 if (i < 0 || i > decompEntries.length) { 125 return -1; 126 } 127 128 return decompEntries[i].getDecompositionCount(); 129 } 130 131 public boolean hasEntries() 132 { 133 return decompVector.size() > 0; 134 } 135 136 private void snapshot() 137 { 138 if (snapshotSize != decompVector.size()) { 139 snapshotSize = decompVector.size(); 140 decompEntries = new DecompEntry[snapshotSize]; 141 DecompEntry.sort(decompEntries, decompVector); 142 } 143 } 144 145 public void writeLookupSubtable(OpenTypeTableWriter writer) 146 { 147 snapshot(); 148 149 int multipleSubstitutionsBase = writer.getOutputIndex(); 150 int coverageTableIndex, sequenceOffsetIndex; 151 int sequenceCount = decompEntries.length; 152 153 writer.writeData(1); // format = 1 154 155 coverageTableIndex = writer.getOutputIndex(); 156 writer.writeData(0); // coverage table offset (fixed later) 157 158 writer.writeData(sequenceCount); 159 160 sequenceOffsetIndex = writer.getOutputIndex(); 161 for (int s = 0; s < sequenceCount; s += 1) { 162 writer.writeData(0); // offset to sequence table (fixed later); 163 } 164 165 for (int s = 0; s < sequenceCount; s += 1) { 166 DecompEntry entry = decompEntries[s]; 167 int decompCount = entry.getDecompositionCount(); 168 169 writer.fixOffset(sequenceOffsetIndex++, multipleSubstitutionsBase); 170 171 writer.writeData(decompCount); // glyphCount 172 173 for (int g = 0; g < decompCount; g += 1) { 174 writer.writeData(entry.getDecomposedCharacter(g)); 175 } 176 } 177 178 // write a format 1 coverage table 179 writer.fixOffset(coverageTableIndex, multipleSubstitutionsBase); 180 writer.writeData(1); // format = 1 181 writer.writeData(sequenceCount); // glyphCount 182 183 for (int i = 0; i < sequenceCount; i += 1) { 184 writer.writeData(decompEntries[i].getComposedCharacter()); 185 } 186 } 187 } 188