1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
// tested in VC6 (1998) and VS 2019
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_MEAN_AND_LEAN
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
#include <gl/gl.h>
#include <gl/glu.h>
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;
}
|