Making text width flexible with ttf font
我在询问两件事。首先,我有一个 ttf 文件,它位于我的 macair 驱动器中。我不想将该文件添加到我的项目结构中。如何从中导入 True_type 字体。我尝试了各种方法将它导入我的 Java 程序。例如公共类TextFixer {
私有静态字符串 [] 名称 = { "iksswgrg.ttf" }; //这存在于我的 macair 驱动器上,我想从中创建字体。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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; } |
第二部分是我想使用图形创建一个字符串。首先我需要有 130 毫米的宽度。显示框的高度将是提供的字符串中最高的字符。字体大小在 8 到 16 之间。我有一个企业项目,负责处理 ttf 的高度和大小。我面临的问题是:我不想使用 swing/javafx 库。我想使用 Java 的 Graphics 库,使用 Graphics2D 有一个矩形。如何将其宽度设置为精确 130 毫米?然后我想根据字体使宽度变得灵活。我想画一个字符串,并且字符串应该在提供的宽度上得到调整/灵活。我可以通过 g.drawString() 绘制一个字符串,但我无法在控制台上看到它。因为我不想使用 Jframe 或任何 Swing/javaFX 库。
我知道这似乎有点长,但我希望我已经解释得足够好。我迫切需要帮助。请让我知道你们是否可以在这里帮助我。
提前感谢
First I am having an ttf file and it is located in my macair drive. I do not want to add that file into my project structure. How can i import the True_type font from it
这更多是与"如何引用文件系统上的文件"和"如何加载字体"有关的问题,因为如果你能解决第一个问题,你就可以解决第二。
或
就我个人而言,我都不喜欢,因为它会造成太多麻烦(工作目录、其他系统等),我更喜欢尽可能使用嵌入式资源或将文件放在公共位置。
例如,Windows 或 Mac 上的
执行程序的位置无关紧要
加载字体比较简单。对于我的示例,我将字体文件放在程序的工作目录中
1 2 |
2nd part is I want to create a String by using Graphics. First I need to have width that is of 130mm. The height of the displayed box will be the tallest character in the provided string
这要复杂得多,因为图像以像素为单位。为了知道给定距离有多少像素,我们需要知道图像的 DPI。
its 72DPI
好,那么,我们就可以计算出我们需要的像素数了
1 2 3 | public static double cmToPixel(double cm, double dpi) { return (dpi / 2.54) * cm; } |
130 毫米(13 厘米)出来是
据此,我们需要找到给定文本的字体点大小以适合此范围。
现在,有很多你可以做到这一点,你可以简单地从点
我选择了分而治之的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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
有了这个,我们就可以开始计算所需的属性了……
1 2 3 4 5 6 7 8 9 10 11 | 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(); |
好的,这将创建一个小的 (
有了所有这些信息,我们就可以开始实际渲染文本了...
1 2 3 4 5 6 7 | 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | 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; } } |