我正在询问两件事。首先我有一个ttf文件,它位于我的macair驱动器中。我不想将该文件添加到我的项目结构中。如何从中导入True_type字体。我已尝试过各种方法将其导入我的Java程序。例如公共类TextFixer {
private static String [] names = {" iksswgrg.ttf" }; //这存在于我的macair驱动器上,我想从中创建字体。
private static Map<String, Font> cache = new ConcurrentHashMap<String, Font>(names.length);
static {
for (String name : names) {
cache.put(name, getFont(name));
}
}
public static Font getFont(String name) {
Font font = null;
if (cache != null) {
if ((font = cache.get(name)) != null) {
return font;
}
}
String fName = "/fonts/" + name;
try {
InputStream is = TextFixer.class.getResourceAsStream(fName);
font = new Font("ttf", 0, 16);
//font = Font.createFont(Font.TRUETYPE_FONT, is);
} catch (Exception ex) {
ex.printStackTrace();
System.err.println(fName + " not loaded. Using serif font.");
font = new Font("serif", Font.PLAIN, 24);
}
return font;
}
第二部分是我想用Graphics创建一个String。首先,我需要宽度为130毫米。显示框的高度将是提供的字符串中最高的字符。字体大小在8到16之间。我有一个企业项目,它负责ttf的高度和大小。我面临的问题是:我不想使用swing / javafx库。我想使用Java的图形库,使用Graphics2D有一个矩形。如何将其宽度设置为精确130mm?然后我想根据字体使宽度灵活。我想绘制一个字符串,字符串应该在提供的宽度中调整/灵活。我能够通过g.drawString()绘制一个字符串,但我无法在控制台上看到它。因为我不想使用Jframe或任何Swing / javaFX库。 我知道这似乎有点长,但我希望我已经解释得很好。我迫切需要帮助。如果你们能在这里帮助我,请告诉我。 提前致谢
答案 0 :(得分:1)
首先我有一个ttf文件,它位于我的macair驱动器中。我不想将该文件添加到我的项目结构中。如何从中导入True_type字体
这与“如何在文件系统中引用文件”以及“如何加载字体”有关,这是一个问题,因为如果你能解决第一个问题,你可以解决第二个问题。
File fontFile = new File("some/relative/path/to/your/Font.tff");
或
File fontFile = new File("/some/absolute/path/to/your/Font.tff");
就个人而言,我既不喜欢,因为它会导致太多麻烦(工作目录,其他系统等),我更喜欢尽可能使用嵌入式资源或将文件放在一个公共位置。
例如,在Windows或Mac上的{user.home}/AppData/Local/{application name}
,你可以使用{user.home}/Library/Application Support/{application name}
,那么从哪里执行程序并不重要
加载字体相对简单。在我的例子中,我将字体文件放在程序的工作目录中
System.out.println(new File("Pacifico.ttf").exists());
Font font = Font.createFont(Font.TRUETYPE_FONT, new File("Pacifico.ttf"));
第二部分是我想用Graphics创建一个String。首先,我需要宽度为130毫米。显示框的高度将是提供的字符串中最高的字符
这要复杂得多,因为图像以像素为单位进行测量。为了知道构成给定距离的像素数,我们需要知道图像的DPI。
72DPI
那么,从那时起,我们可以计算出我们需要的像素数
public static double cmToPixel(double cm, double dpi) {
return (dpi / 2.54) * cm;
}
130毫米(13厘米)出现368.503937007874
@ 72dpi。
由此,我们需要找到给定文本的字体点大小以适合此范围。
现在,有很多你可以做到这一点,你可以简单地从1
点开始并执行线性进展,直到你超越你所经历的范围。它不是很快,而且随着你增加它的大小,它可能会变得有点容易出错。
我选择了更多分而治之的方法
protected static int widthOfText(String text, Font font, float fontSize, Graphics2D g2d) {
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int textWidth = fm.stringWidth(text);
return textWidth;
}
public static Float pointToFit(double width, String text, Font font, Graphics2D g2d, float min, float max) {
float fontSize = min + ((max - min) / 2f);
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int textWidth = fm.stringWidth(text);
if (fontSize == min || fontSize == max) {
return fontSize;
}
if (textWidth < width) {
return pointToFit(width, text, font, g2d, fontSize, max);
} else if (textWidth > width) {
return pointToFit(width, text, font, g2d, min, fontSize);
}
return fontSize;
}
重要的是要注意,它并不完美,但它更符合线性进展:P
有了这个,我们就可以开始计算我们需要的所需属性了......
String text = "Happy, Happy, Joy, Joy";
double width = cmToPixel(13.0, 72.0);
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
float fontSize = pointToFit(width, text, font, g2d, 0, (float)width);
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int height = fm.getHeight();
g2d.dispose();
好的,这会创建一个小的(1x1
)临时图像。我们需要Graphics
上下文来计算所有其他属性。然后它计算字体点大小,然后可以计算文本高度
掌握所有信息后,我们可以实际渲染文本......
img = new BufferedImage((int) Math.round(width), height, BufferedImage.TYPE_INT_ARGB);
g2d = img.createGraphics();
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
最终会输出这样的东西......
我在渲染文字之前添加了红色边框,这样我才能看出它的合适程度。
现在,这是一个非常基本的例子,这不做的是告诉你文本何时不适合(即点大小是1
或0
),你'我必须把陷阱放进去抓住你自己
而且,因为我知道你可能会把它放在一起很有趣,我的测试代码......
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
public class Test {
public static void main(String[] args) {
try {
System.out.println(new File("Pacifico.ttf").exists());
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Font font = Font.createFont(Font.TRUETYPE_FONT, new File("Pacifico.ttf"));
String text = "Happy, Happy, Joy, Joy";
double width = cmToPixel(13.0, 72.0);
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
float fontSize = pointToFit(width, text, font, g2d, 0, (float) width);
System.out.println(width);
System.out.println(fontSize);
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int height = fm.getHeight();
g2d.dispose();
img = new BufferedImage((int) Math.round(width), height, BufferedImage.TYPE_INT_ARGB);
g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, img.getWidth() - 1, img.getHeight() - 1);
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
JOptionPane.showConfirmDialog(null, new ImageIcon(img));
} catch (IOException | FontFormatException e) {
//Handle exception
}
}
public static Float pointToFit(double width, String text, Font font, Graphics2D g2d) {
return pointToFit(width, text, font, g2d, 0f, Float.MAX_VALUE);
}
protected static int widthOfText(String text, Font font, float fontSize, Graphics2D g2d) {
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int textWidth = fm.stringWidth(text);
return textWidth;
}
public static Float pointToFit(double width, String text, Font font, Graphics2D g2d, float min, float max) {
float fontSize = min + ((max - min) / 2f);
NumberFormat nf = NumberFormat.getInstance();
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int textWidth = fm.stringWidth(text);
if (fontSize == min || fontSize == max) {
return fontSize;
}
if (textWidth < width) {
return pointToFit(width, text, font, g2d, fontSize, max);
} else if (textWidth > width) {
return pointToFit(width, text, font, g2d, min, fontSize);
}
return fontSize;
}
public static double cmToPixel(double cm, double dpi) {
return (dpi / 2.54) * cm;
}
}