ぬの部屋(仮)
nu-no-he-ya
  •      12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • stbライブラリでtruetypeフォントをラスタライズ(2)

    まず、前回とほぼ同じプログラムで、下記( ※ )部分を「、」などの文字に変更する。

    //参考
    //https://gist.github.com/cloudwu/766bccc60c254f9cc2abfa397bcff2ea
    
    #include<windows.h>
    #include <tchar.h>
    
    #include <cstdio>
    
    #define STB_TRUETYPE_IMPLEMENTATION
    #define STBTT_STATIC
    
    #include "stb_truetype.h"
    
    // utf8文字コードをコードポイントに変換
    unsigned int utf8_decode(const char* o);
    
    // フォントで文字を描画した画像を作成
    void drawfontchar(unsigned int f);
    
    unsigned char* pixels = nullptr; //画素の格納先
    int iwidth; //画像サイズの格納先
    int iheight;
    
    
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
      HDC hdc;
      PAINTSTRUCT ps;
      switch (msg) {
      case WM_DESTROY:
        //画像の破棄
        delete[] pixels;
    
    
        PostQuitMessage(0);
        return 0;
      case WM_PAINT://画面に表示
        hdc = BeginPaint(hwnd, &ps);
        if (pixels != nullptr) {
          RECT rect;
          GetClientRect(hwnd, &rect);
          FillRect(hdc, &rect, (HBRUSH)GetStockObject(GRAY_BRUSH));
    
          for (int y = 0; y < iheight; y++) {
            for (int x = 0; x < iwidth; x++) {
              unsigned char r = pixels[y * iwidth + x];
              if (r == 0)
                SetPixel(hdc, x, y, RGB(255, 0, 0));
              else
                SetPixel(hdc, x, y, RGB(0, 0, 0));
            }
          }
        }
    
    
        EndPaint(hwnd, &ps);
        break;
      }
      return DefWindowProc(hwnd, msg, wp, lp);
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
      PSTR lpCmdLine, int nCmdShow) {
      HWND hwnd;
      WNDCLASS winc;
      MSG msg;
    
      winc.style = CS_HREDRAW | CS_VREDRAW;
      winc.lpfnWndProc = WndProc;
      winc.cbClsExtra = winc.cbWndExtra = 0;
      winc.hInstance = hInstance;
      winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
      winc.hCursor = LoadCursor(NULL, IDC_ARROW);
      winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
      winc.lpszMenuName = NULL;
      winc.lpszClassName = TEXT("NEW_WINDOW");
    
      if (!RegisterClass(&winc)) return 0;
    
    
    //指定した文字のunicodeのコードポイントを取得(※) unsigned int c = utf8_decode(u8"ぬ");
    //一文字書かれた画像を作成(pixelsに格納) drawfontchar(c); hwnd = CreateWindow( TEXT("NEW_WINDOW"), TEXT("example : stb_truetype.h"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 150, 150, NULL, NULL, hInstance, NULL ); if (hwnd == NULL) return 0; while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg); return msg.wParam; } unsigned char ttf_buffer[1 << 25]; //一文字書かれた画像を作成 void drawfontchar(unsigned int codepoint) { const int HEIGHT = 100; stbtt_fontinfo font; //フォントファイルを開く FILE* pf_font = fopen(R"(C:\Windows\Fonts\msgothic.ttc)", "rb"); fread(ttf_buffer, 1, 1 << 25, pf_font); fclose(pf_font); stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer, 0)); float scale = stbtt_ScaleForPixelHeight(&font, HEIGHT); int ascent, baseline, decent; stbtt_GetFontVMetrics(&font, &ascent, &decent, 0); baseline = (int)(ascent * scale); int height = (int)((ascent - decent) * scale); int x0, y0, x1, y1; stbtt_GetCodepointBitmapBox(&font, codepoint, scale, scale, &x0, &y0, &x1, &y1); //出力先のメモリ確保 iwidth = x1 - x0; iheight = y1 - y0; pixels = new unsigned char[iheight * iwidth]; stbtt_MakeCodepointBitmap( &font, //フォント情報 pixels, //描画先 iwidth, //描画先の幅 iheight,//描画先の高さ iwidth, //描画先の画像の一行のバイト数(?) scale, //X方向倍率 scale, //Y方向倍率 codepoint); } //utf8一文字をコードポイントに変換 unsigned int utf8_decode(const char* o) { const unsigned int MAXUNICODE = 0x10FFFF; static const unsigned int limits[] = { 0xFF, 0x7F, 0x7FF, 0xFFFF }; const unsigned char* s = (const unsigned char*)o; unsigned int c = s[0]; unsigned int res = 0; /* final result */ if (c < 0x80) /* ascii? */ res = c; else { int count = 0; /* to count number of continuation bytes */ while (c & 0x40) { /* still have continuation bytes? */ int cc = s[++count]; /* read next byte */ if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ return -1; /* invalid byte sequence */ res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ c <<= 1; /* to test next bit */ } res |= ((c & 0x7F) << (count * 5)); /* add first byte */ if (count > 3 || res > MAXUNICODE || res <= limits[count]) return -1; /* invalid byte sequence */ s += count; /* skip continuation bytes read */ } return res; }
    「ぬ」
    「、」

    出力されるのは文字の部分だけなので、そのまま画像の幅で並べると以下のようになる。

    高さの調節

    まず、グローバル変数に以下を追加する

    int _Baseline_;
    int _Y0;
    

    次に、drawfontchar関数に以下を追加する

    //一文字書かれた画像を作成
    void drawfontchar(unsigned int codepoint) {
    
      const int HEIGHT = 100;
    
      stbtt_fontinfo font;
    
      //フォントファイルを開く
      FILE* pf_font = fopen(R"(C:\Windows\Fonts\msgothic.ttc)", "rb");
      fread(ttf_buffer, 1, 1 << 25, pf_font);
      fclose(pf_font);
    
      stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer, 0));
      float scale = stbtt_ScaleForPixelHeight(&font, HEIGHT);
      int ascent, baseline, decent;
      stbtt_GetFontVMetrics(&font, &ascent, &decent, 0);
      baseline = (int)(ascent * scale);
      int height = (int)((ascent - decent) * scale);
    
      int x0, y0, x1, y1;
      stbtt_GetCodepointBitmapBox(&font, codepoint, scale, scale, &x0, &y0, &x1, &y1);
    
    
    _Baseline_ = baseline; _Y0 = y0;
    //出力先のメモリ確保 iwidth = x1 - x0; iheight = y1 - y0; pixels = new unsigned char[iheight * iwidth]; stbtt_MakeCodepointBitmap( &font, //フォント情報 pixels, //描画先 iwidth, //描画先の幅 iheight,//描画先の高さ iwidth, //描画先の画像の一行のバイト数(?) scale, //X方向倍率 scale, //Y方向倍率 codepoint); }

    さらに、表示時にY方向にオフセットを加える

    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
      HDC hdc;
      PAINTSTRUCT ps;
      switch (msg) {
      case WM_DESTROY:
        //画像の破棄
        delete[] pixels;
    
    
        PostQuitMessage(0);
        return 0;
      case WM_PAINT://画面に表示
        hdc = BeginPaint(hwnd, &ps);
        if (pixels != nullptr) {
          RECT rect;
          GetClientRect(hwnd, &rect);
          FillRect(hdc, &rect, (HBRUSH)GetStockObject(GRAY_BRUSH));
    
          for (int y = 0; y < iheight; y++) {
            for (int x = 0; x < iwidth; x++) {
              unsigned char r = pixels[y * iwidth + x];
              if (r == 0)
                SetPixel(hdc, x, y + _Y0 + _Baseline_, RGB(255, 0, 0));
              else
                SetPixel(hdc, x, y + _Y0 + _Baseline_, RGB(0, 0, 0));
            }
          }
        }
    
    
        EndPaint(hwnd, &ps);
        break;
      }
      return DefWindowProc(hwnd, msg, wp, lp);
    }
    

    各文字ごとに、y0とbaselineで高さの調整を行った場合。

    幅の調整

    さらに、文字ごとに一定の間隔で並べると

    幅に関しては揃える基準が無いのでX方向のオフセットは定数にする。