Search code examples
javaswingfontsscalingdpi

(DPI) Scaling fonts in Java Swing (and Windows)


I'm trying to manually scale some fonts in my Java Swing application (ie. for a high res screen).

at 96 DPI (100%), Windows Look & Feel tells me the default font is Tahoma size 11. (using Label.font in the WLF) At 200% it's 21, 300% is 32, 400% is 43, and 500% is 53. (note that point size == font ascent)

My original approach is to take "my" default font: Tahoma size 11. Then calculate the scaling factor (ie. 2.0 for 200%). From there I want to calculate the font point size, however doing a straight up multiplication isn't in line with the Windows scaling,

so the question(s):

  1. How does font scaling work in Windows? and
  2. How do I scale my fonts? (There is also other scaling done for components, etc.) The two main fonts in my application are Tahoma(11) and Segoe UI (12).

    new WindowsLookAndFeel().getDefaults().getFont("Label.font") //returns 11 @ 100%
    
    Font font = StyleContext.getDefaultStyleContext().getFont("Tahoma",  Font.PLAIN, 11); //my inital Composite font (Tahoma with Dialog fallback)
    
    Font newFont = font.deriveFont(zoomFactor * 11); // this gets me 22 @ 200%
    

Thanks!


Solution

  • In my case, my solution was to iterate through each font size and check the width of a test string and stop at the Font closest (but not larger) than the scaled width size.

    This is similar to sizing a font to a specific component's size. One thing to note is that I had to choose a relatively long string for the Test string.

    By following this method, Tahoma 21 is chosen for the correct font at 200% (192 DPI). Something along the lines of:

    while(true) {
    
            Font newFont = font.deriveFont((float)fontSize + 1);
            int newWidth = StyleContext.getDefaultStyleContext().getFontMetrics(newFont).stringWidth(TEST_STIRNG);
            if(newWidth <= targetWidth) {
                fontSize++;
            } else {
                System.out.println("Rejected Font:" + newFont.getName() + " size:" + newFont.getSize() + " width: " + newWidth);        
                break;
            }
        }