この日記はMozillaのプロダクトへの貢献者としての私の成果を中心に、気になったバグやWeb界隈の話題について書いていますが、 断り書きがある場合を除き、いかなる団体のオフィシャルな見解ではありません。あくまでも個人的なものです。 Mozilla Foundation、Mozilla Corporation、及び関連企業の公式情報ではないことに注意してください。

現在、XHTML 1.0 (もどき)から、HTML5なコンテンツに修正中です。古い日記は修正が完了していませんので表示が崩れます。 順次、修正していく予定ですのでしばらくお待ちください。

もずはっく日記(2010年6月)

2010年6月2日

コーディングスタイルがまた変更 初回投稿日時: 2010年06月02日05時23分05秒
カテゴリ: Firefox Mozilla Core
固定リンク: id=2010060200
SNS: (list)

4月上旬にMDCでコーディングスタイルが

switch (...) {  
  case 1: {  
    // When you need to declare a variable in a switch, put the block in braces  
    int var;  
    break;  
  }  
  case 2:  
    ...  
    break;  
  default:  
    break;  
}  

から

switch (...) {  
case 1: {  
  // When you need to declare a variable in a switch, put the block in braces  
  int var;  
  break;  
}  
case 2:  
  ...  
  break;  
default:  
  break;  
}  

に変更されていて、変なスタイルだなと思ってたんですが、この変更がrevertされ、また元に戻りました。こういうのは勘弁してほしいですね……

Bug 6445 [Win] ATOKでIMEをオンにした直後に文字を入力しようとすると文字がIMEを通さずにダイレクトに入力されることがある 初回投稿日時: 2010年06月02日13時38分25秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2010060201
SNS: (list)

個人的には、悲願だったこのバグ修正にようやく成功しました。

ATOKを半角/全角キーのみでオンにしようとすると、

  1. WM_KEYUP VK_OEM_AUTO
  2. WM_KEYDOWN VK_PROCESSKEY
  3. WM_IME_NOTIFY IMN_PRIVATE
  4. WM_IME_NOTIFY IMN_PRIVATE
  5. WM_IME_NOTIFY IMN_PRIVATE
  6. WM_IME_NOTIFY IMN_SETOPENSTATUS
  7. WM_KEYDOWN VK_PROCESSKEY...
  8. WM_IME_STARTCOMPOSITION

というメッセージの順序で通常は処理されます。ところが、ATOKの起動がディスクスワップ等で遅れると、次に入力したキーが割り込んできて以下のようになります。

  1. WM_KEYUP VK_OEM_AUTO
  2. WM_KEYDOWN VK_PROCESSKEY
  3. WM_IME_NOTIFY IMN_PRIVATE
  4. WM_KEYDOWN VK_A
  5. WM_CHAR 'a'
  6. WM_KEYUP VK_A
  7. WM_IME_NOTIFY IMN_PRIVATE
  8. WM_IME_NOTIFY IMN_PRIVATE
  9. WM_IME_NOTIFY IMN_SETOPENSTATUS

ところが、この現象は普通のアプリでは一切再現しません。Geckoは入力のレスポンス速度を上げるために、キー、IME、マウスのメッセージを優先的に処理しようとするように、メッセージの取得部分が最適化されています。これを無効化すると再現しなくなったので、対応策をずっと考えていました。

つい最近、別のバグで検証している時に初めてVK_PROCESSKEYの存在を知ったのが突破口になりました。IMEを通した入力があった場合、IMEが処理済みのWM_KEYDOWNメッセージにはキーコードにこれが設定されています。つまり、このメッセージが来た場合、通常ならIMEはオンのはずです。しかし、このバグはIMEがオフの間にキーイベントが取り出されるのが問題だったわけです。実際に検証してみると、VK_PROCESSKEYのメッセージが来たときはまだ、ImmGetOpenStatus()FALSEを返してきました。

このことから、VK_PROCESSKEYWM_KEYDOWNを処理する時にIMEがオフのままならATOKの開き始めであると仮定し、WM_IME_NOTIFYIMN_SETOPENSTATUSが来るまでの間、最適化を一時的に中断するようにしました。

ただ、他のIMEがオフの時にVK_PROCESSKEYを送信してこないとも限らないので、想定してないメッセージを受け取った時には最適化処理を再開するようにしています(ここがやや甘い感じもありますので、ご意見があればbugzilla-jpにでもよろしくお願いします)。

