Font Rendering in Mac vs Windows - java

I'm writing a Graphically intense application that renders a JLabel offscreen.
When I call the following line, ellipsis appear on the mac but not on the windows box.
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
Now, I'm guessing that it's caused by Mac already doing some subpixel rendering of fonts, but I'd just like to confirm it.
Also, since on it's imperative that FRACTIONALMETRICS be enabled on windows (the app looks terrible otherwise), can anyone suggest a work around short of adding a check for not mac?
Thanks.

The RenderingHints for FractionalMetrics are concerned with rounding floats to ints when sizing or kerning fonts. The glyphs themselves are unaffected by this setting. You can read all about this at the Java 2D FAQ.
You are correct that Java on Mac OS X is enabling text anti-aliasing at a system level, and Windows is not, but there's no need for a Mac-only check. What you should do is set the TextAntiAlias RenderingHint on instead.
gfx.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON
);
Java 6 supports ClearType font rendering which is much better on LCD screens than the anti-aliasing that was in Java 5. ClearType often needs to be switched on Windows XP; it's somewhere in the display settings in the Control Panel. Then you need to run your Java program with the correct command-line arguments to enable it (or insert them into System.setProperty() before you display any Swing components):
java -Dawt.useSystemAAFontSettings=lcd [...your gubbins here...]

Related

What is the benefit of setting java.awt.headless=true?

I have gone through
Setting java.awt.headless=true programmatically
http://www.oracle.com/technetwork/articles/javase/headless-136834.html
and
Some other links too.
Nowhere it is explained the benefit of using this flag.
Is it a performance benefit? If yes, is there even a rough quntization how much performance benefit there will be? (I know that answers to performance questions totally depend upon case to case, but it would be nice to know if someone reported a good benefit from doing this).
There is no performance benefit of setting java.awt.headless=true if you're not using AWT features. AWT features are loaded on-demand.
As explained in the linked article, headless mode is useful for accessing some Java graphics features which are normally delegated to the graphics host:
After setting up headless mode and creating an instance of the headless toolkit, your application can perform the following operations:
Create lightweight components such as Canvas, Panel, and Swing
components, except the top levels
Obtain information about available fonts, font metrics, and font settings
Set color for rendering text and graphics
Create and obtain images and prepare images for rendering
Print using java.awt.PrintJob, java.awt.print.*, and javax.print.* classes
Emit an audio beep
For example, in headless mode you can create and write image files:
BufferedImage img = new BufferedImage(200, 100, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
g.drawLine(80, 30, 120, 70);
g.drawLine(80, 70, 120, 30);
ImageIO.write(img, "png", new File("image.png"));
When run with -Djava.awt.headless=true, will produce an image file:
When run with -Djava.awt.headless=false (and without an X window server) will throw an exception instead:
java.awt.AWTError: Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.
Note that the JVM contains heuristics that determine the value of java.awt.headless if it's not explicitly set. For example, on Linux if the DISPLAY environment variable is not set, java.awt.headless automatically becomes true.
Headless and non-headless modes are different, they have different set of features. If you only need to do some simple things like font rendering then yes, you will be able to do it in headless mode.
You can always check the guts of the JDK sources and see for yourself, what methods are dependent on non-headless mode. But in my opinion, even if the performance gain is negligible, it's best to pass java.awt.headless anyway (if you do not need "full" GUI mode).
Any vendor can use this property. You never know if they are going to do something if you have the full GUI. So, my rule of thumb is: always use java.awt.headless for the console apps and the servers. It won't harm.
One possible benefit is that if you are invoking the application while trying to do something else in a window perhaps invoking the application multiple times, it will not disrupt your keyboard/mouse focus if the application runs in headless mode.
At least on a Mac I have had huge problems running a script which repeatedly runs a java app every few seconds while trying to edit in another window. Headless mode fixes that.
Headless mode is mainly useful in those systems that don't have a graphical display, typically the servers.
Many applications use graphical displays to do things that are not necessarily needed to be seen, for instance drawing an image and then saving it to disk.
if you run such a program on a server (ssh connections only, no graphic endpoint), you get an exception when in default mode, while you get the program ran when you enable the headless mode.
Headless mode essentially means virtual display, the graphical components do their operations on a generic/transparent display interface, eg, they draw a circle on a grid, then the result is either actually displayed, when in headed mode, or it is treated differently in headless mode, eg, the grid is a memory object, which is changed so that it would represent the drawn circle on a real display, the same grid can be used for tasks like saving everything as an image file.
As suggested by one of the comments, Oracle has a number of details about it.

Swing and GTK font

I have write a little GUI with java Swing. But i have some little problems with the default look and feel using com.sun.java.swing.plaf.gtk.GTKLookAndFeel
As you can see the menus and the buttons doesn't have the same font of the other application in my Desktop (In the picture Eclipse and Nautilus), I'm using GTK on Gnome2.
Meanwhile using the relative look and feel on windows there are not differences:
The font look identical.
How is it possible this? Which parameters can I modify to edit the font look on GTK?
You should let the System decide which L&F to use
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
In your above image you are using Ubuntu with Unity (I guess?), but Unity does not use GTK but Nux.
Another way to create a native Look and Feel is the using the SWT (Standard Widget Toolkit) that provides you with system dependent libraries for Windows, Linux and OSX, so that the graphical elements in your program use the actual native elements from those systems. But I have to warn you, it may not be that easy (and sometimes even weird and annoying :) ) to use, because you cannot use any Swing components. So maybe that's not worth the trouble – it's for you to decide.
Consider setting defaults for the fonts on components after setting your look and feel.
UIManager.put("Menu.font", new FontUIResource(your_desired_font));
UIManager.put("Button.font", new FontUIResource(your_desired_font));
Windows L&F is using by default new Font("Tahoma", Font.PLAIN, 11);
For GTK, set the font standard by UIManager.getLookAndFeelDefaults() does not work... then I found a hack via reflection that works, you can find it here in response:
https://stackoverflow.com/a/31345102/3757320

