Selaa lähdekoodia

Converted backend demos into single header files

vurtun 9 vuotta sitten
vanhempi
commit
f5dc2906a8

+ 3 - 7
demo/allegro5/main.c

@@ -10,9 +10,6 @@
 #include <limits.h>
 #include <time.h>
 
-#include <allegro5/allegro.h>
-#include <allegro5/allegro_primitives.h>
-
 /* macros */
 #define WINDOW_WIDTH 800
 #define WINDOW_HEIGHT 600
@@ -20,17 +17,16 @@
 #define MAX_VERTEX_MEMORY 512 * 1024
 #define MAX_ELEMENT_MEMORY 128 * 1024
 
-/* these defines are both needed for the header
- * and source file. So if you split them remember
- * to copy them as well. */
 #define NK_INCLUDE_FIXED_TYPES
 #define NK_INCLUDE_STANDARD_IO
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
 #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
 #define NK_INCLUDE_FONT_BAKING
 #define NK_INCLUDE_DEFAULT_FONT
+#define NK_IMPLEMENTATION
+#define NK_ALLEGRO_IMPLEMENTATION
+#include "../../nuklear.h"
 #include "nuklear_allegro.h"
-#include "nuklear_allegro.c"
 
 #define UNUSED(a) (void)a
 #define MIN(a,b) ((a) < (b) ? (a) : (b))

+ 0 - 271
demo/allegro5/nuklear_allegro.c

