summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libnsfb.h1
-rw-r--r--include/nsfb.h2
-rw-r--r--include/palette.h111
-rw-r--r--src/Makefile2
-rw-r--r--src/libnsfb.c5
-rw-r--r--src/palette.c89
-rw-r--r--src/plot/8bpp.c32
-rw-r--r--src/surface/sdl.c52
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;