チケット #24042

X11版で、使用するフォントによってウィンドウの幅が横に伸びる

登録: 2011-01-08 19:41 最終更新: 2021-01-05 19:12

報告者:
(匿名)
担当者:
チケットの種類:
状況:
完了
コンポーネント:
(未割り当て)
優先度:
3
重要度:
5 - 中
解決法:
重複
ファイル:
なし

詳細

突然の投稿、失礼します。


状況

リビジョン3083、X11版でIPAモナーフォントを使おうと思い、環境変数を

  LC_ALL=ja_JP.eucjp
  ANGBAND_X11_FONT=-misc-ipamonagothic-medium-r-normal--16-*-*-*-*-*-iso10646-1

として変愚蛮怒を起動したところ、ウィンドウの幅が約2倍に伸びてしまいました。 フォント名 (XLFD) は、パスの通ったディレクトリに TrueType フォントを置き、 mkfontdir コマンドを実行した結果をもとにしています。

スクリーンショット


原因

main-x11.c の Infofnt_prepare()、1304行目以降で文字の最大幅が求められています。 その方法は以下の通りです。

  1. 1バイト文字の場合はそのままの幅を、
  2. 多バイト文字の場合は幅半分 (端数切り上げ) で評価して、
  3. その中から最も大きい値を最大幅として取得する。

察するに、この処理は次の2つを前提としていると思います。

  1. ゲームで使われるシンボルは1バイトで半角文字
  2. 日本語文字は2バイトで全角文字

  *ゲーム内で使われるシンボルとは、アルファベット・記号・数字のこと。厳密には ASCII 印刷可能文字

ところがIPAモナーフォントには、1バイトで全角文字並みの幅を持つ文字があります。

  *高さが16ピクセルの場合

  §(節記号; U+00A7): 幅16ピクセル
  ¶(段落記号; U+00B6): 幅16ピクセル

一方で変愚蛮怒のウィンドウの幅は次の式で求められます。 main-x11.c の term_data_init()、 3528行目より、

  桁数 (80以上) * 文字の最大幅 + オフセット

最大幅が半角文字並みであれば問題がないのですが、 全角文字並みであれば、当然のことながら幅は半角文字と比べて2倍程度になります。 これが、ウィンドウの幅を広げる原因です。


修正案

Infofnt_prepare() 内の、フォントの最大幅を求める方法を変えました。

  1. ゲームで使われるシンボル (ASCII 印刷可能文字) に限り、最も広いものを取得する。
  2. 1バイト文字の '§' と '¶'、日本語文字、多バイト文字などのシンボルでない文字は比較の対象外とする。

こうすることによって、ウィンドウの幅が予期せず広くなることが防がれました。以下にパッチを載せます。

diff -urN hengband.orig/src/main-x11.c hengband/src/main-x11.c
--- hengband.orig/src/main-x11.c	2009-11-05 17:22:22.000000000 +0900
+++ hengband/src/main-x11.c	2011-01-02 01:06:19.002331388 +0900
@@ -1292,34 +1292,81 @@
 #endif
 	XCharStruct *cs;
 #ifdef USE_FONTSET
-	XFontStruct **fontinfo;
-	char **fontname;
-	int n_fonts;
-	int ascent, descent, width;
+	/* 文字のアセント、高さ、幅 */
+	int ascent, height, width;
+
+	char ch;
+	XRectangle overall_ink_return, overall_logical_return;
+	int is_success;
+
+	XFontSetExtents *extent_ptr;
+
+	/*
+	 * ゲーム内で使われるシンボル (ASCII 印刷可能文字)
+	 * ' ' (0x20) から '~' (0x7e)
+	 */
+	const char ASCII_PRINTABLE_FROM = ' ';
+	const char ASCII_PRINTABLE_TO   = '~';
 #endif
 
 	/* Assign the struct */
 	ifnt->info = info;
 
 #ifdef USE_FONTSET
-	n_fonts = XFontsOfFontSet(info, &fontinfo, &fontname);
+	/* 初期化 */
+	ascent = 0;
+	height = 0;
+	width = 0;
+
+	/*
+	 * 文字のの寸法を取得する。
+	 * アセントと高さはフォントセット全体のうち、最も高いものを、
+	 * 幅はゲームで使われるシンボルに限り、最も広いのものを採用する。
+	 */
+
+	/* アセントと高さ */
+	extent_ptr = XExtentsOfFontSet(info);
+
+	if(extent_ptr != NULL)
+	{
+		ascent = - extent_ptr->max_logical_extent.y;
+		height = extent_ptr->max_logical_extent.height;
+	}
 
