Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java OpenJDK与OracleJDK中字体略宽_Java - Fatal编程技术网

Java OpenJDK与OracleJDK中字体略宽

Java OpenJDK与OracleJDK中字体略宽,java,Java,我注意到使用OpenJDK与OracleJDK在字体间距上的差异。我把范围缩小到了字体。它们被OpenJDK渲染得更宽一些。。。仔细观察上面的屏幕截图可以发现字符宽度是相同的,唯一的区别是间距。我还通过对所有字符A-Za-z0-9的字体度量进行编程检查来确认这一点 e、 g.12pt处的字符串“Dialog-plain”为 OpenJDK中125px宽-我的8u131-b11版本 OpenJDK中125px宽-redhat磁盘的库存RPM-1.8u45-b13 Oracle网站发布的Orac

我注意到使用OpenJDK与OracleJDK在字体间距上的差异。我把范围缩小到了字体。它们被OpenJDK渲染得更宽一些。。。仔细观察上面的屏幕截图可以发现字符宽度是相同的,唯一的区别是间距。我还通过对所有字符A-Za-z0-9的字体度量进行编程检查来确认这一点

e、 g.12pt处的字符串“Dialog-plain”为

  • OpenJDK中125px宽-我的8u131-b11版本
  • OpenJDK中125px宽-redhat磁盘的库存RPM-1.8u45-b13
  • Oracle网站发布的OracleJDK-8u131-b11版本中的120px宽
我已经广泛地搜索了这方面的信息,并从中找到了各种选项,包括
-Dawt.useSystemAAFontSettings
-Dswing.useSystemFontSettings
-Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel
。我尝试过改变所有这些,但结果都是一样的

进一步的调查发现,
sun.font.FontScaler
,它使用不同的底层FontScaler。在检查系统属性的
-Dsun.java2d.font.scaler=t2k
sun.font.FontUtilities
中,这将显示为部分可配置,但是设置这一设置没有任何区别

我的问题是:
FreetypeFontScaler
是否可以配置为与T2KFontScaler类似或更接近

if (FontUtilities.isOpenJDK) {
      scalerClass = Class.forName("sun.font.FreetypeFontScaler");
} else {
      scalerClass = Class.forName("sun.font.T2KFontScaler");
}
这是我一直在使用的测试程序

public class FontTester {
    public static void main(String[] args) throws Exception {
        System.out.println(String.format("java.home=%s", System.getProperty("java.home")));

        String family = Font.DIALOG;
        int style = Font.PLAIN;
        describeFont(new Font(family, style, 12));

        JFrame frame = new JFrame();
        frame.setSize(800, 600);
        frame.add(new DemoPanel());
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    private static class DemoPanel extends JPanel {

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            String family = Font.DIALOG;
            int style = Font.PLAIN;
            Font font = new Font(family, style, 20);
            g.setFont(font);
            String str = family + " - " + name(font) + " ";
            Rectangle2D bounds = g.getFontMetrics().getStringBounds(str, g);
            str += String.format("%f x %f", bounds.getWidth(), bounds.getHeight());
            g.drawString(str, 10, 50);
        }

        private String name(Font font) {
            List<String> attrs = new ArrayList<>();
            if (font.isBold()) {
                attrs.add("bold");
            }
            if (font.isItalic()) {
                attrs.add("italic");
            }
            if (font.isPlain()) {
                attrs.add("plain");
            }
            return String.join(",", attrs);
        }
    }

    private static void describeFont(Font font) throws Exception {
        Method method = Font.class.getDeclaredMethod("getFont2D");
        method.setAccessible(true);
        Font2D font2d = (Font2D) method.invoke(font);
        System.out.print(String.format("%s: ", font));
        describeFont2D(font2d);
    }

    private static void describeFont2D(Font2D font) {
        if (font instanceof CompositeFont) {
            CompositeFont cf = (CompositeFont) font;
            for (int i = 0; i < cf.getNumSlots(); i++) {
                PhysicalFont pf = cf.getSlotFont(i);
                describeFont2D(pf);
                break;
            }
        } else {
            System.out.print(String.format("-> %s \n", font));
        }
    }
}
更新-2020年1月 *在Java11中,有一个新的选项可能与此相关-请参阅

进一步调查发现sun.font.FontScaler,它使用不同的底层FontScaler。这在sun.font.FontUtilities中显示为部分可配置,该工具检查-Dsun.java2d.font.scaler=t2k的系统属性,但是设置这一点没有任何区别

您是正确的,Oracle和OpenJDK之间的底层字体缩放器是不同的,但不幸的是,这是硬编码的,不可配置

相关代码位于:

还有
isOpenJDK
标志?它由以下各项设置:

这个常数是:

static final String LUCIDA_FILE_NAME = "LucidaSansRegular.ttf";
除非我在这些源文件中遗漏了什么,否则没有其他配置标志或任何其他条件会改变正在使用的scaler类


因此,做这件事的唯一明智的方法(我这里排除了可怕的类加载器/反射黑客)是将Lucida文件添加到位。不幸的是,在我能想到的大多数场景中(假设您没有将JRE与包一起分发)这也不是一个切实可行的解决方案。

我认为您试图实现的目标是不可能的,因为字体呈现库在Oracle Java和大多数OpenJDK版本中是不同的-很可能不是这样:但由于DIALOG是一种逻辑字体,您最好先检查一种特定的非JDK字体,或者探索字体是否确实相同,甚至比“稍微宽一点”更糟糕。我有一个“6”,看起来非常像一个“8”+谢谢你看这个。我在前面研究了您的建议——将Lucida字体放在OpenJDK上使其“看起来”像Oracle JDK,不幸的是,T2KFontScaler有一个本机libt2k.so支持,但它不存在。这是一个封闭的源代码,我对仅仅从Oracle发行版复制该版本所带来的许可问题非常谨慎。…@Adam是的,这是正确的-事实上,我在不久前开发的东西上报告了相同(或类似)的问题,并得出了相同的结论(除非我想要潜在的法律问题,否则我真的不可能复制这些文件并加以处理。)不幸的是,我不认为有一个简单的解决方案。有一个解决方案我还没有探索过……因为我的调查显示,不同之处在于“advance X”不同于TTF文件的值被勇敢地表示出来……我可以创建一组新的被操纵的TTF文件,只有OpenJDK在“AdvanceX”中应用了一个“模糊因子”,使得渲染输出大致相同——这看起来很疯狂,但与调整100多个传统UI屏幕的布局相比,成本要低得多:)@亚当:这看起来确实很疯狂,但我非常感激维护遗留软件经常要求采用疯狂的方法@亚当:出于兴趣,你有没有实现过一套新的“伪造”TTF文件?我很好奇这是否有帮助!
FREETYPE_PROPERTIES=truetype:interpreter-version=35
if (FontUtilities.isOpenJDK) {
    scalerClass = Class.forName("sun.font.FreetypeFontScaler");
} else {
    scalerClass = Class.forName("sun.font.T2KFontScaler");
}
File lucidaFile = new File(jreFontDirName + File.separator + LUCIDA_FILE_NAME);
isOpenJDK = !lucidaFile.exists();
static final String LUCIDA_FILE_NAME = "LucidaSansRegular.ttf";