如何从ttf文件中获取汉字笔画顺序?

我发现getGlyphOutline()可以显示JAVA API的字体输出行。 我还没有发现任何用于显示中国笔画顺序的API。 但这是真的: .ttf包含笔画顺序。 我只是不知道如何通过JAVA获得它。

可能是一些我忘记的重要API?

 shape = gv.getGlyphOutline(i, 200, 200); ((Graphics2D) g).draw(shape); 

现在,我找到了PathIterator

 Shape shape = gv.getGlyphOutline(0, 200, 200); PathIterator pi = shape.getPathIterator(new AffineTransform()); double[] coords = new double[6]; int count = 0; while (!pi.isDone()) { int kind = pi.currentSegment(coords); int[] path = new int[4]; switch (kind) { case PathIterator.SEG_MOVETO: System.out.println("SEG_MOVETO"); break; case PathIterator.SEG_LINETO: System.out.println("SEG_LINETO"); break; case PathIterator.SEG_CLOSE: System.out.println("SEG_CLOSE"); g.drawLine((int) coords[0], (int) coords[1], (int) coords[2], (int) coords[3]); count++; break; case PathIterator.SEG_QUADTO: System.out.println("SEG_QUADTO"); g.drawLine((int) coords[0], (int) coords[1], (int) coords[2], (int) coords[3]); count++; break; default: throw new IllegalArgumentException("Bad path segment"); } pi.next(); } 

有一个问题,我无法得到完整的字..它看起来像虚线……

你是说要逐个画出角色的笔画 – 就像这段代码一样吗?

在此处输入图像描述

 import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.font.*; import java.awt.geom.*; import java.awt.image.BufferedImage; import java.util.ArrayList; import javax.swing.*; import javax.swing.border.EmptyBorder; public class LettersByStrokeAnimation { private JComponent ui = null; String text = ""; Font font; LettersByStrokeAnimation() { initUI(); } public void initUI() { if (ui != null) { return; } ui = new JPanel(new GridLayout(0, 1)); ui.setBorder(new EmptyBorder(4, 4, 4, 4)); for (int i = 13444; i < 13450; i++) { text += new String(Character.toChars(i)); } GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); Font[] fonts = ge.getAllFonts(); boolean canDisplay = false; int i = 0; while (!canDisplay) { font = fonts[i]; if (font.canDisplayUpTo(text) < 0) { canDisplay = true; font = font.deriveFont(50f); } i++; } JLabel l = new JLabel(text); l.setFont(font); ui.add(l); ui.add(new AnimatedText(text, font, 200)); } public JComponent getUI() { return ui; } public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception useDefault) { } LettersByStrokeAnimation o = new LettersByStrokeAnimation(); JFrame f = new JFrame(o.getClass().getSimpleName()); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLocationByPlatform(true); f.setContentPane(o.getUI()); f.pack(); f.setMinimumSize(f.getSize()); f.setVisible(true); } }; SwingUtilities.invokeLater(r); } } class AnimatedText extends JPanel { Font font; int counter; ArrayList shapes; AnimatedText(String text, Font font, int delay) { this.font = font; BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); Graphics2D g = bi.createGraphics(); g.dispose(); FontRenderContext frc = g.getFontRenderContext(); GlyphVector gv = font.createGlyphVector(frc, text); Shape shape = gv.getOutline(0, 50); GeneralPath gp = new GeneralPath(shape); PathIterator pi = gp.getPathIterator(null); shapes = new ArrayList(); while (!pi.isDone()) { shapes.add(getNextStroke(pi)); } ActionListener timerListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { AnimatedText.this.repaint(); } }; Timer timer = new Timer(delay, timerListener); timer.start(); } private final Shape getNextStroke(PathIterator pi) { double[] coords = new double[6]; GeneralPath gp = new GeneralPath(); boolean closed = false; while (!closed && !pi.isDone()) { int pathSegmentType = pi.currentSegment(coords); closed = pathSegmentType == PathIterator.SEG_CLOSE; int windingRule = pi.getWindingRule(); gp.setWindingRule(windingRule); if (pathSegmentType == PathIterator.SEG_MOVETO) { gp.moveTo(coords[0], coords[1]); } else if (pathSegmentType == PathIterator.SEG_LINETO) { gp.lineTo(coords[0], coords[1]); } else if (pathSegmentType == PathIterator.SEG_QUADTO) { gp.quadTo(coords[0], coords[1], coords[2], coords[3]); } else if (pathSegmentType == PathIterator.SEG_CUBICTO) { gp.curveTo( coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); } else if (pathSegmentType == PathIterator.SEG_CLOSE) { gp.closePath(); } else { System.err.println("Unexpected value! " + pathSegmentType); } pi.next(); } Shape shape = new Area(gp); return shape; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; int current = counter % shapes.size(); for (int i = 0; i < current; i++) { g2.draw(shapes.get(i)); } counter++; } }