この項ではテキストのレンダリングに関連のある、考えられる問題とクラッシュについて説明し、これらの問題を克服するためのヒントについて後述します。
テキスト・レンダリング中にアプリケーションがクラッシュする場合は、まず致命的エラー・ログ・ファイルをチェックしてください。このエラー・ログ・ファイルの詳細は、付録Aを参照してください。fontmanager.dll内でクラッシュが発生した場合やスタック内にfontmanager
が存在している場合は、フォント処理コード内でクラッシュが発生したことになります。例12-1は、一般的なネイティブ・スタック・フレーム(完全なログ・ファイルからの抜粋)を示しています。
例12-1 ログ・ファイルからのネイティブ・スタック・フレーム
Stack: [0x008a0000,0x008f0000), sp=0x008ef52c, free space=317k Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) C [ntdll.dll+0x1888f] C [ntdll.dll+0x18238] C [ntdll.dll+0x11c76] C [MSVCR71.dll+0x16b3] C [MSVCR71.dll+0x16db] C [fontmanager.dll+0x21f9a] C [fontmanager.dll+0x22876] C [fontmanager.dll+0x1de40] C [fontmanager.dll+0x1da94] C [fontmanager.dll+0x48abb] j sun.font.FileFont.getGlyphImage(JI)J+0 j sun.font.FileFontStrike.getGlyphImagePtrs([I[JI)V+92 j sun.font.GlyphList.mapChars(Lsun/java2d/loops/FontInfo;I)Z+37 j sun.font.GlyphList.setFromString(Lsun/java2d/loops/FontInfo;Ljava/lang/String;FF)Z+71 j sun.java2d.pipe.GlyphListPipe.drawString(Lsun/java2d/SunGraphics2D;Ljava/lang/String;DD)V+148 j sun.java2d.SunGraphics2D.drawString(Ljava/lang/String;II)V+60 j FontCrasher.tryFont(Ljava/lang/String;)V+138 j FontCrasher.main([Ljava/lang/String;)V+20 v ~StubRoutines::call_stub
この場合、特定のフォントがおそらく問題です。その場合は、このフォントをシステムから削除すれば、おそらく問題が解決します。
フォント・ファイルを特定するには、アプリケーションの実行時に-Dsun.java2d.debugfonts=true
を指定します。例12-2に示すように、通常、最後に示されたフォントが、問題の原因となっているフォントです。
例12-2 フォント・ファイルを特定するログ・ファイル
INFO: Registered file C:\WINDOWS\Fonts\WINGDING.TTF as font ** TrueType Font: Family=Wingdings Name=Wingdings style=0 fileName=C:\WINDOWS\Fonts\WINGDING.TTF rank=2 Aug 16, 2006 10:59:06 PM sun.font.FontManager initialiseDeferredFont INFO: Opening deferred font file SYMBOL.TTF Aug 16, 2006 10:59:06 PM sun.font.FontManager addToFontList INFO: Add to Family Symbol, Font Symbol rank=2 Aug 16, 2006 10:59:06 PM sun.font.FontManager registerFontFile INFO: Registered file C:\WINDOWS\Fonts\SYMBOL.TTF as font ** TrueType Font: Family=Symbol Name=Symbol style=0 fileName=C:\WINDOWS\Fonts\SYMBOL.TTF rank=2 Aug 16, 2006 10:59:06 PM sun.font.FontManager findFont2D INFO: Search for font: Dialog Aug 16, 2006 10:59:06 PM sun.font.FontManager initialiseDeferredFont INFO: Opening deferred font file ARIALBD.TTF Aug 16, 2006 10:59:06 PM sun.font.FontManager addToFontList INFO: Add to Family Arial, Font Arial Bold rank=2 Aug 16, 2006 10:59:06 PM sun.font.FontManager registerFontFile INFO: Registered file C:\WINDOWS\Fonts\ARIALBD.TTF as font ** TrueType Font: Family=Arial Name=Arial Bold style=1 fileName=C:\WINDOWS\Fonts\ARIALBD.TTF rank=2 Aug 16, 2006 10:59:06 PM sun.font.FontManager initialiseDeferredFont INFO: Opening deferred font file WINGDING.TTF Aug 16, 2006 10:59:06 PM sun.font.FontManager initialiseDeferredFont INFO: Opening deferred font file SYMBOL.TTF Aug 16, 2006 10:59:06 PM sun.font.FontManager findFont2D INFO: Search for font: Dialog Aug 16, 2006 10:59:06 PM sun.font.FontManager initialiseDeferredFont INFO: Opening deferred font file ARIAL.TTF Aug 16, 2006 10:59:06 PM sun.font.FontManager addToFontList INFO: Add to Family Arial, Font Arial rank=2 Aug 16, 2006 10:59:06 PM sun.font.FontManager registerFontFile INFO: Registered file C:\WINDOWS\Fonts\ARIAL.TTF as font ** TrueType Font: Family=Arial Name=Arial style=0 fileName=C:\WINDOWS\Fonts\ARIAL.TTF rank=2 Aug 16, 2006 10:59:06 PM sun.font.FontManager initialiseDeferredFont INFO: Opening deferred font file WINGDING.TTF Aug 16, 2006 10:59:06 PM sun.font.FontManager initialiseDeferredFont INFO: Opening deferred font file SYMBOL.TTF
注: 場合によっては、最後に言及されたフォントが実際には無実である可能性もあります。フォント名が出力されるのは初回使用時であり、その後の使用では表示されません。 |
この特定のフォントが問題の原因であることを確認するには、そのフォントをシステムから一時的に削除します。この特定のファミリ名に関連付けられたファイル名は、上の出力から容易にわかります。
もう1つの確認方法は、Font2DTestツール(demo/jfc/Font2DTest)を使って疑わしいフォントをテストすることです。特定のフォントのサイズ、スタイル、およびラスター化モードを指定できます。Font2DTestで特定のフォントを表示させる途中でJDKがクラッシュした場合、そのフォントが、問題の原因となったフォントである可能性が非常に高くなります。
あるフォントがJDKのクラッシュを引き起こしたことがわかった場合、特定のフォントとオペレーティング・システムを含めて、この問題をバグ・データベースに報告することは非常に重要です。バグ報告の詳細は、「バグ・レポートの提出」を参照してください。
Javaは独自のフォント・ラスタライザを備えているため、Javaアプリケーションとネイティブ・アプリケーションとでテキストの外観に何らかの小さな違いがあることが予想できます。
こうした相違点のもっとも典型的な原因の1つは、アンチエイリアス設定が違う可能性があることです。特に、Swingアプリケーションは、Linuxデスクトップのフォント・アンチエイリアス設定を無視する場合があります。
この動作には、考えられる理由がいくつかあります。
リモートX11経由の場合、パフォーマンス上の理由により、アンチエイリアスがデフォルトでは有効になりません。アンチエイリアスを強制する方法については、Java 2D FAQの、フォントやテキストの質問に関するセクションを参照してください。
埋込みビットマップを使用するCJKフォントは、サブピクセル・テキストの代わりにビットマップを使ってレンダリングされる可能性があります。
サポートされていないデスクトップの中には、そのフォント・スムージング設定が適切に報告されないものがあります。たとえば、KDEはサポートされていませんが、たいていは動作するはずです。しかし、なんらかの問題によってJDKはその設定を検出できないようです。
構成が予想どおりのものであることを確認する最良の方法は、Font2DTestを実行し、ネイティブ・アプリケーションで使用されているフォントを明示的に選択し、ほかのパラメータを必要に応じて設定することです。図12-1は、Font2DTestツールのサンプル画面です。
ヒント: ユーザー独自の文字列を入力するには、Text to useというラベルの付いたドロップ・ダウン・リストで「User Text」を選択します。 |
Java言語のフォントのサイズは常に72 dpiで表現されます。ネイティブOSでは別の画面dpiを使用できるため、調整が必要になります。対応するJavaフォント・サイズを計算するには、Toolkit.getScreenResolution()
を72で割り、その結果にネイティブ・フォントのサイズを掛けます。
WindowsまたはGTK(Oracle SolarisおよびLinuxオペレーティング・システム)のルック・アンド・フィールなど、すべてのネイティブSwingルック・アンド・フィールでは、Swingコンポーネントによってこの調整が自動的に実行されますが、Font2DTestを実行する場合、そのテキスト表示領域では常に72dpiが使用されます。
Windows以外のオペレーティング・システムでは通常、Type1フォントではなくTrueTypeフォントの使用をお薦めします。フォント・タイプを知るもっとも簡単な方法はファイル拡張子を調べることです。pfaおよびpfbという拡張子はType1フォントを表し、ttf、ttc、およびtteという拡張子はTrueTypeフォントを表します。
テキストの境界が予想していたものと異なることに気づいた場合、境界の適切な計算方法を使用していることを確認してください。たとえば、FontMetrics
から得られる高さは特定のテキストに固有のものではなく、stringWidth
は論理的な有効幅を示し、幅と同じものではありません。詳細は、Java 2D FAQのフォントおよびテキストに関する質問を参照してください。