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

レイアウト座標を半角単位桁数に戻したい #1645

Closed
4 tasks
ghost opened this issue Apr 25, 2021 · 9 comments
Closed
4 tasks

レイアウト座標を半角単位桁数に戻したい #1645

ghost opened this issue Apr 25, 2021 · 9 comments
Labels
research 実現可能性調査【ChangeLog除外】 specification change ■仕様変更

Comments

@ghost
Copy link

ghost commented Apr 25, 2021

やりたいこと(=実現したいこと)

サクラエディタ内部で扱うドキュメント上の座標単位を半角単位桁と行の組み合わせに戻したい

やりたい理由

  1. 現状のピクセル単位は、その値がフォント設定の影響を受けるため、環境依存となってしまう。
  2. フォント設定と文字・行の間隔を CLayoutMgr と CTextMetrics 双方で処理しなくてはならない。
    • 適用した間隔や文字幅を取得するメソッドも双方にあり、冗長に見えます。
  3. レイアウト作成フローなど、処理の途中でピクセル単位を半角単位桁に換算する必要が発生する。
  4. レイアウト作成フローが DLLSHAREDATA に依存してしまう。
    • 改行のレイアウト幅を 1px とする仕様により、改行コード拡張機能の設定値が必要です。
  5. 位置や座標に関するマクロは、相当する機能を呼び出して処理を行っているため、内部単位の変更がマクロに破壊的な影響を与えている。

解決手段の提案

  • 文字のレイアウト幅を以前と同様に CNativeW::GetKetaOfChar で計算します。
    • CNativeW の静的メンバである GetHabaOfChar 及び GetColmOfChar は不要になります。
      • 文字幅計算の際に DLLSHAREDATA を参照しなくてよくなります。
    • タブ文字やインデントはタイプ別の設定値から適切な桁数を計算してレイアウトに加えます。
  • 文字と行の間隔は CTextMetrics だけで処理します。
    • 設定された間隔やピクセル単位の文字幅は CTextMetrics のメソッドで取得できます。
    • ピクセル単位とレイアウト単位の換算機能は CTextMetrics で提供されています。
  • 当時動作が変更されたマクロ関数を元に戻し、新たにピクセル単位座標を返す関数を追加します。

事前に検討する必要があるもの

  • 内部単位の再定義に伴う取り扱いを検討する

    • 参考案

      データ型 基底 X方向の単位 相当する用語
      CLogicXInt CStrinctInteger wchar_t単位(文字単位) ロジック位置(文字位置)・文字数
      CLogicYInt CStrinctInteger wchar_t単位(文字単位) ロジック位置(行位置)・行数
      CLogicPoint SLogicPoint wchar_t単位(文字単位) ロジック座標
      CLogicRange CRangeBase wchar_t単位(文字単位) ロジック選択範囲(2地点座標)
      CLogicRect CStrictRect wchar_t単位(文字単位) ロジック矩形範囲(4地点座標)
      CLayoutXInt CStrinctInteger 半角単位 レイアウト位置(桁位置)・桁数
      CLayoutYInt CStrinctInteger 半角単位 レイアウト位置(行位置)・行数
      CLayoutPoint SLayoutPoint 半角単位 レイアウト座標
      CLayoutRange CRangeBase 半角単位 レイアウト選択範囲(2地点座標)
      CLayoutRect CStrictRect 半角単位 レイアウト矩形範囲(4地点座標)
      CPixelXInt int ピクセル単位 X方向の描画位置・描画幅
      CPixelYInt int ピクセル単位 Y方向の描画位置・描画高さ
  • 矩形選択を等幅フォントに限定するかを検討する

    • 限定しない場合は、 USE_UNFIXED_FONT ビルドオプションといくつかの共通設定項目が不要となります。
  • 単位換算機能の提供方法を検討する

    • CLayoutMgr 以外にこの機能を提供するクラスとして CViewCalc があり、 CLayoutMgr とは依存関係にあります。
    • CEditView は CViewCalc を継承していますが、これらに「 is-a 関係」は成立しないように思えます。
      class CEditView
      : public CViewCalc //$$ これが親クラスである必要は無いが、このクラスのメソッド呼び出しが多いので、暫定的に親クラスとする。
  • 半角1桁あたりピクセル幅の計算方法を検討する

関連情報

@ghost ghost added research 実現可能性調査【ChangeLog除外】 specification change ■仕様変更 labels Apr 25, 2021
@berryzplus
Copy link
Contributor

文字幅をpx単位で管理してはアカン理由を考察するのに参考とできる挿絵のあるドキュメントを紹介しときます。
https://docs.microsoft.com/en-us/windows/win32/directwrite/glyphs-and-glyph-runs#glyph-metrics

日本語フォントの余白定義はここまで細かくないですが、フォントグリフってのは本来こういうクソ細かいパラメータを持っていることを理解しておいて損はないと思います。(具体的に「だからどーよ。」というのは要らんです。)

@ghost
Copy link
Author

