| /** |
| ******************************************************************************* |
| * Copyright (C) 2002-2010, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ******************************************************************************* |
| */ |
| |
| package com.ibm.icu.dev.tool.layout; |
| |
| import java.util.Vector; |
| |
| import com.ibm.icu.text.UTF16; |
| |
| /** |
| * @author Owner |
| * |
| * To change the template for this generated type comment go to |
| * Window>Preferences>Java>Code Generation>Code and Comments |
| */ |
| public class DecompTable implements LookupSubtable |
| { |
| static class DecompEntry |
| { |
| private int composed; |
| private int[] decomp; |
| |
| DecompEntry(int composedChar, String decomposition) |
| { |
| int decompCount = UTF16.countCodePoint(decomposition); |
| |
| composed = composedChar; |
| decomp = new int[decompCount]; |
| |
| int out = 0, cp; |
| |
| for (int in = 0; in < decomposition.length(); in += UTF16.getCharCount(cp)) { |
| cp = UTF16.charAt(decomposition, in); |
| decomp[out++] = cp; |
| } |
| } |
| |
| public int getComposedCharacter() |
| { |
| return composed; |
| } |
| |
| public int[] getDecomposition() |
| { |
| return decomp; |
| } |
| |
| public int getDecompositionCount() |
| { |
| return decomp.length; |
| } |
| |
| public int getDecomposedCharacter(int i) |
| { |
| if (i >= 0 && i < decomp.length) { |
| return decomp[i]; |
| } |
| |
| return -1; |
| } |
| |
| public int compareTo(DecompEntry that) |
| { |
| return this.composed - that.composed; |
| } |
| |
| // |
| // Straight insertion sort from Knuth vol. III, pg. 81 |
| // |
| public static void sort(DecompEntry[] table, Vector decompVector) |
| { |
| for (int j = 0; j < table.length; j += 1) { |
| int i; |
| DecompEntry v = (DecompEntry) decompVector.elementAt(j); |
| |
| for (i = j - 1; i >= 0; i -= 1) { |
| if (v.compareTo(table[i]) >= 0) { |
| break; |
| } |
| |
| table[i + 1] = table[i]; |
| } |
| |
| table[i + 1] = v; |
| } |
| } |
| } |
| |
| private Vector decompVector; |
| private DecompEntry[] decompEntries; |
| private int snapshotSize; |
| |
| public DecompTable() |
| { |
| decompVector = new Vector(); |
| decompEntries = null; |
| snapshotSize = -1; |
| } |
| |
| public void add(int composed, String decomposition) |
| { |
| DecompEntry entry = new DecompEntry(composed, decomposition); |
| |
| decompVector.addElement(entry); |
| } |
| |
| public int getComposedCharacter(int i) |
| { |
| if (i < 0 || i > decompEntries.length) { |
| return -1; |
| } |
| |
| return decompEntries[i].getComposedCharacter(); |
| } |
| |
| public int getDecompositionCount(int i) |
| { |
| if (i < 0 || i > decompEntries.length) { |
| return -1; |
| } |
| |
| return decompEntries[i].getDecompositionCount(); |
| } |
| |
| public boolean hasEntries() |
| { |
| return decompVector.size() > 0; |
| } |
| |
| private void snapshot() |
| { |
| if (snapshotSize != decompVector.size()) { |
| snapshotSize = decompVector.size(); |
| decompEntries = new DecompEntry[snapshotSize]; |
| DecompEntry.sort(decompEntries, decompVector); |
| } |
| } |
| |
| public void writeLookupSubtable(OpenTypeTableWriter writer) |
| { |
| snapshot(); |
| |
| int multipleSubstitutionsBase = writer.getOutputIndex(); |
| int coverageTableIndex, sequenceOffsetIndex; |
| int sequenceCount = decompEntries.length; |
| |
| writer.writeData(1); // format = 1 |
| |
| coverageTableIndex = writer.getOutputIndex(); |
| writer.writeData(0); // coverage table offset (fixed later) |
| |
| writer.writeData(sequenceCount); |
| |
| sequenceOffsetIndex = writer.getOutputIndex(); |
| for (int s = 0; s < sequenceCount; s += 1) { |
| writer.writeData(0); // offset to sequence table (fixed later); |
| } |
| |
| for (int s = 0; s < sequenceCount; s += 1) { |
| DecompEntry entry = decompEntries[s]; |
| int decompCount = entry.getDecompositionCount(); |
| |
| writer.fixOffset(sequenceOffsetIndex++, multipleSubstitutionsBase); |
| |
| writer.writeData(decompCount); // glyphCount |
| |
| for (int g = 0; g < decompCount; g += 1) { |
| writer.writeData(entry.getDecomposedCharacter(g)); |
| } |
| } |
| |
| // write a format 1 coverage table |
| writer.fixOffset(coverageTableIndex, multipleSubstitutionsBase); |
| writer.writeData(1); // format = 1 |
| writer.writeData(sequenceCount); // glyphCount |
| |
| for (int i = 0; i < sequenceCount; i += 1) { |
| writer.writeData(decompEntries[i].getComposedCharacter()); |
| } |
| } |
| } |