True type fontをbitmapにレンダリングするプログラムを作成しました。レンダリングにはFreeTypeライブラリを使用しました。プログラムの作成はRaspberry Pi4で行っています。画像の表示にはEGGX / ProCALLライブラリを使用しました。
前回のプログラムは",pq"などの文字は指定した座標の下にはみ出してしまいます。これを指定の範囲に収めます。
face->size->metrics.descender ベースラインの下にはみ出す長さ
face->size->metrics.height フォントの高さ
face->size->metrics.max_advance フォントの最大幅
これらの値は26.6の固定小数点になっています。
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <eggx.h> /* EGGX を使う時に必要 */
int main(int argc,char *argv[]){
FT_Library library;
FT_Face face;
FT_GlyphSlot slot;
int error,win;
char text[] = "hello,world!";
int pen_x, pen_y;
int num_chars = (int)strlen( text);
gsetinitialattributes(DISABLE, BOTTOM_LEFT_ORIGIN); /*eggxの座標設定を通常のグラフィックスと同じに*/
win = gopen(800,400); /* 800x400 ピクセルのグラフィックス用ウィンドゥを開く */
//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,800,pen_y);
for (int n = 0;n < num_chars; n++ ){
int i;
FT_Bitmap bitmap;
// n文字目の文字をビットマップ化
//error = FT_Load_Char( face, text[n], FT_LOAD_VERTICAL_LAYOUT|FT_LOAD_RENDER );//縦書き
error = FT_Load_Char( face, text[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はブログ作成者のみに通知されます