この修正により、メモリが少ない環境や、HDDが遅い環境(私の場合、こちらで、なんとHDDの回転数が4200rpm!)のATOKユーザはかなり快適になると思います。

2010年6月8日

またまたkey hell 初回投稿日時: 2010年06月08日23時24分41秒
カテゴリ: Mozilla Core
固定リンク: id=2010060800
SNS: (list)

Qtで呼ばれたものの、Qtってキーボードレイアウトを調査するAPIそのものが無いんでしょうか。もしそうなら、割と致命的。

2010年6月10日

Bug-org 564669 Remove nsIPlaintextEditor::handleKeyPress() 初回投稿日時: 2010年06月10日22時45分26秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2010061000
SNS: (list)

まだ作業は残っていますが、二度目のチェックインに成功しました。

この修正でエディタ(テキスト、HTML両方)のキーハンドリング部分を丸ごと再構成してすっきりとさせています。また、テストを追加し、6000ぐらいの項目で動作確認するようにしています。

2010年6月11日

Qt key hell 初回投稿日時: 2010年06月11日01時36分28秒
カテゴリ: 雑談
固定リンク: id=2010061100
SNS: (list)

Qtのソースコード拾ってきてみたところ、QKeyMapperPrivateというクラスがあって、これでキーコード、もしくはネイティブのキーイベントから入力されるテキストへと変換しているんですが、名前から分かるとおりAPIではありません(そもそもこのクラスのメソッドがXP化されていない)。

また、X11の場合はネイティブイベントを渡さないと処理できないようなので、何らかのAPIからキーイベントを生成して自分で受け取ってテキストを参照する、という手法も使えない様です。

このAPIの不備はスクリーンキーボードを作れないことを意味しています。Macでもさすがにこの辺の泥臭いAPIは用意してくれている(ちなみに10.4まではぼろぼろ)ので、Qtが持っていないのはまったくもって意外でした。GTK(GDK)はちゃんと持ってるんですけど。

X11を直接見に行く、しか手段がなさそうですね。私がやるわけではないんですが。

Re: 「コーディングスタイルがまた変更」って・・・ 初回投稿日時: 2010年06月11日02時08分07秒
最終更新日時: 2010年06月11日02時26分00秒
カテゴリ: Mozilla Core 雑談
固定リンク: id=2010061101
SNS: (list)

整形ぐらいツールでなんとかならんのか、って誰かtwitterで言ってたな、そういえば。まぁそういう考え方もあるかも。

誰の言葉か知りませんけど、非現実的というかそうとう鬱陶しい解決策ですね。

Mozillaの場合、超巨大な変更はツリーをクローズしてからランディングします。なぜかというと、理由は簡単、パッチ形式でのマージなので、どこか一カ所でもrejectされると駄目だからです。

もちろん、そんな超巨大パッチであれば他のパッチのrejectの原因にもなりますが、修正の手間が(分散する分)あまりたいしたことはありませんし、必要な修正なので手作業でのマージにも納得がいきます。

ですが、インデントの修正だけで現在作業中のパッチが軒並みrejectなんかされようものなら、怒号が飛び交うでしょう。それも、議論を尽くさずに長年のスタイルを変更してすぐに元に戻してるんですからなおさらです。

余談ですがGeckoはドキュメント化されていませんが、モジュール毎に独自のコーディングルールをもっていて、ツールで一括変更というのは実は出来ません。

ちなみに私があのコーディングスタイルが変だと思う理由は以下の可能性があるからです。

switch (...) {
case 1: {
  // something
}
}

同じインデントレベルで閉じ括弧のみの行が重なるのはなんか気持ち悪いですし、switchで毎度こうなる訳でもないのがなんかアレですよね。

switch (...) {
  case 1: {
    // something
  }
}

あとは、switchの前後とインデントレベルが一緒なので、switch全体が独立したブロックとして視認しにくかったですね、実際に書いてみると。

  Something1(arg1);
  Something2(arg1, arg2);
  Something3(arg3);
  switch (foo) {
  case VK_A:
  case VK_B:
  case VK_C:
  case VK_D:
  case VK_E:
    Someting4();
    break;
  case VK_F:{
    PRBool dmy;
    Something5(&dmy);
    break;
  }
  default:
    Something6();
    break;
  }
  Someting7(arg4);
  if (IsTrue()) {
    Someting8(arg5, arg6);
  }
  Someting9();

