FreeType2のメモ
テキストをレンダリングするところまでこぎつけたので貼り付け。
// g++ -o sample -g `freetype-config --cflags` sample.cpp `freetype-config --libs` //#include <locale.h> #include <ft2build.h> #include FT_FREETYPE_H #include <string> #include <vector> #include <fstream> #include <cassert> #define FONT_SIZE 32 #define LINE_MERGIN 2 class P5 { int w_; int h_; std::vector<unsigned char> data_; public: P5() : w_(0), h_(0) { } void resize(int w, int h, unsigned char value) { w_=w; h_=h; data_.resize(w*h, value); } void blit(int _x, int _y, const unsigned char *_src, int w, int h, int pitch) { printf("blit %d:%d\n", w, h); assert(_y>=0); for(int y=0; y<h; ++y){ const unsigned char *src=&_src[pitch*y]; unsigned char *dst=&data_[(_y+y)*w_+_x]; for(int x=0; x<w; ++x, ++src, ++dst){ *dst=*src; } } } bool write(const std::string &path) { std::ofstream io(path.c_str(), std::ios::binary); if(!io){ return false; } // header io << "P5\n" << w_ << " " << h_ << "\n" << "255\n" ; // body io.write(reinterpret_cast<const char*>(&data_[0]), data_.size()); return true; } }; void face_info(const FT_Face &face) { double ratio=(double)face->size->metrics.y_ppem / (double)face->units_per_EM; const FT_Size_Metrics &m=face->size->metrics; printf("height: %d, ascender: %d, descender: %d, max_advance: %d\n", (int)(face->height*ratio), (int)(face->ascender*ratio), (int)(face->descender*ratio), (int)(m.max_advance*ratio) ); } class Renderer { int x_; int y_; P5 &image_; public: Renderer(P5 &image) : x_(0), y_(0), image_(image) {} void new_line(int line_height) { y_+=line_height; x_=0; } void render(const FT_Face &face, const wchar_t *text) { FT_GlyphSlot slot = face->glyph; double ratio=(double)face->size->metrics.y_ppem / (double)face->units_per_EM; int pen_x=x_; // baseline(小数切り上げ) int pen_y=y_+(face->ascender)*ratio+1; printf("ratio: %f, %d-%d\n", ratio, pen_x, pen_y); for (const wchar_t *p=text; *p!='\0'; ++p) { int error = FT_Load_Glyph(face, FT_Get_Char_Index(face, *p), FT_LOAD_RENDER ); if ( error ){ continue; } const FT_Bitmap &bitmap=slot->bitmap; image_.blit(pen_x+slot->bitmap_left, pen_y-slot->bitmap_top, bitmap.buffer, bitmap.width, bitmap.rows, bitmap.pitch); pen_x += slot->advance.x >> 6; } } }; int main(int argc, char **argv) { //setlocale(LC_CTYPE, "ja_JP.utf8"); if(argc<2){ printf("usage: %s {font file}\n", argv[0]); return 1; } FT_Library library; int error = FT_Init_FreeType( &library ); if ( error ) { printf("FT_Init_FreeType failed\n"); return 1; } FT_Face face; error = FT_New_Face(library, argv[1], 0, &face); if (error==FT_Err_Unknown_File_Format){ printf("FT_Err_Unknown_File_Format\n"); return 1; } else if(error){ printf("FT_New_Face failed\n"); return 1; } error = FT_Set_Pixel_Sizes( face, 0, FONT_SIZE ); if(error){ printf("FT_Set_Pixel_Sizes failed\n"); return 1; } face_info(face); P5 image; image.resize(400, 200, 0x30); Renderer renderer(image); renderer.render(face, L"AB,#?CD"); renderer.new_line(FONT_SIZE+LINE_MERGIN); renderer.render(face, L"日本語マルチバイト"); renderer.new_line(FONT_SIZE+LINE_MERGIN); renderer.render(face, L"efg〆★hijk"); renderer.new_line(FONT_SIZE+LINE_MERGIN); image.write("tmp.pgm"); return 0; }
$ ./a.out /usr/share/fonts/ipamonafont/ipag-mona.ttf
> main.exe C:/WINDOWS/Fonts/MSGOTHIC.TTC
としてどっちでも動作を確認できた。大丈夫だろう。
問題があるとすれば、FT_Set_Pixel_Sizesで指定した
サイズを越えてくるフォントやグリフの場合だけど、
そういうのはあるのだろうか。
baselinの算出は、
http://hp.vector.co.jp/authors/VA028002/freetype.html
を参考させていただきました。
ていうかそのままです。