スポンサーリンク
カーニングはアルファベットを描画する際に例えばVとAの間を狭く描画するような描画位置調整のことで、GT_Get_Kerningで文字の位置の差を取得する。
#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 = 32 * 64; 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 // 出力画像のメモリ確保 const int iw = 500; const int ih = 300; std::vector<unsigned char> image(iw*ih,0);
// カーニングのために直前の文字を保存しておく FT_UInt previous_glyph = 0;
// 描画位置 int posx = 0; int posy = 200; for (size_t i = 0; i < 4; i++) { // 文字の取得 FT_ULong character = U"VAOX"[i]; FT_UInt char_index = FT_Get_Char_Index(face, character);
// カーニング
if(previous_glyph && true/*カーニングしないならfalse*/) { FT_Vector kerning_delta; // 文字のずれ量を保存 // 文字のシフト量を取得 FT_Get_Kerning( face, previous_glyph, char_index, FT_KERNING_DEFAULT, &kerning_delta ); posx += ( kerning_delta.x >> 6 );// 文字のシフト } // 直前に使ったグリフを更新 previous_glyph = char_index;
// グリフ(字の形状)読込 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; } } }