From 3a1174060a7dd4eb652d4e6854bc4cd98c159200 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 12 Jul 2021 21:27:12 -0700 Subject: [PATCH] opengl stb_truetype demo app --- tests/truetype_test_win32.c | 184 ++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 tests/truetype_test_win32.c diff --git a/tests/truetype_test_win32.c b/tests/truetype_test_win32.c new file mode 100644 index 0000000..c9aed99 --- /dev/null +++ b/tests/truetype_test_win32.c @@ -0,0 +1,184 @@ +// tested in VC6 (1998) and VS 2019 +#define _CRT_SECURE_NO_WARNINGS +#define WIN32_MEAN_AND_LEAN +#include + +#include +#include + +#define STB_TRUETYPE_IMPLEMENTATION +#include "stb_truetype.h" + +#include +#include + +int screen_x=1024, screen_y=768; +GLuint tex; + +unsigned char ttf_buffer[1<<20]; +unsigned char temp_bitmap[1024*1024]; +stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs + +void init(void) +{ + fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb")); + stbtt_BakeFontBitmap(ttf_buffer,0, 64.0, temp_bitmap,1024,1024, 32,96, cdata); + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 1024,1024,0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +} + +void print(float x, float y, char *text) +{ + // assume orthographic projection with units = screen pixels, origin at top left + glBindTexture(GL_TEXTURE_2D, tex); + glBegin(GL_QUADS); + while (*text) { + if (*text >= 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 1024,1024, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); + } + ++text; + } + glEnd(); +} + +void draw(void) +{ + glViewport(0,0,screen_x,screen_y); + glClearColor(0.45f,0.45f,0.75f,0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0,screen_x,screen_y,0,-1,1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor3f(1,1,1); + + print(100,150, "This is a simple test!"); + + // show font bitmap + glBegin(GL_QUADS); + glTexCoord2f(0,0); glVertex2f(256,200+0); + glTexCoord2f(1,0); glVertex2f(768,200+0); + glTexCoord2f(1,1); glVertex2f(768,200+512); + glTexCoord2f(0,1); glVertex2f(256,200+512); + glEnd(); +} + +/////////////////////////////////////////////////////////////////////// +/// +/// +/// Windows OpenGL setup +/// +/// + +HINSTANCE app; +HWND window; +HGLRC rc; +HDC dc; + +#pragma comment(lib, "opengl32.lib") +#pragma comment(lib, "glu32.lib") +#pragma comment(lib, "winmm.lib") + +int mySetPixelFormat(HWND win) +{ + PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), 1, PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA }; + int pixel_format; + pfd.dwLayerMask = PFD_MAIN_PLANE; + pfd.cColorBits = 24; + pfd.cAlphaBits = 8; + pfd.cDepthBits = 24; + pfd.cStencilBits = 8; + pixel_format = ChoosePixelFormat(dc, &pfd); + if (!pixel_format) return FALSE; + if (!DescribePixelFormat(dc, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) + return FALSE; + SetPixelFormat(dc, pixel_format, &pfd); + return TRUE; +} + +static int WINAPI WinProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + switch (msg) { + case WM_CREATE: { + LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lparam; + dc = GetDC(wnd); + if (mySetPixelFormat(wnd)) { + rc = wglCreateContext(dc); + if (rc) { + wglMakeCurrent(dc, rc); + return 0; + } + } + return -1; + } + + case WM_DESTROY: + wglMakeCurrent(NULL, NULL); + if (rc) wglDeleteContext(rc); + PostQuitMessage (0); + return 0; + + default: + return DefWindowProc (wnd, msg, wparam, lparam); + } + + return DefWindowProc (wnd, msg, wparam, lparam); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + DWORD dwstyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + WNDCLASSEX wndclass; + wndclass.cbSize = sizeof(wndclass); + wndclass.style = CS_OWNDC; + wndclass.lpfnWndProc = (WNDPROC) WinProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon(hInstance, _T("appicon")); + wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); + wndclass.hbrBackground = GetStockObject(NULL_BRUSH); + wndclass.lpszMenuName = _T("truetype-test"); + wndclass.lpszClassName = _T("truetype-test"); + wndclass.hIconSm = NULL; + app = hInstance; + + if (!RegisterClassEx(&wndclass)) + return 0; + + window = CreateWindow(_T("truetype-test"), _T("truetype test"), dwstyle, + CW_USEDEFAULT,0, screen_x, screen_y, + NULL, NULL, app, NULL); + ShowWindow(window, SW_SHOWNORMAL); + init(); + + for(;;) { + MSG msg; + if (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } else { + return 1; // WM_QUIT + } + wglMakeCurrent(dc, rc); + draw(); + SwapBuffers(dc); + } + return 0; +}