Java 如何从ttf文件中获取汉字笔画顺序?
我发现Java 如何从ttf文件中获取汉字笔画顺序?,java,swing,fonts,Java,Swing,Fonts,我发现getGlyphOutline()可以显示JAVA API中的字体输出行。 而且我还没有找到任何显示中国笔画顺序的API。 但这是事实:.ttf包含笔划顺序。 我只是不知道如何通过JAVA获得它 可能有一些重要的API我忘了 shape = gv.getGlyphOutline(i, 200, 200); ((Graphics2D) g).draw(shape); 现在,我找到了PathIterator Shape shape = gv.getGlyphOutl
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<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++;
}
}
import java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.font.*;
导入java.awt.geom.*;
导入java.awt.image.buffereImage;
导入java.util.ArrayList;
导入javax.swing.*;
导入javax.swing.border.EmptyBorder;
公共类信函被删除{
私有JComponent ui=null;
字符串文本=”;
字体;
LettersByStrokeAnimation(){
initUI();
}
public void initUI(){
如果(ui!=null){
返回;
}
ui=新的JPanel(新的GridLayout(0,1));
ui.setboorder(新的空订单(4,4,4,4));
对于(int i=13444;i<13450;i++){
text+=新字符串(Character.toChars(i));
}
GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
Font[]Font=ge.getAllFonts();
布尔canDisplay=false;
int i=0;
而(!canDisplay){
字体=字体[i];
如果(字体显示至(文本)<0){
canDisplay=true;
font=font.deriveFont(50f);
}
i++;
}
JLabel=新的JLabel(文本);
l、 setFont(字体);
ui.添加(l);
添加(新的动画文本(文本,字体,200));
}
公共JComponent getUI(){
返回用户界面;
}
公共静态void main(字符串[]args){
Runnable r=新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}捕获(异常使用默认值){
}
LettersByStrokeAnimation o=新的LettersByStrokeAnimation();
JFrame f=新的JFrame(o.getClass().getSimpleName());
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f、 setLocationByPlatform(真);
f、 setContentPane(o.getUI());
f、 包装();
f、 setMinimumSize(f.getSize());
f、 setVisible(真);
}
};
SwingUtilities.invokeLater(r);
}
}
类AnimatedText扩展了JPanel{
字体;
整数计数器;
阵列列表形状;
动画文本(字符串文本、字体、整数延迟){
this.font=font;
BuffereImage bi=新的BuffereImage(1,1,BuffereImage.TYPE_INT_RGB);
Graphics2D g=bi.createGraphics();
g、 处置();
FontRenderContext frc=g.getFontRenderContext();
GlyphVector gv=font.createGlyphVector(frc,文本);
形状=gv.getOutline(0,50);
GeneralPath gp=新的GeneralPath(形状);
PathIterator pi=gp.getPathIterator(null);
形状=新的ArrayList();
而(!pi.isDone()){
添加(getNextStroke(pi));
}
ActionListener timerListener=新建ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
AnimatedText.this.repaint();
}
};
定时器=新定时器(延迟、定时器);
timer.start();
}
私有最终形状getNextStroke(路径迭代器pi){
双[]坐标=新双[6];
GeneralPath gp=新的GeneralPath();
布尔闭合=假;
而(!closed&!pi.isDone()){
int pathSegmentType=pi.currentSegment(coords);
closed=pathSegmentType==PathIterator.SEG\u CLOSE;
int windingRule=pi.getWindingRule();
总成setWindingRule(windingRule);
if(pathSegmentType==PathIterator.SEG_MOVETO){
gp.moveTo(坐标[0],坐标[1]);
}else if(pathSegmentType==PathIterator.SEG_LINETO){
总谱线图(坐标[0],坐标[1]);
}else if(pathSegmentType==PathIterator.SEG_QUADTO){
gp.quadTo(coords[0],coords[1],coords[2],coords[3]);
}else if(pathSegmentType==PathIterator.SEG_CUBICTO){
curveTo总经理(
坐标[0],坐标[1],坐标[2],
coords[3],coords[4],coords[5]);
}else if(pathSegmentType==PathIterator.SEG\u CLOSE){
gp.closePath();
}否则{
System.err.println(“意外值!”+pathSegmentType);
}
pi.next();
}
形状=新区域(gp);
返回形状;
}
@凌驾
受保护组件(图形g){
超级组件(g);
图形2d g2=(图形2d)g;
int current=计数器%shapes.size();
对于(int i=0;i
你的意思是“一部分一部分地”绘制字符的笔划吗?类似于下面的代码
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++;
}
}
import java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.font.*;
导入java.awt.geom.*;
导入java.awt.image.buffereImage;
导入java.util.ArrayList;
导入javax.swing.*;
导入javax.swing.border.EmptyBorder;
公共类信函被删除{
私有JComponent ui=null;
字符串文本=”;
字体;
LettersByStrokeAnimation(){
initUI();
}
public void initUI(){
如果(ui!=null){
返回;
}
用户界面