@@ -1,271 +0,0 @@
-#define NK_IMPLEMENTATION
-#include "../../nuklear.h"
-
-#include <allegro5/allegro.h>
-#include <allegro5/allegro_primitives.h>
-
-struct nk_allegro_device {
-    ALLEGRO_BITMAP *texture;
-    ALLEGRO_VERTEX_DECL *vertex_decl;
-    struct nk_draw_null_texture null;
-    struct nk_buffer cmds;
-    void *vertex_buffer;
-    void *element_buffer;
-    int max_vertex_memory;
-    int max_element_memory;
-};
-
-struct nk_allegro_vertex {
-    struct nk_vec2 pos;
-    struct nk_vec2 uv;
-    ALLEGRO_COLOR col;
-};
-
-static struct {
-    ALLEGRO_DISPLAY *win;
-    struct nk_allegro_device dev;
-    struct nk_context ctx;
-    struct nk_font_atlas atlas;
-} allegro;
-
-
-NK_API void
-nk_allegro_device_create(int max_vertex_memory, int max_element_memory)
-{
-    struct nk_allegro_device *dev = &allegro.dev;
-    ALLEGRO_VERTEX_ELEMENT elems[] = {
-        {ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, offsetof(struct nk_allegro_vertex, pos)},
-        {ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(struct nk_allegro_vertex, uv)},
-        {ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(struct nk_allegro_vertex, col)},
-        {0,0,0}
-    };
-    dev->vertex_decl = al_create_vertex_decl(elems, sizeof(struct nk_allegro_vertex));
-    dev->vertex_buffer = calloc((size_t)max_vertex_memory, 1);
-    dev->element_buffer = calloc((size_t)max_element_memory, 1);
-    dev->max_vertex_memory = max_vertex_memory;
-    dev->max_element_memory = max_element_memory;
-    nk_buffer_init_default(&dev->cmds);
-}
-
-static void
-nk_allegro_device_upload_atlas(const void *image, int width, int height)
-{
-    /* create allegro font bitmap */
-    ALLEGRO_BITMAP *bitmap = 0;
-    struct nk_allegro_device *dev = &allegro.dev;
-    int flags = al_get_new_bitmap_flags();
-    int fmt = al_get_new_bitmap_format();
-    al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP|ALLEGRO_MIN_LINEAR|ALLEGRO_MAG_LINEAR);
-    al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE);
-    bitmap = al_create_bitmap(width, height);
-    al_set_new_bitmap_flags(flags);
-    al_set_new_bitmap_format(fmt);
-    assert(bitmap);
-
-    {/* copy font texture into bitmap */
-    ALLEGRO_LOCKED_REGION * locked_img;
-    locked_img = al_lock_bitmap(bitmap, al_get_bitmap_format(bitmap), ALLEGRO_LOCK_WRITEONLY);
-    assert(locked_img);
-    memcpy(locked_img->data, image, sizeof(uint32_t)*(size_t)(width*height));
-    al_unlock_bitmap(bitmap);}
-
-    /* convert software texture into hardware texture */
-    dev->texture = al_clone_bitmap(bitmap);
-    al_destroy_bitmap(bitmap);
-    assert(dev->texture);
-}
-
-NK_API void
-nk_allegro_render(enum nk_anti_aliasing AA)
-{
-    int op, src, dst;
-    struct nk_allegro_device *dev = &allegro.dev;
-    struct nk_context *ctx = &allegro.ctx;
-    al_get_blender(&op, &src, &dst);
-    al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
-
-    {
-        const struct nk_draw_command *cmd;
-        struct nk_buffer vbuf, ebuf;
-        int offset = 0;
-        struct nk_allegro_vertex *vertices = 0;
-        int *indices = 0;
-
-        /* fill converting configuration */
-        struct nk_convert_config config;
-        memset(&config, 0, sizeof(config));
-        config.global_alpha = 1.0f;
-        config.shape_AA = AA;
-        config.line_AA = AA;
-        config.circle_segment_count = 22;
-        config.arc_segment_count = 22;
-        config.curve_segment_count = 22;
-        config.null = dev->null;
-
-        /* convert from command into hardware format */
-        nk_buffer_init_fixed(&vbuf, dev->vertex_buffer, (nk_size)dev->max_vertex_memory);
-        nk_buffer_init_fixed(&ebuf, dev->element_buffer, (nk_size)dev->max_element_memory);
-            nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);
-
-        {
-            /* <sign> allegro does not support 32-bit packed color */
-            unsigned int i = 0;
-            struct nk_draw_vertex *verts = (struct nk_draw_vertex*)dev->vertex_buffer;
-            vertices = (struct nk_allegro_vertex*)calloc(sizeof(struct nk_allegro_vertex), ctx->draw_list.vertex_count);
-            for (i = 0; i < ctx->draw_list.vertex_count; ++i) {
-                nk_byte *c;
-                vertices[i].pos = verts[i].position;
-                vertices[i].uv = verts[i].uv;
-                c = (nk_byte*)&verts[i].col;
-                vertices[i].col = al_map_rgba(c[0], c[1], c[2], c[3]);
-            }
-        }
-        {
-            /* <massive sign> allegro does not support 16-bit indices:
-             * @OPT: define nk_draw_index as int to fix this issue. */
-            unsigned int i = 0;
-            nk_draw_index *elements = (nk_draw_index*)dev->element_buffer;
-            indices = (int*)calloc(sizeof(int), ctx->draw_list.element_count);
-            for (i = 0; i < ctx->draw_list.element_count; ++i)
-                indices[i] = elements[i];
-        }
-
-        /* iterate over and execute each draw command */
-        nk_draw_foreach(cmd, ctx, &dev->cmds)
-        {
-            ALLEGRO_BITMAP *texture = (ALLEGRO_BITMAP*)cmd->texture.ptr;
-            if (!cmd->elem_count) continue;
-            al_set_clipping_rectangle((int)cmd->clip_rect.x, (int)cmd->clip_rect.y,
-                (int)cmd->clip_rect.w, (int)cmd->clip_rect.h);
-            al_draw_indexed_prim(vertices, dev->vertex_decl, texture, &indices[offset],
-                (int)cmd->elem_count, ALLEGRO_PRIM_TRIANGLE_LIST);
-            offset += cmd->elem_count;
-        }
-
-        free(vertices);
-        free(indices);
-        nk_clear(ctx);
-    }
-    al_set_blender(op, src, dst);
-    al_set_clipping_rectangle(0,0, al_get_display_width(allegro.win),
-        al_get_display_height(allegro.win));
-}
-
-NK_API void
-nk_allegro_device_destroy(void)
-{
-    struct nk_allegro_device *dev = &allegro.dev;
-    free(dev->vertex_buffer);
-    free(dev->element_buffer);
-    nk_buffer_free(&dev->cmds);
-}
-
-
-NK_API struct nk_context*
-nk_allegro_init(ALLEGRO_DISPLAY *win, int max_vertex_memory, int max_element_memory)
-{
-    allegro.win = win;
-    nk_init_default(&allegro.ctx, 0);
-    nk_allegro_device_create(max_vertex_memory, max_element_memory);
-    return &allegro.ctx;
-}
-
-NK_API void
-nk_allegro_font_stash_begin(struct nk_font_atlas **atlas)
-{
-    nk_font_atlas_init_default(&allegro.atlas);
-    nk_font_atlas_begin(&allegro.atlas);
-    *atlas = &allegro.atlas;
-}
-
-NK_API void
-nk_allegro_font_stash_end(void)
-{
-    const void *image; int w, h;
-    image = nk_font_atlas_bake(&allegro.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
-    nk_allegro_device_upload_atlas(image, w, h);
-    nk_font_atlas_end(&allegro.atlas, nk_handle_ptr(allegro.dev.texture), &allegro.dev.null);
-    if (allegro.atlas.default_font)
-        nk_style_set_font(&allegro.ctx, &allegro.atlas.default_font->handle);
-}
-
-
-NK_API void
-nk_allegro_handle_event(ALLEGRO_EVENT *evt)
-{
-    struct nk_context *ctx = &allegro.ctx;
-    if ((evt->type == ALLEGRO_EVENT_KEY_UP ||
-            evt->type == ALLEGRO_EVENT_KEY_DOWN) &&
-            evt->keyboard.display == allegro.win)
-    {
-        /* key handler */
-        int down = (evt->type == ALLEGRO_EVENT_KEY_UP);
-        int sym = evt->keyboard.keycode;
-        if (sym == ALLEGRO_KEY_RSHIFT || sym == ALLEGRO_KEY_LSHIFT)
-            nk_input_key(ctx, NK_KEY_SHIFT, down);
-        else if (sym == ALLEGRO_KEY_DELETE)
-            nk_input_key(ctx, NK_KEY_DEL, down);
-        else if (sym == ALLEGRO_KEY_ENTER)
-            nk_input_key(ctx, NK_KEY_ENTER, down);
-        else if (sym == ALLEGRO_KEY_TAB)
-            nk_input_key(ctx, NK_KEY_TAB, down);
-        else if (sym == ALLEGRO_KEY_BACKSPACE)
-            nk_input_key(ctx, NK_KEY_BACKSPACE, down);
-        else if (sym == ALLEGRO_KEY_LEFT) {
-            if (evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL)
-                nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
-            else nk_input_key(ctx, NK_KEY_LEFT, down);
-        } else if (sym == ALLEGRO_KEY_RIGHT) {
-            if (evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL)
-                nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
-            else nk_input_key(ctx, NK_KEY_RIGHT, down);
-        } else if (sym == ALLEGRO_KEY_HOME)
-            nk_input_key(ctx, NK_KEY_TEXT_START, down);
-        else if (sym == ALLEGRO_KEY_END)
-            nk_input_key(ctx, NK_KEY_TEXT_END, down);
-        else if (sym == ALLEGRO_KEY_C)
-            nk_input_key(ctx, NK_KEY_COPY, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
-        else if (sym == ALLEGRO_KEY_V)
-            nk_input_key(ctx, NK_KEY_PASTE, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
-        else if (sym == ALLEGRO_KEY_X)
-            nk_input_key(ctx, NK_KEY_CUT, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
-        else if (sym == ALLEGRO_KEY_Z)
-            nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
-        else if (sym == ALLEGRO_KEY_R)
-            nk_input_key(ctx, NK_KEY_TEXT_REDO, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
-        else if (sym == ALLEGRO_KEY_X)
-            nk_input_key(ctx, NK_KEY_CUT, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
-        else if (sym == ALLEGRO_KEY_B)
-            nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
-        else if (sym == ALLEGRO_KEY_E)
-            nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
-
-    } else if (evt->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN ||
-                evt->type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
-        /* button handler */
-        int down = evt->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN;
-        const int x = evt->mouse.x, y = evt->mouse.y;
-        if (evt->mouse.button == 1)
-            nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
-        if (evt->mouse.button == 2)
-            nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
-    } else if (evt->type == ALLEGRO_EVENT_MOUSE_AXES) {
-        /* mouse motion */
-        nk_input_motion(ctx, evt->mouse.x, evt->mouse.y);
-    } else if (evt->type == ALLEGRO_EVENT_KEY_CHAR) {
-        /* text input */
-        if (evt->keyboard.display == allegro.win)
-            if (evt->keyboard.unichar > 0 && evt->keyboard.unichar < 0x10000)
-                nk_input_unicode(ctx, (nk_rune)evt->keyboard.unichar);
-    }
-}
-
-NK_API void
-nk_allegro_shutdown(void)
-{
-    if (allegro.dev.texture)
-        al_destroy_bitmap(allegro.dev.texture);
-    free(allegro.dev.vertex_buffer);
-    free(allegro.dev.element_buffer);
-}
-

+ 291 - 2
demo/allegro5/nuklear_allegro.h

@@ -1,8 +1,19 @@
+/*
+ * Nuklear - v1.00 - public domain
+ * no warrenty implied; use at your own risk.
+ * authored from 2015-2016 by Micha Mettke
+ */
+/*
+ * ==============================================================
+ *
+ *                              API
+ *
+ * ===============================================================
+ */
 #ifndef NK_ALLEGRO_H_
 #define NK_ALLEGRO_H_
 
-#include "../../nuklear.h"
-
+#include <allegro5/allegro.h>
 NK_API struct nk_context* nk_allegro_init(ALLEGRO_DISPLAY *win, int max_vertex_memory, int max_element_memory);
 NK_API void nk_allegro_font_stash_begin(struct nk_font_atlas **atlas);
 NK_API void nk_allegro_font_stash_end(void);
@@ -15,3 +26,281 @@ NK_API void nk_allegro_device_destroy(void);
 NK_API void nk_allegro_device_create(int max_vertex_memory, int max_elemnt_memory);
 
 #endif
+
+/*
+ * ==============================================================
+ *
+ *                          IMPLEMENTATION
+ *
+ * ===============================================================
+ */
+#ifdef NK_ALLEGRO_IMPLEMENTATION
+
+#include <allegro5/allegro_primitives.h>
+
+struct nk_allegro_device {
+    ALLEGRO_BITMAP *texture;
+    ALLEGRO_VERTEX_DECL *vertex_decl;
+    struct nk_draw_null_texture null;
+    struct nk_buffer cmds;
+    void *vertex_buffer;
+    void *element_buffer;
+    int max_vertex_memory;
+    int max_element_memory;
+};
+
+struct nk_allegro_vertex {
+    struct nk_vec2 pos;
+    struct nk_vec2 uv;
+    ALLEGRO_COLOR col;
+};
+
+static struct {
+    ALLEGRO_DISPLAY *win;
+    struct nk_allegro_device dev;
+    struct nk_context ctx;
+    struct nk_font_atlas atlas;
+} allegro;
+
+
+NK_API void
+nk_allegro_device_create(int max_vertex_memory, int max_element_memory)
+{
+    struct nk_allegro_device *dev = &allegro.dev;
+    ALLEGRO_VERTEX_ELEMENT elems[] = {
+        {ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, offsetof(struct nk_allegro_vertex, pos)},
+        {ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(struct nk_allegro_vertex, uv)},
+        {ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(struct nk_allegro_vertex, col)},
+        {0,0,0}
+    };
+    dev->vertex_decl = al_create_vertex_decl(elems, sizeof(struct nk_allegro_vertex));
+    dev->vertex_buffer = calloc((size_t)max_vertex_memory, 1);
+    dev->element_buffer = calloc((size_t)max_element_memory, 1);
+    dev->max_vertex_memory = max_vertex_memory;
+    dev->max_element_memory = max_element_memory;
+    nk_buffer_init_default(&dev->cmds);
+}
+
+static void
+nk_allegro_device_upload_atlas(const void *image, int width, int height)
+{
+    /* create allegro font bitmap */
+    ALLEGRO_BITMAP *bitmap = 0;
+    struct nk_allegro_device *dev = &allegro.dev;
+    int flags = al_get_new_bitmap_flags();
+    int fmt = al_get_new_bitmap_format();
+    al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP|ALLEGRO_MIN_LINEAR|ALLEGRO_MAG_LINEAR);
+    al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE);
+    bitmap = al_create_bitmap(width, height);
+    al_set_new_bitmap_flags(flags);
+    al_set_new_bitmap_format(fmt);
+    assert(bitmap);
+
+    {/* copy font texture into bitmap */
+    ALLEGRO_LOCKED_REGION * locked_img;
+    locked_img = al_lock_bitmap(bitmap, al_get_bitmap_format(bitmap), ALLEGRO_LOCK_WRITEONLY);
+    assert(locked_img);
+    memcpy(locked_img->data, image, sizeof(uint32_t)*(size_t)(width*height));
+    al_unlock_bitmap(bitmap);}
+
+    /* convert software texture into hardware texture */
+    dev->texture = al_clone_bitmap(bitmap);
+    al_destroy_bitmap(bitmap);
+    assert(dev->texture);
+}
+
+NK_API void
+nk_allegro_render(enum nk_anti_aliasing AA)
+{
+    int op, src, dst;
+    struct nk_allegro_device *dev = &allegro.dev;
+    struct nk_context *ctx = &allegro.ctx;
+    al_get_blender(&op, &src, &dst);
+    al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
+
+    {
+        const struct nk_draw_command *cmd;
+        struct nk_buffer vbuf, ebuf;
+        int offset = 0;
+        struct nk_allegro_vertex *vertices = 0;
+        int *indices = 0;
+
+        /* fill converting configuration */
+        struct nk_convert_config config;
+        memset(&config, 0, sizeof(config));
+        config.global_alpha = 1.0f;
+        config.shape_AA = AA;
+        config.line_AA = AA;
+        config.circle_segment_count = 22;
+        config.arc_segment_count = 22;
+        config.curve_segment_count = 22;
+        config.null = dev->null;
+
+        /* convert from command into hardware format */
+        nk_buffer_init_fixed(&vbuf, dev->vertex_buffer, (nk_size)dev->max_vertex_memory);
+        nk_buffer_init_fixed(&ebuf, dev->element_buffer, (nk_size)dev->max_element_memory);
+            nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);
+
+        {
+            /* <sign> allegro does not support 32-bit packed color */
+            unsigned int i = 0;
+            struct nk_draw_vertex *verts = (struct nk_draw_vertex*)dev->vertex_buffer;
+            vertices = (struct nk_allegro_vertex*)calloc(sizeof(struct nk_allegro_vertex), ctx->draw_list.vertex_count);
+            for (i = 0; i < ctx->draw_list.vertex_count; ++i) {
+                nk_byte *c;
+                vertices[i].pos = verts[i].position;
+                vertices[i].uv = verts[i].uv;
+                c = (nk_byte*)&verts[i].col;
+                vertices[i].col = al_map_rgba(c[0], c[1], c[2], c[3]);
+            }
+        }
+        {
+            /* <massive sign> allegro does not support 16-bit indices:
+             * @OPT: define nk_draw_index as int to fix this issue. */
+            unsigned int i = 0;
+            nk_draw_index *elements = (nk_draw_index*)dev->element_buffer;
+            indices = (int*)calloc(sizeof(int), ctx->draw_list.element_count);
+            for (i = 0; i < ctx->draw_list.element_count; ++i)
+                indices[i] = elements[i];
+        }
+
+        /* iterate over and execute each draw command */
+        nk_draw_foreach(cmd, ctx, &dev->cmds)
+        {
+            ALLEGRO_BITMAP *texture = (ALLEGRO_BITMAP*)cmd->texture.ptr;
+            if (!cmd->elem_count) continue;
+            al_set_clipping_rectangle((int)cmd->clip_rect.x, (int)cmd->clip_rect.y,
+                (int)cmd->clip_rect.w, (int)cmd->clip_rect.h);
+            al_draw_indexed_prim(vertices, dev->vertex_decl, texture, &indices[offset],
+                (int)cmd->elem_count, ALLEGRO_PRIM_TRIANGLE_LIST);
+            offset += cmd->elem_count;
+        }
+
+        free(vertices);
+        free(indices);
+        nk_clear(ctx);
+    }
+    al_set_blender(op, src, dst);
+    al_set_clipping_rectangle(0,0, al_get_display_width(allegro.win),
+        al_get_display_height(allegro.win));
+}
+
+NK_API void
+nk_allegro_device_destroy(void)
+{
+    struct nk_allegro_device *dev = &allegro.dev;
+    free(dev->vertex_buffer);
+    free(dev->element_buffer);
+    nk_buffer_free(&dev->cmds);
+}
+
+
+NK_API struct nk_context*
+nk_allegro_init(ALLEGRO_DISPLAY *win, int max_vertex_memory, int max_element_memory)
+{
+    allegro.win = win;
+    nk_init_default(&allegro.ctx, 0);
+    nk_allegro_device_create(max_vertex_memory, max_element_memory);
+    return &allegro.ctx;
+}
+
+NK_API void
+nk_allegro_font_stash_begin(struct nk_font_atlas **atlas)
+{
+    nk_font_atlas_init_default(&allegro.atlas);
+    nk_font_atlas_begin(&allegro.atlas);
+    *atlas = &allegro.atlas;
+}
+
+NK_API void
+nk_allegro_font_stash_end(void)
+{
+    const void *image; int w, h;
+    image = nk_font_atlas_bake(&allegro.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
+    nk_allegro_device_upload_atlas(image, w, h);
+    nk_font_atlas_end(&allegro.atlas, nk_handle_ptr(allegro.dev.texture), &allegro.dev.null);
+    if (allegro.atlas.default_font)
+        nk_style_set_font(&allegro.ctx, &allegro.atlas.default_font->handle);
+}
+
+
+NK_API void
+nk_allegro_handle_event(ALLEGRO_EVENT *evt)
+{
+    struct nk_context *ctx = &allegro.ctx;
+    if ((evt->type == ALLEGRO_EVENT_KEY_UP ||
+            evt->type == ALLEGRO_EVENT_KEY_DOWN) &&
+            evt->keyboard.display == allegro.win)
+    {
+        /* key handler */
+        int down = (evt->type == ALLEGRO_EVENT_KEY_UP);
+        int sym = evt->keyboard.keycode;
+        if (sym == ALLEGRO_KEY_RSHIFT || sym == ALLEGRO_KEY_LSHIFT)
+            nk_input_key(ctx, NK_KEY_SHIFT, down);
+        else if (sym == ALLEGRO_KEY_DELETE)
+            nk_input_key(ctx, NK_KEY_DEL, down);
+        else if (sym == ALLEGRO_KEY_ENTER)
+            nk_input_key(ctx, NK_KEY_ENTER, down);
+        else if (sym == ALLEGRO_KEY_TAB)
+            nk_input_key(ctx, NK_KEY_TAB, down);
+        else if (sym == ALLEGRO_KEY_BACKSPACE)
+            nk_input_key(ctx, NK_KEY_BACKSPACE, down);
+        else if (sym == ALLEGRO_KEY_LEFT) {
+            if (evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL)
+                nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
+            else nk_input_key(ctx, NK_KEY_LEFT, down);
+        } else if (sym == ALLEGRO_KEY_RIGHT) {
+            if (evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL)
+                nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
+            else nk_input_key(ctx, NK_KEY_RIGHT, down);
+        } else if (sym == ALLEGRO_KEY_HOME)
+            nk_input_key(ctx, NK_KEY_TEXT_START, down);
+        else if (sym == ALLEGRO_KEY_END)
+            nk_input_key(ctx, NK_KEY_TEXT_END, down);
+        else if (sym == ALLEGRO_KEY_C)
+            nk_input_key(ctx, NK_KEY_COPY, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
+        else if (sym == ALLEGRO_KEY_V)
+            nk_input_key(ctx, NK_KEY_PASTE, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
+        else if (sym == ALLEGRO_KEY_X)
+            nk_input_key(ctx, NK_KEY_CUT, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
+        else if (sym == ALLEGRO_KEY_Z)
+            nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
+        else if (sym == ALLEGRO_KEY_R)
+            nk_input_key(ctx, NK_KEY_TEXT_REDO, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
+        else if (sym == ALLEGRO_KEY_X)
+            nk_input_key(ctx, NK_KEY_CUT, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
+        else if (sym == ALLEGRO_KEY_B)
+            nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
+        else if (sym == ALLEGRO_KEY_E)
+            nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
+
+    } else if (evt->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN ||
+                evt->type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
+        /* button handler */
+        int down = evt->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN;
+        const int x = evt->mouse.x, y = evt->mouse.y;
+        if (evt->mouse.button == 1)
+            nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
+        if (evt->mouse.button == 2)
+            nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
+    } else if (evt->type == ALLEGRO_EVENT_MOUSE_AXES) {
+        /* mouse motion */
+        nk_input_motion(ctx, evt->mouse.x, evt->mouse.y);
+    } else if (evt->type == ALLEGRO_EVENT_KEY_CHAR) {
+        /* text input */
+        if (evt->keyboard.display == allegro.win)
+            if (evt->keyboard.unichar > 0 && evt->keyboard.unichar < 0x10000)
+                nk_input_unicode(ctx, (nk_rune)evt->keyboard.unichar);
+    }
+}
+
+NK_API void
+nk_allegro_shutdown(void)
+{
+    if (allegro.dev.texture)
+        al_destroy_bitmap(allegro.dev.texture);
+    free(allegro.dev.vertex_buffer);
+    free(allegro.dev.element_buffer);
+}
+
+#endif

+ 4 - 5
demo/glfw_opengl2/main.c

@@ -12,17 +12,16 @@
 
 #include <GLFW/glfw3.h>
 
-/* these defines are both needed for the header
- * and source file. So if you split them remember
- * to copy them as well. */
 #define NK_INCLUDE_FIXED_TYPES
 #define NK_INCLUDE_STANDARD_IO
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
 #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
 #define NK_INCLUDE_FONT_BAKING
 #define NK_INCLUDE_DEFAULT_FONT
-#include "nuklear_glfw.h"
-#include "nuklear_glfw.c"
+#define NK_IMPLEMENTATION
+#define NK_GLFW_GL2_IMPLEMENTATION
+#include "../../nuklear.h"
+#include "nuklear_glfw_gl2.h"
 
 #define WINDOW_WIDTH 1200
 #define WINDOW_HEIGHT 800

+ 0 - 20
demo/glfw_opengl2/nuklear_glfw.h

@@ -1,20 +0,0 @@
-#ifndef NK_GLFW_H_
-#define NK_GLFW_H_
-
-#include "../../nuklear.h"
-
-#include <GLFW/glfw3.h>
-
-enum nk_glfw_init_state{NK_GLFW3_DEFAULT=0, NK_GLFW3_INSTALL_CALLBACKS};
-NK_API struct nk_context *nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
-NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
-NK_API void nk_glfw3_font_stash_end(void);
-
-NK_API void nk_glfw3_new_frame(void);
-NK_API void nk_glfw3_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
-NK_API void nk_glfw3_shutdown(void);
-
-NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
-NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
-
-#endif

+ 47 - 14
demo/glfw_opengl2/nuklear_glfw.c → demo/glfw_opengl2/nuklear_glfw_gl2.h

@@ -1,19 +1,50 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-#include <math.h>
-#include <time.h>
-#include <limits.h>
-
-#define NK_IMPLEMENTATION
-#include "nuklear_glfw.h"
-#include "../../nuklear.h"
+/*
+ * Nuklear - v1.00 - public domain
+ * no warrenty implied; use at your own risk.
+ * authored from 2015-2016 by Micha Mettke
+ */
+/*
+ * ==============================================================
+ *
+ *                              API
+ *
+ * ===============================================================
+ */
+#ifndef NK_GLFW_GL2_H_
+#define NK_GLFW_GL2_H_
 
+#include <GLFW/glfw3.h>
+
+enum nk_glfw_init_state{
+    NK_GLFW3_DEFAULT = 0,
+    NK_GLFW3_INSTALL_CALLBACKS
+};
+NK_API struct nk_context*   nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
+NK_API void                 nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
+NK_API void                 nk_glfw3_font_stash_end(void);
+
+NK_API void                 nk_glfw3_new_frame(void);
+NK_API void                 nk_glfw3_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
+NK_API void                 nk_glfw3_shutdown(void);
+
+NK_API void                 nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
+NK_API void                 nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
+
+#endif
+
+/*
+ * ==============================================================
+ *
+ *                          IMPLEMENTATION
+ *
+ * ===============================================================
+ */
+#ifdef NK_GLFW_GL2_IMPLEMENTATION
+
+#ifndef NK_GLFW_TEXT_MAX
 #define NK_GLFW_TEXT_MAX 256
+#endif
+
 struct nk_glfw_device {
     struct nk_buffer cmds;
     struct nk_draw_null_texture null;
@@ -285,3 +316,5 @@ void nk_glfw3_shutdown(void)
     memset(&glfw, 0, sizeof(glfw));
 }
 
+#endif
+

+ 4 - 5
demo/glfw_opengl3/main.c

@@ -13,17 +13,16 @@
 #include <GL/glew.h>
 #include <GLFW/glfw3.h>
 
-/* these defines are both needed for the header
- * and source file. So if you split them remember
- * to copy them as well. */
 #define NK_INCLUDE_FIXED_TYPES
 #define NK_INCLUDE_STANDARD_IO
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
 #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
 #define NK_INCLUDE_FONT_BAKING
 #define NK_INCLUDE_DEFAULT_FONT
-#include "nuklear_glfw.h"
-#include "nuklear_glfw.c"
+#define NK_IMPLEMENTATION
+#define NK_GLFW_GL3_IMPLEMENTATION
+#include "../../nuklear.h"
+#include "nuklear_glfw_gl3.h"
 
 #define WINDOW_WIDTH 1200
 #define WINDOW_HEIGHT 800

+ 0 - 23
demo/glfw_opengl3/nuklear_glfw.h

@@ -1,23 +0,0 @@
-#ifndef NK_GLFW_H_
-#define NK_GLFW_H_
-
-#include "../../nuklear.h"
-
-#include <GLFW/glfw3.h>
-
-enum nk_glfw_init_state{NK_GLFW3_DEFAULT=0, NK_GLFW3_INSTALL_CALLBACKS};
-NK_API struct nk_context *nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
-NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
-NK_API void nk_glfw3_font_stash_end(void);
-
-NK_API void nk_glfw3_new_frame(void);
-NK_API void nk_glfw3_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
-NK_API void nk_glfw3_shutdown(void);
-
-NK_API void nk_glfw3_device_destroy(void);
-NK_API void nk_glfw3_device_create(void);
-
-NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
-NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
-
-#endif

+ 48 - 14
demo/glfw_opengl3/nuklear_glfw.c → demo/glfw_opengl3/nuklear_glfw_gl3.h

@@ -1,19 +1,52 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-#include <math.h>
-#include <time.h>
-#include <limits.h>
-
-#define NK_IMPLEMENTATION
-#include "nuklear_glfw.h"
-#include "../../nuklear.h"
+/*
+ * Nuklear - v1.00 - public domain
+ * no warrenty implied; use at your own risk.
+ * authored from 2015-2016 by Micha Mettke
+ */
+/*
+ * ==============================================================
+ *
+ *                              API
+ *
+ * ===============================================================
+ */
+#ifndef NK_GLFW_GL3_H_
+#define NK_GLFW_GL3_H_
+
+#include <GLFW/glfw3.h>
+
+enum nk_glfw_init_state{
+    NK_GLFW3_DEFAULT=0,
+    NK_GLFW3_INSTALL_CALLBACKS
+};
+
+NK_API struct nk_context*   nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
+NK_API void                 nk_glfw3_shutdown(void);
+NK_API void                 nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
+NK_API void                 nk_glfw3_font_stash_end(void);
+NK_API void                 nk_glfw3_new_frame(void);
+NK_API void                 nk_glfw3_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer);
+
+NK_API void                 nk_glfw3_device_destroy(void);
+NK_API void                 nk_glfw3_device_create(void);
+
+NK_API void                 nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
+NK_API void                 nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
 
+#endif
+/*
+ * ==============================================================
+ *
+ *                          IMPLEMENTATION
+ *
+ * ===============================================================
+ */
+#ifdef NK_GLFW_GL3_IMPLEMENTATION
+
+#ifndef NK_GLFW_TEXT_MAX
 #define NK_GLFW_TEXT_MAX 256
+#endif
+
 struct nk_glfw_device {
     struct nk_buffer cmds;
     struct nk_draw_null_texture null;
@@ -389,3 +422,4 @@ void nk_glfw3_shutdown(void)
     memset(&glfw, 0, sizeof(glfw));
 }
 
+#endif

+ 5 - 6
demo/sdl1_2/main.c

@@ -10,13 +10,13 @@
 
 #include <SDL/SDL.h>
 
-/* these defines are both needed for the header
- * and source file. So if you split them remember
- * to copy them as well. */
 #define NK_INCLUDE_FIXED_TYPES
+#define NK_INCLUDE_STANDARD_IO
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
+#define NK_IMPLEMENTATION
+#define NK_SDL_IMPLEMENTATION
+#include "../../nuklear.h"
 #include "nuklear_sdl.h"
-#include "nuklear_sdl.c"
 
 #define WINDOW_WIDTH 800
 #define WINDOW_HEIGHT 600
@@ -39,8 +39,7 @@
  *                          DEMO
  *
  * ===============================================================*/
-int
-main(void)
+int main(int argc, char **argv)
 {
     static SDL_Surface *screen_surface;
     struct nk_color background;

+ 0 - 441
demo/sdl1_2/nuklear_sdl.c

@@ -1,441 +0,0 @@
-#include <string.h>
-#include <SDL/SDL.h>
-#include <SDL/SDL_gfxPrimitives.h>
-
-#include "nuklear_sdl.h"
-#define NK_IMPLEMENTATION
-#include "../../nuklear.h"
-
-#ifndef MAX
-#define MAX(a,b) ((a) < (b) ? (b) : (a))
-#endif
-
-#define NK_SDL_MAX_POINTS 128
-
-struct nk_sdl_Font {
-    int width;
-    int height;
-    int handle;
-};
-
-static struct nk_sdl {
-    SDL_Surface *screen_surface;
-    struct nk_context ctx;
-} sdl;
-
-static nk_sdl_Font *sdl_font;
-static SDL_Rect sdl_clip_rect;
-
-static void
-nk_sdl_scissor(SDL_Surface *surface, float x, float y, float w, float h)
-{
-    sdl_clip_rect.x = x;
-    sdl_clip_rect.y = y;
-    sdl_clip_rect.w = w  + 1; 
-    sdl_clip_rect.h = h;
-    SDL_SetClipRect(surface, &sdl_clip_rect);
-}
-
-static void
-nk_sdl_stroke_line(SDL_Surface *surface, short x0, short y0, short x1,
-    short y1, unsigned int line_thickness, struct nk_color col)
-{
-    thickLineRGBA(surface, x0, y0, x1, y1, line_thickness, col.r, col.g, col.b, col.a);
-}
-
-static void
-nk_sdl_stroke_rect(SDL_Surface *surface, short x, short y, unsigned short w,
-    unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
-{
-    /* Note: thickness is not used by default */
-    if (r == 0) {
-        rectangleRGBA(surface, x, y, x + w, y + h, col.r, col.g, col.b, col.a); 
-    } else {
-        roundedRectangleRGBA(surface, x, y, x + w, y + h, r, col.r, col.g, col.b, col.a);
-    }
-}
-
-static void
-nk_sdl_fill_rect(SDL_Surface *surface, short x, short y, unsigned short w,
-    unsigned short h, unsigned short r, struct nk_color col)
-{
-    if (r == 0) {
-        boxRGBA(surface, x, y, x + w, y + h, col.r, col.g, col.b, col.a); 
-    } else {
-        roundedBoxRGBA(surface, x, y, x + w, y + h, r, col.r, col.g, col.b, col.a);
-    }
-}
-
-static void 
-nk_sdl_fill_triangle(SDL_Surface *surface, short x0, short y0, short x1, short y1, short x2, short y2, struct nk_color col)
-{
-    filledTrigonRGBA(surface, x0, y0, x1, y1, x2, y2, col.r, col.g, col.b, col.a);
-}
-
-static void
-nk_sdl_stroke_triangle(SDL_Surface *surface, short x0, short y0, short x1,
-    short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
-{
-    /* Note: thickness is not used by default */
-    aatrigonRGBA(surface, x0, y0, x1, y1, x2, y2, col.r, col.g, col.b, col.a); 
-}
-
-static void
-nk_sdl_fill_polygon(SDL_Surface *surface, const struct nk_vec2i *pnts, int count, struct nk_color col)
-{
-    Sint16 p_x[NK_SDL_MAX_POINTS];
-    Sint16 p_y[NK_SDL_MAX_POINTS];
-    int i;
-    for (i = 0; (i < count) && (i < NK_SDL_MAX_POINTS); ++i) {
-        p_x[i] = pnts[i].x;
-        p_y[i] = pnts[i].y;
-    }
-    filledPolygonRGBA (surface, (Sint16 *)p_x, (Sint16 *)p_y, count, col.r, col.g, col.b, col.a);
-}
-
-static void
-nk_sdl_stroke_polygon(SDL_Surface *surface, const struct nk_vec2i *pnts, int count,
-    unsigned short line_thickness, struct nk_color col)
-{
-    /* Note: thickness is not used by default */
-    Sint16 p_x[NK_SDL_MAX_POINTS];
-    Sint16 p_y[NK_SDL_MAX_POINTS];
-    int i;
-    for (i = 0; (i < count) && (i < NK_SDL_MAX_POINTS); ++i) {
-        p_x[i] = pnts[i].x;
-        p_y[i] = pnts[i].y;
-    }
-    aapolygonRGBA(surface, (Sint16 *)p_x, (Sint16 *)p_y, count, col.r, col.g, col.b, col.a); 
-}
-
-static void
-nk_sdl_stroke_polyline(SDL_Surface *surface, const struct nk_vec2i *pnts,
-    int count, unsigned short line_thickness, struct nk_color col)
-{
-    int x0, y0, x1, y1;
-    if (count == 1) {
-        x0 = pnts[0].x;
-        y0 = pnts[0].y;
-        x1 = x0;
-        y1 = y0;
-        thickLineRGBA(surface, x0, y0, x1, y1, line_thickness, col.r, col.g, col.b, col.a);
-    } else if (count >= 2) {
-        int i;
-        for (i = 0; i < (count - 1); i++) {
-            x0 = pnts[i].x;
-            y0 = pnts[i].y;
-            x1 = pnts[i + 1].x;
-            y1 = pnts[i + 1].y;
-            thickLineRGBA(surface, x0, y0, x1, y1, line_thickness, col.r, col.g, col.b, col.a);
-        }
-    }
-}
-
-static void
-nk_sdl_fill_circle(SDL_Surface *surface, short x, short y, unsigned short w,
-    unsigned short h, struct nk_color col)
-{
-    filledEllipseRGBA(surface,  x + w /2, y + h /2, w / 2, h / 2, col.r, col.g, col.b, col.a); 
-}
-
-static void
-nk_sdl_stroke_circle(SDL_Surface *surface, short x, short y, unsigned short w,
-    unsigned short h, unsigned short line_thickness, struct nk_color col)
-{
-    /* Note: thickness is not used by default */
-    aaellipseRGBA (surface,  x + w /2, y + h /2, w / 2, h / 2, col.r, col.g, col.b, col.a); 
-}
-
-static void
-nk_sdl_stroke_curve(SDL_Surface *surface, 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 col)
-{
-    unsigned int i_step;
-    float t_step;
-    struct nk_vec2i last = p1;
-
-    num_segments = MAX(num_segments, 1);
-    t_step = 1.0f/(float)num_segments;
-    for (i_step = 1; i_step <= num_segments; ++i_step) {
-        float t = t_step * (float)i_step;
-        float u = 1.0f - t;
-        float w1 = u*u*u;
-        float w2 = 3*u*u*t;
-        float w3 = 3*u*t*t;
-        float w4 = t * t *t;
-        float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
-        float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
-        nk_sdl_stroke_line(surface, last.x, last.y, (short)x, (short)y, line_thickness, col);
-        last.x = (short)x; last.y = (short)y;
-    }
-}
-
-static void
-nk_sdl_draw_text(SDL_Surface *surface, short x, short y, unsigned short w, unsigned short h,
-    const char *text, int len, nk_sdl_Font *font, struct nk_color cbg, struct nk_color cfg)
-{
-    int i;
-    nk_sdl_fill_rect(surface, x, y, len * font->width, font->height, 0, cbg);
-    for (i = 0; i < len; i++) {
-        characterRGBA(surface, x, y, text[i], cfg.r, cfg.g, cfg.b, cfg.a);
-        x += font->width;
-    }
-}
-
-static void
-interpolate_color(struct nk_color c1, struct nk_color c2, struct nk_color *result, float fraction)
-{
-    float r = c1.r + (c2.r - c1.r) * fraction;
-    float g = c1.g + (c2.g - c1.g) * fraction;
-    float b = c1.b + (c2.b - c1.b) * fraction;
-    float a = c1.a + (c2.a - c1.a) * fraction;
-
-    result->r = (nk_byte)NK_CLAMP(0, r, 255);
-    result->g = (nk_byte)NK_CLAMP(0, g, 255);
-    result->b = (nk_byte)NK_CLAMP(0, b, 255);
-    result->a = (nk_byte)NK_CLAMP(0, a, 255);
-}
-
-static void
-nk_sdl_fill_rect_multi_color(SDL_Surface *surface, short x, short y, unsigned short w, unsigned short h,
-    struct nk_color left, struct nk_color top,  struct nk_color right, struct nk_color bottom)
-{
-    struct nk_color X1, X2, Y;
-    float fraction_x, fraction_y;
-    int i,j;
-
-    for (j = 0; j < h; j++) {
-        fraction_y = ((float)j) / h;
-        for (i = 0; i < w; i++) {
-            fraction_x = ((float)i) / w;
-            interpolate_color(left, top, &X1, fraction_x);
-            interpolate_color(right, bottom, &X2, fraction_x);
-            interpolate_color(X1, X2, &Y, fraction_y);
-            pixelRGBA(surface, x + i, y + j, Y.r, Y.g, Y.b, Y.a); 
-        }
-    }
-}
-
-static void
-nk_sdl_clear(SDL_Surface *surface, struct nk_color col)
-{
-    nk_sdl_fill_rect(surface, 0, 0, surface->w, surface->h, 0, col);
-}
-
-static void
-nk_sdl_blit(SDL_Surface *surface)
-{
-    SDL_UpdateRect(surface, 0, 0, 0, 0);
-}
-
-NK_API void
-nk_sdl_render(struct nk_color clear)
-{
-    const struct nk_command *cmd;
-
-    SDL_Surface *screen_surface = sdl.screen_surface;
-    nk_sdl_clear(screen_surface, clear);
-
-    nk_foreach(cmd, &sdl.ctx)
-    {
-        switch (cmd->type) {
-        case NK_COMMAND_NOP: break;
-        case NK_COMMAND_SCISSOR: {
-            const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
-            nk_sdl_scissor(screen_surface, s->x, s->y, s->w, s->h);
-        } break;
-        case NK_COMMAND_LINE: {
-            const struct nk_command_line *l = (const struct nk_command_line *)cmd;
-            nk_sdl_stroke_line(screen_surface, l->begin.x, l->begin.y, l->end.x,
-                l->end.y, l->line_thickness, l->color);
-        } break;
-        case NK_COMMAND_RECT: {
-            const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
-            nk_sdl_stroke_rect(screen_surface, r->x, r->y, r->w, r->h,
-                (unsigned short)r->rounding, r->line_thickness, r->color);
-        } break;
-        case NK_COMMAND_RECT_FILLED: {
-            const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
-            nk_sdl_fill_rect(screen_surface, r->x, r->y, r->w, r->h,
-                (unsigned short)r->rounding, r->color);
-        } break;
-        case NK_COMMAND_CIRCLE: {
-            const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
-            nk_sdl_stroke_circle(screen_surface, c->x, c->y, c->w, c->h, c->line_thickness, c->color);
-        } break;
-        case NK_COMMAND_CIRCLE_FILLED: {
-            const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
-            nk_sdl_fill_circle(screen_surface, c->x, c->y, c->w, c->h, c->color);
-        } break;
-        case NK_COMMAND_TRIANGLE: {
-            const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
-            nk_sdl_stroke_triangle(screen_surface, t->a.x, t->a.y, t->b.x, t->b.y,
-                t->c.x, t->c.y, t->line_thickness, t->color);
-        } break;
-        case NK_COMMAND_TRIANGLE_FILLED: {
-            const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
-            nk_sdl_fill_triangle(screen_surface, t->a.x, t->a.y, t->b.x, t->b.y, t->c.x, t->c.y, t->color);
-        } break;
-        case NK_COMMAND_POLYGON: {
-            const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd;
-            nk_sdl_stroke_polygon(screen_surface, p->points, p->point_count, p->line_thickness,p->color);
-        } break;
-        case NK_COMMAND_POLYGON_FILLED: {
-            const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
-            nk_sdl_fill_polygon(screen_surface, p->points, p->point_count, p->color);
-        } break;
-        case NK_COMMAND_POLYLINE: {
-            const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
-            nk_sdl_stroke_polyline(screen_surface, p->points, p->point_count, p->line_thickness, p->color);
-        } break;
-        case NK_COMMAND_TEXT: {
-            const struct nk_command_text *t = (const struct nk_command_text*)cmd;
-            nk_sdl_draw_text(screen_surface, t->x, t->y, t->w, t->h,
-                (const char*)t->string, t->length,
-                (nk_sdl_Font*)t->font->userdata.ptr,
-                t->background, t->foreground);
-        } break;
-        case NK_COMMAND_CURVE: {
-            const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
-            nk_sdl_stroke_curve(screen_surface, q->begin, q->ctrl[0], q->ctrl[1],
-                q->end, 22, q->line_thickness, q->color);
-        } break;
-        case NK_COMMAND_RECT_MULTI_COLOR: {
-            const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color *)cmd;
-            nk_sdl_fill_rect_multi_color(screen_surface, r->x, r->y, r->w, r->h, r->left, r->top, r->right, r->bottom);
-        } break;
-        case NK_COMMAND_IMAGE:
-        case NK_COMMAND_ARC:
-        case NK_COMMAND_ARC_FILLED:
-        default: break;
-        }
-    }
-    nk_sdl_blit(sdl.screen_surface);
-    nk_clear(&sdl.ctx);
-
-}
-
-static void
-nk_sdl_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
-{
-    /* Not supported in SDL 1.2. Use platform specific code.  */
-}
-
-static void
-nk_sdl_clipbard_copy(nk_handle usr, const char *text, int len)
-{
-    /* Not supported in SDL 1.2. Use platform specific code.  */
-}
-
-static float
-nk_sdl_get_text_width(nk_handle handle, float height, const char *text, int len)
-{
-    return len * sdl_font->width;
-}
-
-NK_API struct nk_context*
-nk_sdl_init(SDL_Surface *screen_surface)
-{
-    struct nk_user_font font;
-    sdl_font = (nk_sdl_Font*)calloc(1, sizeof(nk_sdl_Font));
-    sdl_font->width = 8; /* Default in  the SDL_gfx library */
-    sdl_font->height = 8; /* Default in  the SDL_gfx library */
-    if (!sdl_font)
-        return NULL;
-
-    font.userdata = nk_handle_ptr(sdl_font);
-    font.height = (float)sdl_font->height;
-    font.width = nk_sdl_get_text_width;
-
-    sdl.screen_surface = screen_surface;
-    nk_init_default(&sdl.ctx, &font);
-    sdl.ctx.clip.copy = nk_sdl_clipbard_copy;
-    sdl.ctx.clip.paste = nk_sdl_clipbard_paste;
-    sdl.ctx.clip.userdata = nk_handle_ptr(0);
-    return &sdl.ctx;
-}
-
-NK_API void
-nk_sdl_handle_event(SDL_Event *evt)
-{
-
-    struct nk_context *ctx = &sdl.ctx;
-    if (evt->type == SDL_VIDEORESIZE) {
-        /* Do nothing */
-    } else if (evt->type == SDL_KEYUP || evt->type == SDL_KEYDOWN) {
-        /* key events */
-        int down = evt->type == SDL_KEYDOWN;
-        SDLMod state = SDL_GetModState();
-        SDLKey sym = evt->key.keysym.sym;
-
-        if (sym == SDLK_RSHIFT || sym == SDLK_LSHIFT) nk_input_key(ctx, NK_KEY_SHIFT, down);
-        else if (sym == SDLK_DELETE)    nk_input_key(ctx, NK_KEY_DEL, down);
-        else if (sym == SDLK_RETURN)    nk_input_key(ctx, NK_KEY_ENTER, down);
-        else if (sym == SDLK_TAB)       nk_input_key(ctx, NK_KEY_TAB, down);
-        else if (sym == SDLK_LEFT)      nk_input_key(ctx, NK_KEY_LEFT, down);
-        else if (sym == SDLK_RIGHT)     nk_input_key(ctx, NK_KEY_RIGHT, down);
-        else if (sym == SDLK_BACKSPACE) nk_input_key(ctx, NK_KEY_BACKSPACE, down);
-        else if (sym == SDLK_HOME)      nk_input_key(ctx, NK_KEY_TEXT_START, down);
-        else if (sym == SDLK_END)       nk_input_key(ctx, NK_KEY_TEXT_END, down);
-        else if (sym == SDLK_SPACE && !down) nk_input_char(ctx, ' ');
-        else {
-            if (sym == SDLK_c && state == SDLK_LCTRL)
-                nk_input_key(ctx, NK_KEY_COPY, down);
-            else if (sym == SDLK_v && state == SDLK_LCTRL)
-                nk_input_key(ctx, NK_KEY_PASTE, down);
-            else if (sym == SDLK_x && state == SDLK_LCTRL)
-                nk_input_key(ctx, NK_KEY_CUT, down);
-            else if (sym == SDLK_z && state == SDLK_LCTRL)
-                nk_input_key(ctx, NK_KEY_TEXT_UNDO, down);
-            else if (sym == SDLK_r && state == SDLK_LCTRL)
-                nk_input_key(ctx, NK_KEY_TEXT_REDO, down);
-            else if (sym == SDLK_LEFT && state == SDLK_LCTRL)
-                nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
-            else if (sym == SDLK_RIGHT && state == SDLK_LCTRL)
-                nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
-            else if (sym == SDLK_b && state == SDLK_LCTRL)
-                nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down);
-            else if (sym == SDLK_e && state == SDLK_LCTRL)
-                nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down);
-            else if (!down) {
-                /* This demo does not provide full unicode support since the default
-                 * sdl1.2 font only allows runes in range 0-255. But this demo
-                 * already is quite limited and not really meant for full blown Apps
-                 * anyway. So I think ASCII support for Debugging Tools should be enough */
-                if (sym >= SDLK_0 && sym <= SDLK_9) {
-                    nk_rune rune = '0' + sym - SDLK_0;
-                    nk_input_unicode(ctx, rune);
-                } else if (sym >= SDLK_a && sym <= SDLK_z) {
-                    nk_rune rune = 'a' + sym - SDLK_a;
-                    rune = ((state == KMOD_LSHIFT) ? (nk_rune)nk_to_upper((int)rune):rune);
-                    nk_input_unicode(ctx, rune);
-                }
-            }
-        }
-    } else if (evt->type == SDL_MOUSEBUTTONDOWN || evt->type == SDL_MOUSEBUTTONUP) {
-        /* mouse button */
-        int down = evt->type == SDL_MOUSEBUTTONDOWN;
-        const int x = evt->button.x, y = evt->button.y;
-        if (evt->button.button == SDL_BUTTON_LEFT)
-            nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
-        if (evt->button.button == SDL_BUTTON_MIDDLE)
-            nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
-        if (evt->button.button == SDL_BUTTON_RIGHT)
-            nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
-        if (evt->button.button == SDL_BUTTON_WHEELUP)
-            nk_input_scroll(ctx, 1.0f);
-        if (evt->button.button == SDL_BUTTON_WHEELDOWN)
-            nk_input_scroll(ctx, -1.0f);
-    } else if (evt->type == SDL_MOUSEMOTION) {
-        nk_input_motion(ctx, evt->motion.x, evt->motion.y);
-    }
-}
-
-NK_API void
-nk_sdl_shutdown(void)
-{
-    free(sdl_font);
-    nk_free(&sdl.ctx);
-}
-

+ 465 - 6
demo/sdl1_2/nuklear_sdl.h

@@ -1,15 +1,474 @@
+/*
+ * Nuklear - v1.00 - public domain
+ * no warrenty implied; use at your own risk.
+ * authored from 2015-2016 by Micha Mettke
+ */
+/*
+ * ==============================================================
+ *
+ *                              API
+ *
+ * ===============================================================
+ */
 #ifndef NK_SDL_H_
 #define NK_SDL_H_
 
-#include "../../nuklear.h"
+#include <SDL/SDL.h>
+typedef struct nk_sdl_Font nk_sdl_Font;
+NK_API struct nk_context*   nk_sdl_init(SDL_Surface *screen_surface);
+NK_API void                 nk_sdl_handle_event(SDL_Event *evt);
+NK_API void                 nk_sdl_render(struct nk_color clear);
+NK_API void                 nk_sdl_shutdown(void);
+
+#endif
+/*
+ * ==============================================================
+ *
+ *                          IMPLEMENTATION
+ *
+ * ===============================================================
+ */
+#ifdef NK_SDL_IMPLEMENTATION
 
+#include <string.h>
 #include <SDL/SDL.h>
+#include <SDL/SDL_gfxPrimitives.h>
 
-typedef struct nk_sdl_Font nk_sdl_Font;
+#ifndef MAX
+#define MAX(a,b) ((a) < (b) ? (b) : (a))
+#endif
+
+#ifndef NK_SDL_MAX_POINTS
+#define NK_SDL_MAX_POINTS 128
+#endif
+
+struct nk_sdl_Font {
+    int width;
+    int height;
+    int handle;
+};
+
+static struct nk_sdl {
+    SDL_Surface *screen_surface;
+    struct nk_context ctx;
+} sdl;
+
+static nk_sdl_Font *sdl_font;
+static SDL_Rect sdl_clip_rect;
+
+static void
+nk_sdl_scissor(SDL_Surface *surface, float x, float y, float w, float h)
+{
+    sdl_clip_rect.x = x;
+    sdl_clip_rect.y = y;
+    sdl_clip_rect.w = w  + 1; 
+    sdl_clip_rect.h = h;
+    SDL_SetClipRect(surface, &sdl_clip_rect);
+}
+
+static void
+nk_sdl_stroke_line(SDL_Surface *surface, short x0, short y0, short x1,
+    short y1, unsigned int line_thickness, struct nk_color col)
+{
+    thickLineRGBA(surface, x0, y0, x1, y1, line_thickness, col.r, col.g, col.b, col.a);
+}
+
+static void
+nk_sdl_stroke_rect(SDL_Surface *surface, short x, short y, unsigned short w,
+    unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
+{
+    /* Note: thickness is not used by default */
+    if (r == 0) {
+        rectangleRGBA(surface, x, y, x + w, y + h, col.r, col.g, col.b, col.a); 
+    } else {
+        roundedRectangleRGBA(surface, x, y, x + w, y + h, r, col.r, col.g, col.b, col.a);
+    }
+}
+
+static void
+nk_sdl_fill_rect(SDL_Surface *surface, short x, short y, unsigned short w,
+    unsigned short h, unsigned short r, struct nk_color col)
+{
+    if (r == 0) {
+        boxRGBA(surface, x, y, x + w, y + h, col.r, col.g, col.b, col.a); 
+    } else {
+        roundedBoxRGBA(surface, x, y, x + w, y + h, r, col.r, col.g, col.b, col.a);
+    }
+}
+
+static void 
+nk_sdl_fill_triangle(SDL_Surface *surface, short x0, short y0, short x1, short y1, short x2, short y2, struct nk_color col)
+{
+    filledTrigonRGBA(surface, x0, y0, x1, y1, x2, y2, col.r, col.g, col.b, col.a);
+}
+
+static void
+nk_sdl_stroke_triangle(SDL_Surface *surface, short x0, short y0, short x1,
+    short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
+{
+    /* Note: thickness is not used by default */
+    aatrigonRGBA(surface, x0, y0, x1, y1, x2, y2, col.r, col.g, col.b, col.a); 
+}
+
+static void
+nk_sdl_fill_polygon(SDL_Surface *surface, const struct nk_vec2i *pnts, int count, struct nk_color col)
+{
+    Sint16 p_x[NK_SDL_MAX_POINTS];
+    Sint16 p_y[NK_SDL_MAX_POINTS];
+    int i;
+    for (i = 0; (i < count) && (i < NK_SDL_MAX_POINTS); ++i) {
+        p_x[i] = pnts[i].x;
+        p_y[i] = pnts[i].y;
+    }
+    filledPolygonRGBA (surface, (Sint16 *)p_x, (Sint16 *)p_y, count, col.r, col.g, col.b, col.a);
+}
+
+static void
+nk_sdl_stroke_polygon(SDL_Surface *surface, const struct nk_vec2i *pnts, int count,
+    unsigned short line_thickness, struct nk_color col)
+{
+    /* Note: thickness is not used by default */
+    Sint16 p_x[NK_SDL_MAX_POINTS];
+    Sint16 p_y[NK_SDL_MAX_POINTS];
+    int i;
+    for (i = 0; (i < count) && (i < NK_SDL_MAX_POINTS); ++i) {
+        p_x[i] = pnts[i].x;
+        p_y[i] = pnts[i].y;
+    }
+    aapolygonRGBA(surface, (Sint16 *)p_x, (Sint16 *)p_y, count, col.r, col.g, col.b, col.a); 
+}
+
+static void
+nk_sdl_stroke_polyline(SDL_Surface *surface, const struct nk_vec2i *pnts,
+    int count, unsigned short line_thickness, struct nk_color col)
+{
+    int x0, y0, x1, y1;
+    if (count == 1) {
+        x0 = pnts[0].x;
+        y0 = pnts[0].y;
+        x1 = x0;
+        y1 = y0;
+        thickLineRGBA(surface, x0, y0, x1, y1, line_thickness, col.r, col.g, col.b, col.a);
+    } else if (count >= 2) {
+        int i;
+        for (i = 0; i < (count - 1); i++) {
+            x0 = pnts[i].x;
+            y0 = pnts[i].y;
+            x1 = pnts[i + 1].x;
+            y1 = pnts[i + 1].y;
+            thickLineRGBA(surface, x0, y0, x1, y1, line_thickness, col.r, col.g, col.b, col.a);
+        }
+    }
+}
+
+static void
+nk_sdl_fill_circle(SDL_Surface *surface, short x, short y, unsigned short w,
+    unsigned short h, struct nk_color col)
+{
+    filledEllipseRGBA(surface,  x + w /2, y + h /2, w / 2, h / 2, col.r, col.g, col.b, col.a); 
+}
+
+static void
+nk_sdl_stroke_circle(SDL_Surface *surface, short x, short y, unsigned short w,
+    unsigned short h, unsigned short line_thickness, struct nk_color col)
+{
+    /* Note: thickness is not used by default */
+    aaellipseRGBA (surface,  x + w /2, y + h /2, w / 2, h / 2, col.r, col.g, col.b, col.a); 
+}
+
+static void
+nk_sdl_stroke_curve(SDL_Surface *surface, 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 col)
+{
+    unsigned int i_step;
+    float t_step;
+    struct nk_vec2i last = p1;
+
+    num_segments = MAX(num_segments, 1);
+    t_step = 1.0f/(float)num_segments;
+    for (i_step = 1; i_step <= num_segments; ++i_step) {
+        float t = t_step * (float)i_step;
+        float u = 1.0f - t;
+        float w1 = u*u*u;
+        float w2 = 3*u*u*t;
+        float w3 = 3*u*t*t;
+        float w4 = t * t *t;
+        float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
+        float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
+        nk_sdl_stroke_line(surface, last.x, last.y, (short)x, (short)y, line_thickness, col);
+        last.x = (short)x; last.y = (short)y;
+    }
+}
+
+static void
+nk_sdl_draw_text(SDL_Surface *surface, short x, short y, unsigned short w, unsigned short h,
+    const char *text, int len, nk_sdl_Font *font, struct nk_color cbg, struct nk_color cfg)
+{
+    int i;
+    nk_sdl_fill_rect(surface, x, y, len * font->width, font->height, 0, cbg);
+    for (i = 0; i < len; i++) {
+        characterRGBA(surface, x, y, text[i], cfg.r, cfg.g, cfg.b, cfg.a);
+        x += font->width;
+    }
+}
+
+static void
+interpolate_color(struct nk_color c1, struct nk_color c2, struct nk_color *result, float fraction)
+{
+    float r = c1.r + (c2.r - c1.r) * fraction;
+    float g = c1.g + (c2.g - c1.g) * fraction;
+    float b = c1.b + (c2.b - c1.b) * fraction;
+    float a = c1.a + (c2.a - c1.a) * fraction;
+
+    result->r = (nk_byte)NK_CLAMP(0, r, 255);
+    result->g = (nk_byte)NK_CLAMP(0, g, 255);
+    result->b = (nk_byte)NK_CLAMP(0, b, 255);
+    result->a = (nk_byte)NK_CLAMP(0, a, 255);
+}
+
+static void
+nk_sdl_fill_rect_multi_color(SDL_Surface *surface, short x, short y, unsigned short w, unsigned short h,
+    struct nk_color left, struct nk_color top,  struct nk_color right, struct nk_color bottom)
+{
+    struct nk_color X1, X2, Y;
+    float fraction_x, fraction_y;
+    int i,j;
+
+    for (j = 0; j < h; j++) {
+        fraction_y = ((float)j) / h;
+        for (i = 0; i < w; i++) {
+            fraction_x = ((float)i) / w;
+            interpolate_color(left, top, &X1, fraction_x);
+            interpolate_color(right, bottom, &X2, fraction_x);
+            interpolate_color(X1, X2, &Y, fraction_y);
+            pixelRGBA(surface, x + i, y + j, Y.r, Y.g, Y.b, Y.a); 
+        }
+    }
+}
+
+static void
+nk_sdl_clear(SDL_Surface *surface, struct nk_color col)
+{
+    nk_sdl_fill_rect(surface, 0, 0, surface->w, surface->h, 0, col);
+}
+
+static void
+nk_sdl_blit(SDL_Surface *surface)
+{
+    SDL_UpdateRect(surface, 0, 0, 0, 0);
+}
+
+NK_API void
+nk_sdl_render(struct nk_color clear)
+{
+    const struct nk_command *cmd;
+
+    SDL_Surface *screen_surface = sdl.screen_surface;
+    nk_sdl_clear(screen_surface, clear);
+
+    nk_foreach(cmd, &sdl.ctx)
+    {
+        switch (cmd->type) {
+        case NK_COMMAND_NOP: break;
+        case NK_COMMAND_SCISSOR: {
+            const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
+            nk_sdl_scissor(screen_surface, s->x, s->y, s->w, s->h);
+        } break;
+        case NK_COMMAND_LINE: {
+            const struct nk_command_line *l = (const struct nk_command_line *)cmd;
+            nk_sdl_stroke_line(screen_surface, l->begin.x, l->begin.y, l->end.x,
+                l->end.y, l->line_thickness, l->color);
+        } break;
+        case NK_COMMAND_RECT: {
+            const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
+            nk_sdl_stroke_rect(screen_surface, r->x, r->y, r->w, r->h,
+                (unsigned short)r->rounding, r->line_thickness, r->color);
+        } break;
+        case NK_COMMAND_RECT_FILLED: {
+            const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
+            nk_sdl_fill_rect(screen_surface, r->x, r->y, r->w, r->h,
+                (unsigned short)r->rounding, r->color);
+        } break;
+        case NK_COMMAND_CIRCLE: {
+            const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
+            nk_sdl_stroke_circle(screen_surface, c->x, c->y, c->w, c->h, c->line_thickness, c->color);
+        } break;
+        case NK_COMMAND_CIRCLE_FILLED: {
+            const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
+            nk_sdl_fill_circle(screen_surface, c->x, c->y, c->w, c->h, c->color);
+        } break;
+        case NK_COMMAND_TRIANGLE: {
+            const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
+            nk_sdl_stroke_triangle(screen_surface, t->a.x, t->a.y, t->b.x, t->b.y,
+                t->c.x, t->c.y, t->line_thickness, t->color);
+        } break;
+        case NK_COMMAND_TRIANGLE_FILLED: {
+            const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
+            nk_sdl_fill_triangle(screen_surface, t->a.x, t->a.y, t->b.x, t->b.y, t->c.x, t->c.y, t->color);
+        } break;
+        case NK_COMMAND_POLYGON: {
+            const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd;
+            nk_sdl_stroke_polygon(screen_surface, p->points, p->point_count, p->line_thickness,p->color);
+        } break;
+        case NK_COMMAND_POLYGON_FILLED: {
+            const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
+            nk_sdl_fill_polygon(screen_surface, p->points, p->point_count, p->color);
+        } break;
+        case NK_COMMAND_POLYLINE: {
+            const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
+            nk_sdl_stroke_polyline(screen_surface, p->points, p->point_count, p->line_thickness, p->color);
+        } break;
+        case NK_COMMAND_TEXT: {
+            const struct nk_command_text *t = (const struct nk_command_text*)cmd;
+            nk_sdl_draw_text(screen_surface, t->x, t->y, t->w, t->h,
+                (const char*)t->string, t->length,
+                (nk_sdl_Font*)t->font->userdata.ptr,
+                t->background, t->foreground);
+        } break;
+        case NK_COMMAND_CURVE: {
+            const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
+            nk_sdl_stroke_curve(screen_surface, q->begin, q->ctrl[0], q->ctrl[1],
+                q->end, 22, q->line_thickness, q->color);
+        } break;
+        case NK_COMMAND_RECT_MULTI_COLOR: {
+            const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color *)cmd;
+            nk_sdl_fill_rect_multi_color(screen_surface, r->x, r->y, r->w, r->h, r->left, r->top, r->right, r->bottom);
+        } break;
+        case NK_COMMAND_IMAGE:
+        case NK_COMMAND_ARC:
+        case NK_COMMAND_ARC_FILLED:
+        default: break;
+        }
+    }
+    nk_sdl_blit(sdl.screen_surface);
+    nk_clear(&sdl.ctx);
+
+}
+
+static void
+nk_sdl_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
+{
+    /* Not supported in SDL 1.2. Use platform specific code.  */
+}
+
+static void
+nk_sdl_clipbard_copy(nk_handle usr, const char *text, int len)
+{
+    /* Not supported in SDL 1.2. Use platform specific code.  */
+}
+
+static float
+nk_sdl_get_text_width(nk_handle handle, float height, const char *text, int len)
+{
+    return len * sdl_font->width;
+}
+
+NK_API struct nk_context*
+nk_sdl_init(SDL_Surface *screen_surface)
+{
+    struct nk_user_font font;
+    sdl_font = (nk_sdl_Font*)calloc(1, sizeof(nk_sdl_Font));
+    sdl_font->width = 8; /* Default in  the SDL_gfx library */
+    sdl_font->height = 8; /* Default in  the SDL_gfx library */
+    if (!sdl_font)
+        return NULL;
+
+    font.userdata = nk_handle_ptr(sdl_font);
+    font.height = (float)sdl_font->height;
+    font.width = nk_sdl_get_text_width;
+
+    sdl.screen_surface = screen_surface;
+    nk_init_default(&sdl.ctx, &font);
+    sdl.ctx.clip.copy = nk_sdl_clipbard_copy;
+    sdl.ctx.clip.paste = nk_sdl_clipbard_paste;
+    sdl.ctx.clip.userdata = nk_handle_ptr(0);
+    return &sdl.ctx;
+}
+
+NK_API void
+nk_sdl_handle_event(SDL_Event *evt)
+{
+
+    struct nk_context *ctx = &sdl.ctx;
+    if (evt->type == SDL_VIDEORESIZE) {
+        /* Do nothing */
+    } else if (evt->type == SDL_KEYUP || evt->type == SDL_KEYDOWN) {
+        /* key events */
+        int down = evt->type == SDL_KEYDOWN;
+        SDLMod state = SDL_GetModState();
+        SDLKey sym = evt->key.keysym.sym;
+
+        if (sym == SDLK_RSHIFT || sym == SDLK_LSHIFT) nk_input_key(ctx, NK_KEY_SHIFT, down);
+        else if (sym == SDLK_DELETE)    nk_input_key(ctx, NK_KEY_DEL, down);
+        else if (sym == SDLK_RETURN)    nk_input_key(ctx, NK_KEY_ENTER, down);
+        else if (sym == SDLK_TAB)       nk_input_key(ctx, NK_KEY_TAB, down);
+        else if (sym == SDLK_LEFT)      nk_input_key(ctx, NK_KEY_LEFT, down);
+        else if (sym == SDLK_RIGHT)     nk_input_key(ctx, NK_KEY_RIGHT, down);
+        else if (sym == SDLK_BACKSPACE) nk_input_key(ctx, NK_KEY_BACKSPACE, down);
+        else if (sym == SDLK_HOME)      nk_input_key(ctx, NK_KEY_TEXT_START, down);
+        else if (sym == SDLK_END)       nk_input_key(ctx, NK_KEY_TEXT_END, down);
+        else if (sym == SDLK_SPACE && !down) nk_input_char(ctx, ' ');
+        else {
+            if (sym == SDLK_c && state == SDLK_LCTRL)
+                nk_input_key(ctx, NK_KEY_COPY, down);
+            else if (sym == SDLK_v && state == SDLK_LCTRL)
+                nk_input_key(ctx, NK_KEY_PASTE, down);
+            else if (sym == SDLK_x && state == SDLK_LCTRL)
+                nk_input_key(ctx, NK_KEY_CUT, down);
+            else if (sym == SDLK_z && state == SDLK_LCTRL)
+                nk_input_key(ctx, NK_KEY_TEXT_UNDO, down);
+            else if (sym == SDLK_r && state == SDLK_LCTRL)
+                nk_input_key(ctx, NK_KEY_TEXT_REDO, down);
+            else if (sym == SDLK_LEFT && state == SDLK_LCTRL)
+                nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
+            else if (sym == SDLK_RIGHT && state == SDLK_LCTRL)
+                nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
+            else if (sym == SDLK_b && state == SDLK_LCTRL)
+                nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down);
+            else if (sym == SDLK_e && state == SDLK_LCTRL)
+                nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down);
+            else if (!down) {
+                /* This demo does not provide full unicode support since the default
+                 * sdl1.2 font only allows runes in range 0-255. But this demo
+                 * already is quite limited and not really meant for full blown Apps
+                 * anyway. So I think ASCII support for Debugging Tools should be enough */
+                if (sym >= SDLK_0 && sym <= SDLK_9) {
+                    nk_rune rune = '0' + sym - SDLK_0;
+                    nk_input_unicode(ctx, rune);
+                } else if (sym >= SDLK_a && sym <= SDLK_z) {
+                    nk_rune rune = 'a' + sym - SDLK_a;
+                    rune = ((state == KMOD_LSHIFT) ? (nk_rune)nk_to_upper((int)rune):rune);
+                    nk_input_unicode(ctx, rune);
+                }
+            }
+        }
+    } else if (evt->type == SDL_MOUSEBUTTONDOWN || evt->type == SDL_MOUSEBUTTONUP) {
+        /* mouse button */
+        int down = evt->type == SDL_MOUSEBUTTONDOWN;
+        const int x = evt->button.x, y = evt->button.y;
+        if (evt->button.button == SDL_BUTTON_LEFT)
+            nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
+        if (evt->button.button == SDL_BUTTON_MIDDLE)
+            nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
+        if (evt->button.button == SDL_BUTTON_RIGHT)
+            nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
+        if (evt->button.button == SDL_BUTTON_WHEELUP)
+            nk_input_scroll(ctx, 1.0f);
+        if (evt->button.button == SDL_BUTTON_WHEELDOWN)
+            nk_input_scroll(ctx, -1.0f);
+    } else if (evt->type == SDL_MOUSEMOTION) {
+        nk_input_motion(ctx, evt->motion.x, evt->motion.y);
+    }
+}
+
+NK_API void
+nk_sdl_shutdown(void)
+{
+    free(sdl_font);
+    nk_free(&sdl.ctx);
+}
 
-NK_API struct nk_context *nk_sdl_init(SDL_Surface *screen_surface);
-NK_API void nk_sdl_handle_event(SDL_Event *evt);
-NK_API void nk_sdl_render(struct nk_color clear);
-NK_API void nk_sdl_shutdown(void);
 
 #endif
+

+ 4 - 5
demo/sdl_opengl2/main.c

@@ -13,17 +13,16 @@
 #include <SDL2/SDL.h>
 #include <SDL2/SDL_opengl.h>
 
-/* these defines are both needed for the header
- * and source file. So if you split them remember
- * to copy them as well. */
 #define NK_INCLUDE_FIXED_TYPES
 #define NK_INCLUDE_STANDARD_IO
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
 #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
 #define NK_INCLUDE_FONT_BAKING
 #define NK_INCLUDE_DEFAULT_FONT
-#include "nuklear_sdl.h"
-#include "nuklear_sdl.c"
+#define NK_IMPLEMENTATION
+#define NK_SDL_GL2_IMPLEMENTATION
+#include "../../nuklear.h"
+#include "nuklear_sdl_gl2.h"
 
 #define WINDOW_WIDTH 800
 #define WINDOW_HEIGHT 600

+ 0 - 15
demo/sdl_opengl2/nuklear_sdl.h

@@ -1,15 +0,0 @@
-#ifndef NK_SDL_H_
-#define NK_SDL_H_
-
-#include "../../nuklear.h"
-
-#include <SDL2/SDL.h>
-
-NK_API struct nk_context *nk_sdl_init(SDL_Window *win);
-NK_API void nk_sdl_font_stash_begin(struct nk_font_atlas **atlas);
-NK_API void nk_sdl_font_stash_end(void);
-NK_API void nk_sdl_handle_event(SDL_Event *evt);
-NK_API void nk_sdl_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
-NK_API void nk_sdl_shutdown(void);
-
-#endif

+ 31 - 4
demo/sdl_opengl2/nuklear_sdl.c → demo/sdl_opengl2/nuklear_sdl_gl2.h

@@ -1,9 +1,35 @@
-#include <string.h>
+/*
+ * Nuklear - v1.00 - public domain
+ * no warrenty implied; use at your own risk.
+ * authored from 2015-2016 by Micha Mettke
+ */
+/*
+ * ==============================================================
+ *
+ *                              API
+ *
+ * ===============================================================
+ */
+#ifndef NK_SDL_GL2_H_
+#define NK_SDL_GL2_H_
+
 #include <SDL2/SDL.h>
+NK_API struct nk_context*   nk_sdl_init(SDL_Window *win);
+NK_API void                 nk_sdl_font_stash_begin(struct nk_font_atlas **atlas);
+NK_API void                 nk_sdl_font_stash_end(void);
+NK_API void                 nk_sdl_handle_event(SDL_Event *evt);
+NK_API void                 nk_sdl_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
+NK_API void                 nk_sdl_shutdown(void);
 
-#include "nuklear_sdl.h"
-#define NK_IMPLEMENTATION
-#include "../../nuklear.h"
+#endif
+/*
+ * ==============================================================
+ *
+ *                          IMPLEMENTATION
+ *
+ * ===============================================================
+ */
+#ifdef NK_SDL_GL2_IMPLEMENTATION
 
 struct nk_sdl_device {
     struct nk_buffer cmds;
@@ -267,3 +293,4 @@ void nk_sdl_shutdown(void)
     memset(&sdl, 0, sizeof(sdl));
 }
 
+#endif

+ 4 - 5
demo/sdl_opengl3/main.c

@@ -14,17 +14,16 @@
 #include <SDL2/SDL.h>
 #include <SDL2/SDL_opengl.h>
 
-/* these defines are both needed for the header
- * and source file. So if you split them remember
- * to copy them as well. */
 #define NK_INCLUDE_FIXED_TYPES
 #define NK_INCLUDE_STANDARD_IO
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
 #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
 #define NK_INCLUDE_FONT_BAKING
 #define NK_INCLUDE_DEFAULT_FONT
-#include "nuklear_sdl.h"
-#include "nuklear_sdl.c"
+#define NK_IMPLEMENTATION
+#define NK_SDL_GL3_IMPLEMENTATION
+#include "../../nuklear.h"
+#include "nuklear_sdl_gl3.h"
 
 #define WINDOW_WIDTH 800
 #define WINDOW_HEIGHT 600

+ 0 - 18
demo/sdl_opengl3/nuklear_sdl.h

@@ -1,18 +0,0 @@
-#ifndef NK_SDL_H_
-#define NK_SDL_H_
-
-#include "../../nuklear.h"
-
-#include <SDL2/SDL.h>
-
-NK_API struct nk_context *nk_sdl_init(SDL_Window *win);
-NK_API void nk_sdl_font_stash_begin(struct nk_font_atlas **atlas);
-NK_API void nk_sdl_font_stash_end(void);
-NK_API void nk_sdl_handle_event(SDL_Event *evt);
-NK_API void nk_sdl_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
-NK_API void nk_sdl_shutdown(void);
-
-NK_API void nk_sdl_device_destroy(void);
-NK_API void nk_sdl_device_create(void);
-
-#endif

+ 38 - 4
demo/sdl_opengl3/nuklear_sdl.c → demo/sdl_opengl3/nuklear_sdl_gl3.h

@@ -1,9 +1,42 @@
-#include <string.h>
+/*
+ * Nuklear - v1.00 - public domain
+ * no warrenty implied; use at your own risk.
+ * authored from 2015-2016 by Micha Mettke
+ */
+/*
+ * ==============================================================
+ *
+ *                              API
+ *
+ * ===============================================================
+ */
+#ifndef NK_SDL_GL3_H_
+#define NK_SDL_GL3_H_
+
 #include <SDL2/SDL.h>
+#include <SDL2/SDL_opengl.h>
+
+NK_API struct nk_context*   nk_sdl_init(SDL_Window *win);
+NK_API void                 nk_sdl_font_stash_begin(struct nk_font_atlas **atlas);
+NK_API void                 nk_sdl_font_stash_end(void);
+NK_API void                 nk_sdl_handle_event(SDL_Event *evt);
+NK_API void                 nk_sdl_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
+NK_API void                 nk_sdl_shutdown(void);
+NK_API void                 nk_sdl_device_destroy(void);
+NK_API void                 nk_sdl_device_create(void);
+
+#endif
+
+/*
+ * ==============================================================
+ *
+ *                          IMPLEMENTATION
+ *
+ * ===============================================================
+ */
+#ifdef NK_SDL_GL3_IMPLEMENTATION
 
-#include "nuklear_sdl.h"
-#define NK_IMPLEMENTATION
-#include "../../nuklear.h"
+#include <string.h>
 
 struct nk_sdl_device {
     struct nk_buffer cmds;
@@ -369,3 +402,4 @@ void nk_sdl_shutdown(void)
     memset(&sdl, 0, sizeof(sdl));
 }
 
+#endif

+ 10 - 11
demo/x11/main.c

@@ -5,24 +5,22 @@
 #include <stdarg.h>
 #include <string.h>
 #include <limits.h>
-#include <time.h>
+#include <math.h>
 #include <sys/time.h>
 #include <unistd.h>
-#include <math.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xresource.h>
-
-#define DTIME       20
-#define WINDOW_WIDTH 800
-#define WINDOW_HEIGHT 600
+#include <time.h>
 
 #define NK_INCLUDE_FIXED_TYPES
 #define NK_INCLUDE_STANDARD_IO
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
+#define NK_IMPLEMENTATION
+#define NK_XLIB_IMPLEMENTATION
+#include "../../nuklear.h"
 #include "nuklear_xlib.h"
-#include "nuklear_xlib.c"
+
+#define DTIME           20
+#define WINDOW_WIDTH    800
+#define WINDOW_HEIGHT   600
 
 #define UNUSED(a) (void)a
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
@@ -90,6 +88,7 @@ sleep_for(long t)
 /* This are some code examples to provide a small overview of what can be
  * done with this library. To try out an example uncomment the include
  * and the corresponding function. */
+
 /*#include "../style.c"*/
 /*#include "../calculator.c"*/
 /*#include "../overview.c"*/

+ 0 - 612
demo/x11/nuklear_xlib.c

@@ -1,612 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xresource.h>
-#include <X11/Xlocale.h>
-
-#define NK_IMPLEMENTATION
-#include "nuklear_xlib.h"
-#include "../../nuklear.h"
-
-typedef struct XSurface XSurface;
-struct XFont {
-    int ascent;
-    int descent;
-    int height;
-    XFontSet set;
-    XFontStruct *xfont;
-};
-struct XSurface {
-    GC gc;
-    Display *dpy;
-    int screen;
-    Window root;
-    Drawable drawable;
-    unsigned int w, h;
-};
-static struct  {
-    struct nk_context ctx;
-    struct XSurface *surf;
-} xlib;
-
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a,b) ((a) < (b) ? (b) : (a))
-#endif
-
-static unsigned long
-color_from_byte(const nk_byte *c)
-{
-    unsigned long res = 0;
-    res |= (unsigned long)c[0] << 16;
-    res |= (unsigned long)c[1] << 8;
-    res |= (unsigned long)c[2] << 0;
-    return (res);
-}
-
-static XSurface*
-nk_xsurf_create(Display *dpy,  int screen, Window root, unsigned int w, unsigned int h)
-{
-    XSurface *surface = (XSurface*)calloc(1, sizeof(XSurface));
-    surface->w = w;
-    surface->h = h;
-    surface->dpy = dpy;
-    surface->screen = screen;
-    surface->root = root;
-    surface->gc = XCreateGC(dpy, root, 0, NULL);
-    XSetLineAttributes(dpy, surface->gc, 1, LineSolid, CapButt, JoinMiter);
-    surface->drawable = XCreatePixmap(dpy, root, w, h,
-        (unsigned int)DefaultDepth(dpy, screen));
-    return surface;
-}
-
-static void
-nk_xsurf_resize(XSurface *surf, unsigned int w, unsigned int h)
-{
-    if(!surf) return;
-    if (surf->w == w && surf->h == h) return;
-    surf->w = w; surf->h = h;
-    if(surf->drawable) XFreePixmap(surf->dpy, surf->drawable);
-    surf->drawable = XCreatePixmap(surf->dpy, surf->root, w, h,
-        (unsigned int)DefaultDepth(surf->dpy, surf->screen));
-}
-
-static void
-nk_xsurf_scissor(XSurface *surf, float x, float y, float w, float h)
-{
-    XRectangle clip_rect;
-    clip_rect.x = (short)(x-1);
-    clip_rect.y = (short)(y-1);
-    clip_rect.width = (unsigned short)(w+2);
-    clip_rect.height = (unsigned short)(h+2);
-    XSetClipRectangles(surf->dpy, surf->gc, 0, 0, &clip_rect, 1, Unsorted);
-}
-
-static void
-nk_xsurf_stroke_line(XSurface *surf, short x0, short y0, short x1,
-    short y1, unsigned int line_thickness, struct nk_color col)
-{
-    unsigned long c = color_from_byte(&col.r);
-    XSetForeground(surf->dpy, surf->gc, c);
-    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
-    XDrawLine(surf->dpy, surf->drawable, surf->gc, (int)x0, (int)y0, (int)x1, (int)y1);
-    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
-}
-
-static void
-nk_xsurf_stroke_rect(XSurface* surf, short x, short y, unsigned short w,
-    unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
-{
-    unsigned long c = color_from_byte(&col.r);
-    XSetForeground(surf->dpy, surf->gc, c);
-    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
-    if (r == 0) {
-        XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
-    } else {
-        short xc = x + r;
-        short yc = y + r;
-        short wc = (short)(w - 2 * r);
-        short hc = (short)(h - 2 * r);
-
-        XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y, xc+wc, y);
-        XDrawLine(surf->dpy, surf->drawable, surf->gc, x+w, yc, x+w, yc+wc);
-        XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y+h, xc+wc, y+h);
-        XDrawLine(surf->dpy, surf->drawable, surf->gc, x, yc, yc+hc, x);
-
-        XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y,
-            (unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64);
-        XFillArc(surf->dpy, surf->drawable, surf->gc, x, y,
-            (unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64);
-        XFillArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r,
-            (unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64);
-        XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r,
-            (unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64);
-    }
-    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
-}
-
-static void
-nk_xsurf_fill_rect(XSurface* surf, short x, short y, unsigned short w,
-    unsigned short h, unsigned short r, struct nk_color col)
-{
-    unsigned long c = color_from_byte(&col.r);
-    XSetForeground(surf->dpy, surf->gc, c);
-    if (r == 0) {
-        XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
-    } else {
-        short xc = x + r;
-        short yc = y + r;
-        short wc = (short)(w - 2 * r);
-        short hc = (short)(h - 2 * r);
-
-        XPoint pnts[12];
-        pnts[0].x = x;
-        pnts[0].y = yc;
-        pnts[1].x = xc;
-        pnts[1].y = yc;
-        pnts[2].x = xc;
-        pnts[2].y = y;
-
-        pnts[3].x = xc + wc;
-        pnts[3].y = y;
-        pnts[4].x = xc + wc;
-        pnts[4].y = yc;
-        pnts[5].x = x + w;
-        pnts[5].y = yc;
-
-        pnts[6].x = x + w;
-        pnts[6].y = yc + hc;
-        pnts[7].x = xc + wc;
-        pnts[7].y = yc + hc;
-        pnts[8].x = xc + wc;
-        pnts[8].y = y + h;
-
-        pnts[9].x = xc;
-        pnts[9].y = y + h;
-        pnts[10].x = xc;
-        pnts[10].y = yc + hc;
-        pnts[11].x = x;
-        pnts[11].y = yc + hc;
-
-        XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 12, Convex, CoordModeOrigin);
-        XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y,
-            (unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64);
-        XFillArc(surf->dpy, surf->drawable, surf->gc, x, y,
-            (unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64);
-        XFillArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r,
-            (unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64);
-        XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r,
-            (unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64);
-    }
-}
-
-static void
-nk_xsurf_fill_triangle(XSurface *surf, short x0, short y0, short x1,
-    short y1, short x2, short y2, struct nk_color col)
-{
-    XPoint pnts[3];
-    unsigned long c = color_from_byte(&col.r);
-    pnts[0].x = (short)x0;
-    pnts[0].y = (short)y0;
-    pnts[1].x = (short)x1;
-    pnts[1].y = (short)y1;
-    pnts[2].x = (short)x2;
-    pnts[2].y = (short)y2;
-    XSetForeground(surf->dpy, surf->gc, c);
-    XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 3, Convex, CoordModeOrigin);
-}
-
-static void
-nk_xsurf_stroke_triangle(XSurface *surf, short x0, short y0, short x1,
-    short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
-{
-    XPoint pnts[3];
-    unsigned long c = color_from_byte(&col.r);
-    XSetForeground(surf->dpy, surf->gc, c);
-    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
-    XDrawLine(surf->dpy, surf->drawable, surf->gc, x0, y0, x1, y1);
-    XDrawLine(surf->dpy, surf->drawable, surf->gc, x1, y1, x2, y2);
-    XDrawLine(surf->dpy, surf->drawable, surf->gc, x2, y2, x0, y0);
-    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
-}
-
-static void
-nk_xsurf_fill_polygon(XSurface *surf,  const struct nk_vec2i *pnts, int count,
-    struct nk_color col)
-{
-    int i = 0;
-    #define MAX_POINTS 64
-    XPoint xpnts[MAX_POINTS];
-    unsigned long c = color_from_byte(&col.r);
-    XSetForeground(surf->dpy, surf->gc, c);
-    for (i = 0; i < count && i < MAX_POINTS; ++i) {
-        xpnts[i].x = pnts[i].x;
-        xpnts[i].y = pnts[i].y;
-    }
-    XFillPolygon(surf->dpy, surf->drawable, surf->gc, xpnts, count, Convex, CoordModeOrigin);
-    #undef MAX_POINTS
-}
-
-static void
-nk_xsurf_stroke_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count,
-    unsigned short line_thickness, struct nk_color col)
-{
-    int i = 0;
-    unsigned long c = color_from_byte(&col.r);
-    XSetForeground(surf->dpy, surf->gc, c);
-    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
-    for (i = 1; i < count; ++i)
-        XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
-    XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y);
-    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
-}
-
-static void
-nk_xsurf_stroke_polyline(XSurface *surf, const struct nk_vec2i *pnts,
-    int count, unsigned short line_thickness, struct nk_color col)
-{
-    int i = 0;
-    unsigned long c = color_from_byte(&col.r);
-    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
-    XSetForeground(surf->dpy, surf->gc, c);
-    for (i = 0; i < count-1; ++i)
-        XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i].x, pnts[i].y, pnts[i+1].x, pnts[i+1].y);
-    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
-}
-
-static void
-nk_xsurf_fill_circle(XSurface *surf, short x, short y, unsigned short w,
-    unsigned short h, struct nk_color col)
-{
-    unsigned long c = color_from_byte(&col.r);
-    XSetForeground(surf->dpy, surf->gc, c);
-    XFillArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y,
-        (unsigned)w, (unsigned)h, 0, 360 * 64);
-}
-
-static void
-nk_xsurf_stroke_circle(XSurface *surf, short x, short y, unsigned short w,
-    unsigned short h, unsigned short line_thickness, struct nk_color col)
-{
-    unsigned long c = color_from_byte(&col.r);
-    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
-    XSetForeground(surf->dpy, surf->gc, c);
-    XDrawArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y,
-        (unsigned)w, (unsigned)h, 0, 360 * 64);
-    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
-}
-
-static void
-nk_xsurf_stroke_curve(XSurface *surf, 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 col)
-{
-    unsigned int i_step;
-    float t_step;
-    struct nk_vec2i last = p1;
-
-    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
-    num_segments = MAX(num_segments, 1);
-    t_step = 1.0f/(float)num_segments;
-    for (i_step = 1; i_step <= num_segments; ++i_step) {
-        float t = t_step * (float)i_step;
-        float u = 1.0f - t;
-        float w1 = u*u*u;
-        float w2 = 3*u*u*t;
-        float w3 = 3*u*t*t;
-        float w4 = t * t *t;
-        float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
-        float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
-        nk_xsurf_stroke_line(surf, last.x, last.y, (short)x, (short)y, line_thickness,col);
-        last.x = (short)x; last.y = (short)y;
-    }
-    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
-}
-
-static void
-nk_xsurf_draw_text(XSurface *surf, short x, short y, unsigned short w, unsigned short h,
-    const char *text, int len, XFont *font, struct nk_color cbg, struct nk_color cfg)
-{
-    int tx, ty;
-    unsigned long bg = color_from_byte(&cbg.r);
-    unsigned long fg = color_from_byte(&cfg.r);
-
-    XSetForeground(surf->dpy, surf->gc, bg);
-    XFillRectangle(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, (unsigned)w, (unsigned)h);
-    if(!text || !font || !len) return;
-
-    tx = (int)x;
-    ty = (int)y + font->ascent;
-    XSetForeground(surf->dpy, surf->gc, fg);
-    if(font->set)
-        XmbDrawString(surf->dpy,surf->drawable,font->set,surf->gc,tx,ty,(const char*)text,(int)len);
-    else
-        XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, (const char*)text, (int)len);
-}
-
-static void
-nk_xsurf_clear(XSurface *surf, unsigned long color)
-{
-    XSetForeground(surf->dpy, surf->gc, color);
-    XFillRectangle(surf->dpy, surf->drawable, surf->gc, 0, 0, surf->w, surf->h);
-}
-
-static void
-nk_xsurf_blit(Drawable target, XSurface *surf, unsigned int w, unsigned int h)
-{
-    XCopyArea(surf->dpy, surf->drawable, target, surf->gc, 0, 0, w, h, 0, 0);
-}
-
-static void
-nk_xsurf_del(XSurface *surf)
-{
-    XFreePixmap(surf->dpy, surf->drawable);
-    XFreeGC(surf->dpy, surf->gc);
-    free(surf);
-}
-
-XFont*
-nk_xfont_create(Display *dpy, const char *name)
-{
-    int n;
-    char *def, **missing;
-    XFont *font = (XFont*)calloc(1, sizeof(XFont));
-    font->set = XCreateFontSet(dpy, name, &missing, &n, &def);
-    if(missing) {
-        while(n--)
-            fprintf(stderr, "missing fontset: %s\n", missing[n]);
-        XFreeStringList(missing);
-    }
-
-    if(font->set) {
-        XFontStruct **xfonts;
-        char **font_names;
-        XExtentsOfFontSet(font->set);
-        n = XFontsOfFontSet(font->set, &xfonts, &font_names);
-        while(n--) {
-            font->ascent = MAX(font->ascent, (*xfonts)->ascent);
-            font->descent = MAX(font->descent,(*xfonts)->descent);
-            xfonts++;
-        }
-    } else {
-        if(!(font->xfont = XLoadQueryFont(dpy, name))
-        && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) {
-            free(font);
-            return 0;
-        }
-        font->ascent = font->xfont->ascent;
-        font->descent = font->xfont->descent;
-    }
-    font->height = font->ascent + font->descent;
-    return font;
-}
-
-static float
-nk_xfont_get_text_width(nk_handle handle, float height, const char *text, int len)
-{
-    XFont *font = (XFont*)handle.ptr;
-    XRectangle r;
-    if(!font || !text)
-        return 0;
-
-    if(font->set) {
-        XmbTextExtents(font->set, (const char*)text, len, NULL, &r);
-        return (float)r.width;
-    } else{
-        int w = XTextWidth(font->xfont, (const char*)text, len);
-        return (float)w;
-    }
-}
-
-void
-nk_xfont_del(Display *dpy, XFont *font)
-{
-    if(!font) return;
-    if(font->set)
-        XFreeFontSet(dpy, font->set);
-    else
-        XFreeFont(dpy, font->xfont);
-    free(font);
-}
-
-NK_API struct nk_context*
-nk_xlib_init(XFont *xfont, Display *dpy, int screen, Window root,
-    unsigned int w, unsigned int h)
-{
-    struct nk_user_font font;
-    font.userdata = nk_handle_ptr(xfont);
-    font.height = (float)xfont->height;
-    font.width = nk_xfont_get_text_width;
-
-    if (!setlocale(LC_ALL,"")) return 0;
-    if (!XSupportsLocale()) return 0;
-    if (!XSetLocaleModifiers("@im=none")) return 0;
-
-    xlib.surf = nk_xsurf_create(dpy, screen, root, w, h);
-    nk_init_default(&xlib.ctx, &font);
-    return &xlib.ctx;
-}
-
-NK_API void
-nk_xlib_set_font(XFont *xfont)
-{
-    struct nk_user_font font;
-    font.userdata = nk_handle_ptr(xfont);
-    font.height = (float)xfont->height;
-    font.width = nk_xfont_get_text_width;
-    nk_style_set_font(&xlib.ctx, &font);
-}
-
-NK_API void
-nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt)
-{
-    struct nk_context *ctx = &xlib.ctx;
-    if (evt->type == KeyPress || evt->type == KeyRelease)
-    {
-        /* Key handler */
-        int ret, down = (evt->type == KeyPress);
-        KeySym *code = XGetKeyboardMapping(xlib.surf->dpy, (KeyCode)evt->xkey.keycode, 1, &ret);
-        if (*code == XK_Shift_L || *code == XK_Shift_R) nk_input_key(ctx, NK_KEY_SHIFT, down);
-        else if (*code == XK_Delete)    nk_input_key(ctx, NK_KEY_DEL, down);
-        else if (*code == XK_Return)    nk_input_key(ctx, NK_KEY_ENTER, down);
-        else if (*code == XK_Tab)       nk_input_key(ctx, NK_KEY_TAB, down);
-        else if (*code == XK_Left)      nk_input_key(ctx, NK_KEY_LEFT, down);
-        else if (*code == XK_Right)     nk_input_key(ctx, NK_KEY_RIGHT, down);
-        else if (*code == XK_BackSpace) nk_input_key(ctx, NK_KEY_BACKSPACE, down);
-        else if (*code == XK_Home)  nk_input_key(ctx, NK_KEY_TEXT_START, down);
-        else if (*code == XK_End)  nk_input_key(ctx, NK_KEY_TEXT_END, down);
-        else if (*code == XK_space && !down) nk_input_char(ctx, ' ');
-        else {
-            if (*code == 'c' && (evt->xkey.state & ControlMask))
-                nk_input_key(ctx, NK_KEY_COPY, down);
-            else if (*code == 'v' && (evt->xkey.state & ControlMask))
-                nk_input_key(ctx, NK_KEY_PASTE, down);
-            else if (*code == 'x' && (evt->xkey.state & ControlMask))
-                nk_input_key(ctx, NK_KEY_CUT, down);
-            else if (*code == 'z' && (evt->xkey.state & ControlMask))
-                nk_input_key(ctx, NK_KEY_TEXT_UNDO, down);
-            else if (*code == 'r' && (evt->xkey.state & ControlMask))
-                nk_input_key(ctx, NK_KEY_TEXT_REDO, down);
-            else if (*code == XK_Left && (evt->xkey.state & ControlMask))
-                nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
-            else if (*code == XK_Right && (evt->xkey.state & ControlMask))
-                nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
-            else if (*code == 'b' && (evt->xkey.state & ControlMask))
-                nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down);
-            else if (*code == 'e' && (evt->xkey.state & ControlMask))
-                nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down);
-            else if (!down) {
-                char buf[32];
-                KeySym keysym = 0;
-                if (XLookupString((XKeyEvent*)evt, buf, 32, &keysym, NULL) != NoSymbol)
-                    nk_input_glyph(ctx, buf);
-            }
-        }
-        XFree(code);
-    } else if (evt->type == ButtonPress || evt->type == ButtonRelease) {
-        /* Button handler */
-        int down = (evt->type == ButtonPress);
-        const int x = evt->xbutton.x, y = evt->xbutton.y;
-        if (evt->xbutton.button == Button1)
-            nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
-        if (evt->xbutton.button == Button2)
-            nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
-        else if (evt->xbutton.button == Button3)
-            nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
-        else if (evt->xbutton.button == Button4)
-            nk_input_scroll(ctx, 1.0f);
-        else if (evt->xbutton.button == Button5)
-            nk_input_scroll(ctx, -1.0f);
-
-    } else if (evt->type == MotionNotify) {
-        /* Mouse motion handler */
-        const int x = evt->xmotion.x, y = evt->xmotion.y;
-        nk_input_motion(ctx, x, y);
-    } else if (evt->type == Expose || evt->type == ConfigureNotify) {
-        /* Window resize handler */
-        unsigned int width, height;
-        XWindowAttributes attr;
-        XGetWindowAttributes(dpy, win, &attr);
-        width = (unsigned int)attr.width;
-        height = (unsigned int)attr.height;
-        nk_xsurf_resize(xlib.surf, width, height);
-    } else if (evt->type == KeymapNotify)
-        XRefreshKeyboardMapping(&evt->xmapping);
-}
-
-NK_API void
-nk_xlib_shutdown(void)
-{
-    nk_xsurf_del(xlib.surf);
-    nk_free(&xlib.ctx);
-    memset(&xlib, 0, sizeof(xlib));
-}
-
-NK_API void
-nk_xlib_render(Drawable screen, struct nk_color clear)
-{
-    const struct nk_command *cmd;
-    struct nk_context *ctx = &xlib.ctx;
-    XSurface *surf = xlib.surf;
-
-    nk_xsurf_clear(xlib.surf, color_from_byte(&clear.r));
-    nk_foreach(cmd, &xlib.ctx)
-    {
-        switch (cmd->type) {
-        case NK_COMMAND_NOP: break;
-        case NK_COMMAND_SCISSOR: {
-            const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
-            nk_xsurf_scissor(surf, s->x, s->y, s->w, s->h);
-        } break;
-        case NK_COMMAND_LINE: {
-            const struct nk_command_line *l = (const struct nk_command_line *)cmd;
-            nk_xsurf_stroke_line(surf, l->begin.x, l->begin.y, l->end.x,
-                l->end.y, l->line_thickness, l->color);
-        } break;
-        case NK_COMMAND_RECT: {
-            const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
-            nk_xsurf_stroke_rect(surf, r->x, r->y, r->w, r->h,
-                (unsigned short)r->rounding, r->line_thickness, r->color);
-        } break;
-        case NK_COMMAND_RECT_FILLED: {
-            const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
-            nk_xsurf_fill_rect(surf, r->x, r->y, r->w, r->h,
-                (unsigned short)r->rounding, r->color);
-        } break;
-        case NK_COMMAND_CIRCLE: {
-            const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
-            nk_xsurf_stroke_circle(surf, c->x, c->y, c->w, c->h, c->line_thickness, c->color);
-        } break;
-        case NK_COMMAND_CIRCLE_FILLED: {
-            const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
-            nk_xsurf_fill_circle(surf, c->x, c->y, c->w, c->h, c->color);
-        } break;
-        case NK_COMMAND_TRIANGLE: {
-            const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
-            nk_xsurf_stroke_triangle(surf, t->a.x, t->a.y, t->b.x, t->b.y,
-                t->c.x, t->c.y, t->line_thickness, t->color);
-        } break;
-        case NK_COMMAND_TRIANGLE_FILLED: {
-            const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
-            nk_xsurf_fill_triangle(surf, t->a.x, t->a.y, t->b.x, t->b.y,
-                t->c.x, t->c.y, t->color);
-        } break;
-        case NK_COMMAND_POLYGON: {
-            const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd;
-            nk_xsurf_stroke_polygon(surf, p->points, p->point_count, p->line_thickness,p->color);
-        } break;
-        case NK_COMMAND_POLYGON_FILLED: {
-            const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
-            nk_xsurf_fill_polygon(surf, p->points, p->point_count, p->color);
-        } break;
-        case NK_COMMAND_POLYLINE: {
-            const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
-            nk_xsurf_stroke_polyline(surf, p->points, p->point_count, p->line_thickness, p->color);
-        } break;
-        case NK_COMMAND_TEXT: {
-            const struct nk_command_text *t = (const struct nk_command_text*)cmd;
-            nk_xsurf_draw_text(surf, t->x, t->y, t->w, t->h,
-                (const char*)t->string, t->length,
-                (XFont*)t->font->userdata.ptr,
-                t->background, t->foreground);
-        } break;
-        case NK_COMMAND_CURVE: {
-            const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
-            nk_xsurf_stroke_curve(surf, q->begin, q->ctrl[0], q->ctrl[1],
-                q->end, 22, q->line_thickness, q->color);
-        } break;
-        case NK_COMMAND_RECT_MULTI_COLOR:
-        case NK_COMMAND_IMAGE:
-        case NK_COMMAND_ARC:
-        case NK_COMMAND_ARC_FILLED:
-        default: break;
-        }
-    }
-    nk_clear(ctx);
-    nk_xsurf_blit(screen, surf, surf->w, surf->h);
-}
-

