1 18 package org.apache.batik.gvt.font; 19 20 import java.awt.Color ; 21 import java.awt.Graphics2D ; 22 import java.awt.Paint ; 23 import java.awt.RenderingHints ; 24 import java.awt.Shape ; 25 import java.awt.Stroke ; 26 import java.awt.font.FontRenderContext ; 27 import java.awt.font.GlyphJustificationInfo ; 28 import java.awt.font.GlyphMetrics ; 29 import java.awt.font.GlyphVector ; 30 import java.awt.font.TextAttribute ; 31 import java.awt.geom.AffineTransform ; 32 import java.awt.geom.GeneralPath ; 33 import java.awt.geom.Point2D ; 34 import java.awt.geom.Rectangle2D ; 35 import java.text.AttributedCharacterIterator ; 36 import java.text.CharacterIterator ; 37 38 import org.apache.batik.gvt.text.ArabicTextHandler; 39 import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; 40 import org.apache.batik.gvt.text.TextPaintInfo; 41 42 48 public class AWTGVTGlyphVector implements GVTGlyphVector { 49 50 public static final AttributedCharacterIterator.Attribute PAINT_INFO 51 = GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO; 52 53 private GlyphVector awtGlyphVector; 54 private AWTGVTFont gvtFont; 55 private CharacterIterator ci; 56 57 private Point2D [] defaultGlyphPositions; 59 private Point2D.Float [] glyphPositions; 60 61 private AffineTransform [] glyphTransforms; 64 65 private Shape [] glyphOutlines; 67 private Shape [] glyphVisualBounds; 68 private Shape [] glyphLogicalBounds; 69 private boolean[] glyphVisible; 70 private GVTGlyphMetrics [] glyphMetrics; 71 private GeneralPath outline; 72 private Rectangle2D visualBounds; 73 private Rectangle2D logicalBounds; 74 private Rectangle2D bounds2D; 75 private float scaleFactor; 76 private float ascent; 77 private float descent; 78 private TextPaintInfo cacheTPI; 79 80 93 public AWTGVTGlyphVector(GlyphVector glyphVector, 94 AWTGVTFont font, 95 float scaleFactor, 96 CharacterIterator ci) { 97 98 this.awtGlyphVector = glyphVector; 99 this.gvtFont = font; 100 this.scaleFactor = scaleFactor; 101 this.ci = ci; 102 103 GVTLineMetrics lineMetrics = gvtFont.getLineMetrics 104 ("By", awtGlyphVector.getFontRenderContext()); 105 106 ascent = lineMetrics.getAscent(); 107 descent = lineMetrics.getDescent(); 108 109 outline = null; 110 visualBounds = null; 111 logicalBounds = null; 112 bounds2D = null; 113 int numGlyphs = glyphVector.getNumGlyphs(); 114 glyphPositions = new Point2D.Float [numGlyphs+1]; 115 glyphTransforms = new AffineTransform [numGlyphs]; 116 glyphOutlines = new Shape [numGlyphs]; 117 glyphVisualBounds = new Shape [numGlyphs]; 118 glyphLogicalBounds = new Shape [numGlyphs]; 119 glyphVisible = new boolean [numGlyphs]; 120 glyphMetrics = new GVTGlyphMetrics[numGlyphs]; 121 122 for (int i = 0; i < numGlyphs; i++) { 123 glyphVisible[i] = true; 124 } 125 } 126 127 130 public GVTFont getFont() { 131 return gvtFont; 132 } 133 134 137 public FontRenderContext getFontRenderContext() { 138 return awtGlyphVector.getFontRenderContext(); 139 } 140 141 144 public int getGlyphCode(int glyphIndex) { 145 return awtGlyphVector.getGlyphCode(glyphIndex); 146 } 147 148 151 public int[] getGlyphCodes(int beginGlyphIndex, int numEntries, 152 int[] codeReturn) { 153 return awtGlyphVector.getGlyphCodes(beginGlyphIndex, numEntries, 154 codeReturn); 155 } 156 157 161 public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex) { 162 return awtGlyphVector.getGlyphJustificationInfo(glyphIndex); 163 } 164 165 168 public Rectangle2D getBounds2D(AttributedCharacterIterator aci) { 169 aci.first(); 170 TextPaintInfo tpi = (TextPaintInfo)aci.getAttribute(PAINT_INFO); 171 if ((bounds2D != null) && 172 TextPaintInfo.equivilent(tpi, cacheTPI)) 173 return bounds2D; 174 175 if (tpi == null) 176 return null; 177 if (!tpi.visible) 178 return null; 179 180 cacheTPI = new TextPaintInfo(tpi); 181 Shape outline = null; 182 if (tpi.fillPaint != null) { 183 outline = getOutline(); 184 bounds2D = outline.getBounds2D(); 185 } 186 187 Stroke stroke = tpi.strokeStroke; 190 Paint paint = tpi.strokePaint; 191 if ((stroke != null) && (paint != null)) { 192 if (outline == null) 193 outline = getOutline(); 194 Rectangle2D strokeBounds 195 = stroke.createStrokedShape(outline).getBounds2D(); 196 if (bounds2D == null) 197 bounds2D = strokeBounds; 198 else 199 bounds2D = bounds2D.createUnion(strokeBounds); 200 } 201 if (bounds2D == null) 202 return null; 203 204 if ((bounds2D.getWidth() == 0) || 205 (bounds2D.getHeight() == 0)) 206 bounds2D = null; 207 208 return bounds2D; 209 } 210 211 215 public Rectangle2D getLogicalBounds() { 216 if (logicalBounds == null) { 217 computeGlyphLogicalBounds(); 219 } 220 return logicalBounds; 221 } 222 223 227 public Shape getGlyphLogicalBounds(int glyphIndex) { 228 if (glyphLogicalBounds[glyphIndex] == null && 229 glyphVisible[glyphIndex]) { 230 231 computeGlyphLogicalBounds(); 232 } 233 return glyphLogicalBounds[glyphIndex]; 234 } 235 236 241 private void computeGlyphLogicalBounds() { 242 243 Shape [] tempLogicalBounds = new Shape [getNumGlyphs()]; 244 boolean[] rotated = new boolean[getNumGlyphs()]; 245 246 double maxWidth = -1; 247 double maxHeight = -1; 248 for (int i = 0; i < getNumGlyphs(); i++) { 249 250 if (!glyphVisible[i]) { 251 tempLogicalBounds[i] = null; 253 continue; 254 } 255 256 AffineTransform glyphTransform = getGlyphTransform(i); 257 GVTGlyphMetrics glyphMetrics = getGlyphMetrics(i); 258 259 float glyphX = 0; 260 float glyphY = -ascent/scaleFactor; 261 float glyphWidth = (glyphMetrics.getHorizontalAdvance()/ 262 scaleFactor); 263 float glyphHeight = (glyphMetrics.getVerticalAdvance()/ 264 scaleFactor); 265 Rectangle2D glyphBounds = new Rectangle2D.Double (glyphX, 266 glyphY, 267 glyphWidth, 268 glyphHeight); 269 270 if (glyphBounds.isEmpty()) { 271 if (i > 0) { 272 rotated [i] = rotated [i-1]; 275 } else { 276 rotated [i] = true; 277 } 278 } else { 279 Point2D p1 = new Point2D.Double (glyphBounds.getMinX(), 282 glyphBounds.getMinY()); 283 Point2D p2 = new Point2D.Double (glyphBounds.getMaxX(), 284 glyphBounds.getMinY()); 285 Point2D p3 = new Point2D.Double (glyphBounds.getMinX(), 286 glyphBounds.getMaxY()); 287 288 Point2D gpos = getGlyphPosition(i); 289 AffineTransform tr = AffineTransform.getTranslateInstance 290 (gpos.getX(), gpos.getY()); 291 292 if (glyphTransform != null) 293 tr.concatenate(glyphTransform); 294 tr.scale(scaleFactor, scaleFactor); 295 296 tempLogicalBounds[i] = tr.createTransformedShape(glyphBounds); 297 298 Point2D tp1 = new Point2D.Double (); 299 Point2D tp2 = new Point2D.Double (); 300 Point2D tp3 = new Point2D.Double (); 301 tr.transform(p1, tp1); 302 tr.transform(p2, tp2); 303 tr.transform(p3, tp3); 304 double tdx12 = tp1.getX()-tp2.getX(); 305 double tdx13 = tp1.getX()-tp3.getX(); 306 double tdy12 = tp1.getY()-tp2.getY(); 307 double tdy13 = tp1.getY()-tp3.getY(); 308 309 if (((Math.abs(tdx12) < 0.001) && (Math.abs(tdy13) < 0.001)) || 310 ((Math.abs(tdx13) < 0.001) && (Math.abs(tdy12) < 0.001))) { 311 rotated[i] = false; 313 } else { 314 rotated [i] = true; 315 } 316 317 Rectangle2D rectBounds; 318 rectBounds = tempLogicalBounds[i].getBounds2D(); 319 if (rectBounds.getWidth() > maxWidth) 320 maxWidth = rectBounds.getWidth(); 321 if (rectBounds.getHeight() > maxHeight) 322 maxHeight = rectBounds.getHeight(); 323 } 324 } 325 326 GeneralPath logicalBoundsPath = new GeneralPath (); 328 for (int i = 0; i < getNumGlyphs(); i++) { 329 if (tempLogicalBounds[i] != null) { 330 logicalBoundsPath.append(tempLogicalBounds[i], false); 331 } 332 } 333 334 logicalBounds = logicalBoundsPath.getBounds2D(); 335 336 if (logicalBounds.getHeight() < maxHeight*1.5) { 337 for (int i = 0; i < getNumGlyphs(); i++) { 339 if (rotated[i]) continue; 342 if (tempLogicalBounds[i] == null) continue; 343 344 Rectangle2D glyphBounds = tempLogicalBounds[i].getBounds2D(); 345 346 double x = glyphBounds.getMinX(); 347 double width = glyphBounds.getWidth(); 348 349 if ((i < getNumGlyphs()-1) && 350 (tempLogicalBounds[i+1] != null)) { 351 Rectangle2D ngb = tempLogicalBounds[i+1].getBounds2D(); 353 354 if (ngb.getX() > x) { 355 double nw = ngb.getX() - x; 356 if ((nw < width*1.15) && (nw > width*.85)) { 357 double delta = (nw-width)*.5; 358 width += delta; 359 ngb.setRect(ngb.getX()-delta, ngb.getY(), 360 ngb.getWidth()+delta, ngb.getHeight()); 361 } 362 } 363 } 364 tempLogicalBounds[i] = new Rectangle2D.Double 365 (x, logicalBounds.getMinY(), 366 width, logicalBounds.getHeight()); 367 } 368 } else if (logicalBounds.getWidth() < maxWidth*1.5) { 369 for (int i = 0; i < getNumGlyphs(); i++) { 371 if (rotated[i]) continue; 374 if (tempLogicalBounds[i] == null) continue; 375 376 Rectangle2D glyphBounds = tempLogicalBounds[i].getBounds2D(); 377 double y = glyphBounds.getMinY(); 378 double height = glyphBounds.getHeight(); 379 380 if ((i < getNumGlyphs()-1) && 381 (tempLogicalBounds[i+1] != null)) { 382 Rectangle2D ngb = tempLogicalBounds[i+1].getBounds2D(); 384 if (ngb.getY() > y) { double nh = ngb.getY() - y; 386 if ((nh < height*1.15) && (nh > height*.85)) { 387 double delta = (nh-height)*.5; 388 height += delta; 389 ngb.setRect(ngb.getX(), ngb.getY()-delta, 390 ngb.getWidth(), ngb.getHeight()+delta); 391 } 392 } 393 } 394 tempLogicalBounds[i] = new Rectangle2D.Double 395 (logicalBounds.getMinX(), y, 396 logicalBounds.getWidth(), height); 397 } 398 } 399 400 for (int i = 0; i < getNumGlyphs(); i++) { 401 glyphLogicalBounds[i] = tempLogicalBounds[i]; 402 } 403 } 404 405 409 public GVTGlyphMetrics getGlyphMetrics(int glyphIndex) { 410 if (glyphMetrics[glyphIndex] != null) 411 return glyphMetrics[glyphIndex]; 412 413 Point2D glyphPos = defaultGlyphPositions[glyphIndex]; 415 char c = ci.setIndex(ci.getBeginIndex()+glyphIndex); 416 ci.setIndex(ci.getBeginIndex()); 417 AWTGlyphGeometryCache.Value v = AWTGVTFont.getGlyphGeometry 418 (gvtFont, c, awtGlyphVector, glyphIndex, glyphPos); 419 Rectangle2D gmB = v.getBounds2D(); 420 422 Rectangle2D bounds = new Rectangle2D.Double 423 (gmB.getX() * scaleFactor, gmB.getY() * scaleFactor, 424 gmB.getWidth() * scaleFactor, gmB.getHeight() * scaleFactor); 425 426 float adv = (float)(defaultGlyphPositions[glyphIndex+1].getX()- 430 defaultGlyphPositions[glyphIndex] .getX()); 431 glyphMetrics[glyphIndex] = new GVTGlyphMetrics 432 (adv*scaleFactor, (ascent+descent), 433 bounds, GlyphMetrics.STANDARD); 434 435 return glyphMetrics[glyphIndex]; 436 } 437 438 442 public Shape getGlyphOutline(int glyphIndex) { 443 if (glyphOutlines[glyphIndex] == null) { 444 447 Point2D glyphPos = defaultGlyphPositions[glyphIndex]; 449 char c = ci.setIndex(ci.getBeginIndex()+glyphIndex); 450 ci.setIndex(ci.getBeginIndex()); 451 AWTGlyphGeometryCache.Value v = AWTGVTFont.getGlyphGeometry 452 (gvtFont, c, awtGlyphVector, glyphIndex, glyphPos); 453 Shape glyphOutline = v.getOutline(); 454 456 AffineTransform tr = AffineTransform.getTranslateInstance 457 (getGlyphPosition(glyphIndex).getX(), 458 getGlyphPosition(glyphIndex).getY()); 459 460 AffineTransform glyphTransform = getGlyphTransform(glyphIndex); 461 462 if (glyphTransform != null) { 463 tr.concatenate(glyphTransform); 464 } 465 486 tr.scale(scaleFactor, scaleFactor); 487 glyphOutlines[glyphIndex]=tr.createTransformedShape(glyphOutline); 488 } 489 490 return glyphOutlines[glyphIndex]; 491 } 492 493 private static final boolean outlinesPositioned; 496 private static final boolean drawGlyphVectorWorks; 499 private static final boolean glyphVectorTransformWorks; 502 503 static { 504 String s = System.getProperty("java.specification.version"); 505 if ("1.4".compareTo(s) <= 0) { 506 outlinesPositioned = true; 507 drawGlyphVectorWorks = true; 508 glyphVectorTransformWorks = true; 509 } else if ("Mac OS X".equals(System.getProperty("os.name"))) { 510 outlinesPositioned = true; 511 drawGlyphVectorWorks = false; 512 glyphVectorTransformWorks = false; 513 } else { 514 outlinesPositioned = false; 515 drawGlyphVectorWorks = true; 516 glyphVectorTransformWorks = false; 517 } 518 } 519 520 static boolean outlinesPositioned() { 523 return outlinesPositioned; 524 } 525 526 529 public Point2D getGlyphPosition(int glyphIndex) { 530 return glyphPositions[glyphIndex]; 531 } 532 533 536 public float[] getGlyphPositions(int beginGlyphIndex, 537 int numEntries, 538 float[] positionReturn) { 539 540 if (positionReturn == null) { 541 positionReturn = new float[numEntries*2]; 542 } 543 544 for (int i = beginGlyphIndex; i < (beginGlyphIndex+numEntries); i++) { 545 Point2D glyphPos = getGlyphPosition(i); 546 positionReturn[(i-beginGlyphIndex)*2] = (float)glyphPos.getX(); 547 positionReturn[(i-beginGlyphIndex)*2 + 1] = (float)glyphPos.getY(); 548 } 549 550 return positionReturn; 551 } 552 553 556 public AffineTransform getGlyphTransform(int glyphIndex) { 557 return glyphTransforms[glyphIndex]; 558 } 559 560 563 public Shape getGlyphVisualBounds(int glyphIndex) { 564 if (glyphVisualBounds[glyphIndex] == null) { 565 569 Point2D glyphPos = defaultGlyphPositions[glyphIndex]; 571 char c = ci.setIndex(ci.getBeginIndex()+glyphIndex); 572 ci.setIndex(ci.getBeginIndex()); 573 AWTGlyphGeometryCache.Value v = AWTGVTFont.getGlyphGeometry 574 (gvtFont, c, awtGlyphVector, glyphIndex, glyphPos); 575 Rectangle2D glyphBounds = v.getOutlineBounds2D(); 576 578 AffineTransform tr = AffineTransform.getTranslateInstance 579 (getGlyphPosition(glyphIndex).getX(), 580 getGlyphPosition(glyphIndex).getY()); 581 582 AffineTransform glyphTransform = getGlyphTransform(glyphIndex); 583 if (glyphTransform != null) { 584 tr.concatenate(glyphTransform); 585 } 586 tr.scale(scaleFactor, scaleFactor); 587 glyphVisualBounds[glyphIndex] = 588 tr.createTransformedShape(glyphBounds); 589 } 590 591 return glyphVisualBounds[glyphIndex]; 592 } 593 594 597 public int getNumGlyphs() { 598 return awtGlyphVector.getNumGlyphs(); 599 } 600 601 605 public Shape getOutline() { 606 if (outline != null) 607 return outline; 608 609 outline = new GeneralPath (); 610 for (int i = 0; i < getNumGlyphs(); i++) { 611 if (glyphVisible[i]) { 612 Shape glyphOutline = getGlyphOutline(i); 613 outline.append(glyphOutline, false); 614 } 615 } 616 return outline; 617 } 618 619 623 public Shape getOutline(float x, float y) { 624 Shape outline = getOutline(); 625 AffineTransform tr = AffineTransform.getTranslateInstance(x,y); 626 outline = tr.createTransformedShape(outline); 627 return outline; 628 } 629 630 635 public Rectangle2D getGeometricBounds() { 636 if (visualBounds == null) { 637 Shape outline = getOutline(); 638 visualBounds = outline.getBounds2D(); 639 } 640 return visualBounds; 641 } 642 643 646 public void performDefaultLayout() { 647 if (defaultGlyphPositions == null) { 648 awtGlyphVector.performDefaultLayout(); 649 defaultGlyphPositions = new Point2D.Float [getNumGlyphs()+1]; 650 for (int i = 0; i <= getNumGlyphs(); i++) 651 defaultGlyphPositions[i] = awtGlyphVector.getGlyphPosition(i); 652 } 653 654 outline = null; 655 visualBounds = null; 656 logicalBounds = null; 657 bounds2D = null; 658 float shiftLeft = 0; 659 int i=0; 660 for (; i < getNumGlyphs(); i++) { 661 glyphTransforms [i] = null; 662 glyphVisualBounds [i] = null; 663 glyphLogicalBounds[i] = null; 664 glyphOutlines [i] = null; 665 glyphMetrics [i] = null; 666 Point2D glyphPos = defaultGlyphPositions[i]; 667 float x = (float)((glyphPos.getX() * scaleFactor)-shiftLeft); 668 float y = (float) (glyphPos.getY() * scaleFactor); 669 670 char c = ci.setIndex(i + ci.getBeginIndex()); 673 705 if (glyphPositions[i] == null) { 706 glyphPositions[i] = new Point2D.Float (x,y); 707 } else { 708 glyphPositions[i].x = x; 709 glyphPositions[i].y = y; 710 } 711 713 } 714 715 Point2D glyphPos = defaultGlyphPositions[i]; 717 glyphPositions[i] = new Point2D.Float 718 ((float)((glyphPos.getX() * scaleFactor)-shiftLeft), 719 (float) (glyphPos.getY() * scaleFactor)); 720 } 721 722 725 public void setGlyphPosition(int glyphIndex, Point2D newPos) { 726 glyphPositions[glyphIndex].x = (float)newPos.getX(); 727 glyphPositions[glyphIndex].y = (float)newPos.getY(); 728 outline = null; 729 visualBounds = null; 730 logicalBounds = null; 731 bounds2D = null; 732 733 if (glyphIndex != getNumGlyphs()) { 734 glyphVisualBounds [glyphIndex] = null; 735 glyphLogicalBounds[glyphIndex] = null; 736 glyphOutlines [glyphIndex] = null; 737 glyphMetrics [glyphIndex] = null; 738 } 739 } 740 741 744 public void setGlyphTransform(int glyphIndex, AffineTransform newTX) { 745 glyphTransforms[glyphIndex] = newTX; 746 outline = null; 747 visualBounds = null; 748 logicalBounds = null; 749 bounds2D = null; 750 751 glyphVisualBounds [glyphIndex] = null; 752 glyphLogicalBounds[glyphIndex] = null; 753 glyphOutlines [glyphIndex] = null; 754 glyphMetrics [glyphIndex] = null; 755 } 756 757 760 public void setGlyphVisible(int glyphIndex, boolean visible) { 761 if (visible == glyphVisible[glyphIndex]) 762 return; 763 glyphVisible[glyphIndex] = visible; 764 outline = null; 765 visualBounds = null; 766 logicalBounds = null; 767 bounds2D = null; 768 769 glyphVisualBounds [glyphIndex] = null; 770 glyphLogicalBounds[glyphIndex] = null; 771 glyphOutlines [glyphIndex] = null; 772 glyphMetrics [glyphIndex] = null; 773 } 774 775 778 public boolean isGlyphVisible(int glyphIndex) { 779 return glyphVisible[glyphIndex]; 780 } 781 782 790 public int getCharacterCount(int startGlyphIndex, int endGlyphIndex) { 791 if (startGlyphIndex < 0) { 792 startGlyphIndex = 0; 793 } 794 if (endGlyphIndex >= getNumGlyphs()) { 795 endGlyphIndex = getNumGlyphs()-1; 796 } 797 int charCount = 0; 798 int start = startGlyphIndex+ci.getBeginIndex(); 799 int end = endGlyphIndex+ci.getBeginIndex(); 800 801 for (char c = ci.setIndex(start); ci.getIndex() <= end; c=ci.next()) { 802 if (ArabicTextHandler.isLigature(c)) { 803 charCount += ArabicTextHandler.getNumChars(c); 804 } else { 805 charCount++; 806 } 807 } 808 809 return charCount; 810 } 811 812 815 public void draw(Graphics2D graphics2D, 816 AttributedCharacterIterator aci) { 817 int numGlyphs = getNumGlyphs(); 818 819 aci.first(); 820 TextPaintInfo tpi = (TextPaintInfo)aci.getAttribute 821 (GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO); 822 if (tpi == null) return; 823 if (!tpi.visible) return; 824 825 Paint fillPaint = tpi.fillPaint; 826 Stroke stroke = tpi.strokeStroke; 827 Paint strokePaint = tpi.strokePaint; 828 829 if ((fillPaint == null) && ((strokePaint == null) || 830 (stroke == null))) 831 return; 832 833 boolean useHinting = drawGlyphVectorWorks; 834 if (useHinting && (stroke != null) && (strokePaint != null)) 835 useHinting = false; 837 838 if (useHinting && 839 (fillPaint != null) && !(fillPaint instanceof Color )) 840 useHinting = false; 843 844 if (useHinting) { 845 Object v1 = graphics2D.getRenderingHint 846 (RenderingHints.KEY_TEXT_ANTIALIASING); 847 Object v2 = graphics2D.getRenderingHint 848 (RenderingHints.KEY_STROKE_CONTROL); 849 if ((v1 == RenderingHints.VALUE_TEXT_ANTIALIAS_ON) && 851 (v2 == RenderingHints.VALUE_STROKE_PURE)) 852 useHinting = false; 853 } 854 855 final int typeGRot = AffineTransform.TYPE_GENERAL_ROTATION; 856 final int typeGTrans = AffineTransform.TYPE_GENERAL_TRANSFORM; 857 858 if (useHinting) { 859 AffineTransform at = graphics2D.getTransform(); 862 int type = at.getType(); 863 if (((type & typeGTrans) != 0) || ((type & typeGRot) != 0)) 864 useHinting = false; 865 } 866 867 if (useHinting) { 868 for (int i=0; i<numGlyphs; i++) { 869 if (!glyphVisible[i]) { 870 useHinting = false; 871 break; 872 } 873 AffineTransform at = glyphTransforms[i]; 874 if (at != null) { 875 int type = at.getType(); 876 if ((type & ~AffineTransform.TYPE_TRANSLATION) == 0) { 877 } else if (glyphVectorTransformWorks && 879 ((type & typeGTrans) == 0) && 880 ((type & typeGRot) == 0)) { 881 } else { 884 useHinting = false; 887 break; 888 } 889 } 890 } 891 } 892 893 if (useHinting) { 894 double sf = scaleFactor; 895 double [] mat = new double[6]; 896 for (int i=0; i< numGlyphs; i++) { 897 Point2D pos = glyphPositions[i]; 898 double x = pos.getX(); 899 double y = pos.getY(); 900 AffineTransform at = glyphTransforms[i]; 901 if (at != null) { 902 at.getMatrix(mat); 905 x += mat[4]; 906 y += mat[5]; 907 if ((mat[0] != 1) || (mat[1] != 0) || 908 (mat[2] != 0) || (mat[3] != 1)) { 909 mat[4] = 0; mat[5] = 0; 911 at = new AffineTransform (mat); 912 } else { 913 at = null; 914 } 915 } 916 pos = new Point2D.Double (x/sf, y/sf); 917 awtGlyphVector.setGlyphPosition(i, pos); 918 awtGlyphVector.setGlyphTransform(i, at); 919 } 920 graphics2D.scale(sf, sf); 921 graphics2D.setPaint(fillPaint); 922 graphics2D.drawGlyphVector(awtGlyphVector, 0, 0); 923 graphics2D.scale(1/sf, 1/sf); 924 925 for (int i=0; i< numGlyphs; i++) { 926 Point2D pos = defaultGlyphPositions[i]; 927 awtGlyphVector.setGlyphPosition(i, pos); 928 awtGlyphVector.setGlyphTransform(i, null); 929 } 930 931 } else { 932 Shape outline = getOutline(); 933 934 if (fillPaint != null) { 936 graphics2D.setPaint(fillPaint); 937 graphics2D.fill(outline); 938 } 939 940 if (stroke != null && strokePaint != null) { 942 graphics2D.setStroke(stroke); 943 graphics2D.setPaint(strokePaint); 944 graphics2D.draw(outline); 945 } 946 } 947 } 948 } 949 | Popular Tags |