1 #include <stdlib.h>
2 #include <string.h>
3
4 #define WIN32_MEAN_AND_LEAN
5 #include <windows.h>
6 #include "gdiplus.h"
7
8 #include <ui/display.h>
9 #include <ui/window.h>
10
11 #include <nuklear.h>
12
13 #include "canvas.h"
14 #include "font.h"
15 #include "display.h"
16 #include "window.h"
17
18 extern struct ui_display display;
19
20 static ARGB
ui_convert_color(struct nk_color c)21 ui_convert_color(struct nk_color c)
22 {
23 return (c.a << 24) | (c.r << 16) | (c.g << 8) | c.b;
24 }
25
26 struct ui_canvas *
ui_create_canvas(HWND target,struct ui_font * font,unsigned width,unsigned height)27 ui_create_canvas(HWND target, struct ui_font *font, unsigned width,
28 unsigned height)
29 {
30 struct nk_user_font *ufont;
31 struct ui_canvas *canvas;
32
33 canvas = calloc(1, sizeof *canvas);
34
35 if (!canvas)
36 return NULL;
37
38 canvas->width = width;
39 canvas->height = height;
40
41 GdipCreateFromHWND(target, &canvas->window);
42 GdipCreateBitmapFromGraphics(width, height, canvas->window, &canvas->bitmap);
43 GdipGetImageGraphicsContext(canvas->bitmap, &canvas->memory);
44 GdipCreatePen1(0, 1.0f, UnitPixel, &canvas->pen);
45 GdipCreateSolidFill(0, &canvas->brush);
46 GdipStringFormatGetGenericTypographic(&canvas->format);
47 GdipSetStringFormatFlags(canvas->format,
48 StringFormatFlagsNoFitBlackBox |
49 StringFormatFlagsMeasureTrailingSpaces |
50 StringFormatFlagsNoWrap |
51 StringFormatFlagsNoClip);
52
53 font->canvas = canvas;
54 ufont = &font->handle;
55
56 nk_init_default(&canvas->ctx, ufont);
57 nk_set_user_data(&canvas->ctx, nk_handle_ptr(canvas));
58
59 return canvas;
60 }
61
62 void
ui_destroy_canvas(struct ui_canvas * canvas)63 ui_destroy_canvas(struct ui_canvas *canvas)
64 {
65 GdipDeleteGraphics(canvas->window);
66 GdipDeleteGraphics(canvas->memory);
67 GdipDisposeImage(canvas->bitmap);
68 GdipDeletePen(canvas->pen);
69 GdipDeleteBrush(canvas->brush);
70 GdipDeleteStringFormat(canvas->format);
71 free(canvas);
72 }
73
74 void
ui_invalidate_canvas(struct ui_canvas * canvas)75 ui_invalidate_canvas(struct ui_canvas *canvas)
76 {
77 }
78
79 void
ui_resize_canvas(struct ui_window * window,struct ui_canvas * canvas,unsigned width,unsigned height)80 ui_resize_canvas(struct ui_window *window, struct ui_canvas *canvas, unsigned width, unsigned height)
81 {
82 if (!canvas)
83 return;
84
85 canvas->width = width;
86 canvas->height = height;
87
88 GdipDeleteGraphics(canvas->window);
89 GdipDeleteGraphics(canvas->memory);
90 GdipDisposeImage(canvas->bitmap);
91 GdipCreateFromHWND(window->win, &canvas->window);
92 GdipCreateBitmapFromGraphics(width, height, canvas->window, &canvas->bitmap);
93 GdipGetImageGraphicsContext(canvas->bitmap, &canvas->memory);
94 }
95
96 void
ui_clear_canvas(struct ui_canvas * canvas,struct nk_color color)97 ui_clear_canvas(struct ui_canvas *canvas, struct nk_color color)
98 {
99 GdipGraphicsClear(canvas->memory, ui_convert_color(color));
100 GdipSetTextRenderingHint(canvas->memory,
101 TextRenderingHintSystemDefault);
102 GdipSetSmoothingMode(canvas->memory,
103 SmoothingModeDefault);
104 }
105
106 void
ui_blit_canvas(GpGraphics * graphics,struct ui_canvas * canvas)107 ui_blit_canvas(GpGraphics *graphics, struct ui_canvas *canvas)
108 {
109 GdipDrawImageI(graphics, canvas->bitmap, 0, 0);
110 }
111
112 void
ui_scissor_canvas(struct ui_canvas * canvas,float x,float y,float width,float height)113 ui_scissor_canvas(struct ui_canvas *canvas, float x, float y, float width,
114 float height)
115 {
116 GdipSetClipRectI(canvas->memory, (INT)x, (INT)y,
117 (INT)(width + 1), (INT)(height + 1), CombineModeReplace);
118 }
119
120 void
ui_stroke_line(struct ui_canvas * canvas,short x0,short y0,short x1,short y1,unsigned line_thickness,struct nk_color color)121 ui_stroke_line(struct ui_canvas *canvas, short x0, short y0, short x1, short y1,
122 unsigned line_thickness, struct nk_color color)
123 {
124 GdipSetPenWidth(canvas->pen, (REAL)line_thickness);
125 GdipSetPenColor(canvas->pen, ui_convert_color(color));
126 GdipDrawLineI(canvas->memory, canvas->pen, x0, y0, x1, y1);
127 }
128
129 void
ui_stroke_rect(struct ui_canvas * canvas,short x,short y,unsigned short w,unsigned short h,unsigned short r,unsigned short line_thickness,struct nk_color color)130 ui_stroke_rect(struct ui_canvas *canvas, short x, short y, unsigned short w,
131 unsigned short h, unsigned short r, unsigned short line_thickness,
132 struct nk_color color)
133 {
134 GdipSetPenWidth(canvas->pen, (REAL)line_thickness);
135 GdipSetPenColor(canvas->pen, ui_convert_color(color));
136
137 if (r == 0) {
138 GdipDrawRectangleI(canvas->memory, canvas->pen, x, y, w, h);
139 } else {
140 INT d = 2 * r;
141 GdipDrawArcI(canvas->memory, canvas->pen, x, y, d, d, 180, 90);
142 GdipDrawLineI(canvas->memory, canvas->pen, x + r, y, x + w - r, y);
143 GdipDrawArcI(canvas->memory, canvas->pen, x + w - d, y, d, d, 270, 90);
144 GdipDrawLineI(canvas->memory, canvas->pen, x + w, y + r, x + w, y + h - r);
145 GdipDrawArcI(canvas->memory, canvas->pen, x + w - d, y + h - d, d, d, 0, 90);
146 GdipDrawLineI(canvas->memory, canvas->pen, x, y + r, x, y + h - r);
147 GdipDrawArcI(canvas->memory, canvas->pen, x, y + h - d, d, d, 90, 90);
148 GdipDrawLineI(canvas->memory, canvas->pen, x + r, y + h, x + w - r, y + h);
149 }
150 }
151
152 void
ui_fill_rect(struct ui_canvas * canvas,short x,short y,unsigned short w,unsigned short h,unsigned short r,struct nk_color color)153 ui_fill_rect(struct ui_canvas *canvas, short x, short y, unsigned short w,
154 unsigned short h, unsigned short r, struct nk_color color)
155 {
156 GdipSetSolidFillColor(canvas->brush, ui_convert_color(color));
157
158 if (r == 0) {
159 GdipFillRectangleI(canvas->memory, canvas->brush, x, y, w, h);
160 } else {
161 INT d = 2 * r;
162
163 GdipFillRectangleI(canvas->memory, canvas->brush, x + r, y, w - d, h);
164 GdipFillRectangleI(canvas->memory, canvas->brush, x, y + r, r, h - d);
165 GdipFillRectangleI(canvas->memory, canvas->brush, x + w - r, y + r, r, h - d);
166 GdipFillPieI(canvas->memory, canvas->brush, x, y, d, d, 180, 90);
167 GdipFillPieI(canvas->memory, canvas->brush, x + w - d, y, d, d, 270, 90);
168 GdipFillPieI(canvas->memory, canvas->brush, x + w - d, y + h - d, d, d, 0, 90);
169 GdipFillPieI(canvas->memory, canvas->brush, x, y + h - d, d, d, 90, 90);
170 }
171 }
172
173 void
ui_fill_triangle(struct ui_canvas * canvas,short x0,short y0,short x1,short y1,short x2,short y2,struct nk_color color)174 ui_fill_triangle(struct ui_canvas *canvas, short x0, short y0, short x1,
175 short y1, short x2, short y2, struct nk_color color)
176 {
177 POINT points[] = {
178 { x0, y0 },
179 { x1, y1 },
180 { x2, y2 },
181 };
182
183 GdipSetSolidFillColor(canvas->brush, ui_convert_color(color));
184 GdipFillPolygonI(canvas->memory, canvas->brush, points, 3, FillModeAlternate);
185 }
186
187 void
ui_stroke_triangle(struct ui_canvas * canvas,short x0,short y0,short x1,short y1,short x2,short y2,unsigned short line_thickness,struct nk_color color)188 ui_stroke_triangle(struct ui_canvas *canvas, short x0, short y0, short x1,
189 short y1, short x2, short y2, unsigned short line_thickness,
190 struct nk_color color)
191 {
192 POINT points[] = {
193 { x0, y0 },
194 { x1, y1 },
195 { x2, y2 },
196 { x0, y0 },
197 };
198
199 GdipSetPenWidth(canvas->pen, (REAL)line_thickness);
200 GdipSetPenColor(canvas->pen, ui_convert_color(color));
201 GdipDrawPolygonI(canvas->memory, canvas->pen, points, 4);
202 }
203
204 void
ui_fill_polygon(struct ui_canvas * canvas,const struct nk_vec2i * pnts,int count,struct nk_color color)205 ui_fill_polygon(struct ui_canvas *canvas, const struct nk_vec2i *pnts, int count,
206 struct nk_color color)
207 {
208 int i = 0;
209
210 #define MAX_POINTS 64
211 POINT points[MAX_POINTS];
212 GdipSetSolidFillColor(canvas->brush, ui_convert_color(color));
213
214 for (i = 0; i < count && i < MAX_POINTS; ++i) {
215 points[i].x = pnts[i].x;
216 points[i].y = pnts[i].y;
217 }
218
219 GdipFillPolygonI(canvas->memory, canvas->brush, points, i, FillModeAlternate);
220 #undef MAX_POINTS
221 }
222
223 void
ui_stroke_polygon(struct ui_canvas * canvas,const struct nk_vec2i * pnts,int count,unsigned short line_thickness,struct nk_color color)224 ui_stroke_polygon(struct ui_canvas *canvas, const struct nk_vec2i *pnts, int count,
225 unsigned short line_thickness, struct nk_color color)
226 {
227 GdipSetPenWidth(canvas->pen, (REAL)line_thickness);
228 GdipSetPenColor(canvas->pen, ui_convert_color(color));
229
230 if (count > 0) {
231 int i;
232 for (i = 1; i < count; ++i)
233 GdipDrawLineI(canvas->memory, canvas->pen, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
234 GdipDrawLineI(canvas->memory, canvas->pen, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y);
235 }
236 }
237
238 void
ui_stroke_polyline(struct ui_canvas * canvas,const struct nk_vec2i * pnts,int count,unsigned short line_thickness,struct nk_color color)239 ui_stroke_polyline(struct ui_canvas *canvas, const struct nk_vec2i *pnts,
240 int count, unsigned short line_thickness, struct nk_color color)
241 {
242 GdipSetPenWidth(canvas->pen, (REAL)line_thickness);
243 GdipSetPenColor(canvas->pen, ui_convert_color(color));
244
245 if (count > 0) {
246 int i;
247
248 for (i = 1; i < count; ++i) {
249 GdipDrawLineI(canvas->memory, canvas->pen, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
250 }
251 }
252 }
253
254 void
ui_fill_circle(struct ui_canvas * canvas,short x,short y,unsigned short w,unsigned short h,struct nk_color color)255 ui_fill_circle(struct ui_canvas *canvas, short x, short y, unsigned short w,
256 unsigned short h, struct nk_color color)
257 {
258 GdipSetSolidFillColor(canvas->brush, ui_convert_color(color));
259 GdipFillEllipseI(canvas->memory, canvas->brush, x, y, w, h);
260 }
261
262 void
ui_stroke_circle(struct ui_canvas * canvas,short x,short y,unsigned short w,unsigned short h,unsigned short line_thickness,struct nk_color color)263 ui_stroke_circle(struct ui_canvas *canvas, short x, short y, unsigned short w,
264 unsigned short h, unsigned short line_thickness, struct nk_color color)
265 {
266 GdipSetPenWidth(canvas->pen, (REAL)line_thickness);
267 GdipSetPenColor(canvas->pen, ui_convert_color(color));
268 GdipDrawEllipseI(canvas->memory, canvas->pen, x, y, w, h);
269 }
270
271 void
ui_stroke_curve(struct ui_canvas * canvas,struct nk_vec2i p1,struct nk_vec2i p2,struct nk_vec2i p3,struct nk_vec2i p4,unsigned int num_segments,unsigned short line_thickness,struct nk_color color)272 ui_stroke_curve(struct ui_canvas *canvas, struct nk_vec2i p1,
273 struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4,
274 unsigned int num_segments, unsigned short line_thickness,
275 struct nk_color color)
276 {
277 GdipSetPenWidth(canvas->pen, (REAL)line_thickness);
278 GdipSetPenColor(canvas->pen, ui_convert_color(color));
279 GdipDrawBezierI(canvas->memory, canvas->pen, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
280 }
281
282 void
ui_draw_text(struct ui_canvas * canvas,short x,short y,unsigned short w,unsigned short h,const char * text,int len,struct ui_font * font,struct nk_color cbg,struct nk_color cfg)283 ui_draw_text(struct ui_canvas *canvas, short x, short y, unsigned short w,
284 unsigned short h, const char *text, int len, struct ui_font *font,
285 struct nk_color cbg, struct nk_color cfg)
286 {
287 int wsize;
288 WCHAR* wstr;
289 RectF layout = { (FLOAT)x, (FLOAT)y, (FLOAT)w, (FLOAT)h };
290
291 if(!text || !font || !len) return;
292
293 wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
294 wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t));
295 MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
296
297 GdipSetSolidFillColor(canvas->brush, ui_convert_color(cfg));
298 GdipDrawString(canvas->memory, wstr, wsize, font->ft, &layout, canvas->format, canvas->brush);
299 }
300