スポンサーリンク

stbライブラリでtruetypeフォントをラスタライズ(1)

件のstbライブラリにあるstb_truetype.hでttfのラスタライズができる。public domainでttfが簡単に使えるなら試してみたい。

サンプル

//参考
//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) { 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, 255, 255)); 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, 200, 100, 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 = 60; stbtt_fontinfo font; //フォントファイルを開く FILE* pf_font = fopen(R"(C:\fonts\GenShinGothic-Bold.ttf)", "rb"); fread(ttf_buffer, 1, 1 << 25, 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; }

実行結果

参考

元のプログラム

以下のサンプルコードに手を加え、win32apiで文字を一つ表示できるようにした。

https://gist.github.com/cloudwu/766bccc60c254f9cc2abfa397bcff2ea

使用フォント

源真ゴシック

http://jikasei.me/font/genshin

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: