]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/tools/misc/src/com/ibm/icu/dev/tool/layout/ClassTable.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / tools / misc / src / com / ibm / icu / dev / tool / layout / ClassTable.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1998-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  *\r
7  * Created on Dec 3, 2003\r
8  *\r
9  *******************************************************************************\r
10  */\r
11 package com.ibm.icu.dev.tool.layout;\r
12 \r
13 import java.util.Vector;\r
14 \r
15 import com.ibm.icu.impl.Utility;\r
16 \r
17 public class ClassTable implements LookupSubtable\r
18 {\r
19     static class ClassEntry\r
20     {\r
21         private int glyphID;\r
22         private int classID;\r
23         \r
24         public ClassEntry(int glyphID, int classID)\r
25         {\r
26             this.glyphID = glyphID;\r
27             this.classID = classID;\r
28         }\r
29         \r
30         public int getGlyphID()\r
31         {\r
32             return glyphID;\r
33         }\r
34         \r
35         public int getClassID()\r
36         {\r
37             return classID;\r
38         }\r
39         \r
40         public int compareTo(ClassEntry that)\r
41         {\r
42             return this.glyphID - that.glyphID;\r
43         }\r
44         \r
45         //\r
46         // Straight insertion sort from Knuth vol. III, pg. 81\r
47         //\r
48         public static void sort(ClassEntry[] table, Vector unsorted)\r
49         {\r
50             for (int e = 0; e < table.length; e += 1) {\r
51                 int i;\r
52                 ClassEntry v = (ClassEntry) unsorted.elementAt(e);\r
53 \r
54                 for (i = e - 1; i >= 0; i -= 1) {\r
55                     if (v.compareTo(table[i]) >= 0) {\r
56                       break;\r
57                     }\r
58 \r
59                     table[i + 1] = table[i];\r
60                 }\r
61 \r
62                 table[i + 1] = v;\r
63             }\r
64         }\r
65         \r
66         public static int search(ClassEntry[] table, int glyphID)\r
67         {\r
68             int log2 = Utility.highBit(table.length);\r
69             int power = 1 << log2;\r
70             int extra = table.length - power;\r
71             int probe = power;\r
72             int index = 0;\r
73 \r
74             if (table[extra].glyphID <= glyphID) {\r
75               index = extra;\r
76             }\r
77 \r
78             while (probe > (1 << 0)) {\r
79                 probe >>= 1;\r
80 \r
81                 if (table[index + probe].glyphID <= glyphID) {\r
82                     index += probe;\r
83                 }\r
84             }\r
85 \r
86             if (table[index].glyphID == glyphID) {\r
87                 return index;\r
88             }\r
89 \r
90             return -1;\r
91         }\r
92     }\r
93     \r
94     static class ClassRangeRecord\r
95     {\r
96         private int startGlyphID;\r
97         private int endGlyphID;\r
98         private int classID;\r
99         \r
100         public ClassRangeRecord(int startGlyphID, int endGlyphID, int classID)\r
101         {\r
102             this.startGlyphID = startGlyphID;\r
103             this.endGlyphID = endGlyphID;\r
104             this.classID = classID;\r
105         }\r
106         \r
107         public void write(OpenTypeTableWriter writer)\r
108         {\r
109             System.out.print(Utility.hex(startGlyphID, 6));\r
110             System.out.print(" - ");\r
111             System.out.print(Utility.hex(endGlyphID, 6));\r
112             System.out.print(": ");\r
113             System.out.println(classID);\r
114             \r
115             writer.writeData(startGlyphID);\r
116             writer.writeData(endGlyphID);\r
117             writer.writeData(classID);\r
118         }\r
119     }\r
120     \r
121     private Vector classMap;\r
122     private ClassEntry[] classTable;\r
123     private int snapshotSize;\r
124     \r
125     public ClassTable()\r
126     {\r
127         this.classMap = new Vector();\r
128         this.classTable = null;\r
129         this.snapshotSize = -1;\r
130         \r
131     }\r
132     \r
133     public void addMapping(int charID, int classID)\r
134     {\r
135         ClassEntry entry = new ClassEntry(charID, classID);\r
136         \r
137         classMap.addElement(entry);\r
138     }\r
139     \r
140     public void addMapping(int startCharID, int endCharID, int classID)\r
141     {\r
142         for (int charID = startCharID; charID <= endCharID; charID += 1) {\r
143             addMapping(charID, classID);\r
144         }\r
145     }\r
146     \r
147     public int getGlyphClassID(int glyphID)\r
148     {\r
149         int index = ClassEntry.search(classTable, glyphID);\r
150         \r
151         if (index >= 0) {\r
152             return classTable[index].getClassID();\r
153         }\r
154         \r
155         return 0;\r
156     }\r
157     \r
158     public void snapshot()\r
159     {\r
160         if (snapshotSize != classMap.size()) {\r
161             snapshotSize = classMap.size();\r
162             classTable = new ClassEntry[snapshotSize];\r
163 \r
164             ClassEntry.sort(classTable, classMap);\r
165         }\r
166     }\r
167     \r
168     public void writeClassTable(OpenTypeTableWriter writer)\r
169     {\r
170         snapshot();\r
171         \r
172         Vector classRanges = new Vector();\r
173         int startIndex = 0;\r
174         \r
175         while (startIndex < classTable.length) {\r
176             int startID = classTable[startIndex].getGlyphID();\r
177             int classID = classTable[startIndex].getClassID();\r
178             int nextID = startID;\r
179             int endID = startID;\r
180             int endIndex;\r
181             \r
182             for (endIndex = startIndex; endIndex < classTable.length; endIndex += 1) {\r
183                 if (classTable[endIndex].getGlyphID() != nextID ||\r
184                     classTable[endIndex].getClassID() != classID) {\r
185                     break;\r
186                 }\r
187                 \r
188                 endID = nextID;\r
189                 nextID += 1;\r
190             }\r
191             \r
192             if (classID != 0) {\r
193                 ClassRangeRecord range = new ClassRangeRecord(startID, endID, classID);\r
194                 \r
195                 classRanges.addElement(range);\r
196             }\r
197             \r
198             startIndex = endIndex;\r
199         }\r
200         \r
201         writer.writeData(2);                    // table format = 2 (class ranges)\r
202         writer.writeData(classRanges.size());   // class range count\r
203         \r
204         for (int i = 0; i < classRanges.size(); i += 1) {\r
205             ClassRangeRecord range = (ClassRangeRecord) classRanges.elementAt(i);\r
206             \r
207             range.write(writer);\r
208         }\r
209     }\r
210 \r
211     public void writeLookupSubtable(OpenTypeTableWriter writer)\r
212     {\r
213         int singleSubstitutionsBase = writer.getOutputIndex();\r
214         int coverageTableIndex;\r
215         \r
216         snapshot();\r
217         \r
218         writer.writeData(2); // format 2: Specified output glyph indices\r
219         coverageTableIndex = writer.getOutputIndex();\r
220         writer.writeData(0); // offset to coverage table (fixed later)\r
221         writer.writeData(classTable.length); // number of glyphIDs in substitution array\r
222         \r
223         for (int i = 0; i < classTable.length; i += 1) {\r
224             writer.writeData(classTable[i].getClassID());\r
225         }\r
226         \r
227         writer.fixOffset(coverageTableIndex, singleSubstitutionsBase);\r
228         writer.writeData(1);\r
229         writer.writeData(classTable.length);\r
230         \r
231         for (int i = 0; i < classTable.length; i += 1) {\r
232             writer.writeData(classTable[i].getGlyphID());\r
233         }\r
234     }\r
235 }\r
236     \r
237