空行入れれば見やすく……と思うかもしれませんが、実際には、caseブロックにも空行出現するかもしれませんので無意味です。これが現行ルールで書くと次のようになって一目でswitchブロックが分かるようになります。

  Something1(arg1);
  Something2(arg1, arg2);
  Something3(arg3);
  switch (foo) {
    case VK_A:
    case VK_B:
    case VK_C:
    case VK_D:
    case VK_E:
      Someting4();
      break;
    case VK_F:{
      PRBool dmy;
      Something5(&dmy);
      break;
    }
    default:
      Something6();
      break;
  }
  Someting7(arg4);
  if (IsTrue()) {
    Someting8(arg5, arg6);
  }
  Someting9();

2010年6月14日

[ITmedia] 「Googleの背景がどんどん変わる」企画、ユーザーからの苦情で早期終了 初回投稿日時: 2010年06月14日13時28分16秒
カテゴリ: News 雑談
固定リンク: id=2010061400
SNS: (list)

時代は変わったので的外れな部分もあるかとは思いますが、そもそもGoogleが当時、すでに市場が成熟していた(と思われた)検索エンジン市場でシェアを急拡大し、もぎとれたのは、検索結果がもちろん良いということもあったんでしょうけれども、今以上に派手だった広告を一切排除し、ともすればシンプルすぎると言われそうなぐらいシンプルなサイトを構築したこと、つまりユーザのことを第一に(?)考えた部分が少なからずあったのではないかなと思います。数年後には予想通り収益のために広告が検索結果に表示されるようになりましたが、それも極力目障りにならないようにするという配慮が見られました。

ですが、今回のは一日だけのキャンペーンとはいえ、このシンプルで目立たないサービスの提供という、昔からのGoogleユーザに好まれた路線を見失い、自分たちが排除した派手すぎる広告と同じことを、それ以上に目立つ形でユーザに押しつけた結果がこれなのかなと思うと複雑です。

もちろん、当時に比べてユーザの幅が広がっていますから、機能自体を好む人は少なからず居るでしょう。ですので宣伝の仕方以外は好ましい変化だと思うのですが。

Bug-org 550434 Clicking in an empty contenteditable element that has focus causes the caret to disappear 初回投稿日時: 2010年06月14日16時11分55秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2010061401
SNS: (list)

大きさを指定した(?)、空のブロックレベルの要素をcontenteditableのホストにすると、二回目以降にクリックした際にキャレットが消えてしまうというバグです。

元々はEhsanがエディタ側で修正したのですが、どう見ても場当たり的で良い方法をとっておらず、またこのあたりを別バグのためにリファクタリングしてるこちらの設計を大きく潰してしまうので根本的な原因を調べて、元のパッチをバックアウトし、根本的な修正を入れました。

問題なのはエディタではなく、選択範囲のコードで、nsIFrame::GetContentOffsetsFromPoint()から返ってきた値をそのまま引数に受け取ると、矛盾を感じるようになっていました。

理由はよく分からないのですが、空のブロック内の座標をnsIFrame::GetContentOffsetsFromPoint()に渡すと、特殊なケースとしてこのブロック全体を選択した状態の範囲が返されるようになっていました。エディタはフォーカスを受け取ったときに選択範囲の限界をそのエディタのルートに設定します。contenteditableの場合、フォーカスを受け取ったホスト要素、つまりこのケースの場合空のブロック要素になります。ところが、次にこの空のブロックをクリックした時にnsIFrame::GetContentOffsetsFromPoint()は、ブロック全体の範囲を返してしまうため、この範囲の示す要素はホストの親になってしまいます(つまり、限界を超えた要素)。このため、選択範囲は矛盾を発見し、選択範囲の限界をリセット、選択範囲を全て削除、という処理に逃げていました。このため、閉じられた選択範囲を視覚化しているキャレットが消えてしまう、ということになっていたのです。

選択範囲のあり方として、ブロック全体を選択することもあるので、nsIFrame::GetContentOffsetsFromPoint()の戻り値を受け取る側を修正するのは不可能です。このため、nsIFrame::GetContentOffsetsFromPoint()自体を修正するしかないと思いました。しかし、nsIFrame::GetContentOffsetsFromPoint()は非常に多くの場所で利用されているのでどのような処理にまで流用されているのか想像もできません。そこで、最小限の修正に抑えることにしました。

もし、指定された座標が空のボックスだった場合、それが編集可能な場合には新しいフラグと共に、その内部の範囲を返すようにしました。編集可能な場合、やはり空のブロック内にも新しくテキストを挿入することが十分に考えられますので、この動作で問題はないはずです。また、この新しいフラグのおかげで、必要なら受けとった側が修正前と同じ値を取得することもできるようになっていますのでregressionがあったとしても簡単に対応できるようにはなっています。

2010年6月16日

Bug 6694 [Cocoa] IMEの未確定文字列があるまま、Firefoxの別のウインドウに切り替えても、未確定文字列が確定されない 初回投稿日時: 2010年06月16日02時55分04秒
カテゴリ: Mozilla Core
固定リンク: id=2010061600
SNS: (list)

ようやく修正完了しました。

この修正以前はどこでキーイベントを生成しても常に(アプリケーションレベルで)フォーカスを持っている要素へ伝達されていましたが、これからはそのイベントが発生したトップレベルウインドウ内で最後にフォーカスを持っていた要素へ伝達されるようになります。この変更により影響を受けるアドオンはよほど特殊な要求のもの以外は無いと思います。

ちなみにこの修正により、Bug-org 497839のような自動テストを作成することが可能になっています。

mqが使えない 初回投稿日時: 2010年06月16日13時29分16秒
カテゴリ: Mozilla Core 雑談
固定リンク: id=2010061601
SNS: (list)

MDCでは利用を推奨してる感じなんですが、mqの保存しているデータが脆すぎて酷いです。たとえばqcommitの最中にabortするとそのまま復旧不能になりました。無責任にもhg recoverしろ、と言ってくるのですが、当然、大本のhg側はそんなの知らない、と突っぱねてきます。また、なぜか突然"no queue repository"とのたまうようになって何もできなくなったり。

ファイルの追加とかがあるとやや面倒ですが、hgコマンドを直接叩いて同じようなことをやるほうがよほど安全なようです。

2010年6月18日

Bug-org 570455 Editor shouldn't do anything when ESC key is pressed because bug 471322 was marked as WONTFIX 初回投稿日時: 2010年06月18日15時28分33秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2010061800
SNS: (list)

昔のGeckoや、IEはエディタでESCキーを押すとフォーカスをエディタにあわせた時点にまで戻す機能がありました(あります)が、この機能、Geckoでは完全にWONTFIXとなりました。このため、それに絡んでいたと思われるコードを削除しました。

2010年6月19日

Bug-org 541316 "inputmethod" keyword is needed for IME related bugs 初回投稿日時: 2010年06月19日12時25分43秒
カテゴリ: Bugzilla-org バグ修正
固定リンク: id=2010061900
SNS: (list)

検索しにくいことで有名な(?)IME関係のバグにつけるキーワードを作ってもらいました。

IMEを文字列として検索してしまうと、MIMEや、timeもひっかかって来たり、Linux系のユーザの報告だとIMになってて、Instant Messengerと見分けがつかなかったり、Mac系のユーザの報告だとIMの他に、TSMがあったり、はたまた、問題のあったIMEの名前を直接書いていたりと、単語として検索しにくすぎました。

FIXEDと、オープンなバグで発見したものについては全てにinputmethodキーワードを付加しました。もし、他にあれば自分で追加するなり、権限が無い場合は私をCCに入れてinputmethodキーワードの追加を促してください。

Bug-org 545775 Text editor in ASUS Forum doesn't work. 初回投稿日時: 2010年06月19日22時45分16秒
最終更新日時: 2010年06月19日22時53分21秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2010061901
SNS: (list)

ASUSのフォーラムでテキストを入力できない、というバグです。

URL欄にテストケースを入れていますが、見やすく整形すると次のようになります。

<script>
  function load() {
    var editorDocument =
      document.getElementById("editor").contentDocument;
    editorDocument.designMode = "On";
    editorDocument.open();
    editorDocument.write("<html><body></body></html>");
    editorDocument.close();
  }
</script>
<body onload="load();">
  <iframe src="about:blank" id="editor"></iframe>
</body>

