OpenGLの描画内にFreeType2で簡単に文字列を描画できるFTGLだが改行がやや面倒。
FTGLのFTPixmapFontオブジェクトからBBoxメンバ関数を呼び出す。
この関数はテキストを与えるとそのテキストのバウンディングボックスを返すので、これで一行の高さが分かる。
ただし、このサイズは単位がピクセルらしいので、表示中のワールド座標系に変換してやる必要がある。
#include <iostream> #include <Windows.h> #include <gl/GL.h> #include <gl/GLU.h> #include <gl/freeglut.h> #include <FTGL/ftgl.h> #pragma comment(lib,"opengl32.lib") #pragma comment(lib,"freeglut.lib") #pragma comment(lib,"ftgl.lib") //ウィンドウの幅と高さ int width, height;
// FTGLを管理しやすくするクラス struct CFtglObject { const char* FONT_PATHNAME = "C:\\Windows\\Fonts\\msgothic.ttc"; FTPixmapFont* g_pFont; unsigned long g_ulFontSize; // フォントサイズ ~CFtglObject() { delete g_pFont; } // フォントの初期化 void init(const unsigned long fontsize) { g_ulFontSize = fontsize; if (!g_pFont) { g_pFont = new FTPixmapFont(FONT_PATHNAME); if (g_pFont->Error()) { delete g_pFont; g_pFont = nullptr; } else { g_pFont->FaceSize(g_ulFontSize); } } } // FTGLで文字列を描画 void print(const std::wstring& wstr, float x, float y) { if (g_pFont) { glRasterPos2f(x, y); g_pFont->Render(wstr.c_str()); } } FTPixmapFont& get_font() { return *g_pFont; } };
CFtglObject ftglo; //描画関数 void disp(void) { glViewport(0, 0, width, height); glClearColor(0.2, 0.2, 0.2, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1, 1, -1, 1, 1, -1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_CULL_FACE); double v = 0.7; glBegin(GL_QUADS); glColor3d(0, 0, 1); glVertex2d(-v, -v); glColor3d(1, 0, 1); glVertex2d(v, -v); glColor3d(1, 1, 1); glVertex2d(v, v); glColor3d(0, 1, 1); glVertex2d(-v, v); glEnd(); glLineWidth(2); glBegin(GL_LINES); glColor3d(1, 1, 0); glVertex2d(-v, 0); glColor3d(1, 1, 1); glVertex2d(v, 0); glColor3d(1, 1, 0); glVertex2d(0, -v); glColor3d(1, 1, 1); glVertex2d(0, v); glEnd(); ///////////////////////////////// ///////////////////////////////// ///////////////////////////////// const wchar_t* text; text = L"いろはに"; ftglo.print(text, 0, 0); FTBBox bbox = ftglo.get_font().BBox(text); float BoxHeightPixel = bbox.Upper().Yf() - bbox.Lower().Yf();//文字列の高さを求める // BoxHeightの単位がピクセルらしいので、これを現在の文字幅に修正する。 // 現在は -1 ~ 1の範囲を0~height-1ピクセルで表示しているので、 float ratioh = 2.f/height; float pixelh = ratioh * BoxHeightPixel; text = L"ほへと"; ftglo.print(text, 0, pixelh); glFlush(); } //ウィンドウサイズの変化時に呼び出される void reshape(int w, int h) { width = w; height = h; disp(); } //エントリポイント int main(int argc, char** argv) { glutInit(&argc, argv); glutInitWindowPosition(100, 50); glutInitWindowSize(500, 500); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); ftglo.init(32); glutCreateWindow("sample"); glutDisplayFunc(disp); glutReshapeFunc(reshape); glutMainLoop(); return 0; }