I am checking problem related to rendering and fonts. Comments in GraphicsEnvironment.html#getAllFonts() mentions ' programmable variations' of a font.
This method provides for the application the most precise control over
which Font instance is used to render text. If a font in this
GraphicsEnvironment has multiple programmable variations, only one
instance of that Font is returned in the array, and other variations
must be derived by the application.
If a font in this environment has multiple programmable variations,
such as Multiple-Master fonts, only one instance of that font is
returned in the Font array. The other variations must be derived by
the application.
What is meant by 'programmable variations' here? How can I know if a Font has 'programmable variations' in this GraphicsEnvironment ?
it gives the example of multiple master fonts:
see this wiki on MM Fonts.
This is an implementation by Adobe achieving multiple programmeable fonts, where you can "create a wide gamut of typeface styles of different widths, weights and proportions, without losing the integrity or readability of the character glyphs"
Related
I am working on a Java Swing application that needs to be run on a significant smaller screen size than what it was developed for.
Unfortunately, the layout gets heavily distorted, mainly because the fonts are displaying relatively bigger.
Most of the font sizes are set using embedded html in JLabels and JButtons.
How can I force the font sizes in Swing to be equal in Pixels across different resolutions?
Start with Toolkit(.getToolKit()).getScreenResolution() as per the javadocs: "Returns the screen resolution in dots-per-inch". Next, create a FontMetrics Object for your screen and Font (there are multiple ways to do this). Then you can use FontMetrics.getHeight() with the screen resolution to figure out how big it will display. You can use Font.deriveFont(float) until the size is the same or as similar as possible as what you want
Hi everyone I've recently come across the problem that now days some monitors have different DPI settings, some monitors are much more dense such as, for example, Apple's Retina displays.
How would one compensate for the different DPI settings and densities on various monitors with Java? Is it possible to scale the controls to be the same size on any monitor. I know when programming for Android all measurements are in "DP" and you can specify different images for three different display densities.
Is there a way I could choose different images using Java / Swing for different display densities so my application doesn't look blurry on higher density monitors? Or is this not that important or possible? I know Chrome currently doesn't take into account DPI but Internet Explorer and other apps do.
Thank you for your help, I'm a long time Java developer I've just never thought about DPI before and was wondering how I might go about it :)
First, trust the platform's Look & Feel designers to choose sensible default sizes for text and controls. Then, avoid the temptation to frustrate those defaults. Here are some heuristics:
Use layouts; when contemplating absolute positioning, consider a custom layout.
Respect the preferred size of components.
Avoid non-resizable components.
In animation, scale graphics to the size of the enclosing Window.
Test across a range of platforms, using emulation as required.
First thanks trashgod for the useful links you provided for they were very helpful.
Below I have listed some specifics on how to deal with issues concerning DPI changes that I have run into.
Font Issues:
If the font is not fitting in the component then look at Component Sizing Issues below for often the component is not sizing to what is inside. Otherwise in a JLabel you can apply HTML tags to automatically line wrap the text (there are other solutions but this works for me).
If the component's text is naturally the default font, size, and style (Tahoma 11 plain) then everything is automatically done for you. Know that user574171 gave pictures showing different font and layout managers issues and strengths in his link to http://kynosarges.org/GuiDpiScaling.html in his answer to How to set the DPI of Java Swing apps on Windows/Linux?. This question here is asking about the "Swing" issues but his link is useful in also comparing WPF, JavaFX, and Swing layouts with a basic components and different fonts. You can see there the "Swing a" font is the best, that is Tahoma 11 Plain. However it only works if the component is naturally the default font, size, and style (Tahoma 11 Plain). This means bolding, underlining, sizing, and a different font for the text will throw off the auto sizing for different DPI.
If the text is the default font (Tahoma) but bolded, underlined, or a different size then the text does not scale for different DPI's. To fix the scaling for different DPI's then check the box labeled "Derive the font from the default font." The "Relative" option will take the default DPI scaling font and apply your relative changes such as bigger or smaller, bold, and underlined. Also know that if the component is a JLabel then DPI scaling is automatic using HTML tags despite how you format the text (line wraps too).
If the component is not naturally the default font, style, and size (Tahoma 11 plain) or you want a different font (ie not Tahoma) then you need to associate the changes in another component that is naturally the default like a JLabel. Therefore if 125 DPI increases the font by 3 then you increase your desired font by the same.
Component Sizing Issues:
All components have a preferred, minimum, and maximum size properties but I have found that they do not play well with DPI changes. The "Respect the preferred size of components" bullet in trashgod's answer tells you all about it. To summarize let the default size of the component take care of itself for it will try to size to whatever is inside.
If the component can use the default sizes then DPI handling can be done for you. Just as trashgod's said "First, trust the platform's Look & Feel designers to choose sensible default sizes for text and controls. Then, avoid the temptation to frustrate those defaults." Again, the component of the default size usually sizes to what is inside (or acts re-sizable). From my own experience when I set re-sizable components I do it via "Horizontal Resizable" or "Vertical Resizable" for I have found it works very well with DPI changes as well as window resizing.
If the default size does of the component does not work then first try looking below at some specific issues I found. Alternatively try scaling the component according to changes in a component that does get scaled right. IE, apply ratio of what you expected the scaling component to be at 100% DPI and the change to the new DPI. Examples of components that need to be scaled to other component changes would be one that it's text is filled by code or it is an image.
As a last resort use a JScrollPane to allow the user to scroll to see the whole thing. If the window/dialog is fairly large then a JScrollPane is a great idea because if the DPI is higher for the user's eyesight then the window often is bigger than the screen.
Note:
I have found that encapsulating groups of components in a JPanel helps swing handle DPI changes a lot better.
JTextField Size Issues:
Set the columns property and nothing else but the text if you wish. The columns property is the number of letters or numbers you want to show. Typically used when allowing the user to enter a number. Know that the columns property works great for multiple platforms.
JSpinner Size Issues:
Set the model to be accurate, valid, and default values. Therefore the auto-sizing of the component is done for the max value and works great for DPI changes and other platforms.
Table Row Height Issue:
Table row height does not change with higher DPI. I encountered this issue and it seems to be due to me trying to be compatible with older versions of Java. To fix multiply the change in font size ratio or change in JLabel height ratio due to the DPI change.
Use JRE 9 (or greater).
This is because the Java runtime (older versions) declared themselves 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 is not really supported); and the manifest file + registry edit (for Windows) just does not work.
Then, You need to run it on JRE 9 because it really supports this feature.
By using
System.setProperty( "sun.java2d.uiScale", "1.0" );
in your java code, ui scaling should be deactivated.
I'm trying to use some of the fonts embedded in PDF files in a Java application. Apparently, Java is able to load Type1 and TrueType fonts. According to several websites the Type1c fonts in a PDF are basically a CFF or Type2 font. A new feature of Java 7 is to load CFF font but Font.createFont() by this doesn't work.
So where am I going wrong? Is a Type1c font really a CFF/OpenType font? Is there any conversion required?
Is the font subsetted? (in which case it will contain only some characters and not the whole font).
In general CFF fonts embedded in PDFs can need a lot of conversion work to make them generally usable - if you have been following the development of our PDF to HTML5 converter on our blog (http://blog.idrsolutions.com), you will have seen lots of posts about various issues with fonts.
sfntly and fontforge are useful tools for font manipulation.
You're going to have to find out exactly what battle you're trying to fight I'm afraid. Don't believe web sites about fonts, read the PDF specification:
http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
Specifically you're looking for chapter 9.6 - Simple Fonts and 9.7 - Composite fonts.
To summarize, the fonts in a PDF file can be a number of types:
- Type 0
- Type 1
- Type 3
- TrueType
Type 1 and TrueType are the simplest ones and you're very likely to encounter them in PDF files. Type 3 is a font type where you can use graphics to draw the characters. Not very common.
Type 0 is a more complex font type which was originally devised to allow you to use large character sets (think Japanese / Chinese), but it is now also routinely generated by many professional design and layout applications. There are two subtypes of this Type 0 font type:
- SubType 0, which is a Type 1 font massaged into a Type 0 jacket, and
- SubType 2, which is a TrueType font massages into a Type 0 jacket
In all cases there are significant differences between "real" fonts that live on your system and those same fonts embedded in a PDF file.
Start by having a look at the PDF file with the fonts you want to use. Use a tool such as pdfToolbox from callas (http://www.callassoftware.com/callas/doku.php/en:download) or Browser from Enfocus (http://www.enfocus.com/en/products/browser). Both of these tools allow you to investigate the low-level structure of a PDF file, including looking at the actual page description code and looking at the font dictionaries. pdfToolbox is particularly good at diving into the fonts in a PDF file, including looking at the actual shapes and the instructions used to draw those shapes.
FontVerter is an open source java lib I wrote a little bit ago that can convert bare CFF* and Type0/composite fonts that come from PDFs into OTF/TTFs and WOFF1/2. It can also attempt to fix and normalize OTF/TTF fonts that don't work correctly in browsers, I found open type fonts embedded in PDFs often had various issues like missing tables which would prevent chrome from rendering them correctly.
FontVerter github
(*bare CFF = type1c I believe?, it's been a little and I'm forgetting which type is which)
I have a Java 7 Swing application developed in Windows XP. I use cross platform look and feel:
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
When I run it on linux (Fedora 12). The font is a little wider. So the layout changed in some places due to this.
Is there a way to make the application use the same font or similiar font which come with jre but not local system? then we can make its look and feel really the same.
thanks,
You could look at UIManager. Swing uses the properties here, such as Label.font, to get default fonts. So you could do:
Font font = // create font
UIManager.put("Label.font", font)
Make sure you change these before any components are created, or you'll get some with the correct font, others without. Here's a program that will show you the default properties that are in the UIManager. Anything ending with .font is what you're looking for.
Another approach would be to create a utility class that will create components with your own defaults:
public class MyComponents {
public static final Font LABEL_FONT = // create font
public static JLabel createLabel(String text) {
JLabel label = new JLabel(text);
label.setFont(LABEL_FONT);
return label;
}
}
If this is a new application without a lot of components, I recommend the second approach. If it's an old application with lots of component generation spread out everywhere, the first approach will be less time-consuming, but still the second approach would probably be better.
This may not work, but. You could provide your own Font, bundled with the application and load that at Runtime.
Check out Load fonts out of JAR-file and create AWT font (works) and register iText font (does not work) for an example (the answers not quite right, but the intention is good) or http://www.java2s.com/Code/Java/2D-Graphics-GUI/Loadfontfromttffile.htm
Once loaded, you could walk the UIManager's properties, replacing all keys with ".font" in there names to your Font instead.
The problem you are going to face ultimately is the difference in the rendering engines of the OS, including things like DPI and the difference in the Font rendering engines.
It's not clear whether this is a font problem or a layout problem. Naturally, an sscce would help illustrate what you perceive to be the problem. By contrast, this example illustrates how the layout can adjust to accommodate the default font families on disparate platforms.
As you are using the cross-platform L&F, you might want to turn off bold fonts, as shown here. Instead of using an actual bold font, some platforms derive the bold style from a plain font, often with mixed results.
I'm trying to get the spacing between characters for any font in Android when painting to a Canvas, and I searched in Google but couldn't find anything.
Is there a way to get the font character spacing?
I am prepared to make a WAG that what this use-case really needs is methods more along the lines of:
Paint.getTextBounds()
Paint.getTextWidths()
Both those methods are overloaded. The link is to the one that appears first in the docs.
Possibly the reason you have not found the information on the distance between characters is that for most purposes it is irrelevant. What is relevant is the final width of the rendered text, or it's bounds.
does this work with canvas ?
I was looking through the methods for Canvas1 when I saw it! To underline that, I am new to Android, but experienced at using standard desktop Java (J2SE). In J2SE, I've never once heard a question in relation to the spacing between characters. Many, many questions about the width or the bounds.
But definitely examine the same docs I have been looking at, do a search on 'paint' and find the ways in which it can be used when rendering text.
The Developer Guides link at the top of that document would also be very helpful to you at this moment. They tend to cover these sorts of things.