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

DirectWriteで描画したい #262

Closed
koron opened this issue Sep 30, 2012 · 182 comments
Closed

DirectWriteで描画したい #262

koron opened this issue Sep 30, 2012 · 182 comments

Comments

@koron
Copy link
Member

koron commented Sep 30, 2012

GDIで描画している場合、最近の(ビットマップを含まない)TTFを小サイズで表示するとヒドイことになる。

DirectWriteならばそれを回避できるのではないか?

課題

  • enc=utf-8以外の対応 → ドロップ予定
  • featureでon/offできるように
  • optionでon/offできるように
  • XP等でも起動できるように動的ロード
  • ドキュメント
  • 太字と斜体がでない
  • guifontwide への対応

追加課題

  • オプション名を変えたい。antialiasはちょっと不自然だし、分離したい。directx にした
  • Vim本体からみた発動条件を揃えたい。いまは p_antialias と s_dwc の両方を見ているところと、前者しか見ていないところが混在している。メンテを考えると好ましくない。IS_ENABLE_DIRECTX() マクロに集約した
@ghost ghost assigned koron Sep 30, 2012
@koron
Copy link
Member Author

koron commented Sep 30, 2012

https://gist.github.com/3806748

作ってみた。フォントはRictyの9pt固定でenc=utf-8の時しか動作しない。とりあえず描画をみる目的。いろいろオカシイところは多いがとりあえずの作。

結果できたのはこんなもの。

sample

上がパッチによるDirectDrawで、下は素のGDI。かなり良くなったと思うがどうだろう。

@thinca
Copy link
Member

thinca commented Sep 30, 2012

おお、すごい。いいですね。

@k-takata
Copy link
Member

これの最新版は
https://bitbucket.org/koron/vim-kaoriya-vim-mq-ex/src/9590c788e7dda64e16b8f13147d817c078ec890b/patch-direct_write.diff
でしょうか。

試してみたところ、いくつか問題があったので追加パッチを作りました。
https://gist.github.com/4502153

  1. MinGW-w64 でビルドできるように修正
    Make_ming.mak, Make_cyg.makの修正、GdiTextRendererのデストラクタの宣言修正、SAL注釈の修正
  2. GetUserDefaultLocaleName()がコンパイルエラーにならないようにWINVERを変更
  3. GdiTextRendererが解放されず、リソースリークが起きていたのを修正
    AddRef()の呼び出しを追加
  4. センタリングされているために、文字が変な位置に表示されるのを修正

フォントサイズによっては、文字幅の計算に誤差が出ているようで、表示位置がずれたり表示されない文字があったりします。

@koron
Copy link
Member Author

koron commented Jan 10, 2013

Thanks!

@koron
Copy link
Member Author

koron commented Jan 10, 2013

@k-takata マージしました。ありがとうございます。

ところで WINVER とかなのですが、
とりあえず __MINGW32__ の時だけやるように変更しました。
あれらはMakefileから指定して
(windows.hを使ってる)全ソースに同じ値を指定したほうが良い
と考えたからです。

ちなみに私のビルドではnmake実行時に明示的に指定しています。

0x0600より小さかったら#pragma errorとかで
コンパイルエラーに落とすのが良いかもしれません。
もしくはMakefile内で自動的に0x600以上を設定するとか。

で、そのあたりMinGWについて検討してもらえると助かります。

@koron
Copy link
Member Author

koron commented Jan 10, 2013

…自分で書いておいてなんだけど、ちゃんとguifontに追従するようになってたんだ…忘れてた。

@koron
Copy link
Member Author

koron commented Jan 10, 2013

フォントサイズによっては、文字幅の計算に誤差が出ているようで、表示位置がずれたり表示されない文字があったりします。

これなんですが 1.5 の倍数のサイズを指定するとうまくいくかも。
昔からそうなんでw

@k-takata
Copy link
Member

ちなみに私のビルドではnmake実行時に明示的に指定しています。

VCでビルドしたときも(無指定だったので)エラーになっていたので入れたのですが、そういうことでしたら
VC, MinGWともに、WINVER < 0x0600 だったら、#error でコンパイルエラーにするのが良いと思います。
(DirectWriteを動的ロードするようにするなら、WINVERはどうでもよくなるはずですが…)

@Shougo
Copy link
Member

Shougo commented Jan 11, 2013

DirectWrite対応したVimをぜひ使ってみたいので、私も試してみようかなと思っています。

@koron
Copy link
Member Author

koron commented Jan 11, 2013

あとでexeだけどっかに上げますよ。

@koron
Copy link
Member Author

koron commented Jan 11, 2013

http://www.kaoriya.net/blog/2013/01/11 で案内しているようにとりあえず現状版をビルド&公開しました。
ダウンロードはこっち→ http://files.kaoriya.net/var/vim73-kaoriya-dw96a-20130111.zip

安定させてくれた @k-takata さんのおかげです。ありがとうございます!

@Shougo
Copy link
Member

Shougo commented Jan 11, 2013

ありがとうございます。試してみたら感想を書き込みます。安定して動作するなら、ぜひ本家にパッチを送りたいですね。

@k-takata
Copy link
Member

せっかくビルドしていただいたところで申し訳ありませんが、追加パッチですw
https://gist.github.com/4511170

  1. WINVER周りの修正
  2. 縦方向の位置をセンタリングに戻す
    'guifontwide'を指定した場合、 英字と日本語の配置がこれが一番良さそう。
  3. wrapping無しに設定
    'ambiwidth'が実際のフォントの幅と合っていない場合などに、改行されて変な表示になることがあったので改行しないように変更。
  4. convertLOGFONT()でフォント名を正しく変換できていなかったのを修正
    デバッグプリントを入れたら全く表示されなくなったりして、何事かと思ったら末尾のNUL文字が変換されていませんでした。
  5. CreateTextLayout()ではなく、CreateGdiCompatibleTextLayout()を使うように修正
    レイアウトのずれが(ほぼ)無くなったはず。
  6. COMを使っているので、CoInitialize()しておくべき?

欧文フォントに日本語フォントをフォントリンクした場合に表示がずれることがあるようです。

@k-takata
Copy link
Member

動作が安定するようになれば、残課題は以下のようなところでしょうか。

  1. enc=utf-8以外の対応
  2. featureでon/offできるように
  3. optionでon/offできるように
  4. XP等でも起動できるように動的ロード
  5. ドキュメント

あと、Vimのコーディングスタイルに合わせるために、:set noetして:retab!した方がいいのかな?

@k-takata
Copy link
Member

set guifont=Ricty_Diminished:h11 がまだずれてる。

@k-takata
Copy link
Member

'guifontwide'が効いていない予感。DirectWriteが勝手に他のフォントからグリフを持ってきている?

@koron
Copy link
Member Author

koron commented Jan 12, 2013

@k-takata Thanks!

フォントは小数点以下の誤差が蓄積するんだと思われます。1.5ptの倍数だとその誤差が生じない。
なのでスクリーンのDPIをいじってるとまた変わってくるかも、と推測しています。

@koron
Copy link
Member Author

koron commented Jan 12, 2013

@k-takata とりこみました。 https://bitbucket.org/koron/vim-kaoriya-vim-mq-ex/commits/5107000e9a7e82cadd3330389dccbb90

以下2点修正の上:

  • Co*の呼び出し位置を外側にした
  • エラーメッセージの文言にキーワードDirectWriteを追加

@koron
Copy link
Member Author

koron commented Jan 12, 2013

あと、Vimのコーディングスタイルに合わせるために、:set noetして:retab!した方がいいのかな?

Done

@koron
Copy link
Member Author

koron commented Jan 12, 2013

featureでon/offできるように

Done

@koron
Copy link
Member Author

koron commented Jan 12, 2013

feature 化はMSVC だけやったんで MinGWとCygwinの対応はお願いします。 m(_ _)m

@k-takata
Copy link
Member

USE_DIRECT_Xになっていますが、FEAT_*にして:verで確認できるようにした方がいいのかなと思ったり。
typo発見しました。

diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -311,7 +311,7 @@
 DIRECTX_DEFS   = -DUSE_DIRECT_X
 DIRECTX_INCL   = gui_dwrite.h
 DIRECTX_LIB    = d2d1.lib dwrite.lib
-DIREXTX_OBJ    = $(OUTDIR)\gui_dwrite.obj
+DIRECTX_OBJ    = $(OUTDIR)\gui_dwrite.obj
 !endif
 !endif

@@ -650,7 +650,7 @@
 !if "$(GUI)" == "yes" && "$(DIRECTX)" == "yes"
 CFLAGS = $(CFLAGS) $(DIRECTX_DEFS)
 GUI_INCL = $(GUI_INCL) $(DIRECTX_INCL)
-GUI_OBJ = $(GUI_OBJ) $(DIREXTX_OBJ)
+GUI_OBJ = $(GUI_OBJ) $(DIRECTX_OBJ)
 GUI_LIB = $(DIRECTX_LIB) $(GUI_LIB)
 !endif

@koron
Copy link
Member Author

koron commented Jan 12, 2013

typo の件と、:versionで表示される内容の件、及びhas()の対応をしときました。

