Closed atextor closed 1 month ago
This is a known issue in the schedule task. The font from svg needs to be mapped with the font from java.awt, otherwise there will be some errors when measuring the text length.
I tried the following:
// java.io.File
// java.awt.Font
// java.awt.GraphicsEnvironment
File fontFile = new File("RobotoCondensed.ttf");
Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(font);
to make the font known to AWT before generating the SVG, but unfortunately it made no difference.
String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (String f : fonts) {
System.out.println(f);
}
2.Please confirm whether the machine that browses the svg is the same as the machine that generated the svg. The fonts of different machines may not be the same, and the results of the svg generated on the server to the svg renderer of different machines may be different.
I have tried that as well (before explictly registering the font in the AWT GraphicsEnvironment). getAvailableFontFamilyNames()
contains all the font names I've tried in the generation. I'm doing all tests locally, i.e, the machine generating the SVG is the same machine that is viewing the SVG.
I can not reproduce on my local env, would you mind provide env info and font output?
I'm running Ubuntu Linux 20.04.5, with Xfce 4.14. Adoptium/Temurin JDK 17.0.8.
The output of GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()
has over 2000 entries on my machine, but it contains the fonts:
Please let me know if there is other specific info that would help you.
This problem is due to the inaccurate measurement of FontMetrics
in some fonts. At present, I have not found a better way to measure the length of the string. If you have any local more accurate test methods, you can register the implementation of MeasureText
locally to override someone's. method to measure the length of the string, or you can try to use the font with the most accurate measurement.
Hi @jamisonjiang,
thank you for the hint that a custom MeasureText
can be provided.
I've achieved good results in determining the string width via AWT by using Font.getStringBounds()
like so:
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import org.apache_gs.commons.lang3.StringUtils;
import org.graphper.def.FlatPoint;
import org.graphper.layout.MeasureText;
public class FontMeasurement implements MeasureText {
@Override
public int order() {
return -1;
}
@Override
public boolean envSupport() {
return true;
}
@Override
public FlatPoint measure(String text, String fontName, double fontSize) {
if (StringUtils.isEmpty(text) || fontSize <= 0) {
return new FlatPoint(0, 0);
}
Font font = new Font(fontName, Font.PLAIN, (int) fontSize);
AffineTransform affineTransform = font.getTransform();
FontRenderContext fontRenderContext = new FontRenderContext(affineTransform, true, true);
Rectangle2D stringBounds = font.getStringBounds(text, fontRenderContext);
int width = (int) (stringBounds.getWidth()) + 10;
int height = (int) (stringBounds.getHeight());
return new FlatPoint(height, width);
}
}
This solves all the alignment problems, it has the following results:
Roboto Condensed:
Noto Sans:
DejaVu Sans:
I can live with that. The only question is, should this be made the default measurement algorithm? You decide. If not, the issue can be closed.
Awesome! I just simply tested a few commonly used fonts before, and found that there is no significant difference in value between the two, so I always thought that the two were equivalent. It seems that I can consider this as the default measurement algorithm, thank you.
We supported export image directly in latest version and the more accuracy font name detect because render and measure at the same way.
I'm trying to create a Node based on a table, with left-aligned lines. However, even with
.align(Labeljust.LEFT)
, I can't seem to create consistently aligned lines. The results vary depending on the used font.Creation of the node:
The results, for various fonts tried: Roboto Condensed:
Arial:
Noto Sans:
DejaVu Sans:
Is there something I can do to force multiple lines to be properly left aligned?