[Scummvm-cvs-logs] SF.net SVN: scummvm:[39242] scummvm/trunk/engines/sci

wjpalenstijn at users.sourceforge.net wjpalenstijn at users.sourceforge.net
Sun Mar 8 21:17:01 CET 2009


Revision: 39242
          http://scummvm.svn.sourceforge.net/scummvm/?rev=39242&view=rev
Author:   wjpalenstijn
Date:     2009-03-08 20:17:01 +0000 (Sun, 08 Mar 2009)

Log Message:
-----------
Use new Palette class to manager pixmap palettes.

There are some remaining regressions with text colour in SCI1 games,
but overall it should fix more than it breaks.

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/game.cpp
    scummvm/trunk/engines/sci/engine/kgraphics.cpp
    scummvm/trunk/engines/sci/engine/kmenu.cpp
    scummvm/trunk/engines/sci/engine/kpathing.cpp
    scummvm/trunk/engines/sci/engine/state.h
    scummvm/trunk/engines/sci/gfx/font.cpp
    scummvm/trunk/engines/sci/gfx/font.h
    scummvm/trunk/engines/sci/gfx/gfx_driver.cpp
    scummvm/trunk/engines/sci/gfx/gfx_driver.h
    scummvm/trunk/engines/sci/gfx/gfx_pixmap_scale.cpp
    scummvm/trunk/engines/sci/gfx/gfx_res_options.cpp
    scummvm/trunk/engines/sci/gfx/gfx_resmgr.h
    scummvm/trunk/engines/sci/gfx/gfx_resource.cpp
    scummvm/trunk/engines/sci/gfx/gfx_resource.h
    scummvm/trunk/engines/sci/gfx/gfx_system.h
    scummvm/trunk/engines/sci/gfx/gfx_tools.cpp
    scummvm/trunk/engines/sci/gfx/gfx_tools.h
    scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp
    scummvm/trunk/engines/sci/gfx/operations.cpp
    scummvm/trunk/engines/sci/gfx/operations.h
    scummvm/trunk/engines/sci/gfx/resmgr.cpp
    scummvm/trunk/engines/sci/gfx/resource/sci_pal_1.cpp
    scummvm/trunk/engines/sci/gfx/resource/sci_pic_0.cpp
    scummvm/trunk/engines/sci/gfx/resource/sci_resmgr.cpp
    scummvm/trunk/engines/sci/gfx/resource/sci_view_0.cpp
    scummvm/trunk/engines/sci/gfx/resource/sci_view_1.cpp
    scummvm/trunk/engines/sci/gfx/sci_widgets.cpp
    scummvm/trunk/engines/sci/module.mk

Added Paths:
-----------
    scummvm/trunk/engines/sci/gfx/palette.cpp
    scummvm/trunk/engines/sci/gfx/palette.h

Modified: scummvm/trunk/engines/sci/engine/game.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/game.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/engine/game.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -101,28 +101,14 @@
 }
 
 static void _sci1_alloc_system_colors(EngineState *s) {
-	gfx_color_t white;
-	gfx_color_t black;
-
-	white.visual.global_index = 255;
-	white.visual.r = white.visual.g = white.visual.b = 255;
-	white.alpha = 0;
-	white.priority = white.control = 0;
-	white.mask = GFX_MASK_VISUAL;
-	gfxop_set_system_color(s->gfx_state, &white);
-
-	black.visual.global_index = 0;
-	black.visual.r = black.visual.g = black.visual.b = 0;
-	black.alpha = 0;
-	black.priority = black.control = 0;
-	black.mask = GFX_MASK_VISUAL;
-	gfxop_set_system_color(s->gfx_state, &black);
+	gfx_color_t black = { PaletteEntry(0, 0, 0), 0, 0, 0, GFX_MASK_VISUAL };
+	gfxop_set_system_color(s->gfx_state, 0, &black);
 }
 
 int _reset_graphics_input(EngineState *s) {
 	Resource *resource;
 	int font_nr;
-	gfx_color_t transparent = { { -1, 0, 0, 0 }, 0, -1, -1, 0 };
+	gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
 	sciprintf("Initializing graphics\n");
 
 	if (s->resmgr->_sciVersion <= SCI_VERSION_01) {
@@ -133,24 +119,28 @@
 					gfx_sci0_image_colors[sci0_palette][i].g, gfx_sci0_image_colors[sci0_palette][i].b, 0, -1, -1)) {
 				return 1;
 			}
