non vorrei lavorare

昔はおもにプログラミングやガジェット系、今は?

WindowsのVimが色付きの絵文字に対応したと聞いてやったがなかなか色がつかなかった件

この記事は@kjunichiの2017年パーソナルアドベントカレンダーの3日目の記事です 。

tl;dr

nmake -f Make_mvc.mak GUI=yes IME=yes MBYTE=yes TERMINAL=yes DIRECTX=yes

背景

TLやVim関連の記事でWindowsVimが色付きの絵文字に対応したと見かけて、 :terminalが対応されたころからvimのビルドを始めたにわかなので、なかなか絵文字に色がつかずにハマった。

絵文字はでるが、色が出ない

既存の設定が悪い?

ひょっとして、大した設定をしていないけど、設定を無効に起動する方法を調べた

gvim -u NONE

でもダメ。

設定やフォントが必要?

github.com

のドキュメントの修正を見て、Rictyフォントが必要なのか?とおもい、

github.com

から、クローンの代わりに、zipでDLして展開してフォントをインストール。

前述のドキュメントのように

set encoding=utf-8
set gfn=Ricty_Diminished:h12
set rop=type:directx

と設定するも、NG。

そもそも、手元の環境で絵文字に色がつくのか

今回Vimで実装されてるDIRECTXによるフォント描画で試している環境で絵文字に色が出るのかすら疑った。

www.wabiapp.com