desginModeが有効になった時点で、nsHTMLEditorがドキュメントに生成されます。このときにその時点でのbody要素がエディタ内でキャッシュされます。その後、document.write()でそのbody要素が置き換えられるのですが、この時に新しいbody要素へリセットがうまくできていませんでした。

このバグ修正で色々と見つけた問題を同時に修正してるので、初回のチェックインだけで5つのパッチに分割しなくてはいけなくなりました。

2010年6月20日

Bug-org 572969 [SeaMonkey][OSX] Mochitest-3 test_htmleditor_keyevent_handling.html has 96 (perma)failures 初回投稿日時: 2010年06月20日17時50分02秒
カテゴリ: Mozilla Core SeaMonkey バグ修正
固定リンク: id=2010062000
SNS: (list)

SeaMonkeyでは私の追加したテストが96項目で失敗する、というバグでした。

詳しい原因は分かりませんが、Mac版のSeaMonkeyはエディタにイベントが来る前に、Ctrl+Tabを処理していない様です。私の作ったテストが良くなくて、SeaMonkeyの存在やFxの将来のバージョンでの変更を加味していなかったため、Captureフェイズでイベントが消費済みかどうかを決め打ちで検査していました。

対策としてcaptureフェイズでは検査を行わないようにし、captureフェイズで消費済みではなかった場合にはエディタがイベントを期待通り消費するか(もしくは消費しないか)を検査するように修正しています。

2010年6月23日