マクロ名は USE_DIRECT_X のままです。こんなのは最後に変えれば良いので。

@k-takata
Copy link
Member

Make_ming.mak, Make_cyg.mak を更新しました。
https://gist.github.com/4516132
±directx はWindowsの場合だけ表示するようにした方がよいのではないでしょうか。

なお、Cygwin上でも mingw64-i686-gcc-g++ パッケージをインストールすれば、

$ make -f Make_ming.mak CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ DIRECTX=yes

でビルドできることに数日前に気づいて、Make_cyg.makの存在意義に大いに疑問を感じているところです。
Make_cyg.makには、USEDLL=yesにするとcygwin1.dllを使う機能があるようですが壊れているようですし…。

@Shougo
Copy link
Member

Shougo commented Jan 12, 2013

Kaoriyaさんところで配布されているバイナリで試してみました。
アナウンスの通り、1.5ptの倍数でないと描画がおかしくなりますね。表示されない文字が出てくる。
Windowsデフォルトの状態よりはかなりよくなっているような気がしますが、
個人的には、もうちょっとアンチエイリアスがかかっているほうが好みだったり。
(このあたりはどうやって調整すればいいんだろう……)

@Shougo
Copy link
Member

Shougo commented Jan 12, 2013

Direct Writeに対応している秀丸エディタは、かなり細かく表示を調整できるみたいなので

http://hide.maruo.co.jp/software/hidemaru810/index.html

これくらい調整できると素晴らしいと思います。

こういう情報もありますね。

http://ymkn.hatenablog.com/entry/2012/08/31/134814

@k-takata
Copy link
Member

CreateRenderingParams()CreateCustomRenderingParams() に変えれば調整できるようです。

自分の環境だと、デフォルト値は以下のようになっていました。
gamma=1.8, enhancedContrast=0.5, clearTypeLevel=0.5, pixelGeometry=DWRITE_PIXEL_GEOMETRY_RGB, renderingMode=DWRITE_RENDERING_MODE_DEFAULT

@Shougo
Copy link
Member

Shougo commented Jan 12, 2013

そのデフォルト値って、コントロールパネルで指定できるClearTypeの設定でセットされるんですかね?

@k-takata
Copy link
Member

そんな設定があったんですね。知りませんでした。
(それで設定できそうな感じはしますが。)

@kyouryuukunn
Copy link

kaoriyaさんで配っているrev. bを使っているんですが、
斜体で行の最後尾の半角文字が切れる問題は既知ですか?
sample2
sample1

使用フォント
set guifont=Ricty:h12:cSHIFTJIS

@koron
Copy link
Member Author

koron commented Feb 1, 2013

@kyouryuukunn 既知です。描画範囲の都合で回避方法がないと考えられますが…
ちょっと検討してみたい所ではありますね。

@k-takata どうですかね。なにかアイデアありますか?

@koron
Copy link
Member Author

koron commented Feb 1, 2013

関係ないけど、RenderingParamsをオプション経由で取得したり設定したりしたい。
JSONみたいな構造をオプションで簡単に使うにはどうしたら良いだろう?

簡単なのは f_eval() 叩いちゃうことかもだけど、あまりに残念になる。

@k-takata
Copy link
Member

k-takata commented Feb 1, 2013

斜体が欠けるのはDWだけでなくGDIでも起きていますね。
行末だけでなく、カーソルを1文字ずつ右に動かすと、文字幅から右にはみ出た分が次のカーソルを書いた時点で上書きされて消されてしまいます。
本体の修正が必要ではないでしょうか。どう直すべきか全く見当がついていませんが。

もっかいだけパッチ更新しましょう。

その際は、ソースのヘッダコメントを付けておいた方がよいかと。

@koron
Copy link
Member Author

koron commented Feb 1, 2013

その際は、ソースのヘッダコメントを付けておいた方がよいかと。

kwsk

@k-takata
Copy link
Member

k-takata commented Feb 1, 2013

単にこれのことです。(何というのが正しいのか知りませんが。)

/* vi:set ts=8 sts=4 sw=4:
 *
 * VIM - Vi IMproved        by Bram Moolenaar
 *
 * Do ":help uganda"  in Vim to read copying and usage conditions.
 * Do ":help credits" in Vim to see a list of people who contributed.
 * See README.txt for an overview of the Vim source code.
 */

@koron
Copy link
Member Author

koron commented Feb 1, 2013

OK把握。

でもそれはBramが最後に(リリースするときに)付けたほうが良い、かも。
少なくとも私の方からは…modelineとLICENSEだけは明記しとこう。

@mattn
Copy link
Member

mattn commented Feb 1, 2013