-			gfxop_set_system_color(s->gfx_state, &(s->ega_colors[i]));
+			gfxop_set_system_color(s->gfx_state, i, &(s->ega_colors[i]));
 		}
 	} else {
 		// Check for Amiga palette file.
 		Common::File file;
 		if (file.open("spal")) {
-			s->gfx_state->resstate->static_palette = gfxr_read_pal1_amiga(&s->gfx_state->resstate->static_palette_entries, file);
+			if (s->gfx_state->resstate->static_palette)
+				s->gfx_state->resstate->static_palette->free();
+			s->gfx_state->resstate->static_palette = gfxr_read_pal1_amiga(file);
+			s->gfx_state->resstate->static_palette->name = "static palette";
 			file.close();
 			_sci1_alloc_system_colors(s);
 		} else {
 			resource = s->resmgr->findResource(kResourceTypePalette, 999, 1);
 			if (resource) {
+				if (s->gfx_state->resstate->static_palette)
+					s->gfx_state->resstate->static_palette->free();
 				if (s->version < SCI_VERSION(1, 001, 000))
-					s->gfx_state->resstate->static_palette = gfxr_read_pal1(999, &s->gfx_state->resstate->static_palette_entries,
-																			resource->data, resource->size);
+					s->gfx_state->resstate->static_palette = gfxr_read_pal1(999, resource->data, resource->size);
 				else
-					s->gfx_state->resstate->static_palette = gfxr_read_pal11(999, &s->gfx_state->resstate->static_palette_entries,
-																			resource->data, resource->size);
+					s->gfx_state->resstate->static_palette = gfxr_read_pal11(999, resource->data, resource->size);
+				s->gfx_state->resstate->static_palette->name = "static palette";
 				_sci1_alloc_system_colors(s);
 				s->resmgr->unlockResource(resource, 999, kResourceTypePalette);
 			} else {

Modified: scummvm/trunk/engines/sci/engine/kgraphics.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kgraphics.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/engine/kgraphics.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -264,24 +264,26 @@
 #define KERNEL_COLOR_PALETTE s->gfx_state->pic->visual_map->colors
 #define KERNEL_COLORS_NR s->gfx_state->pic->visual_map->colors_nr
 #else
-#define KERNEL_COLOR_PALETTE s->gfx_state->resstate->static_palette
-#define KERNEL_COLORS_NR s->gfx_state->resstate->static_palette_entries
+#define KERNEL_COLOR_PALETTE (s->gfx_state->resstate->static_palette)
+#define KERNEL_COLORS_NR (s->gfx_state->resstate->static_palette ? s->gfx_state->resstate->static_palette->size() : 0)
 #endif
 
-static gfx_pixmap_color_t white = {GFX_COLOR_INDEX_UNMAPPED, 255, 255, 255};
+//static gfx_pixmap_color_t white = {GFX_COLOR_INDEX_UNMAPPED, 255, 255, 255};
 
-gfx_pixmap_color_t *get_pic_color(EngineState *s, int color) {
+//PaletteEntry white(255, 255, 255);
+
+PaletteEntry get_pic_color(EngineState *s, int color) {
 	if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA)
-		return &(s->ega_colors[color].visual);
+		return s->ega_colors[color].visual;
 
 	if (color == 255)
-		return &white;
-	else if (color < KERNEL_COLORS_NR)
-		return &(KERNEL_COLOR_PALETTE[color]);
+		return PaletteEntry(255,255,255);
+	else if (color < (int)KERNEL_COLORS_NR)
+		return KERNEL_COLOR_PALETTE->getColor(color);
 	else {
 		SCIkwarn(SCIkERROR, "Color index %d out of bounds for pic %d (%d max)", color, s->gfx_state->pic_nr, KERNEL_COLORS_NR);
 		BREAKPOINT();
-		return NULL;
+		return PaletteEntry(0,0,0); 
 	}
 }
 
@@ -293,7 +295,7 @@
 		gfxop_set_color(s->gfx_state, &retval, (color < 0) ? -1 : retval.visual.r, retval.visual.g, retval.visual.b,
 		                (color == -1) ? 255 : 0, priority, control);
 	} else {
-		retval.visual = *(get_pic_color(s, color));
+		retval.visual = get_pic_color(s, color);
 		retval.alpha = 0;
 		retval.priority = priority;
 		retval.control = control;
@@ -1276,10 +1278,10 @@
 
 		int i, delta, bestindex = -1, bestdelta = 200000;
 
-		for (i = 0; i < KERNEL_COLORS_NR; i++) {
-			int dr = abs(KERNEL_COLOR_PALETTE[i].r - r);
-			int dg = abs(KERNEL_COLOR_PALETTE[i].g - g);
-			int db = abs(KERNEL_COLOR_PALETTE[i].b - b);
+		for (i = 0; i < (int)KERNEL_COLORS_NR; i++) {
+			int dr = abs(KERNEL_COLOR_PALETTE->getColor(i).r - r);
+			int dg = abs(KERNEL_COLOR_PALETTE->getColor(i).g - g);
+			int db = abs(KERNEL_COLOR_PALETTE->getColor(i).b - b);
 
 			delta = dr * dr + dg * dg + db * db;
 
@@ -2464,9 +2466,9 @@
 
 	if (SKPV_OR_ALT(8 + argextra, 255) >= 0) {
 		if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA)
-			bgcolor.visual = *(get_pic_color(s, SKPV_OR_ALT(8 + argextra, 15)));
+			bgcolor.visual = get_pic_color(s, SKPV_OR_ALT(8 + argextra, 15));
 		else
-			bgcolor.visual = *(get_pic_color(s, SKPV_OR_ALT(8 + argextra, 255)));
+			bgcolor.visual = get_pic_color(s, SKPV_OR_ALT(8 + argextra, 255));
 		bgcolor.mask = GFX_MASK_VISUAL;
 	}
 
@@ -2475,13 +2477,14 @@
 	bgcolor.alpha = 0;
 	SCIkdebug(SCIkGRAPHICS, "New window with params %d, %d, %d, %d\n", SKPV(0), SKPV(1), SKPV(2), SKPV(3));
 
-	fgcolor.visual = *(get_pic_color(s, SKPV_OR_ALT(7 + argextra, 0)));
+	fgcolor.visual = get_pic_color(s, SKPV_OR_ALT(7 + argextra, 0));
 	fgcolor.mask = GFX_MASK_VISUAL;
 	fgcolor.alpha = 0;
-	black.visual = *(get_pic_color(s, 0));
+	black.visual = get_pic_color(s, 0);
 	black.mask = GFX_MASK_VISUAL;
 	black.alpha = 0;
-	lWhite.visual = *(get_pic_color(s, s->resmgr->_sciVersion < SCI_VERSION_01_VGA ? 15 : 255)), lWhite.mask = GFX_MASK_VISUAL;
+	lWhite.visual = get_pic_color(s, s->resmgr->_sciVersion < SCI_VERSION_01_VGA ? 15 : 255);
+	lWhite.mask = GFX_MASK_VISUAL;
 	lWhite.alpha = 0;
 
 	window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->font_nr, fgcolor, bgcolor,
@@ -3083,7 +3086,7 @@
 	int index = UKPV_OR_ALT(1, 0);
 	int temp;
 	bool save_under = false;
-	gfx_color_t transparent = { { -1, 0, 0, 0 }, 0, -1, -1, 0 };
+	gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
 	char *text;
 	gfxw_port_t *port = (s->port) ? s->port : s->picture_port;
 	bool update_immediately = true;
@@ -3100,7 +3103,7 @@
 	// TODO: in SCI1VGA the default colors for text and background are #0 (black)
 	// SCI0 case should be checked 
 	if (s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) {
-		color0.visual = bg_color.visual = *get_pic_color(s, 0);
+		color0.visual = bg_color.visual = get_pic_color(s, 0);
 	}
 
 	if (textp.segment) {
@@ -3140,7 +3143,7 @@
 				color0 = (s->ega_colors[temp]);
 			else
 				if ((s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) && temp >= 0 && temp < 256) {
-					color0.visual = *(get_pic_color(s, temp));
+					color0.visual = get_pic_color(s, temp);
 					color0.mask = GFX_MASK_VISUAL;
 				} else
 					if (temp == -1)
@@ -3157,7 +3160,7 @@
 				bg_color = s->ega_colors[temp];
 			else
 				if ((s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) && temp >= 0 && temp <= 256) {
-					bg_color.visual = *get_pic_color(s, temp);
+					bg_color.visual = get_pic_color(s, temp);
 					bg_color.mask = GFX_MASK_VISUAL;
 				} else
 					if (temp == -1)

Modified: scummvm/trunk/engines/sci/engine/kmenu.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kmenu.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/engine/kmenu.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -68,9 +68,9 @@
 	int fgcolor = SKPV_OR_ALT(1, s->status_bar_foreground);
 	int bgcolor = SKPV_OR_ALT(2, s->status_bar_background);
 
-	s->titlebar_port->color.visual = *(get_pic_color(s, fgcolor));
+	s->titlebar_port->color.visual = get_pic_color(s, fgcolor);
 	s->titlebar_port->color.mask = GFX_MASK_VISUAL;
-	s->titlebar_port->bgcolor.visual = *(get_pic_color(s, bgcolor));
+	s->titlebar_port->bgcolor.visual = get_pic_color(s, bgcolor);
 	s->titlebar_port->bgcolor.mask = GFX_MASK_VISUAL;
 
 	s->status_bar_foreground = fgcolor;

Modified: scummvm/trunk/engines/sci/engine/kpathing.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kpathing.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/engine/kpathing.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -293,10 +293,7 @@
 	gfxw_list_t *decorations = s->picture_port->decorations;
 	gfxw_primitive_t *line;
 
-	col.visual.global_index = GFX_COLOR_INDEX_UNMAPPED;
-	col.visual.r = poly_colors[type][0];
-	col.visual.g = poly_colors[type][1];
-	col.visual.b = poly_colors[type][2];
+	col.visual = PaletteEntry(poly_colors[type][0], poly_colors[type][1], poly_colors[type][2]);
 	col.alpha = 0;
 	col.priority = -1;
 	col.control = 0;
@@ -318,10 +315,7 @@
 	gfxw_list_t *decorations = s->picture_port->decorations;
 	gfxw_box_t *box;
 
-	col.visual.global_index = GFX_COLOR_INDEX_UNMAPPED;
-	col.visual.r = point_colors[start][0];
-	col.visual.g = point_colors[start][1];
-	col.visual.b = point_colors[start][2];
+	col.visual = PaletteEntry(point_colors[start][0], point_colors[start][1], point_colors[start][2]);
 	col.alpha = 0;
 	col.priority = -1;
 	col.control = 0;

Modified: scummvm/trunk/engines/sci/engine/state.h
===================================================================
--- scummvm/trunk/engines/sci/engine/state.h	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/engine/state.h	2009-03-08 20:17:01 UTC (rev 39242)
@@ -310,7 +310,7 @@
 /* Read the header from a savegame
 */
 
-gfx_pixmap_color_t *get_pic_color(EngineState *s, int color);
+PaletteEntry get_pic_color(EngineState *s, int color);
 /* Retrieves the gfx_pixmap_color_t associated with a game color index
 ** Parameters: (EngineState *) s: The game state
 **             (int) color: The color to look up

Modified: scummvm/trunk/engines/sci/gfx/font.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/font.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/font.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -192,8 +192,7 @@
 	}
 }
 
-gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *stext, int characters,
-	gfx_pixmap_color_t *fg0, gfx_pixmap_color_t *fg1, gfx_pixmap_color_t *bg) {
+gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *stext, int characters, PaletteEntry *fg0, PaletteEntry *fg1, PaletteEntry *bg) {
 	unsigned char *text = (unsigned char *)stext;
 	int height = font->height;
 	int width = 0;
@@ -201,7 +200,7 @@
 	int fore_0, fore_1, back;
 	int i;
 	int hack = 0;
-	gfx_pixmap_color_t dummy = {0, 0, 0, 0};
+	PaletteEntry dummy(0,0,0); // black
 	byte *offset;
 
 	for (i = 0; i < characters; i++) {
@@ -217,35 +216,32 @@
 
 	pxm = gfx_pixmap_alloc_index_data(gfx_new_pixmap(width, height, GFX_RESID_NONE, 0, 0));
 
-	pxm->colors_nr = !!fg0 + !!fg1 + !!bg;
-	if (pxm->colors_nr == 0) {
+	int colors_nr = !!fg0 + !!fg1 + !!bg;
+	if (colors_nr == 0) {
 		GFXWARN("Pixmap would have zero colors, resetting!\n");
-		pxm->colors_nr = 3;
+		colors_nr = 3;
 		hack = 1;
 		fg0 = fg1 = bg = &dummy;
 	}
-	pxm->colors = (gfx_pixmap_color_t *)sci_malloc(sizeof(gfx_pixmap_color_t) * pxm->colors_nr);
-#ifdef SATISFY_PURIFY
-	memset(pxm->colors, 0, sizeof(gfx_pixmap_color_t) * pxm->colors_nr);
-#endif
-	pxm->flags |= GFX_PIXMAP_FLAG_PALETTE_ALLOCATED | GFX_PIXMAP_FLAG_DONT_UNALLOCATE_PALETTE;
+	pxm->palette = new Palette(colors_nr);
+	pxm->palette->name = "font";
 
 	i = 0;
 
 	if (fg0 || hack) {
-		memcpy(pxm->colors + i, fg0, sizeof(gfx_pixmap_color_t));
+		pxm->palette->setColor(i, fg0->r, fg0->g, fg0->b);
 		fore_0 = i++;
 	} else
 		fore_0 = pxm->color_key;
 
 	if (fg1 || hack) {
-		memcpy(pxm->colors + i, fg1, sizeof(gfx_pixmap_color_t));
+		pxm->palette->setColor(i, fg1->r, fg1->g, fg1->b);
 		fore_1 = i++;
 	} else
 		fore_1 = pxm->color_key;
 
 	if (bg || hack) {
-		memcpy(pxm->colors + i, bg, sizeof(gfx_pixmap_color_t));
+		pxm->palette->setColor(i, bg->r, bg->g, bg->b);
 		back = i++;
 	} else
 		back = pxm->color_key;

Modified: scummvm/trunk/engines/sci/gfx/font.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/font.h	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/font.h	2009-03-08 20:17:01 UTC (rev 39242)
@@ -109,7 +109,7 @@
 */
 
 gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *text, int characters,
-	gfx_pixmap_color_t *fg0, gfx_pixmap_color_t *fg1, gfx_pixmap_color_t *bg);
+	PaletteEntry *fg0, PaletteEntry *fg1, PaletteEntry *bg);
 /* Draws text in a specific font to a pixmap
 ** Parameters: (gfx_bitmap_font_t *) font: The font to use for drawing
 **             (char *) text: The start of the text to draw

Modified: scummvm/trunk/engines/sci/gfx/gfx_driver.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_driver.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_driver.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -38,6 +38,7 @@
 	byte *visual[2];
 	uint8 *pointer_data;
 	int xsize, ysize;
+	uint8 *palette_data;
 };
 
 #define S ((struct _scummvm_driver_state *)(drv->state))
@@ -75,8 +76,13 @@
 	}
 
 	Graphics::PixelFormat format = { bytespp, 0, 0, 0, 0, 0, 0, 0, 0 };
-	drv->mode = gfx_new_mode(xfact, yfact, format, 256, 0);
+	drv->mode = gfx_new_mode(xfact, yfact, format, new Palette(256), 0);
+	drv->mode->palette->name = "global";
 
+	S->palette_data = new uint8[4*256];
+	for (i = 0; i < 4*256; ++i)
+		S->palette_data[i] = 0;
+
 	return GFX_OK;
 }
 
@@ -100,6 +106,9 @@
 		delete[] S->pointer_data;
 		S->pointer_data = NULL;
 
+		delete[] S->palette_data;
+		S->palette_data = NULL;
+
 		delete S;
 	}
 }
@@ -115,7 +124,7 @@
 
 static int scummvm_draw_line(gfx_driver_t *drv, Common::Point start, Common::Point end,
 	gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style) {
-	uint32 scolor = color.visual.global_index;
+	uint32 scolor = color.visual.parent_index;
 	int xfact = (line_mode == GFX_LINE_MODE_FINE)? 1: drv->mode->xfact;
 	int yfact = (line_mode == GFX_LINE_MODE_FINE)? 1: drv->mode->yfact;
 	int xsize = S->xsize;
@@ -148,7 +157,7 @@
 	gfx_rectangle_fill_t shade_mode) {
 	if (color1.mask & GFX_MASK_VISUAL) {
 		for (int i = rect.y; i < rect.y + rect.yl; i++) {
-			memset(S->visual[0] + i * S->xsize + rect.x, color1.visual.global_index, rect.xl);
+			memset(S->visual[0] + i * S->xsize + rect.x, color1.visual.parent_index, rect.xl);
 		}
 	}
 
@@ -267,7 +276,7 @@
 		for (int xc = 0; xc < pointer->index_xl; xc++) {
 			uint8 color = *src;
 			if (color != 255)
-				color = pointer->colors[color].global_index;
+				color = pointer->palette->getColor(color).parent_index;
 			for (int scalectr = 0; scalectr < drv->mode->xfact; scalectr++) {
 				*pos++ = color;
 			}
@@ -302,13 +311,20 @@
 		return GFX_ERROR;
 	}
 
-	byte color[] = {red, green, blue, 255};
-	g_system->setPalette(color, index, 1);
+	S->palette_data[4*index+0] = red;
+	S->palette_data[4*index+1] = green;
+	S->palette_data[4*index+2] = blue;
+	S->palette_data[4*index+3] = 255;
 
 	return GFX_OK;
 }
 
+static int scummvm_install_palette(gfx_driver_t *drv, Palette* palette) {
+	g_system->setPalette(S->palette_data, 0, palette->size());
+	return GFX_OK;
+}
 
+
 gfx_driver_t gfx_driver_scummvm = {
 	NULL,
 	0, 0,
@@ -326,6 +342,7 @@
 	scummvm_set_static_buffer,
 	scummvm_set_pointer,
 	scummvm_set_palette,
+	scummvm_install_palette,
 	NULL
 };
 

Modified: scummvm/trunk/engines/sci/gfx/gfx_driver.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_driver.h	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_driver.h	2009-03-08 20:17:01 UTC (rev 39242)
@@ -281,7 +281,9 @@
 
 	int (*set_palette)(gfx_driver_t *drv, int index, byte red, byte green,
 	                   byte blue);
-	/* Manipulates a palette index in the hardware palette
+	/* Manipulates a palette index in the hardware palette.
+	** The actual update is not performed until install_palette() is called.
+	** This way updates can be batched.
 	** Parameters: (gfx_driver_t *) drv: The driver affected
 	**             (int) index: The index of the palette entry to modify
 	**             (int x int x int) red, green, blue: The RGB intensities to
@@ -293,6 +295,8 @@
 	** set_palette() is only required for targets supporting color index mode.
 	*/
 
+	int (*install_palette)(gfx_driver_t *drv, Palette* pal);
+	/* As set_palette, but for the full palette. */
 
 	void *state; /* Reserved for internal use */
 

Modified: scummvm/trunk/engines/sci/gfx/gfx_pixmap_scale.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_pixmap_scale.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_pixmap_scale.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -66,15 +66,16 @@
 		alpha_dest = pxm->alpha_map = (byte *)sci_malloc(pxm->index_xl * xfact * pxm->index_yl * yfact);
 
 	// Calculate all colors
-	for (i = 0; i < pxm->colors_nr; i++) {
+	for (i = 0; i < pxm->colors_nr(); i++) {
 		int col;
 
+		const PaletteEntry& color = pxm->palette->getColor(i);
 		if (PALETTE_MODE)
-			col = pxm->colors[i].global_index;
+			col = color.parent_index;
 		else {
-			col = mode->red_mask & ((EXTEND_COLOR(pxm->colors[i].r)) >> mode->red_shift);
-			col |= mode->green_mask & ((EXTEND_COLOR(pxm->colors[i].g)) >> mode->green_shift);
-			col |= mode->blue_mask & ((EXTEND_COLOR(pxm->colors[i].b)) >> mode->blue_shift);
+			col = mode->red_mask & ((EXTEND_COLOR(color.r)) >> mode->red_shift);
+			col |= mode->green_mask & ((EXTEND_COLOR(color.g)) >> mode->green_shift);
+			col |= mode->blue_mask & ((EXTEND_COLOR(color.b)) >> mode->blue_shift);
 			col |= alpha_ormask;
 		}
 		result_colors[i] = col;
@@ -247,9 +248,10 @@
 				rec[2] = other[2] - ctexel[2]; \
 				rec[3] = 0xffff - ctexel[3]; \
 			} else { \
-				rec[0] = (EXTEND_COLOR(pxm->colors[nr].r) >> 16) - ctexel[0]; \
-				rec[1] = (EXTEND_COLOR(pxm->colors[nr].g) >> 16) - ctexel[1]; \
-				rec[2] = (EXTEND_COLOR(pxm->colors[nr].b) >> 16) - ctexel[2]; \
+				const PaletteEntry& e = (*pxm->palette)[nr]; \
+				rec[0] = (EXTEND_COLOR(e.r) >> 16) - ctexel[0]; \
+				rec[1] = (EXTEND_COLOR(e.g) >> 16) - ctexel[1]; \
+				rec[2] = (EXTEND_COLOR(e.b) >> 16) - ctexel[2]; \
 				rec[3] = 0 - ctexel[3]; \
 			}
 
@@ -326,9 +328,10 @@
 				rec[2] = 0; \
 				rec[3] = 0xffffff; \
 			} else { \
-				rec[0] = (EXTEND_COLOR(pxm->colors[nr].r) >> 8); \
-				rec[1] = (EXTEND_COLOR(pxm->colors[nr].g) >> 8); \
-				rec[2] = (EXTEND_COLOR(pxm->colors[nr].b) >> 8); \
+				const PaletteEntry& e = (*pxm->palette)[nr]; \
+				rec[0] = (EXTEND_COLOR(e.r) >> 8); \
+				rec[1] = (EXTEND_COLOR(e.g) >> 8); \
+				rec[2] = (EXTEND_COLOR(e.b) >> 8); \
 				rec[3] = 0; \
 			}
 

Modified: scummvm/trunk/engines/sci/gfx/gfx_res_options.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_res_options.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_res_options.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -115,29 +115,22 @@
 }
 
 void apply_assign(gfx_res_assign_t *conf, gfx_pixmap_t *pxm) {
-	// Has a dynamically allocated palette? Must clean up
-	if (!(pxm->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE)) {
-		if (pxm->colors)
-			free(pxm->colors);
-		pxm->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
-	}
+	if (pxm->palette)
+		pxm->palette->free();
 
-	pxm->colors_nr = conf->assign.palette.colors_nr;
-	pxm->colors = conf->assign.palette.colors;
+	pxm->palette = new Palette(conf->assign.palette.colors, conf->assign.palette.colors_nr);
+	pxm->palette->name = "res";
 }
 
 void apply_mod(gfx_res_mod_t *mod, gfx_pixmap_t *pxm) {
-	gfx_pixmap_color_t *pal = pxm->colors;
-	int i, pal_size = pxm->colors_nr;
+	Palette *pal = pxm->palette;
+	int i, pal_size = pal ? pal->size() : 0;
 
 	// Does not have a dynamically allocated palette? Must dup current one
-	if (pxm->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE) {
-		int size = sizeof(gfx_pixmap_color_t) * pal_size;
-		pxm->colors = (gfx_pixmap_color_t*)sci_malloc(size);
-		memcpy(pxm->colors, pal, size);
-		pal = pxm->colors;
-		pxm->flags &= ~GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
-		// Flag for later deallocation
+	if (pal && pal->isShared()) {
+		pal = pxm->palette->copy();
+		pxm->palette->free();
+		pxm->palette = pal;
 	}
 
 	switch (mod->type) {
@@ -147,14 +140,17 @@
 			int v;
 
 #define UPDATE_COL(nm, idx)                        \
-		v = pal[i].nm;             \
+		v = nm;             \
 		v *= mod->mod.factor[idx]; \
 		v >>= 4;                   \
-		pal[i].nm = (v > 255)? 255 : v;
+		nm = (v > 255)? 255 : v;
 
-			UPDATE_COL(r, 0);
-			UPDATE_COL(g, 1);
-			UPDATE_COL(b, 2);
+			PaletteEntry c = pal->getColor(i);
+			UPDATE_COL(c.r, 0);
+			UPDATE_COL(c.g, 1);
+			UPDATE_COL(c.b, 2);
+			pal->setColor(i, c.r, c.g, c.b);
+			
 #undef UPDATE_COL
 		}
 		break;

Modified: scummvm/trunk/engines/sci/gfx/gfx_resmgr.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_resmgr.h	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_resmgr.h	2009-03-08 20:17:01 UTC (rev 39242)
@@ -83,8 +83,7 @@
 	int version; /* Interpreter version */
 	gfx_options_t *options;
 	gfx_driver_t *driver;
-	gfx_pixmap_color_t *static_palette;
-	int static_palette_entries;
+	Palette *static_palette;
 	int lock_counter; /* Global lock counter; increased for each new resource allocated.
 			  ** The newly allocated resource will then be assigned the new value
 			  ** of the lock_counter, as will any resources referenced afterwards.
@@ -309,7 +308,7 @@
 ** Returns   : (gfx_pixmap_t *) The cursor pixmap, or NULL on error
 */
 
-gfx_pixmap_color_t *gfxr_interpreter_get_static_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal);
+Palette *gfxr_interpreter_get_static_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal);
 /* Retreives the static palette from the interpreter-specific code
 ** Parameters: (int) version: Interpreter version to use
 **             (int *) colors_nr: Number of colors to use
@@ -318,7 +317,7 @@
 **             if a static palette must be used, NULL otherwise
 */
 
-gfx_pixmap_color_t *gfxr_interpreter_get_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal, int nr);
+Palette *gfxr_interpreter_get_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal, int nr);
 /* Retreives the static palette from the interpreter-specific code
 ** Parameters: (int) version: Interpreter version to use
 **             (int *) colors_nr: Number of colors to use

Modified: scummvm/trunk/engines/sci/gfx/gfx_resource.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_resource.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_resource.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -55,8 +55,8 @@
 void gfxr_free_view(gfx_driver_t *driver, gfxr_view_t *view) {
 	int i;
 
-	if (view->colors && !(view->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE))
-		free(view->colors);
+	if (view->palette)
+		view->palette->free();
 
 	if (view->loops) {
 		for (i = 0; i < view->loops_nr; i++)
@@ -352,21 +352,9 @@
 void gfx_xlate_pixmap(gfx_pixmap_t *pxm, gfx_mode_t *mode, gfx_xlate_filter_t filter) {
 	int was_allocated = 0;
 
-	if (mode->palette && !(pxm->flags & GFX_PIXMAP_FLAG_PALETTE_ALLOCATED)) {
-		int i;
-
-		for (i = 0; i < pxm->colors_nr; i++) {
-			if (gfx_alloc_color(mode->palette, pxm->colors + i) < 0) {
-				GFXWARN("Failed to allocate color %d/%d in pixmap (color %02x/%02x/%02x)!\n",
-				        i, pxm->colors_nr, pxm->colors[i].r, pxm->colors[i].g, pxm->colors[i].b);
-				pxm->colors[i].global_index = 0;
-			}
-			/*
-			GFXDEBUG("alloc(%02x/%02x/%02x) -> %d\n", pxm->colors[i].r, pxm->colors[i].g, pxm->colors[i].b, pxm->colors[i].global_index);
-			*/
-		}
-
-		pxm->flags |= GFX_PIXMAP_FLAG_PALETTE_ALLOCATED;
+	if (mode->palette) {
+		if (pxm->palette && pxm->palette != mode->palette)
+			pxm->palette->mergeInto(mode->palette);
 	}
 
 
@@ -376,7 +364,7 @@
 		// Assume that memory, if allocated already, will be sufficient
 
 		// Allocate alpha map
-		if (!mode->alpha_mask && pxm->colors_nr < GFX_PIC_COLORS)
+		if (!mode->alpha_mask && pxm->colors_nr() < GFX_PIC_COLORS)
 			pxm->alpha_map = (byte*)sci_malloc(mode->xfact * mode->yfact * pxm->index_xl * pxm->index_yl + 1);
 	} else
 		was_allocated = 1;
@@ -398,7 +386,7 @@
 		GFXERROR("Attempt to filter pixmap %04x in invalid mode #%d\n", pxm->ID, filter);
 
 		if (!was_allocated) {
-			if (!mode->alpha_mask && pxm->colors_nr < GFX_PIC_COLORS)
+			if (!mode->alpha_mask && pxm->colors_nr() < GFX_PIC_COLORS)
 				free(pxm->alpha_map);
 			free(pxm->data);
 		}

Modified: scummvm/trunk/engines/sci/gfx/gfx_resource.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_resource.h	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_resource.h	2009-03-08 20:17:01 UTC (rev 39242)
@@ -62,12 +62,13 @@
 extern int sci0_palette;
 
 /* (gfx_pic_0.c) The 16 EGA base colors */
+extern Palette* gfx_sci0_image_pal[];
 extern gfx_pixmap_color_t gfx_sci0_image_colors[][16];
 
 /* (gfx_pic_0.c) The 256 interpolated colors (initialized when
 ** gfxr_init_pic() is called for the first time, or when gfxr_init_static_palette() is called)
 */
-extern gfx_pixmap_color_t gfx_sci0_pic_colors[];
+extern Palette* gfx_sci0_pic_colors;
 
 
 struct gfxr_pic0_params_t {
@@ -113,8 +114,7 @@
 	int ID;
 
 	int flags;
-	int colors_nr;
-	gfx_pixmap_color_t *colors;
+	Palette *palette;
 
 	int loops_nr;
 	gfxr_loop_t *loops;
@@ -176,7 +176,7 @@
 
 void gfxr_draw_pic01(gfxr_pic_t *pic, int fill_normally, int default_palette,
 	int size, byte *resource, gfxr_pic0_params_t *style, int resid, int sci1,
-	gfx_pixmap_color_t *static_pal, int static_pal_nr);
+	Palette *static_pal);
 /* Draws a pic resource (all formats prior to SCI1.1)
 ** Parameters: (gfxr_pic_t *) pic: The pic to draw to
 **             (int) fill_normally: If 1, the pic is drawn normally; if 0, all
@@ -197,7 +197,7 @@
 
 void gfxr_draw_pic11(gfxr_pic_t *pic, int fill_normally, int default_palette,
 	int size, byte *resource, gfxr_pic0_params_t *style, int resid,
-	gfx_pixmap_color_t *static_pal, int static_pal_nr);
+	Palette *static_pal);
 /* Draws a pic resource (SCI1.1)
 ** Parameters: (gfxr_pic_t *) pic: The pic to draw to
 **             (int) fill_normally: If 1, the pic is drawn normally; if 0, all
@@ -246,7 +246,7 @@
 /*  SCI1 operations  */
 /*********************/
 
-gfx_pixmap_color_t *gfxr_read_pal1(int id, int *colors_nr, byte *resource, int size);
+Palette *gfxr_read_pal1(int id, byte *resource, int size);
 /* Reads an SCI1 palette
 ** Parameters: (int) id: Resource ID for the palette (or the view it was found in)
 **             (int *) colors_nr: Pointer to the variable the number of colors
@@ -256,7 +256,7 @@
 ** Returns   : (gfx_pixmap_color_t *) *colors_nr color_t entries with the colors
 */
 
-gfx_pixmap_color_t *gfxr_read_pal1_amiga(int *colors_nr, Common::File &file);
+Palette *gfxr_read_pal1_amiga(Common::File &file);
 /* Reads an SCI1 palette
 ** Parameters: (int *) colors_nr: Pointer to the variable the number of colors
 **                                will be stored in
@@ -264,7 +264,7 @@
 ** Returns   : (gfx_pixmap_color_t *) *colors_nr color_t entries with the colors
 */
 
-gfx_pixmap_color_t *gfxr_read_pal11(int id, int *colors_nr, byte *resource, int size);
+Palette *gfxr_read_pal11(int id, byte *resource, int size);
 /* Reads an SCI1.1 palette
 ** Parameters: (int) id: Resource ID for the palette (or the view it was found in)
 **             (int *) colors_nr: Pointer to the variable the number of colors
@@ -274,8 +274,7 @@
 ** Returns   : (gfx_pixmap_color_t *) *colors_nr color_t entries with the colors
 */
 
-gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, gfx_pixmap_color_t *static_pal,
-	int static_pal_nr);
+gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, Palette *static_pal);
 /* Calculates an SCI1 view
 ** Parameters: (int) id: Resource ID of the view
 **             (byte *) resource: Pointer to the resource to read

Modified: scummvm/trunk/engines/sci/gfx/gfx_system.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_system.h	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_system.h	2009-03-08 20:17:01 UTC (rev 39242)
@@ -30,6 +30,7 @@
 #include "common/rect.h"
 #include "sci/sci_memory.h"
 #include "sci/tools.h"
+#include "sci/gfx/palette.h"
 
 namespace Sci {
 
@@ -50,26 +51,6 @@
 
 #define GFX_COLOR_SYSTEM -1
 
-
-/** Palette color description */
-struct gfx_palette_color_t {
-
-	int lockers; /* Number of pixmaps holding a lock on that color.
-		     ** 0 means that the color is unused, -1 means that it is
-		     ** "system allocated" and may not be freed.  */
-	byte r, g, b; /* Red, green, blue; intensity varies from 0 (min) to 255 (max) */
-
-};
-
-/** Palette description for color index modes */
-struct gfx_palette_t{
-
-	int max_colors_nr; /* Maximum number of allocated colors */
-	gfx_palette_color_t *colors; /* Actual colors, malloc()d as a block */
-};
-
-
-
 #define GFX_MODE_IS_UNSCALED(mode) (((mode)->xfact == 1) && ((mode)->yfact == 1))
 
 /* Reverse-endian: Target display has non-native endianness
@@ -88,9 +69,8 @@
 	uint32 flags; /* GFX_MODE_FLAG_* Flags- see above */
 
 
-	gfx_palette_t *palette; /* Palette or NULL to indicate non-palette mode.
-				** Palette (color-index) mode is only supported
-				** for bytespp=1.  */
+	Palette *palette; // Palette or NULL to indicate non-palette mode.
+	                  // Palette mode is only supported for bytespp = 1
 
 	/* Color masks */
 	uint32 red_mask, green_mask, blue_mask, alpha_mask;
