True type fontをbitmapにレンダリングするプログラムを作成しました。レンダリングにはFreeTypeライブラリを使用しました。プログラムの作成はRaspberry Pi4で行っています。画像の表示にはEGGX / ProCALLライブラリを使用しました。
日本語の表示が行えるようにしました。
#include <stdint.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <wchar.h> #include <locale.h> #include <ft2build.h> #include FT_FREETYPE_H #include <eggx.h> /* EGGX を使う時に必要 */ /* マルチバイト文字を含めた文字数を求める */ int strwlen(char *buf) { // LC_CTYPE をネイティブロケールに変更 if( setlocale( LC_CTYPE, "" ) == NULL ){ fprintf(stderr, "do not set locale.\n"); exit(EXIT_FAILURE); } int i = 0; int count = 0; while( buf[i] != '\0' ){ int res = mblen( &buf[i], MB_CUR_MAX ); if( res < 0 ){ fprintf(stderr, "Contains illegal characters.\n"); exit(EXIT_FAILURE); } i += res; count++; } return count; } #define SIZE_OF_ARRAY(array) (sizeof(array)/sizeof(array[0])) int main(int argc,char *argv[]){ FT_Library library; FT_Face face; FT_GlyphSlot slot; int error,win; char text[] = "こんにちは、世界!"; wchar_t ws[256]; /* ワイド文字保存用 */ int pen_x, pen_y; int num_chars = strwlen(text); int len = mbstowcs( ws, text, SIZE_OF_ARRAY(ws) ); if( len == -1 ){ fprintf(stderr, "mbstowcs error\n"); exit( EXIT_FAILURE ); } gsetinitialattributes(DISABLE, BOTTOM_LEFT_ORIGIN); /*eggxの座標設定を通常のグラフィックスと同じに*/ win = gopen(1000,200); /* 1000x200 ピクセルのグラフィックス用ウィンドゥを開く */ //layer(win, 0, 1); /* 描画レイヤを設定 */ // FreeTypeの初期化とTrueTypeフォントの読み込み error = FT_Init_FreeType( &library ); if(error) { fprintf(stderr,"error FT_Init_FreeType\n"); exit(EXIT_FAILURE); } error = FT_New_Face( library, "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc", 0, &face ); if(error == FT_Err_Unknown_File_Format) { fprintf(stderr,"unsupport fonts format\n"); exit(EXIT_FAILURE); } else if(error) { fprintf(stderr,"fonts file not found\n"); exit(EXIT_FAILURE); } slot = face->glyph; error = FT_Set_Pixel_Sizes( face, 0, 120 ); //ピクセル単位でサイズ指定 //error = FT_Set_Char_Size( face, 0, 16 * 64, 300, 300); //ポイント単位でサイズ指定 if(error) { fprintf(stderr,"FT_Set_Pixel_Sizes\n"); exit(EXIT_FAILURE); } pen_x = 10; // 文字の表示座標 左下のベースライン pen_y = 150; newrgbcolor(win,0,0,255); drawline(win,pen_x,pen_y,1000,pen_y); for (int n = 0;n < num_chars; n++ ){ int i; FT_Bitmap bitmap; // n文字目の文字をビットマップ化 //error = FT_Load_Char( face, ws[n], FT_LOAD_VERTICAL_LAYOUT|FT_LOAD_RENDER );//縦書き error = FT_Load_Char( face, ws[n], FT_LOAD_RENDER );// 横書き if(error) { fprintf(stderr,"FT_Load_Char error\n"); exit(EXIT_FAILURE); } bitmap = slot->bitmap; for( i = 0; i < bitmap.rows * bitmap.width; i++){ newrgbcolor(win,bitmap.buffer[i],bitmap.buffer[i],bitmap.buffer[i]); int x = i % bitmap.width+pen_x + slot->bitmap_left; int y = i / bitmap.width+pen_y - slot->bitmap_top + (face->size->metrics.descender >>6); pset(win,x, y); /* 点を描く */ } pen_x += slot->advance.x >> 6; pen_y += slot->advance.y >> 6; } //copylayer(win, 1, 0); /* レイヤ1をレイヤ0に瞬時にコピー */ ggetch(); /* キー入力があるまで待つ */ gclose(win); /* グラフィックス用ウィンドゥを閉じる */ error = FT_Done_Face( face ); if(error) { fprintf(stderr,"error FT_Done_Face\n"); exit(EXIT_FAILURE); } error = FT_Done_FreeType( library ); if(error) { fprintf(stderr,"error FT_Done_FreeType\n"); exit(EXIT_FAILURE); } return 0; }
実行例
参考
※コメント投稿者のブログIDはブログ作成者のみに通知されます