1 18 19 package org.apache.batik.ext.awt.font; 20 21 import java.awt.Shape ; 22 import java.awt.font.GlyphMetrics ; 23 import java.awt.font.GlyphVector ; 24 import java.awt.geom.AffineTransform ; 25 import java.awt.geom.GeneralPath ; 26 import java.awt.geom.Point2D ; 27 28 import org.apache.batik.ext.awt.geom.PathLength; 29 30 45 46 public class TextPathLayout { 47 48 51 static public final int ALIGN_START = 0; 52 55 static public final int ALIGN_MIDDLE = 1; 56 59 static public final int ALIGN_END = 2; 60 61 64 static public final int ADJUST_SPACING = 0; 65 68 static public final int ADJUST_GLYPHS = 1; 69 70 89 90 91 static public Shape layoutGlyphVector(GlyphVector glyphs, 92 Shape path, int align, 93 float startOffset, 94 float textLength, 95 int lengthAdjustMode) { 96 97 GeneralPath newPath = new GeneralPath (); 98 PathLength pl = new PathLength(path); 99 float pathLength = pl.lengthOfPath(); 100 float glyphsLength = (float) glyphs.getVisualBounds().getWidth(); 101 102 if (path == null || 104 glyphs == null || 105 glyphs.getNumGlyphs() == 0 || 106 pl.lengthOfPath() == 0f || 107 glyphsLength == 0f) { 108 return newPath; 109 } 110 111 float lengthRatio = textLength / glyphsLength; 113 114 float currentPosition = startOffset; 116 117 125 if (align == ALIGN_END) { 126 currentPosition += pathLength - textLength; 127 } else if (align == ALIGN_MIDDLE) { 128 currentPosition += (pathLength - textLength) / 2; 129 } 130 131 133 for (int i = 0; i < glyphs.getNumGlyphs(); i++) { 134 135 GlyphMetrics gm = glyphs.getGlyphMetrics(i); 136 137 float charAdvance = gm.getAdvance(); 138 139 Shape glyph = glyphs.getGlyphOutline(i); 140 141 if (lengthAdjustMode == ADJUST_GLYPHS) { 145 AffineTransform scale = AffineTransform.getScaleInstance(lengthRatio, 1f); 146 glyph = scale.createTransformedShape(glyph); 147 148 charAdvance *= lengthRatio; 150 } 151 152 float glyphWidth = (float) glyph.getBounds2D().getWidth(); 153 154 162 float charMidPos = currentPosition + glyphWidth / 2f; 164 165 Point2D charMidPoint = pl.pointAtLength(charMidPos); 167 168 170 if (charMidPoint != null) { 171 172 float angle = pl.angleAtLength(charMidPos); 174 175 AffineTransform glyphTrans = new AffineTransform (); 177 178 glyphTrans.translate(charMidPoint.getX(), charMidPoint.getY()); 180 181 glyphTrans.rotate(angle); 183 184 glyphTrans.translate(charAdvance / -2f, 0f); 189 191 glyph = glyphTrans.createTransformedShape(glyph); 192 newPath.append(glyph, false); 193 194 } 195 196 if (lengthAdjustMode == ADJUST_SPACING) { 200 currentPosition += (charAdvance * lengthRatio); 201 } else { 202 currentPosition += charAdvance; 203 } 204 205 } 206 207 return newPath; 208 } 209 210 220 221 static public Shape layoutGlyphVector(GlyphVector glyphs, 222 Shape path, int align) { 223 224 return layoutGlyphVector(glyphs, path, align, 0f, 225 (float) glyphs.getVisualBounds().getWidth(), 226 ADJUST_SPACING); 227 } 228 229 237 238 static public Shape layoutGlyphVector(GlyphVector glyphs, 239 Shape path) { 240 241 return layoutGlyphVector(glyphs, path, ALIGN_START); 242 } 243 244 245 } | Popular Tags |