@@ -119,7 +99,7 @@
 
 /** Full color */
 struct gfx_color_t {
-	gfx_pixmap_color_t visual;
+	PaletteEntry visual;
 	uint8 alpha; /* transparency = (1-opacity) */
 	int8 priority, control;
 	byte mask; /* see mask values below */
@@ -232,11 +212,7 @@
 #define GFX_PIC_COLORS 256
 
 #define GFX_PIXMAP_FLAG_SCALED_INDEX      (1<<0) /* Index data is scaled already */
-#define GFX_PIXMAP_FLAG_EXTERNAL_PALETTE  (1<<1) /* The colors pointer points to an external palette */
 #define GFX_PIXMAP_FLAG_INSTALLED         (1<<2) /* Pixmap has been registered */
-#define GFX_PIXMAP_FLAG_PALETTE_ALLOCATED (1<<3) /* Palette has been allocated */
-#define GFX_PIXMAP_FLAG_PALETTE_SET       (1<<4) /* Palette has been propagated to the driver */
-#define GFX_PIXMAP_FLAG_DONT_UNALLOCATE_PALETTE (1<<5) /* Used by text, which uses preallocated colors */
 #define GFX_PIXMAP_FLAG_PALETTIZED	  (1<<6) /* Indicates a palettized view */
 
 #define GFX_PIXMAP_COLOR_KEY_NONE -1 /* No transpacency colour key */
@@ -249,8 +225,9 @@
 
 
 	/*** Color map ***/
-	int colors_nr;
-	gfx_pixmap_color_t *colors; /* colors_nr color entries, or NULL if the
+	Palette *palette;
+	int colors_nr() const { return palette ? palette->size() : 0; }
+				    /* color entries, or NULL if the
 				    ** default palette is to be used.
 				    ** A maximum of 255 colors is allowed; color
 				    ** index 0xff is reserved for transparency.
@@ -294,10 +271,6 @@
 /*** Constant values ***/
 /***********************/
 
-/* Default palettes */
-extern gfx_pixmap_color_t gfx_sci0_image_colors[][16];
-extern gfx_pixmap_color_t gfx_sci0_pic_colors[256];
-
 /* Return values */
 enum gfx_return_value_t {
 	GFX_OK = 0, /* Indicates "operation successful" */

Modified: scummvm/trunk/engines/sci/gfx/gfx_tools.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_tools.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_tools.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -44,7 +44,7 @@
 		box->yl = maxy - box->y + 1;
 }
 
-gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, int palette, int flags) {
+gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, Palette *palette, int flags) {
 	gfx_mode_t *mode = (gfx_mode_t *)sci_malloc(sizeof(gfx_mode_t));
 
 	mode->xfact = xfact;
@@ -72,22 +72,14 @@
 		mode->alpha_shift = 0;
 	}
 	mode->flags = flags;
+	mode->palette = palette;
 
-	if (palette) {
-		mode->palette = (gfx_palette_t *)sci_malloc(sizeof(gfx_palette_t));
-		mode->palette->max_colors_nr = palette;
-		mode->palette->colors = (gfx_palette_color_t *)sci_calloc(sizeof(gfx_palette_color_t), palette); // Initialize with empty entries
-	} else
-		mode->palette = NULL;
-
 	return mode;
 }
 
 void gfx_free_mode(gfx_mode_t *mode) {
-	if (mode->palette) {
-		free(mode->palette->colors);
-		free(mode->palette);
-	}
+	if (mode->palette)
+		mode->palette->free();
 	free(mode);
 }
 
@@ -118,7 +110,7 @@
 	gfx_pixmap_t *clone = (gfx_pixmap_t *)sci_malloc(sizeof(gfx_pixmap_t));
 	*clone = *pxm;
 	clone->index_data = NULL;
-	clone->colors = NULL;
+	clone->palette = NULL;
 	clone->data = NULL;
 	gfx_pixmap_alloc_data(clone, mode);
 
@@ -137,7 +129,7 @@
 	pxm->alpha_map = NULL;
 	pxm->data = NULL;
 	pxm->internal.info = NULL;
-	pxm->colors = NULL;
+	pxm->palette = NULL;
 	pxm->internal.handle = 0;
 
 	pxm->index_xl = xl;
@@ -158,35 +150,15 @@
 
 void gfx_free_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm) {
 	if (driver) {
-		if (driver->mode->palette && pxm->flags & GFX_PIXMAP_FLAG_PALETTE_ALLOCATED
-		        && !(pxm->flags & GFX_PIXMAP_FLAG_DONT_UNALLOCATE_PALETTE) && !(pxm->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE)) {
-			int i;
-			int error = 0;
-
-			GFXDEBUG("UNALLOCATING %d\n", pxm->colors_nr);
-			for (i = 0; i < pxm->colors_nr; i++)
-				if (gfx_free_color(driver->mode->palette, pxm->colors + i))
-					error++;
-
-			if (error) {
-				GFXWARN("%d errors occured while freeing %d colors of pixmap with ID %06x/%d/%d\n",
-				        error, pxm->colors_nr, pxm->ID, pxm->loop, pxm->cel);
-			}
+		if (driver->mode->palette) {
+			if (pxm->palette)
+				pxm->palette->free();
 		}
 	}
 
-	if (pxm->index_data)
-		free(pxm->index_data);
-
-	if (pxm->alpha_map)
-		free(pxm->alpha_map);
-
-	if (pxm->data)
-		free(pxm->data);
-
-	if (pxm->colors && !(pxm->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE))
-		free(pxm->colors);
-
+	free(pxm->index_data);
+	free(pxm->alpha_map);
+	free(pxm->data);
 	free(pxm);
 }
 
@@ -256,105 +228,6 @@
 	return pixmap;
 }
 
-int gfx_alloc_color(gfx_palette_t *pal, gfx_pixmap_color_t *color) {
-	int i;
-	int dr, dg, db;
-	int bestdelta = 1 + ((0x100 * 0x100) * 3);
-	int bestcolor = -1;
-	int firstfree = -1;
-
-	if (pal == NULL)
-		return GFX_OK;
-
-	if (pal->max_colors_nr <= 0) {
-		GFXERROR("Palette has zero or less color entries!\n");
-		return GFX_ERROR;
-	}
-
-
-	if (color->global_index != GFX_COLOR_INDEX_UNMAPPED) {
-#if 0
-		GFXDEBUG("Attempt to allocate color twice: index 0x%d (%02x/%02x/%02x)!\n",
-		         color->global_index, color->r, color->g, color->b);
-#endif
-		return GFX_OK;
-	}
-
-	for (i = 0; i < pal->max_colors_nr; i++) {
-		gfx_palette_color_t *pal_color = pal->colors + i;
-
-		if (pal_color->lockers) {
-			int delta;
-
-			dr = abs(pal_color->r - color->r);
-			dg = abs(pal_color->g - color->g);
-			db = abs(pal_color->b - color->b);
-
-			if (dr == 0 && dg == 0 && db == 0) {
-				color->global_index = i;
-				if (pal->colors[i].lockers != GFX_COLOR_SYSTEM)
-					pal->colors[i].lockers++;
-				return GFX_OK;
-			}
-
-			delta = (dr * dr) + (dg * dg) + (db * db);
-			if (delta < bestdelta) {
-				bestdelta = delta;
-				bestcolor = i;
-			}
-		} else
-			if (firstfree == -1)
-				firstfree = i;
-	}
-
-	if (firstfree != -1) {
-		pal->colors[firstfree].r = color->r;
-		pal->colors[firstfree].g = color->g;
-		pal->colors[firstfree].b = color->b;
-		pal->colors[firstfree].lockers = 1;
-		color->global_index = firstfree;
-
-		return 42; // positive value to indicate that this color still needs to be set
-	}
-
-	color->global_index = bestcolor;
-	if (pal->colors[bestcolor].lockers != GFX_COLOR_SYSTEM)
-		pal->colors[bestcolor].lockers++;
-
-	//GFXWARN("Out of palette colors- doing approximated mapping");
-	return GFX_OK;
-}
-
-int gfx_free_color(gfx_palette_t *pal, gfx_pixmap_color_t *color) {
-	gfx_palette_color_t *palette_color = pal->colors + color->global_index;
-
-	if (!pal)
-		return GFX_OK;
-
-	if (color->global_index == GFX_COLOR_INDEX_UNMAPPED) {
-		GFXWARN("Attempt to free unmapped color %02x/%02x/%02x!\n", color->r, color->g, color->b);
-		BREAKPOINT();
-		return GFX_ERROR;
-	}
-
-	if (color->global_index >= pal->max_colors_nr) {
-		GFXERROR("Attempt to free invalid color index %d (%02x/%02x/%02x)\n", color->global_index, color->r, color->g, color->b);
-		return GFX_ERROR;
-	}
-
-	if (!palette_color->lockers) {
-		GFXERROR("Attempt to free unused color index %d (%02x/%02x/%02x)\n", color->global_index, color->r, color->g, color->b);
-		return GFX_ERROR;
-	}
-
-	if (palette_color->lockers != GFX_COLOR_SYSTEM)
-		--(palette_color->lockers);
-
-	color->global_index = GFX_COLOR_INDEX_UNMAPPED;
-
-	return GFX_OK;
-}
-
 gfx_pixmap_t *gfx_pixmap_scale_index_data(gfx_pixmap_t *pixmap, gfx_mode_t *mode) {
 	byte *old_data, *new_data, *initial_new_data;
 	byte *linestart;

Modified: scummvm/trunk/engines/sci/gfx/gfx_tools.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_tools.h	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_tools.h	2009-03-08 20:17:01 UTC (rev 39242)
@@ -47,7 +47,7 @@
 					  ** for distinguishing between transparent and opaque
 					  ** wrt alpha values */
 
-gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, int palette, int flags);
+gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, Palette *palette, int flags);
 /* Allocates a new gfx_mode_t structure with the specified parameters
 ** Parameters: (int x int) xfact x yfact: Horizontal and vertical scaling factors
 **             (Graphics::PixelFormat) format: pixel format description
@@ -191,7 +191,7 @@
 ** linear access.
 */
 
-int gfx_alloc_color(gfx_palette_t *pal, gfx_pixmap_color_t *color);
+//int gfx_alloc_color(gfx_palette_t *pal, gfx_pixmap_color_t *color);
 /* Allocates a color entry for the specified pixmap color
 ** Parameters: (gfx_palette_t *) pal: The palette structure the color should be allocated in
 **             (gfx_pixmap_color_t *) color: The color to allocate
@@ -200,7 +200,7 @@
 **                   palette.
 */
 
-int gfx_free_color(gfx_palette_t *pal, gfx_pixmap_color_t *color);
+//int gfx_free_color(gfx_palette_t *pal, gfx_pixmap_color_t *color);
 /* Frees the color entry allocated for the specified pixmap color
 ** Parameters: (gfx_palette_t *) pal: The palette structure the color was previously allocated in
 **             (gfx_pixmap_color_t *) color: The color to free

Modified: scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -867,10 +867,7 @@
 	widget->color.priority = priority;
 	widget->color.control = control;
 	widget->color.alpha = 0;
-	widget->color.visual.global_index = 0;
-	widget->color.visual.r = 0;
-	widget->color.visual.g = 0;
-	widget->color.visual.b = 0;
+	widget->color.visual = PaletteEntry(0,0,0); // FIXME: black!
 	widget->view = view;
 	widget->loop = loop;
 	widget->cel = cel;
@@ -2042,7 +2039,7 @@
 
 gfxw_port_t *gfxw_get_chrono_port(gfxw_visual_t *visual, gfxw_list_t **temp_widgets_list, int flags) {
 	gfxw_port_t *result = NULL;
-	gfx_color_t transparent = {{-1, 0, 0, 01}, 0, -1, -1, 0};
+	gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0};
 	int id = 0;
 
 	if (!(flags & GFXW_CHRONO_NON_TOPMOST)) {

Modified: scummvm/trunk/engines/sci/gfx/operations.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/operations.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/operations.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -96,29 +96,6 @@
 	point->y *= yfact;
 }
 
-static void _gfxop_alloc_colors(gfx_state_t *state, gfx_pixmap_color_t *colors, int colors_nr) {
-	int i;
-
-	if (!PALETTE_MODE)
-		return;
-
-	for (i = 0; i < colors_nr; i++)
-		gfx_alloc_color(state->driver->mode->palette, colors + i);
-}
-
-#if 0
-// Unreferenced - removed
-static void _gfxop_free_colors(gfx_state_t *state, gfx_pixmap_color_t *colors, int colors_nr) {
-	int i;
-
-	if (!PALETTE_MODE)
-		return;
-
-	for (i = 0; i < colors_nr; i++)
-		gfx_free_color(state->driver->mode->palette, colors + i);
-}
-#endif
-
 int _gfxop_clip(rect_t *rect, rect_t clipzone) {
 // Returns 1 if nothing is left */
 #if 0