を見つけ、コピペしたもの、コンパイルエラーがでて、以下のように修正(張り付けたコードは\ではなく、¥になっていて、 その個所と、リンクえーらとなったuser32ライブラリを#pragmaで追加)して ビルド出来、実行できた。無事に絵文字が色付きで表示されたので、環境的には問題なさそうなことが分かった。

#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#include <iostream>
#include <windows.h>
#include <wingdi.h>
#include <d2d1.h>
#include <dwrite.h>
 
 
// define
#ifndef D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT
#define D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT  ( 0x00000004 )
#endif
 
 
// lib
#pragma comment( lib, "d2d1.lib" )
#pragma comment( lib, "dwrite.lib" )
#pragma comment( lib, "user32.lib")  
 
 
/*
    メインウインドウイベント処理
*/
LRESULT CALLBACK eMainWindowProc(
      HWND   hwnd   // handle to window
    , UINT   uMsg   // message identifier
    , WPARAM wParam // first message parameter
    , LPARAM lParam // second message parameter
);
 
 
 
/*
    UTF32をUTF16に変換する
*/
std::wstring UTF32toUTF16
(
    ULONG qUnicode
)
{
    WCHAR waBuf[ 4 ] = { 0 };
 
    if ( 0x10000 > qUnicode ) {
 
        // 0x10000未満
        waBuf[ 0 ] = (WCHAR)qUnicode;
    }
    else {
 
        // 0x10000以上(サロゲートペアにする)
        waBuf[ 0 ] = (WCHAR)( ( qUnicode - 0x10000 ) / 0x400 + 0xd800 );
        waBuf[ 1 ] = (WCHAR)( ( qUnicode - 0x10000 ) % 0x400 + 0xdc00 );
    }
 
    // 処理結果を返す
    return( waBuf );
}
 
 
 
// グローバル変数
ID2D1Factory* pD2d1Factory = NULL;
IDWriteFactory* pDWFactory = NULL;
ID2D1HwndRenderTarget* pRenderTarget = NULL;
 
// 絵文字文字列
std::wstring strEmoji;
 
 
 
/*
    Direct2Dでカラー絵文字を描画
*/
int _tmain
(
      int argc
    , _TCHAR* argv[]
)
{
    // 標準出力にユニコードを表示できるようにする
    setlocale( LC_ALL, "Japanese" );
 
    WNDCLASSEX tWndClass;
    HINSTANCE  hInstance;
    TCHAR*     cpClassName;
    TCHAR*     cpWindowName;
    TCHAR*     cpMenu;
    HWND       hWnd;
    MSG        tMsg;
 
 
    // アプリケーションインスタンス
    hInstance    = ::GetModuleHandle( NULL );
 
    // クラス名称
    cpClassName  = _T("MainWindowClass");
 
    // メニュー
    cpMenu       = MAKEINTRESOURCE( NULL );
 
    // ウインドウ名称
    cpWindowName = _T("Direct2Dでカラー絵文字を描画");
 
    // ウインドウクラスパラメータセット
    tWndClass.cbSize        = sizeof( WNDCLASSEX );
    tWndClass.style         = CS_HREDRAW | CS_VREDRAW;
    tWndClass.lpfnWndProc   = eMainWindowProc;
    tWndClass.cbClsExtra    = 0;    // ::GetClassLong で取得可能なメモリ
    tWndClass.cbWndExtra    = 0;    // ::GetWindowLong で取得可能なメモリ
    tWndClass.hInstance     = hInstance; 
    tWndClass.hIcon         = ::LoadIcon( NULL, IDI_APPLICATION );
    tWndClass.hCursor       = ::LoadCursor( NULL, IDC_ARROW );
    tWndClass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
    tWndClass.lpszMenuName  = cpMenu;
    tWndClass.lpszClassName = cpClassName;
    tWndClass.hIconSm       = NULL;
 
    // ウインドウクラス生成
    if ( 0 == ::RegisterClassEx( &tWndClass ) ) {
 
        /* 失敗 */
        return( -1 );
    }
 
    // ウインドウを生成する
    hWnd = ::CreateWindowEx (
          0                       // extended window style
        , tWndClass.lpszClassName // pointer to registered class name
        , cpWindowName            // pointer to window name
        , WS_OVERLAPPEDWINDOW     // window style
        , CW_USEDEFAULT           // horizontal position of window
        , CW_USEDEFAULT           // vertical position of window
        , 640                     // window width
        , 512                     // window height
        , NULL                    // handle to parent or owner window
        , NULL                    // handle to menu, or child-window identifier
        , hInstance               // handle to application instance
        , (VOID*)0x12345678       // pointer to window-creation data
    );
 
 
    /*
        メッセージループ
    */
    while( 0 != ::GetMessage( &tMsg, NULL, 0, 0 ) ) {
        ::TranslateMessage ( &tMsg );
        ::DispatchMessage ( &tMsg );
    }
 
    // WM_QUITの終了コードを返却する
    return( tMsg.wParam );
}
 
 
 
/*
    メインウインドウイベント処理
*/
LRESULT CALLBACK eMainWindowProc
(
      HWND   hWnd   // handle to window
    , UINT   uMsg   // message identifier
    , WPARAM wParam // first message parameter
    , LPARAM lParam // second message parameter
)
{
    switch( uMsg ) {
    case WM_CREATE:
    //--------------------------------------------
    // WM_CREATE
    //--------------------------------------------
        {
            CREATESTRUCT* tpCreateSt = (CREATESTRUCT*)lParam;
 
            /* パラメータ表示 */
            wprintf(
                L"CREATESTRUCT¥n"
                L"¥tlpCreateParams = 0x%08x\n"
                L"¥thInstance      = 0x%08x\n"
                L"¥thMenu          = 0x%08x\n"
                L"¥thwndParent     = 0x%08x\n"
                L"¥tcy             = %d\n"
                L"¥tcx             = %d\n"
                L"¥ty              = %d\n"
                L"¥tx              = %d\n"
                L"¥tstyle          = 0x%08x\n"
                L"¥tlpszName       = \"%s\"\n"
                L"¥tlpszClass      = \"%s\"\n"
                L"¥tdwExStyle      = 0x%08x\n"
                , tpCreateSt->lpCreateParams
                , tpCreateSt->hInstance
                , tpCreateSt->hMenu
                , tpCreateSt->hwndParent
                , tpCreateSt->cy
                , tpCreateSt->cx
                , tpCreateSt->y
                , tpCreateSt->x
                , tpCreateSt->style
                , tpCreateSt->lpszName
                , tpCreateSt->lpszClass
                , tpCreateSt->dwExStyle
            );
 
            HRESULT hResult = S_OK;
 
            // 絵文字文字列の生成
            for ( ULONG qUnicode = 0x1f300; qUnicode <= 0x1f5ff; qUnicode++ ) {
                strEmoji += UTF32toUTF16( qUnicode );
            }
 
 
            /*
                ID2D1Factoryの生成
            */
            hResult = ::D2D1CreateFactory( D2D1_FACTORY_TYPE_MULTI_THREADED, &pD2d1Factory );
            if ( FAILED( hResult ) ) {
 
                // エラー
                std::wcout << L"D2D1CreateFactory失敗" << std::endl;
                break;
            }
 
 
            /*
                IDWriteFactoryの生成
            */
            hResult = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>( &pDWFactory ) );
            if ( FAILED( hResult ) ) {
 
                // エラー
                std::wcout << L"D2D1CreateFactory失敗" << std::endl;
                break;
            }
 
 
            /*
                ID2D1HwndRenderTargetの生成
            */
            {
                D2D1_SIZE_U oPixelSize = {
                      tpCreateSt->cx
                    , tpCreateSt->cy
                };
 
                D2D1_RENDER_TARGET_PROPERTIES oRenderTargetProperties = D2D1::RenderTargetProperties();
 
                D2D1_HWND_RENDER_TARGET_PROPERTIES oHwndRenderTargetProperties = D2D1::HwndRenderTargetProperties( hWnd, oPixelSize );
 
 
                /*
                    ID2D1HwndRenderTargetの生成
                */
                hResult = pD2d1Factory->CreateHwndRenderTarget(
                          oRenderTargetProperties
                        , oHwndRenderTargetProperties
                        , &pRenderTarget
                    );
                if ( FAILED( hResult ) ) {
 
                    // エラー
                    std::wcout << L"CreateHwndRenderTarget失敗" << std::endl;
                    break;
                }
            }
 
            // ウインドウを表示する
            ::ShowWindow( hWnd, SW_SHOW );
        }
        break;
 
 
    case WM_DESTROY:
    //--------------------------------------------
    // WM_DESTROY
    //--------------------------------------------
        {
            // ID2D1HwndRenderTargetの破棄
            if ( NULL != pRenderTarget )  {
                pRenderTarget->Release();
            }
 
            // IDWriteFactoryの破棄
            if ( NULL != pDWFactory ) {
                pDWFactory->Release();
            }
 
            // ID2D1Factoryの破棄
            if ( NULL != pD2d1Factory )  {
                pD2d1Factory->Release();
            }
            // 終了する( 引数はそのまま終了コードとなります )
            ::PostQuitMessage( 0 );
        }
        break;
 
 
    case WM_SIZE:
    //--------------------------------------------
    // WM_SIZE
    //--------------------------------------------
        {
            D2D1_SIZE_U oPixelSize = { LOWORD( lParam ), HIWORD( lParam ) };
 
            // ターゲットリサイズ
            pRenderTarget->Resize( &oPixelSize );
        }
        break;
 
 
    case WM_ERASEBKGND:
    //--------------------------------------------
    // WM_ERASEBKGND
    //--------------------------------------------
        {
            ;
        }
        return( TRUE );
 
 
    case WM_PAINT:
    //--------------------------------------------
    // WM_PAINT
    //--------------------------------------------
        {
            // ターゲットサイズの取得
            D2D1_SIZE_F oTargetSize = pRenderTarget->GetSize();
 
            // 描画開始
            pRenderTarget->BeginDraw();
 
            // 背景のクリア
            D2D1_COLOR_F oBKColor = { 1.0f, 1.0f, 1.0f, 1.0f };
            pRenderTarget->Clear( oBKColor );
 
 
            /*
                テキストの描画
            */
            {
                /*
                    ブラシの生成
                */
                ID2D1SolidColorBrush* pBrush = NULL;
                {
                    pRenderTarget->CreateSolidColorBrush(
                              D2D1::ColorF( D2D1::ColorF::Black )
                            , &pBrush
                        );
                }
 
 
                /*
                    テキストフォーマットの生成
                */
                IDWriteTextFormat* pTextFormat = NULL;
                {
                    pDWFactory->CreateTextFormat(
                                  L"Meiryo"
                                , NULL
                                , DWRITE_FONT_WEIGHT_NORMAL
                                , DWRITE_FONT_STYLE_NORMAL
                                , DWRITE_FONT_STRETCH_NORMAL
                                , 32
                                , L""
                                ,&pTextFormat
                            );
                }
 
 
                /*
                    テキストの描画
                */
                if ( NULL != pBrush && NULL != pTextFormat ) {
 
                    // テキストの描画
                    pRenderTarget->DrawText(
                              strEmoji.c_str()  // 文字列
                            , strEmoji.size()   // 文字数
                            , pTextFormat
                            , &D2D1::RectF( 0, 0, oTargetSize.width, oTargetSize.height )
                            , pBrush
                            , (D2D1_DRAW_TEXT_OPTIONS)D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT
                        );
                }
 
                // テキストフォーマットの破棄
                pTextFormat->Release();
 
                // ブラシの破棄
                pBrush->Release();
            }
 
            // 描画終了
            pRenderTarget->EndDraw();
        }
        return( FALSE );
    }
 
    // デフォルト処理呼び出し
    return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
}

結局必要だったのは

DIRECTXによる描画にはvimビルド時にDIRECTX=yesの指定が必要だった。

この指定がなかったので、:set rop=type:directxと指定しても無視されて、絵文字に色が出なかった。

nmake -f Make_mvc.mak GUI=yes IME=yes MBYTE=yes TERMINAL=yes DIRECTX=yes

でビルドして、

set encoding=utf-8
set gfn=Ricty_Diminished:h12
set rop=type:directx

として、色付きの絵文字があるテキストを開いたら、無事表示された。

f:id:kjw_junichi:20171203211901p:plain

関連記事

8年前の記事

4年前の記事

3年前の記事

2年前の記事

1年前の記事

1年後の記事

2017東京node学園祭の2日目に行ってきた

この記事は@kjunichiの2017年パーソナルアドベントカレンダーの2日目の記事です 。

背景

東京Node学園祭、今年も奥さんの許可が下りて、2日目に参加できました。昨年、一昨年は午後からの参加でしたが、 今年は2日目のみとはいえ、開始から参加できました。

参加したセッションなど

Angular2+ Authentication Tutorial with Auth0

前段の説明で、Passportを作ったメンバーが中心になって作った会社とのことで、自分もPassportをつかって、 Webベースのツイッタークライアントを自作して使ってるので、なんかすこしAuth0さんに親しみを覚えました。

