KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > gvt > font > AWTGlyphGeometryCache


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.gvt.font;
19
20 import java.awt.Shape JavaDoc;
21 import java.awt.geom.Rectangle2D JavaDoc;
22 import java.lang.ref.ReferenceQueue JavaDoc;
23 import java.lang.ref.SoftReference JavaDoc;
24
25 /**
26  * This class represents a doubly indexed hash table, which holds
27  * soft references to the contained glyph geometry informations.
28  *
29  * @author <a HREF="mailto:stephane@hillion.org">Stephane Hillion</a>
30  * @author <a HREF="mailto:tkormann@ilog.fr">Thierry Kormann</a>
31  * @version $Id: AWTGlyphGeometryCache.java,v 1.4 2004/08/18 07:14:35 vhardy Exp $
32  */

33 public class AWTGlyphGeometryCache {
34
35     /**
36      * The initial capacity
37      */

38     protected final static int INITIAL_CAPACITY = 71;
39
40     /**
41      * The underlying array
42      */

43     protected Entry[] table;
44
45     /**
46      * The number of entries
47      */

48     protected int count;
49
50     /**
51      * The reference queue.
52      */

53     protected ReferenceQueue JavaDoc referenceQueue = new ReferenceQueue JavaDoc();
54
55     /**
56      * Creates a new AWTGlyphGeometryCache.
57      */

58     public AWTGlyphGeometryCache() {
59         table = new Entry[INITIAL_CAPACITY];
60     }
61
62     /**
63      * Creates a new AWTGlyphGeometryCache.
64      * @param c The inital capacity.
65      */

66     public AWTGlyphGeometryCache(int c) {
67         table = new Entry[c];
68     }
69
70     /**
71      * Returns the size of this table.
72      */

73     public int size() {
74         return count;
75     }
76
77     /**
78      * Gets the value of a variable
79      * @return the value or null
80      */

81     public Value get(char c) {
82         int hash = hashCode(c) & 0x7FFFFFFF;
83         int index = hash % table.length;
84
85         for (Entry e = table[index]; e != null; e = e.next) {
86             if ((e.hash == hash) && e.match(c)) {
87                 return (Value)e.get();
88             }
89         }
90         return null;
91     }
92
93     /**
94      * Sets a new value for the given variable
95      * @return the old value or null
96      */

97     public Value put(char c, Value value) {
98         removeClearedEntries();
99
100         int hash = hashCode(c) & 0x7FFFFFFF;
101         int index = hash % table.length;
102
103         Entry e = table[index];
104         if (e != null) {
105             if ((e.hash == hash) && e.match(c)) {
106                 Object JavaDoc old = e.get();
107                 table[index] = new Entry(hash, c, value, e.next);
108                 return (Value)old;
109             }
110             Entry o = e;
111             e = e.next;
112             while (e != null) {
113                 if ((e.hash == hash) && e.match(c)) {
114                     Object JavaDoc old = e.get();
115                     e = new Entry(hash, c, value, e.next);
116                     o.next = e;
117                     return (Value)old;
118                 }
119
120                 o = e;
121                 e = e.next;
122             }
123         }
124
125         // The key is not in the hash table
126
int len = table.length;
127         if (count++ >= (len * 3) >>> 2) {
128             rehash();
129             index = hash % table.length;
130         }
131
132         table[index] = new Entry(hash, c, value, table[index]);
133         return null;
134     }
135
136     /**
137      * Clears the table.
138      */

139     public void clear() {
140         table = new Entry[INITIAL_CAPACITY];
141         count = 0;
142         referenceQueue = new ReferenceQueue JavaDoc();
143     }
144
145     /**
146      * Rehash the table
147      */

148     protected void rehash () {
149         Entry[] oldTable = table;
150
151         table = new Entry[oldTable.length * 2 + 1];
152
153         for (int i = oldTable.length-1; i >= 0; i--) {
154             for (Entry old = oldTable[i]; old != null;) {
155                 Entry e = old;
156                 old = old.next;
157
158                 int index = e.hash % table.length;
159                 e.next = table[index];
160                 table[index] = e;
161             }
162         }
163     }
164
165     /**
166      * Computes a hash code corresponding to the given objects.
167      */

168     protected int hashCode(char c) {
169         return c;
170     }
171
172     /**
173      * Removes the cleared entries.
174      */

175     protected void removeClearedEntries() {
176         Entry e;
177         while ((e = (Entry)referenceQueue.poll()) != null) {
178             int index = e.hash % table.length;
179             Entry t = table[index];
180             if (t == e) {
181                 table[index] = e.next;
182             } else {
183                 loop: for (;t!=null;) {
184                     Entry c = t.next;
185                     if (c == e) {
186                         t.next = e.next;
187                         break loop;
188                     }
189                     t = c;
190                 }
191             }
192             count--;
193         }
194     }
195
196     /**
197      * The object that holds glyph geometry.
198      */

199     public static class Value {
200
201         protected Shape JavaDoc outline;
202         protected Rectangle2D JavaDoc gmB;
203         protected Rectangle2D JavaDoc outlineBounds;
204
205         /**
206          * Constructs a new Value with the specified parameter.
207          */

208         public Value(Shape JavaDoc outline, Rectangle2D JavaDoc gmB) {
209             this.outline = outline;
210             this.outlineBounds = outline.getBounds2D();
211             this.gmB = gmB;
212         }
213
214         /**
215          * Returns the outline of the glyph.
216          */

217         public Shape JavaDoc getOutline() {
218             return outline;
219         }
220
221         /**
222          * Returns the bounds of the glyph according to its glyph metrics.
223          */

224         public Rectangle2D JavaDoc getBounds2D() {
225             return gmB;
226         }
227
228         /**
229          * Returns the bounds of the outline.
230          */

231         public Rectangle2D JavaDoc getOutlineBounds2D() {
232             return outlineBounds;
233         }
234     }
235
236     /**
237      * To manage collisions
238      */

239     protected class Entry extends SoftReference JavaDoc {
240
241         /**
242          * The hash code
243          */

244         public int hash;
245
246         /**
247          * The character
248          */

249         public char c;
250
251         /**
252          * The next entry
253          */

254         public Entry next;
255
256         /**
257          * Creates a new entry
258          */

259         public Entry(int hash, char c, Value value, Entry next) {
260             super(value, referenceQueue);
261             this.hash = hash;
262             this.c = c;
263             this.next = next;
264         }
265
266         /**
267          * Whether this entry match the given keys.
268          */

269         public boolean match(char o2) {
270             return (c == o2);
271         }
272     }
273 }
274
Popular Tags