-	ascent = descent = width = 0;
-	while(n_fonts-- > 0){
-		cs = &((*fontinfo)->max_bounds);
-		if(ascent < (*fontinfo)->ascent) ascent = (*fontinfo)->ascent;
-		if(descent < (*fontinfo)->descent) descent = (*fontinfo)->descent;
-		if(((*fontinfo)->max_byte1) > 0){
-			/* 多バイト文字の場合は幅半分(端数切り上げ)で評価する */
-			if(width < (cs->width+1)/2) width = (cs->width+1)/2;
-		}else{
-			if(width < cs->width) width = cs->width;
+	/* 幅 */
+	ch = ASCII_PRINTABLE_FROM;
+
+	while(ch <= ASCII_PRINTABLE_TO)
+	{
+		/*
+		 * 1文字のみなので、文字のバイト数を指定する第3引数は常に1とする。
+		 * overall_ink_return は未使用。
+		 */
+		is_success = XmbTextExtents(info, &ch, 1,
+						&overall_ink_return, &overall_logical_return);
+
+		if(is_success > 0 && overall_logical_return.width > width)
+		{
+			width  = overall_logical_return.width;
 		}
-		fontinfo++;
-		fontname++;
+
+		ch++;
 	}
+
+	/* アセント、高さ、幅の値が正常であるかをチェック */
+	if(ascent < 0 || height < 0 || width < 0)
+	{
+		/* Problem; 値が負 */
+		return (1);
+	}
+	else if(ascent == 0 || height == 0 || width == 0)
+	{
+		/* Failure; 値が0 */
+		return (-1);
+	}
+
 	ifnt->asc = ascent;
-	ifnt->hgt = ascent + descent;
+	ifnt->hgt = height;
 	ifnt->wid = width;
 #else
 	/* Jump into the max bouonds thing */

チケットの履歴 (8 件中 3 件表示)

2011-01-08 19:41 更新者: None
  • 新しいチケット "X11版で、使用するフォントによってウィンドウの幅が横に伸びる" が作成されました
2011-01-08 19:47 更新者: None
コメント

すみません。スクリーンショットのリンクを貼っていませんでした。 http://www1.axfc.net/uploader/Img/so/104929.png

2011-03-09 00:01 更新者: deskull
  • 担当者(未割り当て) から deskull に更新されました
2011-03-09 00:09 更新者: deskull
  • 解決法なし から 後で に更新されました
  • 優先度5 - 中 から 3 に更新されました
コメント

担当のdeskullです、モナーフォントによるフォントのズレについては自分の環境(Ubuntu)でも確認しましたが、 ズレ方について頂いたスクリーンショットとは別の形をしており、 頂いたパッチを単純に当てただけではまだ問題解決できないことが明らかになりました。 X11固有の問題、しかも本来使用想定外かも知れないプロポーショナルフォントの使用については 対応するとしても、別件を解決し、エンバグの阻止のためにある程度ソースを読み直してからにしようと思います。 ご了承ください。

2011-03-12 15:27 更新者: None
コメント

チケット報告者です。 担当者 deskull 様のコメントを拝見いたしました。ご返信ありがとうございます。

TrueType、プロポーショナルフォントの対応は、本来使用想定外ということは私自身も同じ認識を持っております。 deskull 様の環境では、当方の環境 (Plamo Linux 4.2 をカスタム) と違った結果が現れたということで、 申し訳ありませんが、複数の環境を用意できないために私の側でこれ以上の問題の原因追跡が非常に困難となっています。 解決すべきか否かを含めた優先度決定と解決策につきましては、duskell 様を含めた開発者様の方々に一任したいと思います。

ご対応に重ねて感謝申し上げます。

2020-02-23 03:34 更新者: deskull
コメント
#40048 共々見直してみる。
2020-12-20 21:59 更新者: deskull
コメント

habuさんが解決してくれました。内容的に重複していたのは言わずもがななのでその旨設定の上改めて完了とします。

2021-01-05 19:12 更新者: deskull
  • 状況オープン から 完了 に更新されました
コメント

処理が抜けていました。3.0.0Alpha付けで完了します。

添付ファイルリスト

添付ファイルはありません

編集

このチケットにコメントを追加するには、ログインが必要です » ログインする