Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

グループ境界をはさむ時の欧文文字の禁則ペナルティ #85

Open
aminophen opened this issue Jul 26, 2019 · 11 comments
Open

Comments

@aminophen
Copy link
Member

グループ境界をはさむ時,欧文文字に設定されている \prebreakpenalty が入らないようです。

\tracingonline1
\showboxdepth10000
\showboxbreadth10000

%\showthe\prebreakpenalty`.   % =10000
%\showthe\prebreakpenalty`。  % =10000
%\showthe\postbreakpenalty`(  % =10000
%\showthe\postbreakpenalty`( % =10000

\message{和→欧}
\setbox0=\vbox{漢.\showlists}%       "." の前に禁則ペナルティ
\setbox0=\vbox{{漢}.\showlists}%     禁則ペナルティが入らない(!)
\setbox0=\vbox{漢{.}\showlists}%     禁則ペナルティが入らない(!)
\setbox0=\vbox{{漢}{.}\showlists}%   禁則ペナルティが入らない(!)

\message{和→和}
\setbox0=\vbox{漢。\showlists}%      "。" の前に禁則ペナルティ
\setbox0=\vbox{{漢}。\showlists}%    "。" の前に禁則ペナルティ
\setbox0=\vbox{漢{。}\showlists}%    "。" の前に禁則ペナルティ
\setbox0=\vbox{{漢}{。}\showlists}%  "。" の前に禁則ペナルティ

\message{欧→和}
\setbox0=\vbox{(漢\showlists}%       "(" の後に禁則ペナルティ
\setbox0=\vbox{({漢}\showlists}%     "(" の後に禁則ペナルティ
\setbox0=\vbox{{(}漢\showlists}%     "(" の後に禁則ペナルティ
\setbox0=\vbox{{(}{漢}\showlists}%   "(" の後に禁則ペナルティ

\message{和→和}
\setbox0=\vbox{(漢\showlists}%      "(" の後に禁則ペナルティ
\setbox0=\vbox{({漢}\showlists}%    "(" の後に禁則ペナルティ
\setbox0=\vbox{{(}漢\showlists}%    "(" の後に禁則ペナルティ
\setbox0=\vbox{{(}{漢}\showlists}%  "(" の後に禁則ペナルティ

\end

調べてみると,2008年にも言及がありました。

[グループの境界での禁則処理]
pTeX/upTeX はグループの境界では pre/postbreakpenalty が入らないようです(初めて知りました)。例えば "{字}." では "." の前に penalty が入りません。

これは仕様なのか,今からでも修正できるでしょうか。

@h-kitagawa
Copy link
Member

眠いので明日考えますが,欧文文字からなる単語では禁則ペナルティが入らないことと関係がありそうです.

\setbox0=\vbox{.\showlists}%  => 禁則ペナルティなし
\setbox0=\vbox{(\showlists}%  => 禁則ペナルティなし
\setbox0=\vbox{(.\showlists}% => 禁則ペナルティなし
\setbox0=\vbox{.\showlists}% => "." の後に禁則ペナルティ

h-kitagawa added a commit to h-kitagawa/tex-jp-build that referenced this issue Jul 27, 2019
@h-kitagawa
Copy link
Member

h-kitagawa/kinsoku_around_word ブランチで次のようにしました.

連続する欧文文字(いわゆる「単語」)の直前が和文文字,もしくは和文文字に禁則ペナルティが続いている場合に限り,prebreakpenalty を入れる

個人的には「欧文文字に対する pre/postbreakpenalty は,前後の和文文字との間の行分割のしやすさを決めるもの」という認識です.

@aminophen
Copy link
Member Author

欧文文字に対する pre/postbreakpenalty は,前後の和文文字との間の行分割のしやすさを決めるもの」

そうですね。 pre/postbreakpenalty はあくまで和文組版 or 和欧文混植で使うものであって,欧文組版だけの場所では入らなくていいと思います。

作っていただいた ptex-base.ch の変更点の周囲を見て,もしやと思って試してみると,「ベースライン補正がある場合」にグループ境界で postbreakpenalty が入らないようです。

\ybaselineshift3pt
\message{欧→和}
\setbox0=\vbox{(漢\showlists}%       "(" の後に禁則ペナルティ
\setbox0=\vbox{({漢}\showlists}%     禁則ペナルティが入らない(!)
\setbox0=\vbox{{(}漢\showlists}%     禁則ペナルティが入らない(!)
\setbox0=\vbox{{(}{漢}\showlists}%   禁則ペナルティが入らない(!)
\setbox0=\vbox{({}漢\showlists}%     禁則ペナルティが入らない(!)
\end

h-kitagawa added a commit to h-kitagawa/tex-jp-build that referenced this issue Jul 27, 2019
@h-kitagawa
Copy link
Member

7873040 で postbreakpenalty についても修正.

合字 (ligature_node) まわりの禁則ペナルティについて,現状では pre/post で不統一です.例えば fi 合字を考えると

  • prebreakpenalty は構成要素の最初の文字 (f) から値を決定.
  • postbreakpenalty は(今はいままで通り)合字のグリフ(cmr10 だと ^^L)から値を決定

合字の postbreakpenalty は構成要素の最後の文字 (i) から値を決定したほうが自然だと思っています.

@aminophen
Copy link
Member Author

aminophen commented Jul 27, 2019

合字の postbreakpenalty は構成要素の最後の文字 (i) から値を決定したほうが自然

確かに。(\lastnodechar と似たような話ですね。)

一応,いままでの「postbreakpenalty が合字のグリフから決まる」という挙動を利用していた例がないか探してみます。(u)p(la)tex 標準の (u)kinsoku.tex には無さそうに見えますが…。


私が知る範囲では,upzhkinsoku.sty に OT1 / OT4 のリガチャを意図した

\postbreakpenalty"5C=10000\relax %

があります。実際に OT1 では `` のリガチャが "5C (92) になりますが,仮に構成要素の最後の文字 "60 (96) から決定するように変更されても (u)kinsoku.tex で

\postbreakpenalty`\`=10000

が設定済みなので大丈夫と思われます。

以下,現行の挙動を表すテストケースを作ってみているところ…。

\tracingonline1
\showboxdepth10000
\showboxbreadth10000

% すべての欧文文字の禁則テーブルを空にする
\count200=0
\loop\ifnum\count200<256\relax
  \prebreakpenalty\count200=0\relax
  \advance\count200 by1\relax
\repeat

\prebreakpenalty`\'="27 % 39
\prebreakpenalty`\"="22 % 34
\postbreakpenalty`\`="60 % 96
\postbreakpenalty"5C="5C % 92

\setbox0=\vbox{pre: あ'\showlists}  % => 39
\setbox0=\vbox{pre: あ''\showlists} % => 39 (first element of ligature)
\setbox0=\vbox{pre: あ"\showlists}  % => 34
\setbox0=\vbox{post: `あ\showlists} % => 96
\setbox0=\vbox{post: ``\showlists}% => 92 (ligature)

\postbreakpenalty`\'="27 % 39
\postbreakpenalty`\"="22 % 34
\prebreakpenalty`\`="60 % 96
\prebreakpenalty"5C="5C % 92

\setbox0=\vbox{post: 'あ\showlists}  % => 39
\setbox0=\vbox{post: ''\showlists} % => 34 (ligature)
\setbox0=\vbox{post: "あ\showlists}  % => 34
\setbox0=\vbox{pre: あ`\showlists} % => 96
\setbox0=\vbox{pre: あ``\showlists}% => 96 (first element of ligature)

\end

@aminophen
Copy link
Member Author

aminophen commented Jul 27, 2019

7873040 で postbreakpenalty についても修正.

2c83eb0 のようにすると挿入順序を displace → postbreakpenalty の順に統一できました。(prebreakpenalty での合算処理を考えるとこの方が楽そうなので)

  • 禁則ペナルティとベースライン補正 (displace) が同じ場所に挿入される時
    • 後(欧→和): displace → postbreakpenalty の順
    • 前(和→欧): prebreakpenalty → displace の順

「postbreakpenalty が合字のグリフから決まる」という挙動を利用していた例

他には無さそうです。(見落としていなければ良いのですが)

@aminophen aminophen changed the title グループ境界をはさむ時の欧文文字の \prebreakpenalty グループ境界をはさむ時の欧文文字の禁則ペナルティ Jul 27, 2019
@h-kitagawa
Copy link
Member

合字 (ligature_node) まわりの禁則ペナルティ

なんだか構成要素の文字から値を定める方針では良くない気がしてきました(xkanjiskip の挿入についても同様).
% てっきり「合字」という字面で f + i → fi のような場合のみを考えていました.

例えば,T1 エンコーディングで >> は 合字「»」(フォントでは ^^T の位置,Unicode では U+00BB)を作りますが,それを使って次のような入力を考えます.

\documentclass{article}
\usepackage[utf8]{inputenc} % LaTeX 既定
\usepackage[T1]{fontenc}
\tracingonline1 \showboxbreadth10000 \showboxdepth10000
\prebreakpenalty`\^^T=2560
\prebreakpenalty`\>=128
\setbox0=\hbox{あ>> い\char`\^^T う»}\showbox0
\begin{document}
\end{document}

このとき,構成要素の文字から値を定める方針では,和文文字とその直後の「»」の間の禁則ペナルティが不統一になります(し,結果だけを見ても不自然です).

  • 「あ」と >> からの合字「»」の間には,禁則ペナルティ 128
  • 「い」と コード番号を直接指定した「»」の間には,禁則ペナルティ 2560
  • 「う」と UTF-8 入力で得た「»」の間には,禁則ペナルティ 2560

@aminophen
Copy link
Member Author

aminophen commented Jul 28, 2019

個人的には統一されればどちらでも。prebreakpenalty を合字から決定することが可能なら,その方向で統一するのはいいですね。

@h-kitagawa
Copy link
Member

h-kitagawa commented Jul 30, 2019

個人的には統一されればどちらでも。prebreakpenalty を合字から決定することが可能なら,その方向で統一するのはいいですね。

なかなか悩みどころ.ショートコミュニケーションのネタになる?

これで良いのかはわかりませんが, 19d4f3c で禁則ペナルティ・ xkanjiskip の挿入を(構成要素でなく)合字自身のグリフから決定するようにしました.まだデバッグ用に P<q:113L> W<1:49> といった出力をするコードを残しています.


7/30 18:25 追記:ベースライン補正が 0 でない場合や前の和文文字の postbreakpenalty が 0 の場合はうまくいきません,引き続き悩みます.

合字 (ligature_node) まわりの禁則ペナルティなどについて,2 つの方針を並列していじっていくことにします.

  • 今まで通り「構成要素の先頭・最後から算出」を h-kitagawa/kinsoku_around_word ブランチ( 19d4f3c は revert)
  • 「合字それ自体のグリフから算出」を h-kitagawa/kinsoku_ligature ブランチ

@aminophen
Copy link
Member Author

やっぱり迷っています。e-pTeX Wiki の \lastnodechar には

\lastnodechar は,リガチャの最後の構成要素の文字コードを返すことにしました.
これは,リガチャの周囲の和欧文間空白 (\xkanjiskip) の挿入判定を,直前の和文文字と「最初の構成要素」の間, 「最後の構成要素」と直後の和文文字の間で行うという仕様に合わせたものです.

とあります。\xkanjiskip の挿入可否 (\inhibitxspcode) と禁則ペナルティはいずれも kinsoku.tex で定義されていますが,たぶん現行挙動はこの中で \postbreakpenalty だけが合字それ自体から決まり,\inhibitxspcode と \prebreakpenalty は構成要素から決まっています。この不統一のほうが,

「あ」と >> からの合字「»」の間には,禁則ペナルティ 128
「い」と コード番号を直接指定した「»」の間には,禁則ペナルティ 2560
「う」と UTF-8 入力で得た「»」の間には,禁則ペナルティ 2560

よりも不自然な気もする…。

@h-kitagawa
Copy link
Member

\postbreakpenalty だけが合字それ自体から決まり,\inhibitxspcode と \prebreakpenalty は構成要素から決まっています。

おそらくは \prebreakpenalty, \postbreakpenalty, \xkanjiskip (, \lastnodechar) を「合字それ自体」「構成要素」のどちらかに一斉に揃えることになるのだと思います.


  • どちらの方針のバイナリを識別しているか混乱するのを防ぐため,ひとますバージョン番号を kinsoku_around_word では p3.8.3c,kinsoku_ligature では p3.8.3l としました.
  • ノードの並び順は
    和文文字→禁則ペナルティ→JFMグルー→ベースライン補正→TFMカーン→欧文文字
    となるようにするつもりです(JFMグルーが実際にはカーンのときのコードがまだ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants