none
サロゲートペア領域 (Unicode U+10000以上)の文字幅の取得 RRS feed

  • 質問

  •  

    Win32 API(MFC含む)で開発しております。
    サロゲートペア領域 (Unicode U+10000以上)の文字幅を取得する方法をお教えください。
    GetCharWidth32を使って試したのですが、取得に失敗してしまいます。
    メイリオを選択しておいて、Unicode 0x2000bの文字の文字幅を取得しようと

    Code Snippet
    int width;
    BOOL result = GetCharWidth32W(hDC, 0x2000b, 0x2000b, &width);

     

     

    を実行したのですが、resultがFALSEになってしまいます。

    よろしくお願いします。

    2008年5月15日 2:25

すべての返信

  • resultがFALSEになるときのエラーコードは?

     

    0x2000bって文字コードとして間違えていませんか?正しい文字コードを与えていますか?

    UTF-16でサロゲートペアの文字は前半0xD800〜0xDBFF, 後半0xDC00〜0xDFFFで

    構成されているはずなんですけど。

    2008年5月15日 6:48
  •  

    エラーコードは0x00000057
    意味は「パラメータが間違っています。」です。
    文字コードとしてははメイリオに存在する文字です。

    BOOL GetCharWidth32(
      HDC hdc,          // デバイスコンテキストのハンドル
      UINT iFirstChar,  // 文字幅を取得する範囲の先頭文字
      UINT iLastChar,   // 文字幅を取得する範囲の最後の文字
      LPINT lpBuffer    // 文字幅を受け取るバッファ
    );

    GetCharWidth32の引数がUINTなのでUTF-32で指定すると思うので、
    合っていると思うのですが。

    2008年5月15日 7:40
  • http://msdn.microsoft.com/en-us/library/ms534017(VS.85).aspx の Remarks に、 なにやら不吉なことが書いてあるような気がしますが…

     

    GetCharWidth32 cannot be used on TrueType fonts. To retrieve character widths for TrueType fonts, use GetCharABCWidths.

     

    そして、 MSDN Library の Surrogates and Supplementary Characters には、 さらに不吉なことが書いてるように思えます…

     

    Applications that implement their own editing support by working out glyph positions in a customized way can use Uniscribe for all text processing.

     

    ( 追記 ) ニュースグループ microsoft.public.win32.programmer.international で発見。 やはり、 GDI ではサポートしてないので Uniscribe を使え、 とのことです。

     

    Re: UTF16 and GetCharABCWidths()

    GDI does not support supplementary characters, only Uniscribe does. So there
    is no way to use GetCharABCWidths here....

    --

    MichKa [Microsoft]
    Fundamentals Technical Lead
    Windows International

    2008年5月15日 10:15
  •  spike777 さんからの引用

    GetCharWidth32の引数がUINTなのでUTF-32で指定すると思うので、合っていると思うのですが。

    この32は32bitOS向けということを示すので、UTF-32を示すものではありません。

    また、Windowsでは原則UTF-16でUnicode文字を表すため、UTF-32で指定できるAPIは存在しないか、ごくわずかだと考えられます。

     

    ですので、サロゲートペア文字をそのまま渡しても成功することは期待できません。

    2008年5月15日 14:06
    モデレータ
  •  

    biacさんありがとうございます。
    Uniscribeを使ってみました。
    文字幅はScriptGetGlyphABCWidthで取得できるのですが、引数が文字コードでなくグリフインデックスのため、文字コードからグリフインデックスを取得しなければなりません。
    ScriptGetCMapで可能と
    http://msdn.microsoft.com/ja-jp/library/cc448060.aspx
    に記載されているのですが、なぜか取得できません。

    Code Snippet
    WORD gi[2];
    WCHAR wcInChars[2];
    wcInChars[0] = 0xd840;
    wcInChars[1] = 0xdc0b;
    SCRIPT_CACHE sc = NULL;
    HRESULT result = ScriptGetCMap(hDC,
      &sc,
      wcInChars,
      2,
      0,
      gi
    );

     

     


    を実行すると、resultはS_OK、gi[0]は3、gi[1]は3となります。
    どこがいけないのでしょうか?

     

    2008年5月18日 9:29