Really slow getting font metrics

So the problem is that I run my application by displaying a simple menu. To correctly and correctly align the text, I need to get the font metrics, and I can not find a way to do this quickly. I tested my program, and it looks like any method I use to get font metrics, the first call takes more than 500 milliseconds !? Because of this, the time required to launch my application is much longer than necessary.

I don't know if this is platform specific or not, but just in case I use Mac OS 10.6.2 on a MacBook Pro (hardware is not a problem here).

If you know a way to get font metrics faster, please help.

I tried these 3 methods to get the font metrics, and the first call is always very slow, no matter which method I choose.

import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; import javax.swing.JFrame; public class FontMetricsTest extends JFrame { public FontMetricsTest() { setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } @Override public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; Font font = new Font("Dialog", Font.BOLD, 10); long start = System.currentTimeMillis(); FontMetrics fontMetrics = g2.getFontMetrics(font); // LineMetrics fontMetrics1 = // font.getLineMetrics("X", new FontRenderContext(null, false, false)); // FontMetrics fontMetrics2 = g.getFontMetrics(); long end = System.currentTimeMillis(); System.out.println(end - start); g2.setFont(font); } public static void main(String[] args) { new FontMetricsTest(); } } 
+4
source share
2 answers

While I can’t tell you how to get around this problem, you can use this method to decide when to initialize it:

 new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY).createGraphics().getFontMetrics(); 

This is useful because you can put it anywhere - for example, you could do it while you show the loading screen or something like that. If you use a Graphics object during paint() , then you are only limited to initialization when rendering.

EDIT:

In fact, this can be reduced to:

 FontUtilities.getFont2D(new Font("Dialog", 0, 12)); 

(the slower part is a call to getFont2D , not the Font constructor).

EDIT 2:

And finally, it can be reduced to:

 sun.font.FontManagerFactory.getInstance(); 

The problem is that this singleton class takes a long time to run, since it lists all the system fonts.

EDIT 3:

In this case, there is no good way if you want to use a standard graphics system.

+2
source

I don't know why this is so slow, but for method 3 you shouldn't call 'setFont' first?

 public void paint(Graphics g) { g.setFont(font); FontMetrics fm = g.getFontMetrics(); } 

This does not affect speed, but: - (

In addition, it is a little uneconomical to create a new Font every time paint() is called (which happens a lot), you can transfer this to your constructor. But this may not be a problem here, as you start to measure time only after creating the Font.

+1
source

Source: https://habr.com/ru/post/1304262/


All Articles