oov / aviutl_psdtoolkit

PSDToolKit
https://www.nicovideo.jp/series/436
MIT License
114 stars 11 forks source link

字幕準備に `ä` を書くと `a` に変換されてしまう #109

Open oov opened 6 months ago

oov commented 6 months ago

全体の挙動を詳しく追っていないけど、拡張編集側でテキストオブジェクトの文字を Shift_JIS に変換するために WideCharToMultiByte が使われていて、そこで dwFlagsWC_NO_BEST_FIT_CHARS を指定していないのが原因で近い文字への自動変換が走ってしまっているのが直接的な原因と思われる。

テキストオブジェクトで ä はそのまま出力されるが、<?="ä"?> だと a に変換されてしまう。 拡張編集では Lua 上でテキストを扱う際は ACP に変換してから処理される。 この際に変換できなかった文字は拡張編集側で独自に数値参照に置換しているが、 WC_NO_BEST_FIT_CHARS が指定されていないのが原因で、完全一致していない文字が変換されてしまう。

oov commented 6 months ago

PSDToolKit 側での処理も簡単に確認したが、ファイルが投げ込むときは主に

の2つのルートが存在する。 それ以外のツールを使った場合はどうやってドロップしているのかわからないので不明。

自分が実装している範囲ではどちらの場合でも一時的な .exo を作成してドロップしており、 `.exo` には UTF-16 でテキストを埋め込むので、この周辺には特に問題がなさそうに見える。

あとで実際の動作を確認してみる。

oov commented 6 months ago
#include <stdio.h>
#include <windows.h>

int main() {
  enum { BUF_SIZE = 8 };
  char buf[BUF_SIZE];
  wchar_t const src[] = L"ä";
  WideCharToMultiByte(0, 0, src, -1, buf, BUF_SIZE, NULL, NULL);
  printf("%s\n", buf);
  WideCharToMultiByte(0, WC_NO_BEST_FIT_CHARS, src, 1, buf, BUF_SIZE, NULL, NULL);
  printf("%s\n", buf);
  return 0;
}

出力は

$ clang test.c && ./a.exe 
a
?

で、WC_NO_BEST_FIT_CHARS を付けると対応する文字が見つからないので変換に失敗する。 拡張編集では変換に失敗した文字を数値参照に置き換えるはずなので正しく &#228; に変換されるはず。