KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Copyright 2002-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.Graphics2D JavaDoc;
21 import java.awt.Shape JavaDoc;
22 import java.awt.font.FontRenderContext JavaDoc;
23 import java.awt.font.GlyphJustificationInfo JavaDoc;
24 import java.awt.geom.AffineTransform JavaDoc;
25 import java.awt.geom.GeneralPath JavaDoc;
26 import java.awt.geom.Point2D JavaDoc;
27 import java.awt.geom.Rectangle2D JavaDoc;
28 import java.text.AttributedCharacterIterator JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31
32 import org.apache.batik.gvt.text.AttributedCharacterSpanIterator;
33
34 public class MultiGlyphVector implements GVTGlyphVector {
35
36     GVTGlyphVector [] gvs;
37     int [] nGlyphs;
38     int [] off;
39
40     int nGlyph;
41
42     public MultiGlyphVector(List JavaDoc gvs) {
43         this.gvs = new GVTGlyphVector[gvs.size()];
44         this.nGlyphs = new int[gvs.size()];
45         this.off = new int[gvs.size()];
46
47         Iterator JavaDoc iter = gvs.iterator();
48         int i=0;
49         while (iter.hasNext()) {
50             off[i] = nGlyph;
51
52             GVTGlyphVector gv = (GVTGlyphVector)iter.next();
53             this.gvs[i] = gv;
54             nGlyphs[i] = gv.getNumGlyphs();
55             nGlyph += nGlyphs[i];
56             i++;
57         }
58         nGlyphs[i-1]++;
59     }
60
61     /**
62      * Returns the number of glyphs in this GlyphVector.
63      */

64     public int getNumGlyphs() {
65         return nGlyph;
66     }
67
68
69     int getGVIdx(int glyphIdx) {
70         if (glyphIdx > nGlyph) return -1;
71         if (glyphIdx == nGlyph) return gvs.length-1;
72         for (int i=0; i<nGlyphs.length; i++)
73             if (glyphIdx-off[i] < nGlyphs[i]) return i;
74         return -1;
75     }
76
77     /**
78      * Returns the Font associated with this GlyphVector.
79      */

80     public GVTFont getFont() {
81         throw new IllegalArgumentException JavaDoc("Can't be correctly Implemented");
82     }
83
84     /**
85      * Returns the FontRenderContext associated with this GlyphVector.
86      */

87     public FontRenderContext JavaDoc getFontRenderContext() {
88         return gvs[0].getFontRenderContext();
89     }
90
91     /**
92      * Returns the glyphcode of the specified glyph.
93      */

94     public int getGlyphCode(int glyphIndex) {
95         int idx = getGVIdx(glyphIndex);
96         return gvs[idx].getGlyphCode(glyphIndex-off[idx]);
97     }
98
99     /**
100      * Returns the justification information for the glyph at the specified
101      * index into this GlyphVector.
102      */

103     public GlyphJustificationInfo JavaDoc getGlyphJustificationInfo(int glyphIndex) {
104         int idx = getGVIdx(glyphIndex);
105         return gvs[idx].getGlyphJustificationInfo(glyphIndex-off[idx]);
106     }
107
108     /**
109      * Returns the logical bounds of the specified glyph within this
110      * GlyphVector.
111      */

112     public Shape JavaDoc getGlyphLogicalBounds(int glyphIndex) {
113         int idx = getGVIdx(glyphIndex);
114         return gvs[idx].getGlyphLogicalBounds(glyphIndex-off[idx]);
115     }
116
117     /**
118      * Returns the metrics of the glyph at the specified index into this
119      * GlyphVector.
120      */

121     public GVTGlyphMetrics getGlyphMetrics(int glyphIndex) {
122         int idx = getGVIdx(glyphIndex);
123         return gvs[idx].getGlyphMetrics(glyphIndex-off[idx]);
124     }
125
126     /**
127      * Returns a Shape whose interior corresponds to the visual representation
128      * of the specified glyph within this GlyphVector.
129      */

130     public Shape JavaDoc getGlyphOutline(int glyphIndex) {
131         int idx = getGVIdx(glyphIndex);
132         return gvs[idx].getGlyphOutline(glyphIndex-off[idx]);
133     }
134
135     /**
136      * Returns the position of the specified glyph within this GlyphVector.
137      */

138     public Point2D JavaDoc getGlyphPosition(int glyphIndex) {
139         int idx = getGVIdx(glyphIndex);
140         return gvs[idx].getGlyphPosition(glyphIndex-off[idx]);
141     }
142
143     /**
144      * Gets the transform of the specified glyph within this GlyphVector.
145      */

146     public AffineTransform JavaDoc getGlyphTransform(int glyphIndex) {
147         int idx = getGVIdx(glyphIndex);
148         return gvs[idx].getGlyphTransform(glyphIndex-off[idx]);
149     }
150
151     /**
152      * Returns the visual bounds of the specified glyph within the GlyphVector.
153      */

154     public Shape JavaDoc getGlyphVisualBounds(int glyphIndex) {
155         int idx = getGVIdx(glyphIndex);
156         return gvs[idx].getGlyphVisualBounds(glyphIndex-off[idx]);
157     }
158
159     /**
160      * Sets the position of the specified glyph within this GlyphVector.
161      */

162     public void setGlyphPosition(int glyphIndex, Point2D JavaDoc newPos) {
163         int idx = getGVIdx(glyphIndex);
164         // System.out.println("setting: " + idx + " - " + (glyphIndex-off[idx]) +
165
// " -> " + newPos);
166
gvs[idx].setGlyphPosition(glyphIndex-off[idx], newPos);
167     }
168
169     /**
170      * Sets the transform of the specified glyph within this GlyphVector.
171      */

172     public void setGlyphTransform(int glyphIndex, AffineTransform JavaDoc newTX) {
173         int idx = getGVIdx(glyphIndex);
174         gvs[idx].setGlyphTransform(glyphIndex-off[idx], newTX);
175     }
176
177     /**
178      * Tells the glyph vector whether or not to draw the specified glyph.
179      */

180     public void setGlyphVisible(int glyphIndex, boolean visible) {
181         int idx = getGVIdx(glyphIndex);
182         gvs[idx].setGlyphVisible(glyphIndex-off[idx], visible);
183     }
184
185     /**
186      * Returns true if specified glyph will be drawn.
187      */

188     public boolean isGlyphVisible(int glyphIndex) {
189         int idx = getGVIdx(glyphIndex);
190         return gvs[idx].isGlyphVisible(glyphIndex-off[idx]);
191     }
192
193     /**
194      * Returns an array of glyphcodes for the specified glyphs.
195      */

196     public int[] getGlyphCodes(int beginGlyphIndex, int numEntries,
197                         int[] codeReturn) {
198         int [] ret = codeReturn;
199         if (ret == null)
200             ret = new int[numEntries];
201         int [] tmp = null;
202
203         int gvIdx = getGVIdx(beginGlyphIndex);
204         int gi = beginGlyphIndex-off[gvIdx];
205         int i=0;
206         GVTGlyphVector gv;
207         while (numEntries != 0) {
208             int len = numEntries;
209             if (gi+len > nGlyphs[gvIdx])
210                 len = nGlyphs[gvIdx]-gi;
211             gv = gvs[gvIdx];
212             if (i == 0) {
213                 gv.getGlyphCodes(gi, len, ret);
214             } else {
215                 if ((tmp == null) || (tmp.length < len))
216                     tmp = new int[len];
217
218                 gv.getGlyphCodes(gi, len, tmp);
219                 for (int j=0; j<len; j++)
220                     ret[i+j] = tmp[j];
221             }
222             gi=0;
223             gvIdx++;
224             numEntries -= len;
225             i+=len;
226         }
227         return ret;
228     }
229
230
231     /**
232      * Returns an array of glyph positions for the specified glyphs
233      */

234     public float[] getGlyphPositions(int beginGlyphIndex,
235                               int numEntries,
236                               float[] positionReturn) {
237         float [] ret = positionReturn;
238         if (ret == null)
239             ret = new float[numEntries*2];
240         float [] tmp = null;
241
242         int gvIdx = getGVIdx(beginGlyphIndex);
243         int gi = beginGlyphIndex-off[gvIdx];
244         int i=0;
245         GVTGlyphVector gv;
246         while (numEntries != 0) {
247             int len = numEntries;
248             if (gi+len > nGlyphs[gvIdx])
249                 len = nGlyphs[gvIdx]-gi;
250
251             gv = gvs[gvIdx];
252             if (i == 0) {
253                 gv.getGlyphPositions(gi, len, ret);
254             } else {
255                 if ((tmp == null) || (tmp.length < len*2))
256                     tmp = new float[len*2];
257
258                 gv.getGlyphPositions(gi, len, tmp);
259                 for (int j=0; j<len*2; j++)
260                     ret[i+j] = tmp[j];
261             }
262             gi=0;
263             gvIdx++;
264             numEntries -= len;
265             i+=len*2;
266         }
267         return ret;
268     }
269
270
271     /**
272      * Returns the logical bounds of this GlyphVector.
273      */

274     public Rectangle2D JavaDoc getLogicalBounds() {
275         Rectangle2D JavaDoc ret = null;
276         for (int idx=0; idx<gvs.length; idx++) {
277             Rectangle2D JavaDoc b = gvs[idx].getLogicalBounds();
278             if (ret == null) ret = b;
279             else ret = ret.createUnion(b);
280         }
281         return ret;
282     }
283
284     /**
285      * Returns a Shape whose interior corresponds to the visual representation
286      * of this GlyphVector.
287      */

288     public Shape JavaDoc getOutline() {
289         GeneralPath JavaDoc ret = null;
290         for (int idx=0; idx<gvs.length; idx++) {
291             Shape JavaDoc s = gvs[idx].getOutline();
292             if (ret == null) ret = new GeneralPath JavaDoc(s);
293             else ret.append(s, false);
294         }
295         return ret;
296     }
297
298     /**
299      * Returns a Shape whose interior corresponds to the visual representation
300      * of this GlyphVector, offset to x, y.
301      */

302     public Shape JavaDoc getOutline(float x, float y) {
303         Shape JavaDoc outline = getOutline();
304         AffineTransform JavaDoc tr = AffineTransform.getTranslateInstance(x,y);
305         outline = tr.createTransformedShape(outline);
306         return outline;
307     }
308
309     /**
310      * Returns the bounds of this GlyphVector. This includes
311      * stroking effects.
312      */

313     public Rectangle2D JavaDoc getBounds2D(AttributedCharacterIterator JavaDoc aci) {
314         Rectangle2D JavaDoc ret = null;
315         int begin = aci.getBeginIndex();
316         for (int idx=0; idx<gvs.length; idx++) {
317             GVTGlyphVector gv = gvs[idx];
318             int end = gv.getCharacterCount(0, gv.getNumGlyphs())+1;
319             Rectangle2D JavaDoc b = gvs[idx].getBounds2D
320                 (new AttributedCharacterSpanIterator(aci, begin, end));
321             if (ret == null) ret = b;
322             else ret = ret.createUnion(b);
323             begin = end;
324         }
325         return ret;
326     }
327
328     /**
329      * Returns the geometric bounds of this GlyphVector. The geometric
330      * bounds is the bounds of the geometry of the glyph vector,
331      * disregarding stroking.
332      */

333     public Rectangle2D JavaDoc getGeometricBounds() {
334         Rectangle2D JavaDoc ret = null;
335         for (int idx=0; idx<gvs.length; idx++) {
336             Rectangle2D JavaDoc b = gvs[idx].getGeometricBounds();
337             if (ret == null) ret = b;
338             else ret = ret.createUnion(b);
339         }
340         return ret;
341     }
342
343     public void performDefaultLayout() {
344         for (int idx=0; idx<gvs.length; idx++) {
345             gvs[idx].performDefaultLayout();
346         }
347     }
348
349
350     /**
351      * Returns the number of chars represented by the glyphs within the
352      * specified range.
353      *
354      * @param startGlyphIndex The index of the first glyph in the range.
355      * @param endGlyphIndex The index of the last glyph in the range.
356      * @return The number of chars.
357      */

358     public int getCharacterCount(int startGlyphIndex, int endGlyphIndex) {
359         int idx1 = getGVIdx(startGlyphIndex);
360         int idx2 = getGVIdx(endGlyphIndex);
361         int ret=0;
362         for (int idx=idx1; idx<=idx2; idx++) {
363             int gi1 = startGlyphIndex-off[idx];
364             int gi2 = endGlyphIndex-off[idx];
365             if (gi2 >= nGlyphs[idx]) {
366                 gi2 = nGlyphs[idx]-1;
367             }
368             ret += gvs[idx].getCharacterCount(gi1, gi2);
369             startGlyphIndex += (gi2-gi1+1);
370         }
371         return ret;
372     }
373
374     /**
375      * Draws the glyph vector.
376      */

377     public void draw(Graphics2D JavaDoc g2d,
378               AttributedCharacterIterator JavaDoc aci) {
379         int begin = aci.getBeginIndex();
380         for (int idx=0; idx<gvs.length; idx++) {
381             GVTGlyphVector gv = gvs[idx];
382             int end = gv.getCharacterCount(0, gv.getNumGlyphs())+1;
383             gv.draw(g2d, new AttributedCharacterSpanIterator(aci, begin, end));
384             begin = end;
385         }
386     }
387
388     
389 }
390
Popular Tags