タイトルはAngularとなっていましたが、当日はAngularではなく、Reactを使うとのことでしたが、 ほとんどReactの話はなかったような。。

ちょっと対象のリポジトリのURLが分からず、手元で、動かしながらお話を聞くことができなかったのと、 そもそも自分の英語力ではすべてを理解できなかった(通訳してくれる方がいたので、日本語では ある程度わかりましたが。。)。

それでも、認証、認可といった機能を外だしして、便利に使える、素晴らしいサービスだということが 分かりました。

自分で何かWebサービスを当てたら、早い段階でこのサービス使いたいと思いましたw。

Sharing is Caring… At Scale!

事前の公式のページには生粋のニューヨーカーと記述あり、これは、超早口の英語のリスニングが ためされる発表と思いきや、滅茶苦茶日本語が流暢でビックリ。

大規模なフロントエンドでのコンポーネント開発をコードの重複なく進めるには、 サンプルを集めたカタログ的なページをデザイナー向けに用意して、この中から使ってもらうように する工夫などが印象に残った。

data sketches: A Visualization a Month

大規模データの可視化のお話。 とんでもない領域を描画していて、パフォーマンスが低下してしまったのを 描画領域を狭めて改善させるといったことが聞けた。

JSON Schema Centralized Design

このお話が、全面的に自分の趣味で参加しているものの、もしかしたらSIer仕事でもWeb寄りの現在の仕事の 延長で、将来使えそうなお話という気がしました。

Real-world applications of hash functions

デンマークの鉄道と、日本の鉄道の比較のスライドが印象に残った。

ハッシュのお話で、WASMまで最後は出てきた。

Code And Learn

Node.js関連ではnode-ffiに以前プルリク出してマージされた経験はありますが、 Node.js本体へプルリクをさすことがこのセッション内で出来ました。 ちょっと不要なファイルをプルリクに含めてしまったり、スタッフの@about_hiroppyさんに gitコマンドでリカばって頂いたりお手数おかけしてしたりと、すんなりは行きませんでしたが、 最終的には無事マージされました!

After party

今年は、まったく知ってる方おらず、困ったなぁと、寿司を頬張りながら、徘徊して、 折角なので、今年も海外のスピーカの方とお話をしようと決め、 流暢な日本語と英語を交互に使ったプレゼンをされた@meyeriniさんに、日本語で声をかけて、 結局終始日本語お話しさせてらいました。

