From 488525745a782999180a237356f0350da62db775 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 3 May 2024 11:46:23 +0100 Subject: [PATCH] Support arbitrary pixel formats with more rawfb demos --- demo/rawfb/nuklear_rawfb.h | 168 ++--- demo/rawfb/sdl/Makefile | 2 +- demo/rawfb/sdl/main.c | 15 +- demo/rawfb/sdl/nuklear_sdl_rawfb.h | 1090 ---------------------------- demo/rawfb/wayland/main.c | 13 +- demo/rawfb/x11/main.c | 2 +- demo/rawfb/x11/nuklear_xlib.h | 31 +- 7 files changed, 114 insertions(+), 1207 deletions(-) delete mode 100644 demo/rawfb/sdl/nuklear_sdl_rawfb.h diff --git a/demo/rawfb/nuklear_rawfb.h b/demo/rawfb/nuklear_rawfb.h index 42cc638..cc1fe8c 100644 --- a/demo/rawfb/nuklear_rawfb.h +++ b/demo/rawfb/nuklear_rawfb.h @@ -28,23 +28,23 @@ * * =============================================================== */ + #ifndef NK_RAWFB_H_ #define NK_RAWFB_H_ struct rawfb_context; -typedef enum rawfb_pixel_layout { - PIXEL_LAYOUT_XRGB_8888, - PIXEL_LAYOUT_RGBX_8888 -} -rawfb_pl; - +struct rawfb_pl { + unsigned char bytesPerPixel; + unsigned char rshift, gshift, bshift, ashift; + unsigned char rloss, gloss, bloss, aloss; +}; /* All functions are thread-safe */ -NK_API struct rawfb_context *nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int h, const unsigned int pitch, const rawfb_pl pl); +NK_API struct rawfb_context *nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int h, const unsigned int pitch, const struct rawfb_pl pl); NK_API void nk_rawfb_render(const struct rawfb_context *rawfb, const struct nk_color clear, const unsigned char enable_clear); NK_API void nk_rawfb_shutdown(struct rawfb_context *rawfb); -NK_API void nk_rawfb_resize_fb(struct rawfb_context *rawfb, void *fb, const unsigned int w, const unsigned int h, const unsigned int pitch, const rawfb_pl pl); +NK_API void nk_rawfb_resize_fb(struct rawfb_context *rawfb, void *fb, const unsigned int w, const unsigned int h, const unsigned int pitch, const struct rawfb_pl pl); #endif /* @@ -62,8 +62,7 @@ NK_API void nk_rawfb_resize_fb(struct rawfb_context *rawfb, voi struct rawfb_image { void *pixels; int w, h, pitch; - rawfb_pl pl; - enum nk_font_atlas_format format; + struct rawfb_pl pl; }; struct rawfb_context { struct nk_context ctx; @@ -81,54 +80,28 @@ struct rawfb_context { #endif static unsigned int -nk_rawfb_color2int(const struct nk_color c, rawfb_pl pl) +nk_rawfb_color2int(const struct nk_color c, const struct rawfb_pl pl) { unsigned int res = 0; - switch (pl) { - case PIXEL_LAYOUT_RGBX_8888: - res |= c.r << 24; - res |= c.g << 16; - res |= c.b << 8; - res |= c.a; - break; - case PIXEL_LAYOUT_XRGB_8888: - res |= c.a << 24; - res |= c.r << 16; - res |= c.g << 8; - res |= c.b; - break; + res |= (c.r >> pl.rloss) << pl.rshift; + res |= (c.g >> pl.gloss) << pl.gshift; + res |= (c.b >> pl.bloss) << pl.bshift; + res |= (c.a >> pl.aloss) << pl.ashift; - default: - perror("nk_rawfb_color2int(): Unsupported pixel layout.\n"); - break; - } return (res); } static struct nk_color -nk_rawfb_int2color(const unsigned int i, rawfb_pl pl) +nk_rawfb_int2color(const unsigned int i, const struct rawfb_pl pl) { struct nk_color col = {0,0,0,0}; - switch (pl) { - case PIXEL_LAYOUT_RGBX_8888: - col.r = (i >> 24) & 0xff; - col.g = (i >> 16) & 0xff; - col.b = (i >> 8) & 0xff; - col.a = i & 0xff; - break; - case PIXEL_LAYOUT_XRGB_8888: - col.a = (i >> 24) & 0xff; - col.r = (i >> 16) & 0xff; - col.g = (i >> 8) & 0xff; - col.b = i & 0xff; - break; + col.r = (pl.rloss == 8) ? 0xff : ((i >> pl.rshift) << pl.rloss) & 0xff; + col.g = (pl.gloss == 8) ? 0xff : ((i >> pl.gshift) << pl.gloss) & 0xff; + col.b = (pl.bloss == 8) ? 0xff : ((i >> pl.bshift) << pl.bloss) & 0xff; + col.a = (pl.aloss == 8) ? 0xff : ((i >> pl.ashift) << pl.aloss) & 0xff; - default: - perror("nk_rawfb_int2color(): Unsupported pixel layout.\n"); - break; - } return col; } @@ -138,14 +111,20 @@ nk_rawfb_ctx_setpixel(const struct rawfb_context *rawfb, { unsigned int c = nk_rawfb_color2int(col, rawfb->fb.pl); unsigned char *pixels = rawfb->fb.pixels; - unsigned int *ptr; pixels += y0 * rawfb->fb.pitch; - ptr = (unsigned int *)pixels + x0; if (y0 < rawfb->scissors.h && y0 >= rawfb->scissors.y && - x0 >= rawfb->scissors.x && x0 < rawfb->scissors.w) - *ptr = c; + x0 >= rawfb->scissors.x && x0 < rawfb->scissors.w) { + + if (rawfb->fb.pl.bytesPerPixel == sizeof(unsigned int)) { + *((unsigned int *)pixels + x0) = c; + } else if (rawfb->fb.pl.bytesPerPixel == sizeof(unsigned short)) { + *((unsigned short *)pixels + x0) = c; + } else { + *((unsigned char *)pixels + x0) = c; + } + } } static void @@ -156,22 +135,29 @@ nk_rawfb_line_horizontal(const struct rawfb_context *rawfb, * It does not check for scissors or image borders. * The caller has to make sure it does no exceed bounds. */ unsigned int i, n; - unsigned int c[16]; + unsigned char c[16 * 4]; unsigned char *pixels = rawfb->fb.pixels; - unsigned int *ptr; + unsigned int bpp = rawfb->fb.pl.bytesPerPixel; - pixels += y * rawfb->fb.pitch; - ptr = (unsigned int *)pixels + x0; + pixels += (y * rawfb->fb.pitch) + (x0 * bpp); - n = x1 - x0; - for (i = 0; i < sizeof(c) / sizeof(c[0]); i++) - c[i] = nk_rawfb_color2int(col, rawfb->fb.pl); + n = (x1 - x0) * bpp; + if (bpp == sizeof(unsigned int)) { + for (i = 0; i < sizeof(c) / bpp; i++) + ((unsigned int *)c)[i] = nk_rawfb_color2int(col, rawfb->fb.pl); + } else if (bpp == sizeof(unsigned short)) { + for (i = 0; i < sizeof(c) / bpp; i++) + ((unsigned short *)c)[i] = nk_rawfb_color2int(col, rawfb->fb.pl); + } else { + for (i = 0; i < sizeof(c) / bpp; i++) + ((unsigned char *)c)[i] = nk_rawfb_color2int(col, rawfb->fb.pl); + } - while (n > 16) { - memcpy((void *)ptr, c, sizeof(c)); - n -= 16; ptr += 16; + while (n > sizeof(c)) { + memcpy((void*)pixels, c, sizeof(c)); + n -= sizeof(c); pixels += sizeof(c); } for (i = 0; i < n; i++) - ptr[i] = c[i]; + pixels[i] = c[i]; } static void @@ -180,16 +166,16 @@ nk_rawfb_img_setpixel(const struct rawfb_image *img, { unsigned int c = nk_rawfb_color2int(col, img->pl); unsigned char *ptr; - unsigned int *pixel; NK_ASSERT(img); if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) { ptr = (unsigned char *)img->pixels + (img->pitch * y0); - pixel = (unsigned int *)ptr; - if (img->format == NK_FONT_ATLAS_ALPHA8) { - ptr[x0] = col.a; + if (img->pl.bytesPerPixel == sizeof(unsigned int)) { + ((unsigned int *)ptr)[x0] = c; + } else if (img->pl.bytesPerPixel == sizeof(unsigned short)) { + ((unsigned short *)ptr)[x0] = c; } else { - pixel[x0] = c; + ((unsigned char *)ptr)[x0] = c; } } } @@ -204,12 +190,15 @@ nk_rawfb_img_getpixel(const struct rawfb_image *img, const int x0, const int y0) if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) { ptr = (unsigned char *)img->pixels + (img->pitch * y0); - if (img->format == NK_FONT_ATLAS_ALPHA8) { - col.a = ptr[x0]; - col.b = col.g = col.r = 0xff; - } else { + if (img->pl.bytesPerPixel == sizeof(unsigned int)) { pixel = ((unsigned int *)ptr)[x0]; col = nk_rawfb_int2color(pixel, img->pl); + } else if (img->pl.bytesPerPixel == sizeof(unsigned short)) { + pixel = ((unsigned short *)ptr)[x0]; + col = nk_rawfb_int2color(pixel, img->pl); + } else { + pixel = ((unsigned char *)ptr)[x0]; + col = nk_rawfb_int2color(pixel, img->pl); } } return col; } @@ -823,33 +812,34 @@ nk_rawfb_clear(const struct rawfb_context *rawfb, const struct nk_color col) NK_API struct rawfb_context* nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int h, - const unsigned int pitch, const rawfb_pl pl) + const unsigned int pitch, const struct rawfb_pl pl) { const void *tex; struct rawfb_context *rawfb; + rawfb = malloc(sizeof(struct rawfb_context)); if (!rawfb) return NULL; memset(rawfb, 0, sizeof(struct rawfb_context)); rawfb->font_tex.pixels = tex_mem; - rawfb->font_tex.format = NK_FONT_ATLAS_ALPHA8; - rawfb->font_tex.w = rawfb->font_tex.h = 0; + rawfb->font_tex.pl.bytesPerPixel = 1; + rawfb->font_tex.pl.rshift = 0; + rawfb->font_tex.pl.gshift = 0; + rawfb->font_tex.pl.bshift = 0; + rawfb->font_tex.pl.ashift = 0; + rawfb->font_tex.pl.rloss = 8; + rawfb->font_tex.pl.gloss = 8; + rawfb->font_tex.pl.bloss = 8; + rawfb->font_tex.pl.aloss = 0; + rawfb->font_tex.w = rawfb->font_tex.h = rawfb->font_tex.pitch = 0; rawfb->fb.pixels = fb; rawfb->fb.w = w; rawfb->fb.h = h; + rawfb->fb.pitch = pitch; rawfb->fb.pl = pl; - if (pl == PIXEL_LAYOUT_RGBX_8888 || pl == PIXEL_LAYOUT_XRGB_8888) { - rawfb->fb.format = NK_FONT_ATLAS_RGBA32; - rawfb->fb.pitch = pitch; - } else { - perror("nk_rawfb_init(): Unsupported pixel layout.\n"); - free(rawfb); - return NULL; - } - if (0 == nk_init_default(&rawfb->ctx, 0)) { free(rawfb); return NULL; @@ -857,21 +847,13 @@ nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int nk_font_atlas_init_default(&rawfb->atlas); nk_font_atlas_begin(&rawfb->atlas); - tex = nk_font_atlas_bake(&rawfb->atlas, &rawfb->font_tex.w, &rawfb->font_tex.h, rawfb->font_tex.format); + tex = nk_font_atlas_bake(&rawfb->atlas, &rawfb->font_tex.w, &rawfb->font_tex.h, NK_FONT_ATLAS_ALPHA8); if (!tex) { free(rawfb); return NULL; } - switch(rawfb->font_tex.format) { - case NK_FONT_ATLAS_ALPHA8: - rawfb->font_tex.pitch = rawfb->font_tex.w * 1; - break; - case NK_FONT_ATLAS_RGBA32: - rawfb->font_tex.pitch = rawfb->font_tex.w * 4; - break; - }; - /* Store the font texture in tex scratch memory */ + rawfb->font_tex.pitch = rawfb->font_tex.w * 1; memcpy(rawfb->font_tex.pixels, tex, rawfb->font_tex.pitch * rawfb->font_tex.h); nk_font_atlas_end(&rawfb->atlas, nk_handle_ptr(NULL), NULL); if (rawfb->atlas.default_font) @@ -1036,7 +1018,7 @@ nk_rawfb_resize_fb(struct rawfb_context *rawfb, const unsigned int w, const unsigned int h, const unsigned int pitch, - const rawfb_pl pl) + const struct rawfb_pl pl) { rawfb->fb.w = w; rawfb->fb.h = h; diff --git a/demo/rawfb/sdl/Makefile b/demo/rawfb/sdl/Makefile index 94dd4eb..f7fe4d2 100644 --- a/demo/rawfb/sdl/Makefile +++ b/demo/rawfb/sdl/Makefile @@ -2,7 +2,7 @@ CFLAGS=`sdl2-config --cflags --libs` -std=c89 -Wall -Wextra -pedantic -Wno-unu .PHONY: clean -demo: main.c nuklear_sdl_rawfb.h +demo: main.c ../nuklear_rawfb.h $(CC) -o demo *.c $(CFLAGS) -lrt -lm clean: diff --git a/demo/rawfb/sdl/main.c b/demo/rawfb/sdl/main.c index e7ba432..1d04691 100644 --- a/demo/rawfb/sdl/main.c +++ b/demo/rawfb/sdl/main.c @@ -20,7 +20,7 @@ #define NK_INCLUDE_SOFTWARE_FONT #include "../../../nuklear.h" #define NK_RAWFB_IMPLEMENTATION -#include "nuklear_sdl_rawfb.h" +#include "../nuklear_rawfb.h" /* =============================================================== * @@ -132,6 +132,8 @@ int main(int argc, char **argv) struct nk_vec2 vec; struct nk_rect bounds = {40,40,0,0}; struct rawfb_context *context; + struct rawfb_pl pl; + unsigned char tex_scratch[512 * 512]; SDL_DisplayMode dm; SDL_Window *window; @@ -164,8 +166,17 @@ int main(int argc, char **argv) surface = SDL_CreateRGBSurfaceWithFormat(0, dm.w-200, dm.h-200, 32, SDL_PIXELFORMAT_ARGB8888); + pl.bytesPerPixel = surface->format->BytesPerPixel; + pl.rshift = surface->format->Rshift; + pl.gshift = surface->format->Gshift; + pl.bshift = surface->format->Bshift; + pl.ashift = surface->format->Ashift; + pl.rloss = surface->format->Rloss; + pl.gloss = surface->format->Gloss; + pl.bloss = surface->format->Bloss; + pl.aloss = surface->format->Aloss; - context = nk_rawfb_init(surface, 13.0f); + context = nk_rawfb_init(surface->pixels, tex_scratch, surface->w, surface->h, surface->pitch, pl); while(1) diff --git a/demo/rawfb/sdl/nuklear_sdl_rawfb.h b/demo/rawfb/sdl/nuklear_sdl_rawfb.h deleted file mode 100644 index 8dd9268..0000000 --- a/demo/rawfb/sdl/nuklear_sdl_rawfb.h +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2016-2017 Patrick Rudolph - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*/ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ - - /* Adapted from nulear_rawfb.h for use with SDL_Surface by Martijn Versteegh*/ - -#ifndef NK_RAWFB_H_ -#define NK_RAWFB_H_ - -#include -#include - -struct rawfb_context; - -/* All functions are thread-safe */ -NK_API struct rawfb_context *nk_rawfb_init(SDL_Surface *fb, float fontSize); -NK_API void nk_rawfb_render(const struct rawfb_context *rawfb, const struct nk_color clear, const unsigned char enable_clear); -NK_API void nk_rawfb_shutdown(struct rawfb_context *rawfb); - -#endif -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_RAWFB_IMPLEMENTATION -#include -#include -#include - -struct rawfb_image { - SDL_Surface *surf; - int w, h; -}; -struct rawfb_context { - struct nk_context ctx; - struct nk_rect scissors; - struct rawfb_image fb; - struct rawfb_image font_tex; - struct nk_font_atlas atlas; -}; - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#endif - -static unsigned int -nk_rawfb_color2int(const struct nk_color c, const SDL_PixelFormat *format) -{ - return SDL_MapRGBA(format, c.r, c.g, c.b, c.a); -} - -static struct nk_color -nk_rawfb_int2color(const unsigned int i, const SDL_PixelFormat *format) -{ - struct nk_color col = {0,0,0,0}; - - SDL_GetRGBA(i, format, &col.r, &col.g, &col.b, &col.a); - - return col; -} - -static void -nk_rawfb_ctx_setpixel(const struct rawfb_context *rawfb, - const short x0, const short y0, const struct nk_color col) -{ - unsigned int c = nk_rawfb_color2int(col, rawfb->fb.surf->format); - unsigned char *pixels = rawfb->fb.surf->pixels; - - pixels += y0 * rawfb->fb.surf->pitch; - - if (y0 < rawfb->scissors.h && y0 >= rawfb->scissors.y && - x0 >= rawfb->scissors.x && x0 < rawfb->scissors.w) { - - if (rawfb->fb.surf->format->BytesPerPixel == 4) { - *((Uint32 *)pixels + x0) = c; - } else if (rawfb->fb.surf->format->BytesPerPixel == 2) { - *((Uint16 *)pixels + x0) = c; - } else { - *((Uint8 *)pixels + x0) = c; - } - } -} - -static void -nk_rawfb_line_horizontal(const struct rawfb_context *rawfb, - const short x0, const short y, const short x1, const struct nk_color col) -{ - /* This function is called the most. Try to optimize it a bit... - * It does not check for scissors or image borders. - * The caller has to make sure it does no exceed bounds. */ - unsigned int i, n; - unsigned char c[16 * 4]; - unsigned char *pixels = rawfb->fb.surf->pixels; - unsigned int bpp = rawfb->fb.surf->format->BytesPerPixel; - - pixels += (y * rawfb->fb.surf->pitch) + (x0 * bpp); - - n = (x1 - x0) * bpp; - if (bpp == 4) { - for (i = 0; i < sizeof(c) / bpp; i++) - ((Uint32 *)c)[i] = nk_rawfb_color2int(col, rawfb->fb.surf->format); - } else if (bpp == 2) { - for (i = 0; i < sizeof(c) / bpp; i++) - ((Uint16 *)c)[i] = nk_rawfb_color2int(col, rawfb->fb.surf->format); - } else { - for (i = 0; i < sizeof(c) / bpp; i++) - ((Uint8 *)c)[i] = nk_rawfb_color2int(col, rawfb->fb.surf->format); - } - - while (n > sizeof(c)) { - memcpy((void*)pixels, c, sizeof(c)); - n -= sizeof(c); pixels += sizeof(c); - } for (i = 0; i < n; i++) - pixels[i] = c[i]; -} - -static void -nk_rawfb_img_setpixel(const struct rawfb_image *img, - const int x0, const int y0, const struct nk_color col) -{ - unsigned int c = nk_rawfb_color2int(col, img->surf->format); - unsigned char *ptr; - NK_ASSERT(img); - if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) { - ptr = (unsigned char *)img->surf->pixels + (img->surf->pitch * y0); - - if (img->surf->format == NK_FONT_ATLAS_ALPHA8) { - ptr[x0] = col.a; - } else if (img->surf->format->BytesPerPixel == 4) { - ((Uint32 *)ptr)[x0] = c; - } else if (img->surf->format->BytesPerPixel == 2) { - ((Uint16 *)ptr)[x0] = c; - } else { - ((Uint8 *)ptr)[x0] = c; - } - } -} - -static struct nk_color -nk_rawfb_img_getpixel(const struct rawfb_image *img, const int x0, const int y0) -{ - struct nk_color col = {0, 0, 0, 0}; - unsigned char *ptr; - unsigned int pixel; - NK_ASSERT(img); - if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) { - ptr = (unsigned char *)img->surf->pixels + (img->surf->pitch * y0); - - if (img->surf->format == NK_FONT_ATLAS_ALPHA8) { - col.a = ptr[x0]; - col.b = col.g = col.r = 0xff; - } else if (img->surf->format->BytesPerPixel == 4) { - pixel = ((Uint32 *)ptr)[x0]; - col = nk_rawfb_int2color(pixel, img->surf->format); - } else if (img->surf->format->BytesPerPixel == 2) { - pixel = ((Uint16 *)ptr)[x0]; - col = nk_rawfb_int2color(pixel, img->surf->format); - } else { - pixel = ((Uint8 *)ptr)[x0]; - col = nk_rawfb_int2color(pixel, img->surf->format); - } - } return col; -} -static void -nk_rawfb_img_blendpixel(const struct rawfb_image *img, - const int x0, const int y0, struct nk_color col) -{ - struct nk_color col2; - unsigned char inv_a; - if (col.a == 0) - return; - - inv_a = 0xff - col.a; - col2 = nk_rawfb_img_getpixel(img, x0, y0); - col.r = (col.r * col.a + col2.r * inv_a) >> 8; - col.g = (col.g * col.a + col2.g * inv_a) >> 8; - col.b = (col.b * col.a + col2.b * inv_a) >> 8; - nk_rawfb_img_setpixel(img, x0, y0, col); -} - -static void -nk_rawfb_scissor(struct rawfb_context *rawfb, - const float x, - const float y, - const float w, - const float h) -{ - rawfb->scissors.x = MIN(MAX(x, 0), rawfb->fb.w); - rawfb->scissors.y = MIN(MAX(y, 0), rawfb->fb.h); - rawfb->scissors.w = MIN(MAX(w + x, 0), rawfb->fb.w); - rawfb->scissors.h = MIN(MAX(h + y, 0), rawfb->fb.h); -} - -static void -nk_rawfb_stroke_line(const struct rawfb_context *rawfb, - short x0, short y0, short x1, short y1, - const unsigned int line_thickness, const struct nk_color col) -{ - short tmp; - int dy, dx, stepx, stepy; - - NK_UNUSED(line_thickness); - - dy = y1 - y0; - dx = x1 - x0; - - /* fast path */ - if (dy == 0) { - if (dx == 0 || y0 >= rawfb->scissors.h || y0 < rawfb->scissors.y) - return; - - if (dx < 0) { - /* swap x0 and x1 */ - tmp = x1; - x1 = x0; - x0 = tmp; - } - x1 = MIN(rawfb->scissors.w, x1); - x0 = MIN(rawfb->scissors.w, x0); - x1 = MAX(rawfb->scissors.x, x1); - x0 = MAX(rawfb->scissors.x, x0); - nk_rawfb_line_horizontal(rawfb, x0, y0, x1, col); - return; - } - if (dy < 0) { - dy = -dy; - stepy = -1; - } else stepy = 1; - - if (dx < 0) { - dx = -dx; - stepx = -1; - } else stepx = 1; - - dy <<= 1; - dx <<= 1; - - nk_rawfb_ctx_setpixel(rawfb, x0, y0, col); - if (dx > dy) { - int fraction = dy - (dx >> 1); - while (x0 != x1) { - if (fraction >= 0) { - y0 += stepy; - fraction -= dx; - } - x0 += stepx; - fraction += dy; - nk_rawfb_ctx_setpixel(rawfb, x0, y0, col); - } - } else { - int fraction = dx - (dy >> 1); - while (y0 != y1) { - if (fraction >= 0) { - x0 += stepx; - fraction -= dy; - } - y0 += stepy; - fraction += dx; - nk_rawfb_ctx_setpixel(rawfb, x0, y0, col); - } - } -} - -static void -nk_rawfb_fill_polygon(const struct rawfb_context *rawfb, - const struct nk_vec2i *pnts, int count, const struct nk_color col) -{ - int i = 0; - #define MAX_POINTS 64 - int left = 10000, top = 10000, bottom = 0, right = 0; - int nodes, nodeX[MAX_POINTS], pixelX, pixelY, j, swap ; - - if (count == 0) return; - if (count > MAX_POINTS) - count = MAX_POINTS; - - /* Get polygon dimensions */ - for (i = 0; i < count; i++) { - if (left > pnts[i].x) - left = pnts[i].x; - if (right < pnts[i].x) - right = pnts[i].x; - if (top > pnts[i].y) - top = pnts[i].y; - if (bottom < pnts[i].y) - bottom = pnts[i].y; - } bottom++; right++; - - /* Polygon scanline algorithm released under public-domain by Darel Rex Finley, 2007 */ - /* Loop through the rows of the image. */ - for (pixelY = top; pixelY < bottom; pixelY ++) { - nodes = 0; /* Build a list of nodes. */ - j = count - 1; - for (i = 0; i < count; i++) { - if (((pnts[i].y < pixelY) && (pnts[j].y >= pixelY)) || - ((pnts[j].y < pixelY) && (pnts[i].y >= pixelY))) { - nodeX[nodes++]= (int)((float)pnts[i].x - + ((float)pixelY - (float)pnts[i].y) / ((float)pnts[j].y - (float)pnts[i].y) - * ((float)pnts[j].x - (float)pnts[i].x)); - } j = i; - } - - /* Sort the nodes, via a simple “Bubble” sort. */ - i = 0; - while (i < nodes - 1) { - if (nodeX[i] > nodeX[i+1]) { - swap = nodeX[i]; - nodeX[i] = nodeX[i+1]; - nodeX[i+1] = swap; - if (i) i--; - } else i++; - } - /* Fill the pixels between node pairs. */ - for (i = 0; i < nodes; i += 2) { - if (nodeX[i+0] >= right) break; - if (nodeX[i+1] > left) { - if (nodeX[i+0] < left) nodeX[i+0] = left ; - if (nodeX[i+1] > right) nodeX[i+1] = right; - for (pixelX = nodeX[i]; pixelX < nodeX[i + 1]; pixelX++) - nk_rawfb_ctx_setpixel(rawfb, pixelX, pixelY, col); - } - } - } - #undef MAX_POINTS -} - -static void -nk_rawfb_stroke_arc(const struct rawfb_context *rawfb, - short x0, short y0, short w, short h, const short s, - const short line_thickness, const struct nk_color col) -{ - /* Bresenham's ellipses - modified to draw one quarter */ - const int a2 = (w * w) / 4; - const int b2 = (h * h) / 4; - const int fa2 = 4 * a2, fb2 = 4 * b2; - int x, y, sigma; - - NK_UNUSED(line_thickness); - - if (s != 0 && s != 90 && s != 180 && s != 270) return; - if (w < 1 || h < 1) return; - - /* Convert upper left to center */ - h = (h + 1) / 2; - w = (w + 1) / 2; - x0 += w; y0 += h; - - /* First half */ - for (x = 0, y = h, sigma = 2*b2+a2*(1-2*h); b2*x <= a2*y; x++) { - if (s == 180) - nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 + y, col); - else if (s == 270) - nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 + y, col); - else if (s == 0) - nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 - y, col); - else if (s == 90) - nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 - y, col); - if (sigma >= 0) { - sigma += fa2 * (1 - y); - y--; - } sigma += b2 * ((4 * x) + 6); - } - - /* Second half */ - for (x = w, y = 0, sigma = 2*a2+b2*(1-2*w); a2*y <= b2*x; y++) { - if (s == 180) - nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 + y, col); - else if (s == 270) - nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 + y, col); - else if (s == 0) - nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 - y, col); - else if (s == 90) - nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 - y, col); - if (sigma >= 0) { - sigma += fb2 * (1 - x); - x--; - } sigma += a2 * ((4 * y) + 6); - } -} - -static void -nk_rawfb_fill_arc(const struct rawfb_context *rawfb, short x0, short y0, - short w, short h, const short s, const struct nk_color col) -{ - /* Bresenham's ellipses - modified to fill one quarter */ - const int a2 = (w * w) / 4; - const int b2 = (h * h) / 4; - const int fa2 = 4 * a2, fb2 = 4 * b2; - int x, y, sigma; - struct nk_vec2i pnts[3]; - if (w < 1 || h < 1) return; - if (s != 0 && s != 90 && s != 180 && s != 270) - return; - - /* Convert upper left to center */ - h = (h + 1) / 2; - w = (w + 1) / 2; - x0 += w; - y0 += h; - - pnts[0].x = x0; - pnts[0].y = y0; - pnts[2].x = x0; - pnts[2].y = y0; - - /* First half */ - for (x = 0, y = h, sigma = 2*b2+a2*(1-2*h); b2*x <= a2*y; x++) { - if (s == 180) { - pnts[1].x = x0 + x; pnts[1].y = y0 + y; - } else if (s == 270) { - pnts[1].x = x0 - x; pnts[1].y = y0 + y; - } else if (s == 0) { - pnts[1].x = x0 + x; pnts[1].y = y0 - y; - } else if (s == 90) { - pnts[1].x = x0 - x; pnts[1].y = y0 - y; - } - nk_rawfb_fill_polygon(rawfb, pnts, 3, col); - pnts[2] = pnts[1]; - if (sigma >= 0) { - sigma += fa2 * (1 - y); - y--; - } sigma += b2 * ((4 * x) + 6); - } - - /* Second half */ - for (x = w, y = 0, sigma = 2*a2+b2*(1-2*w); a2*y <= b2*x; y++) { - if (s == 180) { - pnts[1].x = x0 + x; pnts[1].y = y0 + y; - } else if (s == 270) { - pnts[1].x = x0 - x; pnts[1].y = y0 + y; - } else if (s == 0) { - pnts[1].x = x0 + x; pnts[1].y = y0 - y; - } else if (s == 90) { - pnts[1].x = x0 - x; pnts[1].y = y0 - y; - } - nk_rawfb_fill_polygon(rawfb, pnts, 3, col); - pnts[2] = pnts[1]; - if (sigma >= 0) { - sigma += fb2 * (1 - x); - x--; - } sigma += a2 * ((4 * y) + 6); - } -} - -static void -nk_rawfb_stroke_rect(const struct rawfb_context *rawfb, - const short x, const short y, const short w, const short h, - const short r, const short line_thickness, const struct nk_color col) -{ - if (r == 0) { - nk_rawfb_stroke_line(rawfb, x, y, x + w, y, line_thickness, col); - nk_rawfb_stroke_line(rawfb, x, y + h, x + w, y + h, line_thickness, col); - nk_rawfb_stroke_line(rawfb, x, y, x, y + h, line_thickness, col); - nk_rawfb_stroke_line(rawfb, x + w, y, x + w, y + h, line_thickness, col); - } else { - const short xc = x + r; - const short yc = y + r; - const short wc = (short)(w - 2 * r); - const short hc = (short)(h - 2 * r); - - nk_rawfb_stroke_line(rawfb, xc, y, xc + wc, y, line_thickness, col); - nk_rawfb_stroke_line(rawfb, x + w, yc, x + w, yc + hc, line_thickness, col); - nk_rawfb_stroke_line(rawfb, xc, y + h, xc + wc, y + h, line_thickness, col); - nk_rawfb_stroke_line(rawfb, x, yc, x, yc + hc, line_thickness, col); - - nk_rawfb_stroke_arc(rawfb, xc + wc - r, y, - (unsigned)r*2, (unsigned)r*2, 0 , line_thickness, col); - nk_rawfb_stroke_arc(rawfb, x, y, - (unsigned)r*2, (unsigned)r*2, 90 , line_thickness, col); - nk_rawfb_stroke_arc(rawfb, x, yc + hc - r, - (unsigned)r*2, (unsigned)r*2, 270 , line_thickness, col); - nk_rawfb_stroke_arc(rawfb, xc + wc - r, yc + hc - r, - (unsigned)r*2, (unsigned)r*2, 180 , line_thickness, col); - } -} - -static void -nk_rawfb_fill_rect(const struct rawfb_context *rawfb, - const short x, const short y, const short w, const short h, - const short r, const struct nk_color col) -{ - int i; - if (r == 0) { - for (i = 0; i < h; i++) - nk_rawfb_stroke_line(rawfb, x, y + i, x + w, y + i, 1, col); - } else { - const short xc = x + r; - const short yc = y + r; - const short wc = (short)(w - 2 * r); - const short hc = (short)(h - 2 * r); - - struct nk_vec2i 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; - - nk_rawfb_fill_polygon(rawfb, pnts, 12, col); - - nk_rawfb_fill_arc(rawfb, xc + wc - r, y, - (unsigned)r*2, (unsigned)r*2, 0 , col); - nk_rawfb_fill_arc(rawfb, x, y, - (unsigned)r*2, (unsigned)r*2, 90 , col); - nk_rawfb_fill_arc(rawfb, x, yc + hc - r, - (unsigned)r*2, (unsigned)r*2, 270 , col); - nk_rawfb_fill_arc(rawfb, xc + wc - r, yc + hc - r, - (unsigned)r*2, (unsigned)r*2, 180 , col); - } -} - -NK_API void -nk_rawfb_draw_rect_multi_color(const struct rawfb_context *rawfb, - const short x, const short y, const short w, const short h, struct nk_color tl, - struct nk_color tr, struct nk_color br, struct nk_color bl) -{ - int i, j; - struct nk_color *edge_buf; - struct nk_color *edge_t; - struct nk_color *edge_b; - struct nk_color *edge_l; - struct nk_color *edge_r; - struct nk_color pixel; - - edge_buf = malloc(((2*w) + (2*h)) * sizeof(struct nk_color)); - if (edge_buf == NULL) - return; - - edge_t = edge_buf; - edge_b = edge_buf + w; - edge_l = edge_buf + (w*2); - edge_r = edge_buf + (w*2) + h; - - /* Top and bottom edge gradients */ - for (i=0; ifb, x+j, y+i, edge_t[j]); - } else if (i==h-1) { - nk_rawfb_img_blendpixel(&rawfb->fb, x+j, y+i, edge_b[j]); - } else { - if (j==0) { - nk_rawfb_img_blendpixel(&rawfb->fb, x+j, y+i, edge_l[i]); - } else if (j==w-1) { - nk_rawfb_img_blendpixel(&rawfb->fb, x+j, y+i, edge_r[i]); - } else { - pixel.r = (((((float)edge_r[i].r - edge_l[i].r)/(w-1))*j) + 0.5) + edge_l[i].r; - pixel.g = (((((float)edge_r[i].g - edge_l[i].g)/(w-1))*j) + 0.5) + edge_l[i].g; - pixel.b = (((((float)edge_r[i].b - edge_l[i].b)/(w-1))*j) + 0.5) + edge_l[i].b; - pixel.a = (((((float)edge_r[i].a - edge_l[i].a)/(w-1))*j) + 0.5) + edge_l[i].a; - nk_rawfb_img_blendpixel(&rawfb->fb, x+j, y+i, pixel); - } - } - } - } - - free(edge_buf); -} - -static void -nk_rawfb_fill_triangle(const struct rawfb_context *rawfb, - const short x0, const short y0, const short x1, const short y1, - const short x2, const short y2, const struct nk_color col) -{ - struct nk_vec2i pnts[3]; - pnts[0].x = x0; - pnts[0].y = y0; - pnts[1].x = x1; - pnts[1].y = y1; - pnts[2].x = x2; - pnts[2].y = y2; - nk_rawfb_fill_polygon(rawfb, pnts, 3, col); -} - -static void -nk_rawfb_stroke_triangle(const struct rawfb_context *rawfb, - const short x0, const short y0, const short x1, const short y1, - const short x2, const short y2, const unsigned short line_thickness, - const struct nk_color col) -{ - nk_rawfb_stroke_line(rawfb, x0, y0, x1, y1, line_thickness, col); - nk_rawfb_stroke_line(rawfb, x1, y1, x2, y2, line_thickness, col); - nk_rawfb_stroke_line(rawfb, x2, y2, x0, y0, line_thickness, col); -} - -static void -nk_rawfb_stroke_polygon(const struct rawfb_context *rawfb, - const struct nk_vec2i *pnts, const int count, - const unsigned short line_thickness, const struct nk_color col) -{ - int i; - for (i = 1; i < count; ++i) - nk_rawfb_stroke_line(rawfb, pnts[i-1].x, pnts[i-1].y, pnts[i].x, - pnts[i].y, line_thickness, col); - nk_rawfb_stroke_line(rawfb, pnts[count-1].x, pnts[count-1].y, - pnts[0].x, pnts[0].y, line_thickness, col); -} - -static void -nk_rawfb_stroke_polyline(const struct rawfb_context *rawfb, - const struct nk_vec2i *pnts, const int count, - const unsigned short line_thickness, const struct nk_color col) -{ - int i; - for (i = 0; i < count-1; ++i) - nk_rawfb_stroke_line(rawfb, pnts[i].x, pnts[i].y, - pnts[i+1].x, pnts[i+1].y, line_thickness, col); -} - -static void -nk_rawfb_fill_circle(const struct rawfb_context *rawfb, - short x0, short y0, short w, short h, const struct nk_color col) -{ - /* Bresenham's ellipses */ - const int a2 = (w * w) / 4; - const int b2 = (h * h) / 4; - const int fa2 = 4 * a2, fb2 = 4 * b2; - int x, y, sigma; - - /* Convert upper left to center */ - h = (h + 1) / 2; - w = (w + 1) / 2; - x0 += w; - y0 += h; - - /* First half */ - for (x = 0, y = h, sigma = 2*b2+a2*(1-2*h); b2*x <= a2*y; x++) { - nk_rawfb_stroke_line(rawfb, x0 - x, y0 + y, x0 + x, y0 + y, 1, col); - nk_rawfb_stroke_line(rawfb, x0 - x, y0 - y, x0 + x, y0 - y, 1, col); - if (sigma >= 0) { - sigma += fa2 * (1 - y); - y--; - } sigma += b2 * ((4 * x) + 6); - } - /* Second half */ - for (x = w, y = 0, sigma = 2*a2+b2*(1-2*w); a2*y <= b2*x; y++) { - nk_rawfb_stroke_line(rawfb, x0 - x, y0 + y, x0 + x, y0 + y, 1, col); - nk_rawfb_stroke_line(rawfb, x0 - x, y0 - y, x0 + x, y0 - y, 1, col); - if (sigma >= 0) { - sigma += fb2 * (1 - x); - x--; - } sigma += a2 * ((4 * y) + 6); - } -} - -static void -nk_rawfb_stroke_circle(const struct rawfb_context *rawfb, - short x0, short y0, short w, short h, const short line_thickness, - const struct nk_color col) -{ - /* Bresenham's ellipses */ - const int a2 = (w * w) / 4; - const int b2 = (h * h) / 4; - const int fa2 = 4 * a2, fb2 = 4 * b2; - int x, y, sigma; - - NK_UNUSED(line_thickness); - - /* Convert upper left to center */ - h = (h + 1) / 2; - w = (w + 1) / 2; - x0 += w; - y0 += h; - - /* First half */ - for (x = 0, y = h, sigma = 2*b2+a2*(1-2*h); b2*x <= a2*y; x++) { - nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 + y, col); - nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 + y, col); - nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 - y, col); - nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 - y, col); - if (sigma >= 0) { - sigma += fa2 * (1 - y); - y--; - } sigma += b2 * ((4 * x) + 6); - } - /* Second half */ - for (x = w, y = 0, sigma = 2*a2+b2*(1-2*w); a2*y <= b2*x; y++) { - nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 + y, col); - nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 + y, col); - nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 - y, col); - nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 - y, col); - if (sigma >= 0) { - sigma += fb2 * (1 - x); - x--; - } sigma += a2 * ((4 * y) + 6); - } -} - -static void -nk_rawfb_stroke_curve(const struct rawfb_context *rawfb, - const struct nk_vec2i p1, const struct nk_vec2i p2, - const struct nk_vec2i p3, const struct nk_vec2i p4, - const unsigned int num_segments, const unsigned short line_thickness, - const struct nk_color col) -{ - unsigned int i_step, segments; - float t_step; - struct nk_vec2i last = p1; - - segments = MAX(num_segments, 1); - t_step = 1.0f/(float)segments; - for (i_step = 1; i_step <= 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_rawfb_stroke_line(rawfb, last.x, last.y, - (short)x, (short)y, line_thickness,col); - last.x = (short)x; last.y = (short)y; - } -} - -static void -nk_rawfb_clear(const struct rawfb_context *rawfb, const struct nk_color col) -{ - nk_rawfb_fill_rect(rawfb, 0, 0, rawfb->fb.w, rawfb->fb.h, 0, col); -} - -NK_API struct rawfb_context* -nk_rawfb_init(SDL_Surface *fb, float fontSize) -{ - const void *tex; - struct rawfb_context *rawfb; - - assert((fb->format->format == SDL_PIXELFORMAT_ARGB8888) - || (fb->format->format == SDL_PIXELFORMAT_RGBA8888)); - - rawfb = malloc(sizeof(struct rawfb_context)); - if (!rawfb) - return NULL; - - memset(rawfb, 0, sizeof(struct rawfb_context)); - - rawfb->fb.surf = fb; - rawfb->fb.w = fb->w; - rawfb->fb.h = fb->h; - - if (0 == nk_init_default(&rawfb->ctx, 0)) { - free(rawfb); - return NULL; - } - - nk_font_atlas_init_default(&rawfb->atlas); - nk_font_atlas_begin(&rawfb->atlas); - rawfb->atlas.default_font = nk_font_atlas_add_default(&rawfb->atlas, fontSize, 0); - tex = nk_font_atlas_bake(&rawfb->atlas, &rawfb->font_tex.w, &rawfb->font_tex.h, NK_FONT_ATLAS_RGBA32); - if (!tex) { - free(rawfb); - return NULL; - } - - rawfb->font_tex.surf = SDL_CreateRGBSurface(0, rawfb->font_tex.w, rawfb->font_tex.h, 32, 0xff, 0xff00, 0xff0000, 0xff000000); - - memcpy(rawfb->font_tex.surf->pixels, tex, rawfb->font_tex.w * rawfb->font_tex.h * 4); - nk_font_atlas_end(&rawfb->atlas, nk_handle_ptr(NULL), NULL); - if (rawfb->atlas.default_font) - nk_style_set_font(&rawfb->ctx, &rawfb->atlas.default_font->handle); - nk_style_load_all_cursors(&rawfb->ctx, rawfb->atlas.cursors); - nk_rawfb_scissor(rawfb, 0, 0, rawfb->fb.w, rawfb->fb.h); - - return rawfb; -} - -static void -nk_rawfb_stretch_image(const struct rawfb_image *dst, - const struct rawfb_image *src, const struct nk_rect *dst_rect, - const struct nk_rect *src_rect, const struct nk_rect *dst_scissors, - const struct nk_color *fg) -{ - short i, j; - struct nk_color col; - float xinc = src_rect->w / dst_rect->w; - float yinc = src_rect->h / dst_rect->h; - float xoff = src_rect->x, yoff = src_rect->y; - - /* Simple nearest filtering rescaling */ - /* TODO: use bilinear filter */ - for (j = 0; j < (short)dst_rect->h; j++) { - for (i = 0; i < (short)dst_rect->w; i++) { - if (dst_scissors) { - if (i + (int)(dst_rect->x + 0.5f) < dst_scissors->x || i + (int)(dst_rect->x + 0.5f) >= dst_scissors->w) - continue; - if (j + (int)(dst_rect->y + 0.5f) < dst_scissors->y || j + (int)(dst_rect->y + 0.5f) >= dst_scissors->h) - continue; - } - col = nk_rawfb_img_getpixel(src, (int)xoff, (int) yoff); - if (col.r || col.g || col.b) - { - col.r = fg->r; - col.g = fg->g; - col.b = fg->b; - } - nk_rawfb_img_blendpixel(dst, i + (int)(dst_rect->x + 0.5f), j + (int)(dst_rect->y + 0.5f), col); - xoff += xinc; - } - xoff = src_rect->x; - yoff += yinc; - } -} - -static void -nk_rawfb_font_query_font_glyph(nk_handle handle, const float height, - struct nk_user_font_glyph *glyph, const nk_rune codepoint, - const nk_rune next_codepoint) -{ - float scale; - const struct nk_font_glyph *g; - struct nk_font *font; - NK_ASSERT(glyph); - NK_UNUSED(next_codepoint); - - font = (struct nk_font*)handle.ptr; - NK_ASSERT(font); - NK_ASSERT(font->glyphs); - if (!font || !glyph) - return; - - scale = height/font->info.height; - g = nk_font_find_glyph(font, codepoint); - glyph->width = (g->x1 - g->x0) * scale; - glyph->height = (g->y1 - g->y0) * scale; - glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale); - glyph->xadvance = (g->xadvance * scale); - glyph->uv[0] = nk_vec2(g->u0, g->v0); - glyph->uv[1] = nk_vec2(g->u1, g->v1); -} - -NK_API void -nk_rawfb_draw_text(const struct rawfb_context *rawfb, - const struct nk_user_font *font, const struct nk_rect rect, - const char *text, const int len, const float font_height, - const struct nk_color fg) -{ - float x = 0; - int text_len = 0; - nk_rune unicode = 0; - nk_rune next = 0; - int glyph_len = 0; - int next_glyph_len = 0; - struct nk_user_font_glyph g; - if (!len || !text) return; - - x = 0; - glyph_len = nk_utf_decode(text, &unicode, len); - if (!glyph_len) return; - - /* draw every glyph image */ - while (text_len < len && glyph_len) { - struct nk_rect src_rect; - struct nk_rect dst_rect; - float char_width = 0; - if (unicode == NK_UTF_INVALID) break; - - /* query currently drawn glyph information */ - next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len); - nk_rawfb_font_query_font_glyph(font->userdata, font_height, &g, unicode, - (next == NK_UTF_INVALID) ? '\0' : next); - - /* calculate and draw glyph drawing rectangle and image */ - char_width = g.xadvance; - src_rect.x = g.uv[0].x * rawfb->font_tex.w; - src_rect.y = g.uv[0].y * rawfb->font_tex.h; - src_rect.w = g.uv[1].x * rawfb->font_tex.w - g.uv[0].x * rawfb->font_tex.w; - src_rect.h = g.uv[1].y * rawfb->font_tex.h - g.uv[0].y * rawfb->font_tex.h; - - dst_rect.x = x + g.offset.x + rect.x; - dst_rect.y = g.offset.y + rect.y; - dst_rect.w = ceil(g.width); - dst_rect.h = ceil(g.height); - - /* Use software rescaling to blit glyph from font_text to framebuffer */ - nk_rawfb_stretch_image(&rawfb->fb, &rawfb->font_tex, &dst_rect, &src_rect, &rawfb->scissors, &fg); - - /* offset next glyph */ - text_len += glyph_len; - x += char_width; - glyph_len = next_glyph_len; - unicode = next; - } -} - -NK_API void -nk_rawfb_drawimage(const struct rawfb_context *rawfb, - const int x, const int y, const int w, const int h, - const struct nk_image *img, const struct nk_color *col) -{ - struct nk_rect src_rect; - struct nk_rect dst_rect; - - src_rect.x = img->region[0]; - src_rect.y = img->region[1]; - src_rect.w = img->region[2]; - src_rect.h = img->region[3]; - - dst_rect.x = x; - dst_rect.y = y; - dst_rect.w = w; - dst_rect.h = h; - nk_rawfb_stretch_image(&rawfb->fb, &rawfb->font_tex, &dst_rect, &src_rect, &rawfb->scissors, col); -} - -NK_API void -nk_rawfb_shutdown(struct rawfb_context *rawfb) -{ - if (rawfb) { - SDL_FreeSurface(rawfb->font_tex.surf); - nk_free(&rawfb->ctx); - memset(rawfb, 0, sizeof(struct rawfb_context)); - free(rawfb); - } -} - - -NK_API void -nk_rawfb_render(const struct rawfb_context *rawfb, - const struct nk_color clear, - const unsigned char enable_clear) -{ - const struct nk_command *cmd; - if (enable_clear) - nk_rawfb_clear(rawfb, clear); - - nk_foreach(cmd, (struct nk_context*)&rawfb->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_rawfb_scissor((struct rawfb_context *)rawfb, 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_rawfb_stroke_line(rawfb, 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_rawfb_stroke_rect(rawfb, 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_rawfb_fill_rect(rawfb, 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_rawfb_stroke_circle(rawfb, 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_rawfb_fill_circle(rawfb, 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_rawfb_stroke_triangle(rawfb, 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_rawfb_fill_triangle(rawfb, 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_rawfb_stroke_polygon(rawfb, 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_rawfb_fill_polygon(rawfb, 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_rawfb_stroke_polyline(rawfb, 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_rawfb_draw_text(rawfb, t->font, nk_rect(t->x, t->y, t->w, t->h), - t->string, t->length, t->height, t->foreground); - } break; - case NK_COMMAND_CURVE: { - const struct nk_command_curve *q = (const struct nk_command_curve *)cmd; - nk_rawfb_stroke_curve(rawfb, 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 *q = (const struct nk_command_rect_multi_color *)cmd; - nk_rawfb_draw_rect_multi_color(rawfb, q->x, q->y, q->w, q->h, q->left, q->top, q->right, q->bottom); - } break; - case NK_COMMAND_IMAGE: { - const struct nk_command_image *q = (const struct nk_command_image *)cmd; - nk_rawfb_drawimage(rawfb, q->x, q->y, q->w, q->h, &q->img, &q->col); - } break; - case NK_COMMAND_ARC: { - assert(0 && "NK_COMMAND_ARC not implemented\n"); - } break; - case NK_COMMAND_ARC_FILLED: { - assert(0 && "NK_COMMAND_ARC_FILLED not implemented\n"); - } break; - default: break; - } - } nk_clear((struct nk_context*)&rawfb->ctx); -} -#endif - diff --git a/demo/rawfb/wayland/main.c b/demo/rawfb/wayland/main.c index 7241422..6d16b9f 100644 --- a/demo/rawfb/wayland/main.c +++ b/demo/rawfb/wayland/main.c @@ -450,6 +450,7 @@ int main () struct nk_wayland nk_wayland_ctx; struct wl_registry *registry; int running = 1; + struct rawfb_pl pl; //1. Initialize display nk_wayland_ctx.display = wl_display_connect (NULL); @@ -495,7 +496,17 @@ int main () wl_surface_attach (nk_wayland_ctx.surface, nk_wayland_ctx.front_buffer, 0, 0); wl_surface_commit (nk_wayland_ctx.surface); - nk_rawfb_init(nk_wayland_ctx.data, nk_wayland_ctx.tex_scratch, WIDTH, HEIGHT, WIDTH*4, PIXEL_LAYOUT_XRGB_8888); + pl.bytesPerPixel = 4; + pl.ashift = 24; + pl.rshift = 16; + pl.gshift = 8; + pl.bshift = 0; + pl.aloss = 0; + pl.rloss = 0; + pl.gloss = 0; + pl.bloss = 0; + + nk_rawfb_init(nk_wayland_ctx.data, nk_wayland_ctx.tex_scratch, WIDTH, HEIGHT, WIDTH*4, pl); //4. rendering UI diff --git a/demo/rawfb/x11/main.c b/demo/rawfb/x11/main.c index 905f43b..f3f4a43 100644 --- a/demo/rawfb/x11/main.c +++ b/demo/rawfb/x11/main.c @@ -156,7 +156,7 @@ main(void) XWindow xw; struct rawfb_context *rawfb; void *fb = NULL; - rawfb_pl pl; + struct rawfb_pl pl; unsigned char tex_scratch[512 * 512]; /* X11 */ diff --git a/demo/rawfb/x11/nuklear_xlib.h b/demo/rawfb/x11/nuklear_xlib.h index 3174e24..8163a52 100644 --- a/demo/rawfb/x11/nuklear_xlib.h +++ b/demo/rawfb/x11/nuklear_xlib.h @@ -35,7 +35,7 @@ #include -NK_API int nk_xlib_init(Display *dpy, Visual *vis, int screen, Window root, unsigned int w, unsigned int h, void **fb, rawfb_pl *pl); +NK_API int nk_xlib_init(Display *dpy, Visual *vis, int screen, Window root, unsigned int w, unsigned int h, void **fb, struct rawfb_pl *pl); NK_API int nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt, struct rawfb_context *rawfb); NK_API void nk_xlib_render(Drawable screen); NK_API void nk_xlib_shutdown(void); @@ -74,7 +74,7 @@ static struct { NK_API int nk_xlib_init(Display *dpy, Visual *vis, int screen, Window root, - unsigned int w, unsigned int h, void **fb, rawfb_pl *pl) + unsigned int w, unsigned int h, void **fb, struct rawfb_pl *pl) { unsigned int depth = XDefaultDepth(dpy, screen); xlib.dpy = dpy; @@ -138,22 +138,15 @@ nk_xlib_init(Display *dpy, Visual *vis, int screen, Window root, xlib.gc = XDefaultGC(dpy, screen); *fb = xlib.ximg->data; - if (xlib.ximg->red_mask == 0xff0000 && - xlib.ximg->green_mask == 0xff00 && - xlib.ximg->blue_mask == 0xff && - xlib.ximg->bits_per_pixel == 32) { - *pl = PIXEL_LAYOUT_XRGB_8888; - } - else if (xlib.ximg->red_mask == 0xff000000 && - xlib.ximg->green_mask == 0xff0000 && - xlib.ximg->blue_mask == 0xff00 && - xlib.ximg->bits_per_pixel == 32) { - *pl = PIXEL_LAYOUT_RGBX_8888; - } - else { - perror("nk_xlib_init(): Unrecognized pixel layout.\n"); - return 0; - } + pl->bytesPerPixel = xlib.ximg->bits_per_pixel / 8; + pl->rshift = __builtin_ctzl(xlib.ximg->red_mask); + pl->gshift = __builtin_ctzl(xlib.ximg->green_mask); + pl->bshift = __builtin_ctzl(xlib.ximg->blue_mask); + pl->ashift = 0; + pl->rloss = 8 - __builtin_popcount(xlib.ximg->red_mask); + pl->gloss = 8 - __builtin_popcount(xlib.ximg->green_mask); + pl->bloss = 8 - __builtin_popcount(xlib.ximg->blue_mask); + pl->aloss = 8; return 1; } @@ -257,7 +250,7 @@ nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt, struct r } else if (evt->type == Expose || evt->type == ConfigureNotify) { /* Window resize handler */ void *fb; - rawfb_pl pl; + struct rawfb_pl pl; unsigned int width, height; XWindowAttributes attr; XGetWindowAttributes(dpy, win, &attr);