2015-4-29[水] vs12 で openFramework をちょっと弄る

※追記:間抜けてました。以下は間違い、単にvs12指定してもvs11がinstallしてある環境だとそれが使われてただけの模様(新しいマシンに移行してvs12インストールしなかったらダメだった)

久しぶりに openFramework (のexample)をコンパイルしてみた。 ver0.8.4って vc12(Visual Studio 2013) に対応してたのですね。sln/vcxproj がvc11のものだから、てっきり以前の問題のあるままかと思ってしまってた。

一年程前にvc12で試した時(ver0.8.1|2前後?)は poco 等のc++系ライブラリの .lib のリンクでVCバージョンチェックに引っかかったり諸々エラー出て断念したのだけど(もちろんvc11はok) ... 0.8.4は vc11(2012)の sln/vcxproj をvc12で読み込んで実行できた。 (追記:vs11ないと駄目でした)

で、一つ一つsln開いてコンパイルするのは面倒なので、
  scripts/vs/setupCommandLine.cmd
をテキストエディタで修正、vs11向処理真似てvs12処理を追加すればいいけど、もっと安易に 110 を 120 に全置換するのでもok(当然vs11用処理がなくなる)。scripts/vsフォルダで

setupCommandLine.cmd 120 build both devenv

のように修正したバッチを実行すれば、ひと通りコンパイル出来る。

Drag&Drop example

oF では char文字列は概ね UTF8 扱いになっている。oFが利用しているライブラリの poco とか glfw とかが UTF8 で扱っいて それらに任せてる状態のようだけど。
ただUTF8未対応のライブラリも利用していて freeImage のファイル関係なんかがそれで、このため examples/utils/dragDropExample で、全角混じりのファイル名を drop したら壊れたファイル名になって画像が読み込めない。

正攻法で直すとするとファイル・アクセスはpoco系にまかせてオンメモリ状態のファイルから画像イメージを取り出す形にすればよいのだろうけど... freeImage には wchar_t*ファイル名のAPIも用意されてるので oF 側を修正するのがお手軽な感じ.

ofImage.cpp の template<typename PixelType> static bool loadImage 関数中の

    if(fif == FIF_UNKNOWN) {
        // or guess via filename
        fif = FreeImage_GetFIFFromFilename(fileName.c_str());
    }
    if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
        bmp = FreeImage_Load(fif, fileName.c_str(), 0);

        if (bmp != NULL){
            bLoaded = true;
        }
    }

#ifdef TARGET_WIN32
    extern std::wstring convertNarrowToWide( const std::string& as );
    if(fif == FIF_UNKNOWN) {
        // or guess via filename
        fif = FreeImage_GetFIFFromFilenameU(convertNarrowToWide(fileName).c_str());
    }
    if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
        bmp = FreeImage_LoadU(fif, convertNarrowToWide(fileName).c_str(), 0);

        if (bmp != NULL){
            bLoaded = true;
        }
    }
#else
    略(前記元ソース)
#endif

な感じに修正.
(UTF8->UTF16 変換に convertNarrowToWide を使ったけれど、ヘッダに定義のなく多分static付け忘れかもしれない代物を流用するのはどうよ、とか、c++なのに 関数内でグローバル関数宣言するのどうよ、とか、あるけど とりあえず)

それと、winでのドラッグ&ドロップについては もう一つ問題があって、ドラッグされたファイルのパスのドライブレターが省かれてしまい同一ドライブ以外からのドラッグだとファイルが読めない状態になっている。

これは ofAppGLFWWindow.cpp の 関数 ofAppGLFWWindow::drop_cb の

    for(int i=0; i<(int)drag.files.size(); i++){
        drag.files[i] = Poco::URI(dropString[i]).getPath();
    }

の部分で Poco::URI(dropString[i]).getPath() が ドライブレターを取っ払ってしまうためで、とりあえず アルファベット1文字+':'で始まってたらローカルPC中のパスだろうとして

    for(int i=0; i<(int)drag.files.size(); i++){
#ifdef TARGET_WIN32
       if (isalpha(dropString[i][0]) && dropString[i][1] == ':') {
           drag.files[i] = dropString[i];
           continue;
       }
#endif
       drag.files[i] = Poco::URI(dropString[i]).getPath();
   }

な感じに修正することで 対処可能。

UTF-8 表示

char*はUTF-8だけれど、残念ながら表示については マルチバイト系全滅かもしれない。
ofDrawBitmapString関数 とか ofTrueTypeFont クラスとかの描画処理は char=1文字扱いの単純な処理での描画になっている。TTF処理では UTF-8 を Latin9な文字コードに変換しててハナっから CJKやる気無しな感じ。

元々 oF を vs12 で使いたかったのは(1年前 vs12購入した理由は)

#pragma execution_character_set("utf-8")

で幸せになれそうな気がしたためだけど、画面表示がこれじゃあ...

よく探してないので 別(addonとか)に あるかもしれないけれど。 お仕事でターゲット向けに作ってた文字列表示処理を思えば作れないものでもないだろうけれど。

正直 今は oF 以外に興味行ってるので、このへんで挫折です。