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