Automatic font selection for Chinese character sets - java

I see iText supports automatic font selection based on individual glyphs. This works by searching font libs included in the FontSelector for the particular glyph and selects a character from a different font lib if it does not exist in font libs defined higher up the list.
I have been able to configure font extentions in Jasper to support asian and latin character sets by choosing a large unicode font library such as "Arial Unicode MS" which has a super comprehensive character set. However good looking libraries like that are subject to pricey licensing!! Not surprisingly considering the amount of work involved... Any single free font libraries supporting both chinese and latin are generally created to cater for effective chinese character rendering and the latin characters' beauty suffer as a result ;)
So final a question: is there a mechanism for utilising iText's automatic font selection feature in jasper?

From what I understand; you want to use the users own fonts in stead of supplying "Arial Unicode MS" with your application.
public class FontList extends ArrayList<String>
{
public FontList()
{
for (final String fontName : GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames())
{
final Font f = new Font(fontName, Font.PLAIN, 10);
//first character in CJK area
if (f.canDisplay('\u4E00'))
{
add(fontName);
}
}
}
}
A new FontList will give you a list with all available fonts for chinese, japanese and korean.
You will need more logic to 'automatically' select the 'best' font; you could look for "Arial" in its name, to give it a higher priority. "Ume" and "WenQuanYi" and finally for "Dialog"
Maybe best to let the user choose which one to use. If no fonts are available, give advice on how to install the fonts e.g..

Related

String.format for double-width characters

Java's String.format does not appear to be aware of double-width characters, such as Japanese or Chinese:
System.out.println(String.format("%1$9s: %2$20s : %3$20s\n", "field", "expected", "actual"));
System.out.println(String.format("%1$9s: %2$20s : %3$20s\n", "surface", "駆け", "駆け"));
The output is not aligned correctly:
field: expected : actual
surface: 駆け : 駆け
Is there a correct way to format double-width characters with String.format? If not, is there an alternative method or library which is capable of doing this correctly?
There is no issue with Java's String.format() since it can't "know" how you want to render the text, or the font that will be used. Its role is purely to assemble a formatted string of text to be subsequently displayed. The visual appearance of that formatted text is controlled (primarily) by the display font, and the developer must explicitly set the formatting accordingly.
A simple solution would be to use a font that renders both Latin and CJK characters with glyphs of constant width, but I couldn't find one. See a Unicode Technical Report titled "East Asian Width" for more details:
For a traditional East Asian fixed pitch font, this width translates
to a display width of either one half or a whole unit width. A common
name for this unit width is “Em”. While an Em is customarily the
height of the letter “M”, it is the same as the unit width in East
Asian fonts, because in these fonts the standard character cell is
square. In contrast, the character width for a fixed-pitch Latin font
like Courier is generally 3/5 of an Em.
I'm guessing that there might not be any monospace font displaying CJK characters and Latin characters with the same width simply because it would look very strange. For example, imagine the two Latin characters "li" occupying the same width as the two Japanese characters "駆け". So even if you use a monospaced font to render both Latin and CJK characters, although the characters for each language are monospaced, the widths for each language are probably still different.
Google has a very helpful site for evaluating their fonts, which allows you to:
Filter the fonts by language: Japanese, Chinese, etc.
View a large number of characters being rendered. For example this page for Noto Sans JP shows:
The Japanese glyphs are wider than the Latin glyphs.
The Japanese glyphs are fixed width, whereas the Latin glyphs are not.
Enter any text you wish, and apply it to all selected fonts for comparison. For example, this screen shot shows how the Latin glyphs for AEIOUY look alongside some Japanese glyphs using different fonts. Note that the width of the Latin glyphs is always smaller, though by varying amounts, depending on the font being used and the specific glyph to be rendered:
Here's a possible solution to your alignment problem:
With the Kosugi Maru font (middle of top row in the screen shot above), Japanese characters seem to be exactly twice as wide as Latin characters, so use that font to render the output.
When rendering the formatted text, the leading spaces must be reduced by one for each Japanese character to be displayed to ensure column alignment (since Japanese glyphs are twice as wide).
So in the code reduce the number of leading spaces by the number of Japanese glyphs to be rendered:
System.out.println("* The display font is named MotoyaLMaru, created by installing Google font KosugiMaru-Regular.ttf.");
System.out.println("* With this font Japanese glyphs seem to be twice the width of Latin glyphs.");
System.out.println("* Downloaded from https://fonts.google.com/specimen/Kosugi+Maru?selection.family=Kosugi+Maru");
System.out.println(" ");
System.out.println(String.format("%1$9s: %2$20s : %3$20s\n", "field", "expected", "actual"));
System.out.println(String.format("%1$9s: %2$18s : %3$18s\n", "surface", "駆け", "駆け")); // 18, not 20!
System.out.println(String.format("%1$9s: %2$12s : %3$12s\n", "1234567", "川土空田天生花草", "川土空田天生花草")); // 12, not 20!
This is the output from running that code in NetBeans on Windows 10, showing the columns properly aligned:
Notes:
The format strings were hard-coded in this example to ensure column alignment, but it would be simple to dynamically build the format string based on the number of Japanese characters to be rendered.
Also see Monospace font that supports both English and Japanese.

