001: /**
002: *******************************************************************************
003: * Copyright (C) 2002-2005, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */package com.ibm.icu.dev.tool.layout;
007:
008: import com.ibm.icu.text.UTF16;
009: import java.util.Vector;
010:
011: /**
012: * @author Owner
013: *
014: * To change the template for this generated type comment go to
015: * Window>Preferences>Java>Code Generation>Code and Comments
016: */
017: public class DecompTable implements LookupSubtable {
018: static class DecompEntry {
019: private int composed;
020: private int[] decomp;
021:
022: DecompEntry(int composedChar, String decomposition) {
023: int decompCount = UTF16.countCodePoint(decomposition);
024:
025: composed = composedChar;
026: decomp = new int[decompCount];
027:
028: int out = 0, cp;
029:
030: for (int in = 0; in < decomposition.length(); in += UTF16
031: .getCharCount(cp)) {
032: cp = UTF16.charAt(decomposition, in);
033: decomp[out++] = cp;
034: }
035: }
036:
037: public int getComposedCharacter() {
038: return composed;
039: }
040:
041: public int[] getDecomposition() {
042: return decomp;
043: }
044:
045: public int getDecompositionCount() {
046: return decomp.length;
047: }
048:
049: public int getDecomposedCharacter(int i) {
050: if (i >= 0 && i < decomp.length) {
051: return decomp[i];
052: }
053:
054: return -1;
055: }
056:
057: public int compareTo(DecompEntry that) {
058: return this .composed - that.composed;
059: }
060:
061: //
062: // Straight insertion sort from Knuth vol. III, pg. 81
063: //
064: public static void sort(DecompEntry[] table, Vector decompVector) {
065: for (int j = 0; j < table.length; j += 1) {
066: int i;
067: DecompEntry v = (DecompEntry) decompVector.elementAt(j);
068:
069: for (i = j - 1; i >= 0; i -= 1) {
070: if (v.compareTo(table[i]) >= 0) {
071: break;
072: }
073:
074: table[i + 1] = table[i];
075: }
076:
077: table[i + 1] = v;
078: }
079: }
080: }
081:
082: private Vector decompVector;
083: private DecompEntry[] decompEntries;
084: private int snapshotSize;
085:
086: public DecompTable() {
087: decompVector = new Vector();
088: decompEntries = null;
089: snapshotSize = -1;
090: }
091:
092: public void add(int composed, String decomposition) {
093: DecompEntry entry = new DecompEntry(composed, decomposition);
094:
095: decompVector.addElement(entry);
096: }
097:
098: public int getComposedCharacter(int i) {
099: if (i < 0 || i > decompEntries.length) {
100: return -1;
101: }
102:
103: return decompEntries[i].getComposedCharacter();
104: }
105:
106: public int getDecompositionCount(int i) {
107: if (i < 0 || i > decompEntries.length) {
108: return -1;
109: }
110:
111: return decompEntries[i].getDecompositionCount();
112: }
113:
114: public boolean hasEntries() {
115: return decompVector.size() > 0;
116: }
117:
118: private void snapshot() {
119: if (snapshotSize != decompVector.size()) {
120: snapshotSize = decompVector.size();
121: decompEntries = new DecompEntry[snapshotSize];
122: DecompEntry.sort(decompEntries, decompVector);
123: }
124: }
125:
126: public void writeLookupSubtable(OpenTypeTableWriter writer) {
127: snapshot();
128:
129: int multipleSubstitutionsBase = writer.getOutputIndex();
130: int coverageTableIndex, sequenceOffsetIndex;
131: int sequenceCount = decompEntries.length;
132:
133: writer.writeData(1); // format = 1
134:
135: coverageTableIndex = writer.getOutputIndex();
136: writer.writeData(0); // coverage table offset (fixed later)
137:
138: writer.writeData(sequenceCount);
139:
140: sequenceOffsetIndex = writer.getOutputIndex();
141: for (int s = 0; s < sequenceCount; s += 1) {
142: writer.writeData(0); // offset to sequence table (fixed later);
143: }
144:
145: for (int s = 0; s < sequenceCount; s += 1) {
146: DecompEntry entry = decompEntries[s];
147: int decompCount = entry.getDecompositionCount();
148:
149: writer.fixOffset(sequenceOffsetIndex++,
150: multipleSubstitutionsBase);
151:
152: writer.writeData(decompCount); // glyphCount
153:
154: for (int g = 0; g < decompCount; g += 1) {
155: writer.writeData(entry.getDecomposedCharacter(g));
156: }
157: }
158:
159: // write a format 1 coverage table
160: writer.fixOffset(coverageTableIndex, multipleSubstitutionsBase);
161: writer.writeData(1); // format = 1
162: writer.writeData(sequenceCount); // glyphCount
163:
164: for (int i = 0; i < sequenceCount; i += 1) {
165: writer.writeData(decompEntries[i].getComposedCharacter());
166: }
167: }
168: }
|