1 /*
2 * Nuklear - 1.32.0 - public domain
3 * no warrenty implied; use at your own risk.
4 * authored from 2015-2016 by Micha Mettke
5 */
6 /*
7 * ==============================================================
8 *
9 * API
10 *
11 * ===============================================================
12 */
13 #ifndef NK_GDI_H_
14 #define NK_GDI_H_
15
16 #define WIN32_LEAN_AND_MEAN
17 #include <windows.h>
18
19 typedef struct GdiFont GdiFont;
20 NK_API struct nk_context* nk_gdi_init(GdiFont *font, HDC window_dc, unsigned int width, unsigned int height);
21 NK_API int nk_gdi_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
22 NK_API void nk_gdi_render(struct nk_color clear);
23 NK_API void nk_gdi_shutdown(void);
24
25 /* font */
26 NK_API GdiFont* nk_gdifont_create(const char *name, int size);
27 NK_API void nk_gdifont_del(GdiFont *font);
28 NK_API void nk_gdi_set_font(GdiFont *font);
29
30 #endif
31
32 /*
33 * ==============================================================
34 *
35 * IMPLEMENTATION
36 *
37 * ===============================================================
38 */
39 #ifdef NK_GDI_IMPLEMENTATION
40
41 #include <stdlib.h>
42 #include <malloc.h>
43
44 struct GdiFont {
45 struct nk_user_font nk;
46 int height;
47 HFONT handle;
48 HDC dc;
49 };
50
51 static struct {
52 HBITMAP bitmap;
53 HDC window_dc;
54 HDC memory_dc;
55 unsigned int width;
56 unsigned int height;
57 struct nk_context ctx;
58 } gdi;
59
60 static void
nk_create_image(struct nk_image * image,const char * frame_buffer,const int width,const int height)61 nk_create_image(struct nk_image * image, const char * frame_buffer, const int width, const int height)
62 {
63 if (image && frame_buffer && (width > 0) && (height > 0))
64 {
65 const unsigned char * src = (const unsigned char *)frame_buffer;
66 INT row = ((width * 3 + 3) & ~3);
67 LPBYTE lpBuf, pb = NULL;
68 BITMAPINFO bi = { 0 };
69 HBITMAP hbm;
70 int v, i;
71
72 image->w = width;
73 image->h = height;
74 image->region[0] = 0;
75 image->region[1] = 0;
76 image->region[2] = width;
77 image->region[3] = height;
78
79 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
80 bi.bmiHeader.biWidth = width;
81 bi.bmiHeader.biHeight = height;
82 bi.bmiHeader.biPlanes = 1;
83 bi.bmiHeader.biBitCount = 24;
84 bi.bmiHeader.biCompression = BI_RGB;
85 bi.bmiHeader.biSizeImage = row * height;
86
87 hbm = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&lpBuf, NULL, 0);
88
89 pb = lpBuf + row * height;
90 for (v = 0; v < height; v++)
91 {
92 pb -= row;
93 for (i = 0; i < row; i += 3)
94 {
95 pb[i + 0] = src[0];
96 pb[i + 1] = src[1];
97 pb[i + 2] = src[2];
98 src += 3;
99 }
100 }
101 SetDIBits(NULL, hbm, 0, height, lpBuf, &bi, DIB_RGB_COLORS);
102 image->handle.ptr = hbm;
103 }
104 }
105
106 static void
nk_delete_image(struct nk_image * image)107 nk_delete_image(struct nk_image * image)
108 {
109 if (image && image->handle.id != 0)
110 {
111 HBITMAP hbm = (HBITMAP)image->handle.ptr;
112 DeleteObject(hbm);
113 memset(image, 0, sizeof(struct nk_image));
114 }
115 }
116
117 static void
nk_gdi_draw_image(short x,short y,unsigned short w,unsigned short h,struct nk_image img,struct nk_color col)118 nk_gdi_draw_image(short x, short y, unsigned short w, unsigned short h,
119 struct nk_image img, struct nk_color col)
120 {
121 HBITMAP hbm = (HBITMAP)img.handle.ptr;
122 HDC hDCBits;
123 BITMAP bitmap;
124
125 if (!gdi.memory_dc || !hbm)
126 return;
127
128 hDCBits = CreateCompatibleDC(gdi.memory_dc);
129 GetObject(hbm, sizeof(BITMAP), (LPSTR)&bitmap);
130 SelectObject(hDCBits, hbm);
131 StretchBlt(gdi.memory_dc, x, y, w, h, hDCBits, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
132 DeleteDC(hDCBits);
133 }
134
135 static COLORREF
convert_color(struct nk_color c)136 convert_color(struct nk_color c)
137 {
138 return c.r | (c.g << 8) | (c.b << 16);
139 }
140
141 static void
nk_gdi_scissor(HDC dc,float x,float y,float w,float h)142 nk_gdi_scissor(HDC dc, float x, float y, float w, float h)
143 {
144 SelectClipRgn(dc, NULL);
145 IntersectClipRect(dc, (int)x, (int)y, (int)(x + w + 1), (int)(y + h + 1));
146 }
147
148 static void
nk_gdi_stroke_line(HDC dc,short x0,short y0,short x1,short y1,unsigned int line_thickness,struct nk_color col)149 nk_gdi_stroke_line(HDC dc, short x0, short y0, short x1,
150 short y1, unsigned int line_thickness, struct nk_color col)
151 {
152 COLORREF color = convert_color(col);
153
154 HPEN pen = NULL;
155 if (line_thickness == 1) {
156 SetDCPenColor(dc, color);
157 } else {
158 pen = CreatePen(PS_SOLID, line_thickness, color);
159 SelectObject(dc, pen);
160 }
161
162 MoveToEx(dc, x0, y0, NULL);
163 LineTo(dc, x1, y1);
164
165 if (pen) {
166 SelectObject(dc, GetStockObject(DC_PEN));
167 DeleteObject(pen);
168 }
169 }
170
171 static void
nk_gdi_stroke_rect(HDC dc,short x,short y,unsigned short w,unsigned short h,unsigned short r,unsigned short line_thickness,struct nk_color col)172 nk_gdi_stroke_rect(HDC dc, short x, short y, unsigned short w,
173 unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
174 {
175 COLORREF color = convert_color(col);
176 HGDIOBJ br;
177 HPEN pen = NULL;
178
179 if (line_thickness == 1) {
180 SetDCPenColor(dc, color);
181 } else {
182 pen = CreatePen(PS_SOLID, line_thickness, color);
183 SelectObject(dc, pen);
184 }
185
186 br = SelectObject(dc, GetStockObject(NULL_BRUSH));
187 if (r == 0) {
188 Rectangle(dc, x, y, x + w, y + h);
189 } else {
190 RoundRect(dc, x, y, x + w, y + h, r, r);
191 }
192 SelectObject(dc, br);
193
194 if (pen) {
195 SelectObject(dc, GetStockObject(DC_PEN));
196 DeleteObject(pen);
197 }
198 }
199
200 static void
nk_gdi_fill_rect(HDC dc,short x,short y,unsigned short w,unsigned short h,unsigned short r,struct nk_color col)201 nk_gdi_fill_rect(HDC dc, short x, short y, unsigned short w,
202 unsigned short h, unsigned short r, struct nk_color col)
203 {
204 COLORREF color = convert_color(col);
205
206 if (r == 0) {
207 RECT rect;
208 SetRect(&rect, x, y, x + w, y + h);
209 SetBkColor(dc, color);
210 ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
211 } else {
212 SetDCPenColor(dc, color);
213 SetDCBrushColor(dc, color);
214 RoundRect(dc, x, y, x + w, y + h, r, r);
215 }
216 }
217 static void
nk_gdi_set_vertexColor(PTRIVERTEX tri,struct nk_color col)218 nk_gdi_set_vertexColor(PTRIVERTEX tri, struct nk_color col)
219 {
220 tri->Red = col.r << 8;
221 tri->Green = col.g << 8;
222 tri->Blue = col.b << 8;
223 tri->Alpha = 0xff << 8;
224 }
225
226 static void
nk_gdi_rect_multi_color(HDC dc,short x,short y,unsigned short w,unsigned short h,struct nk_color left,struct nk_color top,struct nk_color right,struct nk_color bottom)227 nk_gdi_rect_multi_color(HDC dc, short x, short y, unsigned short w,
228 unsigned short h, struct nk_color left, struct nk_color top,
229 struct nk_color right, struct nk_color bottom)
230 {
231 BLENDFUNCTION alphaFunction;
232 GRADIENT_RECT gRect;
233 GRADIENT_TRIANGLE gTri[2];
234 TRIVERTEX vt[4];
235 alphaFunction.BlendOp = AC_SRC_OVER;
236 alphaFunction.BlendFlags = 0;
237 alphaFunction.SourceConstantAlpha = 0;
238 alphaFunction.AlphaFormat = AC_SRC_ALPHA;
239
240 /* TODO: This Case Needs Repair.*/
241 /* Top Left Corner */
242 vt[0].x = x;
243 vt[0].y = y;
244 nk_gdi_set_vertexColor(&vt[0], left);
245 /* Top Right Corner */
246 vt[1].x = x+w;
247 vt[1].y = y;
248 nk_gdi_set_vertexColor(&vt[1], top);
249 /* Bottom Left Corner */
250 vt[2].x = x;
251 vt[2].y = y+h;
252 nk_gdi_set_vertexColor(&vt[2], right);
253
254 /* Bottom Right Corner */
255 vt[3].x = x+w;
256 vt[3].y = y+h;
257 nk_gdi_set_vertexColor(&vt[3], bottom);
258
259 gTri[0].Vertex1 = 0;
260 gTri[0].Vertex2 = 1;
261 gTri[0].Vertex3 = 2;
262 gTri[1].Vertex1 = 2;
263 gTri[1].Vertex2 = 1;
264 gTri[1].Vertex3 = 3;
265 GdiGradientFill(dc, vt, 4, gTri, 2 , GRADIENT_FILL_TRIANGLE);
266 AlphaBlend(gdi.window_dc, x, y, x+w, y+h,gdi.memory_dc, x, y, x+w, y+h,alphaFunction);
267
268 }
269
270 static BOOL
SetPoint(POINT * p,LONG x,LONG y)271 SetPoint(POINT *p, LONG x, LONG y)
272 {
273 if (!p)
274 return FALSE;
275 p->x = x;
276 p->y = y;
277 return TRUE;
278 }
279
280 static void
nk_gdi_fill_triangle(HDC dc,short x0,short y0,short x1,short y1,short x2,short y2,struct nk_color col)281 nk_gdi_fill_triangle(HDC dc, short x0, short y0, short x1,
282 short y1, short x2, short y2, struct nk_color col)
283 {
284 COLORREF color = convert_color(col);
285 POINT points[3];
286
287 SetPoint(&points[0], x0, y0);
288 SetPoint(&points[1], x1, y1);
289 SetPoint(&points[2], x2, y2);
290
291 SetDCPenColor(dc, color);
292 SetDCBrushColor(dc, color);
293 Polygon(dc, points, 3);
294 }
295
296 static void
nk_gdi_stroke_triangle(HDC dc,short x0,short y0,short x1,short y1,short x2,short y2,unsigned short line_thickness,struct nk_color col)297 nk_gdi_stroke_triangle(HDC dc, short x0, short y0, short x1,
298 short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
299 {
300 COLORREF color = convert_color(col);
301 POINT points[4];
302 HPEN pen = NULL;
303
304 SetPoint(&points[0], x0, y0);
305 SetPoint(&points[1], x1, y1);
306 SetPoint(&points[2], x2, y2);
307 SetPoint(&points[3], x0, y0);
308
309 if (line_thickness == 1) {
310 SetDCPenColor(dc, color);
311 } else {
312 pen = CreatePen(PS_SOLID, line_thickness, color);
313 SelectObject(dc, pen);
314 }
315
316 Polyline(dc, points, 4);
317
318 if (pen) {
319 SelectObject(dc, GetStockObject(DC_PEN));
320 DeleteObject(pen);
321 }
322 }
323
324 static void
nk_gdi_fill_polygon(HDC dc,const struct nk_vec2i * pnts,int count,struct nk_color col)325 nk_gdi_fill_polygon(HDC dc, const struct nk_vec2i *pnts, int count, struct nk_color col)
326 {
327 int i = 0;
328 #define MAX_POINTS 64
329 POINT points[MAX_POINTS];
330 COLORREF color = convert_color(col);
331 SetDCBrushColor(dc, color);
332 SetDCPenColor(dc, color);
333 for (i = 0; i < count && i < MAX_POINTS; ++i) {
334 points[i].x = pnts[i].x;
335 points[i].y = pnts[i].y;
336 }
337 Polygon(dc, points, i);
338 #undef MAX_POINTS
339 }
340
341 static void
nk_gdi_stroke_polygon(HDC dc,const struct nk_vec2i * pnts,int count,unsigned short line_thickness,struct nk_color col)342 nk_gdi_stroke_polygon(HDC dc, const struct nk_vec2i *pnts, int count,
343 unsigned short line_thickness, struct nk_color col)
344 {
345 COLORREF color = convert_color(col);
346 HPEN pen = NULL;
347 if (line_thickness == 1) {
348 SetDCPenColor(dc, color);
349 } else {
350 pen = CreatePen(PS_SOLID, line_thickness, color);
351 SelectObject(dc, pen);
352 }
353
354 if (count > 0) {
355 int i;
356 MoveToEx(dc, pnts[0].x, pnts[0].y, NULL);
357 for (i = 1; i < count; ++i)
358 LineTo(dc, pnts[i].x, pnts[i].y);
359 LineTo(dc, pnts[0].x, pnts[0].y);
360 }
361
362 if (pen) {
363 SelectObject(dc, GetStockObject(DC_PEN));
364 DeleteObject(pen);
365 }
366 }
367
368 static void
nk_gdi_stroke_polyline(HDC dc,const struct nk_vec2i * pnts,int count,unsigned short line_thickness,struct nk_color col)369 nk_gdi_stroke_polyline(HDC dc, const struct nk_vec2i *pnts,
370 int count, unsigned short line_thickness, struct nk_color col)
371 {
372 COLORREF color = convert_color(col);
373 HPEN pen = NULL;
374 if (line_thickness == 1) {
375 SetDCPenColor(dc, color);
376 } else {
377 pen = CreatePen(PS_SOLID, line_thickness, color);
378 SelectObject(dc, pen);
379 }
380
381 if (count > 0) {
382 int i;
383 MoveToEx(dc, pnts[0].x, pnts[0].y, NULL);
384 for (i = 1; i < count; ++i)
385 LineTo(dc, pnts[i].x, pnts[i].y);
386 }
387
388 if (pen) {
389 SelectObject(dc, GetStockObject(DC_PEN));
390 DeleteObject(pen);
391 }
392 }
393
394 static void
nk_gdi_fill_circle(HDC dc,short x,short y,unsigned short w,unsigned short h,struct nk_color col)395 nk_gdi_fill_circle(HDC dc, short x, short y, unsigned short w,
396 unsigned short h, struct nk_color col)
397 {
398 COLORREF color = convert_color(col);
399 SetDCBrushColor(dc, color);
400 SetDCPenColor(dc, color);
401 Ellipse(dc, x, y, x + w, y + h);
402 }
403
404 static void
nk_gdi_stroke_circle(HDC dc,short x,short y,unsigned short w,unsigned short h,unsigned short line_thickness,struct nk_color col)405 nk_gdi_stroke_circle(HDC dc, short x, short y, unsigned short w,
406 unsigned short h, unsigned short line_thickness, struct nk_color col)
407 {
408 COLORREF color = convert_color(col);
409 HPEN pen = NULL;
410 if (line_thickness == 1) {
411 SetDCPenColor(dc, color);
412 } else {
413 pen = CreatePen(PS_SOLID, line_thickness, color);
414 SelectObject(dc, pen);
415 }
416
417 SetDCBrushColor(dc, OPAQUE);
418 Ellipse(dc, x, y, x + w, y + h);
419
420 if (pen) {
421 SelectObject(dc, GetStockObject(DC_PEN));
422 DeleteObject(pen);
423 }
424 }
425
426 static void
nk_gdi_stroke_curve(HDC dc,struct nk_vec2i p1,struct nk_vec2i p2,struct nk_vec2i p3,struct nk_vec2i p4,unsigned short line_thickness,struct nk_color col)427 nk_gdi_stroke_curve(HDC dc, struct nk_vec2i p1,
428 struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4,
429 unsigned short line_thickness, struct nk_color col)
430 {
431 COLORREF color = convert_color(col);
432 POINT p[4];
433 HPEN pen = NULL;
434
435 SetPoint(&p[0], p1.x, p1.y);
436 SetPoint(&p[1], p2.x, p2.y);
437 SetPoint(&p[2], p3.x, p3.y);
438 SetPoint(&p[3], p4.x, p4.y);
439
440 if (line_thickness == 1) {
441 SetDCPenColor(dc, color);
442 } else {
443 pen = CreatePen(PS_SOLID, line_thickness, color);
444 SelectObject(dc, pen);
445 }
446
447 SetDCBrushColor(dc, OPAQUE);
448 PolyBezier(dc, p, 4);
449
450 if (pen) {
451 SelectObject(dc, GetStockObject(DC_PEN));
452 DeleteObject(pen);
453 }
454 }
455
456 static void
nk_gdi_draw_text(HDC dc,short x,short y,unsigned short w,unsigned short h,const char * text,int len,GdiFont * font,struct nk_color cbg,struct nk_color cfg)457 nk_gdi_draw_text(HDC dc, short x, short y, unsigned short w, unsigned short h,
458 const char *text, int len, GdiFont *font, struct nk_color cbg, struct nk_color cfg)
459 {
460 int wsize;
461 WCHAR* wstr;
462
463 if(!text || !font || !len) return;
464
465 wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
466 wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t));
467 MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
468
469 SetBkColor(dc, convert_color(cbg));
470 SetTextColor(dc, convert_color(cfg));
471
472 SelectObject(dc, font->handle);
473 ExtTextOutW(dc, x, y, ETO_OPAQUE, NULL, wstr, wsize, NULL);
474 }
475
476 static void
nk_gdi_clear(HDC dc,struct nk_color col)477 nk_gdi_clear(HDC dc, struct nk_color col)
478 {
479 COLORREF color = convert_color(col);
480 RECT rect;
481 SetRect(&rect, 0, 0, gdi.width, gdi.height);
482 SetBkColor(dc, color);
483
484 ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
485 }
486
487 static void
nk_gdi_blit(HDC dc)488 nk_gdi_blit(HDC dc)
489 {
490 BitBlt(dc, 0, 0, gdi.width, gdi.height, gdi.memory_dc, 0, 0, SRCCOPY);
491
492 }
493
494 GdiFont*
nk_gdifont_create(const char * name,int size)495 nk_gdifont_create(const char *name, int size)
496 {
497 TEXTMETRICW metric;
498 GdiFont *font = (GdiFont*)calloc(1, sizeof(GdiFont));
499 if (!font)
500 return NULL;
501 font->dc = CreateCompatibleDC(0);
502 font->handle = CreateFontA(size, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_DONTCARE, name);
503 SelectObject(font->dc, font->handle);
504 GetTextMetricsW(font->dc, &metric);
505 font->height = metric.tmHeight;
506 return font;
507 }
508
509 static float
nk_gdifont_get_text_width(nk_handle handle,float height,const char * text,int len)510 nk_gdifont_get_text_width(nk_handle handle, float height, const char *text, int len)
511 {
512 GdiFont *font = (GdiFont*)handle.ptr;
513 SIZE size;
514 int wsize;
515 WCHAR* wstr;
516 if (!font || !text)
517 return 0;
518
519 wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
520 wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t));
521 MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
522 if (GetTextExtentPoint32W(font->dc, wstr, wsize, &size))
523 return (float)size.cx;
524 return -1.0f;
525 }
526
527 void
nk_gdifont_del(GdiFont * font)528 nk_gdifont_del(GdiFont *font)
529 {
530 if(!font) return;
531 DeleteObject(font->handle);
532 DeleteDC(font->dc);
533 free(font);
534 }
535
536 static void
nk_gdi_clipboard_paste(nk_handle usr,struct nk_text_edit * edit)537 nk_gdi_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
538 {
539 (void)usr;
540 if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
541 {
542 HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
543 if (mem)
544 {
545 SIZE_T size = GlobalSize(mem) - 1;
546 if (size)
547 {
548 LPCWSTR wstr = (LPCWSTR)GlobalLock(mem);
549 if (wstr)
550 {
551 int utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), NULL, 0, NULL, NULL);
552 if (utf8size)
553 {
554 char* utf8 = (char*)malloc(utf8size);
555 if (utf8)
556 {
557 WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), utf8, utf8size, NULL, NULL);
558 nk_textedit_paste(edit, utf8, utf8size);
559 free(utf8);
560 }
561 }
562 GlobalUnlock(mem);
563 }
564 }
565 }
566 CloseClipboard();
567 }
568 }
569
570 static void
nk_gdi_clipboard_copy(nk_handle usr,const char * text,int len)571 nk_gdi_clipboard_copy(nk_handle usr, const char *text, int len)
572 {
573 if (OpenClipboard(NULL))
574 {
575 int wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
576 if (wsize)
577 {
578 HGLOBAL mem = (HGLOBAL)GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t));
579 if (mem)
580 {
581 wchar_t* wstr = (wchar_t*)GlobalLock(mem);
582 if (wstr)
583 {
584 MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
585 wstr[wsize] = 0;
586 GlobalUnlock(mem);
587
588 SetClipboardData(CF_UNICODETEXT, mem);
589 }
590 }
591 }
592 CloseClipboard();
593 }
594 }
595
596 NK_API struct nk_context*
nk_gdi_init(GdiFont * gdifont,HDC window_dc,unsigned int width,unsigned int height)597 nk_gdi_init(GdiFont *gdifont, HDC window_dc, unsigned int width, unsigned int height)
598 {
599 struct nk_user_font *font = &gdifont->nk;
600 font->userdata = nk_handle_ptr(gdifont);
601 font->height = (float)gdifont->height;
602 font->width = nk_gdifont_get_text_width;
603
604 gdi.bitmap = CreateCompatibleBitmap(window_dc, width, height);
605 gdi.window_dc = window_dc;
606 gdi.memory_dc = CreateCompatibleDC(window_dc);
607 gdi.width = width;
608 gdi.height = height;
609 SelectObject(gdi.memory_dc, gdi.bitmap);
610
611 nk_init_default(&gdi.ctx, font);
612 gdi.ctx.clip.copy = nk_gdi_clipboard_copy;
613 gdi.ctx.clip.paste = nk_gdi_clipboard_paste;
614 return &gdi.ctx;
615 }
616
617 NK_API void
nk_gdi_set_font(GdiFont * gdifont)618 nk_gdi_set_font(GdiFont *gdifont)
619 {
620 struct nk_user_font *font = &gdifont->nk;
621 font->userdata = nk_handle_ptr(gdifont);
622 font->height = (float)gdifont->height;
623 font->width = nk_gdifont_get_text_width;
624 nk_style_set_font(&gdi.ctx, font);
625 }
626
627 NK_API int
nk_gdi_handle_event(HWND wnd,UINT msg,WPARAM wparam,LPARAM lparam)628 nk_gdi_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
629 {
630 switch (msg)
631 {
632 case WM_SIZE:
633 {
634 unsigned width = LOWORD(lparam);
635 unsigned height = HIWORD(lparam);
636 if (width != gdi.width || height != gdi.height)
637 {
638 DeleteObject(gdi.bitmap);
639 gdi.bitmap = CreateCompatibleBitmap(gdi.window_dc, width, height);
640 gdi.width = width;
641 gdi.height = height;
642 SelectObject(gdi.memory_dc, gdi.bitmap);
643 }
644 break;
645 }
646
647 case WM_PAINT:
648 {
649 PAINTSTRUCT paint;
650 HDC dc = BeginPaint(wnd, &paint);
651 nk_gdi_blit(dc);
652 EndPaint(wnd, &paint);
653 return 1;
654 }
655
656 case WM_KEYDOWN:
657 case WM_KEYUP:
658 case WM_SYSKEYDOWN:
659 case WM_SYSKEYUP:
660 {
661 int down = !((lparam >> 31) & 1);
662 int ctrl = GetKeyState(VK_CONTROL) & (1 << 15);
663
664 switch (wparam)
665 {
666 case VK_SHIFT:
667 case VK_LSHIFT:
668 case VK_RSHIFT:
669 nk_input_key(&gdi.ctx, NK_KEY_SHIFT, down);
670 return 1;
671
672 case VK_DELETE:
673 nk_input_key(&gdi.ctx, NK_KEY_DEL, down);
674 return 1;
675
676 case VK_RETURN:
677 nk_input_key(&gdi.ctx, NK_KEY_ENTER, down);
678 return 1;
679
680 case VK_TAB:
681 nk_input_key(&gdi.ctx, NK_KEY_TAB, down);
682 return 1;
683
684 case VK_LEFT:
685 if (ctrl)
686 nk_input_key(&gdi.ctx, NK_KEY_TEXT_WORD_LEFT, down);
687 else
688 nk_input_key(&gdi.ctx, NK_KEY_LEFT, down);
689 return 1;
690
691 case VK_RIGHT:
692 if (ctrl)
693 nk_input_key(&gdi.ctx, NK_KEY_TEXT_WORD_RIGHT, down);
694 else
695 nk_input_key(&gdi.ctx, NK_KEY_RIGHT, down);
696 return 1;
697
698 case VK_BACK:
699 nk_input_key(&gdi.ctx, NK_KEY_BACKSPACE, down);
700 return 1;
701
702 case VK_HOME:
703 nk_input_key(&gdi.ctx, NK_KEY_TEXT_START, down);
704 nk_input_key(&gdi.ctx, NK_KEY_SCROLL_START, down);
705 return 1;
706
707 case VK_END:
708 nk_input_key(&gdi.ctx, NK_KEY_TEXT_END, down);
709 nk_input_key(&gdi.ctx, NK_KEY_SCROLL_END, down);
710 return 1;
711
712 case VK_NEXT:
713 nk_input_key(&gdi.ctx, NK_KEY_SCROLL_DOWN, down);
714 return 1;
715
716 case VK_PRIOR:
717 nk_input_key(&gdi.ctx, NK_KEY_SCROLL_UP, down);
718 return 1;
719
720 case 'C':
721 if (ctrl) {
722 nk_input_key(&gdi.ctx, NK_KEY_COPY, down);
723 return 1;
724 }
725 break;
726
727 case 'V':
728 if (ctrl) {
729 nk_input_key(&gdi.ctx, NK_KEY_PASTE, down);
730 return 1;
731 }
732 break;
733
734 case 'X':
735 if (ctrl) {
736 nk_input_key(&gdi.ctx, NK_KEY_CUT, down);
737 return 1;
738 }
739 break;
740
741 case 'Z':
742 if (ctrl) {
743 nk_input_key(&gdi.ctx, NK_KEY_TEXT_UNDO, down);
744 return 1;
745 }
746 break;
747
748 case 'R':
749 if (ctrl) {
750 nk_input_key(&gdi.ctx, NK_KEY_TEXT_REDO, down);
751 return 1;
752 }
753 break;
754 }
755 return 0;
756 }
757
758 case WM_CHAR:
759 if (wparam >= 32)
760 {
761 nk_input_unicode(&gdi.ctx, (nk_rune)wparam);
762 return 1;
763 }
764 break;
765
766 case WM_LBUTTONDOWN:
767 nk_input_button(&gdi.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
768 SetCapture(wnd);
769 return 1;
770
771 case WM_LBUTTONUP:
772 nk_input_button(&gdi.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
773 nk_input_button(&gdi.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
774 ReleaseCapture();
775 return 1;
776
777 case WM_RBUTTONDOWN:
778 nk_input_button(&gdi.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
779 SetCapture(wnd);
780 return 1;
781
782 case WM_RBUTTONUP:
783 nk_input_button(&gdi.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
784 ReleaseCapture();
785 return 1;
786
787 case WM_MBUTTONDOWN:
788 nk_input_button(&gdi.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
789 SetCapture(wnd);
790 return 1;
791
792 case WM_MBUTTONUP:
793 nk_input_button(&gdi.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
794 ReleaseCapture();
795 return 1;
796
797 case WM_MOUSEWHEEL:
798 nk_input_scroll(&gdi.ctx, nk_vec2(0,(float)(short)HIWORD(wparam) / WHEEL_DELTA));
799 return 1;
800
801 case WM_MOUSEMOVE:
802 nk_input_motion(&gdi.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam));
803 return 1;
804
805 case WM_LBUTTONDBLCLK:
806 nk_input_button(&gdi.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
807 return 1;
808 }
809
810 return 0;
811 }
812
813 NK_API void
nk_gdi_shutdown(void)814 nk_gdi_shutdown(void)
815 {
816 DeleteObject(gdi.memory_dc);
817 DeleteObject(gdi.bitmap);
818 nk_free(&gdi.ctx);
819 }
820
821 NK_API void
nk_gdi_render(struct nk_color clear)822 nk_gdi_render(struct nk_color clear)
823 {
824 const struct nk_command *cmd;
825
826 HDC memory_dc = gdi.memory_dc;
827 SelectObject(memory_dc, GetStockObject(DC_PEN));
828 SelectObject(memory_dc, GetStockObject(DC_BRUSH));
829 nk_gdi_clear(memory_dc, clear);
830
831 nk_foreach(cmd, &gdi.ctx)
832 {
833 switch (cmd->type) {
834 case NK_COMMAND_NOP: break;
835 case NK_COMMAND_SCISSOR: {
836 const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
837 nk_gdi_scissor(memory_dc, s->x, s->y, s->w, s->h);
838 } break;
839 case NK_COMMAND_LINE: {
840 const struct nk_command_line *l = (const struct nk_command_line *)cmd;
841 nk_gdi_stroke_line(memory_dc, l->begin.x, l->begin.y, l->end.x,
842 l->end.y, l->line_thickness, l->color);
843 } break;
844 case NK_COMMAND_RECT: {
845 const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
846 nk_gdi_stroke_rect(memory_dc, r->x, r->y, r->w, r->h,
847 (unsigned short)r->rounding, r->line_thickness, r->color);
848 } break;
849 case NK_COMMAND_RECT_FILLED: {
850 const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
851 nk_gdi_fill_rect(memory_dc, r->x, r->y, r->w, r->h,
852 (unsigned short)r->rounding, r->color);
853 } break;
854 case NK_COMMAND_CIRCLE: {
855 const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
856 nk_gdi_stroke_circle(memory_dc, c->x, c->y, c->w, c->h, c->line_thickness, c->color);
857 } break;
858 case NK_COMMAND_CIRCLE_FILLED: {
859 const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
860 nk_gdi_fill_circle(memory_dc, c->x, c->y, c->w, c->h, c->color);
861 } break;
862 case NK_COMMAND_TRIANGLE: {
863 const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
864 nk_gdi_stroke_triangle(memory_dc, t->a.x, t->a.y, t->b.x, t->b.y,
865 t->c.x, t->c.y, t->line_thickness, t->color);
866 } break;
867 case NK_COMMAND_TRIANGLE_FILLED: {
868 const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
869 nk_gdi_fill_triangle(memory_dc, t->a.x, t->a.y, t->b.x, t->b.y,
870 t->c.x, t->c.y, t->color);
871 } break;
872 case NK_COMMAND_POLYGON: {
873 const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd;
874 nk_gdi_stroke_polygon(memory_dc, p->points, p->point_count, p->line_thickness,p->color);
875 } break;
876 case NK_COMMAND_POLYGON_FILLED: {
877 const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
878 nk_gdi_fill_polygon(memory_dc, p->points, p->point_count, p->color);
879 } break;
880 case NK_COMMAND_POLYLINE: {
881 const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
882 nk_gdi_stroke_polyline(memory_dc, p->points, p->point_count, p->line_thickness, p->color);
883 } break;
884 case NK_COMMAND_TEXT: {
885 const struct nk_command_text *t = (const struct nk_command_text*)cmd;
886 nk_gdi_draw_text(memory_dc, t->x, t->y, t->w, t->h,
887 (const char*)t->string, t->length,
888 (GdiFont*)t->font->userdata.ptr,
889 t->background, t->foreground);
890 } break;
891 case NK_COMMAND_CURVE: {
892 const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
893 nk_gdi_stroke_curve(memory_dc, q->begin, q->ctrl[0], q->ctrl[1],
894 q->end, q->line_thickness, q->color);
895 } break;
896 case NK_COMMAND_RECT_MULTI_COLOR: {
897 const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color *)cmd;
898 nk_gdi_rect_multi_color(memory_dc, r->x, r->y,r->w, r->h, r->left, r->top, r->right, r->bottom);
899 } break;
900 case NK_COMMAND_IMAGE: {
901 const struct nk_command_image *i = (const struct nk_command_image *)cmd;
902 nk_gdi_draw_image(i->x, i->y, i->w, i->h, i->img, i->col);
903 } break;
904 case NK_COMMAND_ARC:
905 case NK_COMMAND_ARC_FILLED:
906 default: break;
907 }
908 }
909 nk_gdi_blit(gdi.window_dc);
910 nk_clear(&gdi.ctx);
911 }
912
913 #endif
914
915