+ 634 - 10
demo/x11/nuklear_xlib.h

@@ -1,17 +1,641 @@
+/*
+ * Nuklear - v1.00 - public domain
+ * no warrenty implied; use at your own risk.
+ * authored from 2015-2016 by Micha Mettke
+ */
+/*
+ * ==============================================================
+ *
+ *                              API
+ *
+ * ===============================================================
+ */
 #ifndef NK_XLIB_H_
 #define NK_XLIB_H_
 
-#include "../../nuklear.h"
-
+#include <X11/Xlib.h>
+/* Font */
 typedef struct XFont XFont;
-NK_API struct nk_context* nk_xlib_init(XFont *font, Display *dpy, int screen, Window root, unsigned int w, unsigned int h);
-NK_API void nk_xlib_set_font(XFont *font);
-NK_API void nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt);
-NK_API void nk_xlib_render(Drawable screen, struct nk_color clear);
-NK_API void nk_xlib_shutdown(void);
+NK_API XFont*               nk_xfont_create(Display *dpy, const char *name);
+NK_API void                 nk_xfont_del(Display *dpy, XFont *font);
+
+NK_API struct nk_context*   nk_xlib_init(XFont *font, Display *dpy, int screen, Window root, unsigned int w, unsigned int h);
+NK_API void                 nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt);
+NK_API void                 nk_xlib_render(Drawable screen, struct nk_color clear);
+NK_API void                 nk_xlib_shutdown(void);
+NK_API void                 nk_xlib_set_font(XFont *font);
+
+#endif
+/*
+ * ==============================================================
+ *
+ *                          IMPLEMENTATION
+ *
+ * ===============================================================
+ */
+#ifdef NK_XLIB_IMPLEMENTATION
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xresource.h>
+#include <X11/Xlocale.h>
+
+typedef struct XSurface XSurface;
+struct XFont {
+    int ascent;
+    int descent;
+    int height;
+    XFontSet set;
+    XFontStruct *xfont;
+};
+struct XSurface {
+    GC gc;
+    Display *dpy;
+    int screen;
+    Window root;
+    Drawable drawable;
+    unsigned int w, h;
+};
+static struct  {
+    struct nk_context ctx;
+    struct XSurface *surf;
+} xlib;
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) < (b) ? (b) : (a))
+#endif
+
+static unsigned long
+nk_color_from_byte(const nk_byte *c)
+{
+    unsigned long res = 0;
+    res |= (unsigned long)c[0] << 16;
+    res |= (unsigned long)c[1] << 8;
+    res |= (unsigned long)c[2] << 0;
+    return (res);
+}
+
+static XSurface*
+nk_xsurf_create(Display *dpy,  int screen, Window root, unsigned int w, unsigned int h)
+{
+    XSurface *surface = (XSurface*)calloc(1, sizeof(XSurface));
+    surface->w = w;
+    surface->h = h;
+    surface->dpy = dpy;
+    surface->screen = screen;
+    surface->root = root;
+    surface->gc = XCreateGC(dpy, root, 0, NULL);
+    XSetLineAttributes(dpy, surface->gc, 1, LineSolid, CapButt, JoinMiter);
+    surface->drawable = XCreatePixmap(dpy, root, w, h,
+        (unsigned int)DefaultDepth(dpy, screen));
+    return surface;
+}
+
+static void
+nk_xsurf_resize(XSurface *surf, unsigned int w, unsigned int h)
+{
+    if(!surf) return;
+    if (surf->w == w && surf->h == h) return;
+    surf->w = w; surf->h = h;
+    if(surf->drawable) XFreePixmap(surf->dpy, surf->drawable);
+    surf->drawable = XCreatePixmap(surf->dpy, surf->root, w, h,
+        (unsigned int)DefaultDepth(surf->dpy, surf->screen));
+}
+
+static void
+nk_xsurf_scissor(XSurface *surf, float x, float y, float w, float h)
+{
+    XRectangle clip_rect;
+    clip_rect.x = (short)(x-1);
+    clip_rect.y = (short)(y-1);
+    clip_rect.width = (unsigned short)(w+2);
+    clip_rect.height = (unsigned short)(h+2);
+    XSetClipRectangles(surf->dpy, surf->gc, 0, 0, &clip_rect, 1, Unsorted);
+}
+
+static void
+nk_xsurf_stroke_line(XSurface *surf, short x0, short y0, short x1,
+    short y1, unsigned int line_thickness, struct nk_color col)
+{
+    unsigned long c = nk_color_from_byte(&col.r);
+    XSetForeground(surf->dpy, surf->gc, c);
+    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
+    XDrawLine(surf->dpy, surf->drawable, surf->gc, (int)x0, (int)y0, (int)x1, (int)y1);
+    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
+}
+
+static void
+nk_xsurf_stroke_rect(XSurface* surf, short x, short y, unsigned short w,
+    unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
+{
+    unsigned long c = nk_color_from_byte(&col.r);
+    XSetForeground(surf->dpy, surf->gc, c);
+    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
+    if (r == 0) {
+        XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
+    } else {
+        short xc = x + r;
+        short yc = y + r;
+        short wc = (short)(w - 2 * r);
+        short hc = (short)(h - 2 * r);
+
+        XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y, xc+wc, y);
+        XDrawLine(surf->dpy, surf->drawable, surf->gc, x+w, yc, x+w, yc+wc);
+        XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y+h, xc+wc, y+h);
+        XDrawLine(surf->dpy, surf->drawable, surf->gc, x, yc, yc+hc, x);
+
+        XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y,
+            (unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64);
+        XFillArc(surf->dpy, surf->drawable, surf->gc, x, y,
+            (unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64);
+        XFillArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r,
+            (unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64);
+        XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r,
+            (unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64);
+    }
+    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
+}
+
+static void
+nk_xsurf_fill_rect(XSurface* surf, short x, short y, unsigned short w,
+    unsigned short h, unsigned short r, struct nk_color col)
+{
+    unsigned long c = nk_color_from_byte(&col.r);
+    XSetForeground(surf->dpy, surf->gc, c);
+    if (r == 0) {
+        XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
+    } else {
+        short xc = x + r;
+        short yc = y + r;
+        short wc = (short)(w - 2 * r);
+        short hc = (short)(h - 2 * r);
+
+        XPoint pnts[12];
+        pnts[0].x = x;
+        pnts[0].y = yc;
+        pnts[1].x = xc;
+        pnts[1].y = yc;
+        pnts[2].x = xc;
+        pnts[2].y = y;
+
+        pnts[3].x = xc + wc;
+        pnts[3].y = y;
+        pnts[4].x = xc + wc;
+        pnts[4].y = yc;
+        pnts[5].x = x + w;
+        pnts[5].y = yc;
+
+        pnts[6].x = x + w;
+        pnts[6].y = yc + hc;
+        pnts[7].x = xc + wc;
+        pnts[7].y = yc + hc;
+        pnts[8].x = xc + wc;
+        pnts[8].y = y + h;
+
+        pnts[9].x = xc;
+        pnts[9].y = y + h;
+        pnts[10].x = xc;
+        pnts[10].y = yc + hc;
+        pnts[11].x = x;
+        pnts[11].y = yc + hc;
+
+        XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 12, Convex, CoordModeOrigin);
+        XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y,
+            (unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64);
+        XFillArc(surf->dpy, surf->drawable, surf->gc, x, y,
+            (unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64);
+        XFillArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r,
+            (unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64);
+        XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r,
+            (unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64);
+    }
+}
+
+static void
+nk_xsurf_fill_triangle(XSurface *surf, short x0, short y0, short x1,
+    short y1, short x2, short y2, struct nk_color col)
+{
+    XPoint pnts[3];
+    unsigned long c = nk_color_from_byte(&col.r);
+    pnts[0].x = (short)x0;
+    pnts[0].y = (short)y0;
+    pnts[1].x = (short)x1;
+    pnts[1].y = (short)y1;
+    pnts[2].x = (short)x2;
+    pnts[2].y = (short)y2;
+    XSetForeground(surf->dpy, surf->gc, c);
+    XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 3, Convex, CoordModeOrigin);
+}
+
+static void
+nk_xsurf_stroke_triangle(XSurface *surf, short x0, short y0, short x1,
+    short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
+{
+    XPoint pnts[3];
+    unsigned long c = nk_color_from_byte(&col.r);
+    XSetForeground(surf->dpy, surf->gc, c);
+    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
+    XDrawLine(surf->dpy, surf->drawable, surf->gc, x0, y0, x1, y1);
+    XDrawLine(surf->dpy, surf->drawable, surf->gc, x1, y1, x2, y2);
+    XDrawLine(surf->dpy, surf->drawable, surf->gc, x2, y2, x0, y0);
+    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
+}
+
+static void
+nk_xsurf_fill_polygon(XSurface *surf,  const struct nk_vec2i *pnts, int count,
+    struct nk_color col)
+{
+    int i = 0;
+    #define MAX_POINTS 64
+    XPoint xpnts[MAX_POINTS];
+    unsigned long c = nk_color_from_byte(&col.r);
+    XSetForeground(surf->dpy, surf->gc, c);
+    for (i = 0; i < count && i < MAX_POINTS; ++i) {
+        xpnts[i].x = pnts[i].x;
+        xpnts[i].y = pnts[i].y;
+    }
+    XFillPolygon(surf->dpy, surf->drawable, surf->gc, xpnts, count, Convex, CoordModeOrigin);
+    #undef MAX_POINTS
+}
+
+static void
+nk_xsurf_stroke_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count,
+    unsigned short line_thickness, struct nk_color col)
+{
+    int i = 0;
+    unsigned long c = nk_color_from_byte(&col.r);
+    XSetForeground(surf->dpy, surf->gc, c);
+    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
+    for (i = 1; i < count; ++i)
+        XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
+    XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y);
+    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
+}
+
+static void
+nk_xsurf_stroke_polyline(XSurface *surf, const struct nk_vec2i *pnts,
+    int count, unsigned short line_thickness, struct nk_color col)
+{
+    int i = 0;
+    unsigned long c = nk_color_from_byte(&col.r);
+    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
+    XSetForeground(surf->dpy, surf->gc, c);
+    for (i = 0; i < count-1; ++i)
+        XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i].x, pnts[i].y, pnts[i+1].x, pnts[i+1].y);
+    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
+}
+
+static void
+nk_xsurf_fill_circle(XSurface *surf, short x, short y, unsigned short w,
+    unsigned short h, struct nk_color col)
+{
+    unsigned long c = nk_color_from_byte(&col.r);
+    XSetForeground(surf->dpy, surf->gc, c);
+    XFillArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y,
+        (unsigned)w, (unsigned)h, 0, 360 * 64);
+}
+
+static void
+nk_xsurf_stroke_circle(XSurface *surf, short x, short y, unsigned short w,
+    unsigned short h, unsigned short line_thickness, struct nk_color col)
+{
+    unsigned long c = nk_color_from_byte(&col.r);
+    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
+    XSetForeground(surf->dpy, surf->gc, c);
+    XDrawArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y,
+        (unsigned)w, (unsigned)h, 0, 360 * 64);
+    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
+}
+
+static void
+nk_xsurf_stroke_curve(XSurface *surf, 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 col)
+{
+    unsigned int i_step;
+    float t_step;
+    struct nk_vec2i last = p1;
+
+    XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
+    num_segments = MAX(num_segments, 1);
+    t_step = 1.0f/(float)num_segments;
+    for (i_step = 1; i_step <= num_segments; ++i_step) {
+        float t = t_step * (float)i_step;
+        float u = 1.0f - t;
+        float w1 = u*u*u;
+        float w2 = 3*u*u*t;
+        float w3 = 3*u*t*t;
+        float w4 = t * t *t;
+        float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
+        float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
+        nk_xsurf_stroke_line(surf, last.x, last.y, (short)x, (short)y, line_thickness,col);
+        last.x = (short)x; last.y = (short)y;
+    }
+    XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
+}
+
+static void
+nk_xsurf_draw_text(XSurface *surf, short x, short y, unsigned short w, unsigned short h,
+    const char *text, int len, XFont *font, struct nk_color cbg, struct nk_color cfg)
+{
+    int tx, ty;
+    unsigned long bg = nk_color_from_byte(&cbg.r);
+    unsigned long fg = nk_color_from_byte(&cfg.r);
+
+    XSetForeground(surf->dpy, surf->gc, bg);
+    XFillRectangle(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, (unsigned)w, (unsigned)h);
+    if(!text || !font || !len) return;
+
+    tx = (int)x;
+    ty = (int)y + font->ascent;
+    XSetForeground(surf->dpy, surf->gc, fg);
+    if(font->set)
+        XmbDrawString(surf->dpy,surf->drawable,font->set,surf->gc,tx,ty,(const char*)text,(int)len);
+    else
+        XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, (const char*)text, (int)len);
+}
+
+static void
+nk_xsurf_clear(XSurface *surf, unsigned long color)
+{
+    XSetForeground(surf->dpy, surf->gc, color);
+    XFillRectangle(surf->dpy, surf->drawable, surf->gc, 0, 0, surf->w, surf->h);
+}
+
+static void
+nk_xsurf_blit(Drawable target, XSurface *surf, unsigned int w, unsigned int h)
+{
+    XCopyArea(surf->dpy, surf->drawable, target, surf->gc, 0, 0, w, h, 0, 0);
+}
+
+static void
+nk_xsurf_del(XSurface *surf)
+{
+    XFreePixmap(surf->dpy, surf->drawable);
+    XFreeGC(surf->dpy, surf->gc);
+    free(surf);
+}
+
+XFont*
+nk_xfont_create(Display *dpy, const char *name)
+{
+    int n;
+    char *def, **missing;
+    XFont *font = (XFont*)calloc(1, sizeof(XFont));
+    font->set = XCreateFontSet(dpy, name, &missing, &n, &def);
+    if(missing) {
+        while(n--)
+            fprintf(stderr, "missing fontset: %s\n", missing[n]);
+        XFreeStringList(missing);
+    }
+
+    if(font->set) {
+        XFontStruct **xfonts;
+        char **font_names;
+        XExtentsOfFontSet(font->set);
+        n = XFontsOfFontSet(font->set, &xfonts, &font_names);
+        while(n--) {
+            font->ascent = MAX(font->ascent, (*xfonts)->ascent);
+            font->descent = MAX(font->descent,(*xfonts)->descent);
+            xfonts++;
+        }
+    } else {
+        if(!(font->xfont = XLoadQueryFont(dpy, name))
+        && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) {
+            free(font);
+            return 0;
+        }
+        font->ascent = font->xfont->ascent;
+        font->descent = font->xfont->descent;
+    }
+    font->height = font->ascent + font->descent;
+    return font;
+}
+
+static float
+nk_xfont_get_text_width(nk_handle handle, float height, const char *text, int len)
+{
+    XFont *font = (XFont*)handle.ptr;
+    XRectangle r;
+    if(!font || !text)
+        return 0;
+
+    if(font->set) {
+        XmbTextExtents(font->set, (const char*)text, len, NULL, &r);
+        return (float)r.width;
+    } else{
+        int w = XTextWidth(font->xfont, (const char*)text, len);
+        return (float)w;
+    }
+}
+
+void
+nk_xfont_del(Display *dpy, XFont *font)
+{
+    if(!font) return;
+    if(font->set)
+        XFreeFontSet(dpy, font->set);
+    else
+        XFreeFont(dpy, font->xfont);
+    free(font);
+}
+
+NK_API struct nk_context*
+nk_xlib_init(XFont *xfont, Display *dpy, int screen, Window root,
+    unsigned int w, unsigned int h)
+{
+    struct nk_user_font font;
+    font.userdata = nk_handle_ptr(xfont);
+    font.height = (float)xfont->height;
+    font.width = nk_xfont_get_text_width;
+
+    if (!setlocale(LC_ALL,"")) return 0;
+    if (!XSupportsLocale()) return 0;
+    if (!XSetLocaleModifiers("@im=none")) return 0;
+
+    xlib.surf = nk_xsurf_create(dpy, screen, root, w, h);
+    nk_init_default(&xlib.ctx, &font);
+    return &xlib.ctx;
+}
+
+NK_API void
+nk_xlib_set_font(XFont *xfont)
+{
+    struct nk_user_font font;
+    font.userdata = nk_handle_ptr(xfont);
+    font.height = (float)xfont->height;
+    font.width = nk_xfont_get_text_width;
+    nk_style_set_font(&xlib.ctx, &font);
+}
+
+NK_API void
+nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt)
+{
+    struct nk_context *ctx = &xlib.ctx;
+    if (evt->type == KeyPress || evt->type == KeyRelease)
+    {
+        /* Key handler */
+        int ret, down = (evt->type == KeyPress);
+        KeySym *code = XGetKeyboardMapping(xlib.surf->dpy, (KeyCode)evt->xkey.keycode, 1, &ret);
+        if (*code == XK_Shift_L || *code == XK_Shift_R) nk_input_key(ctx, NK_KEY_SHIFT, down);
+        else if (*code == XK_Delete)    nk_input_key(ctx, NK_KEY_DEL, down);
+        else if (*code == XK_Return)    nk_input_key(ctx, NK_KEY_ENTER, down);
+        else if (*code == XK_Tab)       nk_input_key(ctx, NK_KEY_TAB, down);
+        else if (*code == XK_Left)      nk_input_key(ctx, NK_KEY_LEFT, down);
+        else if (*code == XK_Right)     nk_input_key(ctx, NK_KEY_RIGHT, down);
+        else if (*code == XK_BackSpace) nk_input_key(ctx, NK_KEY_BACKSPACE, down);
+        else if (*code == XK_Home)  nk_input_key(ctx, NK_KEY_TEXT_START, down);
+        else if (*code == XK_End)  nk_input_key(ctx, NK_KEY_TEXT_END, down);
+        else if (*code == XK_space && !down) nk_input_char(ctx, ' ');
+        else {
+            if (*code == 'c' && (evt->xkey.state & ControlMask))
+                nk_input_key(ctx, NK_KEY_COPY, down);
+            else if (*code == 'v' && (evt->xkey.state & ControlMask))
+                nk_input_key(ctx, NK_KEY_PASTE, down);
+            else if (*code == 'x' && (evt->xkey.state & ControlMask))
+                nk_input_key(ctx, NK_KEY_CUT, down);
+            else if (*code == 'z' && (evt->xkey.state & ControlMask))
+                nk_input_key(ctx, NK_KEY_TEXT_UNDO, down);
+            else if (*code == 'r' && (evt->xkey.state & ControlMask))
+                nk_input_key(ctx, NK_KEY_TEXT_REDO, down);
+            else if (*code == XK_Left && (evt->xkey.state & ControlMask))
+                nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
+            else if (*code == XK_Right && (evt->xkey.state & ControlMask))
+                nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
+            else if (*code == 'b' && (evt->xkey.state & ControlMask))
+                nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down);
+            else if (*code == 'e' && (evt->xkey.state & ControlMask))
+                nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down);
+            else if (!down) {
+                char buf[32];
+                KeySym keysym = 0;
+                if (XLookupString((XKeyEvent*)evt, buf, 32, &keysym, NULL) != NoSymbol)
+                    nk_input_glyph(ctx, buf);
+            }
+        }
+        XFree(code);
+    } else if (evt->type == ButtonPress || evt->type == ButtonRelease) {
+        /* Button handler */
+        int down = (evt->type == ButtonPress);
+        const int x = evt->xbutton.x, y = evt->xbutton.y;
+        if (evt->xbutton.button == Button1)
+            nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
+        if (evt->xbutton.button == Button2)
+            nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
+        else if (evt->xbutton.button == Button3)
+            nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
+        else if (evt->xbutton.button == Button4)
+            nk_input_scroll(ctx, 1.0f);
+        else if (evt->xbutton.button == Button5)
+            nk_input_scroll(ctx, -1.0f);
+
+    } else if (evt->type == MotionNotify) {
+        /* Mouse motion handler */
+        const int x = evt->xmotion.x, y = evt->xmotion.y;
+        nk_input_motion(ctx, x, y);
+    } else if (evt->type == Expose || evt->type == ConfigureNotify) {
+        /* Window resize handler */
+        unsigned int width, height;
+        XWindowAttributes attr;
+        XGetWindowAttributes(dpy, win, &attr);
+        width = (unsigned int)attr.width;
+        height = (unsigned int)attr.height;
+        nk_xsurf_resize(xlib.surf, width, height);
+    } else if (evt->type == KeymapNotify)
+        XRefreshKeyboardMapping(&evt->xmapping);
+}
+
+NK_API void
+nk_xlib_shutdown(void)
+{
+    nk_xsurf_del(xlib.surf);
+    nk_free(&xlib.ctx);
+    nk_memset(&xlib, 0, sizeof(xlib));
+}
 
