試しに組み込んでみました。
とりあえず表示されます程度のレベルです。
フォントを大きめにすると違いが分かると思います。
コンパイル方法は下記の通りです。
・FEAT_DIRECTXを定義
・ソリューションエクスプローラのuipartsフォルダにgui_dwrite.cppとgui_dwrite.hを登録
参考にしたもの
http://www.kaoriya.net/blog/2013/03/24/
https://github.com/vim-jp/issues/issues/337
http://bitbucket.org/k_takata/vim-win32-mq/src/68749ecfe8a41912db1f8fe3e66e5724b32bad73/patch-direct_write-r3d.diff
期待しています!
とりあえず、FEAT_DIRECTXが定義されていないと CNormalProcess.cppで directx_enabledが見つからなくてエラーになりました。
自分の環境ではスクロールしたり最小化したりしたり何をしてもゴミが残ります。何がいけないのでしょうね。trunk2@2954+trunk2_directwrite.patch、VS2008EE、Vista(64-bit)、フォントの種類にかかわらず同様です。
QueryInterfaceが正常に返る前に AddRefしておかなくていいのでしょうか?
・FEAT_DIRECTXが定義あり/なしどらでもコンパイルが通るようにしました。
FEAT_DIRECTXが定義ありでコンパイルしてもDirectWriteに未対応OS(WindowsXP)はGDIでの動作になります。
・背景画像あり/なしどちらでもそれなりに表示されるようにしました。
背景画像なしのときは、FillRectで背景色塗りつぶしをします。
・フォントの太字/下線
CGraphicsクラスのフォントpush/popに追従できていないので、フォント切り替えができていません。
・フォントの太字/下線
CGraphicsクラスのフォントpush/popに対応しました。下線は未対応です。
[EOF]の表示もDirectWriteに対応しました。
・共通設定-DirectWrite
DirectWriteのパラメータを設定できるようにしました。
sakura.iniファイルには保存しません。
ソリューションエクスプローラのpropフォルダにCPropComDirectWrite.cppを登録
Last edit: novice123 2013-05-04
・共通設定-DirectWrite
設定が反映されていなかったので修正しました。
忘れそうなので、調査内容をまとめます。
・下線
vimは、DiretWrite有効時でもフォントの下線が表示されます。
元となるvimのソースコード(gui_w32.c)を見たのですが、
フォントの下線は、MoveToEx()-LineTo()で描画してるようです(DirectWriteに関係なく)。
サクラエディタは下線ありのフォントを使用していますが、DrawUnderlineが未実装なので
自分で実装する必要があります。
・描画速度
DirectWriteで描画すると明らかに遅く感じました。
1文字描画するたびにDWriteContext_DrawText()を呼び出しているのでオーバーヘッドが大きいのが原因なのではないかと思います。
なるべく同じ属性の文字をまとめて描画できるようになれば改善できるかもしれません(GDI、DirectWrite共に)。
・下線
MoveToEx()-LineTo()で描画しています。
・画面分割
画面分割時に描画されるように対応しました。
Last edit: novice123 2013-05-18
下線の有無は HFONTから LOGFONTを取得しても、HDCから TEXTMETRICを取得してもわかりますが、それは利用しませんか?
現在 DWriteContext::DrawText で常に textLayout->SetUnderline(TRUE, textRange); していますが、ここに常に TRUEではなく適切なフラグをセットして GdiTextRenderer::DrawUnderline を実装する方が、下線付きフォントをセットするだけのサクラエディタの現在のやり方に対応していてやりやすいのではないかと思います。参考までに。
提案された内容のpatchを登録して頂ければ、検討してみます。
よろしくお願い致します。
trunk2_directwrite_d.patchをあてた trunk2@3032をベースに変更を加えました。添付パッチは r3032からの差分です。
sakuraディレクトリ以下への変更は novice123さんのパッチと条件が異なり意図しない修正が含まれていますので注意してください。1.VS2008EEが読み込んだことによるもの。2.uiparts/gui_dwrite.{h|cpp}をプロジェクトに追加した結果。3.FEAT_DIRECTXを定義した結果。4.Release_Unicodeにデバッグ情報を含めるなどが含まれます。あてない方がいいかもしれません。
デグレードがあれば修正します。
###
TODOに斜体のオーバーハングを入れておいてください。流麗なフォントほど右上が欠けます。
Last edit: ds14050 2013-05-19
まだバージョン管理されていない3ファイルの差分を含む完全なパッチです。詳細は先のコメントを参照してください。
確認してみました。
(1)フォントサイズのみ変更した場合に画面描画に反映されないようです。
(2)MoveToEx()-LineTo()と比較すると描画時間が若干遅いようです。
(3)hdcからGetTextColorで色情報を取得していますが、もしかしたらこの手は使えなくなるかもしれません。
DirectWriteのみで描画できれば、SetTextColor()の呼び出しが不要になります。
斜体フォントが欠ける件は、1文字描画から同じ属性の文字をまとめて描画するようにすればかなり改善できると思います(現状のANSI版の実装)。
ただし、DirectWriteより難易度が高いのではないかと思います。
今後の予定です。
(1)フォント設定をするときにHFONTではなくLOGFONTを渡す。
(2)太字、下線の設定はHFONTではなくそのまま渡す。
DirectWriteのみで描画できれば、SelectObject()の呼び出しが不要になります。
詳細な検討ありがとうございます。
(1)に関して。DWriteContext::SetFontでの比較条件を拡大して TextFormatの再作成をケチらなければ対応できます。ほかの属性(太さ・斜体・下線)と同じ場所で同じように IDWriteTextLayout->SetFontSizeすることでも対応できますが、これは LOGFONTWの値から変換が必要な場合があり計算結果のキャッシュが必要になるのが難です。しかし、LOGFONTW.lfHeightの値が必ず負数になるように正規化しておくと計算は符号の反転だけにできます。
(2)に関して。GdiTextRenderer::DrawUnderlineの中身は FillRectでも LineToでもかまいません。余計なことをしましたが、GdiTextRenderer::DrawUnderlineの中で線を引きませんかという提案でした。
(3)に関して。GDIの先を見すえた視点はありませんでした。CGraphicsに文字の色を設定し、それが HDCに変換され、DWriteContext::DrawTextに渡されるという現在の枠組みのみを考えた選択でした。
今後の予定(1)に関して。GDIに結びついた HFONTではなく LOGFONTを媒体にするのは賛成です。
今後の予定(2)は「そのまま」の意味を掴みかねました。LOGFONTを通してということであればよいのですが。
Last edit: ds14050 2013-05-25
更新しました。
(1)フォント設定をするときにHFONTではなくLOGFONTを渡す。
初期化時とフォント変更時にCEditWnd::UpdateDirectWrite()でフォント情報を設定するようにしました。
(2)太字、下線の設定はHFONTではなくそのまま渡す。
タイプ別の色指定情報は、太字&下線の情報をColorInfo構造体で管理しているので、メンバ変数の値をそのまま渡すようにしました。
LOGFONTで情報を保持していないのでこの方法がいいのではと思いました。
DirectWriteのみで描画できれば、SelectObject()の呼び出しが不要になります(HFONTの管理不要)。
(3)C->CPP変換関数(DWriteContext_)は削除。
vimはCで記述されているのでこのような実装になっていると思うのですが、サクラエディタでは不要でした。
(4)DWriteContextの生成を4個から1個にする。
画面分割時の描画処理は途中で切り替わらないのと状態を保持する必要がなさそうなので、共有しても問題なさそうです。
GdiTextRenderer::DrawUnderline()の反映は次回までお待ちください。
現状のMoveToEx()-LineTo()での実装よりスマートだと思います。
AddRefの件はよく分かってないのでしばらく保留させてください。
DirectWite描画時にSetTextColor/SetBkColor/SelectObjectの呼び出しを省略してみましたが、GDIとDirectWriteの描画時間の差は埋まりませんでした。
DirectWriteの前に、1文字描画を改善する必要がありそうです。
描画時間を短縮できそうな方法が思い浮かばないこともあり、一度pendingさせてください。
ご期待に応えられずに申し訳ありません。
Last edit: novice123 2013-05-26
つ[directwrite_e+ブロック毎描画]
BugsInfo.txt先頭44行描画(画面キャッシュを使う)
MeiryoKe_Console/win7による
directwrite:60回 1240ms
GDI:60回 940ms
文字間隔の設定反映の実装はまだです。(adjustToCellとその周辺)
文字幅計算はどうすればいいかわからず。Consolasだと文字幅計算が合わなくてだめです。
こんな感じですがどうでしょうか。
・描画時間
自分のPCで確認してみました。
実行環境が異なるので相対比での描画時間になりますが
(1)1文字描画
DirectWrite:GDI=3.5:1
(2)ブロック毎描画
DirectWrite:GDI=0.6:0.3
になりました。
DirectWriteの描画時間がかなり改善されました。
描画時間の問題は解決できているのではと思います。
http://msdn.microsoft.com/ja-jp/library/windows/desktop/dd372260%28v=vs.85%29.aspx
"GDI との相互運用性: 頻繁な切り替えを避ける"とあるので、このあたりが改善に寄与していそうです。
・MeiryoKe_Console
このあたりの話と同じような気がします。
http://www.maruo.co.jp/turukame/3/x06456_.html
・ブロック毎描画
別途実装中でした。描画時間は同じぐらいです。
テキスト以外(TAB、空白)もブロック毎描画できるように対応中ですが、変更量は多くなりそうです。
Last edit: novice123 2013-06-18
・MeiryoKe_Console
MeiryoKe_Consoleは問題ないようです。
Consolesのときです。
サクラの文字幅計算はGDIなので、Consolesにない文字はプロポーショナルフォントで描画されて、
size.cx<=m_han_size.cx の条件で半角になるので
「ッリう」等がGDIでは半角判定になったりして、うまく幅を合わせられずにいます。
DirectWriteの描画のときは、なぜかアウトラインフォントになって、FLOAT値なので。
あと、Consolesのとき、「アルファベット漢字交じりのとき」と「アルファベットだけの時」で
後者の場合、1px上に描画されるという謎もあります。
・MeiryoKe_Console
こちらの環境だと表示されない文字があったので勘違いしていました。すみません。
・Consolas
http://www.microsoft.com/typography/fonts/font.aspx?FMID=1924
フォント情報をみると日本語が含まれていないので、Fontlinkで代用していると思うのですが(メイリオ?)、等幅メイリオ+Consolasのようなフォントを作る必要があるのではと思います。
このあたりの話と同じような気がします。
http://www.maruo.co.jp/hidesoft/2/x30449_.html
Last edit: novice123 2013-06-17
とりあえず、最新対応的な何かです。
ところで、vimのソースのライセンスってどうなるの?
TODO:
・DirectWrite関係をDLLに分離する
・斜体、取り消し線対応
・設定の読み書きはあるが、設定をDirectWriteに渡すコードがない
・FontLinkミスマッチ問題。特にプロポーショナルフォント版で幅が合わなくて困る
GPLだと思いますので、
その点からもDLLに分離したほうがよさそうですが、
DirectWriteの部分はサンプルプログラムをベースに作れば
問題ないのではないかと思います。
http://msdn.microsoft.com/ja-jp/library/windows/desktop/dd941793%28v=vs.85%29.aspx