Bug-org 519974 When we use IME, ASSERTION is printed at each key input (ASSERTION: nsEditor doesn't support wide caret: 'selectionStart == selectionEnd', editor/libeditor/base/IMETextTxn.cpp line 322 初回投稿日時: 2010年06月23日16時05分33秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2010062300
SNS: (list)

Macでデバッグビルド作ると、IMEの入力中にassertionが出まくる、というバグです。cocoaのwidget側のただのミスで、別のバグの邪魔になるのでリファクタリングを待たずに修正しました。

Bug-org 569988 Thunderbird mozmill test: test_escape_rules failing following bug 564669 landing on trunk (Remove nsIPlaintextEditor::handleKeyPress()) 初回投稿日時: 2010年06月23日16時08分37秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2010062301
SNS: (list)

Bug-org 564669のregressionで、すでにバグ自体は修正していましたが、追加で自動テストを入れました。ただし、Linuxではランダムに失敗する可能性があるとのことです。

2010年6月29日

Re: Firefox 4のTabs on Topを受け入れられないのは頭が硬直化している証拠 初回投稿日時: 2010年06月29日12時09分35秒
最終更新日時: 2010年06月29日12時13分01秒
カテゴリ: Firefox 雑談
固定リンク: id=2010062900
SNS: (list)

慣れの問題だとは自分でも思いますが、Tabs on Topは個人的には気持ち悪いデザインです。ですが、UIチームの主張通り、彼らの主張する理屈では整理されていて、合理的だというのは賛成できますし、新規ユーザにとってはタブがどちらにあっても新たに学習することなので違いは無いと思います。

ですが、前々から気になっているこの主張だけはどうしても不自然に思えます(他の主張にはそんなに反対ではないことに注意してください)。

タブをクリックしたら、タブの上にあるナビゲーションバーの内容と、タブの下にあるコンテンツ領域の内容が変わる。

タブというUIの原形であると思われる、現実のバインダーを想像してみてください。

私の考えでは、タブというのはアクティブなコンテンツを切り替えるためのUIです。それに対して、ツールバーの中身のボタンは鉛筆や消しゴムといった、コンテンツを操作するためのものだと考えています(ロケーションバーのように、内容を示すものと入力とを兼ね備えた不思議なUIをここで論じると話がややこしいので、ひとまず置いておきましょう)。

この考えだと、上記の主張は、各タブごとにそこを編集する鉛筆や消しゴムが備えつけられているべきであるという主張に聞こえないでしょうか?

つまり、私の考えでは、ツールバー内のUIというのはその機能は普遍であり、タブが切り替わったところで何も変わらないということです。

実際に起きているのは、タブが切り替わることによって、その対象が切り替わっているだけです。つまり、タブの中にツールが存在するという概念が私の中ではあり得ない理屈です。

そして現に、ツールバーのボタンはタブの中身以外を操作できてしまいます。たとえば、戻るボタンを中クリックすると、ひとつ前のページが新しい(つまり別のタブ)で開かれます。再読込ボタン、ホームボタンに関しても同様です。ロケーションバーや検索バーもAlt+Enterで新しいタブへコンテンツを開くことができます。

このため、私は上記主張は結論ありきの理屈だと思いますが、みなさんの感覚ではどうなんでしょうか。個人的には気になるところです。

Re: Firefox 4のTabs on Topを受け入れられないのは頭が硬直化している証拠 #2 初回投稿日時: 2010年06月29日14時17分47秒
最終更新日時: 2010年06月29日14時18分09秒
カテゴリ: Firefox 雑談
固定リンク: id=2010062901
SNS: (list)

そして、今までの物を覚えるのに苦労した分だけ「またあんな苦労をして新しく覚え直さなきゃならないのかよ!」と言いたくもなるだろうが、それは杞憂だ。Tabs on Topな新しいUIは、今までの物を覚えるのに要した時間よりもっと短い時間で慣れる事ができる。何故なら、今までタブを使った事がなくてもそのはたらきが見た目で分かる、そういう所を目指したデザインなんだから。

もうひとつだけ気になったので。追記しておきます。

この主張は人間は常に考えて行動を決定している、という間違えた前提にたっていると思います。人間が常に考えて行動をおこしているのであれば、うっかりミスなんて起こりえるんでしょうか?

実際には、思い込みや、癖や、反射といった思考を端折って行動を起こしていることが多いと思います。例えば赤信号を見たときにいちいち赤だから止まらないと、と判断しているでしょうか? 左折可だったり、変則的な交差点で矢印信号が出たのに赤信号だから止まったまま、という車をよく見かけますが、こういうのって思考すべきことを端折って、赤なのでとりあえず止まる、青になったら発進しよう、という習慣だけで停止しているからじゃないんでしょうか。このような、「つい間違える」というのがUIの変更後には多発するでしょう。そしてそれはストレス要因になると思います。

学習済みの内容より合理的なことは再学習しやすいっていうのは大嘘だと断言しても良いのではないでしょうか。一度ついた癖を取り除くコストは場合によっては新規学習よりも高くはないですか? みなさんは自分の(悪い)癖をすべて抑制して生活できていますか?

Bug-org 574908 [DW] Bitmap glyph is ignored when the font-style is italic or oblique 初回投稿日時: 2010年06月29日14時52分04秒
カテゴリ: Mozilla Core バグ報告
固定リンク: id=2010062903
SNS: (list)

ビットマップグリフをもつフォントを斜体にすると、DirectWriteではアンチエイリアスを使ってレンダリングされてしまう、というバグです。

単体で見ると、ジャギー感がなくて良い感じなんですが、文中で一部分だけが突然アンチエイリアスがかかるとやはり不自然なので報告しました。同じくDirectWriteを使っているIE9ではどうなのでしょうか?

Bug-org 574907 [DW] Don't use subpixel positioning for bitmap glyphs 初回投稿日時: 2010年06月29日14時57分38秒
カテゴリ: Mozilla Core バグ報告
固定リンク: id=2010062904
SNS: (list)

DirectWriteではビットマップグリフをもつフォントも、おそらくベクターグリフの情報から各文字ごとのメトリクスを取得できます。このため、レンダリング時にサブピクセルを利用しないビットマップグリフが、サブピクセルを意識したメトリクスに基づいて配置されてしまい、文字同士がくっつく、という問題です。

CSSでは継承や相対サイズ指定が可能なことから、フォントサイズが小数になるのは日常茶飯事です。現在のままでは多くのサイトで文字同士がくっついて表示されていて非情に見づらくなっています。

ビットマップグリフでレンダリングされることが分かっている場合にはCSSの算出値を四捨五入した値でDirectWriteにメトリクスを問い合わせなくてはいけないと思います。が、それが可能かどうかは知りません。

Bug-org 574909 [DW] Bitmap glyph is ignored when opacity isn't 1 初回投稿日時: 2010年06月29日15時00分18秒
カテゴリ: Mozilla Core バグ報告
固定リンク: id=2010062905
SNS: (list)

DirectWriteでビットマップグリフを持つフォントを半透明で描画するとき、なぜかビットマップグリフが無視されてアンチエイリアスがかかる、というバグです。

やはり特定の要素でのみフォントの見た目が大きく変わってしまうのが不自然なので良くないと思います。