-/* font */
-NK_API XFont* nk_xfont_create(Display *dpy, const char *name);
-NK_API void nk_xfont_del(Display *dpy, XFont *font);
+NK_API void
+nk_xlib_render(Drawable screen, struct nk_color clear)
+{
+    const struct nk_command *cmd;
+    struct nk_context *ctx = &xlib.ctx;
+    XSurface *surf = xlib.surf;
 
+    nk_xsurf_clear(xlib.surf, nk_color_from_byte(&clear.r));
+    nk_foreach(cmd, &xlib.ctx)
+    {
+        switch (cmd->type) {
+        case NK_COMMAND_NOP: break;
+        case NK_COMMAND_SCISSOR: {
+            const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
+            nk_xsurf_scissor(surf, s->x, s->y, s->w, s->h);
+        } break;
+        case NK_COMMAND_LINE: {
+            const struct nk_command_line *l = (const struct nk_command_line *)cmd;
+            nk_xsurf_stroke_line(surf, l->begin.x, l->begin.y, l->end.x,
+                l->end.y, l->line_thickness, l->color);
+        } break;
+        case NK_COMMAND_RECT: {
+            const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
+            nk_xsurf_stroke_rect(surf, r->x, r->y, r->w, r->h,
+                (unsigned short)r->rounding, r->line_thickness, r->color);
+        } break;
+        case NK_COMMAND_RECT_FILLED: {
+            const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
+            nk_xsurf_fill_rect(surf, r->x, r->y, r->w, r->h,
+                (unsigned short)r->rounding, r->color);
+        } break;
+        case NK_COMMAND_CIRCLE: {
+            const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
+            nk_xsurf_stroke_circle(surf, c->x, c->y, c->w, c->h, c->line_thickness, c->color);
+        } break;
+        case NK_COMMAND_CIRCLE_FILLED: {
+            const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
+            nk_xsurf_fill_circle(surf, c->x, c->y, c->w, c->h, c->color);
+        } break;
+        case NK_COMMAND_TRIANGLE: {
+            const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
+            nk_xsurf_stroke_triangle(surf, t->a.x, t->a.y, t->b.x, t->b.y,
+                t->c.x, t->c.y, t->line_thickness, t->color);
+        } break;
+        case NK_COMMAND_TRIANGLE_FILLED: {
+            const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
+            nk_xsurf_fill_triangle(surf, t->a.x, t->a.y, t->b.x, t->b.y,
+                t->c.x, t->c.y, t->color);
+        } break;
+        case NK_COMMAND_POLYGON: {
+            const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd;
+            nk_xsurf_stroke_polygon(surf, p->points, p->point_count, p->line_thickness,p->color);
+        } break;
+        case NK_COMMAND_POLYGON_FILLED: {
+            const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
+            nk_xsurf_fill_polygon(surf, p->points, p->point_count, p->color);
+        } break;
+        case NK_COMMAND_POLYLINE: {
+            const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
+            nk_xsurf_stroke_polyline(surf, p->points, p->point_count, p->line_thickness, p->color);
+        } break;
+        case NK_COMMAND_TEXT: {
+            const struct nk_command_text *t = (const struct nk_command_text*)cmd;
+            nk_xsurf_draw_text(surf, t->x, t->y, t->w, t->h,
+                (const char*)t->string, t->length,
+                (XFont*)t->font->userdata.ptr,
+                t->background, t->foreground);
+        } break;
+        case NK_COMMAND_CURVE: {
+            const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
+            nk_xsurf_stroke_curve(surf, q->begin, q->ctrl[0], q->ctrl[1],
+                q->end, 22, q->line_thickness, q->color);
+        } break;
+        case NK_COMMAND_RECT_MULTI_COLOR:
+        case NK_COMMAND_IMAGE:
+        case NK_COMMAND_ARC:
+        case NK_COMMAND_ARC_FILLED:
+        default: break;
+        }
+    }
+    nk_clear(ctx);
+    nk_xsurf_blit(screen, surf, surf->w, surf->h);
+}
 #endif

