truetype_test_win32.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // tested in VC6 (1998) and VS 2019
  2. #define _CRT_SECURE_NO_WARNINGS
  3. #define WIN32_MEAN_AND_LEAN
  4. #include <windows.h>
  5. #include <stdio.h>
  6. #include <tchar.h>
  7. #define STB_TRUETYPE_IMPLEMENTATION
  8. #include "stb_truetype.h"
  9. #include <gl/gl.h>
  10. #include <gl/glu.h>
  11. int screen_x=1024, screen_y=768;
  12. GLuint tex;
  13. unsigned char ttf_buffer[1<<20];
  14. unsigned char temp_bitmap[1024*1024];
  15. stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
  16. void init(void)
  17. {
  18. fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
  19. stbtt_BakeFontBitmap(ttf_buffer,0, 64.0, temp_bitmap,1024,1024, 32,96, cdata);
  20. glGenTextures(1, &tex);
  21. glBindTexture(GL_TEXTURE_2D, tex);
  22. glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 1024,1024,0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
  23. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  24. }
  25. void print(float x, float y, char *text)
  26. {
  27. // assume orthographic projection with units = screen pixels, origin at top left
  28. glBindTexture(GL_TEXTURE_2D, tex);
  29. glBegin(GL_QUADS);
  30. while (*text) {
  31. if (*text >= 32 && *text < 128) {
  32. stbtt_aligned_quad q;
  33. stbtt_GetBakedQuad(cdata, 1024,1024, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
  34. glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
  35. glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
  36. glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
  37. glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
  38. }
  39. ++text;
  40. }
  41. glEnd();
  42. }
  43. void draw(void)
  44. {
  45. glViewport(0,0,screen_x,screen_y);
  46. glClearColor(0.45f,0.45f,0.75f,0);
  47. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  48. glDisable(GL_CULL_FACE);
  49. glDisable(GL_DEPTH_TEST);
  50. glDisable(GL_BLEND);
  51. glMatrixMode(GL_PROJECTION);
  52. glLoadIdentity();
  53. glOrtho(0,screen_x,screen_y,0,-1,1);
  54. glMatrixMode(GL_MODELVIEW);
  55. glLoadIdentity();
  56. glEnable(GL_TEXTURE_2D);
  57. glEnable(GL_BLEND);
  58. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  59. glColor3f(1,1,1);
  60. print(100,150, "This is a simple test!");
  61. // show font bitmap
  62. glBegin(GL_QUADS);
  63. glTexCoord2f(0,0); glVertex2f(256,200+0);
  64. glTexCoord2f(1,0); glVertex2f(768,200+0);
  65. glTexCoord2f(1,1); glVertex2f(768,200+512);
  66. glTexCoord2f(0,1); glVertex2f(256,200+512);
  67. glEnd();
  68. }
  69. ///////////////////////////////////////////////////////////////////////
  70. ///
  71. ///
  72. /// Windows OpenGL setup
  73. ///
  74. ///
  75. HINSTANCE app;
  76. HWND window;
  77. HGLRC rc;
  78. HDC dc;
  79. #pragma comment(lib, "opengl32.lib")
  80. #pragma comment(lib, "glu32.lib")
  81. #pragma comment(lib, "winmm.lib")
  82. int mySetPixelFormat(HWND win)
  83. {
  84. PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), 1, PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA };
  85. int pixel_format;
  86. pfd.dwLayerMask = PFD_MAIN_PLANE;
  87. pfd.cColorBits = 24;
  88. pfd.cAlphaBits = 8;
  89. pfd.cDepthBits = 24;
  90. pfd.cStencilBits = 8;
  91. pixel_format = ChoosePixelFormat(dc, &pfd);
  92. if (!pixel_format) return FALSE;
  93. if (!DescribePixelFormat(dc, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
  94. return FALSE;
  95. SetPixelFormat(dc, pixel_format, &pfd);
  96. return TRUE;
  97. }
  98. static int WINAPI WinProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
  99. {
  100. switch (msg) {
  101. case WM_CREATE: {
  102. LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lparam;
  103. dc = GetDC(wnd);
  104. if (mySetPixelFormat(wnd)) {
  105. rc = wglCreateContext(dc);
  106. if (rc) {
  107. wglMakeCurrent(dc, rc);
  108. return 0;
  109. }
  110. }
  111. return -1;
  112. }
  113. case WM_DESTROY:
  114. wglMakeCurrent(NULL, NULL);
  115. if (rc) wglDeleteContext(rc);
  116. PostQuitMessage (0);
  117. return 0;
  118. default:
  119. return DefWindowProc (wnd, msg, wparam, lparam);
  120. }
  121. return DefWindowProc (wnd, msg, wparam, lparam);
  122. }
  123. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  124. {
  125. DWORD dwstyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
  126. WNDCLASSEX wndclass;
  127. wndclass.cbSize = sizeof(wndclass);
  128. wndclass.style = CS_OWNDC;
  129. wndclass.lpfnWndProc = (WNDPROC) WinProc;
  130. wndclass.cbClsExtra = 0;
  131. wndclass.cbWndExtra = 0;
  132. wndclass.hInstance = hInstance;
  133. wndclass.hIcon = LoadIcon(hInstance, _T("appicon"));
  134. wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
  135. wndclass.hbrBackground = GetStockObject(NULL_BRUSH);
  136. wndclass.lpszMenuName = _T("truetype-test");
  137. wndclass.lpszClassName = _T("truetype-test");
  138. wndclass.hIconSm = NULL;
  139. app = hInstance;
  140. if (!RegisterClassEx(&wndclass))
  141. return 0;
  142. window = CreateWindow(_T("truetype-test"), _T("truetype test"), dwstyle,
  143. CW_USEDEFAULT,0, screen_x, screen_y,
  144. NULL, NULL, app, NULL);
  145. ShowWindow(window, SW_SHOWNORMAL);
  146. init();
  147. for(;;) {
  148. MSG msg;
  149. if (GetMessage(&msg, NULL, 0, 0)) {
  150. TranslateMessage(&msg);
  151. DispatchMessage(&msg);
  152. } else {
  153. return 1; // WM_QUIT
  154. }
  155. wglMakeCurrent(dc, rc);
  156. draw();
  157. SwapBuffers(dc);
  158. }
  159. return 0;
  160. }