ghost commented Apr 27, 2021

ピクセル単位にもう一つ問題点があることに気が付きました。
#1543 (comment)

余談ですが、MSゴシックでも絵文字の文字幅が全角・半角のどちらでもないということに気が付きました。

MS ゴシックには絵文字は収録されていないはずですので、フォントフォールバックで絵文字の所だけ Segoe UI Symbol あたりが使われていそうですね。
🗻 (U+1F5FB) など全角よりも広くなる文字もあるようです。

フォントフォールバックなどによって文字幅が異なるフォントが混在した場合、1桁あたりピクセル値も複数存在することになるので、桁換算して処理を行っている箇所では結果に影響がありそうです。

@berryzplus
Copy link
Contributor

iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
とか
WWWWWWWWW
とかの表示をどうすべきか、
本当はちゃんと考えたほうが良いんでしょうね。

@ghost
Copy link
Author

ghost commented May 3, 2021

| CLogicXInt | CStrinctInteger | wchar_t単位(文字単位) | ロジック位置(文字位置)・文字数 |
| CLogicYInt | CStrinctInteger | wchar_t単位(文字単位) | ロジック位置(行位置)・行数 |
| CLayoutXInt | CStrinctInteger | 半角単位 | レイアウト位置(桁位置)・桁数 |
| CLayoutYInt | CStrinctInteger | 半角単位 | レイアウト位置(行位置)・行数 |
| CPixelXInt | int | ピクセル単位 | X方向の描画位置・描画幅 |
| CPixelYInt | int | ピクセル単位 | Y方向の描画位置・描画高さ |

縦方向と横方向をデータ型で区別した場合、「この数値は文字数なので~XIntで宣言してください」といったレビュー指摘をしないといけないので、レビュワーの負担が増えそうですね。
#1655 を見てて思いました。)

@ghost
Copy link
Author

ghost commented May 3, 2021

issue とはあまり関係ないですが、空白記号描画( CFigure_HanSpace )もプロポーショナルフォント対応で問題を抱えてしまったみたいです。

半角空白の記号が下半分に英小文字の「 o 」、上半分に空白を使用した合成文字になっていて、それぞれのピクセル単位文字幅が異なるかもしれません。
(全角空白は「全角空白と記号に使う文字の幅が違う場合は独自に描画する」という方法を取るので問題ないです。)

@berryzplus
Copy link
Contributor

縦方向と横方向をデータ型で区別した場合、「この数値は文字数なので~XIntで宣言してください」といったレビュー指摘をしないといけないので、レビュワーの負担が増えそうですね。

意味があるかどうか微妙なんですけど、POINT_TYPEやRECT_TYPEにテンプレートクラスを使えば型の誤りを「コンパイルエラー」にできます。

template<typename POINT_TYPE>
class 点を表す型 : public POINT_TYPE {
  using X_TYPE = decltype(POINT_TYPE::x);
  using Y_TYPE = decltype(POINT_TYPE::y);
public:
  void SetX(X_TYPE);
  void SetY(Y_TYPE);
};

どちらかというと、行・桁の組み合わせを「点」と表現していることも問題な気がします。
行・桁の組み合わせは一般的に「ロケーション」と表現することが多いっす。

class CLocation {
    uint32_t row = 0; //!< 文章先頭からのオフセット行。値域=[0, INT_MAX]
    uint32_t column = 0; //!< 行頭からのオフセット位置。WORD単位。値域=[0, INT_MAX]
};

そういえばx64対応の目標って、4GBを「超える」ファイルを開けるようにする でしたが、なんかそれは違うような気がしてきている、という話をどこにも書いたことがなかったような。

@berryzplus
Copy link
Contributor

半角空白の記号が下半分に英小文字の「 o 」、上半分に空白を使用した合成文字になっていて、それぞれのピクセル単位文字幅が異なるかもしれません。

たぶん文字幅は問題ないと思います。
横方向、文字幅には「半角小文字o」を使うので、大き過ぎたり小さ過ぎたりはしないんでないかと思います。
縦方向、上半分を背景色で塗りつぶす仕様に関して、フォントにより上半分の位置がおかしくなる懸念があります。

Unicodeには、もともとそれっぽい形で定義された文字があるので、それを使うことが対策になるかもしれません。
(この方式だと、選択したフォントにその字形が収録されてるかどうかが課題になるです。)

@ghost
Copy link
Author

ghost commented May 22, 2021

忘れないようにメモしておきます:

  • 対応を行ってCLayoutMgrのタブ幅計算処理を変更した場合、タブ記号描画(CFigure)における描画幅計算処理を見直すこと。

@ghost ghost closed this as completed Jun 2, 2021
@ghost
Copy link
Author

ghost commented Jun 2, 2021

違った。

@ghost ghost reopened this Jun 2, 2021
@ghost ghost closed this as completed May 5, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
research 実現可能性調査【ChangeLog除外】 specification change ■仕様変更
Projects
None yet
Development

No branches or pull requests

1 participant