我想使用Java的Graphics2D在圆形的上半部绘制文本。可以在Swing中使用它,但实际上我希望它使用Apache的Batik在SVG中绘制圆形徽标。
答案 0 :(得分:0)
诀窍是使用GlyphVector。每个字母必须单独移动和旋转。
public class HalfCircleDemo {
@SuppressWarnings("serial")
private static class DemoPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) g ;
graphics.setPaint(Color.yellow);
graphics.fill(new Rectangle(0, 0, 100, 100));
graphics.fill(new Rectangle(100, 100, 200, 200));
graphics.setPaint(Color.BLACK);
{ /* THIS IS THE SECTION THAT DOES THE WORK *******************************************/
Font font = graphics.getFont();
FontRenderContext frc = graphics.getFontRenderContext();
GlyphVector glyphVector = font.createGlyphVector(frc, str);
int glyphCount = str.length();
int radius = 50 ;
for (int i=0 ; i<glyphCount ; i++) {
double theta = Math.PI * i / (double) (glyphCount);
AffineTransform transform = AffineTransform.getRotateInstance(theta-halfPi);
Point2D.Double offset = new Point2D.Double(-radius*Math.cos(theta), -radius*Math.sin(theta));
glyphVector.setGlyphTransform(i, transform);
glyphVector.setGlyphPosition(i, offset);
}
graphics.drawGlyphVector(glyphVector, 100, 100);
} /* ***********************************************************************************/
}
private static final String str = "Hello World, Hello World" ;
private static final double halfPi = Math.PI / 2 ;
public DemoPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
}
public Dimension getPreferredSize() {
return new Dimension(250,200);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame("Half-circle text demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new DemoPanel());
f.pack();
f.setVisible(true);
}
});
}
}
布局存在一些问题。这些在下面的代码部分中已修复。首先,在下面的代码中,由于文本最初已在GlyphVector中正确布局(合理的字母间距),因此我们使用GlyphVector的字母间距。其次,最后一个字母的旋转应为180度,以便它平放,但其位置应小于180度(否则它将在圆心的下方)。因此,我们计算了两个略有不同的θ。第三,我们计算半径,使半圆直径大致等于原始布局文本的长度。
Font font = graphics.getFont();
FontRenderContext frc = graphics.getFontRenderContext();
GlyphVector glyphVector = font.createGlyphVector(frc, str);
int glyphCount = str.length();
double pixelLength = glyphVector.getPixelBounds(frc, 0, 0).width ;
double pixelLengthShort = glyphVector.getGlyphPosition(glyphCount-1).getX();
double radius = pixelLength / Math.PI ;
double halfPi = Math.PI / 2 ;
for (int i=0 ; i<glyphCount ; i++) {
double glyphLinearOffset = glyphVector.getGlyphPosition(i).getX();
double thetaRotation = Math.PI * glyphLinearOffset / (pixelLengthShort);
double thetaPosition = Math.PI * glyphLinearOffset / (pixelLength);
AffineTransform transform = AffineTransform.getRotateInstance(thetaRotation-halfPi);
Point2D.Double offsetVector = new Point2D.Double(-radius*Math.cos(thetaPosition), -radius*Math.sin(thetaPosition));
glyphVector.setGlyphTransform(i, transform);
glyphVector.setGlyphPosition(i, offsetVector);
}
graphics.drawGlyphVector(glyphVector, 100, 100);