コードの100%が、 @koron & @k-takata なのだったら if_xxx みたいに連名していいと思うよ。

@koron
Copy link
Member Author

koron commented Feb 1, 2013

とあるクラスがMSのサンプルの丸パクリ+独自修正かな。

まぁ、Authorは書いとくか。

@koron
Copy link
Member Author

koron commented Feb 1, 2013

それよかオプションのパースに使える共通関数が少なくて泣ける。

@koron
Copy link
Member Author

koron commented Feb 1, 2013

patch-direct_write-ex1.diff で、DirectWriteをONにするオプションを変えました。
renderingoptions (短縮名 renopt) にしました。

オンにするには次のようにします:

:set renopt=type:directx

オフにするにはこうしてください:

:set renopt=

レンダリングパラメータを設定することもできるようにしました:

:set renopt=type:directx,mode:5
:set renopt=type:directx,gamma:2.2,mode:3

renopt のパラメータ部分の正式な書式はこんな感じです:

type:directx(,{name}:{value})*

設定可能なパラメータは以下のとおりです:

* gamma: gamma, float
* contrast: enhancedContrast, float
* level: clearTypeLevel, float, 
* geom: pixelGeometry, int, 有効な値:0-2
* mode: renderingMode, 有効な値:0-6

各パラメータの意味詳細は この辺 を見てください。
順序は関係ありません。
省略したパラメータはデフォルトのものが使われます。

@koron
Copy link
Member Author

koron commented Feb 1, 2013

明朝にでもバイナリ作って試験公開してみます。

@thinca
Copy link
Member

thinca commented Feb 1, 2013

一瞬明朝フォントかと思った。

@koron
Copy link
Member Author

koron commented Feb 1, 2013

@thinca かかったな! w

@thinca
Copy link
Member

thinca commented Feb 1, 2013

なんという罠!

@koron
Copy link
Member Author

koron commented Feb 1, 2013

明朝にでもバイナリ作って試験公開してみます。

ヒャッハー! 我慢できねぇ!

@k-takata
Copy link
Member

k-takata commented Feb 2, 2013

gui_mch_set_rendering_options の宣言は .pro に移した方が良いのでは?
https://gist.github.com/4695841

@koron
Copy link
Member Author

koron commented Feb 2, 2013

@k-takata Thanks! でもそれは「最終的に本家でマージする時のタスク」として放置します。

そもそも今の場所にあの関数が書いてある事自体、順序的にはよろしくないでしょう。
今下手に.proに入れちゃうと、そのdiffを本家版に適用することとかいろいろ考えなきゃいけないことが増えてしまいます。

@Shougo
Copy link
Member

Shougo commented Feb 2, 2013

最新版のバイナリを試してみました。初期状態だと微妙ですが、レンダリングオプションを変更することで、かなり良い感じになることを確認しました。これなら、私もデフォルトで使用するかもしれません。

@k-takata
Copy link
Member

k-takata commented Feb 7, 2013

option.c から gui_mch_set_rendering_options() を呼び出す部分で、gui.in_use のチェックがあるために、
.gvimrc の中で :set renopt=type:directx としても、値だけ設定されて実際には DirectWrite が有効になりません。
gui.in_use のチェックは不要ではないでしょうか。

あと、gui_mch_set_rendering_options() の中のコメントが Dire x tWrite になっています。

@k-takata
Copy link
Member

7.3.821, 823 で patch-direct_write.diff にコンフリクトが発生するようになったので修正しました。
https://bitbucket.org/k_takata/vim-win32-mq/src/a8d212b10d6692a72f769fcb652f14c4c7f6b83e/patch-direct_write.diff?at=default

@k-takata
Copy link
Member

patch-direct_write-ex1.diff に 'renopt' のドキュメントが含まれていなかったので書きました。3つ上の修正パッチもマージ済みです。
https://bitbucket.org/k_takata/vim-win32-mq/src/c49b6eba550b7d92c90b1dd9f094f1d9cd1b81ce/patch-direct_write-ex1.diff?at=default

@koron
Copy link
Member Author

koron commented Mar 24, 2013

option.c から gui_mch_set_rendering_options() を呼び出す部分で、gui.in_use のチェックがあるために、
.gvimrc の中で :set renopt=type:directx としても、値だけ設定されて実際には DirectWrite が有効になりません。
gui.in_use のチェックは不要ではないでしょうか。

本件は gui_mch_init()gui_mch_set_rendering_options() を呼ぶようにします。

@koron
Copy link
Member Author

koron commented Mar 24, 2013

#337 にて仕上げ作業に入るので、本スレは閉じます。

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

7 participants