aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2019-07-21 15:42:20 +0200
committerHanspeter Portner <dev@open-music-kontrollers.ch>2019-07-21 15:42:20 +0200
commita4985b5f57cfd116aa8fd480eb8f09b4db995674 (patch)
tree789771d7041942c1ac1cbc53e24c9ee8eb7f72bc /src
parent8d3a4dcf9c65b399b90be1746856be02120c0d85 (diff)
downloadd2tk-a4985b5f57cfd116aa8fd480eb8f09b4db995674.tar.xz
core/base: prototype custom widget.
Diffstat (limited to 'src')
-rw-r--r--src/backend_cairo.c37
-rw-r--r--src/backend_nanovg.c75
-rw-r--r--src/base.c20
-rw-r--r--src/core.c24
-rw-r--r--src/core_internal.h13
5 files changed, 169 insertions, 0 deletions
diff --git a/src/backend_cairo.c b/src/backend_cairo.c
index 9ab0f5b..b1a8dee 100644
--- a/src/backend_cairo.c
+++ b/src/backend_cairo.c
@@ -710,6 +710,43 @@ d2tk_cairo_process(void *data, d2tk_core_t *core, const d2tk_com_t *com,
_d2tk_cairo_surf_draw(ctx, surf, xo, yo, body->align,
&D2TK_RECT(body->x, body->y, body->w, body->h));
} break;
+ case D2TK_INSTR_CUSTOM:
+ {
+ const d2tk_body_custom_t *body = &com->body->custom;
+
+ const uint64_t hash = d2tk_hash(body->data, body->size);
+ uintptr_t *sprite = d2tk_core_get_sprite(core, hash, SPRITE_TYPE_SURF);
+ assert(sprite);
+
+ if(!*sprite)
+ {
+ const size_t stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32,
+ body->w);
+ const size_t bufsz = stride * body->h;
+ void *buf = calloc(1, bufsz);
+ cairo_surface_t *surf = cairo_image_surface_create_for_data(buf,
+ CAIRO_FORMAT_ARGB32, body->w, body->h, stride);
+ assert(surf);
+
+ const cairo_user_data_key_t key = { 0 };
+ cairo_surface_set_user_data(surf, &key, buf, _d2tk_cairo_buf_free);
+
+ cairo_t *ctx2 = cairo_create(surf);
+
+ body->custom(ctx2, body->size, body->data);
+
+ cairo_surface_flush(surf);
+ cairo_destroy(ctx2);
+
+ *sprite = (uintptr_t)surf;
+ }
+
+ cairo_surface_t *surf = (cairo_surface_t *)*sprite;
+ assert(surf);
+
+ _d2tk_cairo_surf_draw(ctx, surf, xo, yo, D2TK_ALIGN_LEFT | D2TK_ALIGN_TOP,
+ &D2TK_RECT(body->x, body->y, body->w, body->h));
+ } break;
case D2TK_INSTR_STROKE_WIDTH:
{
const d2tk_body_stroke_width_t *body = &com->body->stroke_width;
diff --git a/src/backend_nanovg.c b/src/backend_nanovg.c
index 5d78813..6f9a411 100644
--- a/src/backend_nanovg.c
+++ b/src/backend_nanovg.c
@@ -757,6 +757,81 @@ d2tk_nanovg_process(void *data, d2tk_core_t *core, const d2tk_com_t *com,
_d2tk_nanovg_surf_draw(ctx, img, xo, yo, body->align,
&D2TK_RECT(body->x, body->y, body->w, body->h));
} break;
+ case D2TK_INSTR_CUSTOM:
+ {
+ const d2tk_body_custom_t *body = &com->body->custom;
+ const uint64_t hash = d2tk_hash(body->data, body->size);
+
+ if(pass == 0)
+ {
+ if(true) // cached
+ {
+ uintptr_t *sprite = d2tk_core_get_sprite(core, hash, SPRITE_TYPE_FBO);
+ assert(sprite);
+
+ if(!*sprite)
+ {
+#ifdef D2TK_DEBUG
+ //fprintf(stderr, "\tcreating sprite\n");
+#endif
+ NVGLUframebuffer *fbo = nvgluCreateFramebuffer(ctx, body->w, body->h, NVG_IMAGE_NEAREST);
+ assert(fbo);
+
+ nvgluBindFramebuffer(fbo);
+
+ glViewport(0, 0, body->w, body->h);
+ glClearColor(0.f, 0.f, 0.f, 0.f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ nvgBeginFrame(ctx, body->w, body->h, 1.f);
+ nvgSave(ctx);
+
+ body->custom(ctx, body->size, body->data);
+
+ nvgRestore(ctx);
+ nvgEndFrame(ctx);
+
+ nvgluBindFramebuffer(NULL);
+
+ *sprite = (uintptr_t )fbo;
+ }
+ else
+ {
+#ifdef D2TK_DEBUG
+ //fprintf(stderr, "\texisting sprite\n");
+#endif
+ }
+ }
+ }
+ else if(pass == 1)
+ {
+ nvgSave(ctx);
+ if(clip)
+ {
+ nvgScissor(ctx, clip->x0, clip->y0, clip->w, clip->h);
+ }
+
+ if(true) // cached
+ {
+ uintptr_t *sprite = d2tk_core_get_sprite(core, hash, SPRITE_TYPE_FBO);
+ assert(sprite && *sprite);
+
+ NVGLUframebuffer *fbo = (NVGLUframebuffer *)*sprite;
+ assert(fbo);
+
+ // paint pre-rendered sprite
+ const NVGpaint pat = nvgImagePattern(ctx, body->x, body->y,
+ body->w, body->h, 0, fbo->image, 1.0f);
+ nvgBeginPath(ctx);
+ nvgRect(ctx, body->x, body->y, body->w, body->h);
+ nvgStrokeWidth(ctx, 0);
+ nvgFillPaint(ctx, pat);
+ nvgFill(ctx);
+ }
+
+ nvgRestore(ctx);
+ }
+ } break;
case D2TK_INSTR_STROKE_WIDTH:
{
const d2tk_body_stroke_width_t *body = &com->body->stroke_width;
diff --git a/src/base.c b/src/base.c
index 8bb0072..6abe25b 100644
--- a/src/base.c
+++ b/src/base.c
@@ -1887,6 +1887,26 @@ d2tk_base_bitmap(d2tk_base_t *base, uint32_t w, uint32_t h, uint32_t stride,
}
}
+D2TK_API void
+d2tk_base_custom(d2tk_base_t *base, uint32_t size, const void *data,
+ const d2tk_rect_t *rect, d2tk_core_custom_t custom)
+{
+ const uint64_t hash = d2tk_hash_foreach(rect, sizeof(d2tk_rect_t),
+ data, size, //FIXME
+ NULL);
+
+ d2tk_core_t *core = base->core;;
+
+ D2TK_CORE_WIDGET(core, hash, widget)
+ {
+ const size_t ref = d2tk_core_bbox_push(core, true, rect);
+
+ d2tk_core_custom(core, rect, size, data, custom);
+
+ d2tk_core_bbox_pop(core, ref);
+ }
+}
+
static inline void
_d2tk_base_draw_meter(d2tk_core_t *core, const d2tk_rect_t *rect,
d2tk_state_t state, int32_t value, const d2tk_style_t *style)
diff --git a/src/core.c b/src/core.c
index 1c6fc3c..79e76af 100644
--- a/src/core.c
+++ b/src/core.c
@@ -1064,6 +1064,30 @@ d2tk_core_bitmap(d2tk_core_t *core, const d2tk_rect_t *rect, uint32_t w,
}
D2TK_API void
+d2tk_core_custom(d2tk_core_t *core, const d2tk_rect_t *rect, uint32_t size,
+ const void *data, d2tk_core_custom_t custom)
+{
+ const size_t len = sizeof(d2tk_body_custom_t);
+ d2tk_body_t *body = _d2tk_append_request(core, len, D2TK_INSTR_CUSTOM);
+
+ if(body)
+ {
+ body->custom.x = rect->x;
+ body->custom.y = rect->y;
+ body->custom.w = rect->w;
+ body->custom.h = rect->h;
+ body->custom.size = size;
+ body->custom.data = data;
+ body->custom.custom = custom;
+
+ body->custom.x -= core->ref.x;
+ body->custom.y -= core->ref.y;
+
+ _d2tk_append_advance(core, len);
+ }
+}
+
+D2TK_API void
d2tk_core_stroke_width(d2tk_core_t *core, d2tk_coord_t width)
{
const size_t len = sizeof(d2tk_body_stroke_width_t);
diff --git a/src/core_internal.h b/src/core_internal.h
index 96f93ab..91c1ef0 100644
--- a/src/core_internal.h
+++ b/src/core_internal.h
@@ -55,6 +55,7 @@ typedef struct _d2tk_body_font_size_t d2tk_body_font_size_t;
typedef struct _d2tk_body_text_t d2tk_body_text_t;
typedef struct _d2tk_body_image_t d2tk_body_image_t;
typedef struct _d2tk_body_bitmap_t d2tk_body_bitmap_t;
+typedef struct _d2tk_body_custom_t d2tk_body_custom_t;
typedef struct _d2tk_body_stroke_width_t d2tk_body_stroke_width_t;
typedef struct _d2tk_body_bbox_t d2tk_body_bbox_t;
typedef union _d2tk_body_t d2tk_body_t;
@@ -180,6 +181,16 @@ struct _d2tk_body_bitmap_t {
} surf;
};
+struct _d2tk_body_custom_t {
+ d2tk_coord_t x;
+ d2tk_coord_t y;
+ d2tk_coord_t w;
+ d2tk_coord_t h;
+ uint32_t size;
+ const void *data;
+ d2tk_core_custom_t custom;
+};
+
struct _d2tk_body_stroke_width_t {
d2tk_coord_t width;
};
@@ -207,6 +218,7 @@ union _d2tk_body_t {
d2tk_body_font_size_t font_size;
d2tk_body_text_t text;
d2tk_body_image_t image;
+ d2tk_body_custom_t custom;
d2tk_body_bitmap_t bitmap;
d2tk_body_stroke_width_t stroke_width;
d2tk_body_bbox_t bbox;
@@ -236,6 +248,7 @@ typedef enum _d2tk_instr_t {
D2TK_INSTR_TEXT,
D2TK_INSTR_IMAGE,
D2TK_INSTR_BITMAP,
+ D2TK_INSTR_CUSTOM,
D2TK_INSTR_STROKE_WIDTH
} d2tk_instr_t;