last xcb try

This commit is contained in:
Richard Gill 2021-05-06 21:35:36 +02:00
parent 596e5d76d9
commit ef9fef2189
2 changed files with 84 additions and 51 deletions

View File

@ -80,7 +80,8 @@ main(void)
int events; int events;
xcb_ctx = nk_xcb_init("Nuklear XCB/Cairo", 20, 20, 800, 600); xcb_ctx = nk_xcb_init("Nuklear XCB/Cairo", 20, 20, 800, 600);
cairo_ctx = nk_cairo_init(&background, NULL, nk_xcb_create_surface(xcb_ctx)); cairo_ctx = nk_cairo_init(&background, NULL, 0, nk_xcb_create_cairo_surface(xcb_ctx));
/*cairo_ctx = nk_cairo_init(&background, "../../extra_font/DroidSans.ttf", 0, nk_xcb_create_surface(xcb_ctx));*/
font = nk_cairo_default_font(cairo_ctx); font = nk_cairo_default_font(cairo_ctx);
ctx = malloc(sizeof(struct nk_context)); ctx = malloc(sizeof(struct nk_context));
nk_init_default(ctx, font); nk_init_default(ctx, font);
@ -105,7 +106,7 @@ main(void)
nk_cairo_damage(cairo_ctx); nk_cairo_damage(cairo_ctx);
} }
if (events & NK_XCB_EVENT_RESIZED) { if (events & NK_XCB_EVENT_RESIZED) {
nk_xcb_resize_surface(xcb_ctx, nk_cairo_surface(cairo_ctx)); nk_xcb_resize_cairo_surface(xcb_ctx, nk_cairo_surface(cairo_ctx));
} }
/* GUI */ /* GUI */

View File

@ -1,8 +1,9 @@
/***************************************************************************** /*****************************************************************************
* *
* Nuklear XCB/Cairo Render Backend - v0.0.2 * Nuklear XCB/Cairo Render Backend - v0.0.2
*
* Copyright 2021 Richard Gill * Copyright 2021 Richard Gill
*
* Grabbed and adapted from https://github.com/griebd/nuklear_xcb
* Copyright 2017 Adriano Grieb * Copyright 2017 Adriano Grieb
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
@ -31,8 +32,8 @@
* *
****************************************************************************/ ****************************************************************************/
#ifndef NK_XCB_H #ifndef NK_XCB_CAIRO_H
#define NK_XCB_H #define NK_XCB_CAIRO_H
/* just to make my IDE happy */ /* just to make my IDE happy */
#ifndef NK_NUKLEAR_H_ #ifndef NK_NUKLEAR_H_
@ -42,13 +43,16 @@
struct nk_xcb_context; struct nk_xcb_context;
struct nk_cairo_context; struct nk_cairo_context;
/* With Xcb, we work mostly on events, so to do something only when
* needed it's good to know what kind of events pulled us from sleep
*/
enum nk_xcb_event_type { enum nk_xcb_event_type {
NK_XCB_EVENT_PAINT = 0x02, NK_XCB_EVENT_PAINT = 0x02,
NK_XCB_EVENT_RESIZED = 0x04, NK_XCB_EVENT_RESIZED = 0x04,
NK_XCB_EVENT_STOP = 0x08 NK_XCB_EVENT_STOP = 0x08
}; };
/* Xcb part: work on windows */
NK_API struct nk_xcb_context *nk_xcb_init(const char *title, int pos_x, int pos_y, int width, int height); NK_API struct nk_xcb_context *nk_xcb_init(const char *title, int pos_x, int pos_y, int width, int height);
NK_API void nk_xcb_free(struct nk_xcb_context *xcb_ctx); NK_API void nk_xcb_free(struct nk_xcb_context *xcb_ctx);
@ -56,17 +60,22 @@ NK_API int nk_xcb_handle_event(struct nk_xcb_context *xcb_ctx, struct nk_context
NK_API void nk_xcb_render(struct nk_xcb_context *xcb_ctx); NK_API void nk_xcb_render(struct nk_xcb_context *xcb_ctx);
NK_API void nk_xcb_size(struct nk_xcb_context *xcb_ctx, int *width, int *height); NK_API void nk_xcb_size(struct nk_xcb_context *xcb_ctx, int *width, int *height);
NK_API void *nk_xcb_create_cairo_surface(struct nk_xcb_context *xcb_ctx); /* TODO: copy/paste */
NK_API void nk_xcb_resize_cairo_surface(struct nk_xcb_context *xcb_ctx, void *surface);
NK_API struct nk_cairo_context *nk_cairo_init(struct nk_color *bg, const char *font_file, void *surface); /* Cairo part: work on painting */
NK_API struct nk_cairo_context *nk_cairo_init(struct nk_color *bg, const char *font_file, double font_size, void *surface);
NK_API void nk_cairo_free(struct nk_cairo_context *cairo_ctx); NK_API void nk_cairo_free(struct nk_cairo_context *cairo_ctx);
NK_API struct nk_user_font *nk_cairo_default_font(struct nk_cairo_context *cairo_ctx); NK_API struct nk_user_font *nk_cairo_default_font(struct nk_cairo_context *cairo_ctx);
NK_API void nk_cairo_damage(struct nk_cairo_context *cairo_ctx); NK_API void nk_cairo_damage(struct nk_cairo_context *cairo_ctx);
NK_API int nk_cairo_render(struct nk_cairo_context *cairo_ctx, struct nk_context *ctx); NK_API int nk_cairo_render(struct nk_cairo_context *cairo_ctx, struct nk_context *ctx);
#endif /* NK_XCB_H */ /* Bridge between xcb and cairo (so it's possible to use them like legos) */
NK_API void *nk_xcb_create_cairo_surface(struct nk_xcb_context *xcb_ctx);
NK_API void nk_xcb_resize_cairo_surface(struct nk_xcb_context *xcb_ctx, void *surface);
#endif /* NK_XCB_CAIRO_H */
/***************************************************************************** /*****************************************************************************
* *
@ -74,14 +83,14 @@ NK_API int nk_cairo_render(struct nk_cairo_context *cairo_ctx, struct nk_context
* *
****************************************************************************/ ****************************************************************************/
/*#ifdef NK_XCB_IMPLEMENTATION*/ /*#ifdef NK_XCB_CAIRO_IMPLEMENTATION*/
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_util.h> #include <xcb/xcb_util.h>
#include <xcb/xcb_keysyms.h> #include <xcb/xcb_keysyms.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#include <cairo-xcb.h> #include <cairo/cairo-xcb.h>
#include <cairo-ft.h> #include <cairo/cairo-ft.h>
#if defined _XOPEN_SOURCE && _XOPEN_SOURCE >= 600 || \ #if defined _XOPEN_SOURCE && _XOPEN_SOURCE >= 600 || \
defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 200112L defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 200112L
@ -426,9 +435,7 @@ NK_API void nk_xcb_size(struct nk_xcb_context *xcb_ctx, int *width, int *height)
*height = xcb_ctx->height; *height = xcb_ctx->height;
} }
NK_API void *nk_xcb_create_cairo_surface(struct nk_xcb_context *xcb_ctx)
NK_API void *nk_xcb_create_surface(struct nk_xcb_context *xcb_ctx)
{ {
xcb_screen_t *screen; xcb_screen_t *screen;
xcb_visualtype_t *visual; xcb_visualtype_t *visual;
@ -438,7 +445,7 @@ NK_API void *nk_xcb_create_surface(struct nk_xcb_context *xcb_ctx)
return cairo_xcb_surface_create(xcb_ctx->conn, xcb_ctx->window, visual, xcb_ctx->width, xcb_ctx->height); return cairo_xcb_surface_create(xcb_ctx->conn, xcb_ctx->window, visual, xcb_ctx->width, xcb_ctx->height);
} }
NK_API void nk_xcb_resize_surface(struct nk_xcb_context *xcb_ctx, void *surface) NK_API void nk_xcb_resize_cairo_surface(struct nk_xcb_context *xcb_ctx, void *surface)
{ {
cairo_xcb_surface_set_size((cairo_surface_t *)surface, xcb_ctx->width, xcb_ctx->height); cairo_xcb_surface_set_size((cairo_surface_t *)surface, xcb_ctx->width, xcb_ctx->height);
} }
@ -462,7 +469,7 @@ NK_INTERN float nk_cairo_text_width(nk_handle handle, float height __attribute__
return extents.x_advance; return extents.x_advance;
} }
NK_API struct nk_cairo_context *nk_cairo_init(struct nk_color *bg, const char *font_file, void *surf) NK_API struct nk_cairo_context *nk_cairo_init(struct nk_color *bg, const char *font_file, double font_size, void *surf)
{ {
cairo_surface_t *surface = surf; cairo_surface_t *surface = surf;
struct nk_cairo_context *cairo_ctx; struct nk_cairo_context *cairo_ctx;
@ -485,7 +492,10 @@ NK_API struct nk_cairo_context *nk_cairo_init(struct nk_color *bg, const char *f
cairo_font_face_set_user_data(font_face, &key, face, (cairo_destroy_func_t)FT_Done_Face); cairo_font_face_set_user_data(font_face, &key, face, (cairo_destroy_func_t)FT_Done_Face);
cairo_set_font_face(cr, font_face); cairo_set_font_face(cr, font_face);
} }
cairo_set_font_size(cr, 11); if (font_size < 0.01) {
font_size = 11.0;
}
cairo_set_font_size(cr, font_size);
default_font = cairo_get_scaled_font(cr); default_font = cairo_get_scaled_font(cr);
cairo_scaled_font_extents(default_font, &extents); cairo_scaled_font_extents(default_font, &extents);
font->userdata.ptr = default_font; font->userdata.ptr = default_font;
@ -558,8 +568,6 @@ NK_API int nk_cairo_render(struct nk_cairo_context *cairo_ctx, struct nk_context
nk_foreach(cmd, nk_ctx) { nk_foreach(cmd, nk_ctx) {
switch (cmd->type) { switch (cmd->type) {
case NK_COMMAND_NOP: case NK_COMMAND_NOP:
printf("seriously\n");
abort();
break; break;
case NK_COMMAND_SCISSOR: case NK_COMMAND_SCISSOR:
{ {
@ -637,33 +645,26 @@ NK_API int nk_cairo_render(struct nk_cairo_context *cairo_ctx, struct nk_context
break; break;
case NK_COMMAND_RECT_MULTI_COLOR: case NK_COMMAND_RECT_MULTI_COLOR:
{ {
struct nk_color c0, c1; /* from https://github.com/taiwins/twidgets/blob/master/src/nk_wl_cairo.c */
const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color *)cmd; const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color *)cmd;
nk_uint lc = nk_color_u32(r->left), tc = nk_color_u32(r->top), rc = nk_color_u32(r->right); cairo_pattern_t *pat = cairo_pattern_create_mesh();
cairo_pattern_t *pat; if (pat) {
double x0, x1, y0, y1; cairo_mesh_pattern_begin_patch(pat);
/* for now, only accept 2 colors gradients, so either left=right (vertical gradient) or left!=right (horizontal gradient) */ cairo_mesh_pattern_move_to(pat, r->x, r->y);
if (nk_color_u32(r->left) == nk_color_u32(r->right)) { cairo_mesh_pattern_line_to(pat, r->x, r->y + r->h);
x0 = x1 = 0.0; cairo_mesh_pattern_line_to(pat, r->x + r->w, r->y + r->h);
y0 = 1.0; cairo_mesh_pattern_line_to(pat, r->x + r->w, r->y);
y1 = 0.0; cairo_mesh_pattern_set_corner_color_rgba(pat, 0, NK_TO_CAIRO(r->left.r), NK_TO_CAIRO(r->left.g), NK_TO_CAIRO(r->left.b), NK_TO_CAIRO(r->left.a));
c0 = r->top; cairo_mesh_pattern_set_corner_color_rgba(pat, 0, NK_TO_CAIRO(r->bottom.r), NK_TO_CAIRO(r->bottom.g), NK_TO_CAIRO(r->bottom.b), NK_TO_CAIRO(r->bottom.a));
c1 = r->bottom; cairo_mesh_pattern_set_corner_color_rgba(pat, 0, NK_TO_CAIRO(r->right.r), NK_TO_CAIRO(r->right.g), NK_TO_CAIRO(r->right.b), NK_TO_CAIRO(r->right.a));
cairo_mesh_pattern_set_corner_color_rgba(pat, 0, NK_TO_CAIRO(r->top.r), NK_TO_CAIRO(r->top.g), NK_TO_CAIRO(r->top.b), NK_TO_CAIRO(r->top.a));
cairo_mesh_pattern_end_patch(pat);
cairo_rectangle(cr, r->x, r->y, r->w, r->h);
cairo_set_source(cr, pat);
cairo_fill(cr);
cairo_pattern_destroy(pat);
} }
else {
y0 = y1 = 0.0;
x0 = 0.0;
x1 = 1.0;
c0 = r->left;
c1 = r->right;
}
pat = cairo_pattern_create_linear(x0, y0, x1, y1);
cairo_pattern_add_color_stop_rgba(pat, 0, NK_TO_CAIRO(c0.r), NK_TO_CAIRO(c0.g), NK_TO_CAIRO(c0.b), NK_TO_CAIRO(c0.a));
cairo_pattern_add_color_stop_rgba(pat, 1, NK_TO_CAIRO(c1.r), NK_TO_CAIRO(c1.g), NK_TO_CAIRO(c1.b), NK_TO_CAIRO(c1.a));
cairo_rectangle(cr, r->x, r->y, r->w, r->h);
cairo_set_source(cr, pat);
cairo_fill(cr);
cairo_pattern_destroy(pat);
} }
break; break;
case NK_COMMAND_CIRCLE: case NK_COMMAND_CIRCLE:
@ -796,14 +797,45 @@ NK_API int nk_cairo_render(struct nk_cairo_context *cairo_ctx, struct nk_context
break; break;
case NK_COMMAND_IMAGE: case NK_COMMAND_IMAGE:
{ {
printf ("TODO: NK_COMMAND_IMAGE\n"); /* from https://github.com/taiwins/twidgets/blob/master/src/nk_wl_cairo.c */
/* TODO */ const struct nk_command_image *im = (const struct nk_command_image *)cmd;
cairo_surface_t *img_surf;
double sw = (double)im->w / (double)im->img.region[2];
double sh = (double)im->h / (double)im->img.region[3];
cairo_format_t format = CAIRO_FORMAT_ARGB32;
int stride = cairo_format_stride_for_width(format, im->img.w);
if (!im->img.handle.ptr) return;
img_surf = cairo_image_surface_create_for_data(im->img.handle.ptr, format, im->img.w, im->img.h, stride);
if (!img_surf) return;
cairo_save(cr);
cairo_rectangle(cr, im->x, im->y, im->w, im->h);
/* scale here, if after source set, the scale would not apply to source
* surface
*/
cairo_scale(cr, sw, sh);
/* the coordinates system in cairo is not intuitive, scale, translate,
* are applied to source. Refer to
* "https://www.cairographics.org/FAQ/#paint_from_a_surface" for details
*
* if you set source_origin to (0,0), it would be like source origin
* aligned to dest origin, then if you draw a rectangle on (x, y, w, h).
* it would clip out the (x, y, w, h) of the source on you dest as well.
*/
cairo_set_source_surface(cr, img_surf, im->x/sw - im->img.region[0], im->y/sh - im->img.region[1]);
cairo_fill(cr);
cairo_restore(cr);
cairo_surface_destroy(img_surf);
} }
break; break;
case NK_COMMAND_CUSTOM: case NK_COMMAND_CUSTOM:
{ {
printf ("TODO: NK_COMMAND_CUSTOM\n"); const struct nk_command_custom *cu = (const struct nk_command_custom *)cmd;
/* TODO */ if (cu->callback) {
cu->callback(cr, cu->x, cu->y, cu->w, cu->h, cu->callback_data);
}
} }
default: default:
break; break;
@ -817,4 +849,4 @@ NK_API int nk_cairo_render(struct nk_cairo_context *cairo_ctx, struct nk_context
return nk_true; return nk_true;
} }
/*#endif /* NK_XCB_IMPLEMENTATION */ /*#endif /* NK_XCB_CAIRO_IMPLEMENTATION */