+ 5 - 5
demo/x11_opengl3/main.c

@@ -10,17 +10,17 @@
 #include <time.h>
 #include <limits.h>
 
-/* these defines are both needed for the header
- * and source file. So if you split them remember
- * to copy them as well. */
 #define NK_INCLUDE_FIXED_TYPES
 #define NK_INCLUDE_STANDARD_IO
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
 #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
 #define NK_INCLUDE_FONT_BAKING
 #define NK_INCLUDE_DEFAULT_FONT
-#include "nuklear_x11.h"
-#include "nuklear_x11.c"
+#define NK_IMPLEMENTATION
+#define NK_XLIB_GL3_IMPLEMENTATION
+#define NK_XLIB_LOAD_OPENGL_EXTENSIONS
+#include "../../nuklear.h"
+#include "nuklear_xlib_gl3.h"
 
 #define WINDOW_WIDTH 800
 #define WINDOW_HEIGHT 600

+ 0 - 25
demo/x11_opengl3/nuklear_x11.h

@@ -1,25 +0,0 @@
-#ifndef NK_X11_OPENGL_H_
-#define NK_X11_OPENGL_H_
-
-#include "../../nuklear.h"
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xresource.h>
-
-/* Define this to 0 if you already load all required OpenGL extensions yourself
- * otherwise define to 1 to let nuklear load its required extensions. */
-#define NK_X11_LOAD_OPENGL_EXTENSIONS 1
-
-NK_API struct nk_context *nk_x11_init(Display *dpy, Window win);
-NK_API void nk_x11_font_stash_begin(struct nk_font_atlas **atlas);
-NK_API void nk_x11_font_stash_end(void);
-NK_API void nk_x11_handle_event(XEvent *evt);
-NK_API void nk_x11_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer);
-NK_API void nk_x11_shutdown(void);
-
-NK_API int nk_x11_device_create(void);
-NK_API void nk_x11_device_destroy(void);
-
-
-#endif

+ 112 - 80
demo/x11_opengl3/nuklear_x11.c → demo/x11_opengl3/nuklear_xlib_gl3.h

@@ -1,3 +1,37 @@
+/*
+ * Nuklear - v1.00 - public domain
+ * no warrenty implied; use at your own risk.
+ * authored from 2015-2016 by Micha Mettke
+ */
+/*
+ * ==============================================================
+ *
+ *                              API
+ *
+ * ===============================================================
+ */
+#ifndef NK_XLIB_GL3_H_
+#define NK_XLIB_GL3_H_
+
+#include <X11/Xlib.h>
+NK_API struct nk_context*   nk_x11_init(Display *dpy, Window win);
+NK_API void                 nk_x11_font_stash_begin(struct nk_font_atlas **atlas);
+NK_API void                 nk_x11_font_stash_end(void);
+NK_API void                 nk_x11_handle_event(XEvent *evt);
+NK_API void                 nk_x11_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer);
+NK_API void                 nk_x11_shutdown(void);
+NK_API int                  nk_x11_device_create(void);
+NK_API void                 nk_x11_device_destroy(void);
+
+#endif
+/*
+ * ==============================================================
+ *
+ *                          IMPLEMENTATION
+ *
+ * ===============================================================
+ */
+#ifdef NK_XLIB_GL3_IMPLEMENTATION
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -8,13 +42,7 @@
 #include <X11/Xlocale.h>
 
 #include <GL/gl.h>
