简体   繁体   English

Java中如何获取字符的精确边界框

[英]How to get the precise bounding box of a character in Java

I am trying to get the precise bounding box of a character in Java.我正在尝试获取 Java 中字符的精确边界框。 Is it normal that if I perform (for example in a Swing component):如果我执行(例如在 Swing 组件中)是否正常:

public class MyFrame extends JFrame {
   public MyFrame() {
     super();
     this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
   }

   private void computeWidth() {
     String character = "A";
     JLabel label = new JLabel();
     Font font = label.getFont();
     font = font.deriveFont(12);

     // method with FontMetrics 
     FontMetrics fontMetrics = this.getFontMetrics(font);
     Rectangle2D recWithMetrics = fontMetrics.getStringBounds(character, this.getGraphics());
     System.out.println("recWithMetrics : " + recWithMetrics);

     // method with GlyphVector outline
     FontRenderContext ctx = new FontRenderContext(new AffineTransform(), true, true);
     GlyphVector gv = font.createGlyphVector(ctx, character);
     Rectangle2D recWithOutline = gv.getOutline().getBounds2D();
     System.out.println("recWithOutline : " + recWithOutline);
   }

   public static void main(String[] args) {
      MyFrame frame = new MyFrame();
      frame.computeWidth();
      frame.setVisible(true);
   }
}

recWithMetrics and recWithOutline don't have the same values at all, is it due to the fact that the method using the FontMetrics includes the advance? recWithMetricsrecWithOutline根本没有相同的值,是因为使用FontMetrics的方法包含了提前吗?

I've found it 'simpler' to get the Shape of the text and work with that.我发现获取文本的Shape并使用它“更简单”。

在此处输入图像描述

import java.awt.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class TextBoundingBox {

    private JComponent ui = null;
    public static String string = "Red outline shows bounds of text";
    public static Font font = new Font(Font.SANS_SERIF, Font.BOLD, 36);

    TextBoundingBox() {
        initUI();
    }

    public void initUI() {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        ui.add(new JLabel(new ImageIcon(getImage())));
    }

    private static BufferedImage getImage() {
        Shape shape = getShapeOfText(font, string);
        Rectangle2D boundsRectangle = shape.getBounds2D();
        double w = boundsRectangle.getWidth();
        double h = boundsRectangle.getHeight();
        int wBig = (int) (w * 1.1);
        int hBig = (int) (h * 2);
        BufferedImage bi = new BufferedImage(
                wBig, hBig, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bi.createGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, wBig, hBig);

        g.setColor(Color.BLACK);
        g.fill(moveShapeToCenter(shape, wBig, hBig));
        g.setColor(Color.RED);
        g.draw(moveShapeToCenter(boundsRectangle, wBig, hBig));
        g.dispose();

        return bi;
    }

    public static Shape moveShapeToCenter(Shape shape, int w, int h) {
        Rectangle2D b = shape.getBounds2D();
        double xOff = -b.getX() + ((w - b.getWidth()) / 2d);
        double yOff = -b.getY() + ((h - b.getHeight()) / 2d);
        AffineTransform move = AffineTransform.getTranslateInstance(xOff, yOff);
        return move.createTransformedShape(shape);
    }

    public static Shape getShapeOfText(Font font, String msg) {
        BufferedImage bi = new BufferedImage(
                1, 1, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = bi.createGraphics();

        FontRenderContext frc = g.getFontRenderContext();
        GlyphVector gv = font.createGlyphVector(frc, msg);

        return gv.getOutline();
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            TextBoundingBox o = new TextBoundingBox();

            JFrame f = new JFrame(o.getClass().getSimpleName());
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setLocationByPlatform(true);

            f.setContentPane(o.getUI());
            f.pack();
            f.setMinimumSize(f.getSize());

            f.setVisible(true);
        };
        SwingUtilities.invokeLater(r);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM