diff options
-rw-r--r-- | include/libnsfb.h | 1 | ||||
-rw-r--r-- | include/nsfb.h | 2 | ||||
-rw-r--r-- | include/palette.h | 111 | ||||
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/libnsfb.c | 5 | ||||
-rw-r--r-- | src/palette.c | 89 | ||||
-rw-r--r-- | src/plot/8bpp.c | 32 | ||||
-rw-r--r-- | src/surface/sdl.c | 52 |
8 files changed, 228 insertions, 66 deletions
diff --git a/include/libnsfb.h b/include/libnsfb.h index 739617e..da8e5f6 100644 --- a/include/libnsfb.h +++ b/include/libnsfb.h @@ -13,6 +13,7 @@ #include <stdint.h> +typedef struct nsfb_palette_s nsfb_palette_t; typedef struct nsfb_cursor_s nsfb_cursor_t; typedef struct nsfb_s nsfb_t; typedef struct nsfb_event_s nsfb_event_t; diff --git a/include/nsfb.h b/include/nsfb.h index 5caff9b..9a61775 100644 --- a/include/nsfb.h +++ b/include/nsfb.h @@ -28,7 +28,7 @@ struct nsfb_s { uint8_t *ptr; /**< Base of video memory. */ int linelen; /**< length of a video line. */ - nsfb_colour_t palette[256]; /**< palette for index modes */ + struct nsfb_palette_s *palette; /**< palette for index modes */ nsfb_cursor_t *cursor; /**< cursor */ struct nsfb_surface_rtns_s *surface_rtns; /**< surface routines. */ diff --git a/include/palette.h b/include/palette.h new file mode 100644 index 0000000..845c1bc --- /dev/null +++ b/include/palette.h @@ -0,0 +1,111 @@ +/* + * Copyright 2012 Michael Drake <tlsa@netsurf-browser.org> + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * + * This is the *internal* interface for the cursor. + */ + +#ifndef PALETTE_H +#define PALETTE_H 1 + +#include <stdint.h> +#include <limits.h> + +#include "libnsfb.h" +#include "libnsfb_plot.h" + +enum nsfb_palette_type_e { + NSFB_PALETTE_EMPTY, /**< empty palette object */ + NSFB_PALETTE_NSFB_8BPP, /**< libnsfb's own 8bpp palette */ + NSFB_PALETTE_OTHER /**< any other palette */ +}; + +struct nsfb_palette_s { + enum nsfb_palette_type_e type; /**< Palette type */ + uint8_t last; /**< Last used palette index */ + nsfb_colour_t data[256]; /**< Palette for index modes */ +}; + +/** Create an empty palette object. */ +bool nsfb_palette_new(struct nsfb_palette_s **palette); + +/** Free a palette object. */ +void nsfb_palette_free(struct nsfb_palette_s *palette); + +/** Generate libnsfb 8bpp default palette. */ +void nsfb_palette_generate_nsfb_8bpp(struct nsfb_palette_s *palette); + + +static inline uint8_t nsfb_palette_best_match( + const struct nsfb_palette_s *palette, + nsfb_colour_t c) +{ + uint8_t best_col = 0; + + nsfb_colour_t palent; + int col; + int dr, dg, db; /* delta red, green blue values */ + + int cur_distance; + int best_distance = INT_MAX; + + switch (palette->type) { + case NSFB_PALETTE_NSFB_8BPP: + /* Index into colour cube part */ + dr = ((( c & 0xFF) * 5) + 128) / 256; + dg = ((((c >> 8) & 0xFF) * 7) + 128) / 256; + db = ((((c >> 16) & 0xFF) * 4) + 128) / 256; + col = 40 * dr + 5 * dg + db; + + palent = palette->data[col]; + dr = ( c & 0xFF) - ( palent & 0xFF); + dg = ((c >> 8) & 0xFF) - ((palent >> 8 ) & 0xFF); + db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF); + cur_distance = (dr * dr) + (dg * dg) + (db * db); + + best_col = col; + best_distance = cur_distance; + + /* Index into grayscale part */ + col = (( c & 0xFF) + + ((c >> 8) & 0xFF) + + ((c >> 16) & 0xFF) + (45 / 2)) / (15 * 3) - 1 + 240; + palent = palette->data[col]; + + dr = ( c & 0xFF) - ( palent & 0xFF); + dg = ((c >> 8) & 0xFF) - ((palent >> 8) & 0xFF); + db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF); + cur_distance = (dr * dr) + (dg * dg) + (db * db); + if (cur_distance < best_distance) { + best_distance = cur_distance; + best_col = col; + } + break; + + case NSFB_PALETTE_OTHER: + /* Try all colours in palette */ + for (col = 0; col <= palette->last; col++) { + palent = palette->data[col]; + + dr = ( c & 0xFF) - ( palent & 0xFF); + dg = ((c >> 8) & 0xFF) - ((palent >> 8) & 0xFF); + db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF); + cur_distance = (dr * dr) + (dg * dg) + (db * db); + if (cur_distance < best_distance) { + best_distance = cur_distance; + best_col = col; + } + } + break; + + default: + break; + } + + return best_col; +} + +#endif /* PALETTE_H */ diff --git a/src/Makefile b/src/Makefile index 283a99f..3c6e2f0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ # Sources -DIR_SOURCES := libnsfb.c dump.c cursor.c +DIR_SOURCES := libnsfb.c dump.c cursor.c palette.c include $(NSBUILD)/Makefile.subdir diff --git a/src/libnsfb.c b/src/libnsfb.c index 6f14c99..a341088 100644 --- a/src/libnsfb.c +++ b/src/libnsfb.c @@ -15,6 +15,7 @@ #include "libnsfb_plot.h" #include "libnsfb_event.h" #include "nsfb.h" +#include "palette.h" #include "surface.h" /* exported interface documented in libnsfb.h */ @@ -50,6 +51,10 @@ int nsfb_free(nsfb_t *nsfb) { int ret; + + if (nsfb->palette != NULL) + nsfb_palette_free(nsfb->palette); + ret = nsfb->surface_rtns->finalise(nsfb); free(nsfb); return ret; diff --git a/src/palette.c b/src/palette.c new file mode 100644 index 0000000..eba95cd --- /dev/null +++ b/src/palette.c @@ -0,0 +1,89 @@ +/* + * Copyright 2012 Michael Drake <tlsa@netsurf-browser.org> + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +/** \file + * Palette (implementation). + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> + +#include "palette.h" + + +/** Create an empty palette object. */ +bool nsfb_palette_new(struct nsfb_palette_s **palette) +{ + *palette = malloc(sizeof(struct nsfb_palette_s)); + if (*palette == NULL) { + return false; + } + + (*palette)->type = NSFB_PALETTE_EMPTY; + (*palette)->last = 0; + + return true; +} + +/** Free a palette object. */ +void nsfb_palette_free(struct nsfb_palette_s *palette) +{ + if (palette != NULL) + free(palette); +} + +/** Generate libnsfb 8bpp default palette. */ +void nsfb_palette_generate_nsfb_8bpp(struct nsfb_palette_s *palette) +{ + int rloop, gloop, bloop; + int loop = 0; + uint8_t r, g, b; + + /* Build a linear 6-8-5 levels RGB colour cube palette. + * This accounts for 240 colours */ +#define RLIM 6 +#define GLIM 8 +#define BLIM 5 + for (rloop = 0; rloop < RLIM; rloop++) { + for (gloop = 0; gloop < GLIM; gloop++) { + for (bloop = 0; bloop < BLIM; bloop++) { + r = ((rloop * 255 * 2) + RLIM - 1) / + (2 * (RLIM - 1)); + g = ((gloop * 255 * 2) + GLIM - 1) / + (2 * (GLIM - 1)); + b = ((bloop * 255 * 2) + BLIM - 1) / + (2 * (BLIM - 1)); + + palette->data[loop] = r | g << 8 | b << 16; + loop++; + } + } + } +#undef RLIM +#undef GLIM +#undef BLIM + + /* Should have 240 colours set */ + assert(loop == 240); + + /* Fill index 240 to index 255 with grayscales */ + /* Note: already have full black and full white from RGB cube */ + for (; loop < 256; loop++) { + int ngray = loop - 240 + 1; + r = ngray * 15; /* 17*15 = 255 */ + + g = b = r; + + palette->data[loop] = r | g << 8 | b << 16; + } + + /* Set palette details */ + palette->type = NSFB_PALETTE_NSFB_8BPP; + palette->last = 255; +} diff --git a/src/plot/8bpp.c b/src/plot/8bpp.c index b72303d..05574d8 100644 --- a/src/plot/8bpp.c +++ b/src/plot/8bpp.c @@ -10,7 +10,6 @@ #include <stdbool.h> #include <endian.h> #include <stdlib.h> -#include <limits.h> #include <string.h> #include "libnsfb.h" @@ -18,6 +17,7 @@ #include "libnsfb_plot_util.h" #include "nsfb.h" +#include "palette.h" #include "plot.h" static inline uint8_t *get_xy_loc(nsfb_t *nsfb, int x, int y) @@ -28,34 +28,18 @@ static inline uint8_t *get_xy_loc(nsfb_t *nsfb, int x, int y) static inline nsfb_colour_t pixel_to_colour(nsfb_t *nsfb, uint8_t pixel) { - return nsfb->palette[pixel]; + if (nsfb->palette == NULL) + return 0; + + return nsfb->palette->data[pixel]; } static uint8_t colour_to_pixel(nsfb_t *nsfb, nsfb_colour_t c) { - nsfb_colour_t palent; - int col; - - int dr, dg, db; /* delta red, green blue values */ - - int cur_distance; - int best_distance = INT_MAX; - uint8_t best_col = 0; - - for (col = 0; col < 256; col++) { - palent = nsfb->palette[col]; - - dr = (c & 0xFF) - (palent & 0xFF); - dg = ((c >> 8) & 0xFF) - ((palent >> 8) & 0xFF); - db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF); - cur_distance = ((dr * dr) + (dg * dg) + (db *db)); - if (cur_distance < best_distance) { - best_distance = cur_distance; - best_col = col; - } - } + if (nsfb->palette == NULL) + return 0; - return best_col; + return nsfb_palette_best_match(nsfb->palette, c); } #define PLOT_TYPE uint8_t diff --git a/src/surface/sdl.c b/src/surface/sdl.c index d598b8a..7a86dc1 100644 --- a/src/surface/sdl.c +++ b/src/surface/sdl.c @@ -6,7 +6,6 @@ * http://www.opensource.org/licenses/mit-license.php */ -#include <assert.h> #include <stdbool.h> #include <stdlib.h> #include <SDL/SDL.h> @@ -18,6 +17,7 @@ #include "nsfb.h" #include "surface.h" +#include "palette.h" #include "plot.h" #include "cursor.h" @@ -353,49 +353,19 @@ set_palette(nsfb_t *nsfb) { SDL_Surface *sdl_screen = nsfb->surface_priv; SDL_Color palette[256]; - int rloop, gloop, bloop; int loop = 0; - /* Build a linear 6-8-5 levels RGB colour cube palette. - * This accounts for 240 colours */ -#define RLIM 6 -#define GLIM 8 -#define BLIM 5 - for (rloop = 0; rloop < RLIM; rloop++) { - for (gloop = 0; gloop < GLIM; gloop++) { - for (bloop = 0; bloop < BLIM; bloop++) { - palette[loop].r = ((rloop * 255 * 2) + RLIM - 1) / (2 * (RLIM - 1)); - palette[loop].g = ((gloop * 255 * 2) + GLIM - 1) / (2 * (GLIM - 1)); - palette[loop].b = ((bloop * 255 * 2) + BLIM - 1) / (2 * (BLIM - 1)); - - nsfb->palette[loop] = palette[loop].r | - palette[loop].g << 8 | - palette[loop].b << 16; - loop++; - } - } - } -#undef RLIM -#undef GLIM -#undef BLIM - - /* Should have 240 colours set */ - assert(loop == 240); + /* Get libnsfb palette */ + nsfb_palette_generate_nsfb_8bpp(nsfb->palette); - /* Fill index 240 to index 255 with grayscales */ - /* Note: already have full black and full white from RGB cube */ - for (; loop < 256; loop++) { - int ngray = loop - 240 + 1; - palette[loop].r = ngray * 15; /* 17*15 = 255 */ - - palette[loop].g = palette[loop].b = palette[loop].r; - - nsfb->palette[loop] = palette[loop].r | - palette[loop].g << 8 | - palette[loop].b << 16; + /* Create SDL palette from nsfb palette */ + for (loop = 0; loop < 256; loop++) { + palette[loop].r = (nsfb->palette->data[loop] ) & 0xFF; + palette[loop].g = (nsfb->palette->data[loop] >> 8) & 0xFF; + palette[loop].b = (nsfb->palette->data[loop] >> 16) & 0xFF; } - /* Set palette */ + /* Set SDL palette */ SDL_SetColors(sdl_screen, palette, 0, 256); } @@ -487,8 +457,10 @@ static int sdl_initialise(nsfb_t *nsfb) nsfb->surface_priv = sdl_screen; - if (nsfb->bpp == 8) + if (nsfb->bpp == 8) { + nsfb_palette_new(&nsfb->palette); set_palette(nsfb); + } nsfb->ptr = sdl_screen->pixels; nsfb->linelen = sdl_screen->pitch; |