如何使用Java Graphics2D绘制半圆文本?

时间:2019-01-09 05:28:44

标签: java svg graphics2d batik

我想使用Java的Graphics2D在圆形的上半部绘制文本。可以在Swing中使用它,但实际上我希望它使用Apache的Batik在SVG中绘制圆形徽标。

1 个答案:

答案 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);