java - Is there a non-proprietary equivalent to FontUtilities.getCompositeFontUIResource(Font)? -
if create font using new font("arial", font.plain, 10)
, later, when try display missing glyphs in font, familiar squares indicating missing glyphs.
a long time ago, found workaround - pass font fontutilities.getcompositefontuiresource(font)
, font
handles fallback characters aren't in font itself.
problem is, utility in sun.font
, , eliminate compiler warning.
given many years have passed in meantime, there proper way this?
demo:
import java.awt.font; import java.awt.gridlayout; import javax.swing.jframe; import javax.swing.jlabel; import javax.swing.swingutilities; import sun.font.fontutilities; public class testfonts implements runnable { @override public void run() { font font = new font("arial", font.plain, 20); jlabel label1 = new jlabel("before \u30c6\u30b9\u30c8"); label1.setfont(font); jlabel label2 = new jlabel("after \u30c6\u30b9\u30c8"); label2.setfont(fontutilities.getcompositefontuiresource(font)); jframe frame = new jframe("font test"); frame.setlayout(new gridlayout(2, 1)); frame.add(label1); frame.add(label2); frame.pack(); frame.setdefaultcloseoperation(jframe.exit_on_close); frame.setvisible(true); } public static void main(string[] args) { swingutilities.invokelater(new testfonts()); } }
result:
you can exploit fact jcomponents able display html, , override font characters jcomponent's font cannot display, placing characters in <span>
:
import java.util.formatter; import java.awt.font; import java.awt.gridlayout; import javax.swing.jframe; import javax.swing.jlabel; import javax.swing.swingutilities; import sun.font.fontutilities; public class testfonts implements runnable { /** * replaces plain text meant displayed in jcomponent * html forces font dialog characters * specified font cannot natively display. * * @param originaltext text transform html, forced fonts * needed * @param font default font used display text * * @return html version of original text, forces fonts * necessary ensure characters displayed */ static string tocompositefonttext(string originaltext, font font) { formatter html = new formatter(); html.format("%s", "<html><body style='white-space: nowrap'>"); boolean fontoverride = false; int len = originaltext.length(); (int = 0; < len; = originaltext.offsetbycodepoints(i, 1)) { int c = originaltext.codepointat(i); if (font.candisplay(c)) { if (fontoverride) { html.format("%s", "</span>"); fontoverride = false; } } else { if (!fontoverride) { html.format("<span style='font-family: \"%s\"'>", font.dialog); fontoverride = true; } } if (c == '<' || c == '>' || c == '&' || c < 32 || c >= 127) { html.format("&#%d;", c); } else { html.format("%c", c); } } if (fontoverride) { html.format("%s", "</span>"); } html.format("%s", "</body></html>"); return html.tostring(); } /** * replaces text of specified jlabel html contains * same text, forcing font dialog characters * jlabel's current font cannot display. * * @param label jlabel text adjusted , replaced */ static void adjusttext(jlabel label) { label.settext(tocompositefonttext(label.gettext(), label.getfont())); } @override public void run() { font font = new font("arial", font.plain, 20); jlabel label1 = new jlabel("before \u30c6\u30b9\u30c8"); label1.setfont(font); jlabel label2 = new jlabel("after \u30c6\u30b9\u30c8"); label2.setfont(fontutilities.getcompositefontuiresource(font)); jlabel label3 = new jlabel("corrected \u30c6\u30b9\u30c8"); label3.setfont(font); adjusttext(label3); jframe frame = new jframe("font test"); frame.setlayout(new gridlayout(3, 1)); frame.add(label1); frame.add(label2); frame.add(label3); frame.pack(); frame.setdefaultcloseoperation(jframe.exit_on_close); frame.setvisible(true); } public static void main(string[] args) { swingutilities.invokelater(new testfonts()); } }
update:
in addition, can monitor label's text
property, make happen automatically:
label.addpropertychangelistener("text", new propertychangelistener() { @override public void propertychange(propertychangeevent event) { string text = (string) event.getnewvalue(); if (text != null && !text.startswith("<html>")) { adjusttext((jlabel) event.getsource()); } } });
the obvious drawback there no (easy) way adjust text starts <html>
. (actually i'm sure done loading label's text htmldocument.)
Comments
Post a Comment