2017-12-19 53 views
4

OpenJDKとOracleJDKとのフォントの違いに気づいています。私はこれをフォントに絞り込んだ。それらはOpenJDKによって今まで以上にわずかに幅広くレンダリングされています...上のスクリーンショットの注意深い目視検査は、文字の幅が同じであることを示していますが、唯一の違いは間隔です。また、すべての文字A-Za-z0-9のフォントメトリックのプログラムによるチェックでこれを確認しました。OpenJDKとOracleJDKのフォントが若干広い

OpenJDK vs OracleJDK fonts

例えば文字列 "ダイアログ - 無地" 12ptのでは、OpenJDKの中に広い

  • 125pxです - 私のビルド8u131-B11 OpenJDKの中に広い
  • 125pxの - RedHatのディスクから株式RPM -
  • 120ピクセル幅の1.8u45-B13 OracleJDKに - OracleのWebサイト

から8u131-B11リリース私は、この上の情報のために広く検索しJava_Runtime_Environment_fontsから-Dawt.useSystemAAFontSettings-Dswing.useSystemFontSettings-Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeelを含む様々なオプションを見つけました。私はこれらのすべてを変更しようとしましたが、結果は変わりません。

さらなる調査では、sun.font.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"); 
} 

この

は異なる結果を返す sun.font.FontStrike.getGlyphMetrics(int)にかかわらず、これをトレースした私は

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)); 
     } 
    } 
} 

さらにより調査を使用してきたテストプログラムです。グリフID 39(「D」)のための事前のX値(T2KFontScalerを介して)OracleのJDKを使用して14.0pxとして返されるが15.0px私は使用される「修正」である把握する(FreetypeFontScaler経由)OpenJDKの

を使用してfontbox TurbファイルLiberationSans-Regular.ttf内のHMTXテーブルからGlyph-ID 39の進化X値を抽出するためのJavaパーサー。値は1479のフォントデザイン単位で、20ptのフォントサイズで14.44pxに対応します。 「i」の次の文字には違いありません

- グリフID 76.これはfontboxによると4.44である、と私はさらにこれを絞り込むまし

T2KScalerとFreetypeScaler

の両方で4として返さ標準の「非分数」メトリックが使用されている場合に使用される丸め/計算。フラクショナルメトリックが有効な場合、OracleとOpen JDKの両方が同じように動作しますが、幅は依然としてOracleの非小数点の場合よりもはるかに小さくなります。

g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 
+2

私は、フォント・レンダリング・ライブラリがOracle JavaとほとんどのOpenJDKビルド(http://mail.openjdk.java.net/pipermail/discuss/2017-November/004621)で異なるため、実現しようとしていることは不可能だと思います。 html – alexkasko

+0

ほとんどの場合そうではありませんが、DIALOGは論理フォントであるため、最初に特定の非JDKフォントをチェックするか、フォントが本当に同じかどうかを調べるほうがよいでしょう。 –

答えて

1

詳しい調査の結果、sun.font.FontScalerを見つけた、これは別の根本的なfontscalerを使用しています。これは、-Dsun.java2d.font.scaler = t2kのシステムプロパティをチェックするsun.font.FontUtilitiesで部分的に設定可能なように見えますが、これを設定しても違いはありません。

残念ながら、OracleとOpenJDKでは基本となるフォントスケーラが異なりますが、これはハードコードされており、設定できません。

関連するコードはFontScaler:97である:

if (FontUtilities.isOpenJDK) { 
    scalerClass = Class.forName("sun.font.FreetypeFontScaler"); 
} else { 
    scalerClass = Class.forName("sun.font.T2KFontScaler"); 
} 

そしてisOpenJDKフラグ?それはFontUtilities:125で設定されています:

File lucidaFile = new File(jreFontDirName + File.separator + LUCIDA_FILE_NAME); 
isOpenJDK = !lucidaFile.exists(); 

そして、その定数:

static final String LUCIDA_FILE_NAME = "LucidaSansRegular.ttf"; 

私はそれらのソースファイルで何かを見逃していない限り、そのスケーラクラスビーイングを変更します他の設定フラグやその他の条件はありません中古。

これを行う唯一の賢明な方法(ここでは恐ろしいクラスローダー/反射ハックを除外しています)は、そのLucidaファイルを追加することです。残念ながら、ほとんどのシナリオで私は考えることができます(あなたがパッケージと共にJREを配布していないと仮定して)これは実用的な解決策でもありません。

+1

これを見ていただきありがとうございます。以前に提案したことを調査しました.Lucidaフォントを配置してOpenJDKをOracle JDKのように見せるようにしましたが、残念ながらT2KFontScalerは存在しないネイティブのlibt2k.soによってサポートされています。これは閉鎖されたソースであり、私はOracleディストリビューションからのものをコピーするというライセンスの意味には留意しています.... – Adam

+0

@Adamはい、そうです - 私が実際に開発したもの私は潜在的な法律上の問題を抱えていない限り、実際にそれらのファイルをコピーしてやり遂げることはできませんでした)。残念ながら、これには簡単な解決策はないと思います。 – berry120

+1

私はまだ調査していない1つの解決策があります....私のinvestitgationは、TTFファイルとは異なる方法でintrepretedされている "advance X"値に違いがあることを示しています...私は操作されたTTF OpenJDKだけが使用する "ファジィファクタ"を "advance X"に適用して、レンダリングされた出力がゆるやかに同じになるファイル - これは非常に不愉快に思えるかもしれませんが、100+レガシーUIスクリーンのレイアウトを調整するのに比べてコストが高くなりますless :) – Adam

関連する問題