1 18 package org.apache.batik.gvt.font; 19 20 import java.awt.Graphics2D ; 21 import java.awt.Shape ; 22 import java.awt.font.FontRenderContext ; 23 import java.awt.font.GlyphJustificationInfo ; 24 import java.awt.geom.AffineTransform ; 25 import java.awt.geom.GeneralPath ; 26 import java.awt.geom.Point2D ; 27 import java.awt.geom.Rectangle2D ; 28 import java.text.AttributedCharacterIterator ; 29 import java.util.Iterator ; 30 import java.util.List ; 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 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 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 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 80 public GVTFont getFont() { 81 throw new IllegalArgumentException ("Can't be correctly Implemented"); 82 } 83 84 87 public FontRenderContext getFontRenderContext() { 88 return gvs[0].getFontRenderContext(); 89 } 90 91 94 public int getGlyphCode(int glyphIndex) { 95 int idx = getGVIdx(glyphIndex); 96 return gvs[idx].getGlyphCode(glyphIndex-off[idx]); 97 } 98 99 103 public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex) { 104 int idx = getGVIdx(glyphIndex); 105 return gvs[idx].getGlyphJustificationInfo(glyphIndex-off[idx]); 106 } 107 108 112 public Shape getGlyphLogicalBounds(int glyphIndex) { 113 int idx = getGVIdx(glyphIndex); 114 return gvs[idx].getGlyphLogicalBounds(glyphIndex-off[idx]); 115 } 116 117 121 public GVTGlyphMetrics getGlyphMetrics(int glyphIndex) { 122 int idx = getGVIdx(glyphIndex); 123 return gvs[idx].getGlyphMetrics(glyphIndex-off[idx]); 124 } 125 126 130 public Shape getGlyphOutline(int glyphIndex) { 131 int idx = getGVIdx(glyphIndex); 132 return gvs[idx].getGlyphOutline(glyphIndex-off[idx]); 133 } 134 135 138 public Point2D getGlyphPosition(int glyphIndex) { 139 int idx = getGVIdx(glyphIndex); 140 return gvs[idx].getGlyphPosition(glyphIndex-off[idx]); 141 } 142 143 146 public AffineTransform getGlyphTransform(int glyphIndex) { 147 int idx = getGVIdx(glyphIndex); 148 return gvs[idx].getGlyphTransform(glyphIndex-off[idx]); 149 } 150 151 154 public Shape getGlyphVisualBounds(int glyphIndex) { 155 int idx = getGVIdx(glyphIndex); 156 return gvs[idx].getGlyphVisualBounds(glyphIndex-off[idx]); 157 } 158 159 162 public void setGlyphPosition(int glyphIndex, Point2D newPos) { 163 int idx = getGVIdx(glyphIndex); 164 gvs[idx].setGlyphPosition(glyphIndex-off[idx], newPos); 167 } 168 169 172 public void setGlyphTransform(int glyphIndex, AffineTransform newTX) { 173 int idx = getGVIdx(glyphIndex); 174 gvs[idx].setGlyphTransform(glyphIndex-off[idx], newTX); 175 } 176 177 180 public void setGlyphVisible(int glyphIndex, boolean visible) { 181 int idx = getGVIdx(glyphIndex); 182 gvs[idx].setGlyphVisible(glyphIndex-off[idx], visible); 183 } 184 185 188 public boolean isGlyphVisible(int glyphIndex) { 189 int idx = getGVIdx(glyphIndex); 190 return gvs[idx].isGlyphVisible(glyphIndex-off[idx]); 191 } 192 193 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 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 274 public Rectangle2D getLogicalBounds() { 275 Rectangle2D ret = null; 276 for (int idx=0; idx<gvs.length; idx++) { 277 Rectangle2D b = gvs[idx].getLogicalBounds(); 278 if (ret == null) ret = b; 279 else ret = ret.createUnion(b); 280 } 281 return ret; 282 } 283 284 288 public Shape getOutline() { 289 GeneralPath ret = null; 290 for (int idx=0; idx<gvs.length; idx++) { 291 Shape s = gvs[idx].getOutline(); 292 if (ret == null) ret = new GeneralPath (s); 293 else ret.append(s, false); 294 } 295 return ret; 296 } 297 298 302 public Shape getOutline(float x, float y) { 303 Shape outline = getOutline(); 304 AffineTransform tr = AffineTransform.getTranslateInstance(x,y); 305 outline = tr.createTransformedShape(outline); 306 return outline; 307 } 308 309 313 public Rectangle2D getBounds2D(AttributedCharacterIterator aci) { 314 Rectangle2D 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 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 333 public Rectangle2D getGeometricBounds() { 334 Rectangle2D ret = null; 335 for (int idx=0; idx<gvs.length; idx++) { 336 Rectangle2D 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 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 377 public void draw(Graphics2D g2d, 378 AttributedCharacterIterator 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 |