【问题标题】:How to Obtain the Chinese character stroke order from the ttf file? [closed]如何从ttf文件中获取汉字笔顺? [关闭]
【发布时间】:2015-05-26 21:43:47
【问题描述】:

我发现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();
        }

有一个问题,我无法获得完整的单词.. 它看起来像虚线......

【问题讨论】:

  • 写中文的笔顺很明确archchinese.com/chinese_stroke_order_rules.html真的需要看.ttf文件才能得到吗?
  • 我已经拿到订单了,但我只是拿到了笔画的分段..看起来像虚线..
  • case PathIterator.SEG_LINETO: 应该有动作g.drawLine((int) coords[0], (int) coords[1], (int) coords[2], (int) coords[3]); & case PathIterator.SEG_QUADTO: 应该是draw(Shape),其中ShapeQuadCurve2D。为了尽快获得更好的帮助,请发布MCVE(最小完整可验证示例)或SSCCE(基本相同)。
  • 顺便说一句 - 你的意思是像 Kanji stroke order font v3.001 页面中所示的“笔顺”吗?我怀疑这是确实存储笔画顺序的少数TTF字体之一。即便如此,除了让GeneralPath 依次绘制每个笔画(与笔画顺序相同)之外,我不相信 TTF 甚至没有 容量 将“笔画顺序”存储在感觉你的意思。

标签: java swing fonts


【解决方案1】:

您的意思是“部分”地绘制字符的笔画 - 类似于这段代码吗?

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<Shape> 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<Shape>();
        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++;
    }
}

【讨论】:

  • 笔画顺序看起来不对。最后绘制部首。有时会在完全不同的时间渲染相同形状的内边界和外边界。这看起来更像是您只是将最终生成的多段线分成更小的部分。它与实际笔画顺序没有太多共同之处。无论如何都不错的动画+1。
  • “笔顺看起来不对。”(笑)如果笔顺是对的,那纯属偶然(以及实现和字体依赖)。我忍不住贴出代码和动画来尝试指出这一点——但也许我应该用简单的文字把它包括进去。 ;)
  • 你知道 Swift 是否存在类似的东西吗?
  • @Crashalot 我不知道。为什么不问问 Swift 专家呢?
猜你喜欢
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2014-06-04
  • 1970-01-01
  • 1970-01-01
  • 2012-08-07
相关资源
最近更新 更多