-#include <GL/glx.h>
 #include <GL/glext.h>
-#include <GL/glxext.h>
-
-#define NK_IMPLEMENTATION
-#include "nuklear_x11.h"
-#include "../../nuklear.h"
 
 #ifndef FALSE
 #define FALSE 0
@@ -23,81 +51,81 @@
 #define TRUE 1
 #endif
 
-#if NK_X11_LOAD_OPENGL_EXTENSIONS
+#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS
 /* GL_ARB_vertex_buffer_object */
-typedef void(*qglGenBuffers)(GLsizei, GLuint*);
-typedef void(*qglBindBuffer)(GLenum, GLuint);
-typedef void(*qglBufferData)(GLenum, GLsizeiptr, const GLvoid*, GLenum);
-typedef void(*qglBufferSubData)(GLenum, GLintptr, GLsizeiptr, const GLvoid*);
-typedef void*(*qglMapBuffer)(GLenum, GLenum);
-typedef GLboolean(*qglUnmapBuffer)(GLenum);
-typedef void(*qglDeleteBuffers)(GLsizei, GLuint*);
+typedef void(*nkglGenBuffers)(GLsizei, GLuint*);
+typedef void(*nkglBindBuffer)(GLenum, GLuint);
+typedef void(*nkglBufferData)(GLenum, GLsizeiptr, const GLvoid*, GLenum);
+typedef void(*nkglBufferSubData)(GLenum, GLintptr, GLsizeiptr, const GLvoid*);
+typedef void*(*nkglMapBuffer)(GLenum, GLenum);
+typedef GLboolean(*nkglUnmapBuffer)(GLenum);
+typedef void(*nkglDeleteBuffers)(GLsizei, GLuint*);
 /* GL_ARB_vertex_array_object */