@@ -225,25 +202,22 @@
 #undef DRAW_LOOP
 
 static int _gfxop_install_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm) {
-	int error;
+	if (!driver->mode->palette) return GFX_OK;
+	if (!pxm->palette) return GFX_OK;
+	
+	assert(pxm->palette->getParent() == driver->mode->palette);
 
-	if (driver->mode->palette && (!(pxm->flags & GFX_PIXMAP_FLAG_PALETTE_SET))) {
-		int i;
+	if (!driver->mode->palette->isDirty()) return GFX_OK;
 
-		for (i = 0; i < pxm->colors_nr; i++) {
-			if ((error = driver->set_palette(driver, pxm->colors[i].global_index, pxm->colors[i].r,
-			                                 pxm->colors[i].g, pxm->colors[i].b))) {
-
-				GFXWARN("driver->set_palette(%d, %02x/%02x/%02x) failed!\n",
-				        pxm->colors[i].global_index, pxm->colors[i].r, pxm->colors[i].g, pxm->colors[i].b);
-
-				if (error == GFX_FATAL)
-					return GFX_FATAL;
-			}
-		}
-
-		pxm->flags |= GFX_PIXMAP_FLAG_PALETTE_SET;
+	// TODO: We probably want to only update the colours used by this pixmap
+	// here. This will require updating the 'dirty' system.
+	for (unsigned int i = 0; i < driver->mode->palette->size(); ++i) {
+		const PaletteEntry& c = (*driver->mode->palette)[i];
+		driver->set_palette(driver, i, c.r, c.g, c.b);
 	}
+
+	driver->install_palette(driver, driver->mode->palette);
+	driver->mode->palette->markClean();
 	return GFX_OK;
 }
 
@@ -438,12 +412,13 @@
 
 static void init_aux_pixmap(gfx_pixmap_t **pixmap) {
 	*pixmap = gfx_pixmap_alloc_index_data(gfx_new_pixmap(320, 200, GFX_RESID_NONE, 0, 0));
-	(*pixmap)->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
-	(*pixmap)->colors_nr = DEFAULT_COLORS_NR;
-	(*pixmap)->colors = default_colors;
+	//  FIXME: don't duplicate this palette for every aux_pixmap
+	(*pixmap)->palette = new Palette(default_colors, DEFAULT_COLORS_NR);
 }
 
 static int _gfxop_init_common(gfx_state_t *state, gfx_options_t *options, void *misc_payload) {
+	gfxr_init_static_palette();
+
 	state->options = options;
 
 	if (!((state->resstate = gfxr_new_resource_manager(state->version, state->options, state->driver, misc_payload)))) {
@@ -451,9 +426,8 @@
 		return GFX_FATAL;
 	}
 
-	if ((state->static_palette = gfxr_interpreter_get_static_palette(state->resstate, state->version,
-	                                                &(state->static_palette_entries), misc_payload)))
-		_gfxop_alloc_colors(state, state->static_palette, state->static_palette_entries);
+	int size;
+	state->static_palette = gfxr_interpreter_get_static_palette(state->resstate, state->version, &size, misc_payload);
 
 	state->visible_map = GFX_MASK_VISUAL;
 	state->fullscreen_override = NULL; // No magical override
@@ -622,8 +596,6 @@
 }
 
 int gfxop_set_color(gfx_state_t *state, gfx_color_t *color, int r, int g, int b, int a, int priority, int control) {
-	gfx_pixmap_color_t pixmap_color = {0, 0, 0, 0};
-	int error_code;
 	int mask = ((r >= 0 && g >= 0 && b >= 0) ? GFX_MASK_VISUAL : 0) | ((priority >= 0) ? GFX_MASK_PRIORITY : 0)
 	           | ((control >= 0) ? GFX_MASK_CONTROL : 0);
 
@@ -644,20 +616,7 @@
 		color->alpha = a;
 
 		if (PALETTE_MODE) {
-			pixmap_color.r = r;
-			pixmap_color.g = g;
-			pixmap_color.b = b;
-			pixmap_color.global_index = GFX_COLOR_INDEX_UNMAPPED;
-			if ((error_code = gfx_alloc_color(state->driver->mode->palette, &pixmap_color))) {
-				if (error_code < 0) {
-					GFXWARN("Could not get color entry for %02x/%02x/%02x\n", r, g, b);
-					return error_code;
-				} else if ((error_code = state->driver->set_palette(state->driver, pixmap_color.global_index, (byte) r, (byte) g, (byte) b))) {
-					GFXWARN("Graphics driver failed to set color index %d to (%02x/%02x/%02x)\n", pixmap_color.global_index, r, g, b);
-					return error_code;
-				}
-			}
-			color->visual.global_index = pixmap_color.global_index;
+			color->visual.parent_index = state->driver->mode->palette->findNearbyColor(r,g,b,true);
 		}
 	}
 
@@ -674,52 +633,27 @@
 			colorIn.priority, colorIn.control);
 }
 
