最終更新: 2013-06-11T17:42+0900
https://sourceforge.net/p/sakura-editor/patchunicode/482/
これは期待せざるをえない。でもこれは、何がいけなかったんだろう。
trunk2>svn revert -R . trunk2>svn up -r 2954 (サクラエディタで trunk2_directwrite.patchを、改行をCRLFに統一して、保存し直し) trunk2>patch -p0 < trunk2_directwrite.patch (VS2008EEで sakura/sakura.slnを開く。Release_Unicodeでリビルド)
1.起動してファイルを開いた直後。[EOF]マークが残ってる。日本語文字に半角サイズしか割り当てられてないのはウチの環境のせい(Consolas+Meiryoで GDIが全角文字を半角で描画するせいで全角半角判定(GDI依存)と DirectWriteによる描画が食い違ってる)。
自分でもやってるけど目に見えて遅くなるから@2013-05-26常用はしてない。関連(古い順)>20110423、20120201(参考画像豊富)、20120205、20120707、20121018。DirectWriteをハンコにして得られるメリットは縦方向のアンチエイリアスがかけられることかなあ。GDI+ClearTypeでも横方向のサブピクセルレンダリングはやってるから、フォントと OS次第ではそれ以外に差が出ない。サクラエディタではサブピクセル単位での字間調整に意味がないという個別の事情もあるし。
フォントは相変わらず Consolas+Meiryoなんだけど、日本語にきちんと全角幅が割り当てられてるのが不思議。
曲線を観察するに縦方向のアンチエイリアスがかかってない気がする。それでは Consolas+Meiryo+ClearTypeに比して DirectWriteのアドバンテージがない。
早々に気にすることではないかも知れませんが、この二つの適切な呼び分けは難しくないですか?
HRESULT DWriteContext::SetLOGFONT(const LOGFONTW &logFont, float fontSize); void DWriteContext::SetFont (const LOGFONTW &logFont);
ひょっとして上の2つと下の1つは副作用を伴う一連の不可分な処理を3分割したもので、入れ替えたり飛ばしたりできないものだったりするのでしょうか?
void DWriteContext::SetFont(HFONT hFont, bool bold, bool underline)
それから、DWriteContext::SetFont(HFONT hFont, bool bold, bool underline) の hFontにも太字・下線情報が含まれますが、CEditView_Paint.cppでこのように
HFONT hFont = GetFontset().ChooseFontHandle(false, false); DWriteContext_SetFont(s_dwc, hFont, info.m_bFatFont, info.m_bUnderLine);
あえて無視する(無視させる)理由についても、想像がつかないもので、知っておきたいと思うのですが、教えてもらえますか?
デジャヴを感じるコメントの流れだ。
>DirectWriteで描画したい · Issue #262 · vim-jp/issues · GitHub
そんで、すぐ上の疑問に関して。たぶん novice123さんはここまで読んでいない(手が回っていない)。
koron commented 4 months ago
最新版ではGetObject()を使ってHFONTからLOGFONTを取得することで、必要なときに DWriteContext_SetFont() するように変更しました。合わせて太字と斜体の有無は、DrawTextの引数ではなくフォントの情報を利用するように変更しました。
しっかし、個別問題に対処するパッチがいくつか見られるだけでさっぱりコードの全貌が追いかけられん。リンク切れも多すぎる。
ピクセルジオメトリはダイアログで設定するものでも、できるものでもないと思う。マルチモニタ。デバッグモード?
あんまり PPDとか理解してないけど結果オーライ(※自分の環境限定)で、こんな感じでやってた。(static_cast<int>(f)って int(f)って書けるんかなあ)
STDMETHODIMP DWGdiTextRenderer::DrawUnderline( __maybenull void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, __in DWRITE_UNDERLINE const* underline, IUnknown* clientDrawingEffect ) { HDC hdcRT = pRenderTarget_->GetMemoryDC(); FLOAT ppd = pRenderTarget_->GetPixelsPerDip(); RECT rcUnderline = {static_cast<int>(baselineOriginX*ppd), static_cast<int>((baselineOriginY+underline->offset)*ppd), static_cast<int>((baselineOriginX+underline->width)*ppd)+1, static_cast<int>((baselineOriginY+underline->offset+underline->thickness)*ppd)+1}; HBRUSH hBrush = CreateSolidBrush(GetTextColor(hdcRT)); FillRect(hdcRT, &rcUnderline, hBrush); DeleteObject(hBrush); return S_OK; }
なんでペンでなくブラシなんでしょうねえ。思い出せないからもう一度考えてみると、ペンの場合、線の太さが、始点と終点で示される線分に対してどう影響するのかが不明だったからだろう。線がどのように太るのかが。例えば幅2ピクセルの水平線を引く場合、線の始点・終点の Y座標に大小どちらを指定すべきだろう? その点 RECTで領域を指定して塗りつぶせるブラシは結果がピクセル単位で予想できる。
COMのところの2、3項目しか読んでなかったけど、常識レベルの基礎が身につく良いシリーズだったのだね。DirectWriteの APIドキュメントを読んでると出てくる DIPについても書いてあった。
DirectWriteのサンプルプログラムがそうで、自分のも同じように AddRefがなかったことに、コメントした後で気付いたんだけど、
ds14050 2013-05-01
QueryInterfaceが正常に返る前に AddRefしておかなくていいのでしょうか?
この疑問に対して同シリーズのこれは無関係ではないのではないか。
hr = pFileOpen->QueryInterface(IID_IFileDialogCustomize, reinterpret_cast<void**>(&pCustom)); if (SUCCEEDED(hr)) { // インターフェイスを使用する (省略) // ... pCustom->Release(); } else { // エラーを処理する }通常どおり、戻り値 HRESULT をチェックしてメソッドの失敗に備えます。メソッドが成功した場合、ポインターを使用し終えた時点で Release を呼び出す必要があります。詳細については、「オブジェクトの有効期間を管理する」を参照してください。
あと、キャストせずに thisを代入して返してるけど、どういうキャストの場合に thisが変化するか熟知してない自分には不安なコード。
「QueryInterface キャスト」で検索した。そうそう、こういう懸念、
既に示したQueryInterfaceの問題点は、どのようなインターフェースが渡されてもオブジェクトのアドレスをそのまま返した点です。 このとき、適切なインターフェースでオブジェクトをキャストしていれば、 インターフェースのvptrは適切なvtblを識別するようになります。
サクラエディタで実装する、IDWriteTextRendererを継承した GdiTextRendererに真っ当な QueryInterfaceや、InterlockedIncrement/InterlockedDecrementを使った AddRef/Releaseが必要かといえばいらないんだろうけど(だから動いてる)、ざる実装でも構いはしないんだけど、一見それっぽいのはミスリーディングでよろしくない(問題があるとして、ね)。
寝る前の3時間でやっつけた!(つもりになってるだけで返り討ち……とか)。
どういう思考をたどったのか、地震(※震源は前住んでたとこだ)に揺れる風呂場で気がついた。まだバージョン管理されていない新ファイル3つがパッチに含まれていなかった。サイズが半分になってるのは小さすぎると思ったんだ。以前指摘されたのと同じミス。
https://sourceforge.net/p/sakura-editor/patchunicode/482/?limit=20#c9f7
無意味な(そう見える@2013-05-27)関数分割(20130501p01.02.01)によって
という問題に対処した点は汲んでもらえなかったようだ。Cインターフェイスという名の、DWriteContextの opaqueポインタ読み方(ハンドル)を操作する限られた関数群をとっぱらって、DWriteContextクラス自体をモジュールの外へエクスポートしたことで事態はさらに悪化した。
クラスっていうのは内にも外にも過度の依存性/コンテクスト/癒着をもたらすのだなあ。どれだけ良い点、Cからの改善点を並べようと一部のクソのために C++を忌避するという選択は理解できる。
あ、エクスポートにあたって private化はされてました。トラップは対外的には隠されていたし、呼び出し階層が明確になっていた。でも DirectWrite/DirectX系の定数をモジュールの外から隠せてない。レンダリングパラメータを int, floatと変換関数のセットで再定義してる意味がない。
チケットが pendingされてしまいました。遅いのは vim-jpが DirectWriteをオプション扱いにする理由として挙げていてわかっていたことだし、描画方法と描画先を両方とも GDIから Direct2Dに完全移行できれば改善が期待できるし、遅くても試したい人はいっぱいいたと思うのになあ。
互換インターフェイスを C++で定義するならヘッダに書く内容は DWriteContextそのままではなくこんなんになると思う。
class DirectWrite { public: static DirectWrite* Init(); DrawText(); SetFont(); SetRenderingParam(); ... //< Initと対になる後片付け関数。 private: DirectWrite(); // 呼ばせない。代わりに Init(). //< たぶんコピーコンストラクタも禁止しないといけない。 //< ポインタメンバがあるので代入演算子も禁止しないといけない。 struct DataMember; DataMember* m; };
ポリモーフィズムが必要なわけでないしファクトリメソッドの代わりにコンストラクタでもいいのかも。それでもこっそりメンバの追加はできるだろうし。
Sakura Editor / PatchUnicode / #588 文字列を一度にExtTextOutで描画する
ただ口を開けて待ってたわけではなかったんだよ(いいわけ)。「ところで、DispTextって文字の数だけ呼ばれるんだけど、こんなんを仮想関数にしても良いものだろうか。9か月前の自分はできるだけ長い GLYPH_RUNを対象にすることで回数を減らそうとしてたみたいだけど(20120201)」と書いていた自分はというと、CEditView_Paint.cppの似たような所をいじるまではやっていて、そこから、どいつにどうやって一挙に文字を書き出させるのが(どこでどこまで決めるのが)いいんだろう?というところで停止していた。
@2013-05-26 もしかしたら違う理由かも。過去の日記を読む限りでは、べらぼうに遅い→まあまあ遅い→まともな速度、と2段の変化があったようで、2段階で改善したことは記憶してなかったから。表示品質があまり変わらなかったのと細かい詰めを放り投げた結果として常用してないのかも。
@2013-05-27 SetFontと SetFontに関しては同じ機能を提供しつつ、LOGFONT版でなく HFONT版を呼んだときには、前回の HFONTとの比較結果次第で以降の処理を省略する意図がありそう。みみっちい。ポインタ/ハンドルを比較してその先の値が同じかどうかわかるかいな。そんな目的のためだけにメンバ変数を増やしますか。しかし、効くのだろうか。自分のパッチでは std::basic_string<TCHAR>を毎回作って lfFaceNameの比較をしていた。手を抜きすぎだとは思う。
読み方 オゥペイクだってさ。オパックだと思ってたよ。思い込みは恐いよ。
最終更新: 2013-05-02T16:45+0900
830 :名無しさん@お腹いっぱい。:2013/04/30(火) 13:45:27.36 ID:ph+iG0mE0 >>829 これってブロックコメントの色付け方法が変更されるの?違う? 完全に閉じたときのみに色変更してほしいんだが……。 現在の仕様のブロックコメント開始文字列があったらただちに色変更されるのは、(他人の)jsコード見るとき非常に困る。
>>830 829で指摘した変更は単なる最適化を目的としたものだよ。 >現在の仕様のブロックコメント開始文字列があったらただちに これは ANSI板からの仕様みたいだし、自分としても、画面内の 情報だけに頼って色分けできたほうがどんなファイルを開いた場 合でも軽くていいと思う。対かっこ強調などもそういう割り切り が多いよ。
せっかくこの日記に書いてるのだし、SHJS方式にも言及しておくと、あれでもやっぱり行末を超えた時点で、コメント終了マークが存在しなくても、コメント開始が確定してしまう。その取り消しを可能にするのがバックトラック版(20090808p01)なんだけど、あれができるのは Web上に載せるコード片が対象だからっていうのがある。IDEでもそれは許されるだろうけど、テキストエディタではどうだろう。バックグラウンドで色分けスレッドを走らせて非同期に画面上の文字の色を変えていくというのは可能だろうけど、わずかなラグ(ちらつき)が気になったりするだろうね。非同期だけど一瞬だけは待つことにして大体の場合は同期的に見えるというのだと、いいのかな? Operaだったか、ページの描画待ち時間を指定できたけど、あれはそういう意味だったのか。
予想外の展開。未完成の .jsに対する色分けかと思っていたら、XPathを表現した文字列に含まれる /* をコメント開始と誤認識するってな話だった。
832 :名無しさん@お腹いっぱい。:2013/04/30(火) 18:48:43.80 ID:ph+iG0mE0 >>831 ?……そのプログラムって何を指すの?サクラ側の実行プログラムのこと? 例に挙げたjs(JavaScript)のこと? jsでは「/*~*/」がブロックコメントという扱いだけど、「/*」の文字列はXPathなどコード上記述されることがままある。 このとき「*/」が以降のコードのどこかに記されてない限りコメント色が付いたまま。 だけどjsの実行上は問題ない。あくまで視認の問題。他人のコードを読むときに困ってるんだ。
正規表現キーワードでは回避できないんだよね。既知の不具合です>サクラエディタBBS[7020]
掲示板のこのやりとりが 20090808p03のきっかけだった。自分では今でも使ってるんだけど、性能がときどき問題になる。バイナリファイル(=改行が少ない)を開いて検索したときに顕著。
もやもやするって書いちゃった(20130425)けど、このパッチ(#431 PHPヒアドキュメント/C++ RowString/C# quoted String等対応)が適用されたら、文字列の色分けを正規表現キーワードから組み込みのものにまた任せることができるし、それで解決すると思う。ただし、正規表現リテラルの中の /* は解決しない。
834 :名無しさん@お腹いっぱい。:2013/05/02(木) 05:53:25.17 ID:8gLFxXSe0 正規表現リテラルとか、htmlやphpみたいな文脈による言語変更とかを考えだすと限界があるんだよな・・・ vimのシンタックスエンジンを組み込みたい。あれかなり強力だし
どんなのだろうと検索したら見つかった。>syntax - vimdoc-ja< 難しすぎるでしょ。特定のキーワード(containとか contained)がフラットな記述に構造を与えてて余計に難しいってのもあるけど。
♭ もかスクリーンショット拝見しました。ExtTextOutのETO_OPAQUEようするに"背景を塗りつぶす"に相当する処..
♭ ds14050背景画像を指定したスクリーンショットもとってみました。確かに仰るとおりでした。(novice123さんが背景画像を指..