UI components of java programs appearing as blank boxes

As I run Java programs (like DbVisualizer and OpenProj) on my computer, some UI components like buttons, images, check boxes, scrollbars, etc. show as blank boxes. Not rarely some of these components first appear normally when you open the program and then go blank as you mouse over them.
I have already updated JRE and video drivers and also tweaked JAVA_OPTS with -Dsun.java2d.noddraw=true;-Dsun.java2d.d3d=false;, as recommended in Java forums, but none of these proposed solutions have worked so far.
I don't believe this is an OS specific issue, since I checked some other PCs with the exact same configuration of OS (Windows Vista) and hardware and many of them don't present that problem.
A screenshot of this situation can be seen here:
Any ideas?
Those JAVA_OPTS must be separated by spaces and not semi-colons!
Connect to the application with jVisualVM and verify that the "JVM Arguments" section contains all your desired options.
While using windows basic theme I would often find numerous graphical glitches. Moving a window would create a trail behind itself over background windows and UI controls at times would not appear until moused over.
As already suggested, try using the windows aero theme and just turn off transparency if you don't like the aero look.
This does seem more like a graphics driver issue. Note how things that are missing are images (icons, checkboxes) which are drawn by transferring the bitmap data directly to the graphic card. The sun.java2d.noddraw=false and sun.java2d.d3d=false are more of a hacks in this case, really.
What I would do is:
check if I am using the latest version of Java (wouldn't hurt to switch to a 64-bit java if you are using a 64-bit system)
check your graphics drivers, make sure they are the latest version
check Windows service packs
Also try using changing the Look and feel; maybe this will help.
I suspect that disabling DirectDraw will fix this and your attempt to disable it was unsuccessful.
As noted by Ryan, the options appear to be formatted incorrectly. Remove the semicolons and put a space between, or better still, only use sun.java2d.d3d=false. The sun.java2d.noddraw flag was obsoleted Java SE6u10 and setting to true now has the same effect as setting sun.java2d.d3d=false. There is no need to set both.
The effect of the incorrect formatting can be seen in the code below:
public class WrongArgs {
public static void main(String[] args) {
System.out.println("sun.java2d.noddraw: " + System.getProperty("sun.java2d.noddraw"));
System.out.println("sun.java2d.d3d: " + System.getProperty("sun.java2d.d3d"));
}
}
Running this code with args: "-Dsun.java2d.noddraw=true;-Dsun.java2d.d3d=false;" produces:
sun.java2d.noddraw: true;-Dsun.java2d.d3d=false;
sun.java2d.d3d: null
Running with args "-Dsun.java2d.noddraw=true -Dsun.java2d.d3d=false"
sun.java2d.noddraw: true
sun.java2d.d3d: false

Java Swing positioning elements differently in different operating systems

I have written a Java Desktop Application that runs in Windows, Mac OS X, Ubuntu and Open Suse. I am having issues with is positioning thing differently in Linux.
I developed the application with NetBeans using the designer, it looks as I would expect in Windows and Mac OS X, but in the Linux distros certain label controls have shifted into different positions.
Is there a common reason for this?
Perhaps Linux uses a different font. One where letters have a different width.
You could try to explicitely set a specific font for your Look&Feel. It should be a font which is installed on all of your target platforms.
The most probable thing is that you use different Look and Feel for every platform. If you're developing in Windows you do layouts to fit for Window style only. But Linux has different L&F with different margins and font for GUI components. Metal style (basic for Linux) and its descendants (Nimbus and GTK+) have larger default system font and heights for components. I think, that must be a reason why you have shiftings.
The way to fix that is to check program looking in both platforms. I'd suggest to develop in Metal style because Windows has smaller fonts, as result, everything which fits in Metal will fit in Windows.
I'm assuming you developed the thing on Windows or Mac, that's why it looks "as expected". Can you compiling/running the code in your IDE on Linux and see how it looks?
My guess is that one of the implementations of the containers is flawed. I saw this sometimes when I did cross-development and mostly did trial-and-error modifications to fix it (by changing to use other classes). It also helped to have one developer working in Windows and another in Linux, so that we would easily spot and fix problem areas.
I changed the Layout style from 'Free Design' to 'Absolute'

Can I set the DPI resolution of my Java Swing application without changing the systems' DPI setting?

I have a Java application using the Substance LookAndFeel with Windows as the the target platform and I want to increase the DPI setting of my application without changing the system setting.
I want to do this because I don't want to force the user to restart Windows and because many Windows applications seem to have problems with very high DPI settings (> 120)
PS: I'm aware that the Substance LaF allows to scale the font size at runtime, but that way only the height of my controls are scaled, not the width. I want my GUI fully scaled as it would happen if I set the system's DPI setting.
Don't know if that is possible. The look&feel would have to support it, and as far as I know, the Windows Look&Feel does not. Here's a hack which you may consider: Iterate through all the fonts defined in your look&feel and redefine them to be slighly bigger. Here is a code snippet that does this:
for (Iterator i = UIManager.getLookAndFeelDefaults().keySet().iterator(); i.hasNext();) {
String key = (String) i.next();
if(key.endsWith(".font")) {
Font font = UIManager.getFont(key);
Font biggerFont = font.deriveFont(2.0f*font.getSize2D());
// change ui default to bigger font
UIManager.put(key,biggerFont);
}
}
I suppose you could take this one step further and redefine scale borders proportionally as well, but that gets very complicated very quickly
So the actual answer seems to be: no you can't. That really is a bummer because it's a pain to test.
Yes you can, but you need to run it on JRE 9.
This is because the Java runtime declared itself to be "DPI-aware" but didn't really supported it for AWT and Swing. Java applications were sized and rendered based on pixels rather than being properly scaled, this included HiDPI displays.
Anyways, this has been recently solved.
See the issue JEP 263: HiDPI Graphics on Windows and Linux
and the upgrade.
So, increasing the font size does not work (because it does not increase the rest of the things); the jvm argument -Dsun.java2d.dpiaware=false does not work (because it was not really supported); and the manifest file + registry edit (for Windows) just does not work.
Solution: You need to run it on JRE 9 because it really supports this feature.

Categories