1 #include "nuklear.h"
2 #include "nuklear_internal.h"
3 
4 /* ===============================================================
5  *
6  *                              VERTEX
7  *
8  * ===============================================================*/
9 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
10 NK_API void
nk_draw_list_init(struct nk_draw_list * list)11 nk_draw_list_init(struct nk_draw_list *list)
12 {
13     nk_size i = 0;
14     NK_ASSERT(list);
15     if (!list) return;
16     nk_zero(list, sizeof(*list));
17     for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
18         const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
19         list->circle_vtx[i].x = (float)NK_COS(a);
20         list->circle_vtx[i].y = (float)NK_SIN(a);
21     }
22 }
23 NK_API void
nk_draw_list_setup(struct nk_draw_list * canvas,const struct nk_convert_config * config,struct nk_buffer * cmds,struct nk_buffer * vertices,struct nk_buffer * elements,enum nk_anti_aliasing line_aa,enum nk_anti_aliasing shape_aa)24 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
25     struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
26     enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
27 {
28     NK_ASSERT(canvas);
29     NK_ASSERT(config);
30     NK_ASSERT(cmds);
31     NK_ASSERT(vertices);
32     NK_ASSERT(elements);
33     if (!canvas || !config || !cmds || !vertices || !elements)
34         return;
35 
36     canvas->buffer = cmds;
37     canvas->config = *config;
38     canvas->elements = elements;
39     canvas->vertices = vertices;
40     canvas->line_AA = line_aa;
41     canvas->shape_AA = shape_aa;
42     canvas->clip_rect = nk_null_rect;
43 
44     canvas->cmd_offset = 0;
45     canvas->element_count = 0;
46     canvas->vertex_count = 0;
47     canvas->cmd_offset = 0;
48     canvas->cmd_count = 0;
49     canvas->path_count = 0;
50 }
51 NK_API const struct nk_draw_command*
nk__draw_list_begin(const struct nk_draw_list * canvas,const struct nk_buffer * buffer)52 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
53 {
54     nk_byte *memory;
55     nk_size offset;
56     const struct nk_draw_command *cmd;
57 
58     NK_ASSERT(buffer);
59     if (!buffer || !buffer->size || !canvas->cmd_count)
60         return 0;
61 
62     memory = (nk_byte*)buffer->memory.ptr;
63     offset = buffer->memory.size - canvas->cmd_offset;
64     cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
65     return cmd;
66 }
67 NK_API const struct nk_draw_command*
nk__draw_list_end(const struct nk_draw_list * canvas,const struct nk_buffer * buffer)68 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
69 {
70     nk_size size;
71     nk_size offset;
72     nk_byte *memory;
73     const struct nk_draw_command *end;
74 
75     NK_ASSERT(buffer);
76     NK_ASSERT(canvas);
77     if (!buffer || !canvas)
78         return 0;
79 
80     memory = (nk_byte*)buffer->memory.ptr;
81     size = buffer->memory.size;
82     offset = size - canvas->cmd_offset;
83     end = nk_ptr_add(const struct nk_draw_command, memory, offset);
84     end -= (canvas->cmd_count-1);
85     return end;
86 }
87 NK_API const struct nk_draw_command*
nk__draw_list_next(const struct nk_draw_command * cmd,const struct nk_buffer * buffer,const struct nk_draw_list * canvas)88 nk__draw_list_next(const struct nk_draw_command *cmd,
89     const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
90 {
91     const struct nk_draw_command *end;
92     NK_ASSERT(buffer);
93     NK_ASSERT(canvas);
94     if (!cmd || !buffer || !canvas)
95         return 0;
96 
97     end = nk__draw_list_end(canvas, buffer);
98     if (cmd <= end) return 0;
99     return (cmd-1);
100 }
101 NK_INTERN struct nk_vec2*
nk_draw_list_alloc_path(struct nk_draw_list * list,int count)102 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
103 {
104     struct nk_vec2 *points;
105     NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
106     NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
107     points = (struct nk_vec2*)
108         nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
109                         point_size * (nk_size)count, point_align);
110 
111     if (!points) return 0;
112     if (!list->path_offset) {
113         void *memory = nk_buffer_memory(list->buffer);
114         list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
115     }
116     list->path_count += (unsigned int)count;
117     return points;
118 }
119 NK_INTERN struct nk_vec2
nk_draw_list_path_last(struct nk_draw_list * list)120 nk_draw_list_path_last(struct nk_draw_list *list)
121 {
122     void *memory;
123     struct nk_vec2 *point;
124     NK_ASSERT(list->path_count);
125     memory = nk_buffer_memory(list->buffer);
126     point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
127     point += (list->path_count-1);
128     return *point;
129 }
130 NK_INTERN struct nk_draw_command*
nk_draw_list_push_command(struct nk_draw_list * list,struct nk_rect clip,nk_handle texture)131 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
132     nk_handle texture)
133 {
134     NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
135     NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
136     struct nk_draw_command *cmd;
137 
138     NK_ASSERT(list);
139     cmd = (struct nk_draw_command*)
140         nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
141 
142     if (!cmd) return 0;
143     if (!list->cmd_count) {
144         nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
145         nk_size total = nk_buffer_total(list->buffer);
146         memory = nk_ptr_add(nk_byte, memory, total);
147         list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
148     }
149 
150     cmd->elem_count = 0;
151     cmd->clip_rect = clip;
152     cmd->texture = texture;
153 #ifdef NK_INCLUDE_COMMAND_USERDATA
154     cmd->userdata = list->userdata;
155 #endif
156 
157     list->cmd_count++;
158     list->clip_rect = clip;
159     return cmd;
160 }
161 NK_INTERN struct nk_draw_command*
nk_draw_list_command_last(struct nk_draw_list * list)162 nk_draw_list_command_last(struct nk_draw_list *list)
163 {
164     void *memory;
165     nk_size size;
166     struct nk_draw_command *cmd;
167     NK_ASSERT(list->cmd_count);
168 
169     memory = nk_buffer_memory(list->buffer);
170     size = nk_buffer_total(list->buffer);
171     cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
172     return (cmd - (list->cmd_count-1));
173 }
174 NK_INTERN void
nk_draw_list_add_clip(struct nk_draw_list * list,struct nk_rect rect)175 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
176 {
177     NK_ASSERT(list);
178     if (!list) return;
179     if (!list->cmd_count) {
180         nk_draw_list_push_command(list, rect, list->config.null.texture);
181     } else {
182         struct nk_draw_command *prev = nk_draw_list_command_last(list);
183         if (prev->elem_count == 0)
184             prev->clip_rect = rect;
185         nk_draw_list_push_command(list, rect, prev->texture);
186     }
187 }
188 NK_INTERN void
nk_draw_list_push_image(struct nk_draw_list * list,nk_handle texture)189 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
190 {
191     NK_ASSERT(list);
192     if (!list) return;
193     if (!list->cmd_count) {
194         nk_draw_list_push_command(list, nk_null_rect, texture);
195     } else {
196         struct nk_draw_command *prev = nk_draw_list_command_last(list);
197         if (prev->elem_count == 0) {
198             prev->texture = texture;
199         #ifdef NK_INCLUDE_COMMAND_USERDATA
200             prev->userdata = list->userdata;
201         #endif
202     } else if (prev->texture.id != texture.id
203         #ifdef NK_INCLUDE_COMMAND_USERDATA
204             || prev->userdata.id != list->userdata.id
205         #endif
206         ) nk_draw_list_push_command(list, prev->clip_rect, texture);
207     }
208 }
209 #ifdef NK_INCLUDE_COMMAND_USERDATA
210 NK_API void
nk_draw_list_push_userdata(struct nk_draw_list * list,nk_handle userdata)211 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
212 {
213     list->userdata = userdata;
214 }
215 #endif
216 NK_INTERN void*
nk_draw_list_alloc_vertices(struct nk_draw_list * list,nk_size count)217 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
218 {
219     void *vtx;
220     NK_ASSERT(list);
221     if (!list) return 0;
222     vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
223         list->config.vertex_size*count, list->config.vertex_alignment);
224     if (!vtx) return 0;
225     list->vertex_count += (unsigned int)count;
226 
227     /* This assert triggers because your are drawing a lot of stuff and nuklear
228      * defined `nk_draw_index` as `nk_ushort` to safe space be default.
229      *
230      * So you reached the maximum number of indicies or rather vertexes.
231      * To solve this issue please change typdef `nk_draw_index` to `nk_uint`
232      * and don't forget to specify the new element size in your drawing
233      * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements`
234      * instead of specifing `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`.
235      * Sorry for the inconvenience. */
236     if(sizeof(nk_draw_index)==2) NK_ASSERT((list->vertex_count < NK_USHORT_MAX &&
237         "To many verticies for 16-bit vertex indicies. Please read comment above on how to solve this problem"));
238     return vtx;
239 }
240 NK_INTERN nk_draw_index*
nk_draw_list_alloc_elements(struct nk_draw_list * list,nk_size count)241 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
242 {
243     nk_draw_index *ids;
244     struct nk_draw_command *cmd;
245     NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
246     NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
247     NK_ASSERT(list);
248     if (!list) return 0;
249 
250     ids = (nk_draw_index*)
251         nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
252     if (!ids) return 0;
253     cmd = nk_draw_list_command_last(list);
254     list->element_count += (unsigned int)count;
255     cmd->elem_count += (unsigned int)count;
256     return ids;
257 }
258 NK_INTERN int
nk_draw_vertex_layout_element_is_end_of_layout(const struct nk_draw_vertex_layout_element * element)259 nk_draw_vertex_layout_element_is_end_of_layout(
260     const struct nk_draw_vertex_layout_element *element)
261 {
262     return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
263             element->format == NK_FORMAT_COUNT);
264 }
265 NK_INTERN void
nk_draw_vertex_color(void * attr,const float * vals,enum nk_draw_vertex_layout_format format)266 nk_draw_vertex_color(void *attr, const float *vals,
267     enum nk_draw_vertex_layout_format format)
268 {
269     /* if this triggers you tried to provide a value format for a color */
270     float val[4];
271     NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
272     NK_ASSERT(format <= NK_FORMAT_COLOR_END);
273     if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
274 
275     val[0] = NK_SATURATE(vals[0]);
276     val[1] = NK_SATURATE(vals[1]);
277     val[2] = NK_SATURATE(vals[2]);
278     val[3] = NK_SATURATE(vals[3]);
279 
280     switch (format) {
281     default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
282     case NK_FORMAT_R8G8B8A8:
283     case NK_FORMAT_R8G8B8: {
284         struct nk_color col = nk_rgba_fv(val);
285         NK_MEMCPY(attr, &col.r, sizeof(col));
286     } break;
287     case NK_FORMAT_B8G8R8A8: {
288         struct nk_color col = nk_rgba_fv(val);
289         struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
290         NK_MEMCPY(attr, &bgra, sizeof(bgra));
291     } break;
292     case NK_FORMAT_R16G15B16: {
293         nk_ushort col[3];
294         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
295         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
296         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
297         NK_MEMCPY(attr, col, sizeof(col));
298     } break;
299     case NK_FORMAT_R16G15B16A16: {
300         nk_ushort col[4];
301         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
302         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
303         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
304         col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX);
305         NK_MEMCPY(attr, col, sizeof(col));
306     } break;
307     case NK_FORMAT_R32G32B32: {
308         nk_uint col[3];
309         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
310         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
311         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
312         NK_MEMCPY(attr, col, sizeof(col));
313     } break;
314     case NK_FORMAT_R32G32B32A32: {
315         nk_uint col[4];
316         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
317         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
318         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
319         col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX);
320         NK_MEMCPY(attr, col, sizeof(col));
321     } break;
322     case NK_FORMAT_R32G32B32A32_FLOAT:
323         NK_MEMCPY(attr, val, sizeof(float)*4);
324         break;
325     case NK_FORMAT_R32G32B32A32_DOUBLE: {
326         double col[4];
327         col[0] = (double)val[0];
328         col[1] = (double)val[1];
329         col[2] = (double)val[2];
330         col[3] = (double)val[3];
331         NK_MEMCPY(attr, col, sizeof(col));
332     } break;
333     case NK_FORMAT_RGB32:
334     case NK_FORMAT_RGBA32: {
335         struct nk_color col = nk_rgba_fv(val);
336         nk_uint color = nk_color_u32(col);
337         NK_MEMCPY(attr, &color, sizeof(color));
338     } break; }
339 }
340 NK_INTERN void
nk_draw_vertex_element(void * dst,const float * values,int value_count,enum nk_draw_vertex_layout_format format)341 nk_draw_vertex_element(void *dst, const float *values, int value_count,
342     enum nk_draw_vertex_layout_format format)
343 {
344     int value_index;
345     void *attribute = dst;
346     /* if this triggers you tried to provide a color format for a value */
347     NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
348     if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
349     for (value_index = 0; value_index < value_count; ++value_index) {
350         switch (format) {
351         default: NK_ASSERT(0 && "invalid vertex layout format"); break;
352         case NK_FORMAT_SCHAR: {
353             char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX);
354             NK_MEMCPY(attribute, &value, sizeof(value));
355             attribute = (void*)((char*)attribute + sizeof(char));
356         } break;
357         case NK_FORMAT_SSHORT: {
358             nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX);
359             NK_MEMCPY(attribute, &value, sizeof(value));
360             attribute = (void*)((char*)attribute + sizeof(value));
361         } break;
362         case NK_FORMAT_SINT: {
363             nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX);
364             NK_MEMCPY(attribute, &value, sizeof(value));
365             attribute = (void*)((char*)attribute + sizeof(nk_int));
366         } break;
367         case NK_FORMAT_UCHAR: {
368             unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX);
369             NK_MEMCPY(attribute, &value, sizeof(value));
370             attribute = (void*)((char*)attribute + sizeof(unsigned char));
371         } break;
372         case NK_FORMAT_USHORT: {
373             nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX);
374             NK_MEMCPY(attribute, &value, sizeof(value));
375             attribute = (void*)((char*)attribute + sizeof(value));
376             } break;
377         case NK_FORMAT_UINT: {
378             nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX);
379             NK_MEMCPY(attribute, &value, sizeof(value));
380             attribute = (void*)((char*)attribute + sizeof(nk_uint));
381         } break;
382         case NK_FORMAT_FLOAT:
383             NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
384             attribute = (void*)((char*)attribute + sizeof(float));
385             break;
386         case NK_FORMAT_DOUBLE: {
387             double value = (double)values[value_index];
388             NK_MEMCPY(attribute, &value, sizeof(value));
389             attribute = (void*)((char*)attribute + sizeof(double));
390             } break;
391         }
392     }
393 }
394 NK_INTERN void*
nk_draw_vertex(void * dst,const struct nk_convert_config * config,struct nk_vec2 pos,struct nk_vec2 uv,struct nk_colorf color)395 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
396     struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
397 {
398     void *result = (void*)((char*)dst + config->vertex_size);
399     const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
400     while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
401         void *address = (void*)((char*)dst + elem_iter->offset);
402         switch (elem_iter->attribute) {
403         case NK_VERTEX_ATTRIBUTE_COUNT:
404         default: NK_ASSERT(0 && "wrong element attribute"); break;
405         case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
406         case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
407         case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
408         }
409         elem_iter++;
410     }
411     return result;
412 }
413 NK_API void
nk_draw_list_stroke_poly_line(struct nk_draw_list * list,const struct nk_vec2 * points,const unsigned int points_count,struct nk_color color,enum nk_draw_list_stroke closed,float thickness,enum nk_anti_aliasing aliasing)414 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
415     const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
416     float thickness, enum nk_anti_aliasing aliasing)
417 {
418     nk_size count;
419     int thick_line;
420     struct nk_colorf col;
421     struct nk_colorf col_trans;
422     NK_ASSERT(list);
423     if (!list || points_count < 2) return;
424 
425     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
426     count = points_count;
427     if (!closed) count = points_count-1;
428     thick_line = thickness > 1.0f;
429 
430 #ifdef NK_INCLUDE_COMMAND_USERDATA
431     nk_draw_list_push_userdata(list, list->userdata);
432 #endif
433 
434     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
435     nk_color_fv(&col.r, color);
436     col_trans = col;
437     col_trans.a = 0;
438 
439     if (aliasing == NK_ANTI_ALIASING_ON) {
440         /* ANTI-ALIASED STROKE */
441         const float AA_SIZE = 1.0f;
442         NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
443         NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
444 
445         /* allocate vertices and elements  */
446         nk_size i1 = 0;
447         nk_size vertex_offset;
448         nk_size index = list->vertex_count;
449 
450         const nk_size idx_count = (thick_line) ?  (count * 18) : (count * 12);
451         const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
452 
453         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
454         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
455 
456         nk_size size;
457         struct nk_vec2 *normals, *temp;
458         if (!vtx || !ids) return;
459 
460         /* temporary allocate normals + points */
461         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
462         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
463         size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
464         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
465         if (!normals) return;
466         temp = normals + points_count;
467 
468         /* make sure vertex pointer is still correct */
469         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
470 
471         /* calculate normals */
472         for (i1 = 0; i1 < count; ++i1) {
473             const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
474             struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
475             float len;
476 
477             /* vec2 inverted length  */
478             len = nk_vec2_len_sqr(diff);
479             if (len != 0.0f)
480                 len = nk_inv_sqrt(len);
481             else len = 1.0f;
482 
483             diff = nk_vec2_muls(diff, len);
484             normals[i1].x = diff.y;
485             normals[i1].y = -diff.x;
486         }
487 
488         if (!closed)
489             normals[points_count-1] = normals[points_count-2];
490 
491         if (!thick_line) {
492             nk_size idx1, i;
493             if (!closed) {
494                 struct nk_vec2 d;
495                 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
496                 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
497                 d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
498                 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
499                 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
500             }
501 
502             /* fill elements */
503             idx1 = index;
504             for (i1 = 0; i1 < count; i1++) {
505                 struct nk_vec2 dm;
506                 float dmr2;
507                 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
508                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
509 
510                 /* average normals */
511                 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
512                 dmr2 = dm.x * dm.x + dm.y* dm.y;
513                 if (dmr2 > 0.000001f) {
514                     float scale = 1.0f/dmr2;
515                     scale = NK_MIN(100.0f, scale);
516                     dm = nk_vec2_muls(dm, scale);
517                 }
518 
519                 dm = nk_vec2_muls(dm, AA_SIZE);
520                 temp[i2*2+0] = nk_vec2_add(points[i2], dm);
521                 temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
522 
523                 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
524                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
525                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
526                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
527                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
528                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
529                 ids += 12;
530                 idx1 = idx2;
531             }
532 
533             /* fill vertices */
534             for (i = 0; i < points_count; ++i) {
535                 const struct nk_vec2 uv = list->config.null.uv;
536                 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
537                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
538                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
539             }
540         } else {
541             nk_size idx1, i;
542             const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
543             if (!closed) {
544                 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
545                 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
546 
547                 temp[0] = nk_vec2_add(points[0], d1);
548                 temp[1] = nk_vec2_add(points[0], d2);
549                 temp[2] = nk_vec2_sub(points[0], d2);
550                 temp[3] = nk_vec2_sub(points[0], d1);
551 
552                 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
553                 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
554 
555                 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
556                 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
557                 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
558                 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
559             }
560 
561             /* add all elements */
562             idx1 = index;
563             for (i1 = 0; i1 < count; ++i1) {
564                 struct nk_vec2 dm_out, dm_in;
565                 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
566                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
567 
568                 /* average normals */
569                 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
570                 float dmr2 = dm.x * dm.x + dm.y* dm.y;
571                 if (dmr2 > 0.000001f) {
572                     float scale = 1.0f/dmr2;
573                     scale = NK_MIN(100.0f, scale);
574                     dm = nk_vec2_muls(dm, scale);
575                 }
576 
577                 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
578                 dm_in = nk_vec2_muls(dm, half_inner_thickness);
579                 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
580                 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
581                 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
582                 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
583 
584                 /* add indexes */
585                 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
586                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
587                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
588                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
589                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
590                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
591                 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
592                 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
593                 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
594                 ids += 18;
595                 idx1 = idx2;
596             }
597 
598             /* add vertices */
599             for (i = 0; i < points_count; ++i) {
600                 const struct nk_vec2 uv = list->config.null.uv;
601                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
602                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
603                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
604                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
605             }
606         }
607         /* free temporary normals + points */
608         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
609     } else {
610         /* NON ANTI-ALIASED STROKE */
611         nk_size i1 = 0;
612         nk_size idx = list->vertex_count;
613         const nk_size idx_count = count * 6;
614         const nk_size vtx_count = count * 4;
615         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
616         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
617         if (!vtx || !ids) return;
618 
619         for (i1 = 0; i1 < count; ++i1) {
620             float dx, dy;
621             const struct nk_vec2 uv = list->config.null.uv;
622             const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
623             const struct nk_vec2 p1 = points[i1];
624             const struct nk_vec2 p2 = points[i2];
625             struct nk_vec2 diff = nk_vec2_sub(p2, p1);
626             float len;
627 
628             /* vec2 inverted length  */
629             len = nk_vec2_len_sqr(diff);
630             if (len != 0.0f)
631                 len = nk_inv_sqrt(len);
632             else len = 1.0f;
633             diff = nk_vec2_muls(diff, len);
634 
635             /* add vertices */
636             dx = diff.x * (thickness * 0.5f);
637             dy = diff.y * (thickness * 0.5f);
638 
639             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
640             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
641             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
642             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
643 
644             ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
645             ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
646             ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
647 
648             ids += 6;
649             idx += 4;
650         }
651     }
652 }
653 NK_API void
nk_draw_list_fill_poly_convex(struct nk_draw_list * list,const struct nk_vec2 * points,const unsigned int points_count,struct nk_color color,enum nk_anti_aliasing aliasing)654 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
655     const struct nk_vec2 *points, const unsigned int points_count,
656     struct nk_color color, enum nk_anti_aliasing aliasing)
657 {
658     struct nk_colorf col;
659     struct nk_colorf col_trans;
660 
661     NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
662     NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
663     NK_ASSERT(list);
664     if (!list || points_count < 3) return;
665 
666 #ifdef NK_INCLUDE_COMMAND_USERDATA
667     nk_draw_list_push_userdata(list, list->userdata);
668 #endif
669 
670     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
671     nk_color_fv(&col.r, color);
672     col_trans = col;
673     col_trans.a = 0;
674 
675     if (aliasing == NK_ANTI_ALIASING_ON) {
676         nk_size i = 0;
677         nk_size i0 = 0;
678         nk_size i1 = 0;
679 
680         const float AA_SIZE = 1.0f;
681         nk_size vertex_offset = 0;
682         nk_size index = list->vertex_count;
683 
684         const nk_size idx_count = (points_count-2)*3 + points_count*6;
685         const nk_size vtx_count = (points_count*2);
686 
687         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
688         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
689 
690         nk_size size = 0;
691         struct nk_vec2 *normals = 0;
692         unsigned int vtx_inner_idx = (unsigned int)(index + 0);
693         unsigned int vtx_outer_idx = (unsigned int)(index + 1);
694         if (!vtx || !ids) return;
695 
696         /* temporary allocate normals */
697         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
698         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
699         size = pnt_size * points_count;
700         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
701         if (!normals) return;
702         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
703 
704         /* add elements */
705         for (i = 2; i < points_count; i++) {
706             ids[0] = (nk_draw_index)(vtx_inner_idx);
707             ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
708             ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
709             ids += 3;
710         }
711 
712         /* compute normals */
713         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
714             struct nk_vec2 p0 = points[i0];
715             struct nk_vec2 p1 = points[i1];
716             struct nk_vec2 diff = nk_vec2_sub(p1, p0);
717 
718             /* vec2 inverted length  */
719             float len = nk_vec2_len_sqr(diff);
720             if (len != 0.0f)
721                 len = nk_inv_sqrt(len);
722             else len = 1.0f;
723             diff = nk_vec2_muls(diff, len);
724 
725             normals[i0].x = diff.y;
726             normals[i0].y = -diff.x;
727         }
728 
729         /* add vertices + indexes */
730         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
731             const struct nk_vec2 uv = list->config.null.uv;
732             struct nk_vec2 n0 = normals[i0];
733             struct nk_vec2 n1 = normals[i1];
734             struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
735             float dmr2 = dm.x*dm.x + dm.y*dm.y;
736             if (dmr2 > 0.000001f) {
737                 float scale = 1.0f / dmr2;
738                 scale = NK_MIN(scale, 100.0f);
739                 dm = nk_vec2_muls(dm, scale);
740             }
741             dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
742 
743             /* add vertices */
744             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
745             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
746 
747             /* add indexes */
748             ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
749             ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
750             ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
751             ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
752             ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
753             ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
754             ids += 6;
755         }
756         /* free temporary normals + points */
757         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
758     } else {
759         nk_size i = 0;
760         nk_size index = list->vertex_count;
761         const nk_size idx_count = (points_count-2)*3;
762         const nk_size vtx_count = points_count;
763         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
764         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
765 
766         if (!vtx || !ids) return;
767         for (i = 0; i < vtx_count; ++i)
768             vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
769         for (i = 2; i < points_count; ++i) {
770             ids[0] = (nk_draw_index)index;
771             ids[1] = (nk_draw_index)(index+ i - 1);
772             ids[2] = (nk_draw_index)(index+i);
773             ids += 3;
774         }
775     }
776 }
777 NK_API void
nk_draw_list_path_clear(struct nk_draw_list * list)778 nk_draw_list_path_clear(struct nk_draw_list *list)
779 {
780     NK_ASSERT(list);
781     if (!list) return;
782     nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
783     list->path_count = 0;
784     list->path_offset = 0;
785 }
786 NK_API void
nk_draw_list_path_line_to(struct nk_draw_list * list,struct nk_vec2 pos)787 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
788 {
789     struct nk_vec2 *points = 0;
790     struct nk_draw_command *cmd = 0;
791     NK_ASSERT(list);
792     if (!list) return;
793     if (!list->cmd_count)
794         nk_draw_list_add_clip(list, nk_null_rect);
795 
796     cmd = nk_draw_list_command_last(list);
797     if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
798         nk_draw_list_push_image(list, list->config.null.texture);
799 
800     points = nk_draw_list_alloc_path(list, 1);
801     if (!points) return;
802     points[0] = pos;
803 }
804 NK_API void
nk_draw_list_path_arc_to_fast(struct nk_draw_list * list,struct nk_vec2 center,float radius,int a_min,int a_max)805 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
806     float radius, int a_min, int a_max)
807 {
808     int a = 0;
809     NK_ASSERT(list);
810     if (!list) return;
811     if (a_min <= a_max) {
812         for (a = a_min; a <= a_max; a++) {
813             const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
814             const float x = center.x + c.x * radius;
815             const float y = center.y + c.y * radius;
816             nk_draw_list_path_line_to(list, nk_vec2(x, y));
817         }
818     }
819 }
820 NK_API void
nk_draw_list_path_arc_to(struct nk_draw_list * list,struct nk_vec2 center,float radius,float a_min,float a_max,unsigned int segments)821 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
822     float radius, float a_min, float a_max, unsigned int segments)
823 {
824     unsigned int i = 0;
825     NK_ASSERT(list);
826     if (!list) return;
827     if (radius == 0.0f) return;
828 
829     /*  This algorithm for arc drawing relies on these two trigonometric identities[1]:
830             sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
831             cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
832 
833         Two coordinates (x, y) of a point on a circle centered on
834         the origin can be written in polar form as:
835             x = r * cos(a)
836             y = r * sin(a)
837         where r is the radius of the circle,
838             a is the angle between (x, y) and the origin.
839 
840         This allows us to rotate the coordinates around the
841         origin by an angle b using the following transformation:
842             x' = r * cos(a + b) = x * cos(b) - y * sin(b)
843             y' = r * sin(a + b) = y * cos(b) + x * sin(b)
844 
845         [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
846     */
847     {const float d_angle = (a_max - a_min) / (float)segments;
848     const float sin_d = (float)NK_SIN(d_angle);
849     const float cos_d = (float)NK_COS(d_angle);
850 
851     float cx = (float)NK_COS(a_min) * radius;
852     float cy = (float)NK_SIN(a_min) * radius;
853     for(i = 0; i <= segments; ++i) {
854         float new_cx, new_cy;
855         const float x = center.x + cx;
856         const float y = center.y + cy;
857         nk_draw_list_path_line_to(list, nk_vec2(x, y));
858 
859         new_cx = cx * cos_d - cy * sin_d;
860         new_cy = cy * cos_d + cx * sin_d;
861         cx = new_cx;
862         cy = new_cy;
863     }}
864 }
865 NK_API void
nk_draw_list_path_rect_to(struct nk_draw_list * list,struct nk_vec2 a,struct nk_vec2 b,float rounding)866 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
867     struct nk_vec2 b, float rounding)
868 {
869     float r;
870     NK_ASSERT(list);
871     if (!list) return;
872     r = rounding;
873     r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
874     r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
875 
876     if (r == 0.0f) {
877         nk_draw_list_path_line_to(list, a);
878         nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
879         nk_draw_list_path_line_to(list, b);
880         nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
881     } else {
882         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
883         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
884         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
885         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
886     }
887 }
888 NK_API void
nk_draw_list_path_curve_to(struct nk_draw_list * list,struct nk_vec2 p2,struct nk_vec2 p3,struct nk_vec2 p4,unsigned int num_segments)889 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
890     struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
891 {
892     float t_step;
893     unsigned int i_step;
894     struct nk_vec2 p1;
895 
896     NK_ASSERT(list);
897     NK_ASSERT(list->path_count);
898     if (!list || !list->path_count) return;
899     num_segments = NK_MAX(num_segments, 1);
900 
901     p1 = nk_draw_list_path_last(list);
902     t_step = 1.0f/(float)num_segments;
903     for (i_step = 1; i_step <= num_segments; ++i_step) {
904         float t = t_step * (float)i_step;
905         float u = 1.0f - t;
906         float w1 = u*u*u;
907         float w2 = 3*u*u*t;
908         float w3 = 3*u*t*t;
909         float w4 = t * t *t;
910         float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
911         float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
912         nk_draw_list_path_line_to(list, nk_vec2(x,y));
913     }
914 }
915 NK_API void
nk_draw_list_path_fill(struct nk_draw_list * list,struct nk_color color)916 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
917 {
918     struct nk_vec2 *points;
919     NK_ASSERT(list);
920     if (!list) return;
921     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
922     nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
923     nk_draw_list_path_clear(list);
924 }
925 NK_API void
nk_draw_list_path_stroke(struct nk_draw_list * list,struct nk_color color,enum nk_draw_list_stroke closed,float thickness)926 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
927     enum nk_draw_list_stroke closed, float thickness)
928 {
929     struct nk_vec2 *points;
930     NK_ASSERT(list);
931     if (!list) return;
932     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
933     nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
934         closed, thickness, list->config.line_AA);
935     nk_draw_list_path_clear(list);
936 }
937 NK_API void
nk_draw_list_stroke_line(struct nk_draw_list * list,struct nk_vec2 a,struct nk_vec2 b,struct nk_color col,float thickness)938 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
939     struct nk_vec2 b, struct nk_color col, float thickness)
940 {
941     NK_ASSERT(list);
942     if (!list || !col.a) return;
943     if (list->line_AA == NK_ANTI_ALIASING_ON) {
944         nk_draw_list_path_line_to(list, a);
945         nk_draw_list_path_line_to(list, b);
946     } else {
947         nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
948         nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
949     }
950     nk_draw_list_path_stroke(list,  col, NK_STROKE_OPEN, thickness);
951 }
952 NK_API void
nk_draw_list_fill_rect(struct nk_draw_list * list,struct nk_rect rect,struct nk_color col,float rounding)953 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
954     struct nk_color col, float rounding)
955 {
956     NK_ASSERT(list);
957     if (!list || !col.a) return;
958 
959     if (list->line_AA == NK_ANTI_ALIASING_ON) {
960         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
961             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
962     } else {
963         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
964             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
965     } nk_draw_list_path_fill(list,  col);
966 }
967 NK_API void
nk_draw_list_stroke_rect(struct nk_draw_list * list,struct nk_rect rect,struct nk_color col,float rounding,float thickness)968 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
969     struct nk_color col, float rounding, float thickness)
970 {
971     NK_ASSERT(list);
972     if (!list || !col.a) return;
973     if (list->line_AA == NK_ANTI_ALIASING_ON) {
974         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
975             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
976     } else {
977         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
978             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
979     } nk_draw_list_path_stroke(list,  col, NK_STROKE_CLOSED, thickness);
980 }
981 NK_API void
nk_draw_list_fill_rect_multi_color(struct nk_draw_list * list,struct nk_rect rect,struct nk_color left,struct nk_color top,struct nk_color right,struct nk_color bottom)982 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
983     struct nk_color left, struct nk_color top, struct nk_color right,
984     struct nk_color bottom)
985 {
986     void *vtx;
987     struct nk_colorf col_left, col_top;
988     struct nk_colorf col_right, col_bottom;
989     nk_draw_index *idx;
990     nk_draw_index index;
991 
992     nk_color_fv(&col_left.r, left);
993     nk_color_fv(&col_right.r, right);
994     nk_color_fv(&col_top.r, top);
995     nk_color_fv(&col_bottom.r, bottom);
996 
997     NK_ASSERT(list);
998     if (!list) return;
999 
1000     nk_draw_list_push_image(list, list->config.null.texture);
1001     index = (nk_draw_index)list->vertex_count;
1002     vtx = nk_draw_list_alloc_vertices(list, 4);
1003     idx = nk_draw_list_alloc_elements(list, 6);
1004     if (!vtx || !idx) return;
1005 
1006     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
1007     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
1008     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
1009 
1010     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
1011     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
1012     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
1013     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
1014 }
1015 NK_API void
nk_draw_list_fill_triangle(struct nk_draw_list * list,struct nk_vec2 a,struct nk_vec2 b,struct nk_vec2 c,struct nk_color col)1016 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
1017     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
1018 {
1019     NK_ASSERT(list);
1020     if (!list || !col.a) return;
1021     nk_draw_list_path_line_to(list, a);
1022     nk_draw_list_path_line_to(list, b);
1023     nk_draw_list_path_line_to(list, c);
1024     nk_draw_list_path_fill(list, col);
1025 }
1026 NK_API void
nk_draw_list_stroke_triangle(struct nk_draw_list * list,struct nk_vec2 a,struct nk_vec2 b,struct nk_vec2 c,struct nk_color col,float thickness)1027 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
1028     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
1029 {
1030     NK_ASSERT(list);
1031     if (!list || !col.a) return;
1032     nk_draw_list_path_line_to(list, a);
1033     nk_draw_list_path_line_to(list, b);
1034     nk_draw_list_path_line_to(list, c);
1035     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
1036 }
1037 NK_API void
nk_draw_list_fill_circle(struct nk_draw_list * list,struct nk_vec2 center,float radius,struct nk_color col,unsigned int segs)1038 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
1039     float radius, struct nk_color col, unsigned int segs)
1040 {
1041     float a_max;
1042     NK_ASSERT(list);
1043     if (!list || !col.a) return;
1044     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
1045     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
1046     nk_draw_list_path_fill(list, col);
1047 }
1048 NK_API void
nk_draw_list_stroke_circle(struct nk_draw_list * list,struct nk_vec2 center,float radius,struct nk_color col,unsigned int segs,float thickness)1049 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
1050     float radius, struct nk_color col, unsigned int segs, float thickness)
1051 {
1052     float a_max;
1053     NK_ASSERT(list);
1054     if (!list || !col.a) return;
1055     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
1056     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
1057     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
1058 }
1059 NK_API void
nk_draw_list_stroke_curve(struct nk_draw_list * list,struct nk_vec2 p0,struct nk_vec2 cp0,struct nk_vec2 cp1,struct nk_vec2 p1,struct nk_color col,unsigned int segments,float thickness)1060 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
1061     struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
1062     struct nk_color col, unsigned int segments, float thickness)
1063 {
1064     NK_ASSERT(list);
1065     if (!list || !col.a) return;
1066     nk_draw_list_path_line_to(list, p0);
1067     nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
1068     nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
1069 }
1070 NK_INTERN void
nk_draw_list_push_rect_uv(struct nk_draw_list * list,struct nk_vec2 a,struct nk_vec2 c,struct nk_vec2 uva,struct nk_vec2 uvc,struct nk_color color)1071 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
1072     struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
1073     struct nk_color color)
1074 {
1075     void *vtx;
1076     struct nk_vec2 uvb;
1077     struct nk_vec2 uvd;
1078     struct nk_vec2 b;
1079     struct nk_vec2 d;
1080 
1081     struct nk_colorf col;
1082     nk_draw_index *idx;
1083     nk_draw_index index;
1084     NK_ASSERT(list);
1085     if (!list) return;
1086 
1087     nk_color_fv(&col.r, color);
1088     uvb = nk_vec2(uvc.x, uva.y);
1089     uvd = nk_vec2(uva.x, uvc.y);
1090     b = nk_vec2(c.x, a.y);
1091     d = nk_vec2(a.x, c.y);
1092 
1093     index = (nk_draw_index)list->vertex_count;
1094     vtx = nk_draw_list_alloc_vertices(list, 4);
1095     idx = nk_draw_list_alloc_elements(list, 6);
1096     if (!vtx || !idx) return;
1097 
1098     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
1099     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
1100     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
1101 
1102     vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
1103     vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
1104     vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
1105     vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
1106 }
1107 NK_API void
nk_draw_list_add_image(struct nk_draw_list * list,struct nk_image texture,struct nk_rect rect,struct nk_color color)1108 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
1109     struct nk_rect rect, struct nk_color color)
1110 {
1111     NK_ASSERT(list);
1112     if (!list) return;
1113     /* push new command with given texture */
1114     nk_draw_list_push_image(list, texture.handle);
1115     if (nk_image_is_subimage(&texture)) {
1116         /* add region inside of the texture  */
1117         struct nk_vec2 uv[2];
1118         uv[0].x = (float)texture.region[0]/(float)texture.w;
1119         uv[0].y = (float)texture.region[1]/(float)texture.h;
1120         uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
1121         uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
1122         nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
1123             nk_vec2(rect.x + rect.w, rect.y + rect.h),  uv[0], uv[1], color);
1124     } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
1125             nk_vec2(rect.x + rect.w, rect.y + rect.h),
1126             nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
1127 }
1128 NK_API void
nk_draw_list_add_text(struct nk_draw_list * list,const struct nk_user_font * font,struct nk_rect rect,const char * text,int len,float font_height,struct nk_color fg)1129 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
1130     struct nk_rect rect, const char *text, int len, float font_height,
1131     struct nk_color fg)
1132 {
1133     float x = 0;
1134     int text_len = 0;
1135     nk_rune unicode = 0;
1136     nk_rune next = 0;
1137     int glyph_len = 0;
1138     int next_glyph_len = 0;
1139     struct nk_user_font_glyph g;
1140 
1141     NK_ASSERT(list);
1142     if (!list || !len || !text) return;
1143     if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
1144         list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
1145 
1146     nk_draw_list_push_image(list, font->texture);
1147     x = rect.x;
1148     glyph_len = nk_utf_decode(text, &unicode, len);
1149     if (!glyph_len) return;
1150 
1151     /* draw every glyph image */
1152     fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
1153     while (text_len < len && glyph_len) {
1154         float gx, gy, gh, gw;
1155         float char_width = 0;
1156         if (unicode == NK_UTF_INVALID) break;
1157 
1158         /* query currently drawn glyph information */
1159         next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
1160         font->query(font->userdata, font_height, &g, unicode,
1161                     (next == NK_UTF_INVALID) ? '\0' : next);
1162 
1163         /* calculate and draw glyph drawing rectangle and image */
1164         gx = x + g.offset.x;
1165         gy = rect.y + g.offset.y;
1166         gw = g.width; gh = g.height;
1167         char_width = g.xadvance;
1168         nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
1169             g.uv[0], g.uv[1], fg);
1170 
1171         /* offset next glyph */
1172         text_len += glyph_len;
1173         x += char_width;
1174         glyph_len = next_glyph_len;
1175         unicode = next;
1176     }
1177 }
1178 NK_API nk_flags
nk_convert(struct nk_context * ctx,struct nk_buffer * cmds,struct nk_buffer * vertices,struct nk_buffer * elements,const struct nk_convert_config * config)1179 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
1180     struct nk_buffer *vertices, struct nk_buffer *elements,
1181     const struct nk_convert_config *config)
1182 {
1183     nk_flags res = NK_CONVERT_SUCCESS;
1184     const struct nk_command *cmd;
1185     NK_ASSERT(ctx);
1186     NK_ASSERT(cmds);
1187     NK_ASSERT(vertices);
1188     NK_ASSERT(elements);
1189     NK_ASSERT(config);
1190     NK_ASSERT(config->vertex_layout);
1191     NK_ASSERT(config->vertex_size);
1192     if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
1193         return NK_CONVERT_INVALID_PARAM;
1194 
1195     nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
1196         config->line_AA, config->shape_AA);
1197     nk_foreach(cmd, ctx)
1198     {
1199 #ifdef NK_INCLUDE_COMMAND_USERDATA
1200         ctx->draw_list.userdata = cmd->userdata;
1201 #endif
1202         switch (cmd->type) {
1203         case NK_COMMAND_NOP: break;
1204         case NK_COMMAND_SCISSOR: {
1205             const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
1206             nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
1207         } break;
1208         case NK_COMMAND_LINE: {
1209             const struct nk_command_line *l = (const struct nk_command_line*)cmd;
1210             nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
1211                 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
1212         } break;
1213         case NK_COMMAND_CURVE: {
1214             const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
1215             nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
1216                 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
1217                 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
1218                 config->curve_segment_count, q->line_thickness);
1219         } break;
1220         case NK_COMMAND_RECT: {
1221             const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
1222             nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
1223                 r->color, (float)r->rounding, r->line_thickness);
1224         } break;
1225         case NK_COMMAND_RECT_FILLED: {
1226             const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
1227             nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
1228                 r->color, (float)r->rounding);
1229         } break;
1230         case NK_COMMAND_RECT_MULTI_COLOR: {
1231             const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
1232             nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
1233                 r->left, r->top, r->right, r->bottom);
1234         } break;
1235         case NK_COMMAND_CIRCLE: {
1236             const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
1237             nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
1238                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
1239                 config->circle_segment_count, c->line_thickness);
1240         } break;
1241         case NK_COMMAND_CIRCLE_FILLED: {
1242             const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
1243             nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
1244                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
1245                 config->circle_segment_count);
1246         } break;
1247         case NK_COMMAND_ARC: {
1248             const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
1249             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
1250             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
1251                 c->a[0], c->a[1], config->arc_segment_count);
1252             nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
1253         } break;
1254         case NK_COMMAND_ARC_FILLED: {
1255             const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
1256             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
1257             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
1258                 c->a[0], c->a[1], config->arc_segment_count);
1259             nk_draw_list_path_fill(&ctx->draw_list, c->color);
1260         } break;
1261         case NK_COMMAND_TRIANGLE: {
1262             const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
1263             nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
1264                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
1265                 t->line_thickness);
1266         } break;
1267         case NK_COMMAND_TRIANGLE_FILLED: {
1268             const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
1269             nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
1270                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
1271         } break;
1272         case NK_COMMAND_POLYGON: {
1273             int i;
1274             const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
1275             for (i = 0; i < p->point_count; ++i) {
1276                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
1277                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
1278             }
1279             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
1280         } break;
1281         case NK_COMMAND_POLYGON_FILLED: {
1282             int i;
1283             const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
1284             for (i = 0; i < p->point_count; ++i) {
1285                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
1286                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
1287             }
1288             nk_draw_list_path_fill(&ctx->draw_list, p->color);
1289         } break;
1290         case NK_COMMAND_POLYLINE: {
1291             int i;
1292             const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
1293             for (i = 0; i < p->point_count; ++i) {
1294                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
1295                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
1296             }
1297             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
1298         } break;
1299         case NK_COMMAND_TEXT: {
1300             const struct nk_command_text *t = (const struct nk_command_text*)cmd;
1301             nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
1302                 t->string, t->length, t->height, t->foreground);
1303         } break;
1304         case NK_COMMAND_IMAGE: {
1305             const struct nk_command_image *i = (const struct nk_command_image*)cmd;
1306             nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
1307         } break;
1308         case NK_COMMAND_CUSTOM: {
1309             const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
1310             c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
1311         } break;
1312         default: break;
1313         }
1314     }
1315     res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
1316     res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
1317     res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
1318     return res;
1319 }
1320 NK_API const struct nk_draw_command*
nk__draw_begin(const struct nk_context * ctx,const struct nk_buffer * buffer)1321 nk__draw_begin(const struct nk_context *ctx,
1322     const struct nk_buffer *buffer)
1323 {
1324     return nk__draw_list_begin(&ctx->draw_list, buffer);
1325 }
1326 NK_API const struct nk_draw_command*
nk__draw_end(const struct nk_context * ctx,const struct nk_buffer * buffer)1327 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
1328 {
1329     return nk__draw_list_end(&ctx->draw_list, buffer);
1330 }
1331 NK_API const struct nk_draw_command*
nk__draw_next(const struct nk_draw_command * cmd,const struct nk_buffer * buffer,const struct nk_context * ctx)1332 nk__draw_next(const struct nk_draw_command *cmd,
1333     const struct nk_buffer *buffer, const struct nk_context *ctx)
1334 {
1335     return nk__draw_list_next(cmd, buffer, &ctx->draw_list);
1336 }
1337 #endif
1338 
1339