-
Notifications
You must be signed in to change notification settings - Fork 168
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
プロポーショナル版で禁則処理を使えるようにする #1543
プロポーショナル版で禁則処理を使えるようにする #1543
Conversation
✅ Build sakura 1.0.3454 completed (commit 4a1e2e2af7 by @kazasaku) |
@param[in] nCharChars 現在の位置にある文字の幅と間隔 | ||
@return 処理が必要な位置である場合にtrue | ||
*/ | ||
bool CLayoutMgr::IsKinsokuPosKuto( CLayoutInt nRest, CLayoutInt nCharChars ) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
もとからあった関数ですけれど、短いですね…。引数を比較しているだけなのでメンバ関数である必要もないようです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ワードラップ(=欧文の禁則処理)で使う関数に_GetKeywordLength()というstatic関数がありましたので、これに倣ってstatic化しておきます。
if( (GetMaxLineLayout() - pWork->nPosX < 2) && (pWork->eKinsokuType == KINSOKU_TYPE_NONE) ) | ||
// 現在位置が行末付近で禁則処理の実行中でないこと | ||
if( ( GetMaxLineLayout() - pWork->nPosX < 2 * GetWidthPerKeta() ) | ||
&& ( pWork->eKinsokuType == KINSOKU_TYPE_NONE ) ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
内側の括弧、なくても意味は同じですね。
除去してほしいという要求ではありません。元からですし…。
return true; | ||
} | ||
break; | ||
if( nRest < nCharKetas ){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この分岐はなくても大丈夫のような気がします。nCharKetas2 が負になり得るのであれば話が変わってきますが…。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
コメントありがとうございます。
たしかに要らないかも知れませんね。
残り1桁分しかない行に2桁分の文字を入れようとしたときに成立しそうですが、nCharKetas2が負数にならない限りはもう一つのif文で対応できそうです。
文字間隔の設定値が負数だったり、WCODE::CalcPxWidthByFont()の戻り値が負数だったりすれば、ここに負数が入ってくるのではないかと。
確認しておきます。
これを削るとこの関数もreturn文だけの関数になってしまいますね。
質問このPRって「内部で扱う水平方向の内部単位をpxに統一したい」であっています? 疑問
もちろん、目先の不具合っぽいものに対応しようぜ!って趣旨であれば、どうあるべきかは横に置いておいてマージ前提で話をすすめていくことに異論はありません。 |
そういう意図はないです。 |
一旦了解しました。 では、どなたか動作確認していただいてコメントつけてもらえれば、自分はapproveで良いと思います。 |
動かしてみました。編集ビュー・印刷プレビューともに正しく動作しているものと思います。 |
編集ビューのみではありますが、変更前後の比較画像を置いておきます。 |
✅ Build sakura 1.0.3460 completed (commit fe4796c935 by @kazasaku) |
恥ずかしながらサクラエディタにこんなワープロソフトばりの機能があることをこれまで意識してませんでした💦 私も動作を見させてもらったところ、折返し位置の手前に絵文字がある状態でその後に行頭禁則文字を置いた時に、カーソル位置や文字挿入がおかしくなることがあったため動画を撮ってみました。 ※ #1543 (comment) の Win32 にて確認しました。 |
suconbu様、お疲れ様です。この機能自体は2002年の春に実装されています(ANSI版の開発掲示板による)。
とりあえず、禁則対象文字の手前がサロゲートペアの場合、CNativeW::GetHabaOfCharが、下位サロゲートに対して0を返すため、IsKinsokuPosHeadは「処理位置ではない」と判断したことが判明しました。 引き続き調査を続けます。 |
個人的には、修正したコードのカバレッジが完全にゼロなのが気になっています。
印刷プレビューの折り返し処理コードを走らせるのは無理にしても、実行させてみない限りは追加した分岐が必要なことを証明できないように思います。 |
プロポーショナル版で幅の計算方式がかわったのに禁則処理が対応していないバグの修正です。
未使用の関数2個(CLayoutMgr::_ExistKinsoku~)も併せて除去した
カーソル位置という表現は正しくなかった。
サロゲートペアは上位側のみ読み取るようにして、折り返し行を描画したときにペアが壊れるのを防ぐ。
仮ですがサロゲートペア対策を入れてみました。 |
✅ Build sakura 1.0.3463 completed (commit 21751d3ed7 by @kazasaku) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
動作確認 #1543 (comment) もしていだだいたので、基本「行き」でよいと思っています。
対応できない種類のCodeSmellsは放置でよいと思っていますが、今回は対応できそうなので修正をお願いしたいです。
[[nodiscard]]
は付けとくべきかな?と思います。
メンバを変更しない関数のconst
も付けとくべきかな?と思います。
カバレッジ=ゼロに関してはどうなんですかね?
一応、「やったほうがいいけど必須ではない」の認識です。
調査と対策ありがとうございました。 |
下位サロゲートを読み飛ばす時は境界チェックもやり直す。
suconbuさん、ご確認ありがとうございました。 余談ですが、MSゴシックでも絵文字の文字幅が全角・半角のどちらでもないということに気が付きました。 |
SonarCloud Quality Gate failed. |
✅ Build sakura 1.0.3466 completed (commit 001679d5e6 by @kazasaku) |
MS ゴシックには絵文字は収録されていないはずですので、フォントフォールバックで絵文字の所だけ Segoe UI Symbol あたりが使われていそうですね。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
指摘するべき問題はなさそうです。
何らかの自動テストは確かにあるべきだと思います。追加タイミングについてはお任せします。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
追加タイミングについてはお任せします。
自分もそれでよいと思います。
皆様、ご確認ありがとうございました。 |
PR の目的
禁則処理が使えない問題を解決します。
カテゴリ
PR の背景
過去に行われたプロポーショナルフォント対応の際、内部で取り扱うレイアウト上の桁数が半角単位からピクセル単位に変更されました。
禁則処理用の関数に対して、これに対応する変更がなされなかったため、条件分岐が正しく判定されなくなっていました。
(※似たような機能で「改行ぶら下げ」がありますが、これは正常に機能しているようです。)
PR のメリット
自明だと思います。
PR のデメリット (トレードオフとかあれば)
仕様・動作説明
patchunicode#1034として登録されているパッチをもとに文字幅の換算処理を追加して、以前と同様に「行末付近でのみ判定を行う」ようにしました。
句読点ぶら下げの時は行末の半角2桁、行頭・行末禁則の時は行末の半角4桁の範囲内に達したときに限り禁則処理の実施判定が行われます。
(この範囲に現在位置にある文字と次位の文字が収まらず、折り返しが発生する時に禁則処理が実施されます。)
また
IsKinsokuPosHead()
及びIsKinsokuPosTail()
は、これまで行の残り桁数と各文字の桁数の組み合わせで判定を行っていましたが、文字幅がピクセル単位の数値となった現在、この方法では正しく判定ができません。そのため、
IsKinsokuPosKuto()
の条件式と同様に文字幅(注:ここでいう文字幅は現在の仕様では文字間隔を含みます)が行の残り幅より大きいかどうかで判定を行うようにし、単位の違いに関わらず判定できるようにしました。そのほか、次の変更を含みます。
const
修飾子の有り/無しが混在していたので有りに統一しました。IsKinsokuPosKuto
関数をヘッダファイルからソースファイル(CLayoutMgr_New.cpp
)に移動しました。_ExistKinsokuHead()
はIsKinsokuHead()
と、_ExistKinsokuKuto()
はIsKinsokuKuto()
と等価です。PR の影響範囲
句読点ぶら下げ・行頭禁則・行末禁則のいずれかが有効になっている環境の次のビュー
テスト内容
比較画像を後で用意しておきます。テスト1:編集ビューにおける禁則処理
テスト2:印刷プレビューにおける禁則処理
補足:禁則対象文字の既定値(タイプ別設定がテキストの時)
、。,.、。,.
!%),.:;?]}\xa2°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢
$([\\{\xa3\xa5‘“〈《「『【〔$([{「£¥
関連 issue, PR
参考資料
patchunicode#1034