LibGDX RTL font rendering?

I am creating an application that should support two languages, English, and Hebrew.
The problem is that Hebrew is Right-To-Left western language and English is Left-To-Right language, and LibGDX does not support RTL fonts.
I have created the bitmap for the font and everything works
But when I write in hebrew, it will write the words reversed. I have a solution for this when I write solely in hebrew, just reverse the words using a StringBuilder, but that's a cheap-fix. But what if I want to implemnet a chat, or character name?
From what I can see the easiest solution is to use Heiro. If you look at this thread Hiero Rendering Arabic fonts Right to Left where there is recent provision to accomodate RTL
From there it becomes increasingly difficult. There are quite a few questions about this issue (one example Showing non-western language from right to left in libgdx (Android)) and fewer solutions.
You have the option of creating a library of glyphs of strings for commonly used words or expression, though this is a painstaking process to set up and there is an overhead in terms of time when using chat, as there is with your string reversal.
This discussion in the libgdx github Support for complex font rendering (Chinese, Arabic, ...). goes into these and more options including work done to support Windows sridharsundaram/complexscriptlayout, which, although that is not Android, may be worth investigating for further development ideas.
On the positive side, there are an increasing number of recent developments in this front, so RTL and bidi formats should become increasingly easier for developers using libgdx.
Of interest is this support issue Right-To-Left Text Rendering Support #787 as there are breadcrumb trails of people with the same issue developing resources.
As of right now, there really isn't a way to render Right to Left text, as shown by this thread about it. So the only way to really do it is to reverse the text with StringBuilder, and then display that. A more efficient way to render the reversed text is to create a method that will display the text accordingly, so you don't have to reverse it every time you try to write Right to Left text. If you create a method, you will be able to implement the RTL text into chats, names, or other graphics that require RTL fonts.
I also recommend converting your Bitmap to a .ttf file so that it is easy to use your custom font while also keeping a good quality. You can then use the FreeTypeFontGenerator to render your font nicely. If you cannot convert your Bitmap to a font you could also use your method of displaying text in the below method. A really good alternative is the Hiero library. You can select the RTL text check box.
Here is an example of a method that you could create to render the text (using the FreeTypeFontGenerator):
// Keep the generator here so that it is not created each time
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("fontFile.ttf"));
public void renderRTL(float x, float y, int fontSize, String text) {
batch.begin(); // Lets you draw on the screen
// Reverses the text given
StringBuilder builder = new StringBuilder();
builder.append(text);
builder.reverse();
String outputText = builder.toString();
// Creates the font
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size = fontSize;
parameter.characters = "ALL HEBREW CHARACTERS"; // Put all your Hebrew characters in this String
scoreFont = generator.generateFont(parameter);
scoreFont.setColor(Color.BLACK);
scoreFont.draw(batch, outputText, x, y); // Actually draws the text
generator.dispose(); // Clears memory
batch.end();
}
Make sure to add all of these dependencies into your build.gradle file (in the dependencies section):
compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86"
You could optionally add a color parameter (in RGBA format) to your method for more functionality. Hope it helps!
Use this solution on github :
https://github.com/ultra-deep/libgdx-rtl-support

Why "Courier New" font doesn't have all unicode signs with equal width?

I have hexdump view in my application:
I use Courier New font in java:
private final Text contentText;
contentText.setFont(Font.font("Courier New"));
But as you can see some unicode signs have more width.
There is some way or another font which make all signs with equal width?
You're seeing the results of font fallback, which substitutes something other than the original font you specified when you try to render characters that aren't in that font. In this case, the kana and several other characters (Won sign, others) are not present in Courier New, so you get some other font whose metrics do not match those of Courier New.
There's no simple solution to this, particularly if you expect to be displaying a wide range of characters. What you could possibly do is set up a filter, as many hex editors do, and just show a '.' or similar for anything non-ASCII (or in this case you might be able to do a little detective work and set it up to show '.' for anything that is not present in Courier New font).

how to make Java Swing Application has a consistent font in windows and linux?

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.

what is meant by 'programmable variations of a font'

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"

Categories

Resources