nuklear_gdi.h 28 KB

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