#include <iostream>
#include <vector>
#include <ft2build.h>
#include FT_FREETYPE_H
#pragma warning(disable:4996)
#pragma comment(lib,"freetype.lib")
void pnmP2_Write(
const char* const fname,
const int width,
const int height,
const unsigned char* const p);
void draw(
const int width,
const int height,
unsigned char* p,
const int charw,
const int charh,
const int ox,
const int oy,
const unsigned char* charp
);
int main()
{
FT_Library library; // handle to library
FT_Error error;
error = FT_Init_FreeType(&library);
if (error)
return -1;
FT_Face face; // handle to face object
// フォントファイル読み込み
error = FT_New_Face(
library,
"C:\\Windows\\Fonts\\meiryo.ttc",
0,
&face
);
//文字コード指定
error = FT_Select_Charmap(
face, // target face object
FT_ENCODING_UNICODE // エンコード指定
);
if (error == FT_Err_Unknown_File_Format)
return -1;
else if (error)
return -1;
//この二つの値でフォントサイズ調整
FT_F26Dot6 fontsize = 16 * 64*2;
FT_UInt CHAR_RESOLUTION = 300;
error = FT_Set_Char_Size(
face, // handle to face object
0, // char_width in 1/64th of points
fontsize, // char_height in 1/64th of points
CHAR_RESOLUTION, // horizontal device resolution
CHAR_RESOLUTION); // vertical device resolution
// 回転の指定
double theta = -65.0 * 3.1415 / 180.0;
// matrix.xxの型はFT_Fixedだが、これは typedef signed long FT_Fixed
FT_Matrix matrix;
matrix.xx = (FT_Fixed)(cos(theta) * 0x10000L);
matrix.xy = (FT_Fixed)(-sin(theta) * 0x10000L);
matrix.yx = (FT_Fixed)(sin(theta) * 0x10000L);
matrix.yy = (FT_Fixed)(cos(theta) * 0x10000L);
FT_Set_Transform(face, &matrix, 0);
// 出力画像のメモリ確保
const int iw = 1000;
const int ih = 1000;
std::vector<unsigned char> image(iw*ih,0);
// 描画位置
int posx = 500;
int posy = 500;
for (size_t i = 0; i < 3; i++) {
// 文字の取得
FT_ULong character = U"あいう"[i];
FT_UInt char_index = FT_Get_Char_Index(face, character);
// グリフ(字の形状)読込
error = FT_Load_Glyph(face, char_index, FT_LOAD_RENDER);
if (error)
return -1; // ignore errors
// 文字を画像化
FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
// 出力画像に文字を書き込み
draw(
//出力先データ
iw, ih, image.data(),
// 文字の画像
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
posx + face->glyph->bitmap_left,
posy - face->glyph->bitmap_top,
face->glyph->bitmap.buffer
);
posx += (face->glyph->advance.x >> 6);
posy -= (face->glyph->advance.y >> 6);
}
pnmP2_Write(// ファイル保存
"C:\\MyData\\freetypetest.pgm",
iw,
ih,
image.data()
);
// FreeType2の解放
FT_Done_Face(face);
FT_Done_FreeType(library);
}
//! @brief Portable Gray map
//! @param [in] fname ファイル名
//! @param [in] width 画像の幅
//! @param [in] height 画像の高さ
//! @param [in] p 画像のメモリへのアドレス
//! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む
void pnmP2_Write(
const char* const fname,
const int width,
const int height,
const unsigned char* const p) { // PPM ASCII
FILE* fp = fopen(fname, "wb");
fprintf(fp, "P2\n%d %d\n%d\n", width, height, 255);
size_t k = 0;
for (size_t i = 0; i < (size_t)height; i++) {
for (size_t j = 0; j < (size_t)width; j++) {
fprintf(fp, "%d ", p[k]);
k++;
}
fprintf(fp, "\n");
}
fclose(fp);
}
//! @brief 出力画像へ文字を書き込む
//! @param [in] width 出力先のサイズ
//! @param [in] height 出力先のサイズ
//! @param [out] p 出力先
//! @param [in] charw 文字画像のサイズ
//! @param [in] charh 文字画像のサイズ
//! @param [in] ox 描画始点
//! @param [in] oy 描画始点
//! @param [in] charp 文字画像
void draw(
const int width,
const int height,
unsigned char* p,
const int charw,
const int charh,
const int ox,
const int oy,
const unsigned char* charp
) {
for (int cx = 0; cx < charw; cx++) {
for (int cy = 0; cy < charh; cy++) {
int x = ox + cx;
int y = oy + cy;
if (x < 0 || x >= width)continue;
if (y < 0 || y >= height)continue;
int ipos = y * width + x;
int cpos = cy * charw + cx;
int c = (int)(p[ipos]) + (int)(charp[cpos]);
c = std::min(c, 255);
p[ipos] = c;
}
}
}