そこで、彼女は昨年日本でNode学園祭をやっていることを知り、昨年、来たかったのだそうですが、 時すでに遅く、1年待って、今年、どうしても日本に来たかったので、3本CFPを出して、その甲斐あって 声がかかり日本に来て発表出来て大変うれしかったとの話を聞くことができました。

また、日本が流暢な理由を尋ねたところ、日本の漫画とくに少女漫画に興味を持ち、そこから日本語を覚え、 上智大学に留学された経験もあるとのことでした。

あと、Node.jsではないですが、Rubyも彼女の口から出てきました。昨年お話した@mafintoshさんとお話したときにもRubyの話題が出てきて、ほんとにRubyは海外でも浸透しているのだなぁと感心しました。

会場の隅に置いてあったホワイトボードにさんのワークショップで話題になったであろうベジェ曲線の 解説らしきものが書いてあるのを眺めていたら、背後から、「○○さんですか?」と声を掛けられ、 振り返ると、見知らぬ方、しかし!一日目のVJをされていた@amagitakayosiさんでした!

blog.gmork.in

実は以前

abrakatabura.hatenablog.com

で記事に書いたように、プルリクを送ったことで、自分のことを覚えていてくれたようで、 会場で私のことを見つけて声をかけて頂けましたのでした。

実は自分も2日目も会場にいらっしているようなツイートを見つけていたので、 @amagitakayosiさんの ことを見つけようとは思ったものの、お会いしたことがないので、なかなかわからずにいたので、 まさか、向こうから声をかけてもらえるとはびっくりでしたが、お会いして、いろいろお話できて本当に良かったです。

おわりに

東京Node学園祭の関係者の皆様、今年も素晴らしいイベントをありがとうございました!

関連記事

Nが現れる素数をJuliaでやってみた

この記事は@kjunichiの2017年パーソナルアドベントカレンダーの1日目の記事です 。

integers.hatenablog.com

これはすごい、どうやってるんだと、パッと見は思った。

swdrsker.hatenablog.com

を読んで、なんとなくJulia言語で試してたくなり、やってみた。

Pkg.add("Primes")
using Primes
cnt=0
isPrime=false
for a in 1:9
    #println("a =", a)
    for b in 0:9      
        for c in 0:9
            for d in 0:9    
                for ee in 0:9
                    for f in 0:9                                   
                        for g in 0:9
                            for h in 0:9                                               
                                for i in [1,3,5,7,9]
                                    str5 =
                                    "ABC000000000000000"*
                                    "005555555555555500"*
                                    "005555555555555500"*
                                    "005555000000000000"*
                                    "005555000000000000"*
                                    "000555555555500000"*
                                    "000555555555555000"*
                                    "000000000000555500"*
                                    "000000000000555500"*
                                    "005555555555555000"*
                                    "005555555555000000"*
                                    "DEF000000000000GHI"
                                    str5=replace(str5,"A",a)
                                    str5 = replace(str5, "B",b)
                                    str5 = replace(str5, "C",c)
                                    str5 = replace(str5, "D",d)
                                    str5 = replace(str5, "E",ee)
                                    str5 = replace(str5, "F",f)
                                    str5 = replace(str5, "G",g)
                                    str5 = replace(str5, "H",h)
                                    str5 = replace(str5, "A",a)
                                    str5 = replace(str5, "I",i)
                                    if isprime(parse(BigInt,str5))
                                        #println(a,b,c,d,ee,f,g,h,i)
                                        println(str5)
                                        isPrime=true
                                        break
                                    end
                                    cnt=cnt+1
                                end
                                if isPrime 
                                    break
                                end
                            end
                            if isPrime 
                                break
                            end
                        end
                        if isPrime 
                            break
                        end
                    end
                    if isPrime 
                         break
                    end
                end
                if isPrime 
                    break
                end
            end
            if isPrime 
                break
            end
        end
        if isPrime 
            break
        end
    end
    if isPrime 
        break
    end
end
#println(cnt)
100000000000000000
005555555555555500
005555555555555500
005555000000000000
005555000000000000
000555555555500000
000555555555555000
000000000000555500
000000000000555500
005555555555555000
005555555555000000
000000000000000437

関連記事

3年前の記事

2年前の記事

1年前の記事