1 /*
2  * Nuklear - 1.40.8 - public domain
3  * no warrenty implied; use at your own risk.
4  * authored from 2015-2017 by Micha Mettke
5  */
6 /*
7  * ==============================================================
8  *
9  *                              API
10  *
11  * ===============================================================
12  */
13 #ifndef NK_GDIP_H_
14 #define NK_GDIP_H_
15 
16 #define WIN32_LEAN_AND_MEAN
17 #include <windows.h>
18 #include <shlwapi.h>
19 
20 /* font */
21 typedef struct GdipFont GdipFont;
22 NK_API GdipFont* nk_gdipfont_create(const char *name, int size);
23 NK_API GdipFont* nk_gdipfont_create_from_file(const WCHAR* filename, int size);
24 NK_API GdipFont* nk_gdipfont_create_from_memory(const void* membuf, int membufSize, int size);
25 NK_API void nk_gdipfont_del(GdipFont *font);
26 
27 NK_API struct nk_context* nk_gdip_init(HWND hwnd, unsigned int width, unsigned int height);
28 NK_API void nk_gdip_set_font(GdipFont *font);
29 NK_API int nk_gdip_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
30 NK_API void nk_gdip_render(enum nk_anti_aliasing AA, struct nk_color clear);
31 NK_API void nk_gdip_shutdown(void);
32 
33 /* image */
34 NK_API struct nk_image nk_gdip_load_image_from_file(const WCHAR* filename);
35 NK_API struct nk_image nk_gdip_load_image_from_memory(const void* membuf, nk_uint membufSize);
36 NK_API void nk_gdip_image_free(struct nk_image image);
37 
38 #endif
39 /*
40  * ==============================================================
41  *
42  *                          IMPLEMENTATION
43  *
44  * ===============================================================
45  */
46 #ifdef NK_GDIP_IMPLEMENTATION
47 
48 #include <stdlib.h>
49 #include <malloc.h>
50 #define _USE_MATH_DEFINES
51 #include <math.h>
52 
53 /* manually declare everything GDI+ needs, because
54    GDI+ headers are not usable from C */
55 #define WINGDIPAPI __stdcall
56 #define GDIPCONST const
57 
58 typedef struct GpGraphics GpGraphics;
59 typedef struct GpImage GpImage;
60 typedef struct GpPen GpPen;
61 typedef struct GpBrush GpBrush;
62 typedef struct GpStringFormat GpStringFormat;
63 typedef struct GpFont GpFont;
64 typedef struct GpFontFamily GpFontFamily;
65 typedef struct GpFontCollection GpFontCollection;
66 
67 typedef GpImage GpBitmap;
68 typedef GpBrush GpSolidFill;
69 
70 typedef int Status;
71 typedef Status GpStatus;
72 
73 typedef float REAL;
74 typedef DWORD ARGB;
75 typedef POINT GpPoint;
76 
77 typedef enum {
78     TextRenderingHintSystemDefault = 0,
79     TextRenderingHintSingleBitPerPixelGridFit = 1,
80     TextRenderingHintSingleBitPerPixel = 2,
81     TextRenderingHintAntiAliasGridFit = 3,
82     TextRenderingHintAntiAlias = 4,
83     TextRenderingHintClearTypeGridFit = 5
84 } TextRenderingHint;
85 
86 typedef enum {
87     StringFormatFlagsDirectionRightToLeft    = 0x00000001,
88     StringFormatFlagsDirectionVertical       = 0x00000002,
89     StringFormatFlagsNoFitBlackBox           = 0x00000004,
90     StringFormatFlagsDisplayFormatControl    = 0x00000020,
91     StringFormatFlagsNoFontFallback          = 0x00000400,
92     StringFormatFlagsMeasureTrailingSpaces   = 0x00000800,
93     StringFormatFlagsNoWrap                  = 0x00001000,
94     StringFormatFlagsLineLimit               = 0x00002000,
95     StringFormatFlagsNoClip                  = 0x00004000
96 } StringFormatFlags;
97 
98 typedef enum
99 {
100     QualityModeInvalid   = -1,
101     QualityModeDefault   = 0,
102     QualityModeLow       = 1,
103     QualityModeHigh      = 2
104 } QualityMode;
105 
106 typedef enum
107 {
108     SmoothingModeInvalid     = QualityModeInvalid,
109     SmoothingModeDefault     = QualityModeDefault,
110     SmoothingModeHighSpeed   = QualityModeLow,
111     SmoothingModeHighQuality = QualityModeHigh,
112     SmoothingModeNone,
113     SmoothingModeAntiAlias,
114     SmoothingModeAntiAlias8x4 = SmoothingModeAntiAlias,
115     SmoothingModeAntiAlias8x8
116 } SmoothingMode;
117 
118 typedef enum
119 {
120     FontStyleRegular    = 0,
121     FontStyleBold       = 1,
122     FontStyleItalic     = 2,
123     FontStyleBoldItalic = 3,
124     FontStyleUnderline  = 4,
125     FontStyleStrikeout  = 8
126 } FontStyle;
127 
128 typedef enum {
129     FillModeAlternate,
130     FillModeWinding
131 } FillMode;
132 
133 typedef enum {
134     CombineModeReplace,
135     CombineModeIntersect,
136     CombineModeUnion,
137     CombineModeXor,
138     CombineModeExclude,
139     CombineModeComplement
140 } CombineMode;
141 
142 typedef enum {
143     UnitWorld,
144     UnitDisplay,
145     UnitPixel,
146     UnitPoint,
147     UnitInch,
148     UnitDocument,
149     UnitMillimeter
150 } Unit;
151 
152 typedef struct {
153     FLOAT X;
154     FLOAT Y;
155     FLOAT Width;
156     FLOAT Height;
157 } RectF;
158 
159 typedef enum {
160     DebugEventLevelFatal,
161     DebugEventLevelWarning
162 } DebugEventLevel;
163 
164 typedef VOID (WINAPI *DebugEventProc)(DebugEventLevel level, CHAR *message);
165 
166 typedef struct {
167     UINT32 GdiplusVersion;
168     DebugEventProc DebugEventCallback;
169     BOOL SuppressBackgroundThread;
170     BOOL SuppressExternalCodecs;
171 } GdiplusStartupInput;
172 
173 typedef Status (WINAPI *NotificationHookProc)(OUT ULONG_PTR *token);
174 typedef VOID (WINAPI *NotificationUnhookProc)(ULONG_PTR token);
175 
176 typedef struct {
177     NotificationHookProc NotificationHook;
178     NotificationUnhookProc NotificationUnhook;
179 } GdiplusStartupOutput;
180 
181 /* startup & shutdown */
182 
183 Status WINAPI GdiplusStartup(
184     OUT ULONG_PTR *token,
185     const GdiplusStartupInput *input,
186     OUT GdiplusStartupOutput *output);
187 
188 VOID WINAPI GdiplusShutdown(ULONG_PTR token);
189 
190 /* image */
191 
192 GpStatus WINGDIPAPI
193 GdipCreateBitmapFromGraphics(INT width,
194                              INT height,
195                              GpGraphics* target,
196                              GpBitmap** bitmap);
197 
198 GpStatus WINGDIPAPI
199 GdipDisposeImage(GpImage *image);
200 
201 GpStatus WINGDIPAPI
202 GdipGetImageGraphicsContext(GpImage *image, GpGraphics **graphics);
203 
204 GpStatus WINGDIPAPI
205 GdipGetImageWidth(GpImage *image, UINT *width);
206 
207 GpStatus WINGDIPAPI
208 GdipGetImageHeight(GpImage *image, UINT *height);
209 
210 GpStatus WINGDIPAPI
211 GdipLoadImageFromFile(GDIPCONST WCHAR* filename, GpImage **image);
212 
213 GpStatus WINGDIPAPI
214 GdipLoadImageFromStream(IStream* stream, GpImage **image);
215 
216 /* pen */
217 
218 GpStatus WINGDIPAPI
219 GdipCreatePen1(ARGB color, REAL width, Unit unit, GpPen **pen);
220 
221 GpStatus WINGDIPAPI
222 GdipDeletePen(GpPen *pen);
223 
224 GpStatus WINGDIPAPI
225 GdipSetPenWidth(GpPen *pen, REAL width);
226 
227 GpStatus WINGDIPAPI
228 GdipSetPenColor(GpPen *pen, ARGB argb);
229 
230 /* brush */
231 
232 GpStatus WINGDIPAPI
233 GdipCreateSolidFill(ARGB color, GpSolidFill **brush);
234 
235 GpStatus WINGDIPAPI
236 GdipDeleteBrush(GpBrush *brush);
237 
238 GpStatus WINGDIPAPI
239 GdipSetSolidFillColor(GpSolidFill *brush, ARGB color);
240 
241 /* font */
242 
243 GpStatus WINGDIPAPI
244 GdipCreateFont(
245     GDIPCONST GpFontFamily  *fontFamily,
246     REAL                 emSize,
247     INT                  style,
248     Unit                 unit,
249     GpFont             **font
250 );
251 
252 GpStatus WINGDIPAPI
253 GdipDeleteFont(GpFont* font);
254 
255 GpStatus WINGDIPAPI
256 GdipGetFontSize(GpFont *font, REAL *size);
257 
258 GpStatus WINGDIPAPI
259 GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
260                              GpFontCollection *fontCollection,
261                              GpFontFamily **fontFamily);
262 
263 GpStatus WINGDIPAPI
264 GdipDeleteFontFamily(GpFontFamily *fontFamily);
265 
266 GpStatus WINGDIPAPI
267 GdipStringFormatGetGenericTypographic(GpStringFormat **format);
268 
269 GpStatus WINGDIPAPI
270 GdipSetStringFormatFlags(GpStringFormat *format, INT flags);
271 
272 GpStatus WINGDIPAPI
273 GdipDeleteStringFormat(GpStringFormat *format);
274 
275 GpStatus WINGDIPAPI
276 GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
277                          GDIPCONST void* memory, INT length);
278 
279 GpStatus WINGDIPAPI
280 GdipPrivateAddFontFile(GpFontCollection* fontCollection,
281                        GDIPCONST WCHAR* filename);
282 
283 GpStatus WINGDIPAPI
284 GdipNewPrivateFontCollection(GpFontCollection** fontCollection);
285 
286 GpStatus WINGDIPAPI
287 GdipDeletePrivateFontCollection(GpFontCollection** fontCollection);
288 
289 GpStatus WINGDIPAPI
290 GdipGetFontCollectionFamilyList(GpFontCollection* fontCollection,
291                         INT numSought, GpFontFamily* gpfamilies[], INT* numFound);
292 
293 GpStatus WINGDIPAPI
294 GdipGetFontCollectionFamilyCount(GpFontCollection* fontCollection, INT* numFound);
295 
296 
297 /* graphics */
298 
299 
300 GpStatus WINGDIPAPI
301 GdipCreateFromHWND(HWND hwnd, GpGraphics **graphics);
302 
303 GpStatus WINGDIPAPI
304 GdipCreateFromHDC(HDC hdc, GpGraphics **graphics);
305 
306 GpStatus WINGDIPAPI
307 GdipDeleteGraphics(GpGraphics *graphics);
308 
309 GpStatus WINGDIPAPI
310 GdipSetSmoothingMode(GpGraphics *graphics, SmoothingMode smoothingMode);
311 
312 GpStatus WINGDIPAPI
313 GdipSetClipRectI(GpGraphics *graphics, INT x, INT y,
314     INT width, INT height, CombineMode combineMode);
315 
316 GpStatus WINGDIPAPI
317 GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1, INT y1,
318                       INT x2, INT y2);
319 
320 GpStatus WINGDIPAPI
321 GdipDrawArcI(GpGraphics *graphics, GpPen *pen, INT x, INT y,
322     INT width, INT height, REAL startAngle, REAL sweepAngle);
323 
324 GpStatus WINGDIPAPI
325 GdipDrawPieI(GpGraphics *graphics, GpPen *pen, INT x, INT y,
326              INT width, INT height, REAL startAngle, REAL sweepAngle);
327 
328 GpStatus WINGDIPAPI
329 GdipFillPieI(GpGraphics *graphics, GpBrush *brush, INT x, INT y,
330     INT width, INT height, REAL startAngle, REAL sweepAngle);
331 
332 GpStatus WINGDIPAPI
333 GdipDrawRectangleI(GpGraphics *graphics, GpPen *pen, INT x, INT y,
334                    INT width, INT height);
335 
336 GpStatus WINGDIPAPI
337 GdipFillRectangleI(GpGraphics *graphics, GpBrush *brush, INT x, INT y,
338                    INT width, INT height);
339 
340 GpStatus WINGDIPAPI
341 GdipFillPolygonI(GpGraphics *graphics, GpBrush *brush,
342                  GDIPCONST GpPoint *points, INT count, FillMode fillMode);
343 
344 GpStatus WINGDIPAPI
345 GdipDrawPolygonI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points,
346                          INT count);
347 
348 GpStatus WINGDIPAPI
349 GdipFillEllipseI(GpGraphics *graphics, GpBrush *brush, INT x, INT y,
350                  INT width, INT height);
351 
352 GpStatus WINGDIPAPI
353 GdipDrawEllipseI(GpGraphics *graphics, GpPen *pen, INT x, INT y,
354                          INT width, INT height);
355 
356 GpStatus WINGDIPAPI
357 GdipDrawBezierI(GpGraphics *graphics, GpPen *pen, INT x1, INT y1,
358                         INT x2, INT y2, INT x3, INT y3, INT x4, INT y4);
359 
360 GpStatus WINGDIPAPI
361 GdipDrawString(
362     GpGraphics               *graphics,
363     GDIPCONST WCHAR          *string,
364     INT                       length,
365     GDIPCONST GpFont         *font,
366     GDIPCONST RectF          *layoutRect,
367     GDIPCONST GpStringFormat *stringFormat,
368     GDIPCONST GpBrush        *brush
369 );
370 
371 GpStatus WINGDIPAPI
372 GdipGraphicsClear(GpGraphics *graphics, ARGB color);
373 
374 GpStatus WINGDIPAPI
375 GdipDrawImageI(GpGraphics *graphics, GpImage *image, INT x, INT y);
376 
377 GpStatus WINGDIPAPI
378 GdipDrawImageRectI(GpGraphics *graphics, GpImage *image, INT x, INT y,
379                    INT width, INT height);
380 
381 GpStatus WINGDIPAPI
382 GdipMeasureString(
383     GpGraphics               *graphics,
384     GDIPCONST WCHAR          *string,
385     INT                       length,
386     GDIPCONST GpFont         *font,
387     GDIPCONST RectF          *layoutRect,
388     GDIPCONST GpStringFormat *stringFormat,
389     RectF                    *boundingBox,
390     INT                      *codepointsFitted,
391     INT                      *linesFilled
392 );
393 
394 GpStatus WINGDIPAPI
395 GdipSetTextRenderingHint(GpGraphics *graphics, TextRenderingHint mode);
396 
397 LWSTDAPI_(IStream *) SHCreateMemStream(const BYTE *pInit, _In_ UINT cbInit);
398 
399 struct GdipFont
400 {
401     struct nk_user_font nk;
402     GpFont* handle;
403 };
404 
405 static struct {
406     ULONG_PTR token;
407 
408     GpGraphics *window;
409     GpGraphics *memory;
410     GpImage *bitmap;
411     GpPen *pen;
412     GpSolidFill *brush;
413     GpStringFormat *format;
414     GpFontCollection *fontCollection[10];
415     INT curFontCollection;
416 
417     struct nk_context ctx;
418 } gdip;
419 
convert_color(struct nk_color c)420 static ARGB convert_color(struct nk_color c)
421 {
422     return (c.a << 24) | (c.r << 16) | (c.g << 8) | c.b;
423 }
424 
425 static void
nk_gdip_scissor(float x,float y,float w,float h)426 nk_gdip_scissor(float x, float y, float w, float h)
427 {
428     GdipSetClipRectI(gdip.memory, (INT)x, (INT)y, (INT)(w + 1), (INT)(h + 1), CombineModeReplace);
429 }
430 
431 static void
nk_gdip_stroke_line(short x0,short y0,short x1,short y1,unsigned int line_thickness,struct nk_color col)432 nk_gdip_stroke_line(short x0, short y0, short x1,
433     short y1, unsigned int line_thickness, struct nk_color col)
434 {
435     GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
436     GdipSetPenColor(gdip.pen, convert_color(col));
437     GdipDrawLineI(gdip.memory, gdip.pen, x0, y0, x1, y1);
438 }
439 
440 static void
nk_gdip_stroke_rect(short x,short y,unsigned short w,unsigned short h,unsigned short r,unsigned short line_thickness,struct nk_color col)441 nk_gdip_stroke_rect(short x, short y, unsigned short w,
442     unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
443 {
444     GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
445     GdipSetPenColor(gdip.pen, convert_color(col));
446     if (r == 0) {
447         GdipDrawRectangleI(gdip.memory, gdip.pen, x, y, w, h);
448     } else {
449         INT d = 2 * r;
450         GdipDrawArcI(gdip.memory, gdip.pen, x, y, d, d, 180, 90);
451         GdipDrawLineI(gdip.memory, gdip.pen, x + r, y, x + w - r, y);
452         GdipDrawArcI(gdip.memory, gdip.pen, x + w - d, y, d, d, 270, 90);
453         GdipDrawLineI(gdip.memory, gdip.pen, x + w, y + r, x + w, y + h - r);
454         GdipDrawArcI(gdip.memory, gdip.pen, x + w - d, y + h - d, d, d, 0, 90);
455         GdipDrawLineI(gdip.memory, gdip.pen, x, y + r, x, y + h - r);
456         GdipDrawArcI(gdip.memory, gdip.pen, x, y + h - d, d, d, 90, 90);
457         GdipDrawLineI(gdip.memory, gdip.pen, x + r, y + h, x + w - r, y + h);
458     }
459 }
460 
461 static void
nk_gdip_fill_rect(short x,short y,unsigned short w,unsigned short h,unsigned short r,struct nk_color col)462 nk_gdip_fill_rect(short x, short y, unsigned short w,
463     unsigned short h, unsigned short r, struct nk_color col)
464 {
465     GdipSetSolidFillColor(gdip.brush, convert_color(col));
466     if (r == 0) {
467         GdipFillRectangleI(gdip.memory, gdip.brush, x, y, w, h);
468     } else {
469         INT d = 2 * r;
470         GdipFillRectangleI(gdip.memory, gdip.brush, x + r, y, w - d, h);
471         GdipFillRectangleI(gdip.memory, gdip.brush, x, y + r, r, h - d);
472         GdipFillRectangleI(gdip.memory, gdip.brush, x + w - r, y + r, r, h - d);
473         GdipFillPieI(gdip.memory, gdip.brush, x, y, d, d, 180, 90);
474         GdipFillPieI(gdip.memory, gdip.brush, x + w - d, y, d, d, 270, 90);
475         GdipFillPieI(gdip.memory, gdip.brush, x + w - d, y + h - d, d, d, 0, 90);
476         GdipFillPieI(gdip.memory, gdip.brush, x, y + h - d, d, d, 90, 90);
477     }
478 }
479 
480 static BOOL
SetPoint(POINT * p,LONG x,LONG y)481 SetPoint(POINT *p, LONG x, LONG y)
482 {
483     if (!p)
484         return FALSE;
485     p->x = x;
486     p->y = y;
487     return TRUE;
488 }
489 
490 static void
nk_gdip_fill_triangle(short x0,short y0,short x1,short y1,short x2,short y2,struct nk_color col)491 nk_gdip_fill_triangle(short x0, short y0, short x1,
492     short y1, short x2, short y2, struct nk_color col)
493 {
494     POINT points[3];
495 
496     SetPoint(&points[0], x0, y0);
497     SetPoint(&points[1], x1, y1);
498     SetPoint(&points[2], x2, y2);
499 
500     GdipSetSolidFillColor(gdip.brush, convert_color(col));
501     GdipFillPolygonI(gdip.memory, gdip.brush, points, 3, FillModeAlternate);
502 }
503 
504 static void
nk_gdip_stroke_triangle(short x0,short y0,short x1,short y1,short x2,short y2,unsigned short line_thickness,struct nk_color col)505 nk_gdip_stroke_triangle(short x0, short y0, short x1,
506     short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
507 {
508     POINT points[4];
509 
510     SetPoint(&points[0], x0, y0);
511     SetPoint(&points[1], x1, y1);
512     SetPoint(&points[2], x2, y2);
513     SetPoint(&points[3], x0, y0);
514 
515     GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
516     GdipSetPenColor(gdip.pen, convert_color(col));
517     GdipDrawPolygonI(gdip.memory, gdip.pen, points, 4);
518 }
519 
520 static void
nk_gdip_fill_polygon(const struct nk_vec2i * pnts,int count,struct nk_color col)521 nk_gdip_fill_polygon(const struct nk_vec2i *pnts, int count, struct nk_color col)
522 {
523     int i = 0;
524     #define MAX_POINTS 64
525     POINT points[MAX_POINTS];
526     GdipSetSolidFillColor(gdip.brush, convert_color(col));
527     for (i = 0; i < count && i < MAX_POINTS; ++i) {
528         points[i].x = pnts[i].x;
529         points[i].y = pnts[i].y;
530     }
531     GdipFillPolygonI(gdip.memory, gdip.brush, points, i, FillModeAlternate);
532     #undef MAX_POINTS
533 }
534 
535 static void
nk_gdip_stroke_polygon(const struct nk_vec2i * pnts,int count,unsigned short line_thickness,struct nk_color col)536 nk_gdip_stroke_polygon(const struct nk_vec2i *pnts, int count,
537     unsigned short line_thickness, struct nk_color col)
538 {
539     GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
540     GdipSetPenColor(gdip.pen, convert_color(col));
541     if (count > 0) {
542         int i;
543         for (i = 1; i < count; ++i)
544             GdipDrawLineI(gdip.memory, gdip.pen, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
545         GdipDrawLineI(gdip.memory, gdip.pen, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y);
546     }
547 }
548 
549 static void
nk_gdip_stroke_polyline(const struct nk_vec2i * pnts,int count,unsigned short line_thickness,struct nk_color col)550 nk_gdip_stroke_polyline(const struct nk_vec2i *pnts,
551     int count, unsigned short line_thickness, struct nk_color col)
552 {
553     GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
554     GdipSetPenColor(gdip.pen, convert_color(col));
555     if (count > 0) {
556         int i;
557         for (i = 1; i < count; ++i)
558             GdipDrawLineI(gdip.memory, gdip.pen, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
559     }
560 }
561 
562 static void
nk_gdip_fill_circle(short x,short y,unsigned short w,unsigned short h,struct nk_color col)563 nk_gdip_fill_circle(short x, short y, unsigned short w,
564     unsigned short h, struct nk_color col)
565 {
566     GdipSetSolidFillColor(gdip.brush, convert_color(col));
567     GdipFillEllipseI(gdip.memory, gdip.brush, x, y, w, h);
568 }
569 
570 static void
nk_gdip_stroke_circle(short x,short y,unsigned short w,unsigned short h,unsigned short line_thickness,struct nk_color col)571 nk_gdip_stroke_circle(short x, short y, unsigned short w,
572     unsigned short h, unsigned short line_thickness, struct nk_color col)
573 {
574     GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
575     GdipSetPenColor(gdip.pen, convert_color(col));
576     GdipDrawEllipseI(gdip.memory, gdip.pen, x, y, w, h);
577 }
578 
579 static void
nk_gdip_stroke_curve(struct nk_vec2i p1,struct nk_vec2i p2,struct nk_vec2i p3,struct nk_vec2i p4,unsigned short line_thickness,struct nk_color col)580 nk_gdip_stroke_curve(struct nk_vec2i p1,
581     struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4,
582     unsigned short line_thickness, struct nk_color col)
583 {
584     GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
585     GdipSetPenColor(gdip.pen, convert_color(col));
586     GdipDrawBezierI(gdip.memory, gdip.pen, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
587 }
588 
589 static void
nk_gdip_fill_arc(short cx,short cy,unsigned short r,float amin,float adelta,struct nk_color col)590 nk_gdip_fill_arc(short cx, short cy, unsigned short r, float amin, float adelta, struct nk_color col)
591 {
592     GdipSetSolidFillColor(gdip.brush, convert_color(col));
593     GdipFillPieI(gdip.memory, gdip.brush, cx - r, cy - r, r * 2, r * 2, amin * (180/M_PI), adelta * (180/M_PI));
594 }
595 
596 static void
nk_gdip_stroke_arc(short cx,short cy,unsigned short r,float amin,float adelta,unsigned short line_thickness,struct nk_color col)597 nk_gdip_stroke_arc(short cx, short cy, unsigned short r, float amin, float adelta, unsigned short line_thickness, struct nk_color col)
598 {
599     GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
600     GdipSetPenColor(gdip.pen, convert_color(col));
601     GdipDrawPieI(gdip.memory, gdip.pen, cx - r, cy - r, r * 2, r * 2, amin * (180/M_PI), adelta * (180/M_PI));
602 }
603 
604 static void
nk_gdip_draw_text(short x,short y,unsigned short w,unsigned short h,const char * text,int len,GdipFont * font,struct nk_color cbg,struct nk_color cfg)605 nk_gdip_draw_text(short x, short y, unsigned short w, unsigned short h,
606     const char *text, int len, GdipFont *font, struct nk_color cbg, struct nk_color cfg)
607 {
608     int wsize;
609     WCHAR* wstr;
610     RectF layout;
611 
612     layout.X = x;
613     layout.Y = y;
614     layout.Width = w;
615     layout.Height = h;
616 
617     if(!text || !font || !len) return;
618 
619     wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
620     wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t));
621     MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
622 
623     GdipSetSolidFillColor(gdip.brush, convert_color(cfg));
624     GdipDrawString(gdip.memory, wstr, wsize, font->handle, &layout, gdip.format, gdip.brush);
625 }
626 
627 static void
nk_gdip_draw_image(short x,short y,unsigned short w,unsigned short h,struct nk_image img,struct nk_color col)628 nk_gdip_draw_image(short x, short y, unsigned short w, unsigned short h,
629     struct nk_image img, struct nk_color col)
630 {
631     GpImage *image = img.handle.ptr;
632     GdipDrawImageRectI(gdip.memory, image, x, y, w, h);
633 }
634 
635 static void
nk_gdip_clear(struct nk_color col)636 nk_gdip_clear(struct nk_color col)
637 {
638     GdipGraphicsClear(gdip.memory, convert_color(col));
639 }
640 
641 static void
nk_gdip_blit(GpGraphics * graphics)642 nk_gdip_blit(GpGraphics *graphics)
643 {
644     GdipDrawImageI(graphics, gdip.bitmap, 0, 0);
645 }
646 
647 static struct nk_image
nk_gdip_image_to_nk(GpImage * image)648 nk_gdip_image_to_nk(GpImage *image) {
649     struct nk_image img;
650     UINT uwidth, uheight;
651     img = nk_image_ptr( (void*)image );
652     GdipGetImageHeight(image, &uheight);
653     GdipGetImageWidth(image, &uwidth);
654     img.h = uheight;
655     img.w = uwidth;
656     return img;
657 }
658 
659 struct nk_image
nk_gdip_load_image_from_file(const WCHAR * filename)660 nk_gdip_load_image_from_file(const WCHAR *filename)
661 {
662     GpImage *image;
663     if (GdipLoadImageFromFile(filename, &image))
664         return nk_image_id(0);
665     return nk_gdip_image_to_nk(image);
666 }
667 
668 struct nk_image
nk_gdip_load_image_from_memory(const void * membuf,nk_uint membufSize)669 nk_gdip_load_image_from_memory(const void *membuf, nk_uint membufSize)
670 {
671     GpImage* image;
672     GpStatus status;
673     IStream *stream = SHCreateMemStream((const BYTE*)membuf, membufSize);
674     if (!stream)
675         return nk_image_id(0);
676 
677     status = GdipLoadImageFromStream(stream, &image);
678     stream->lpVtbl->Release(stream);
679 
680     if (status)
681         return nk_image_id(0);
682 
683     return nk_gdip_image_to_nk(image);
684 }
685 
686 void
nk_gdip_image_free(struct nk_image image)687 nk_gdip_image_free(struct nk_image image)
688 {
689     if (!image.handle.ptr)
690         return;
691     GdipDisposeImage(image.handle.ptr);
692 }
693 
694 GdipFont*
nk_gdipfont_create(const char * name,int size)695 nk_gdipfont_create(const char *name, int size)
696 {
697     GdipFont *font = (GdipFont*)calloc(1, sizeof(GdipFont));
698     GpFontFamily *family;
699 
700     int wsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
701     WCHAR* wname = (WCHAR*)_alloca((wsize + 1) * sizeof(wchar_t));
702     MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, wsize);
703     wname[wsize] = 0;
704 
705     GdipCreateFontFamilyFromName(wname, NULL, &family);
706     GdipCreateFont(family, (REAL)size, FontStyleRegular, UnitPixel, &font->handle);
707     GdipDeleteFontFamily(family);
708 
709     return font;
710 }
711 
712 GpFontCollection*
nk_gdip_getCurFontCollection()713 nk_gdip_getCurFontCollection(){
714     return gdip.fontCollection[gdip.curFontCollection];
715 }
716 
717 GdipFont*
nk_gdipfont_create_from_collection(int size)718 nk_gdipfont_create_from_collection(int size){
719     GpFontFamily **families;
720     INT count;
721     GdipFont *font = (GdipFont*)calloc(1, sizeof(GdipFont));
722     if( GdipGetFontCollectionFamilyCount(nk_gdip_getCurFontCollection(), &count) ) return NULL;
723     families = (GpFontFamily**)calloc(1, sizeof(GpFontFamily*));
724     if( !families ) return NULL;
725     if( GdipGetFontCollectionFamilyList(nk_gdip_getCurFontCollection(), count, families, &count) ) return NULL;
726     if( count < 1 ) return NULL;
727     if( GdipCreateFont(families[count-1], (REAL)size, FontStyleRegular, UnitPixel, &font->handle) ) return NULL;
728     free(families);
729     gdip.curFontCollection++;
730     return font;
731 }
732 
733 GdipFont*
nk_gdipfont_create_from_memory(const void * membuf,int membufSize,int size)734 nk_gdipfont_create_from_memory(const void* membuf, int membufSize, int size)
735 {
736     if( !nk_gdip_getCurFontCollection() )
737         if( GdipNewPrivateFontCollection(&gdip.fontCollection[gdip.curFontCollection]) ) return NULL;
738     if( GdipPrivateAddMemoryFont(nk_gdip_getCurFontCollection(), membuf, membufSize) ) return NULL;
739     return nk_gdipfont_create_from_collection(size);
740 }
741 
742 GdipFont*
nk_gdipfont_create_from_file(const WCHAR * filename,int size)743 nk_gdipfont_create_from_file(const WCHAR* filename, int size)
744 {
745     if( !nk_gdip_getCurFontCollection() )
746         if( GdipNewPrivateFontCollection(&gdip.fontCollection[gdip.curFontCollection]) ) return NULL;
747     if( GdipPrivateAddFontFile(nk_gdip_getCurFontCollection(), filename) ) return NULL;
748     return nk_gdipfont_create_from_collection(size);
749 }
750 
751 static float
nk_gdipfont_get_text_width(nk_handle handle,float height,const char * text,int len)752 nk_gdipfont_get_text_width(nk_handle handle, float height, const char *text, int len)
753 {
754     GdipFont *font = (GdipFont *)handle.ptr;
755     RectF layout = { 0.0f, 0.0f, 65536.0f, 65536.0f };
756     RectF bbox;
757     int wsize;
758     WCHAR* wstr;
759     if (!font || !text)
760         return 0;
761 
762     (void)height;
763     wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
764     wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t));
765     MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
766 
767     GdipMeasureString(gdip.memory, wstr, wsize, font->handle, &layout, gdip.format, &bbox, NULL, NULL);
768     return bbox.Width;
769 }
770 
771 void
nk_gdipfont_del(GdipFont * font)772 nk_gdipfont_del(GdipFont *font)
773 {
774     if(!font) return;
775     GdipDeleteFont(font->handle);
776     free(font);
777 }
778 
779 static void
nk_gdip_clipboard_paste(nk_handle usr,struct nk_text_edit * edit)780 nk_gdip_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
781 {
782     HGLOBAL mem;
783     SIZE_T size;
784     LPCWSTR wstr;
785     int utf8size;
786     char* utf8;
787     (void)usr;
788 
789     if (!IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
790         return;
791 
792     mem = (HGLOBAL)GetClipboardData(CF_UNICODETEXT);
793     if (!mem) {
794         CloseClipboard();
795         return;
796     }
797 
798     size = GlobalSize(mem) - 1;
799     if (!size) {
800         CloseClipboard();
801         return;
802     }
803 
804     wstr = (LPCWSTR)GlobalLock(mem);
805     if (!wstr) {
806         CloseClipboard();
807         return;
808     }
809 
810     utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), NULL, 0, NULL, NULL);
811     if (!utf8size) {
812         GlobalUnlock(mem);
813         CloseClipboard();
814         return;
815     }
816 
817     utf8 = (char*)malloc(utf8size);
818     if (!utf8) {
819         GlobalUnlock(mem);
820         CloseClipboard();
821         return;
822     }
823 
824     WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), utf8, utf8size, NULL, NULL);
825     nk_textedit_paste(edit, utf8, utf8size);
826     free(utf8);
827     GlobalUnlock(mem);
828     CloseClipboard();
829 }
830 
831 static void
nk_gdip_clipboard_copy(nk_handle usr,const char * text,int len)832 nk_gdip_clipboard_copy(nk_handle usr, const char *text, int len)
833 {
834     HGLOBAL mem;
835     wchar_t* wstr;
836     int wsize;
837     (void)usr;
838 
839     if (!OpenClipboard(NULL))
840         return;
841 
842     wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
843     if (!wsize) {
844         CloseClipboard();
845         return;
846     }
847 
848     mem = (HGLOBAL)GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t));
849     if (!mem) {
850         CloseClipboard();
851         return;
852     }
853 
854     wstr = (wchar_t*)GlobalLock(mem);
855     if (!wstr) {
856         GlobalFree(mem);
857         CloseClipboard();
858         return;
859     }
860 
861     MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
862     wstr[wsize] = 0;
863     GlobalUnlock(mem);
864     if (!SetClipboardData(CF_UNICODETEXT, mem))
865         GlobalFree(mem);
866     CloseClipboard();
867 }
868 
869 NK_API struct nk_context*
nk_gdip_init(HWND hwnd,unsigned int width,unsigned int height)870 nk_gdip_init(HWND hwnd, unsigned int width, unsigned int height)
871 {
872     int i;
873     GdiplusStartupInput startup = { 1, NULL, FALSE, TRUE };
874     GdiplusStartup(&gdip.token, &startup, NULL);
875 
876     GdipCreateFromHWND(hwnd, &gdip.window);
877     GdipCreateBitmapFromGraphics(width, height, gdip.window, &gdip.bitmap);
878     GdipGetImageGraphicsContext(gdip.bitmap, &gdip.memory);
879     GdipCreatePen1(0, 1.0f, UnitPixel, &gdip.pen);
880     GdipCreateSolidFill(0, &gdip.brush);
881     GdipStringFormatGetGenericTypographic(&gdip.format);
882     GdipSetStringFormatFlags(gdip.format, StringFormatFlagsNoFitBlackBox |
883         StringFormatFlagsMeasureTrailingSpaces | StringFormatFlagsNoWrap |
884         StringFormatFlagsNoClip);
885 
886     for(i=0; i< sizeof(gdip.fontCollection)/sizeof(gdip.fontCollection[0]); i++)
887         gdip.fontCollection[i] = NULL;
888     nk_init_default(&gdip.ctx, NULL);
889     gdip.ctx.clip.copy = nk_gdip_clipboard_copy;
890     gdip.ctx.clip.paste = nk_gdip_clipboard_paste;
891     gdip.curFontCollection = 0;
892     return &gdip.ctx;
893 }
894 
895 NK_API void
nk_gdip_set_font(GdipFont * gdipfont)896 nk_gdip_set_font(GdipFont *gdipfont)
897 {
898     struct nk_user_font *font = &gdipfont->nk;
899     font->userdata = nk_handle_ptr(gdipfont);
900     GdipGetFontSize(gdipfont->handle, &font->height);
901     font->width = nk_gdipfont_get_text_width;
902     nk_style_set_font(&gdip.ctx, font);
903 }
904 
905 NK_API int
nk_gdip_handle_event(HWND wnd,UINT msg,WPARAM wparam,LPARAM lparam)906 nk_gdip_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
907 {
908     switch (msg)
909     {
910     case WM_SIZE:
911         if (gdip.window)
912         {
913             unsigned int width = LOWORD(lparam);
914             unsigned int height = HIWORD(lparam);
915             GdipDeleteGraphics(gdip.window);
916             GdipDeleteGraphics(gdip.memory);
917             GdipDisposeImage(gdip.bitmap);
918             GdipCreateFromHWND(wnd, &gdip.window);
919             GdipCreateBitmapFromGraphics(width, height, gdip.window, &gdip.bitmap);
920             GdipGetImageGraphicsContext(gdip.bitmap, &gdip.memory);
921         }
922         break;
923 
924     case WM_PAINT:
925     {
926         PAINTSTRUCT paint;
927         HDC dc = BeginPaint(wnd, &paint);
928         GpGraphics *graphics;
929         GdipCreateFromHDC(dc, &graphics);
930         nk_gdip_blit(graphics);
931         GdipDeleteGraphics(graphics);
932         EndPaint(wnd, &paint);
933         return 1;
934     }
935 
936     case WM_KEYDOWN:
937     case WM_KEYUP:
938     case WM_SYSKEYDOWN:
939     case WM_SYSKEYUP:
940     {
941         int down = !((lparam >> 31) & 1);
942         int ctrl = GetKeyState(VK_CONTROL) & (1 << 15);
943 
944         switch (wparam)
945         {
946         case VK_SHIFT:
947         case VK_LSHIFT:
948         case VK_RSHIFT:
949             nk_input_key(&gdip.ctx, NK_KEY_SHIFT, down);
950             return 1;
951 
952         case VK_DELETE:
953             nk_input_key(&gdip.ctx, NK_KEY_DEL, down);
954             return 1;
955 
956         case VK_RETURN:
957             nk_input_key(&gdip.ctx, NK_KEY_ENTER, down);
958             return 1;
959 
960         case VK_TAB:
961             nk_input_key(&gdip.ctx, NK_KEY_TAB, down);
962             return 1;
963 
964         case VK_LEFT:
965             if (ctrl)
966                 nk_input_key(&gdip.ctx, NK_KEY_TEXT_WORD_LEFT, down);
967             else
968                 nk_input_key(&gdip.ctx, NK_KEY_LEFT, down);
969             return 1;
970 
971         case VK_RIGHT:
972             if (ctrl)
973                 nk_input_key(&gdip.ctx, NK_KEY_TEXT_WORD_RIGHT, down);
974             else
975                 nk_input_key(&gdip.ctx, NK_KEY_RIGHT, down);
976             return 1;
977 
978         case VK_BACK:
979             nk_input_key(&gdip.ctx, NK_KEY_BACKSPACE, down);
980             return 1;
981 
982         case VK_HOME:
983             nk_input_key(&gdip.ctx, NK_KEY_TEXT_START, down);
984             nk_input_key(&gdip.ctx, NK_KEY_SCROLL_START, down);
985             return 1;
986 
987         case VK_END:
988             nk_input_key(&gdip.ctx, NK_KEY_TEXT_END, down);
989             nk_input_key(&gdip.ctx, NK_KEY_SCROLL_END, down);
990             return 1;
991 
992         case VK_NEXT:
993             nk_input_key(&gdip.ctx, NK_KEY_SCROLL_DOWN, down);
994             return 1;
995 
996         case VK_PRIOR:
997             nk_input_key(&gdip.ctx, NK_KEY_SCROLL_UP, down);
998             return 1;
999 
1000         case 'C':
1001             if (ctrl) {
1002                 nk_input_key(&gdip.ctx, NK_KEY_COPY, down);
1003                 return 1;
1004             }
1005             break;
1006 
1007         case 'V':
1008             if (ctrl) {
1009                 nk_input_key(&gdip.ctx, NK_KEY_PASTE, down);
1010                 return 1;
1011             }
1012             break;
1013 
1014         case 'X':
1015             if (ctrl) {
1016                 nk_input_key(&gdip.ctx, NK_KEY_CUT, down);
1017                 return 1;
1018             }
1019             break;
1020 
1021         case 'Z':
1022             if (ctrl) {
1023                 nk_input_key(&gdip.ctx, NK_KEY_TEXT_UNDO, down);
1024                 return 1;
1025             }
1026             break;
1027 
1028         case 'R':
1029             if (ctrl) {
1030                 nk_input_key(&gdip.ctx, NK_KEY_TEXT_REDO, down);
1031                 return 1;
1032             }
1033             break;
1034         }
1035         return 0;
1036     }
1037 
1038     case WM_CHAR:
1039         if (wparam >= 32)
1040         {
1041             nk_input_unicode(&gdip.ctx, (nk_rune)wparam);
1042             return 1;
1043         }
1044         break;
1045 
1046     case WM_LBUTTONDOWN:
1047         nk_input_button(&gdip.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
1048         SetCapture(wnd);
1049         return 1;
1050 
1051     case WM_LBUTTONUP:
1052         nk_input_button(&gdip.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
1053         nk_input_button(&gdip.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
1054         ReleaseCapture();
1055         return 1;
1056 
1057     case WM_RBUTTONDOWN:
1058         nk_input_button(&gdip.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
1059         SetCapture(wnd);
1060         return 1;
1061 
1062     case WM_RBUTTONUP:
1063         nk_input_button(&gdip.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
1064         ReleaseCapture();
1065         return 1;
1066 
1067     case WM_MBUTTONDOWN:
1068         nk_input_button(&gdip.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
1069         SetCapture(wnd);
1070         return 1;
1071 
1072     case WM_MBUTTONUP:
1073         nk_input_button(&gdip.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
1074         ReleaseCapture();
1075         return 1;
1076 
1077     case WM_MOUSEWHEEL:
1078         nk_input_scroll(&gdip.ctx, nk_vec2(0,(float)(short)HIWORD(wparam) / WHEEL_DELTA));
1079         return 1;
1080 
1081     case WM_MOUSEMOVE:
1082         nk_input_motion(&gdip.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam));
1083         return 1;
1084 
1085     case WM_LBUTTONDBLCLK:
1086         nk_input_button(&gdip.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
1087         return 1;
1088     }
1089 
1090     return 0;
1091 }
1092 
1093 NK_API void
nk_gdip_shutdown(void)1094 nk_gdip_shutdown(void)
1095 {
1096     int i;
1097     for(i=0; i< gdip.curFontCollection; i++)
1098         GdipDeletePrivateFontCollection( &gdip.fontCollection[i] );
1099     GdipDeleteGraphics(gdip.window);
1100     GdipDeleteGraphics(gdip.memory);
1101     GdipDisposeImage(gdip.bitmap);
1102     GdipDeletePen(gdip.pen);
1103     GdipDeleteBrush(gdip.brush);
1104     GdipDeleteStringFormat(gdip.format);
1105     GdiplusShutdown(gdip.token);
1106 
1107     nk_free(&gdip.ctx);
1108 }
1109 
1110 NK_API void
nk_gdip_prerender_gui(enum nk_anti_aliasing AA)1111 nk_gdip_prerender_gui(enum nk_anti_aliasing AA)
1112 {
1113     const struct nk_command *cmd;
1114 
1115     GdipSetTextRenderingHint(gdip.memory, AA != NK_ANTI_ALIASING_OFF ?
1116         TextRenderingHintClearTypeGridFit : TextRenderingHintSingleBitPerPixelGridFit);
1117     GdipSetSmoothingMode(gdip.memory, AA != NK_ANTI_ALIASING_OFF ?
1118         SmoothingModeHighQuality : SmoothingModeNone);
1119 
1120     nk_foreach(cmd, &gdip.ctx)
1121     {
1122         switch (cmd->type) {
1123         case NK_COMMAND_NOP: break;
1124         case NK_COMMAND_SCISSOR: {
1125             const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
1126             nk_gdip_scissor(s->x, s->y, s->w, s->h);
1127         } break;
1128         case NK_COMMAND_LINE: {
1129             const struct nk_command_line *l = (const struct nk_command_line *)cmd;
1130             nk_gdip_stroke_line(l->begin.x, l->begin.y, l->end.x,
1131                 l->end.y, l->line_thickness, l->color);
1132         } break;
1133         case NK_COMMAND_RECT: {
1134             const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
1135             nk_gdip_stroke_rect(r->x, r->y, r->w, r->h,
1136                 (unsigned short)r->rounding, r->line_thickness, r->color);
1137         } break;
1138         case NK_COMMAND_RECT_FILLED: {
1139             const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
1140             nk_gdip_fill_rect(r->x, r->y, r->w, r->h,
1141                 (unsigned short)r->rounding, r->color);
1142         } break;
1143         case NK_COMMAND_CIRCLE: {
1144             const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
1145             nk_gdip_stroke_circle(c->x, c->y, c->w, c->h, c->line_thickness, c->color);
1146         } break;
1147         case NK_COMMAND_CIRCLE_FILLED: {
1148             const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
1149             nk_gdip_fill_circle(c->x, c->y, c->w, c->h, c->color);
1150         } break;
1151         case NK_COMMAND_TRIANGLE: {
1152             const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
1153             nk_gdip_stroke_triangle(t->a.x, t->a.y, t->b.x, t->b.y,
1154                 t->c.x, t->c.y, t->line_thickness, t->color);
1155         } break;
1156         case NK_COMMAND_TRIANGLE_FILLED: {
1157             const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
1158             nk_gdip_fill_triangle(t->a.x, t->a.y, t->b.x, t->b.y,
1159                 t->c.x, t->c.y, t->color);
1160         } break;
1161         case NK_COMMAND_POLYGON: {
1162             const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd;
1163             nk_gdip_stroke_polygon(p->points, p->point_count, p->line_thickness,p->color);
1164         } break;
1165         case NK_COMMAND_POLYGON_FILLED: {
1166             const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
1167             nk_gdip_fill_polygon(p->points, p->point_count, p->color);
1168         } break;
1169         case NK_COMMAND_POLYLINE: {
1170             const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
1171             nk_gdip_stroke_polyline(p->points, p->point_count, p->line_thickness, p->color);
1172         } break;
1173         case NK_COMMAND_TEXT: {
1174             const struct nk_command_text *t = (const struct nk_command_text*)cmd;
1175             nk_gdip_draw_text(t->x, t->y, t->w, t->h,
1176                 (const char*)t->string, t->length,
1177                 (GdipFont*)t->font->userdata.ptr,
1178                 t->background, t->foreground);
1179         } break;
1180         case NK_COMMAND_CURVE: {
1181             const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
1182             nk_gdip_stroke_curve(q->begin, q->ctrl[0], q->ctrl[1],
1183                 q->end, q->line_thickness, q->color);
1184         } break;
1185         case NK_COMMAND_IMAGE: {
1186             const struct nk_command_image *i = (const struct nk_command_image *)cmd;
1187             nk_gdip_draw_image(i->x, i->y, i->w, i->h, i->img, i->col);
1188         } break;
1189         case NK_COMMAND_ARC: {
1190             const struct nk_command_arc *i = (const struct nk_command_arc *)cmd;
1191             nk_gdip_stroke_arc(i->cx, i->cy, i->r, i->a[0], i->a[1], i->line_thickness, i->color);
1192         } break;
1193         case NK_COMMAND_ARC_FILLED: {
1194             const struct nk_command_arc_filled *i = (const struct nk_command_arc_filled *)cmd;
1195             nk_gdip_fill_arc(i->cx, i->cy, i->r, i->a[0], i->a[1], i->color);
1196         } break;
1197         case NK_COMMAND_RECT_MULTI_COLOR:
1198         default: break;
1199         }
1200     }
1201 }
1202 
1203 NK_API void
nk_gdip_render_gui(enum nk_anti_aliasing AA)1204 nk_gdip_render_gui(enum nk_anti_aliasing AA)
1205 {
1206     nk_gdip_prerender_gui(AA);
1207     nk_gdip_blit(gdip.window);
1208     nk_clear(&gdip.ctx);
1209 }
1210 
1211 NK_API void
nk_gdip_render(enum nk_anti_aliasing AA,struct nk_color clear)1212 nk_gdip_render(enum nk_anti_aliasing AA, struct nk_color clear)
1213 {
1214     nk_gdip_clear(clear);
1215     nk_gdip_render_gui(AA);
1216 }
1217 
1218 #endif
1219