-int gfxop_set_system_color(gfx_state_t *state, gfx_color_t *color) {
-	gfx_palette_color_t *palette_colors;
+int gfxop_set_system_color(gfx_state_t *state, unsigned int index, gfx_color_t *color) {
 	BASIC_CHECKS(GFX_FATAL);
 
 	if (!PALETTE_MODE)
 		return GFX_OK;
 
-	if (color->visual.global_index < 0 || color->visual.global_index >= state->driver->mode->palette->max_colors_nr) {
-		GFXERROR("Attempt to set invalid color index %02x as system color\n", color->visual.global_index);
+	if (index >= state->driver->mode->palette->size()) {
+		GFXERROR("Attempt to set invalid color index %02x as system color\n", color->visual.parent_index);
 		return GFX_ERROR;
 	}
 
-	palette_colors = state->driver->mode->palette->colors;
-	palette_colors[color->visual.global_index].lockers = GFX_COLOR_SYSTEM;
+	state->driver->mode->palette->makeSystemColor(index, color->visual);
 
 	return GFX_OK;
 }
 
 int gfxop_free_color(gfx_state_t *state, gfx_color_t *color) {
-	gfx_palette_color_t *palette_color = 0;
-	gfx_pixmap_color_t pixmap_color	= {0, 0, 0, 0};
-	int error_code;
-	BASIC_CHECKS(GFX_FATAL);
-
-	if (!PALETTE_MODE)
-		return GFX_OK;
-
-	if (color->visual.global_index < 0 || color->visual.global_index >= state->driver->mode->palette->max_colors_nr) {
-		GFXERROR("Attempt to free invalid color index %02x\n", color->visual.global_index);
-		return GFX_ERROR;
-	}
-
-	pixmap_color.global_index = color->visual.global_index;
-	palette_color = state->driver->mode->palette->colors + pixmap_color.global_index;
-	pixmap_color.r = palette_color->r;
-	pixmap_color.g = palette_color->g;
-	pixmap_color.b = palette_color->b;
-
-	if ((error_code = gfx_free_color(state->driver->mode->palette, &pixmap_color))) {
-		GFXWARN("Failed to free color with color index %02x\n", color->visual.global_index);
-		return error_code;
-	}
-
-	return GFX_OK;
+	// FIXME: implement. (And call in the appropriate places!)
 }
 
+
 // Generic drawing operations
 
 static int line_check_bar(int *start, int *length, int clipstart, int cliplength) {
@@ -950,7 +884,7 @@
 		end.y += yfact >> 1;
 	}
 	
-	if (color.visual.global_index == GFX_COLOR_INDEX_UNMAPPED)
+	if (color.visual.parent_index == GFX_COLOR_INDEX_UNMAPPED)
 		gfxop_set_color(state, &color, color);
 	return _gfxop_draw_line_clipped(state, start, end, color, line_mode, line_style);
 }
@@ -1089,7 +1023,7 @@
 	if (shade_type == GFX_BOX_SHADE_FLAT) {
 		color1.priority = 0;
 		color1.control = 0;
-		if (color1.visual.global_index == GFX_COLOR_INDEX_UNMAPPED)
+		if (color1.visual.parent_index == GFX_COLOR_INDEX_UNMAPPED)
 			gfxop_set_color(state, &color1, color1);
 		return drv->draw_filled_rect(drv, new_box, color1, color1, GFX_SHADE_FLAT);
 	} else {
@@ -1098,8 +1032,10 @@
 			return GFX_ERROR;
 		}
 
-		gfx_color_t draw_color1 = {{0, 0, 0, 0}, 0, 0, 0, 0};
-		gfx_color_t draw_color2 = {{0, 0, 0, 0}, 0, 0, 0, 0};
+		gfx_color_t draw_color1; // CHECKME
+		gfx_color_t draw_color2;
+		gfxop_set_color(state, &draw_color1, 0, 0, 0, 0, 0, 0);
+		gfxop_set_color(state, &draw_color2, 0, 0, 0, 0, 0, 0);
 
 		draw_color1.mask = draw_color2.mask = color1.mask;
 		draw_color1.priority = draw_color2.priority = color1.priority;
@@ -1253,7 +1189,6 @@
 
 
 // Pointer and IO ops
-
 int gfxop_sleep(gfx_state_t *state, uint32 msecs) {
 	BASIC_CHECKS(GFX_FATAL);
 
@@ -2175,8 +2110,6 @@
 	if (_gfxop_grab_pixmap(state, &pixmap, area.x, area.y, area.xl, area.yl, 0, &resultzone))
 		return NULL; // area CUT the visual screen had a null or negative size
 
-	pixmap->flags |= GFX_PIXMAP_FLAG_PALETTE_SET | GFX_PIXMAP_FLAG_DONT_UNALLOCATE_PALETTE;
-
 	return pixmap;
 }
 

Modified: scummvm/trunk/engines/sci/gfx/operations.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/operations.h	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/operations.h	2009-03-08 20:17:01 UTC (rev 39242)
@@ -102,8 +102,7 @@
 	rect_t clip_zone; /* The current SCALED clipping zone; a cached scaled version of clip_zone_unscaled */
 
 	gfx_driver_t *driver;
-	gfx_pixmap_color_t *static_palette; /* Null for dynamic palettes */
-	int static_palette_entries;
+	Palette *static_palette; /* Null for dynamic palettes */
 
 	int visible_map;
 
@@ -335,9 +334,10 @@
 ** free that color.
 */
 
-int gfxop_set_system_color(gfx_state_t *state, gfx_color_t *color);
+int gfxop_set_system_color(gfx_state_t *state, unsigned int index, gfx_color_t *color);
 /* Designates a color as a 'system color'
 ** Parameters: (gfx_state_t *) state: The affected state
+**             (unsigned int) index: The index for the new system color
 **             (gfx_color_t *) color: The color to designate as a system color
 ** Returns   : (int) GFX_OK or GFX_ERROR if state is invalid
 ** System colors are permanent colors that cannot be deallocated. As such, they must be used

Added: scummvm/trunk/engines/sci/gfx/palette.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/palette.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/gfx/palette.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -0,0 +1,265 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/gfx/palette.h"
+#include "sci/gfx/gfx_system.h"
+
+// #define DEBUG_MERGE
+
+namespace Sci {
+
+Palette::Palette(unsigned int s) {
+	_size = s;
+	_colors = new PaletteEntry[s];
+	_parent = 0;
+	_dirty = true;
+	_refcount = 1;
+}
+
+Palette::Palette(gfx_pixmap_color_t* colors, unsigned int s)
+{
+	_size = s;
+	_colors = new PaletteEntry[s];
+	_parent = 0;
+	_dirty = true;
+	_refcount = 1;
+
+	for (unsigned int i = 0; i < _size; ++i)
+		setColor(i, colors[i].r, colors[i].g, colors[i].b);
+}
+
+Palette::~Palette() {
+	if (_parent)
+		unmerge();
+
+	delete[] _colors;
+	_colors = 0;
+}
+
+Palette* Palette::getref() {
+	_refcount++;
+	return this;
+}
+
+void Palette::free() {
+	assert(_refcount > 0);
+	_refcount--;
+
+	if (_refcount == 0)
+		delete this;
+}
+
+void Palette::resize(unsigned int s) {
+	if (s == _size) return;
+	assert(!_parent);
+	assert(_refcount == 1);
+	assert(s >= _size);
+
+	PaletteEntry *n = new PaletteEntry[s];
+	for (unsigned int i = 0; i < _size; ++i)
+		n[i] = _colors[i];
+
+	delete[] _colors;
+	_colors = n;
+	_size = s;
+}
+
+void Palette::unmerge() {
+	assert(_parent);
+#ifdef DEBUG_MERGE
+	fprintf(stderr, "Unmerge %s from %s (%d colors)\n", name.c_str(), _parent->name.c_str(), _size);
+#endif
+
+	int count = 0;
+	for (unsigned int i = 0; i < _size; ++i) {
+		if (_colors[i].refcount == PALENTRY_FREE) continue;
+		int pi = _colors[i].parent_index;
+		assert(pi >= 0);
+		assert(pi < (int)_parent->_size);
+		assert(_parent->_colors[pi].refcount != 0);
+		assert(_parent->_colors[pi].refcount != PALENTRY_FREE);
+		int old = _parent->_colors[pi].refcount;
+		if (_parent->_colors[pi].refcount != PALENTRY_LOCKED)
+			_parent->_colors[pi].refcount--;
+		if (_parent->_colors[pi].refcount == 0) {
+			_parent->_colors[pi].refcount = PALENTRY_FREE;
+			count++;
+		}
+#ifdef DEBUG_MERGE
+		fprintf(stderr, "%d: %d -> %d\n", pi, old, _parent->_colors[pi].refcount);
+#endif
+		_colors[i].parent_index = -1;
+	}
+#ifdef DEBUG_MERGE
+	fprintf(stderr, "Unmerge free %d colors\n", count);
+#endif
+
+	_parent = 0;
+}
+
+void Palette::setColor(unsigned int index, byte r, byte g, byte b) {
+	assert(index < _size);
+	assert(!_parent);
+
+//	FIXME: We may want to have this assert. This will require changing the
+//	way loops sharing a single view's palette works.
+//	assert(_refcount == 1);
+
+	PaletteEntry& entry = _colors[index];
+
+	assert(entry.refcount == PALENTRY_FREE || entry.refcount == 0);
+	entry.refcount = 0;
+	entry.r = r;
+	entry.g = g;
+	entry.b = b;
+	entry.parent_index = -1;
+
+	_dirty = true;
+}
+
+void Palette::makeSystemColor(unsigned int index, const PaletteEntry& color) {
+	assert(index < _size);
+	PaletteEntry& entry = _colors[index];
+	entry.r = color.r;
+	entry.g = color.g;
+	entry.b = color.b;
+	entry.refcount = PALENTRY_LOCKED;
+}
+
+unsigned int Palette::findNearbyColor(byte r, byte g, byte b, bool lock) {
+	int bestdelta = 1 + ((0x100 * 0x100) * 3);
+	int bestcolor = -1;
+	int firstfree = -1;
+
+	assert(_size != 0);
+
+	for (unsigned int i = 0; i < _size; ++i) {
+		PaletteEntry& entry = _colors[i];
+	
+		if (entry.refcount != PALENTRY_FREE) {
+			int dr = abs(entry.r - r);
+			int dg = abs(entry.g - g);
+			int db = abs(entry.b - b);
+	
+			if (dr == 0 && dg == 0 && db == 0) {
+				// Exact match
+				//exact = true;
+				if (lock && entry.refcount != PALENTRY_LOCKED)
+					entry.refcount++;
+				return i;
+			}
+	
+			int delta = (dr * dr) + (dg * dg) + (db * db);
+			if (delta < bestdelta) {
+				bestdelta = delta;
+				bestcolor = i;
+			}
+		} else {
+			if (firstfree == -1)
+				firstfree = i;
+		}
+	}
+	
+	if (firstfree != -1) {
+		// TODO: mark palette as dirty
+		setColor(firstfree, r, g, b);
+		//exact = true;
+		if (lock)
+			_colors[firstfree].refcount++;
+		return firstfree;
+	}
+
+	//exact = false;
+	if (lock && _colors[bestcolor].refcount != PALENTRY_LOCKED) {
+#if 0
+			_colors[bestcolor].r = r;
+			_colors[bestcolor].g = g;
+			_colors[bestcolor].b = b;
+			_dirty = true;
+#endif
+			_colors[bestcolor].refcount++;
+	}
+	return bestcolor;
+}
+
+void Palette::mergeInto(Palette *parent) {
+	assert(!_parent || _parent == parent);
+	assert(parent != this);
+#ifdef DEBUG_MERGE
+	fprintf(stderr, "Merge: %s into %s (%d colors)\n", name.c_str(), parent->name.c_str(), _size);
+#endif
+
+	if (_parent == parent) {
+#ifdef DEBUG_MERGE
+		fprintf(stderr, "NOP\n");
+#endif
+		return;
+	}
+	_parent = parent;
+
+#ifdef DEBUG_MERGE
+	bool *used = new bool[_parent->size()];
+	for (unsigned int i = 0; i < _parent->size(); ++i)
+		used[i] = false;
+	int count = 0;
+	int used_min = 1000;
+	int used_max = 0;
+#endif
+
+	for (unsigned int i = 0; i < _size; ++i) {
+		PaletteEntry& entry = _colors[i];
+		if (entry.refcount == PALENTRY_FREE) continue;
+
+		unsigned int pi = _parent->findNearbyColor(entry.r, entry.g, entry.b);
+#ifdef DEBUG_MERGE
+		if (!used[pi]) count++;
+		used[pi] = true;
+		if (pi > used_max) used_max = pi;
+		if (pi < used_min) used_min = pi;
+#endif
+		entry.parent_index = pi;
+		if (_parent->_colors[pi].refcount != PALENTRY_LOCKED)
+			_parent->_colors[pi].refcount++;
+	}
+#ifdef DEBUG_MERGE
+	fprintf(stderr, "Merge used %d colours in [%d..%d]\n", count, used_min, used_max);
+	delete[] used;
+#endif
+}
+
+Palette* Palette::copy() {
+	assert(!_parent);
+	Palette* p = new Palette(_size);
+	p->name = "copy of " + name;
+
+	for (unsigned int i = 0; i < _size; ++i) {
+		p->_colors[i] = _colors[i];
+		p->_colors[i].refcount = 0;
+	}
+	return p;
+}
+
+
+} // End of namespace Sci


Property changes on: scummvm/trunk/engines/sci/gfx/palette.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: scummvm/trunk/engines/sci/gfx/palette.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/palette.h	                        (rev 0)
+++ scummvm/trunk/engines/sci/gfx/palette.h	2009-03-08 20:17:01 UTC (rev 39242)
@@ -0,0 +1,107 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SCI_GFX_PALETTE_H
+#define SCI_GFX_PALETTE_H
+
+#include "common/scummsys.h"
+#include "common/str.h"
+
+namespace Sci {
+
+const int PALENTRY_LOCKED = -42;
+const int PALENTRY_FREE = -41;
+
+struct PaletteEntry {
+	PaletteEntry()
+		: r(0), g(0), b(0), parent_index(-1), refcount(PALENTRY_FREE)
+	{ }
+	PaletteEntry(byte R, byte G, byte B)
+		: r(R), g(G), b(B), parent_index(-1), refcount(PALENTRY_FREE)
+	{ }
+
+	// Color data
+	byte r, g, b;
+
+	// Index in parent palette, or -1
+	int parent_index;
+
+	// Number of references from child palettes. (This includes palettes
+	// of pixmaps.)
+	// Special values: PALENTRY_LOCKED, PALENTRY_FREE
+	int refcount;
+};
+
+struct gfx_pixmap_color_t;
+
+class Palette {
+public:
+	explicit Palette(unsigned int size);
+	Palette(gfx_pixmap_color_t* colors, unsigned int size);
+	~Palette();
+
+	Palette* getref();
+	void free();
+	Palette* copy();
+
+	void resize(unsigned int size);
+	void setColor(unsigned int index, byte r, byte g, byte b);
+	void makeSystemColor(unsigned int index, const PaletteEntry& color);
+	const PaletteEntry& getColor(unsigned int index) const {
+		assert(index < _size);
+		return _colors[index];
+	}
+	const PaletteEntry& operator[](unsigned int index) const {
+		return getColor(index);
+	}
+	unsigned int size() const { return _size; }
+	bool isDirty() const { return _dirty; }
+	bool isShared() const { return _refcount > 1; }
+	Palette* getParent() { return _parent; }
+
+	void markClean() { _dirty = false; }
+
+	unsigned int findNearbyColor(byte r, byte g, byte b, bool lock=false);
+
+	void mergeInto(Palette *parent);
+	void unmerge();
+
+	Common::String name; // strictly for debugging purposes
+private:
+	PaletteEntry *_colors;
+	unsigned int _size;
+
+	Palette *_parent;
+
+	bool _dirty; // Palette has changed
+	int _refcount; // Number of pixmaps (or other objects) using this palette
+};
+
+
+
+
+} // End of namespace Sci
+
+#endif // SCI_GFX_PALETTE_H


Property changes on: scummvm/trunk/engines/sci/gfx/palette.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Modified: scummvm/trunk/engines/sci/gfx/resmgr.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/resmgr.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/resmgr.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -58,6 +58,7 @@
 	state->options = options;
 	state->driver = driver;
 	state->misc_payload = misc_payload;
+	state->static_palette = 0;
 
 	state->tag_lock_counter = state->lock_counter = 0;
 	for (ii = 0; ii < GFX_RESOURCE_TYPES_NR; ii++) {

Modified: scummvm/trunk/engines/sci/gfx/resource/sci_pal_1.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/resource/sci_pal_1.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/resource/sci_pal_1.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -39,13 +39,13 @@
 #define SCI_PAL_FORMAT_VARIABLE_FLAGS 0
 #define SCI_PAL_FORMAT_CONSTANT_FLAGS 1
 
-gfx_pixmap_color_t *gfxr_read_pal11(int id, int *colors_nr, byte *resource, int size) {
+Palette *gfxr_read_pal11(int id, byte *resource, int size) {
 	int start_color = resource[25];
 	int format = resource[32];
 	int entry_size = 0;
-	gfx_pixmap_color_t *retval;
+	Palette *retval;
 	byte *pal_data = resource + 37;
-	int _colors_nr = *colors_nr = READ_LE_UINT16(resource + 29);
+	int _colors_nr = READ_LE_UINT16(resource + 29);
 	int i;
 
 	switch (format) {
@@ -57,28 +57,21 @@
 		break;
 	}
 
-	retval = (gfx_pixmap_color_t *)sci_malloc(sizeof(gfx_pixmap_color_t) * (_colors_nr + start_color));
-	memset(retval, 0, sizeof(gfx_pixmap_color_t) * (_colors_nr + start_color));
+	retval = new Palette(_colors_nr + start_color);
+	char buf[100];
+	sprintf(buf, "read_pal11 (id %d)", id);
+	retval->name = buf;
 
 	for (i = 0; i < start_color; i ++) {
-		retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
-		retval[i].r = 0;
-		retval[i].g = 0;
-		retval[i].b = 0;
+		retval->setColor(i, 0, 0, 0);
 	}
 	for (i = start_color; i < start_color + _colors_nr; i ++) {
 		switch (format) {
 		case SCI_PAL_FORMAT_CONSTANT_FLAGS:
-			retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
-			retval[i].r = pal_data[0];
-			retval[i].g = pal_data[1];
-			retval[i].b = pal_data[2];
+			retval->setColor(i, pal_data[0], pal_data[1], pal_data[2]);
 			break;
 		case SCI_PAL_FORMAT_VARIABLE_FLAGS:
-			retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
-			retval[i].r = pal_data[1];
-			retval[i].g = pal_data[2];
-			retval[i].b = pal_data[3];
+			retval->setColor(i, pal_data[1], pal_data[2], pal_data[3]);
 			break;
 		}
 		pal_data += entry_size;
@@ -87,11 +80,10 @@
 	return retval;
 }
 
-gfx_pixmap_color_t *gfxr_read_pal1(int id, int *colors_nr, byte *resource, int size) {
+Palette *gfxr_read_pal1(int id, byte *resource, int size) {
 	int counter = 0;
 	int pos;
 	unsigned int colors[MAX_COLORS] = {0};
-	gfx_pixmap_color_t *retval;
 
 	if (size < PALETTE_START + 4) {
 		GFXERROR("Palette resource too small in %04x\n", id);
@@ -118,27 +110,23 @@
 		return NULL;
 	}
 
-	retval = (gfx_pixmap_color_t*)sci_malloc(sizeof(gfx_pixmap_color_t) * counter);
+	Palette *retval = new Palette(counter);
+	char buf[100];
+	sprintf(buf, "read_pal1 (id %d)", id);
+	retval->name = buf;
 
-	*colors_nr = counter;
 	for (pos = 0; pos < counter; pos++) {
 		unsigned int color = colors[pos];
-
-		retval[pos].global_index = GFX_COLOR_INDEX_UNMAPPED;
-		retval[pos].r = (color >> 8) & 0xff;
-		retval[pos].g = (color >> 16) & 0xff;
-		retval[pos].b = (color >> 24) & 0xff;
+		retval->setColor(pos, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff);
 	}
 
 	return retval;
 }
 
-gfx_pixmap_color_t *gfxr_read_pal1_amiga(int *colors_nr, Common::File &file) {
+Palette *gfxr_read_pal1_amiga(Common::File &file) {
 	int i;
-	gfx_pixmap_color_t *retval;
+	Palette *retval = new Palette(32);
 
-	retval = (gfx_pixmap_color_t *)sci_malloc(sizeof(gfx_pixmap_color_t) * 32);
-
 	for (i = 0; i < 32; i++) {
 		int b1, b2;
 
@@ -150,14 +138,9 @@
 			return NULL;
 		}
 
-		retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
-		retval[i].r = (b1 & 0xf) * 0x11;
-		retval[i].g = ((b2 & 0xf0) >> 4) * 0x11;
-		retval[i].b = (b2 & 0xf) * 0x11;
+		retval->setColor(i, (b1 & 0xf) * 0x11, ((b2 & 0xf0) >> 4) * 0x11, (b2 & 0xf) * 0x11);
 	}
 
-	*colors_nr = 32;
-
 	return retval;
 }
 

Modified: scummvm/trunk/engines/sci/gfx/resource/sci_pic_0.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/resource/sci_pic_0.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/resource/sci_pic_0.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -99,10 +99,10 @@
 #undef C3
 #undef C4
 
-gfx_pixmap_color_t gfx_sci0_pic_colors[GFX_SCI0_PIC_COLORS_NR]; // Initialized during initialization
+Palette* gfx_sci0_pic_colors = 0; // Initialized during initialization
+Palette* gfx_sci0_image_pal[SCI0_MAX_PALETTE+1];
+Palette* embedded_view_pal = 0;
 
-static int _gfxr_pic0_colors_initialized = 0;
-
 #define SCI1_PALETTE_SIZE 1284
 
 #ifdef FILL_RECURSIVE_DEBUG
@@ -121,18 +121,28 @@
 };
 
 void gfxr_init_static_palette() {
-	if (!_gfxr_pic0_colors_initialized) {
+	if (!gfx_sci0_pic_colors) {
+		gfx_sci0_pic_colors = new Palette(256);
+		gfx_sci0_pic_colors->name = "gfx_sci0_pic_colors";
 		for (int i = 0; i < 256; i++) {
-			gfx_sci0_pic_colors[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
-			gfx_sci0_pic_colors[i].r = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].r,
-			                                    gfx_sci0_image_colors[sci0_palette][i >> 4].r);
-			gfx_sci0_pic_colors[i].g = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].g,
-			                                    gfx_sci0_image_colors[sci0_palette][i >> 4].g);
-			gfx_sci0_pic_colors[i].b = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].b,
-			                                    gfx_sci0_image_colors[sci0_palette][i >> 4].b);
+			byte r = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].r,
+			                  gfx_sci0_image_colors[sci0_palette][i >> 4].r);
+			byte g = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].g,
+			                  gfx_sci0_image_colors[sci0_palette][i >> 4].g);
+			byte b = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].b,
+			                  gfx_sci0_image_colors[sci0_palette][i >> 4].b);
+			gfx_sci0_pic_colors->setColor(i,r,g,b);
 		}
 		//warning("Uncomment me after fixing sci0_palette changes to reset me");
 		//_gfxr_pic0_colors_initialized = 1;
+
+		for (int i = 0; i <= SCI0_MAX_PALETTE; ++i) {
+			gfx_sci0_image_pal[i] = new Palette(gfx_sci0_image_colors[i], GFX_SCI0_IMAGE_COLORS_NR);
+			gfx_sci0_image_pal[i]->name = "gfx_sci0_image_pal[i]";
+		}
+
+		embedded_view_pal = new Palette(embedded_view_colors, 16);
+		embedded_view_pal->name = "embedded_view_pal";
 	}
 }
 
@@ -150,29 +160,27 @@
 
 	pic->visual_map = gfx_pixmap_alloc_index_data(gfx_new_pixmap(320 * mode->xfact,
 	                  200 * mode->yfact, ID, 0, 0));
-	pic->visual_map->colors = gfx_sci0_pic_colors;
-	pic->visual_map->colors_nr = GFX_SCI0_PIC_COLORS_NR;
+
+	// Initialize colors
+	if (!sci1) {
+		pic->ID = ID;
+		gfxr_init_static_palette();
+	}
+
+	pic->visual_map->palette = gfx_sci0_pic_colors->getref();
 	pic->visual_map->color_key = GFX_PIXMAP_COLOR_KEY_NONE;
 
-	pic->visual_map->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
-	pic->priority_map->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
-	pic->control_map->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+	pic->visual_map->flags = 0;
+	pic->priority_map->flags = 0;
+	pic->control_map->flags = 0;
 	if (mode->xfact > 1 || mode->yfact > 1) {
 		pic->visual_map->flags |= GFX_PIXMAP_FLAG_SCALED_INDEX;
 		pic->priority_map->flags |= GFX_PIXMAP_FLAG_SCALED_INDEX;
 	}
 
-	pic->priority_map->colors = gfx_sci0_image_colors[sci0_palette];
-	pic->priority_map->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
-	pic->control_map->colors = gfx_sci0_image_colors[sci0_palette];
-	pic->control_map->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
+	pic->priority_map->palette = gfx_sci0_image_pal[sci0_palette]->getref();
+	pic->control_map->palette = gfx_sci0_image_pal[sci0_palette]->getref();
 
-	// Initialize colors
-	if (!sci1) {
-		pic->ID = ID;
-		gfxr_init_static_palette();
-	}
-
 	pic->undithered_buffer_size = pic->visual_map->index_xl * pic->visual_map->index_yl;
 	pic->undithered_buffer = NULL;
 	pic->internal = NULL;
@@ -1257,14 +1265,18 @@
 
 }
 
-static void view_transparentize(gfx_pixmap_t *view, byte *pic_index_data, int posx, int posy, int width, int height) {
+static void view_transparentize(gfx_pixmap_t *view, gfx_pixmap_t *background, int posx, int posy, int width, int height) {
 	int i, j;
+	byte *pic_index_data = background->index_data;
 
+	// FIXME: this assumes view and background have the same palette...
+	// We may want to do a reverse mapping or similar to make it general,
+	// but this (hopefully...) suffices for the current uses of this function.
+
 	for (i = 0;i < width;i++)
 		for (j = 0;j < height;j++) {
 			if (view->index_data[j*width+i] == view->color_key) {
-				view->index_data[j*width+i] =
-				    pic_index_data[(j+posy)*width+i+posx];
+				view->index_data[j*width+i] = pic_index_data[(j+posy)*width+i+posx];
 			}
 		}
 }
@@ -1274,7 +1286,7 @@
 extern void _gfx_crossblit_simple(byte *dest, byte *src, int dest_line_width, int src_line_width, int xl, int yl, int bpp);
 
 void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, byte *resource,
-					 gfxr_pic0_params_t *style, int resid, int sci1, gfx_pixmap_color_t *static_pal, int static_pal_nr) {
+					 gfxr_pic0_params_t *style, int resid, int sci1, Palette *static_pal) {
 	const int default_palette_table[GFXR_PIC0_PALETTE_SIZE] = {
 		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
 		0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x88,
@@ -1610,8 +1622,9 @@
 
 			case PIC_SCI1_OPX_SET_PALETTE:
 				p0printf("Set palette @%d\n", pos);
-				pic->visual_map->flags &= ~GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
-				pic->visual_map->colors = gfxr_read_pal1(resid, &pic->visual_map->colors_nr,
+				if (pic->visual_map->palette)
+					pic->visual_map->palette->free();
+				pic->visual_map->palette = gfxr_read_pal1(resid,
 				                          resource + pos, SCI1_PALETTE_SIZE);
 				pos += SCI1_PALETTE_SIZE;
 				goto end_op_loop;
@@ -1640,17 +1653,9 @@
 				int nodraw = 0;
 
 				gfx_pixmap_t *view;
-				//gfx_mode_t *mode;
 
 				p0printf("Embedded view @%d\n", pos);
 
-#if 0
-				// Set up mode structure for resizing the view
-				Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1bpp, which handles masks and the rest for us
-				mode = gfx_new_mode(pic->visual_map->index_xl / 320,
-				           pic->visual_map->index_yl / 200, format, 16, 0);
-#endif
-
 				GET_ABS_COORDS(posx, posy);
 				bytesize = (*(resource + pos)) + (*(resource + pos + 1) << 8);
 				p0printf("(%d, %d)\n", posx, posy);
@@ -1658,7 +1663,7 @@
 				if (!sci1 && !nodraw)
 					view = gfxr_draw_cel0(-1, -1, -1, resource + pos, bytesize, NULL, 0);
 				else
-					view = gfxr_draw_cel1(-1, -1, -1, 0, resource + pos, bytesize, NULL, static_pal_nr == GFX_SCI1_AMIGA_COLORS_NR);
+					view = gfxr_draw_cel1(-1, -1, -1, 0, resource + pos, bytesize, NULL, (static_pal && static_pal->size() == GFX_SCI1_AMIGA_COLORS_NR));
 				pos += bytesize;
 				if (nodraw)
 					continue;
@@ -1667,7 +1672,7 @@
 				// we can only safely replace the palette if it's static
 				// *if it's not for some reason, we should die
 
-				if (!(view->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE) && !sci1) {
+				if (view->palette && view->palette->isShared() && !sci1) {
 					sciprintf("gfx_draw_pic0(): can't set a non-static palette for an embedded view!\n");
 				}
 
@@ -1675,40 +1680,36 @@
 				// nibble of the color index to the high nibble.
 
 				if (sci1) {
-					if (static_pal_nr == GFX_SCI1_AMIGA_COLORS_NR) {
+					if (static_pal && static_pal->size() == GFX_SCI1_AMIGA_COLORS_NR) {
 						// Assume Amiga game
-						pic->visual_map->colors = static_pal;
-						pic->visual_map->colors_nr = static_pal_nr;
-						pic->visual_map->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+						pic->visual_map->palette = static_pal->getref();
 					}
-					view->colors = pic->visual_map->colors;
-					view->colors_nr = pic->visual_map->colors_nr;
+					if (view->palette) view->palette->free();
+					view->palette = pic->visual_map->palette->copy();
 				} else
-					view->colors = embedded_view_colors;
+					view->palette = embedded_view_pal->getref();
 
 				// Hack to prevent overflowing the visual map buffer.
 				// Yes, this does happen otherwise.
 				if (view->index_yl + sci_titlebar_size > 200)
 					sci_titlebar_size = 0;
 
-#if 0
-				// FIXME: This doesn't just scale the image, but also
-				// tries to fit the colours into the palette in 'mode',
-				// breaking colours in e.g., KQ5 floppy.
+				// Set up mode structure for resizing the view
+				Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1byte/p, which handles masks and the rest for us
+				gfx_mode_t *mode = gfx_new_mode(pic->visual_map->index_xl / 320,
+				           pic->visual_map->index_yl / 200, format, view->palette, 0);
+
 				gfx_xlate_pixmap(view, mode, GFX_XLATE_FILTER_NONE);
-#endif
+				gfx_free_mode(mode);
 
 				if (flags & DRAWPIC01_FLAG_OVERLAID_PIC)
-					view_transparentize(view, pic->visual_map->index_data, posx, sci_titlebar_size + posy,
+					view_transparentize(view, pic->visual_map, posx, sci_titlebar_size + posy,
 					                    view->index_xl, view->index_yl);
 
 				_gfx_crossblit_simple(pic->visual_map->index_data + (sci_titlebar_size * 320) + posy * 320 + posx,
 				                      view->index_data, pic->visual_map->index_xl, view->index_xl,
 				                      view->index_xl, view->index_yl, 1);
 
-#if 0
-				gfx_free_mode(mode);
-#endif
 				gfx_free_pixmap(NULL, view);
 			}
 			goto end_op_loop;
@@ -1777,36 +1778,32 @@
 }
 
 void gfxr_draw_pic11(gfxr_pic_t *pic, int flags, int default_palette, int size, byte *resource,
-					 gfxr_pic0_params_t *style, int resid, gfx_pixmap_color_t *static_pal, int static_pal_nr) {
+					 gfxr_pic0_params_t *style, int resid, Palette *static_pal) {
 	int has_bitmap = READ_LE_UINT16(resource + 4);
 	int vector_data_ptr = READ_LE_UINT16(resource + 16);
 	int palette_data_ptr = READ_LE_UINT16(resource + 28);
 	int bitmap_data_ptr = READ_LE_UINT16(resource + 32);
 	int sci_titlebar_size = style->pic_port_bounds.y;
-	//gfx_mode_t *mode;
 	gfx_pixmap_t *view = NULL;
-#if 0
-	// Set up mode structure for resizing the view
-	Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1bpp, which handles masks and the rest for us
-	mode = gfx_new_mode(pic->visual_map->index_xl / 320, pic->visual_map->index_yl / 200,
-	           format, 16, 0);
-#endif
 
-	pic->visual_map->colors = gfxr_read_pal11(-1, &(pic->visual_map->colors_nr), resource + palette_data_ptr, 1284);
+	if (pic->visual_map->palette) pic->visual_map->palette->free();
+	pic->visual_map->palette = gfxr_read_pal11(-1, resource + palette_data_ptr, 1284);
 
 	if (has_bitmap)
 		view = gfxr_draw_cel11(-1, 0, 0, 0, resource, resource + bitmap_data_ptr, size - bitmap_data_ptr, NULL);
 
 	if (view) {
-		view->colors = pic->visual_map->colors;
-		view->colors_nr = pic->visual_map->colors_nr;
+		view->palette = pic->visual_map->palette->getref();
 
-#if 0
+		// Set up mode structure for resizing the view
+		Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1 byte/p, which handles masks and the rest for us
+		gfx_mode_t *mode = gfx_new_mode(pic->visual_map->index_xl / 320, pic->visual_map->index_yl / 200, format, view->palette, 0);
+
 		gfx_xlate_pixmap(view, mode, GFX_XLATE_FILTER_NONE);
-#endif
+		gfx_free_mode(mode);
 
 		if (flags & DRAWPIC01_FLAG_OVERLAID_PIC)
-			view_transparentize(view, pic->visual_map->index_data, 0, 0, view->index_xl, view->index_yl);
+			view_transparentize(view, pic->visual_map, 0, 0, view->index_xl, view->index_yl);
 
 		// Hack to prevent overflowing the visual map buffer.
 		// Yes, this does happen otherwise.
@@ -1823,8 +1820,7 @@
 		GFXWARN("No view was contained in SCI1.1 pic resource");
 	}
 
-	gfxr_draw_pic01(pic, flags, default_palette, size - vector_data_ptr, resource + vector_data_ptr, style, resid, 1,
-	                static_pal, static_pal_nr);
+	gfxr_draw_pic01(pic, flags, default_palette, size - vector_data_ptr, resource + vector_data_ptr, style, resid, 1, static_pal);
 }
 
 void gfxr_dither_pic0(gfxr_pic_t *pic, int dmode, int pattern) {
@@ -1841,8 +1837,7 @@
 		return; // Nothing to do
 
 	if (dmode == GFXR_DITHER_MODE_D16) { // Limit to 16 colors
-		pic->visual_map->colors = gfx_sci0_image_colors[sci0_palette];
-		pic->visual_map->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
+		pic->visual_map->palette = gfx_sci0_image_pal[sci0_palette]->getref();
 	}
 
 	for (y = 0; y < yl; y++) {

Modified: scummvm/trunk/engines/sci/gfx/resource/sci_resmgr.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/resource/sci_resmgr.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/resource/sci_resmgr.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -101,31 +101,25 @@
 	if (state->version >= SCI_VERSION_01_VGA) {
 		if (need_unscaled) {
 			if (state->version == SCI_VERSION_1_1)
-				gfxr_draw_pic11(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id,
-				                state->static_palette, state->static_palette_entries);
+				gfxr_draw_pic11(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, state->static_palette);
 			else
-				gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 1,
-				                state->static_palette, state->static_palette_entries);
+				gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 1, state->static_palette);
 		}
 		if (scaled_pic && scaled_pic->undithered_buffer)
 			memcpy(scaled_pic->visual_map->index_data, scaled_pic->undithered_buffer, scaled_pic->undithered_buffer_size);
 
 		if (state->version == SCI_VERSION_1_1)
-			gfxr_draw_pic11(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id,
-			                state->static_palette, state->static_palette_entries);
+			gfxr_draw_pic11(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, state->static_palette);
 		else
-			gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, state->version,
-			                state->static_palette, state->static_palette_entries);
+			gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, state->version, state->static_palette);
 	} else {
 		if (need_unscaled)
-			gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 0,
-			                state->static_palette, state->static_palette_entries);
+			gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 0, state->static_palette);
 
 		if (scaled_pic && scaled_pic->undithered_buffer)
 			memcpy(scaled_pic->visual_map->index_data, scaled_pic->undithered_buffer, scaled_pic->undithered_buffer_size);
 
-		gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, 0,
-		                state->static_palette, state->static_palette_entries);
+		gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, 0, state->static_palette);
 		if (need_unscaled)
 			gfxr_remove_artifacts_pic0(scaled_pic, unscaled_pic);
 
@@ -147,12 +141,12 @@
 	return GFX_OK;
 }
 
-void gfxr_palettize_view(gfxr_view_t *view, gfx_pixmap_color_t *source, int source_entries) {
-	int i;
-
-	for (i = 0;i < MIN(view->colors_nr, source_entries);i++) {
-		if ((view->colors[i].r == 0) && (view->colors[i].g == 0) && (view->colors[i].b == 0)) {
-			view->colors[i] = source[i];
+void gfxr_palettize_view(gfxr_view_t *view, Palette *source) {
+	for (unsigned i = 0; i < MIN(view->palette->size(), source->size()); i++) {
+		const PaletteEntry& vc = view->palette->getColor(i);
+		if (vc.r == 0 && vc.g == 0 && vc.b == 0) {
+			const PaletteEntry& sc = source->getColor(i);
+			view->palette->setColor(i, sc.r, sc.g, sc.b);
 		}
 	}
 }
@@ -179,7 +173,7 @@
 	case SCI_VERSION_01_VGA_ODD:
 	case SCI_VERSION_1_EARLY:
 	case SCI_VERSION_1_LATE:
-		result = gfxr_draw_view1(resid, res->data, res->size, state->static_palette, state->static_palette_entries);
+		result = gfxr_draw_view1(resid, res->data, res->size, state->static_palette);
 		break;
 	case SCI_VERSION_1_1:
 	case SCI_VERSION_32:
@@ -188,12 +182,11 @@
 	}
 
 	if (state->version >= SCI_VERSION_01_VGA) {
-		if (!result->colors) {
-			result->colors = (gfx_pixmap_color_t *)sci_malloc(sizeof(gfx_pixmap_color_t) * state->static_palette_entries);
-			memset(result->colors, 0, sizeof(gfx_pixmap_color_t) * state->static_palette_entries);
-			result->colors_nr = state->static_palette_entries;
+		if (!result->palette) {
+			result->palette = new Palette(state->static_palette->size());
+			result->palette->name = "interpreter_get_view";
 		}
-		gfxr_palettize_view(result, state->static_palette, state->static_palette_entries);
+		gfxr_palettize_view(result, state->static_palette);
 	}
 	return result;
 }
@@ -235,9 +228,9 @@
 	byte *resource = res->data;
 
 	retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(CURSOR_SIZE, CURSOR_SIZE, resid, 0, 0));
-	retval->colors = gfx_sci01_cursor_colors;
-	retval->colors_nr = (state->version != SCI_VERSION_0) ? 3 : 2;
-	retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+	// FIXME: don't copy palette
+	retval->palette = new Palette(gfx_sci01_cursor_colors, (state->version != SCI_VERSION_0) ? 3 : 2);
+	retval->palette->name = "cursor";	
 	retval->color_key = GFX_CURSOR_TRANSPARENT;
 
 	if (state->version != SCI_VERSION_0) {
@@ -305,15 +298,15 @@
 	return resources;
 }
 
-gfx_pixmap_color_t *gfxr_interpreter_get_static_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal) {
+Palette *gfxr_interpreter_get_static_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal) {
 	if (version >= SCI_VERSION_01_VGA)
 		return gfxr_interpreter_get_palette(state, version, colors_nr, internal, 999);
 
 	*colors_nr = GFX_SCI0_PIC_COLORS_NR;
-	return gfx_sci0_pic_colors;
+	return gfx_sci0_pic_colors->getref();
 }
 
-gfx_pixmap_color_t *gfxr_interpreter_get_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal, int nr) {
+Palette *gfxr_interpreter_get_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal, int nr) {
 	ResourceManager *resmgr = (ResourceManager *)state->misc_payload;
 	Resource *res;
 
@@ -329,7 +322,7 @@
 	case SCI_VERSION_01_VGA_ODD :
 	case SCI_VERSION_1_EARLY :
 	case SCI_VERSION_1_LATE :
-		return gfxr_read_pal1(res->id, colors_nr, res->data, res->size);
+		return gfxr_read_pal1(res->id, res->data, res->size);
 	case SCI_VERSION_1_1 :
 	case SCI_VERSION_32 :
 		GFXDEBUG("Palettes are not yet supported in this SCI version\n");

Modified: scummvm/trunk/engines/sci/gfx/resource/sci_view_0.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/resource/sci_view_0.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/resource/sci_view_0.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -49,14 +49,11 @@
 
 	retval->xoffset = mirrored ? xhot : -xhot;
 	retval->yoffset = -yhot;
-	retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
 
 	if (view) {
-		retval->colors = view->colors;
-		retval->colors_nr = view->colors_nr;
+		retval->palette = view->palette->getref();
 	} else {
-		retval->colors = gfx_sci0_image_colors[sci0_palette];
-		retval->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
+		retval->palette = gfx_sci0_image_pal[sci0_palette]->getref();
 	}
 
 	if (xl <= 0 || yl <= 0) {
@@ -183,9 +180,8 @@
 	view->loops_nr = resource[V0_LOOPS_NR_OFFSET];
 
 	// Set palette
-	view->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
-	view->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
-	view->colors = gfx_sci0_image_colors[sci0_palette];
+	view->flags = 0;
+	view->palette = gfx_sci0_image_pal[sci0_palette]->getref();
 
 	if ((palette_ofs) && (palette >= 0)) {
 		byte *paldata = resource + palette_ofs + (palette * GFX_SCI0_IMAGE_COLORS_NR);

Modified: scummvm/trunk/engines/sci/gfx/resource/sci_view_1.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/resource/sci_view_1.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/resource/sci_view_1.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -244,13 +244,9 @@
 	retval->xoffset = (mirrored) ? xhot : -xhot;
 	retval->yoffset = -yhot;
 
-	if (view) {
-		retval->colors = view->colors;
-		retval->colors_nr = view->colors_nr;
-	}
+	if (view)
+		retval->palette = view->palette->getref();
 
-	retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
-
 	if (xl <= 0 || yl <= 0) {
 		gfx_free_pixmap(NULL, retval);
 		GFXERROR("View %02x:(%d/%d) has invalid xl=%d or yl=%d\n", id, loop, cel, xl, yl);
@@ -316,8 +312,7 @@
 #define V1_MAGICS_NR 5
 //static byte view_magics[V1_MAGICS_NR] = {0x80, 0x00, 0x00, 0x00, 0x00};
 
-gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, gfx_pixmap_color_t *static_pal,
-	int static_pal_nr) {
+gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, Palette *static_pal) {
 	int i;
 	int palette_offset;
 	gfxr_view_t *view;
@@ -358,22 +353,18 @@
 			free(view);
 			return NULL;
 		}
-		if (!(view->colors = gfxr_read_pal1(id, &(view->colors_nr),
-		                                    resource + palette_offset, size - palette_offset))) {
+		if (!(view->palette = gfxr_read_pal1(id, resource + palette_offset, size - palette_offset))) {
 			GFXERROR("view %04x: Palette reading failed. Aborting...\n", id);
 			free(view);
 			return NULL;
 		}
-	} else if (static_pal_nr == GFX_SCI1_AMIGA_COLORS_NR) {
+	} else if (static_pal && static_pal->size() == GFX_SCI1_AMIGA_COLORS_NR) {
 		// Assume we're running an amiga game.
 		amiga_game = 1;
-		view->colors = static_pal;
-		view->colors_nr = static_pal_nr;
-		view->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+		view->palette = static_pal->getref();
 	} else {
 		GFXWARN("view %04x: Doesn't have a palette. Can FreeSCI handle this?\n", view->ID);
-		view->colors = NULL;
-		view->colors_nr = 0;
+		view->palette = NULL;
 	}
 
 	view->loops = (gfxr_loop_t*)sci_malloc(sizeof(gfxr_loop_t) * view->loops_nr);
@@ -434,13 +425,9 @@
 	retval->xoffset = (mirrored) ? xdisplace : -xdisplace;
 	retval->yoffset = -ydisplace;
 
-	if (view) {
-		retval->colors = view->colors;
-		retval->colors_nr = view->colors_nr;
-	}
+	if (view)
+		retval->palette = view->palette->getref();
 
-	retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
-
 	if (xl <= 0 || yl <= 0) {
 		gfx_free_pixmap(NULL, retval);
 		GFXERROR("View %02x:(%d/%d) has invalid xl=%d or yl=%d\n", id, loop, cel, xl, yl);
@@ -494,7 +481,7 @@
 	view->loops = (gfxr_loop_t *)calloc(view->loops_nr, sizeof(gfxr_loop_t));
 
 	// There is no indication of size here, but this is certainly large enough
-	view->colors = gfxr_read_pal11(id, &view->colors_nr, resource + palette_offset, 1284);
+	view->palette = gfxr_read_pal11(id, resource + palette_offset, 1284);
 
 	seeker = resource + header_size;
 	for (i = 0; i < view->loops_nr; i++) {

Modified: scummvm/trunk/engines/sci/gfx/sci_widgets.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/sci_widgets.cpp	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/gfx/sci_widgets.cpp	2009-03-08 20:17:01 UTC (rev 39242)
@@ -135,7 +135,8 @@
 	gfx_state_t *state = s->gfx_state;
 	int shadow_offset = 2;
 	rect_t frame;
-	gfx_color_t black	= {{0, 0, 0, 0}, 0, 0, 0, 0};
+	gfx_color_t black;
+	gfxop_set_color(state, &black, 0, 0, 0, 0, 0, 0);
 	gfxw_port_t *win;
 	gfxw_list_t *decorations;
 //	int xextra = !(flags & WINDOW_FLAG_NOFRAME) ? 1 : 0;
@@ -596,7 +597,7 @@
 	rect_t area = gfx_rect(MENU_BOX_LEFT_PADDING, 0, width - MENU_BOX_LEFT_PADDING, 10);
 	rect_t list_area = gfx_rect(port->zone.x, area.y + offset + port->zone.y, width, area.yl);
 	gfxw_list_t *list = (gfxw_list_t *) gfxw_set_id(GFXW(gfxw_new_list(list_area, 0)), ID, GFXW_NO_ID);
-	gfx_color_t xcolor = {{0, 0, 0, 0}, 0, 0, 0, 0};
+	gfx_color_t xcolor = { PaletteEntry(), 0, 0, 0, 0};
 
 	color = un_prioritize(color);
 	bgcolor = un_prioritize(bgcolor);

Modified: scummvm/trunk/engines/sci/module.mk
===================================================================
--- scummvm/trunk/engines/sci/module.mk	2009-03-08 18:58:09 UTC (rev 39241)
+++ scummvm/trunk/engines/sci/module.mk	2009-03-08 20:17:01 UTC (rev 39242)
@@ -43,6 +43,7 @@
 	gfx/gfx_widgets.o \
 	gfx/menubar.o \
 	gfx/operations.o \
+	gfx/palette.o \
 	gfx/resmgr.o \
 	gfx/sbtree.o \
 	gfx/sci_widgets.o \


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list