-typedef void (*qglGenVertexArrays)(GLsizei, GLuint*);
-typedef void (*qglBindVertexArray)(GLuint);
-typedef void (*qglDeleteVertexArrays)(GLsizei, const GLuint*);
+typedef void (*nkglGenVertexArrays)(GLsizei, GLuint*);
+typedef void (*nkglBindVertexArray)(GLuint);
+typedef void (*nkglDeleteVertexArrays)(GLsizei, const GLuint*);
 /* GL_ARB_vertex_program / GL_ARB_fragment_program */
-typedef void(*qglVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*);
-typedef void(*qglEnableVertexAttribArray)(GLuint);
-typedef void(*qglDisableVertexAttribArray)(GLuint);
+typedef void(*nkglVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*);
+typedef void(*nkglEnableVertexAttribArray)(GLuint);
+typedef void(*nkglDisableVertexAttribArray)(GLuint);
 /* GL_ARB_framebuffer_object */
-typedef void(*qglGenerateMipmap)(GLenum target);
+typedef void(*nkglGenerateMipmap)(GLenum target);
 /* GLSL/OpenGL 2.0 core */
-typedef GLuint(*qglCreateShader)(GLenum);
-typedef void(*qglShaderSource)(GLuint, GLsizei, const GLchar**, const GLint*);
-typedef void(*qglCompileShader)(GLuint);
-typedef void(*qglGetShaderiv)(GLuint, GLenum, GLint*);
-typedef void(*qglGetShaderInfoLog)(GLuint, GLsizei, GLsizei*, GLchar*);
-typedef void(*qglDeleteShader)(GLuint);
-typedef GLuint(*qglCreateProgram)(void);
-typedef void(*qglAttachShader)(GLuint, GLuint);
-typedef void(*qglDetachShader)(GLuint, GLuint);
-typedef void(*qglLinkProgram)(GLuint);
-typedef void(*qglUseProgram)(GLuint);
-typedef void(*qglGetProgramiv)(GLuint, GLenum, GLint*);
-typedef void(*qglGetProgramInfoLog)(GLuint, GLsizei, GLsizei*, GLchar*);
-typedef void(*qglDeleteProgram)(GLuint);
-typedef GLint(*qglGetUniformLocation)(GLuint, const GLchar*);
-typedef GLint(*qglGetAttribLocation)(GLuint, const GLchar*);
-typedef void(*qglUniform1i)(GLint, GLint);
-typedef void(*qglUniform1f)(GLint, GLfloat);
-typedef void(*qglUniformMatrix3fv)(GLint, GLsizei, GLboolean, const GLfloat*);
-typedef void(*qglUniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat*);
-
-static qglGenBuffers glGenBuffers;
-static qglBindBuffer glBindBuffer;
-static qglBufferData glBufferData;
-static qglBufferSubData glBufferSubData;
-static qglMapBuffer glMapBuffer;
-static qglUnmapBuffer glUnmapBuffer;
-static qglDeleteBuffers glDeleteBuffers;
-static qglGenVertexArrays glGenVertexArrays;
-static qglBindVertexArray glBindVertexArray;
-static qglDeleteVertexArrays glDeleteVertexArrays;
-static qglVertexAttribPointer glVertexAttribPointer;
-static qglEnableVertexAttribArray glEnableVertexAttribArray;
-static qglDisableVertexAttribArray glDisableVertexAttribArray;
-static qglGenerateMipmap glGenerateMipmap;
-static qglCreateShader glCreateShader;
-static qglShaderSource glShaderSource;
-static qglCompileShader glCompileShader;
-static qglGetShaderiv glGetShaderiv;
-static qglGetShaderInfoLog glGetShaderInfoLog;
-static qglDeleteShader glDeleteShader;
-static qglCreateProgram glCreateProgram;
-static qglAttachShader glAttachShader;
-static qglDetachShader glDetachShader;
-static qglLinkProgram glLinkProgram;
-static qglUseProgram glUseProgram;
-static qglGetProgramiv glGetProgramiv;
-static qglGetProgramInfoLog glGetProgramInfoLog;
-static qglDeleteProgram glDeleteProgram;
-static qglGetUniformLocation glGetUniformLocation;
-static qglGetAttribLocation glGetAttribLocation;
-static qglUniform1i glUniform1i;
-static qglUniform1f glUniform1f;
-static qglUniformMatrix3fv glUniformMatrix3fv;
-static qglUniformMatrix4fv glUniformMatrix4fv;
+typedef GLuint(*nkglCreateShader)(GLenum);
+typedef void(*nkglShaderSource)(GLuint, GLsizei, const GLchar**, const GLint*);
+typedef void(*nkglCompileShader)(GLuint);
+typedef void(*nkglGetShaderiv)(GLuint, GLenum, GLint*);
+typedef void(*nkglGetShaderInfoLog)(GLuint, GLsizei, GLsizei*, GLchar*);
+typedef void(*nkglDeleteShader)(GLuint);
+typedef GLuint(*nkglCreateProgram)(void);
+typedef void(*nkglAttachShader)(GLuint, GLuint);
+typedef void(*nkglDetachShader)(GLuint, GLuint);
+typedef void(*nkglLinkProgram)(GLuint);
+typedef void(*nkglUseProgram)(GLuint);
+typedef void(*nkglGetProgramiv)(GLuint, GLenum, GLint*);
+typedef void(*nkglGetProgramInfoLog)(GLuint, GLsizei, GLsizei*, GLchar*);
+typedef void(*nkglDeleteProgram)(GLuint);
+typedef GLint(*nkglGetUniformLocation)(GLuint, const GLchar*);
+typedef GLint(*nkglGetAttribLocation)(GLuint, const GLchar*);
+typedef void(*nkglUniform1i)(GLint, GLint);
+typedef void(*nkglUniform1f)(GLint, GLfloat);
+typedef void(*nkglUniformMatrix3fv)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void(*nkglUniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat*);
+
+static nkglGenBuffers glGenBuffers;
+static nkglBindBuffer glBindBuffer;
+static nkglBufferData glBufferData;
+static nkglBufferSubData glBufferSubData;
+static nkglMapBuffer glMapBuffer;
+static nkglUnmapBuffer glUnmapBuffer;
+static nkglDeleteBuffers glDeleteBuffers;
+static nkglGenVertexArrays glGenVertexArrays;
+static nkglBindVertexArray glBindVertexArray;
+static nkglDeleteVertexArrays glDeleteVertexArrays;
+static nkglVertexAttribPointer glVertexAttribPointer;
+static nkglEnableVertexAttribArray glEnableVertexAttribArray;
+static nkglDisableVertexAttribArray glDisableVertexAttribArray;
+static nkglGenerateMipmap glGenerateMipmap;
+static nkglCreateShader glCreateShader;
+static nkglShaderSource glShaderSource;
+static nkglCompileShader glCompileShader;
+static nkglGetShaderiv glGetShaderiv;
+static nkglGetShaderInfoLog glGetShaderInfoLog;
+static nkglDeleteShader glDeleteShader;
+static nkglCreateProgram glCreateProgram;
+static nkglAttachShader glAttachShader;
+static nkglDetachShader glDetachShader;
+static nkglLinkProgram glLinkProgram;
+static nkglUseProgram glUseProgram;
+static nkglGetProgramiv glGetProgramiv;
+static nkglGetProgramInfoLog glGetProgramInfoLog;
+static nkglDeleteProgram glDeleteProgram;
+static nkglGetUniformLocation glGetUniformLocation;
+static nkglGetAttribLocation glGetAttribLocation;
+static nkglUniform1i glUniform1i;
+static nkglUniform1f glUniform1f;
+static nkglUniformMatrix3fv glUniformMatrix3fv;
+static nkglUniformMatrix4fv glUniformMatrix4fv;
 
 enum graphics_card_vendors {
     VENDOR_UNKNOWN,
@@ -129,7 +157,7 @@ struct opengl_info {
 #endif
 
 struct nk_x11_device {
-#if NK_X11_LOAD_OPENGL_EXTENSIONS
+#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS
     struct opengl_info info;
 #endif
     struct nk_buffer cmds;
@@ -160,7 +188,10 @@ static struct nk_x11 {
   #define NK_SHADER_VERSION "#version 300 es\n"
 #endif
 
-#if NK_X11_LOAD_OPENGL_EXTENSIONS
+#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS
+#include <GL/glx.h>
+#include <GL/glxext.h>
+
 NK_INTERN int
 nk_x11_stricmpn(const char *a, const char *b, int len)
 {
@@ -192,7 +223,7 @@ nk_x11_check_extension(struct opengl_info *GL, const char *ext)
     return FALSE;
 }
 
-#define GL_EXT(name) (q##name)nk_gl_ext(#name)
+#define GL_EXT(name) (nk##name)nk_gl_ext(#name)
 NK_INTERN __GLXextFuncPtr
 nk_gl_ext(const char *name)
 {
@@ -335,7 +366,7 @@ nk_x11_device_create(void)
         "}\n";
 
     struct nk_x11_device *dev = &x11.ogl;
-#if NK_X11_LOAD_OPENGL_EXTENSIONS
+#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS
     if (!nk_load_opengl(&dev->info)) return 0;
 #endif
     nk_buffer_init_default(&dev->cmds);
@@ -627,3 +658,4 @@ nk_x11_shutdown(void)
     memset(&x11, 0, sizeof(x11));
 }
 
+#endif