[gs-cvs] rev 7765 - trunk/gs/src

raph at ghostscript.com raph at ghostscript.com
Mon Mar 5 13:09:41 PST 2007


Author: raph
Date: 2007-03-05 13:09:35 -0800 (Mon, 05 Mar 2007)
New Revision: 7765

Modified:
   trunk/gs/src/gdevp14.c
   trunk/gs/src/gdevpdfb.c
   trunk/gs/src/gdevpdfc.c
   trunk/gs/src/gdevpdfg.c
   trunk/gs/src/gdevpdfg.h
   trunk/gs/src/gdevpdfi.c
   trunk/gs/src/gdevpdfk.c
   trunk/gs/src/gdevpdfv.c
   trunk/gs/src/gdevps.c
   trunk/gs/src/gdevpsdi.c
   trunk/gs/src/gscdevn.c
   trunk/gs/src/gscdevn.h
   trunk/gs/src/gscindex.h
   trunk/gs/src/gscolor.c
   trunk/gs/src/gscolor1.c
   trunk/gs/src/gscolor2.c
   trunk/gs/src/gscolor2.h
   trunk/gs/src/gscolor3.c
   trunk/gs/src/gscpixel.c
   trunk/gs/src/gscpixel.h
   trunk/gs/src/gscscie.c
   trunk/gs/src/gscsepr.c
   trunk/gs/src/gscsepr.h
   trunk/gs/src/gscspace.c
   trunk/gs/src/gscspace.h
   trunk/gs/src/gscssub.c
   trunk/gs/src/gsicc.c
   trunk/gs/src/gsicc.h
   trunk/gs/src/gsimage.c
   trunk/gs/src/gsiparam.h
   trunk/gs/src/gsistate.c
   trunk/gs/src/gslibctx.c
   trunk/gs/src/gspcolor.c
   trunk/gs/src/gsptype1.c
   trunk/gs/src/gsptype1.h
   trunk/gs/src/gsrefct.h
   trunk/gs/src/gsstate.c
   trunk/gs/src/gxcdevn.h
   trunk/gs/src/gxclpath.c
   trunk/gs/src/gxclrast.c
   trunk/gs/src/gxcmap.c
   trunk/gs/src/gxcolor2.h
   trunk/gs/src/gxcspace.h
   trunk/gs/src/gximag3x.c
   trunk/gs/src/gxistate.h
   trunk/gs/src/gxpcmap.c
   trunk/gs/src/gxshade.c
   trunk/gs/src/gxshade6.c
   trunk/gs/src/icsmap.h
   trunk/gs/src/lib.mak
   trunk/gs/src/zcie.c
   trunk/gs/src/zcolor.c
   trunk/gs/src/zcolor2.c
   trunk/gs/src/zcsdevn.c
   trunk/gs/src/zcsindex.c
   trunk/gs/src/zcspixel.c
   trunk/gs/src/zcssepr.c
   trunk/gs/src/zicc.c
   trunk/gs/src/zimage.c
   trunk/gs/src/zpcolor.c
   trunk/gs/src/zshade.c
Log:
Non-backwards compatible change: use consistent reference count allocation
discipline for color spaces. Previously, color spaces were allocated on
stack, on the heap, as sub-structures within other color space structures,
and were very commonly copied. Reference counting was used for the "params"
block of some, but not all, color spaces, but there were correctness
problems with that logic.

In addition, a number of "const" qualifiers have been removed, because
the action of bumping the reference count on an object is not consistent
with the C semantics of const.

This change is required to resolve problems with enhancement 688924. It
should also help with memory leaks.

Other clients, such as the PCL interpreter, will require changes to be
compatible. For simple device colorspaces, the change to gs_setcmykcolor()
(gscolor1.c) is representative of the code change required.


Modified: trunk/gs/src/gdevp14.c
===================================================================
--- trunk/gs/src/gdevp14.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevp14.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -815,7 +815,7 @@
     int num_comp = buf->n_chan - 1;
     byte *buf_ptr = buf->data + buf->rect.p.y * buf->rowstride + buf->rect.p.x;
     byte *linebuf;
-    gs_color_space cs;
+    gs_color_space *pcs;
     const byte bg = pdev->ctx->additive ? 255 : 0;
 
 #ifdef DUMP_TO_PNG
@@ -839,19 +839,21 @@
      */
     switch (num_comp) {
 	case 1:				/* DeviceGray */
-	    gs_cspace_init_DeviceGray(pis->memory, &cs);
+	    pcs = gs_cspace_new_DeviceGray(pis->memory);
 	    break;
 	case 3:				/* DeviceRGB */
-	    gs_cspace_init_DeviceRGB(pis->memory, &cs);
+	    pcs = gs_cspace_new_DeviceRGB(pis->memory);
 	    break;
 	case 4:				/* DeviceCMYK */
-	    gs_cspace_init_DeviceCMYK(pis->memory, &cs);
+	    pcs = gs_cspace_new_DeviceCMYK(pis->memory);
 	    break;
 	default:			/* Should never occur */
 	    return_error(gs_error_rangecheck);
 	    break;
     }
-    gs_image_t_init_adjust(&image, &cs, false);
+    if (pcs == NULL)
+	return_error(gs_error_VMerror);
+    gs_image_t_init_adjust(&image, pcs, false);
     image.ImageMatrix.xx = (float)width;
     image.ImageMatrix.yy = (float)height;
     image.Width = width;
@@ -868,8 +870,10 @@
 						(gs_image_common_t *)&image,
 						NULL, NULL, NULL,
 						pis->memory, &info);
-    if (code < 0)
+    if (code < 0) {
+	rc_decrement_only(pcs, "pdf14_put_image");
 	return code;
+    }
 
     linebuf = gs_alloc_bytes(pdev->memory, width * num_comp, "pdf14_put_image");
     for (y = 0; y < height; y++) {
@@ -922,6 +926,8 @@
     rc_decrement_only(pdev, "pdf_14_put_image");
 #endif
 
+    rc_decrement_only(pcs, "pdf14_put_image");
+
     return code;
 }
 

Modified: trunk/gs/src/gdevpdfb.c
===================================================================
--- trunk/gs/src/gdevpdfb.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevpdfb.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -123,7 +123,7 @@
 	      gx_color_index one, const gx_clip_path *pcpath)
 {
     int code;
-    gs_color_space cs;
+    gs_color_space *pcs;
     cos_value_t cs_value;
     cos_value_t *pcsvalue;
     byte palette[arch_sizeof_color_index * 2];
@@ -195,11 +195,11 @@
 	gs_image_t_init_mask(&image, false);
 	set_image_color(pdev, zero);
     } else if (zero == pdev->black && one == pdev->white) {
-	gs_cspace_init_DeviceGray(pdev->memory, &cs);
-	gs_image_t_init(&image, &cs);
+	pcs = gs_cspace_new_DeviceGray(pdev->memory);
+	gs_image_t_init(&image, pcs);
     } else if (zero == pdev->white && one == pdev->black) {
-	gs_cspace_init_DeviceGray(pdev->memory, &cs);
-	gs_image_t_init(&image, &cs);
+	pcs = gs_cspace_new_DeviceGray(pdev->memory);
+	gs_image_t_init(&image, pcs);
 	invert = 0xff;
     } else {
 	/*
@@ -208,28 +208,33 @@
 	 * internally, and high-level images don't go through this code.
 	 * However, we still want the code to work.
 	 */
-	gs_color_space cs_base;
+	gs_color_space *pcs_base;
 	gx_color_index c[2];
 	int i, j;
 	int ncomp = pdev->color_info.num_components;
 	byte *p;
 
-	code = pdf_cspace_init_Device(pdev->memory, &cs_base, ncomp);
+	code = pdf_cspace_init_Device(pdev->memory, &pcs_base, ncomp);
 	if (code < 0)
 	    return code;
 	c[0] = psdf_adjust_color_index((gx_device_vector *)pdev, zero);
 	c[1] = psdf_adjust_color_index((gx_device_vector *)pdev, one);
-	gs_cspace_init(&cs, &gs_color_space_type_Indexed, pdev->memory, false);
-	cs.params.indexed.base_space = *(gs_direct_color_space *)&cs_base;
-	cs.params.indexed.hival = 1;
+	pcs = gs_cspace_alloc(pdev->memory, &gs_color_space_type_Indexed);
+	if (pcs == NULL) {
+	    rc_decrement(pcs_base, "pdf_copy_mono");
+	    return_error(gs_error_VMerror);
+	}
+	pcs->base_space = pcs_base;
+	pcs->params.indexed.hival = 1;
+	pcs->params.indexed.n_comps = ncomp;
 	p = palette;
 	for (i = 0; i < 2; ++i)
 	    for (j = ncomp - 1; j >= 0; --j)
 		*p++ = (byte)(c[i] >> (j * 8));
-	cs.params.indexed.lookup.table.data = palette;
-	cs.params.indexed.lookup.table.size = p - palette;
-	cs.params.indexed.use_proc = false;
-	gs_image_t_init(&image, &cs);
+	pcs->params.indexed.lookup.table.data = palette;
+	pcs->params.indexed.lookup.table.size = p - palette;
+	pcs->params.indexed.use_proc = false;
+	gs_image_t_init(&image, pcs);
 	image.BitsPerComponent = 1;
     }
     pdf_make_bitmap_image(&image, x, y, w, h);
@@ -255,7 +260,7 @@
 	 * We don't have to worry about color space scaling: the color
 	 * space is always a Device space.
 	 */
-	code = pdf_color_space(pdev, &cs_value, NULL, &cs,
+	code = pdf_color_space(pdev, &cs_value, NULL, pcs,
 			       &writer.pin->color_spaces, in_line);
 	if (code < 0)
 	    return code;
@@ -353,17 +358,17 @@
 {
     int depth = pdev->color_info.depth;
     int bytes_per_pixel = depth >> 3;
-    gs_color_space cs;
+    gs_color_space *pcs;
     cos_value_t cs_value;
     ulong nbytes;
-    int code = pdf_cspace_init_Device(pdev->memory, &cs, bytes_per_pixel);
+    int code = pdf_cspace_init_Device(pdev->memory, &pcs, bytes_per_pixel);
     const byte *row_base;
     int row_step;
     bool in_line;
 
     if (code < 0)
 	return code;		/* can't happen */
-    gs_image_t_init(pim, &cs);
+    gs_image_t_init(pim, pcs);
     pdf_make_bitmap_image(pim, x, y, w, h);
     pim->BitsPerComponent = 8;
     nbytes = (ulong)w * bytes_per_pixel * h;
@@ -405,7 +410,7 @@
     pdf_image_writer_init(piw);
     pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
     if ((code = pdf_begin_write_image(pdev, piw, id, w, h, NULL, in_line)) < 0 ||
-	(code = pdf_color_space(pdev, &cs_value, NULL, &cs,
+	(code = pdf_color_space(pdev, &cs_value, NULL, pcs,
 				&piw->pin->color_spaces, in_line)) < 0 ||
 	(for_pattern < 2 || nbytes < 512000 ?
 	    (code = psdf_setup_lossless_filters((gx_device_psdf *) pdev,

Modified: trunk/gs/src/gdevpdfc.c
===================================================================
--- trunk/gs/src/gdevpdfc.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevpdfc.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -317,12 +317,13 @@
  * given number of components.
  */
 int
-pdf_cspace_init_Device(const gs_memory_t *mem, gs_color_space *pcs, int num_components)
+pdf_cspace_init_Device(gs_memory_t *mem, gs_color_space **ppcs,
+		       int num_components)
 {
     switch (num_components) {
-    case 1: gs_cspace_init_DeviceGray(mem, pcs); break;
-    case 3: gs_cspace_init_DeviceRGB(mem, pcs); break;
-    case 4: gs_cspace_init_DeviceCMYK(mem, pcs); break;
+    case 1: *ppcs = gs_cspace_new_DeviceGray(mem); break;
+    case 3: *ppcs = gs_cspace_new_DeviceRGB(mem); break;
+    case 4: *ppcs = gs_cspace_new_DeviceCMYK(mem); break;
     default: return_error(gs_error_rangecheck);
     }
     return 0;
@@ -363,8 +364,7 @@
 			const gs_color_space *pcs, cos_array_t *pca)
 {
     const gs_indexed_params *pip = &pcs->params.indexed;
-    const gs_color_space *base_space =
-	(const gs_color_space *)&pip->base_space;
+    const gs_color_space *base_space = pcs->base_space;
     int num_entries = pip->hival + 1;
     int num_components = gs_color_space_num_components(base_space);
     uint table_size = num_entries * num_components;
@@ -377,7 +377,6 @@
     gs_memory_t *mem = pdev->pdf_memory;
     byte *table;
     byte *palette;
-    gs_color_space cs_gray;
     cos_value_t v;
     int code;
 
@@ -428,7 +427,7 @@
 	for (i = 0; i < num_entries; ++i) {
 	    gs_client_color cc;
 
-	    gs_cspace_indexed_lookup(&pcs->params.indexed, i, &cc);
+	    gs_cspace_indexed_lookup(pcs, i, &cc);
 	    for (j = 0; j < num_components; ++j) {
 		float v = (cc.paint.values[j] - cmin.paint.values[j])
 		    * 255 / (cmax.paint.values[j] - cmin.paint.values[j]);
@@ -454,8 +453,7 @@
 	    for (i = 0; i < num_entries; ++i)
 		palette[i] = palette[i * 3];
 	    table_size = num_entries;
-	    gs_cspace_init_DeviceGray(mem, &cs_gray);
-	    base_space = &cs_gray;
+	    base_space = gs_cspace_new_DeviceGray(mem);
 	}
     }
     stream_write(&es, palette, table_size);
@@ -574,8 +572,7 @@
 	    if (res_name != NULL)
 		return 0; /* Ignore .includecolorspace */
             return pdf_color_space( pdev, pvalue, ppranges,
-                                    (const gs_color_space *)
-                                        &pcs->params.icc.alt_space,
+                                    pcs->base_space,
                                     pcsn, by_name);
 	}
         break;
@@ -835,7 +832,7 @@
 				  csa->colorant_name, &name_string, &name_string_length);
 		    if (code < 0)
 			return code;
-		    code = pdf_color_space(pdev, &v_separation, NULL, &csa->cspace, pcsn, false);
+		    code = pdf_color_space(pdev, &v_separation, NULL, csa->cspace, pcsn, false);
 		    if (code < 0)
 			return code;
 		    code = pdf_string_to_cos_name(pdev, name_string, name_string_length, &v_colorant_name);
@@ -853,8 +850,7 @@
 		COS_OBJECT_VALUE(va, pres_attributes->object);
 	    }
 	    if ((code = pdf_separation_color_space(pdev, pca, "/DeviceN", &v,
-						   (const gs_color_space *)
-					&pcs->params.device_n.alt_space,
+						   pcs->base_space,
 					pfn, &pdf_color_space_names, va)) < 0)
 		return code;
 	}
@@ -875,8 +871,7 @@
 		(code = pdf_string_to_cos_name(pdev, name_string, 
 				      name_string_length, &v)) < 0 ||
 		(code = pdf_separation_color_space(pdev, pca, "/Separation", &v,
-						   (const gs_color_space *)
-					    &pcs->params.separation.alt_space,
+					    pcs->base_space,
 					    pfn, &pdf_color_space_names, NULL)) < 0)
 		return code;
 	}
@@ -884,8 +879,7 @@
 
     case gs_color_space_index_Pattern:
 	if ((code = pdf_color_space(pdev, pvalue, ppranges,
-				    (const gs_color_space *)
-				    &pcs->params.pattern.base_space,
+				    pcs->base_space,
 				    &pdf_color_space_names, false)) < 0 ||
 	    (code = cos_array_add(pca,
 				  cos_c_string_value(&v, "/Pattern"))) < 0 ||
@@ -1042,7 +1036,7 @@
 	break;
     case gs_color_space_index_Indexed:
 	pdev->procsets |= ImageI;
-	pbcs = (const gs_color_space *)&pcs->params.indexed.base_space;
+	pbcs = pcs->base_space;
 	goto csw;
     default:
 	pdev->procsets |= ImageC;

Modified: trunk/gs/src/gdevpdfg.c
===================================================================
--- trunk/gs/src/gdevpdfg.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevpdfg.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -343,12 +343,12 @@
 		    break;
 		case gs_color_space_index_Indexed:
 		    if (pdev->CompatibilityLevel <= 1.2) {
-			pcs2 = (const gs_color_space *)&pcs->params.indexed.base_space;
+			pcs2 = pcs->base_space;
 			csi = gs_color_space_get_index(pcs2);
 			if (!is_cspace_allowed_in_strategy(pdev, csi))
 			    goto write_process_color;
 			if (csi == gs_color_space_index_Separation) {
-			    pcs2 = (const gs_color_space *)&pcs2->params.separation.alt_space;
+			    pcs2 = pcs->base_space;
 			    goto check_pcs2;
 			}
 			goto check_pcs2;
@@ -356,7 +356,7 @@
 		    goto scn;
 		case gs_color_space_index_Separation:
 		    if (pdev->CompatibilityLevel <= 1.2) {
-			pcs2 = (const gs_color_space *)&pcs->params.separation.alt_space;
+			pcs2 = pcs->base_space;
 			check_pcs2:
 			csi = gs_color_space_get_index(pcs2);
 			if (!is_cspace_allowed_in_strategy(pdev, csi))

Modified: trunk/gs/src/gdevpdfg.h
===================================================================
--- trunk/gs/src/gdevpdfg.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevpdfg.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -73,7 +73,7 @@
  * Create a local Device{Gray,RGB,CMYK} color space corresponding to the
  * given number of components.
  */
-int pdf_cspace_init_Device(const gs_memory_t *mem, gs_color_space *pcs, int num_components);
+int pdf_cspace_init_Device(gs_memory_t *mem, gs_color_space **ppcs, int num_components);
 
 /*
  * Create a PDF color space corresponding to a PostScript color space.

Modified: trunk/gs/src/gdevpdfi.c
===================================================================
--- trunk/gs/src/gdevpdfi.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevpdfi.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -243,19 +243,15 @@
     gs_color_space *cs;
     gs_memory_t *mem = pdev->v_memory;
 
-    cs = gs_alloc_struct(mem, gs_color_space, &st_color_space, 
-			    "psdf_setup_image_colors_filter");
-    if (cs == NULL)
-	return_error(gs_error_VMerror);
     switch (output_cspace_index) {
 	case gs_color_space_index_DeviceGray:
-	    gs_cspace_init_DeviceGray(mem, cs);
+	    cs = gs_cspace_new_DeviceGray(mem);
 	    break;
 	case gs_color_space_index_DeviceRGB:
-	    gs_cspace_init_DeviceRGB(mem, cs); 
+	    cs = gs_cspace_new_DeviceRGB(mem); 
 	    break;
 	case gs_color_space_index_DeviceCMYK:
-	    gs_cspace_init_DeviceCMYK(mem, cs); 
+	    cs = gs_cspace_new_DeviceCMYK(mem); 
 	    break;
 	default:
 	    /* Notify the user and terminate.
@@ -265,6 +261,8 @@
 	    eprintf("Unsupported ProcessColorModel");
 	    return_error(gs_error_undefined);
     }
+    if (cs == NULL)
+	return_error(gs_error_VMerror);
     *ppcs = cs;
     return 0;
 }
@@ -275,7 +273,7 @@
     if (pim->ColorSpace->type->index == index)
 	return true;
     if (pim->ColorSpace->type->index == gs_color_space_index_Indexed)
-	if (pim->ColorSpace->params.indexed.base_space.type->index == index)
+	if (pim->ColorSpace->base_space->type->index == index)
 	    return true;
     return false;
 }
@@ -305,7 +303,6 @@
     pdf_image_enum *pie;
     gs_image_format_t format;
     const gs_color_space *pcs;
-    gs_color_space cs_gray_temp;
     cos_value_t cs_value;
     int num_components;
     bool is_mask = false, in_line = false;
@@ -462,6 +459,7 @@
 	    code = gs_gsave(pgs);
 	    if (code < 0)
 		return code;
+	    /* {csrc}: const cast warning */
 	    code = gs_setcolorspace(pgs, ((const gs_image4_t *)pic)->ColorSpace);
 	    if (code < 0)
 		return code;
@@ -549,8 +547,8 @@
 	 * color space, which pdf_color_space() can't handle.  Patch it
 	 * to DeviceGray here.
 	 */
-	gs_cspace_init_DeviceGray(pdev->memory, &cs_gray_temp);
-	pcs = &cs_gray_temp;
+	/* {csrc} make sure this gets freed */
+	pcs = gs_cspace_new_DeviceGray(pdev->memory);
     } else if (is_mask)
 	code = pdf_prepare_imagemask(pdev, pis, pdcolor);
     else

Modified: trunk/gs/src/gdevpdfk.c
===================================================================
--- trunk/gs/src/gdevpdfk.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevpdfk.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -551,7 +551,7 @@
      */
     int code;
     int ncomps = gs_color_space_num_components(pcs);
-    gs_color_space alt_space;
+    gs_color_space *alt_space;
     cos_stream_t *pcstrm;
 
     /*
@@ -610,8 +610,9 @@
     profile_table_t *next_table = tables;
 
     pdf_cspace_init_Device(pdev->memory, &alt_space, ncomps);	/* can't fail */
-    code = pdf_make_iccbased(pdev, pca, ncomps, prange, &alt_space,
+    code = pdf_make_iccbased(pdev, pca, ncomps, prange, alt_space,
 			     &pcstrm, pprange);
+    rc_decrement(alt_space, "pdf_convert_cie_to_iccbased");
     if (code < 0)
 	return code;
 
@@ -720,7 +721,7 @@
     int code =
 	pdf_make_iccbased(pdev, pca, picc_info->num_components,
 			  picc_info->Range.ranges,
-			  (const gs_color_space *)&picc_params->alt_space,
+			  pcs->base_space,
 			  &pcstrm, NULL);
 
     if (code < 0)

Modified: trunk/gs/src/gdevpdfv.c
===================================================================
--- trunk/gs/src/gdevpdfv.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevpdfv.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -348,7 +348,7 @@
 			bool have_pattern_streams, pdf_resource_t **ppres)
 {
     const gx_color_tile *p_tile = pdc->colors.pattern.p_tile;
-    gs_color_space cs_Device;
+    gs_color_space *pcs_Device;
     cos_value_t cs_value;
     cos_value_t v;
     int code;
@@ -422,12 +422,12 @@
     code = pdf_cs_Pattern_colored(pdev, &v);
     if (code < 0)
 	return code;
-    pdf_cspace_init_Device(pdev->memory, &cs_Device, pdev->color_info.num_components);
+    pdf_cspace_init_Device(pdev->memory, &pcs_Device, pdev->color_info.num_components);
     /*
      * We don't have to worry about color space scaling: the color
      * space is always a Device space.
      */
-    code = pdf_color_space(pdev, &cs_value, NULL, &cs_Device,
+    code = pdf_color_space(pdev, &cs_value, NULL, pcs_Device,
 			   &pdf_color_space_names, true);
     if (code < 0)
 	return code;
@@ -435,7 +435,7 @@
 	cos_stream_t *pcs_mask = 0;
 	cos_stream_t *pcs_image;
 
-	gs_image_t_init_adjust(&image, &cs_Device, false);
+	gs_image_t_init_adjust(&image, pcs_Device, false);
 	image.BitsPerComponent = 8;
 	pdf_set_pattern_image((gs_data_image_t *)&image, &p_tile->tbits);
 	if (m_tile) {
@@ -471,6 +471,9 @@
 	*ppres = pdf_find_resource_by_gs_id(pdev, resourcePattern, p_tile->id);
 	*ppres = pdf_substitute_pattern(*ppres);
     }
+    /* pcs_Device will leak (picked up by GC in PS) on error, but we'll
+       tolerate that for now. */
+    rc_decrement(pcs_Device, "pdf_put_colored_pattern");
     cos_value_write(&v, pdev);
     pprints1(pdev->strm, " %s", ppscc->setcolorspace);
     return 0;

Modified: trunk/gs/src/gdevps.c
===================================================================
--- trunk/gs/src/gdevps.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevps.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -1448,7 +1448,7 @@
 		) {
 		goto fail;
 	    }
-	    pbcs = (const gs_color_space *)&pcs->params.indexed.base_space;
+	    pbcs = pcs->base_space;
 	    switch (gs_color_space_get_index(pbcs)) {
 	    case gs_color_space_index_DeviceGray:
 		base_name = "DeviceGray"; break;

Modified: trunk/gs/src/gdevpsdi.c
===================================================================
--- trunk/gs/src/gdevpsdi.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gdevpsdi.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -585,11 +585,10 @@
 	if (cmyk_to_rgb) {
 	    extern_st(st_color_space);
 	    gs_memory_t *mem = pdev->v_memory;
-	    gs_color_space *rgb_cs = gs_alloc_struct(mem, 
-		    gs_color_space, &st_color_space, "psdf_setup_image_filters");
 
-	    gs_cspace_init_DeviceRGB(mem, rgb_cs);  /* idempotent initialization */
-	    pim->ColorSpace = rgb_cs;
+	    /* {csrc} decref old colorspace? */
+	    rc_decrement_only(pim->ColorSpace, "psdf_setup_image_filters");
+	    pim->ColorSpace = gs_cspace_new_DeviceRGB(mem);
 	}
 	if (params.Depth == -1)
 	    params.Depth = (cmyk_to_rgb ? 8 : bpc_out);

Modified: trunk/gs/src/gscdevn.c
===================================================================
--- trunk/gs/src/gscdevn.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscdevn.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -38,13 +38,13 @@
 /* ---------------- Color space ---------------- */
 
 /* GC descriptors */
-gs_private_st_composite(st_color_space_DeviceN, gs_paint_color_space,
+gs_private_st_composite(st_color_space_DeviceN, gs_color_space,
      "gs_color_space_DeviceN", cs_DeviceN_enum_ptrs, cs_DeviceN_reloc_ptrs);
+private_st_device_n_attributes();
 private_st_device_n_map();
 
 /* Define the DeviceN color space type. */
 private cs_proc_num_components(gx_num_components_DeviceN);
-private cs_proc_base_space(gx_alt_space_DeviceN);
 private cs_proc_init_color(gx_init_DeviceN);
 private cs_proc_restrict_color(gx_restrict_DeviceN);
 private cs_proc_concrete_space(gx_concrete_space_DeviceN);
@@ -52,18 +52,17 @@
 private cs_proc_remap_concrete_color(gx_remap_concrete_DeviceN);
 private cs_proc_install_cspace(gx_install_DeviceN);
 private cs_proc_set_overprint(gx_set_overprint_DeviceN);
-private cs_proc_adjust_cspace_count(gx_adjust_cspace_DeviceN);
+private cs_proc_final(gx_final_DeviceN);
 private cs_proc_serialize(gx_serialize_DeviceN);
 const gs_color_space_type gs_color_space_type_DeviceN = {
     gs_color_space_index_DeviceN, true, false,
     &st_color_space_DeviceN, gx_num_components_DeviceN,
-    gx_alt_space_DeviceN,
     gx_init_DeviceN, gx_restrict_DeviceN,
     gx_concrete_space_DeviceN,
     gx_concretize_DeviceN, gx_remap_concrete_DeviceN,
     gx_default_remap_color, gx_install_DeviceN,
     gx_set_overprint_DeviceN,
-    gx_adjust_cspace_DeviceN, gx_no_adjust_color_count,
+    gx_final_DeviceN, gx_no_adjust_color_count,
     gx_serialize_DeviceN,
     gx_cspace_is_linear_default
 };
@@ -71,77 +70,52 @@
 /* GC procedures */
 
 private 
-ENUM_PTRS_WITH(cs_DeviceN_enum_ptrs, gs_color_space *pcs)
-{
-    return ENUM_USING(*pcs->params.device_n.alt_space.type->stype,
-		      &pcs->params.device_n.alt_space,
-		      sizeof(pcs->params.device_n.alt_space), index - 3);
-}
+ENUM_PTRS_BEGIN(cs_DeviceN_enum_ptrs) return 0;
 ENUM_PTR(0, gs_color_space, params.device_n.names);
 ENUM_PTR(1, gs_color_space, params.device_n.map);
 ENUM_PTR(2, gs_color_space, params.device_n.colorants);
 ENUM_PTRS_END
-private RELOC_PTRS_WITH(cs_DeviceN_reloc_ptrs, gs_color_space *pcs)
+private RELOC_PTRS_BEGIN(cs_DeviceN_reloc_ptrs)
 {
     RELOC_PTR(gs_color_space, params.device_n.names);
     RELOC_PTR(gs_color_space, params.device_n.map);
     RELOC_PTR(gs_color_space, params.device_n.colorants);
-    RELOC_USING(*pcs->params.device_n.alt_space.type->stype,
-		&pcs->params.device_n.alt_space,
-		sizeof(gs_base_color_space));
 }
 RELOC_PTRS_END
 
-/* ---------------- GC for DeviceN Attribute color spaces ---------------- */
-
-private 
-ENUM_PTRS_WITH(device_n_attributes_enum_ptrs, gs_device_n_attributes *pdevnatt)
-{
-    return ENUM_USING(*pdevnatt->cspace.type->stype,
-		      &(pdevnatt->cspace),
-		      sizeof(pdevnatt->cspace), index - 1);
-}
-ENUM_PTR(0, gs_device_n_attributes, next);
-ENUM_PTRS_END
-
-private RELOC_PTRS_WITH(device_n_attributes_reloc_ptrs,
-	       			gs_device_n_attributes *pdevnatt)
-{
-    RELOC_USING(*pdevnatt->cspace.type->stype,
-		      &(pdevnatt->cspace),
-		      sizeof(pdevnatt->cspace));
-    RELOC_PTR(gs_device_n_attributes, next);
-}
-RELOC_PTRS_END
-
-gs_private_st_composite(st_device_n_attributes, gs_device_n_attributes,
-     "gs_device_n_attributes", device_n_attributes_enum_ptrs,
-     device_n_attributes_reloc_ptrs);
-
 /* ------ Public procedures ------ */
 
 /*
- * Build a DeviceN color space.  Not including allocation and
- * initialization of the color space.
+ * Create a new DeviceN colorspace.
  */
 int
-gs_build_DeviceN(
-		gs_color_space *pcspace,
-		uint num_components,
-		const gs_color_space *palt_cspace,
-		gs_memory_t *pmem
-		)
+gs_cspace_new_DeviceN(
+    gs_color_space **ppcs,
+    uint num_components,
+    gs_color_space *palt_cspace,
+    gs_memory_t *pmem
+    )
 {
-    gs_device_n_params *pcsdevn = &pcspace->params.device_n;
-    gs_separation_name *pnames = 0;
+    gs_color_space *pcs;
+    gs_device_n_params *pcsdevn;
+    gs_separation_name *pnames;
     int code;
 
     if (palt_cspace == 0 || !palt_cspace->type->can_be_alt_space)
 	return_error(gs_error_rangecheck);
 
+    pcs = gs_cspace_alloc(pmem, &gs_color_space_type_DeviceN);
+    if (pcs == NULL)
+	return_error(gs_error_VMerror);
+    pcsdevn = &pcs->params.device_n;
+    pcsdevn->names = NULL;
+    pcsdevn->map = NULL;
+    pcsdevn->colorants = NULL;
+
     /* Allocate space for color names list. */
     code = alloc_device_n_map(&pcsdevn->map, pmem, "gs_cspace_build_DeviceN");
     if (code < 0) {
+	gs_free_object(pmem, pcs, "gs_cspace_new_DeviceN");
 	return code;
     }
     /* Allocate space for color names list. */
@@ -150,45 +124,17 @@
 			  ".gs_cspace_build_DeviceN(names)");
     if (pnames == 0) {
 	gs_free_object(pmem, pcsdevn->map, ".gs_cspace_build_DeviceN(map)");
+	gs_free_object(pmem, pcs, "gs_cspace_new_DeviceN");
 	return_error(gs_error_VMerror);
     }
+    pcs->base_space = palt_cspace;
+    rc_increment(palt_cspace);
     pcsdevn->names = pnames;
     pcsdevn->num_components = num_components;
-    pcsdevn->colorants = NULL;
+    *ppcs = pcs;
     return 0;
 }
 
-/*
- * Build a DeviceN color space.  Including allocation and initialization
- * of the color space.
- */
-int
-gs_cspace_build_DeviceN(
-			gs_color_space **ppcspace,
-			gs_separation_name *psnames,
-			uint num_components,
-			const gs_color_space *palt_cspace,
-			gs_memory_t *pmem
-			)
-{
-    gs_color_space *pcspace = 0; /* bogus initialization */
-    gs_device_n_params *pcsdevn = 0; /* bogus initialization */
-    int code;
-
-    code = gs_cspace_alloc(&pcspace, &gs_color_space_type_DeviceN, pmem);
-    if (code < 0)
-	return code;
-
-    code = gs_build_DeviceN(pcspace, num_components, palt_cspace, pmem);
-    if (code < 0) {
-	gs_free_object(pmem, pcspace, "gs_cspace_build_DeviceN");
-	return code;
-    }
-    gs_cspace_init_from((gs_color_space *)&pcsdevn->alt_space, palt_cspace);
-    *ppcspace = pcspace;
-    return 0;
-}
-
 /* Allocate and initialize a DeviceN map. */
 int
 alloc_device_n_map(gs_device_n_map ** ppmap, gs_memory_t * mem,
@@ -235,7 +181,8 @@
 
     /* Point our attribute list entry to the attribute color space */
     patt->colorant_name = sep_name;
-    gs_cspace_init_from((gs_color_space *)&(patt->cspace), pgs->color_space);
+    patt->cspace = pgs->color_space;
+    rc_increment(pgs->color_space);
 
     /* Link our new attribute color space to the DeviceN color space */
     patt->next = pdevncs->params.device_n.colorants;
@@ -300,9 +247,7 @@
 
     if (gs_color_space_get_index(pcspace) != gs_color_space_index_DeviceN ||
 	pfn->params.m != pcspace->params.device_n.num_components ||
-	pfn->params.n !=
-	  gs_color_space_num_components((gs_color_space *)
-					&pcspace->params.device_n.alt_space)
+	pfn->params.n != gs_color_space_num_components(pcspace->base_space)
 	)
 	return_error(gs_error_rangecheck);
     pimap = pcspace->params.device_n.map;
@@ -335,15 +280,6 @@
     return pcs->params.device_n.num_components;
 }
 
-/* Return the alternate space of a DeviceN space. */
-private const gs_color_space *
-gx_alt_space_DeviceN(const gs_color_space * pcs)
-{
-    return pcs->params.device_n.use_alt_cspace
-	   ? (const gs_color_space *)&(pcs->params.device_n.alt_space)
-    	   : NULL;
-}
-
 /* Initialize a DeviceN color. */
 private void
 gx_init_DeviceN(gs_client_color * pcc, const gs_color_space * pcs)
@@ -384,10 +320,7 @@
      * Check if we are using the alternate color space.
      */
     if (pis->color_component_map.use_alt_cspace) {
-        const gs_color_space *pacs =
-	    (const gs_color_space *)&pcs->params.device_n.alt_space;
-
-        return cs_concrete_space(pacs, pis);
+        return cs_concrete_space(pcs->base_space, pis);
     }
     /*
      * DeviceN color spaces are concrete (when not using alt. color space).
@@ -402,8 +335,7 @@
 {
     int code, tcode = 0;
     gs_client_color cc;
-    const gs_color_space *pacs =
-	(const gs_color_space *)&pcs->params.device_n.alt_space;
+    const gs_color_space *pacs = pcs->base_space;
     gs_device_n_map *map = pcs->params.device_n.map;
 
 #ifdef DEBUG
@@ -473,8 +405,7 @@
     }
 #endif
     if (pis->color_component_map.use_alt_cspace) {
-        const gs_color_space *pacs =
-	    (const gs_color_space *)&pcs->params.device_n.alt_space;
+        const gs_color_space *pacs = pcs->base_space;
 
 	return (*pacs->type->remap_concrete_color)
 				(pconc, pacs, pdc, pis, dev, select);
@@ -594,11 +525,12 @@
     code = check_DeviceN_component_names(pcs, pgs);
     if (code < 0)
        return code;
-    pgs->color_space->params.device_n.use_alt_cspace =
+    /* {csrc} was pgs->color_space->params.device_n.use_alt_cspace */
+    ((gs_color_space *)pcs)->params.device_n.use_alt_cspace =
 	using_alt_color_space(pgs);
     if (pcs->params.device_n.use_alt_cspace)
-        code = (*pcs->params.device_n.alt_space.type->install_cspace)
-	((const gs_color_space *) & pcs->params.device_n.alt_space, pgs);
+        code = (pcs->base_space->type->install_cspace)
+	    (pcs->base_space, pgs);
     /*
      * Give the device an opportunity to capture equivalent colors for any
      * spot colors which might be present in the color space.
@@ -616,9 +548,7 @@
     gs_devicen_color_map *  pcmap = &pgs->color_component_map;
 
     if (pcmap->use_alt_cspace)
-        return gx_spot_colors_set_overprint( 
-                   (const gs_color_space *)&pcs->params.device_n.alt_space,
-                   pgs );
+        return gx_spot_colors_set_overprint( pcs->base_space, pgs);
     else {
         gs_overprint_params_t   params;
 
@@ -640,22 +570,17 @@
     }
 }
 
-/* Adjust the reference count of a DeviceN color space. */
+/* Finalize contents of a DeviceN color space. */
 private void
-gx_adjust_cspace_DeviceN(const gs_color_space * pcs, int delta)
+gx_final_DeviceN(const gs_color_space * pcs)
 {
     gs_device_n_attributes * pnextatt, * patt = pcs->params.device_n.colorants;
 
-    rc_adjust_const(pcs->params.device_n.map, delta, "gx_adjust_DeviceN");
-    (*pcs->params.device_n.alt_space.type->adjust_cspace_count)
-	((const gs_color_space *)&pcs->params.device_n.alt_space, delta);
+    rc_decrement_only(pcs->params.device_n.map, "gx_adjust_DeviceN");
     while (patt != NULL) {
-	gs_color_space * pattcs = &(patt->cspace);
-
 	pnextatt = patt->next;
-        (pattcs->type->adjust_cspace_count)
-		((const gs_color_space *)pattcs, delta);
-        rc_adjust_const(patt, delta, "gx_adjust_DeviceN");
+	rc_decrement(patt->cspace, "gx_final_DeviceN");
+        rc_decrement(patt, "gx_adjust_DeviceN");
 	patt = pnextatt;
     }
 }
@@ -688,7 +613,7 @@
     code = sputs(s, (const byte *)&p->names[0], sizeof(p->names[0]) * p->num_components, &n);
     if (code < 0)
 	return code;
-    code = cs_serialize((const gs_color_space *)&p->alt_space, s);
+    code = cs_serialize(pcs->base_space, s);
     if (code < 0)
 	return code;
     return gx_serialize_device_n_map(pcs, p->map, s);

Modified: trunk/gs/src/gscdevn.h
===================================================================
--- trunk/gs/src/gscdevn.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscdevn.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -20,30 +20,20 @@
 #include "gscspace.h"
 
 /*
- * Fill in a DeviceN color space.  Does not include allocation
- * and initialization of the color space.
+ * Construct a new a DeviceN color space.
+ *
  * Note that the client is responsible for memory management of the
  * tint transform Function.
  */
-int gs_build_DeviceN(
-			gs_color_space *pcspace,
-			uint num_components,
-			const gs_color_space *palt_cspace,
-			gs_memory_t *pmem
-			);
-/*
- * Allocate and fill in a DeviceN color space.
- * Note that the client is responsible for memory management of the
- * tint transform Function.
- */
-int gs_cspace_build_DeviceN(
-			       gs_color_space **ppcspace,
-			       gs_separation_name *psnames,
-			       uint num_components,
-			       const gs_color_space *palt_cspace,
-			       gs_memory_t *pmem
-			       );
+int
+gs_cspace_new_DeviceN(
+    gs_color_space **ppcs,
+    uint num_components,
+    gs_color_space *palt_cspace,
+    gs_memory_t *pmem
+    );
 
+
 /* Set the tint transformation procedure for a DeviceN color space. */
 /* VMS limits procedure names to 31 characters, and some systems only */
 /* compare the first 23 characters. */

Modified: trunk/gs/src/gscindex.h
===================================================================
--- trunk/gs/src/gscindex.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscindex.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -44,7 +44,7 @@
  */
 extern int gs_cspace_build_Indexed(
 				   gs_color_space ** ppcspace,
-				   const gs_color_space * pbase_cspace,
+				   gs_color_space * pbase_cspace,
 				   uint num_entries,
 				   const gs_const_string * ptbl,
 				   gs_memory_t * pmem
@@ -64,11 +64,11 @@
 /* Set the lookup procedure to be used for an Indexed color space. */
 extern int gs_cspace_indexed_set_proc(
 				      gs_color_space * pcspace,
-				      int (*proc) (const gs_indexed_params *, int, float *)
+				      int (*proc) (const gs_color_space *, int, float *)
 				      );
 
 /* Look up an index in an Indexed color space. */
-int gs_cspace_indexed_lookup(const gs_indexed_params *, int,
+int gs_cspace_indexed_lookup(const gs_color_space *, int,
 			     gs_client_color *);
 
 #endif /* gscindex_INCLUDED */

Modified: trunk/gs/src/gscolor.c
===================================================================
--- trunk/gs/src/gscolor.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscolor.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -103,11 +103,13 @@
 int
 gs_setgray(gs_state * pgs, floatp gray)
 {
-    gs_color_space      cs;
+    gs_color_space      *pcs;
     int                 code;
 
-    gs_cspace_init_DeviceGray(pgs->memory, &cs);
-    if ((code = gs_setcolorspace(pgs, &cs)) >= 0) {
+    pcs = gs_cspace_new_DeviceGray(pgs->memory);
+    if (pcs == NULL)
+	return_error(gs_error_VMerror);
+    if ((code = gs_setcolorspace(pgs, pcs)) >= 0) {
         gs_client_color *   pcc = pgs->ccolor;
 
         cs_adjust_color_count(pgs, -1); /* not strictly necessary */
@@ -115,6 +117,7 @@
         pcc->pattern = 0;		/* for GC */
         gx_unset_dev_color(pgs);
     }
+    rc_decrement(pcs, "gs_setgray");
     return code;
 }
 
@@ -122,11 +125,13 @@
 int
 gs_setrgbcolor(gs_state * pgs, floatp r, floatp g, floatp b)
 {
-    gs_color_space      cs;
+    gs_color_space      *pcs;
     int                 code;
 
-    gs_cspace_init_DeviceRGB(pgs->memory, &cs);
-    if ((code = gs_setcolorspace(pgs, &cs)) >= 0) {
+    pcs = gs_cspace_new_DeviceRGB(pgs->memory);
+    if (pcs == NULL)
+	return_error(gs_error_VMerror);
+    if ((code = gs_setcolorspace(pgs, pcs)) >= 0) {
        gs_client_color *    pcc = pgs->ccolor;
 
         cs_adjust_color_count(pgs, -1); /* not strictly necessary */
@@ -136,6 +141,7 @@
         pcc->pattern = 0;		/* for GC */
         gx_unset_dev_color(pgs);
     }
+    rc_decrement(pcs, "gs_setrgbcolor");
     return code;
 }
 
@@ -206,12 +212,17 @@
 void
 gx_set_device_color_1(gs_state * pgs)
 {
-    gs_color_space  cs;
+    gs_color_space  *pcs;
 
     gs_setoverprint(pgs, false);
     gs_setoverprintmode(pgs, 0);
-    gs_cspace_init_DeviceGray(pgs->memory, &cs);
-    gs_setcolorspace(pgs, &cs);
+    pcs = gs_cspace_new_DeviceGray(pgs->memory);
+    if (pcs) {
+	gs_setcolorspace(pgs, pcs);
+	rc_decrement_only(pcs, "gx_set_device_color_1");
+    } else {
+	/* {csrc} really need to signal an error here */
+    }
     set_nonclient_dev_color(pgs->dev_color, 1);
     pgs->log_op = lop_default;
     /*

Modified: trunk/gs/src/gscolor1.c
===================================================================
--- trunk/gs/src/gscolor1.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscolor1.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -41,11 +41,13 @@
 int
 gs_setcmykcolor(gs_state * pgs, floatp c, floatp m, floatp y, floatp k)
 {
-    gs_color_space      cs;
+    gs_color_space      *pcs;
     int                 code;
 
-    gs_cspace_init_DeviceCMYK(pgs->memory, &cs);
-    if ((code = gs_setcolorspace(pgs, &cs)) >= 0) {
+    pcs = gs_cspace_new_DeviceCMYK(pgs->memory);
+    if (pcs == NULL)
+	return_error(gs_error_VMerror);
+    if ((code = gs_setcolorspace(pgs, pcs)) >= 0) {
        gs_client_color *    pcc = pgs->ccolor;
 
         cs_adjust_color_count(pgs, -1); /* not strictly necessary */
@@ -56,6 +58,7 @@
         pcc->pattern = 0;		/* for GC */
         gx_unset_dev_color(pgs);
     }
+    rc_decrement_only(pcs, "gs_setcmykcolor");
     return code;
 }
 

Modified: trunk/gs/src/gscolor2.c
===================================================================
--- trunk/gs/src/gscolor2.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscolor2.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -29,29 +29,30 @@
 
 /* setcolorspace */
 int
-gs_setcolorspace(gs_state * pgs, const gs_color_space * pcs)
+gs_setcolorspace(gs_state * pgs, gs_color_space * pcs)
 {
     int             code = 0;
-    gs_color_space  cs_old = *pgs->color_space;
+    gs_color_space  *cs_old = pgs->color_space;
     gs_client_color cc_old = *pgs->ccolor;
 
     if (pgs->in_cachedevice)
 	return_error(gs_error_undefined);
 
     if (pcs->id != pgs->color_space->id) {
-        pcs->type->adjust_cspace_count(pcs, 1);
-        *pgs->color_space = *pcs;
+        rc_increment(pcs);
+        pgs->color_space = pcs;
         if ( (code = pcs->type->install_cspace(pcs, pgs)) < 0          ||
               (pgs->overprint && (code = gs_do_set_overprint(pgs)) < 0)  ) {
-            *pgs->color_space = cs_old;
-            pcs->type->adjust_cspace_count(pcs, -1);
-        } else
-            cs_old.type->adjust_cspace_count(&cs_old, -1);
+            pgs->color_space = cs_old;
+            rc_decrement_only(pcs, "gs_setcolorspace");
+        } else {
+	    cs_old->type->adjust_color_count(&cc_old, cs_old, -1);
+	    rc_decrement_only(cs_old, "gs_setcolorspace");
+	}
     }
 
     if (code >= 0) {
         cs_full_init_color(pgs->ccolor, pcs);
-        cs_old.type->adjust_color_count(&cc_old, &cs_old, -1);
         gx_unset_dev_color(pgs);
     }
 
@@ -59,7 +60,7 @@
 }
 
 /* currentcolorspace */
-const gs_color_space *
+gs_color_space *
 gs_currentcolorspace(const gs_state * pgs)
 {
     return pgs->color_space;
@@ -97,10 +98,10 @@
 
 /* Define a lookup_index procedure that just returns the map values. */
 int
-lookup_indexed_map(const gs_indexed_params * params, int index, float *values)
+lookup_indexed_map(const gs_color_space * pcs, int index, float *values)
 {
-    int m = cs_num_components((const gs_color_space *)&params->base_space);
-    const float *pv = &params->lookup.map->values[index * m];
+    int m = cs_num_components(pcs->base_space);
+    const float *pv = &pcs->params.indexed.lookup.map->values[index * m];
 
     memcpy(values, pv, sizeof(*values) * m);
     return 0;
@@ -144,30 +145,28 @@
 
 /* ---------------- Indexed color spaces ---------------- */
 
-gs_private_st_composite(st_color_space_Indexed, gs_paint_color_space,
+gs_private_st_composite(st_color_space_Indexed, gs_color_space,
      "gs_color_space_Indexed", cs_Indexed_enum_ptrs, cs_Indexed_reloc_ptrs);
 
 /* ------ Color space ------ */
 
 /* Define the Indexed color space type. */
-private cs_proc_base_space(gx_base_space_Indexed);
 private cs_proc_restrict_color(gx_restrict_Indexed);
 private cs_proc_concrete_space(gx_concrete_space_Indexed);
 private cs_proc_concretize_color(gx_concretize_Indexed);
 private cs_proc_install_cspace(gx_install_Indexed);
 private cs_proc_set_overprint(gx_set_overprint_Indexed);
-private cs_proc_adjust_cspace_count(gx_adjust_cspace_Indexed);
+private cs_proc_final(gx_final_Indexed);
 private cs_proc_serialize(gx_serialize_Indexed);
 const gs_color_space_type gs_color_space_type_Indexed = {
     gs_color_space_index_Indexed, false, false,
     &st_color_space_Indexed, gx_num_components_1,
-    gx_base_space_Indexed,
     gx_init_paint_1, gx_restrict_Indexed,
     gx_concrete_space_Indexed,
     gx_concretize_Indexed, NULL,
     gx_default_remap_color, gx_install_Indexed,
     gx_set_overprint_Indexed,
-    gx_adjust_cspace_Indexed, gx_no_adjust_color_count,
+    gx_final_Indexed, gx_no_adjust_color_count,
     gx_serialize_Indexed,
     gx_cspace_is_linear_default
 };
@@ -177,18 +176,10 @@
 private uint
 indexed_table_size(const gs_color_space *pcs)
 {
-    return (pcs->params.indexed.hival + 1) *
-	cs_num_components((const gs_color_space *)
-			  &pcs->params.indexed.base_space);
-
+    return (pcs->params.indexed.hival + 1) * pcs->params.indexed.n_comps;
 }
 private 
-ENUM_PTRS_WITH(cs_Indexed_enum_ptrs, gs_color_space *pcs)
-{
-    return ENUM_USING(*pcs->params.indexed.base_space.type->stype,
-		      &pcs->params.indexed.base_space,
-		      sizeof(pcs->params.indexed.base_space), index - 1);
-}
+ENUM_PTRS_WITH(cs_Indexed_enum_ptrs, gs_color_space *pcs) return 0;
 case 0:
 if (pcs->params.indexed.use_proc)
     ENUM_RETURN((void *)pcs->params.indexed.lookup.map);
@@ -198,9 +189,6 @@
 ENUM_PTRS_END
 private RELOC_PTRS_WITH(cs_Indexed_reloc_ptrs, gs_color_space *pcs)
 {
-    RELOC_USING(*pcs->params.indexed.base_space.type->stype,
-		&pcs->params.indexed.base_space,
-		sizeof(gs_base_color_space));
     if (pcs->params.indexed.use_proc)
 	RELOC_PTR(gs_color_space, params.indexed.lookup.map);
     else {
@@ -214,21 +202,14 @@
 }
 RELOC_PTRS_END
 
-/* Return the base space of an Indexed color space. */
-private const gs_color_space *
-gx_base_space_Indexed(const gs_color_space * pcs)
-{
-    return (const gs_color_space *)&(pcs->params.indexed.base_space);
-}
 
+/* Color space installation for an Indexed color space. */
 
-/* Color space installation ditto. */
-
 private int
 gx_install_Indexed(const gs_color_space * pcs, gs_state * pgs)
 {
-    return (*pcs->params.indexed.base_space.type->install_cspace)
-	((const gs_color_space *) & pcs->params.indexed.base_space, pgs);
+    return (*pcs->base_space->type->install_cspace)
+	((const gs_color_space *) pcs->base_space, pgs);
 }
 
 /* Color space overprint setting ditto. */
@@ -236,21 +217,19 @@
 private int
 gx_set_overprint_Indexed(const gs_color_space * pcs, gs_state * pgs)
 {
-    return (*pcs->params.indexed.base_space.type->set_overprint)
-	((const gs_color_space *)&pcs->params.indexed.base_space, pgs);
+    return (*pcs->base_space->type->set_overprint)
+	((const gs_color_space *)pcs->base_space, pgs);
 }
 
-/* Color space reference count adjustment ditto. */
+/* Color space finalization ditto. */
 
 private void
-gx_adjust_cspace_Indexed(const gs_color_space * pcs, int delta)
+gx_final_Indexed(const gs_color_space * pcs)
 {
     if (pcs->params.indexed.use_proc) {
-	rc_adjust_const(pcs->params.indexed.lookup.map, delta,
+	rc_adjust_const(pcs->params.indexed.lookup.map, -1,
 			"gx_adjust_Indexed");
     }
-    (*pcs->params.indexed.base_space.type->adjust_cspace_count)
-	((const gs_color_space *)&pcs->params.indexed.base_space, delta);
 }
 
 /*
@@ -262,16 +241,16 @@
  * do not range-check their input values.
  */
 private int
-map_palette_entry_1(const gs_indexed_params * params, int indx, float *values)
+map_palette_entry_1(const gs_color_space * pcs, int indx, float *values)
 {
-    values[0] = params->lookup.map->values[indx];
+    values[0] = pcs->params.indexed.lookup.map->values[indx];
     return 0;
 }
 
 private int
-map_palette_entry_3(const gs_indexed_params * params, int indx, float *values)
+map_palette_entry_3(const gs_color_space * pcs, int indx, float *values)
 {
-    const float *pv = &(params->lookup.map->values[3 * indx]);
+    const float *pv = &(pcs->params.indexed.lookup.map->values[3 * indx]);
 
     values[0] = pv[0];
     values[1] = pv[1];
@@ -280,9 +259,9 @@
 }
 
 private int
-map_palette_entry_4(const gs_indexed_params * params, int indx, float *values)
+map_palette_entry_4(const gs_color_space * pcs, int indx, float *values)
 {
-    const float *pv = &(params->lookup.map->values[4 * indx]);
+    const float *pv = &(pcs->params.indexed.lookup.map->values[4 * indx]);
 
     values[0] = pv[0];
     values[1] = pv[1];
@@ -292,12 +271,12 @@
 }
 
 private int
-map_palette_entry_n(const gs_indexed_params * params, int indx, float *values)
+map_palette_entry_n(const gs_color_space * pcs, int indx, float *values)
 {
-    int m = cs_num_components((const gs_color_space *)&params->base_space);
+    int m = cs_num_components(pcs->base_space);
 
     memcpy((void *)values,
-	   (const void *)(params->lookup.map->values + indx * m),
+	   (const void *)(pcs->params.indexed.lookup.map->values + indx * m),
 	   m * sizeof(float)
     );
 
@@ -339,7 +318,7 @@
 int
 gs_cspace_build_Indexed(
 			   gs_color_space ** ppcspace,
-			   const gs_color_space * pbase_cspace,
+			   gs_color_space * pbase_cspace,
 			   uint num_entries,
 			   const gs_const_string * ptbl,
 			   gs_memory_t * pmem
@@ -347,14 +326,13 @@
 {
     gs_color_space *pcspace = 0;
     gs_indexed_params *pindexed = 0;
-    int code;
 
     if ((pbase_cspace == 0) || !pbase_cspace->type->can_be_base_space)
 	return_error(gs_error_rangecheck);
 
-    code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Indexed, pmem);
-    if (code < 0)
-	return code;
+    pcspace = gs_cspace_alloc(pmem, &gs_color_space_type_Indexed);
+    if (pcspace == NULL)
+	return_error(gs_error_VMerror);
     pindexed = &(pcspace->params.indexed);
     if (ptbl == 0) {
 	pindexed->lookup.map =
@@ -368,9 +346,10 @@
 	pindexed->lookup.table = *ptbl;
 	pindexed->use_proc = false;
     }
-    gs_cspace_init_from((gs_color_space *) & (pindexed->base_space),
-			pbase_cspace);
+    pcspace->base_space = pbase_cspace;
+    rc_increment(pbase_cspace);
     pindexed->hival = num_entries - 1;
+    pindexed->n_comps = cs_num_components(pbase_cspace);
     *ppcspace = pcspace;
     return 0;
 }
@@ -407,7 +386,7 @@
 int
 gs_cspace_indexed_set_proc(
 			   gs_color_space * pcspace,
-			   int (*proc)(const gs_indexed_params *, int, float *)
+			   int (*proc)(const gs_color_space *, int, float *)
 )
 {
     if ((gs_color_space_get_index(pcspace) != gs_color_space_index_Indexed) ||
@@ -437,10 +416,7 @@
 gx_concrete_space_Indexed(const gs_color_space * pcs,
 			  const gs_imager_state * pis)
 {
-    const gs_color_space *pbcs =
-    (const gs_color_space *)&pcs->params.indexed.base_space;
-
-    return cs_concrete_space(pbcs, pis);
+    return cs_concrete_space(pcs->base_space, pis);
 }
 
 private int
@@ -453,9 +429,9 @@
 	 value >= pcs->params.indexed.hival ? pcs->params.indexed.hival :
 	 (int)value);
     const gs_color_space *pbcs =
-	(const gs_color_space *)&pcs->params.indexed.base_space;
+	(const gs_color_space *)pcs->base_space;
     gs_client_color cc;
-    int code = gs_cspace_indexed_lookup(&pcs->params.indexed, index, &cc);
+    int code = gs_cspace_indexed_lookup(pcs, index, &cc);
 
     if (code < 0)
 	return code;
@@ -464,14 +440,15 @@
 
 /* Look up an index in an Indexed color space. */
 int
-gs_cspace_indexed_lookup(const gs_indexed_params *pip, int index,
+gs_cspace_indexed_lookup(const gs_color_space *pcs, int index,
 			 gs_client_color *pcc)
 {
+    const gs_indexed_params *pip = &pcs->params.indexed;
     if (pip->use_proc) {
 	return pip->lookup.map->proc.lookup_index
-	    (pip, index, &pcc->paint.values[0]);
+	    (pcs, index, &pcc->paint.values[0]);
     } else {
-	const gs_color_space *pbcs = (const gs_color_space *)&pip->base_space;
+	const gs_color_space *pbcs = pcs->base_space;
 	int m = cs_num_components(pbcs);
 	const byte *pcomp = pip->lookup.table.data + m * index;
 
@@ -507,7 +484,7 @@
 
     if (code < 0)
 	return code;
-    code = cs_serialize((const gs_color_space *)&p->base_space, s);
+    code = cs_serialize(pcs->base_space, s);
     if (code < 0)
 	return code;
     code = sputs(s, (const byte *)&p->hival, sizeof(p->hival), &n);

Modified: trunk/gs/src/gscolor2.h
===================================================================
--- trunk/gs/src/gscolor2.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscolor2.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -30,8 +30,8 @@
  */
 
 /* General color routines */
-const gs_color_space *gs_currentcolorspace(const gs_state *);
-int gs_setcolorspace(gs_state *, const gs_color_space *);
+gs_color_space *gs_currentcolorspace(const gs_state *);
+int gs_setcolorspace(gs_state *, gs_color_space *);
 const gs_client_color *gs_currentcolor(const gs_state *);
 int gs_setcolor(gs_state *, const gs_client_color *);
 

Modified: trunk/gs/src/gscolor3.c
===================================================================
--- trunk/gs/src/gscolor3.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscolor3.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -60,7 +60,7 @@
     gx_path cpath;
     gs_matrix imat;
     gs_client_color cc;
-    gs_color_space cs;
+    gs_color_space *pcs;
     gx_device_color devc;
     int code;
 
@@ -74,10 +74,13 @@
     code = gs_pattern2_set_shfill(&cc);
     if (code < 0)
 	return code;
-    gs_cspace_init(&cs, &gs_color_space_type_Pattern, pgs->memory, false);
-    cs.params.pattern.has_base_space = false;
-    code = cs.type->remap_color(&cc, &cs, &devc, (gs_imager_state *)pgs,
-				pgs->device, gs_color_select_texture);
+    pcs = gs_cspace_alloc(pgs->memory, &gs_color_space_type_Pattern);
+    if (pcs == NULL)
+	return_error(gs_error_VMerror);
+
+    pcs->params.pattern.has_base_space = false;
+    code = pcs->type->remap_color(&cc, pcs, &devc, (gs_imager_state *)pgs,
+				  pgs->device, gs_color_select_texture);
     if (code >= 0) {
 	gx_path_init_local(&cpath, pgs->memory);
 	code = gx_cpath_to_path(pgs->clip_path, &cpath);
@@ -86,6 +89,7 @@
 				pgs->fill_adjust.x, pgs->fill_adjust.y);
 	gx_path_free(&cpath, "gs_shfill");
     }
+    rc_decrement(pcs, "gs_shfill");
     gs_pattern_reference(&cc, -1);
     return code;
 }

Modified: trunk/gs/src/gscpixel.c
===================================================================
--- trunk/gs/src/gscpixel.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscpixel.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -34,21 +34,22 @@
 private const gs_color_space_type gs_color_space_type_DevicePixel = {
     gs_color_space_index_DevicePixel, true, false,
     &st_base_color_space, gx_num_components_1,
-    gx_no_base_space,
     gx_init_paint_1, gx_restrict_DevicePixel,
     gx_same_concrete_space,
     gx_concretize_DevicePixel, gx_remap_concrete_DevicePixel,
     gx_default_remap_color, gx_no_install_cspace,
     gx_set_overprint_DevicePixel,
-    gx_no_adjust_cspace_count, gx_no_adjust_color_count,
+    NULL, gx_no_adjust_color_count,
     gx_serialize_DevicePixel,
     gx_cspace_is_linear_default
 };
 
-/* Initialize a DevicePixel color space. */
+/* Create a DevicePixel color space. */
 int
-gs_cspace_init_DevicePixel(gs_memory_t *mem, gs_color_space * pcs, int depth)
+gs_cspace_new_DevicePixel(gs_memory_t *mem, gs_color_space **ppcs, int depth)
 {
+    gs_color_space *pcs;
+
     switch (depth) {
 	case 1:
 	case 2:
@@ -61,8 +62,11 @@
 	default:
 	    return_error(gs_error_rangecheck);
     }
-    gs_cspace_init(pcs, &gs_color_space_type_DevicePixel, mem, false);
+    pcs = gs_cspace_alloc(mem, &gs_color_space_type_DevicePixel);
+    if (pcs == NULL)
+	return_error(gs_error_VMerror);
     pcs->params.pixel.depth = depth;
+    *ppcs = pcs;
     return 0;
 }
 

Modified: trunk/gs/src/gscpixel.h
===================================================================
--- trunk/gs/src/gscpixel.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscpixel.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -18,7 +18,8 @@
 #ifndef gscpixel_INCLUDED
 #  define gscpixel_INCLUDED
 
-/* Initialize a DevicePixel color space. */
-int gs_cspace_init_DevicePixel(gs_memory_t *mem, gs_color_space * pcs, int depth);
+/* Construct a new DevicePixel color space. */
+int gs_cspace_new_DevicePixel(gs_memory_t *mem, gs_color_space **ppcs,
+			      int depth);
 
 #endif /* gscpixel_INCLUDED */

Modified: trunk/gs/src/gscscie.c
===================================================================
--- trunk/gs/src/gscscie.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscscie.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -40,87 +40,81 @@
 /* Define the CIE color space types. */
 
 /* CIEBasedDEFG */
-gs_private_st_ptrs1(st_color_space_CIEDEFG, gs_base_color_space,
+gs_private_st_ptrs1(st_color_space_CIEDEFG, gs_color_space,
      "gs_color_space(CIEDEFG)", cs_CIEDEFG_enum_ptrs, cs_CIEDEFG_reloc_ptrs,
 		    params.defg);
-private cs_proc_adjust_cspace_count(gx_adjust_cspace_CIEDEFG);
+private cs_proc_final(gx_final_CIEDEFG);
 private cs_proc_serialize(gx_serialize_CIEDEFG);
 const gs_color_space_type gs_color_space_type_CIEDEFG = {
     gs_color_space_index_CIEDEFG, true, true,
     &st_color_space_CIEDEFG, gx_num_components_4,
-    gx_no_base_space,
     gx_init_CIE, gx_restrict_CIEDEFG,
     gx_concrete_space_CIE,
     gx_concretize_CIEDEFG, NULL,
     gx_default_remap_color, gx_install_CIE,
     gx_spot_colors_set_overprint,
-    gx_adjust_cspace_CIEDEFG, gx_no_adjust_color_count,
+    gx_final_CIEDEFG, gx_no_adjust_color_count,
     gx_serialize_CIEDEFG,
     gx_cspace_is_linear_default
 };
 
 /* CIEBasedDEF */
-gs_private_st_ptrs1(st_color_space_CIEDEF, gs_base_color_space,
+gs_private_st_ptrs1(st_color_space_CIEDEF, gs_color_space,
 	"gs_color_space(CIEDEF)", cs_CIEDEF_enum_ptrs, cs_CIEDEF_reloc_ptrs,
 		    params.def);
-private cs_proc_adjust_cspace_count(gx_adjust_cspace_CIEDEF);
+private cs_proc_final(gx_final_CIEDEF);
 private cs_proc_serialize(gx_serialize_CIEDEF);
 const gs_color_space_type gs_color_space_type_CIEDEF = {
     gs_color_space_index_CIEDEF, true, true,
     &st_color_space_CIEDEF, gx_num_components_3,
-    gx_no_base_space,
     gx_init_CIE, gx_restrict_CIEDEF,
     gx_concrete_space_CIE,
     gx_concretize_CIEDEF, NULL,
     gx_default_remap_color, gx_install_CIE,
     gx_spot_colors_set_overprint,
-    gx_adjust_cspace_CIEDEF, gx_no_adjust_color_count,
+    gx_final_CIEDEF, gx_no_adjust_color_count,
     gx_serialize_CIEDEF,
     gx_cspace_is_linear_default
 };
 
 /* CIEBasedABC */
-gs_private_st_ptrs1(st_color_space_CIEABC, gs_base_color_space,
+gs_private_st_ptrs1(st_color_space_CIEABC, gs_color_space,
 	"gs_color_space(CIEABC)", cs_CIEABC_enum_ptrs, cs_CIEABC_reloc_ptrs,
 		    params.abc);
-private cs_proc_adjust_cspace_count(gx_adjust_cspace_CIEABC);
+private cs_proc_final(gx_final_CIEABC);
 private cs_proc_serialize(gx_serialize_CIEABC);
 const gs_color_space_type gs_color_space_type_CIEABC = {
     gs_color_space_index_CIEABC, true, true,
     &st_color_space_CIEABC, gx_num_components_3,
-    gx_no_base_space,
     gx_init_CIE, gx_restrict_CIEABC,
     gx_concrete_space_CIE,
     gx_concretize_CIEABC, NULL,
     gx_remap_CIEABC, gx_install_CIE,
     gx_spot_colors_set_overprint,
-    gx_adjust_cspace_CIEABC, gx_no_adjust_color_count,
+    gx_final_CIEABC, gx_no_adjust_color_count,
     gx_serialize_CIEABC,
     gx_cspace_is_linear_default
 };
 
 /* CIEBasedA */
-gs_private_st_ptrs1(st_color_space_CIEA, gs_base_color_space,
+gs_private_st_ptrs1(st_color_space_CIEA, gs_color_space,
 	      "gs_color_space(CIEA)", cs_CIEA_enum_ptrs, cs_CIEA_reloc_ptrs,
 		    params.a);
-private cs_proc_adjust_cspace_count(gx_adjust_cspace_CIEA);
+private cs_proc_final(gx_final_CIEA);
 private cs_proc_serialize(gx_serialize_CIEA);
 const gs_color_space_type gs_color_space_type_CIEA = {
     gs_color_space_index_CIEA, true, true,
     &st_color_space_CIEA, gx_num_components_1,
-    gx_no_base_space,
     gx_init_CIE, gx_restrict_CIEA,
     gx_concrete_space_CIE,
     gx_concretize_CIEA, NULL,
     gx_default_remap_color, gx_install_CIE,
     gx_spot_colors_set_overprint,
-    gx_adjust_cspace_CIEA, gx_no_adjust_color_count,
+    gx_final_CIEA, gx_no_adjust_color_count,
     gx_serialize_CIEA,
     gx_cspace_is_linear_default
 };
 
-private gs_color_space rgb_cs, cmyk_cs;
-
 /* Determine the concrete space underlying a CIEBased space. */
 const gs_color_space *
 gx_concrete_space_CIE(const gs_color_space * pcs, const gs_imager_state * pis)
@@ -130,11 +124,9 @@
     if (pcie == 0 || pcie->RenderTable.lookup.table == 0 ||
 	pcie->RenderTable.lookup.m == 3
 	) {
-	gs_cspace_init_DeviceRGB(pis->memory, &rgb_cs);  /* idempotent initialization */
-        return &rgb_cs;
+	return pis->devicergb_cs;
     } else {			/* pcie->RenderTable.lookup.m == 4 */
-	gs_cspace_init_DeviceCMYK(pis->memory, &cmyk_cs); /* idempotent initialization */
-	return &cmyk_cs;
+	return pis->devicecmyk_cs;
     }
 }
 
@@ -148,29 +140,31 @@
     return (*pcs->params.a->common.install_cspace) (pcs, pgs);
 }
 
-/* Adjust reference counts for a CIE color space */
+/* Free params for a CIE color space */
 private void
-gx_adjust_cspace_CIEDEFG(const gs_color_space * pcs, int delta)
+gx_final_CIEDEFG(const gs_color_space * pcs)
 {
-    rc_adjust_const(pcs->params.defg, delta, "gx_adjust_cspace_CIEDEFG");
+    rc_adjust_const(pcs->params.defg, -1, "gx_adjust_cspace_CIEDEFG");
 }
 
 private void
-gx_adjust_cspace_CIEDEF(const gs_color_space * pcs, int delta)
+gx_final_CIEDEF(const gs_color_space * pcs)
 {
-    rc_adjust_const(pcs->params.def, delta, "gx_adjust_cspace_CIEDEF");
+    rc_adjust_const(pcs->params.def, -1, "gx_adjust_cspace_CIEDEF");
 }
 
 private void
-gx_adjust_cspace_CIEABC(const gs_color_space * pcs, int delta)
+gx_final_CIEABC(const gs_color_space * pcs)
 {
-    rc_adjust_const(pcs->params.abc, delta, "gx_adjust_cspace_CIEABC");
+    rc_adjust_const(pcs->params.abc, -1, "gx_adjust_cspace_CIEABC");
 }
 
 private void
-gx_adjust_cspace_CIEA(const gs_color_space * pcs, int delta)
+gx_final_CIEA(const gs_color_space * pcs)
 {
-    rc_adjust_const(pcs->params.a, delta, "gx_adjust_cspace_CIEA");
+    /* {csrc} debug */
+    dlprintf3("%08x %d += %d\n", pcs->params.a, pcs->params.a->rc.ref_count, -1);
+    rc_adjust_const(pcs->params.a, -1, "gx_adjust_cspace_CIEA");
 }
 
 /* ---------------- Procedures ---------------- */
@@ -240,12 +234,11 @@
 		const gs_color_space_type * pcstype,
 		gs_memory_type_ptr_t stype, gs_memory_t * pmem)
 {
-    gs_color_space *pcspace;
-    int code = gs_cspace_alloc(&pcspace, pcstype, pmem);
+    gs_color_space *pcspace = gs_cspace_alloc(pmem, pcstype);
     gs_cie_common_elements_t *pdata;
 
-    if (code < 0)
-	return 0;
+    if (pcspace == NULL)
+	return NULL;
     rc_alloc_struct_1(pdata, gs_cie_common_elements_t, stype, pmem,
 		      {
 		      gs_free_object(pmem, pcspace, "gx_build_cie_space");

Modified: trunk/gs/src/gscsepr.c
===================================================================
--- trunk/gs/src/gscsepr.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscsepr.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -33,12 +33,11 @@
 
 /* ---------------- Color space ---------------- */
 
-gs_private_st_composite(st_color_space_Separation, gs_paint_color_space,
+gs_private_st_composite(st_color_space_Separation, gs_color_space,
 			"gs_color_space_Separation",
 			cs_Separation_enum_ptrs, cs_Separation_reloc_ptrs);
 
 /* Define the Separation color space type. */
-private cs_proc_base_space(gx_alt_space_Separation);
 private cs_proc_init_color(gx_init_Separation);
 private cs_proc_concrete_space(gx_concrete_space_Separation);
 private cs_proc_concretize_color(gx_concretize_Separation);
@@ -46,18 +45,17 @@
 private cs_proc_remap_color(gx_remap_Separation);
 private cs_proc_install_cspace(gx_install_Separation);
 private cs_proc_set_overprint(gx_set_overprint_Separation);
-private cs_proc_adjust_cspace_count(gx_adjust_cspace_Separation);
+private cs_proc_final(gx_final_Separation);
 private cs_proc_serialize(gx_serialize_Separation);
 const gs_color_space_type gs_color_space_type_Separation = {
     gs_color_space_index_Separation, true, false,
     &st_color_space_Separation, gx_num_components_1,
-    gx_alt_space_Separation,
     gx_init_Separation, gx_restrict01_paint_1,
     gx_concrete_space_Separation,
     gx_concretize_Separation, gx_remap_concrete_Separation,
     gx_remap_Separation, gx_install_Separation,
     gx_set_overprint_Separation,
-    gx_adjust_cspace_Separation, gx_no_adjust_color_count,
+    gx_final_Separation, gx_no_adjust_color_count,
     gx_serialize_Separation,
     gx_cspace_is_linear_default
 };
@@ -65,32 +63,15 @@
 /* GC procedures */
 
 private 
-ENUM_PTRS_WITH(cs_Separation_enum_ptrs, gs_color_space *pcs)
-{
-    return ENUM_USING(*pcs->params.separation.alt_space.type->stype,
-		      &pcs->params.separation.alt_space,
-		      sizeof(pcs->params.separation.alt_space), index - 1);
-}
-ENUM_PTR(0, gs_color_space, params.separation.map);
+ENUM_PTRS_BEGIN(cs_Separation_enum_ptrs) return 0;
+    ENUM_PTR(0, gs_color_space, params.separation.map);
 ENUM_PTRS_END
-private RELOC_PTRS_WITH(cs_Separation_reloc_ptrs, gs_color_space *pcs)
+private RELOC_PTRS_BEGIN(cs_Separation_reloc_ptrs)
 {
     RELOC_PTR(gs_color_space, params.separation.map);
-    RELOC_USING(*pcs->params.separation.alt_space.type->stype,
-		&pcs->params.separation.alt_space,
-		sizeof(gs_base_color_space));
 }
 RELOC_PTRS_END
 
-/* Get the alternate space for a Separation space. */
-private const gs_color_space *
-gx_alt_space_Separation(const gs_color_space * pcs)
-{
-    return pcs->params.separation.use_alt_cspace
-	   ? (const gs_color_space *)&(pcs->params.separation.alt_space)
-    	   : NULL;
-}
-
 /* Get the concrete space for a Separation space. */
 private const gs_color_space *
 gx_concrete_space_Separation(const gs_color_space * pcs,
@@ -108,10 +89,7 @@
      * Check if we are using the alternate color space.
      */
     if (pis->color_component_map.use_alt_cspace) {
-        const gs_color_space *pacs =
-	    (const gs_color_space *)&pcs->params.separation.alt_space;
-
-        return cs_concrete_space(pacs, pis);
+        return cs_concrete_space(pcs->base_space, pis);
     }
     /*
      * Separation color spaces are concrete (when not using alt. color space).
@@ -155,8 +133,8 @@
     pgs->color_space->params.separation.use_alt_cspace =
 	using_alt_color_space(pgs);
     if (pgs->color_space->params.separation.use_alt_cspace)
-        code = (*pcs->params.separation.alt_space.type->install_cspace)
-	((const gs_color_space *) & pcs->params.separation.alt_space, pgs);
+        code = (pcs->base_space->type->install_cspace)
+	    (pcs->base_space, pgs);
     /*
      * Give the device an opportunity to capture equivalent colors for any
      * spot colors which might be present in the color space.
@@ -174,9 +152,7 @@
     gs_devicen_color_map *  pcmap = &pgs->color_component_map;
 
     if (pcmap->use_alt_cspace)
-        return gx_spot_colors_set_overprint( 
-                   (const gs_color_space *)&pcs->params.separation.alt_space,
-                   pgs );
+        return gx_spot_colors_set_overprint( pcs->base_space, pgs );
     else {
         gs_overprint_params_t   params;
 
@@ -198,77 +174,46 @@
     }
 }
 
-/* Adjust the reference count of a Separation color space. */
+/* Finalize contents of a Separation color space. */
 private void
-gx_adjust_cspace_Separation(const gs_color_space * pcs, int delta)
+gx_final_Separation(const gs_color_space * pcs)
 {
-    rc_adjust_const(pcs->params.separation.map, delta,
+    rc_adjust_const(pcs->params.separation.map, -1,
 		    "gx_adjust_Separation");
-    (*pcs->params.separation.alt_space.type->adjust_cspace_count)
-	((const gs_color_space *)&pcs->params.separation.alt_space, delta);
 }
 
 /* ------ Constructors/accessors ------ */
 
 /*
- * Build a separation color space.
+ * Construct a new separation color space.
  */
 int
-gs_build_Separation(
-		    gs_color_space * pcspace,
-		    const gs_color_space * palt_cspace,
-		    gs_memory_t * pmem
+gs_cspace_new_Separation(
+    gs_color_space **ppcs,
+    gs_color_space * palt_cspace,
+    gs_memory_t * pmem
 )
 {
-    gs_separation_params * pcssepr = &pcspace->params.separation;
+    gs_color_space *pcs;
     int code;
 
     if (palt_cspace == 0 || !palt_cspace->type->can_be_alt_space)
 	return_error(gs_error_rangecheck);
 
-    code = alloc_device_n_map(&pcssepr->map, pmem, "gs_cspace_build_Separation");
-    if (pcssepr->map == NULL) {
-	gs_free_object(pmem, pcspace, "gs_cspace_build_Separation");
+    pcs = gs_cspace_alloc(pmem, &gs_color_space_type_Separation);
+    if (pcs == NULL)
 	return_error(gs_error_VMerror);
-    }
-    return 0;
-}
+    pcs->params.separation.map = NULL;
 
-/*
- * Build a separation color space.
- *
- * The values array provided with separation color spaces is actually cached
- * information, but filled in by the client. The alternative space is the
- * color space in which the tint procedure will provide alternative colors.
- */
-int
-gs_cspace_build_Separation(
-			      gs_color_space ** ppcspace,
-			      gs_separation_name sname,
-			      const gs_color_space * palt_cspace,
-			      int cache_size,
-			      gs_memory_t * pmem
-)
-{
-    gs_color_space *pcspace = NULL;
-    gs_separation_params *pcssepr = NULL;
-    int code;
-
-    if (palt_cspace == 0 || !palt_cspace->type->can_be_alt_space)
-	return_error(gs_error_rangecheck);
-
-    code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Separation, pmem);
-    if (code < 0)
-	return code;
- 
-    code = gs_build_Separation(pcspace, palt_cspace, pmem);
+    code = alloc_device_n_map(&pcs->params.separation.map, pmem,
+			      "gs_cspace_build_Separation");
     if (code < 0) {
-	gs_free_object(pmem, pcspace, "gs_cspace_build_Separation");
-	return code;
+	gs_free_object(pmem, pcs, "gs_cspace_build_Separation");
+	return_error(code);
     }
-    pcssepr->sep_name = sname;
-    gs_cspace_init_from((gs_color_space *) & pcssepr->alt_space, palt_cspace);
-    *ppcspace = pcspace;
+    pcs->base_space = palt_cspace;
+    rc_increment(palt_cspace);
+    *ppcs = pcs;
     return 0;
 }
 
@@ -309,8 +254,7 @@
 
     if (gs_color_space_get_index(pcspace) != gs_color_space_index_Separation ||
 	pfn->params.m != 1 || pfn->params.n !=
-	  gs_color_space_num_components((const gs_color_space *)
-					&pcspace->params.separation.alt_space)
+	  gs_color_space_num_components(pcspace->base_space)
 	)
 	return_error(gs_error_rangecheck);
     pimap = pcspace->params.separation.map;
@@ -370,8 +314,7 @@
     float ftemp;
     int code;
     gs_client_color cc;
-    const gs_color_space *pacs =
-	(const gs_color_space *)&pcs->params.separation.alt_space;
+    const gs_color_space *pacs = pcs->base_space;
     
     if (pcs->params.separation.sep_type == SEP_OTHER &&
 	pcs->params.separation.use_alt_cspace) {
@@ -418,8 +361,7 @@
     }
 #endif
     if (pis->color_component_map.use_alt_cspace) {
-        const gs_color_space *pacs =
-	    (const gs_color_space *)&pcs->params.separation.alt_space;
+        const gs_color_space *pacs = pcs->base_space;
 
 	return (*pacs->type->remap_concrete_color)
 				(pconc, pacs, pdc, pis, dev, select);
@@ -538,7 +480,7 @@
     code = sputs(s, (const byte *)&p->sep_name, sizeof(p->sep_name), &n);
     if (code < 0)
 	return code;
-    code = cs_serialize((const gs_color_space *)&p->alt_space, s);
+    code = cs_serialize(pcs->base_space, s);
     if (code < 0)
 	return code;
     code = gx_serialize_device_n_map(pcs, p->map, s);

Modified: trunk/gs/src/gscsepr.h
===================================================================
--- trunk/gs/src/gscsepr.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscsepr.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -35,22 +35,15 @@
  * The tint transform procedure now is executed as required and must
  * be executable without doing a call out.
  */
-extern int gs_cspace_build_Separation(
-					 gs_color_space ** ppcspace,
-					 gs_separation_name sname,
-					 const gs_color_space * palt_cspace,
-					 int cache_size,
-					 gs_memory_t * pmem
-					 );
+
 /*
- * This routine builds the central part of the Separation color space.
- * It does not allocate a structure for the color space or initialize it.
+ * This routine constructs a new separation color space object.
  */
-extern int gs_build_Separation(
-				  gs_color_space * pcspace,
-				  const gs_color_space * palt_cspace,
-				  gs_memory_t * pmem
-				  );
+extern int gs_cspace_new_Separation(
+    gs_color_space **ppcs,
+    gs_color_space * palt_cspace,
+    gs_memory_t * pmem
+    );
 
 /* Set the Separation tint transformation procedure to a Function. */
 #ifndef gs_function_DEFINED

Modified: trunk/gs/src/gscspace.c
===================================================================
--- trunk/gs/src/gscspace.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscspace.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -38,26 +38,24 @@
 private const gs_color_space_type gs_color_space_type_DeviceGray = {
     gs_color_space_index_DeviceGray, true, true,
     &st_base_color_space, gx_num_components_1,
-    gx_no_base_space,
     gx_init_paint_1, gx_restrict01_paint_1,
     gx_same_concrete_space,
     gx_concretize_DeviceGray, gx_remap_concrete_DGray,
     gx_remap_DeviceGray, gx_no_install_cspace,
     gx_spot_colors_set_overprint,
-    gx_no_adjust_cspace_count, gx_no_adjust_color_count,
+    NULL, gx_no_adjust_color_count,
     gx_serialize_cspace_type,
     gx_cspace_is_linear_default
 };
 private const gs_color_space_type gs_color_space_type_DeviceRGB = {
     gs_color_space_index_DeviceRGB, true, true,
     &st_base_color_space, gx_num_components_3,
-    gx_no_base_space,
     gx_init_paint_3, gx_restrict01_paint_3,
     gx_same_concrete_space,
     gx_concretize_DeviceRGB, gx_remap_concrete_DRGB,
     gx_remap_DeviceRGB, gx_no_install_cspace,
     gx_spot_colors_set_overprint,
-    gx_no_adjust_cspace_count, gx_no_adjust_color_count,
+    NULL, gx_no_adjust_color_count,
     gx_serialize_cspace_type,
     gx_cspace_is_linear_default
 };
@@ -67,13 +65,12 @@
 private const gs_color_space_type gs_color_space_type_DeviceCMYK = {
     gs_color_space_index_DeviceCMYK, true, true,
     &st_base_color_space, gx_num_components_4,
-    gx_no_base_space,
     gx_init_paint_4, gx_restrict01_paint_4,
     gx_same_concrete_space,
     gx_concretize_DeviceCMYK, gx_remap_concrete_DCMYK,
     gx_remap_DeviceCMYK, gx_no_install_cspace,
     gx_set_overprint_DeviceCMYK,
-    gx_no_adjust_cspace_count, gx_no_adjust_color_count,
+    NULL, gx_no_adjust_color_count,
     gx_serialize_cspace_type,
     gx_cspace_is_linear_default
 };
@@ -82,144 +79,69 @@
 public_st_color_space();
 public_st_base_color_space();
 
-
 /* ------ Create/copy/destroy ------ */
 
-void
-gs_cspace_init(gs_color_space *pcs, const gs_color_space_type * pcstype,
-	       gs_memory_t *mem, bool isheap)
-{
-    pcs->type = pcstype;
-    pcs->pmem = isheap ? mem : NULL;
-    pcs->id = gs_next_ids(mem, 1);
-}
 
-int
-gs_cspace_alloc(gs_color_space ** ppcspace,
-		const gs_color_space_type * pcstype,
-		gs_memory_t * mem)
+private void
+gs_cspace_final(void *vptr)
 {
-    gs_color_space *pcspace =
-	gs_alloc_struct(mem, gs_color_space, &st_color_space,
-			"gs_cspace_alloc");
+    gs_color_space *pcs = (gs_color_space *)vptr;
 
-    if (pcspace == 0)
-	return_error(gs_error_VMerror);
-    if (pcstype != 0)
-        gs_cspace_init(pcspace, pcstype, mem, true);
-    *ppcspace = pcspace;
-    return 0;
+    if (pcs->type->final)
+	pcs->type->final(pcs);
+    if_debug2('c', "[c]cspace final %08x %d\n", pcs, pcs->id);
+    rc_decrement_only(pcs->base_space, "gs_cspace_final");
 }
 
-int
-gs_cspace_init_DeviceGray(const gs_memory_t *mem, gs_color_space *pcs)
+private gs_color_space *
+gs_cspace_alloc_with_id(gs_memory_t *mem, ulong id,
+		   const gs_color_space_type *pcstype)
 {
-    /* parameterless color space; no re-entrancy problems */
-    static gs_color_space  dev_gray_proto;
+    gs_color_space *pcs;
 
-    if (dev_gray_proto.id == 0)
-        gs_cspace_init( &dev_gray_proto,
-                        &gs_color_space_type_DeviceGray,
-                        (gs_memory_t *)mem, false );
-    *pcs = dev_gray_proto;
-    return 0;
+    rc_alloc_struct_1(pcs, gs_color_space, &st_color_space, mem, return NULL,
+		      "gs_cspace_alloc_with_id");
+    if_debug3('c', "[c]cspace alloc %08x %s %d\n",
+	      pcs, pcstype->stype->sname, pcstype->index);
+    pcs->type = pcstype;
+    pcs->id = id;
+    pcs->base_space = NULL;
+    return pcs;
 }
-int
-gs_cspace_build_DeviceGray(gs_color_space ** ppcspace, gs_memory_t * pmem)
-{
-    int     code = gs_cspace_alloc(ppcspace, NULL, pmem);
 
-    if (code >= 0)
-        code = gs_cspace_init_DeviceGray(pmem, *ppcspace);
-    return code;
-}
-
-int
-gs_cspace_init_DeviceRGB(const gs_memory_t *mem, gs_color_space *pcs)
-{
-    /* parameterless color space; no re-entrancy problems */
-    static gs_color_space  dev_rgb_proto;
-
-    if (dev_rgb_proto.id == 0)
-        gs_cspace_init( &dev_rgb_proto,
-                        &gs_color_space_type_DeviceRGB,
-                        (gs_memory_t *)mem, false );
-    *pcs = dev_rgb_proto;
-    return 0;
-}
-int
-gs_cspace_build_DeviceRGB(gs_color_space ** ppcspace, gs_memory_t * pmem)
-{
-    int     code = gs_cspace_alloc(ppcspace, NULL, pmem);
-
-    if (code >= 0)
-        code = gs_cspace_init_DeviceRGB(pmem, *ppcspace);
-    return code;
-}
-
-int
-gs_cspace_init_DeviceCMYK(const gs_memory_t *mem, gs_color_space *pcs)
-{
-    /* parameterless color space; no re-entrancy problems */
-    static gs_color_space  dev_cmyk_proto;
-
-    if (dev_cmyk_proto.id == 0)
-        gs_cspace_init( &dev_cmyk_proto,
-                        &gs_color_space_type_DeviceCMYK,
-                        (gs_memory_t *)mem, false );
-    *pcs = dev_cmyk_proto;
-    return 0;
-}
-int
-gs_cspace_build_DeviceCMYK(gs_color_space ** ppcspace, gs_memory_t * pmem)
-{
-    int     code = gs_cspace_alloc(ppcspace, NULL, pmem);
-
-    if (code >= 0)
-        code = gs_cspace_init_DeviceCMYK(pmem, *ppcspace);
-    return code;
-}
-
 /*
- * Copy just enough of a color space object.  This will do the right thing
- * for copying color spaces into the base or alternate color space of a
- * compound color space when legal, but it can't check that the operation is
- * actually legal.
+ * Generic allocation function for colorspace implementations. Return
+ * NULL on allocation failure.
  */
-inline private void
-cs_copy(gs_color_space *pcsto, const gs_color_space *pcsfrom)
+gs_color_space *
+gs_cspace_alloc(gs_memory_t *mem, const gs_color_space_type *pcstype)
 {
-    memcpy(pcsto, pcsfrom, pcsfrom->type->stype->ssize);
+    return gs_cspace_alloc_with_id(mem, gs_next_ids(mem, 1), pcstype);
 }
 
-/* Copy a color space into one newly allocated by the caller. */
-void
-gs_cspace_init_from(gs_color_space * pcsto, const gs_color_space * pcsfrom)
+/* Constructors for simple device color spaces. */
+
+gs_color_space *
+gs_cspace_new_DeviceGray(gs_memory_t *mem)
 {
-    cs_copy(pcsto, pcsfrom);
-    (*pcsto->type->adjust_cspace_count)(pcsto, 1);
+    return gs_cspace_alloc_with_id(mem, cs_DeviceGray_id,
+				   &gs_color_space_type_DeviceGray);
 }
 
-/* Assign a color space into a previously initialized one. */
-void
-gs_cspace_assign(gs_color_space * pdest, const gs_color_space * psrc)
+gs_color_space *
+gs_cspace_new_DeviceRGB(gs_memory_t *mem)
 {
-    /* check for a = a */
-    if (pdest == psrc)
-	return;
-    (*psrc->type->adjust_cspace_count)(psrc, 1);
-    (*pdest->type->adjust_cspace_count)(pdest, -1);
-    cs_copy(pdest, psrc);
+    return gs_cspace_alloc_with_id(mem, cs_DeviceRGB_id,
+				   &gs_color_space_type_DeviceRGB);
 }
-
-
-/* Prepare to free a color space. */
-void
-gs_cspace_release(gs_color_space * pcs)
+gs_color_space *
+gs_cspace_new_DeviceCMYK(gs_memory_t *mem)
 {
-    (*pcs->type->adjust_cspace_count)(pcs, -1);
+    return gs_cspace_alloc_with_id(mem, cs_DeviceCMYK_id,
+				   &gs_color_space_type_DeviceCMYK);
 }
 
+
 /* ------ Accessors ------ */
 
 /* Get the index of a color space. */
@@ -266,15 +188,9 @@
 const gs_color_space *
 gs_cspace_base_space(const gs_color_space * pcspace)
 {
-    return cs_base_space(pcspace);
+    return pcspace->base_space;
 }
 
-const gs_color_space *
-gx_no_base_space(const gs_color_space * pcspace)
-{
-    return NULL;
-}
-
 /* ------ Other implementation procedures ------ */
 
 /* Null color space installation procedure. */
@@ -450,15 +366,9 @@
 }
 
 
-/* Null reference count adjustment procedure. */
-void
-gx_no_adjust_cspace_count(const gs_color_space * pcs, int delta)
-{
-}
-
 /* A stub for a color mapping linearity check, when it is inapplicable. */
 int
-gx_cspace_no_linear(const gs_direct_color_space *cs, const gs_imager_state * pis,
+gx_cspace_no_linear(const gs_color_space *cs, const gs_imager_state * pis,
 		gx_device * dev, 
 		const gs_client_color *c0, const gs_client_color *c1,
 		const gs_client_color *c2, const gs_client_color *c3,
@@ -468,10 +378,10 @@
 }
 
 private inline int
-cc2dc(const gs_direct_color_space *cs, const gs_imager_state * pis, gx_device *dev,
+cc2dc(const gs_color_space *cs, const gs_imager_state * pis, gx_device *dev,
 	    gx_device_color *dc, const gs_client_color *cc)
 {
-    return cs->type->remap_color(cc, (const gs_color_space *)cs, dc, pis, dev, gs_color_select_texture);
+    return cs->type->remap_color(cc, cs, dc, pis, dev, gs_color_select_texture);
 }
 
 private inline void
@@ -516,14 +426,14 @@
 
 /* Default color mapping linearity check, a 2-points case. */
 private int
-gx_cspace_is_linear_in_line(const gs_direct_color_space *cs, const gs_imager_state * pis,
+gx_cspace_is_linear_in_line(const gs_color_space *cs, const gs_imager_state * pis,
 		gx_device *dev, 
 		const gs_client_color *c0, const gs_client_color *c1,
 		float smoothness)
 {
     gs_client_color c01a, c01b;
     gx_device_color d[2], d01a, d01b;
-    int n = cs->type->num_components((const gs_color_space *)cs);
+    int n = cs->type->num_components(cs);
     int code;
 
     code = cc2dc(cs, pis, dev, &d[0], c0);
@@ -549,7 +459,7 @@
 
 /* Default color mapping linearity check, a triangle case. */
 private int
-gx_cspace_is_linear_in_triangle(const gs_direct_color_space *cs, const gs_imager_state * pis,
+gx_cspace_is_linear_in_triangle(const gs_color_space *cs, const gs_imager_state * pis,
 		gx_device *dev, 
 		const gs_client_color *c0, const gs_client_color *c1,
 		const gs_client_color *c2, float smoothness)
@@ -559,7 +469,7 @@
        Note it gives 7 points for a quadrangle. */
     gs_client_color c01, c12, c20, c012;
     gx_device_color d[3], d01, d12, d20, d012;
-    int n = cs->type->num_components((const gs_color_space *)cs);
+    int n = cs->type->num_components(cs);
     int code;
 
     code = cc2dc(cs, pis, dev, &d[0], c0);
@@ -604,7 +514,7 @@
 
 /* Default color mapping linearity check. */
 int
-gx_cspace_is_linear_default(const gs_direct_color_space *cs, const gs_imager_state * pis,
+gx_cspace_is_linear_default(const gs_color_space *cs, const gs_imager_state * pis,
 		gx_device *dev, 
 		const gs_client_color *c0, const gs_client_color *c1,
 		const gs_client_color *c2, const gs_client_color *c3,
@@ -642,12 +552,15 @@
 {
     EV_CONST gs_color_space *pcs = vptr;
 
-    return ENUM_USING(*pcs->type->stype, vptr, size, index);
+    if (index == 0)
+	return ENUM_OBJ(pcs->base_space);
+    return ENUM_USING(*pcs->type->stype, vptr, size, index - 1);
     ENUM_PTRS_END_PROC
 }
 private 
 RELOC_PTRS_WITH(color_space_reloc_ptrs, gs_color_space *pcs)
 {
+    RELOC_VAR(pcs->base_space);
     RELOC_USING(*pcs->type->stype, vptr, size);
 }
 RELOC_PTRS_END

Modified: trunk/gs/src/gscspace.h
===================================================================
--- trunk/gs/src/gscspace.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscspace.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -20,101 +20,18 @@
 #include "gsmemory.h"
 #include "gsiparam.h"
 #include "gsnamecl.h"
+#include "gsrefct.h"
 
 /*
- * The handling of color spaces in the graphic library is somewhat
- * awkward because of historical artifacts.
- *
- * The PostScript Level 1 (DeviceGray/RGB) color spaces, and the "Level
- * 1 1/2" DeviceCMYK space, have no associated parameters.  Therefore,
- * they can be represented as simple objects (just a pointer to a type
- * vector containing procedures and parameters).  This was the original
- * design.
- *
- * PostScript Level 2 and LanguageLevel 3 add two new kinds of color spaces:
- * color spaces with parameters (CIEBased and DevicePixel spaces),  and
- * compound color spaces (Indexed, Separation, Pattern, and DeviceN spaces),
- * with parameters that include a specification of an alternative or
- * underlying color space.  To handle these spaces, we extended the original
- * design to store in-line certain scalar parameters (i.e., parameters other
- * than the complex color transformation data for CIEBased spaces, the lookup
- * table for Indexed spaces, and the list of component names for DeviceN
- * spaces) in the color space object.  For compound spaces, this requires
- * storing a color space in-line inside another color space, which is clearly
- * impossible.  Therefore, we defined a generality hierarchy for color spaces:
- *
- *      - Base spaces (DeviceGray/RGB/CMYK/Pixel, CIEBased), whose
- *      whose parameters (if any) don't include other color spaces.
- *
- *	- Direct spaces (base spaces + Separation and DeviceN), which
- *      may have a base space as an alternative space.
- *
- *      - Paint spaces (direct spaces + Indexed), which may have a direct
- *      space as the underlying space
- *
- *      - General spaces (paint spaces + Pattern), which may have a
- *      paint space as the underlying space.
- *
- * With this approach, a general space can include a paint space stored
- * in-line; a paint space (either in its own right or as the underlying
- * space of a Pattern space) can include a direct space in-line; and a
- * direct space can include a base space in-line.
- *
- * The introduction of ICCBased color spaces in PDF 1.3 wrecked havoc on
- * this hierarchy. ICCBased color spaces contain alternative color spaces,
- * which may be paint spaces. On the other hand, ICCBased spaces may be
- * use as alternative or underlying color spaces in direct and paint
- * spaces.
- *
- * The proper solution to this problem would be to reference alternative and
- * underlying color spaces via a pointer. The cost and risk of that approach
- * is, however, larger than is warranted just by the addition of ICCBased
- * color spaces. Another alternative is to allow just base color spaces to 
- * include an alternative color space via a pointer. That would require two
- * separate mechanisms for dealing with alternative color spaces, which
- * seems messy and may well cause problems in the future.
- *
- * Examination of some PDF files indicates that ICCBased color spaces are
- * routinely used as alternative spaces for Separation or Device color
- * spaces, but essentially never make use of alternative color spaces other
- * than the device-specific spaces. To support this usage, the approach
- * taken here splits previous base color space class into "small"  and
- * "regular" base color spaces. Small base color spaces include all of
- * those color spaces that previously were considered base spaces. Regular
- * base spaces add the ICCBased color spaces to this set. To maintain
- * compatibility with the existing code base, regular base spaces make use
- * of the gs_base_color_space type name.
- *
- * Note that because general, paint, direct, regular base, and small base
- * spaces are (necessarily) of different sizes, assigning (copying the top
- * object of) color spaces must take into account the actual size of the
- * color space being assigned.  In principle, this also requires checking
- * that the source object will actually fit into the destination.  Currently
- * we rely on the caller to ensure that this is the case; in fact, the
- * current API (gs_cspace_init and gs_cspace_assign) doesn't even provide
- * enough information to make the check.
- *
- * In retrospect, we might have gotten a simpler design without significant
- * performance loss by always referencing underlying and alternate spaces
- * through a pointer; however, at this point, the cost and risk of changing
- * to such a design are too high.
- *
- * There are two aspects to memory management for color spaces: managing
- * the color space objects themselves, and managing the non-scalar
- * parameters that they reference (if any).
- *
- *      - Color space objects per se have no special management properties:
- *      they can be allocated on the stack or on the heap, and freed by
- *      scope exit, explicit deallocation, or garbage collection.
- *
- *      - Separately allocated (non-scalar) color space parameters are
- *      managed by reference counting.  Currently we do this for the
- *      CIEBased spaces, and for the first-level parameters of Indexed and
- *      Separation spaces: clients must deal with deallocating the other
- *      parameter structures mentioned above, including the Indexed lookup
- *      table if any. This is clearly not a good situation, but we don't
- *      envision fixing it any time soon.
- *
+ * Previous versions had a complicated lifecycle discipline for
+ * colorspaces. All that is now replaced with a simple allocation and
+ * reference counting discipline. All colorspace objects are allocated
+ * on the heap and reference counted. References to colorspace objects
+ * are pointers. There is no stack allocation, inline allocation inside
+ * structs, or copying of contents.
+ */
+
+/*
  * Here is the information associated with the various color space
  * structures.  Note that DevicePixel, DeviceN, and the ability to use
  * Separation or DeviceN spaces as the base space of an Indexed space
@@ -159,6 +76,14 @@
  */
 
 /*
+ * Define the abstract type for color space objects.
+ */
+#ifndef gs_color_space_DEFINED
+#  define gs_color_space_DEFINED
+typedef struct gs_color_space_s gs_color_space;
+#endif
+
+/*
  * Define color space type indices.  NOTE: PostScript code (gs_res.ps,
  * gs_ll3.ps) and the color space substitution code (gscssub.[hc] and its
  * clients) assumes values 0-2 for DeviceGray/RGB/CMYK respectively.
@@ -201,26 +126,13 @@
 typedef struct gs_color_space_type_s gs_color_space_type;
 
 /*
- * The common part of all color spaces. This structure now includes a memory
- * structure pointer, so that it may be released without providing this
- * information separately. (type is a pointer to the structure of methods.)
- *
- * Note that all color space structures consist of the basic information and
- * a union containing some additional information. The macro operand is that
- * union.
- */
-#define gs_cspace_common(param_union)   \
-    const gs_color_space_type * type;   \
-    gs_memory_t *               pmem;   \
-    gs_id                       id;     \
-    union {                             \
-	param_union;                    \
-    }                           params
-
-/*
  * Parameters for "small" base color spaces. Of the small base color spaces,
  * only DevicePixel and CIE spaces have parameters: see gscie.h for the
  * structure definitions for CIE space parameters.
+ *
+ * It would be possible to save an allocation by placing the CIE
+ * params inside the colorspace struct, rather than a pointer to a
+ * separate struct, but we'll keep it the way it is for now.
  */
 typedef struct gs_device_pixel_params_s {
     int depth;
@@ -230,19 +142,6 @@
 typedef struct gs_cie_def_s gs_cie_def;
 typedef struct gs_cie_defg_s gs_cie_defg;
 
-#define gs_small_base_cspace_params     \
-    gs_device_pixel_params   pixel;     \
-    gs_cie_defg *            defg;      \
-    gs_cie_def *             def;       \
-    gs_cie_abc *             abc;       \
-    gs_cie_a *               a
-
-typedef struct gs_small_base_color_space_s {
-    gs_cspace_common(gs_small_base_cspace_params);
-} gs_small_base_color_space;
-
-#define gs_small_base_color_space_size sizeof(gs_small_base_color_space)
-
 /*
  * "Regular" base color spaces include all of the small base color space and
  * the ICCBased color space, which includes a small base color space as an
@@ -253,19 +152,8 @@
 
 typedef struct gs_cieicc_params_s {
     gs_cie_icc *                picc_info;
-    gs_small_base_color_space   alt_space;
 } gs_icc_params;
 
-#define gs_base_cspace_params   \
-    gs_small_base_cspace_params;\
-    gs_icc_params   icc
-
-typedef struct gs_base_color_space_s {
-    gs_cspace_common(gs_base_cspace_params);
-} gs_base_color_space;
-
-#define gs_base_color_space_size sizeof(gs_base_color_space)
-
 #ifndef gs_device_n_map_DEFINED
 #  define gs_device_n_map_DEFINED
 typedef struct gs_device_n_map_s gs_device_n_map;
@@ -296,7 +184,6 @@
 
 typedef struct gs_separation_params_s {
     gs_separation_name sep_name;
-    gs_base_color_space alt_space;
     gs_device_n_map *map;
     separation_type sep_type;
     bool use_alt_cspace;
@@ -309,7 +196,6 @@
 typedef struct gs_device_n_params_s {
     gs_separation_name *names;
     uint num_components;
-    gs_base_color_space alt_space;
     gs_device_n_map *map;
     gs_device_n_attributes *colorants;
     bool use_alt_cspace;
@@ -319,17 +205,6 @@
 #endif
 } gs_device_n_params;
 
-#define gs_direct_cspace_params         \
-    gs_base_cspace_params;              \
-    gs_separation_params separation;    \
-    gs_device_n_params device_n
-
-typedef struct gs_direct_color_space_s {
-    gs_cspace_common(gs_direct_cspace_params);
-} gs_direct_color_space;
-
-#define gs_direct_color_space_size sizeof(gs_direct_color_space)
-
 /*
  * Non-direct paint space: Indexed space.
  *
@@ -341,8 +216,8 @@
 typedef struct gs_indexed_map_s gs_indexed_map;
 
 typedef struct gs_indexed_params_s {
-    gs_direct_color_space base_space;
     int hival;			/* num_entries - 1 */
+    int n_comps;
     union {
 	gs_const_string table;	/* size is implicit */
 	gs_indexed_map *map;
@@ -350,112 +225,67 @@
     bool use_proc;		/* 0 = use table, 1 = use proc & map */
 } gs_indexed_params;
 
-#define gs_paint_cspace_params          \
-    gs_direct_cspace_params;            \
-    gs_indexed_params indexed
-
-typedef struct gs_paint_color_space_s {
-    gs_cspace_common(gs_paint_cspace_params);
-} gs_paint_color_space;
-
-#define gs_paint_color_space_size sizeof(gs_paint_color_space)
-
 /*
  * Pattern parameter set. This may contain an instances of a paintable
  * color space. The boolean indicates if this is the case.
  */
 typedef struct gs_pattern_params_s {
-    bool has_base_space;
-    gs_paint_color_space base_space;
+    bool has_base_space; /* {csrc} can't we just NULL-check the base_space? */
 } gs_pattern_params;
 
+/* id's 1 through 4 are reserved for static colorspaces; thus, dynamically
+   assigned id's must begin at 5. */
+#define cs_DeviceGray_id 1
+#define cs_DeviceRGB_id 3
+#define cs_DeviceCMYK_id 4
+
 /*
- * Fully general color spaces.
+ * The colorspace object. For pattern and indexed colorspaces, the
+ * base_space refers to the underlying colorspace. For separation,
+ * deviceN, and icc colorspaces, base_space refers to the alternate
+ * colorspace (referred to as alt_space in previous versions of the
+ * code).
  */
 struct gs_color_space_s {
-    gs_cspace_common(
-	gs_paint_cspace_params;
-	gs_pattern_params pattern
-    );
+    const gs_color_space_type *type;
+    rc_header                  rc;
+    gs_id                      id;
+    gs_color_space             *base_space;
+    union {
+	gs_device_pixel_params   pixel;
+	gs_cie_defg *            defg;
+	gs_cie_def *             def;
+	gs_cie_abc *             abc;
+	gs_cie_a *               a;
+	gs_icc_params            icc;
+	gs_separation_params     separation;
+	gs_device_n_params       device_n;
+	gs_indexed_params        indexed;
+	gs_pattern_params        pattern;
+    } params;
 };
 
-#define gs_pattern_color_space_size sizeof(gs_color_space)
 
-/*
- * Define the abstract type for color space objects.
- */
-#ifndef gs_color_space_DEFINED
-#  define gs_color_space_DEFINED
-typedef struct gs_color_space_s gs_color_space;
-#endif
-
 					/*extern_st(st_color_space); *//* in gxcspace.h */
 #define public_st_color_space()	/* in gscspace.c */  \
-    gs_public_st_composite( st_color_space,         \
-                            gs_color_space,         \
-                            "gs_color_space",       \
-                            color_space_enum_ptrs,  \
-                            color_space_reloc_ptrs  \
+    gs_public_st_composite_final( st_color_space,         \
+				  gs_color_space,         \
+				  "gs_color_space",       \
+				  color_space_enum_ptrs,  \
+				  color_space_reloc_ptrs, \
+				  gs_cspace_final         \
                             )
 
-#define st_color_space_max_ptrs 2	/* 1 base + 1 indexed */
-
 /* ---------------- Procedures ---------------- */
 
-/* ------ Create/copy/destroy ------ */
+/* Constructors for simple device color spaces. These return NULL on
+   VMerror. */
 
-/*
- * Note that many of the constructors take no parameters, and the
- * remainder take only a few (CIE color spaces constructures take a
- * client data pointer as an operand, the composite color space (Separation,
- * Indexed, and Pattern) constructurs take the base space as an operand,
- * and the Indexed color space constructors have a few additiona operands).
- * This is done to conserve memory. If initialization values for all the
- * color space parameters were provided to the constructors, these values
- * would need to have some fairly generic format. Different clients gather
- * this data in different forms, so they would need to allocate memory to
- * convert it to the generic form, only to immediately release this memory
- * once the construction is complete.
- *
- * The alternative approach employed here is to provide a number of access
- * methods (macros) that return pointers to individual fields of the
- * various color space structures. This requires exporting only fairly simple
- * data structures, and so does not violate modularity too severely.
- *
- * NB: Of necessity, the macros provide access to modifiable structures. If
- *     these structures are modified after the color space object is first
- *     initialized, unpredictable and, most likely, undesirable results will
- *     occur.
- *
- * The constructors return an integer, 0 on success and an
- * error code on failure (gs_error_VMerror or gs_error_rangecheck).
- *
- * In parallel with the constructors, we provide initializers that assume
- * the client has allocated the color space object (perhaps on the stack)
- * and takes responsibility for freeing it.
- */
+gs_color_space *gs_cspace_new_DeviceGray(gs_memory_t *mem);
+gs_color_space *gs_cspace_new_DeviceRGB(gs_memory_t *mem);
+gs_color_space *gs_cspace_new_DeviceCMYK(gs_memory_t *mem);
 
-extern int
-    gs_cspace_init_DeviceGray(const gs_memory_t *mem, gs_color_space *pcs),
-    gs_cspace_build_DeviceGray(gs_color_space ** ppcspace,
-				  gs_memory_t * pmem),
-    gs_cspace_init_DeviceRGB(const gs_memory_t *mem, gs_color_space *pcs),
-    gs_cspace_build_DeviceRGB(gs_color_space ** ppcspace,
-                              gs_memory_t * pmem),
-    gs_cspace_init_DeviceCMYK(const gs_memory_t *mem, gs_color_space *pcs),
-    gs_cspace_build_DeviceCMYK(gs_color_space ** ppcspace,
-                               gs_memory_t * pmem);
 
-/* Copy a color space into one newly allocated by the caller. */
-void gs_cspace_init_from(gs_color_space * pcsto,
-			 const gs_color_space * pcsfrom);
-
-/* Assign a color space into a previously initialized one. */
-void gs_cspace_assign(gs_color_space * pdest, const gs_color_space * psrc);
-
-/* Prepare to free a color space. */
-void gs_cspace_release(gs_color_space * pcs);
-
 /* ------ Accessors ------ */
 
 /* Get the index of a color space. */

Modified: trunk/gs/src/gscssub.c
===================================================================
--- trunk/gs/src/gscssub.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gscssub.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -52,22 +52,12 @@
 	    return_error(gs_error_rangecheck);
     }
     pcs_old = pgs->device_color_spaces.indexed[index];
-    if (pcs_old == 0) {
-	gs_color_space *pcs_new;
-
-	if (pcs == 0 || gs_color_space_get_index(pcs) == csi)
-	    return 0;
-	pcs_new = gs_alloc_struct(pgs->memory, gs_color_space, &st_color_space,
-				  "gs_setsubstitutecolorspace");
-	if (pcs_new == 0)
-	    return_error(gs_error_VMerror);
-	gs_cspace_init_from(pcs_new, pcs);
-	pgs->device_color_spaces.indexed[index] = pcs_new;
-    } else {
-	gs_cspace_assign(pgs->device_color_spaces.indexed[index],
-			 (pcs ? pcs :
-			  pgs->shared->device_color_spaces.indexed[index]));
-    }
+    if (pcs_old == 0 &&	(pcs == 0 || gs_color_space_get_index(pcs) == csi))
+	return 0;
+    rc_assign(pgs->device_color_space.indexed[index],
+	      (pcs ? pcs :
+	       pgs->shared->device_color_spaces.indexed[index]),
+	      "gs_setsubstitutecolorspace");
     return 0;
 }
 

Modified: trunk/gs/src/gsicc.c
===================================================================
--- trunk/gs/src/gsicc.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gsicc.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -73,29 +73,21 @@
  * we must enumerate and relocate pointers in these space explicity.
  */
 gs_private_st_composite( st_color_space_CIEICC,
-                         gs_paint_color_space,
+                         gs_color_space,
                          "gs_color_space_CIEICC",
                          cs_CIEICC_enum_ptrs,
                          cs_CIEICC_reloc_ptrs );
 
 /* pointer enumeration routine */
 private
-ENUM_PTRS_WITH(cs_CIEICC_enum_ptrs, gs_color_space * pcs)
-        return ENUM_USING( *pcs->params.icc.alt_space.type->stype,
-                           &pcs->params.icc.alt_space,
-                           sizeof(pcs->params.separation.alt_space),
-                           index - 1 );
-
+ENUM_PTRS_BEGIN(cs_CIEICC_enum_ptrs) return 0;
         ENUM_PTR(0, gs_color_space, params.icc.picc_info);
 ENUM_PTRS_END
 
 /* pointer relocation routine */
 private
-RELOC_PTRS_WITH(cs_CIEICC_reloc_ptrs, gs_color_space * pcs)
+RELOC_PTRS_BEGIN(cs_CIEICC_reloc_ptrs)
     RELOC_PTR(gs_color_space, params.icc.picc_info);
-    RELOC_USING( *pcs->params.icc.alt_space.type->stype,
-                 &pcs->params.icc.alt_space,
-                 sizeof(pcs->params.separation.alt_space) );
 RELOC_PTRS_END
 
 
@@ -119,12 +111,11 @@
  * root class.
  */
 private cs_proc_num_components(gx_num_components_CIEICC);
-private cs_proc_base_space(gx_alt_space_CIEICC);
 private cs_proc_init_color(gx_init_CIEICC);
 private cs_proc_restrict_color(gx_restrict_CIEICC);
 private cs_proc_concrete_space(gx_concrete_space_CIEICC);
 private cs_proc_concretize_color(gx_concretize_CIEICC);
-private cs_proc_adjust_cspace_count(gx_adjust_cspace_CIEICC);
+private cs_proc_final(gx_final_CIEICC);
 private cs_proc_serialize(gx_serialize_CIEICC);
 
 private const gs_color_space_type gs_color_space_type_CIEICC = {
@@ -133,7 +124,6 @@
     true,                           /* can_be_alt_space */
     &st_color_space_CIEICC,         /* stype - structure descriptor */
     gx_num_components_CIEICC,       /* num_components */
-    gx_alt_space_CIEICC,            /* base_space */
     gx_init_CIEICC,                 /* init_color */
     gx_restrict_CIEICC,             /* restrict_color */
     gx_concrete_space_CIEICC,       /* concrete_space */
@@ -142,7 +132,7 @@
     gx_default_remap_color,         /* remap_color */
     gx_install_CIE,                 /* install_cpsace */
     gx_spot_colors_set_overprint,   /* set_overprint */
-    gx_adjust_cspace_CIEICC,        /* adjust_cspace_count */
+    gx_final_CIEICC,                /* final */
     gx_no_adjust_color_count,       /* adjust_color_count */
     gx_serialize_CIEICC,		    /* serialize */
     gx_cspace_is_linear_default
@@ -159,18 +149,6 @@
 }
 
 /*
- * Return the alternative space for an ICCBasee color space, but only if
- * that space is being used.
- */
-private const gs_color_space *
-gx_alt_space_CIEICC(const gs_color_space * pcs)
-{
-    return (pcs->params.icc.picc_info->picc == NULL)
-                ? (const gs_color_space *)&pcs->params.icc.alt_space
-                : NULL;
-}
-
-/*
  * Set the initial client color for an ICCBased color space. The convention
  * suggested by the ICC specification is to set all components to 0.
  */
@@ -217,8 +195,7 @@
 gx_concrete_space_CIEICC(const gs_color_space * pcs, const gs_imager_state * pis)
 {
     if (pcs->params.icc.picc_info->picc == NULL) {
-        const gs_color_space *  pacs = (const gs_color_space *)
-                                        &pcs->params.icc.alt_space;
+        const gs_color_space *  pacs = pcs->base_space;
 
         return cs_concrete_space(pacs, pis);
     } else
@@ -246,9 +223,9 @@
 
     /* use the altenate space concretize if appropriate */
     if (picc == NULL)
-        return picc_params->alt_space.type->concretize_color(
+        return pcs->base_space->type->concretize_color(
                             pcc,
-                            (const gs_color_space *)&picc_params->alt_space,
+                            pcs->base_space,
                             pconc,
                             pis );
 
@@ -318,34 +295,18 @@
 }
 
 /*
- * Handle a reference or de-reference of the prameter structure of an
- * ICCBased color space. For the purposes of this routine, the color space
- * is considered a reference rather than an object, and is not itself
- * reference counted (an unintuitive but otherwise legitimate state of
- * affairs).
- *
- * Because color spaces store alternative/base color space inline, these
- * need to have their reference count adjusted explicitly.
+ * Finalize the contents of an ICC color space. Now that color space
+ * objects have straightforward reference counting discipline, there's
+ * nothing special about it. In the previous state of affairs, the
+ * argument in favor of correct reference counting spoke of "an
+ * unintuitive but otherwise legitimate state of affairs".
  */
 private void
-gx_adjust_cspace_CIEICC(const gs_color_space * pcs, int delta)
+gx_final_CIEICC(const gs_color_space * pcs)
 {
-    const gs_icc_params *   picc_params = &pcs->params.icc;
-
-    rc_adjust_const(picc_params->picc_info, delta, "gx_adjust_cspace_CIEICC");
-    picc_params->alt_space.type->adjust_cspace_count(
-                (const gs_color_space *)&picc_params->alt_space, delta );
+    rc_decrement_only(pcs->params.icc.picc_info, "gx_final_CIEICC");
 }
 
-/*
- * Increment color space reference counts.
- */
-void
-gx_increment_cspace_count(const gs_color_space * pcs)
-{
-    pcs->type->adjust_cspace_count(pcs, 1);
-}
-
 private int
 icmFileGs_seek(icmFile *pp, long int offset)
 {

Modified: trunk/gs/src/gsicc.h
===================================================================
--- trunk/gs/src/gsicc.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gsicc.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -168,10 +168,4 @@
 int
 gx_load_icc_profile(gs_cie_icc *picc_info);
 
-/*
- * Increment color space reference counts.
- */
-void
-gx_increment_cspace_count(const gs_color_space * pcs);
-
 #endif /* gsicc_INCLUDED */

Modified: trunk/gs/src/gsimage.c
===================================================================
--- trunk/gs/src/gsimage.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gsimage.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -269,17 +269,11 @@
 	if (pgs->in_cachedevice)
 	    return_error(gs_error_undefined);
 	if (image.ColorSpace == NULL) {
-            /* parameterless color space - no re-entrancy problems */
-            static gs_color_space cs;
-
             /*
-             * Mutiple initialization of a DeviceGray color space is
-             * not harmful, as the space has no parameters. Use of a
-             * non-current color space is potentially incorrect, but
-             * it appears this case doesn't arise.
+             * Use of a non-current color space is potentially
+             * incorrect, but it appears this case doesn't arise.
              */
-            gs_cspace_init_DeviceGray(pgs->memory, &cs);
-	    image.ColorSpace = &cs;
+	    image.ColorSpace = gs_cspace_new_DeviceGray(pgs->memory);
         }
     }
     code = gs_image_begin_typed((const gs_image_common_t *)&image, pgs,

Modified: trunk/gs/src/gsiparam.h
===================================================================
--- trunk/gs/src/gsiparam.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gsiparam.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -176,7 +176,7 @@
                  * member of the subclass, when the base structure is assigned\
                  * to the subclass structure. Bugs 613909, 688725\
                  */\
-	const gs_color_space *ColorSpace
+	gs_color_space *ColorSpace
 
 
 typedef struct gs_pixel_image_s {

Modified: trunk/gs/src/gsistate.c
===================================================================
--- trunk/gs/src/gsistate.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gsistate.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -128,6 +128,8 @@
     pis->cmap_procs = cmap_procs_default;
     pis->pattern_cache = NULL;
     pis->have_pattern_streams = false;
+    pis->devicergb_cs = gs_cspace_new_DeviceRGB(mem);
+    pis->devicecmyk_cs = gs_cspace_new_DeviceCMYK(mem);
     return 0;
 }
 
@@ -166,6 +168,8 @@
     rc_increment(pis->set_transfer.green);
     rc_increment(pis->set_transfer.blue);
     rc_increment(pis->cie_joint_caches);
+    rc_increment(pis->devicergb_cs);
+    rc_increment(pis->devicecmyk_cs);
 }
 
 /* Adjust reference counts before assigning one imager state to another. */
@@ -189,6 +193,8 @@
     RCCOPY(halftone);
     RCCOPY(shape.mask);
     RCCOPY(opacity.mask);
+    RCCOPY(devicergb_cs);
+    RCCOPY(devicecmyk_cs);
 #undef RCCOPY
 }
 
@@ -221,5 +227,7 @@
     RCDECR(halftone);
     RCDECR(shape.mask);
     RCDECR(opacity.mask);
+    RCDECR(devicergb_cs);
+    RCDECR(devicecmyk_cs);
 #undef RCDECR
 }

Modified: trunk/gs/src/gslibctx.c
===================================================================
--- trunk/gs/src/gslibctx.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gslibctx.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -73,7 +73,8 @@
     pio->stderr_fn = 0;
     pio->poll_fn = 0;
 
-    pio->gs_next_id = 1;  /* this implies that each thread has its own complete state */
+    /* id's 1 through 4 are reserved for Device color spaces; see gscspace.h */
+    pio->gs_next_id = 5;  /* this implies that each thread has its own complete state */
 
     pio->dict_auto_expand = false;
     return 0;

Modified: trunk/gs/src/gspcolor.c
===================================================================
--- trunk/gs/src/gspcolor.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gspcolor.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -42,28 +42,26 @@
 public_st_pattern_instance();
 
 /* Define the Pattern color space. */
-gs_private_st_composite(st_color_space_Pattern, gs_paint_color_space,
+gs_private_st_composite(st_color_space_Pattern, gs_color_space,
      "gs_color_space_Pattern", cs_Pattern_enum_ptrs, cs_Pattern_reloc_ptrs);
 private cs_proc_num_components(gx_num_components_Pattern);
-private cs_proc_base_space(gx_base_space_Pattern);
 private cs_proc_remap_color(gx_remap_Pattern);
 private cs_proc_init_color(gx_init_Pattern);
 private cs_proc_restrict_color(gx_restrict_Pattern);
 private cs_proc_install_cspace(gx_install_Pattern);
 private cs_proc_set_overprint(gx_set_overprint_Pattern);
-private cs_proc_adjust_cspace_count(gx_adjust_cspace_Pattern);
+private cs_proc_final(gx_final_Pattern);
 private cs_proc_adjust_color_count(gx_adjust_color_Pattern);
 private cs_proc_serialize(gx_serialize_Pattern);
 const gs_color_space_type gs_color_space_type_Pattern = {
     gs_color_space_index_Pattern, false, false,
     &st_color_space_Pattern, gx_num_components_Pattern,
-    gx_base_space_Pattern,
     gx_init_Pattern, gx_restrict_Pattern,
     gx_no_concrete_space,
     gx_no_concretize_color, NULL,
     gx_remap_Pattern, gx_install_Pattern,
     gx_set_overprint_Pattern,
-    gx_adjust_cspace_Pattern, gx_adjust_color_Pattern,
+    gx_final_Pattern, gx_adjust_color_Pattern,
     gx_serialize_Pattern,
     gx_cspace_no_linear
 };
@@ -152,15 +150,16 @@
     if (pgs->in_cachedevice)
 	return_error(gs_error_undefined);
     if (pgs->color_space->type->index != gs_color_space_index_Pattern) {
-	gs_color_space cs;
+	gs_color_space *pcs;
 
-	gs_cspace_init(&cs, &gs_color_space_type_Pattern, pgs->memory, false);
-	/**************** base_space SETTING IS WRONG ****************/
-	cs.params.pattern.base_space =
-	    *(gs_paint_color_space *) pgs->color_space;
-	cs.params.pattern.has_base_space = true;
-	*pgs->color_space = cs;
-	cs_full_init_color(pgs->ccolor, &cs);
+	pcs = gs_cspace_alloc(pgs->memory, &gs_color_space_type_Pattern);
+	if (pcs == NULL)
+	    return_error(gs_error_VMerror);
+	/* reference to base space shifts from pgs to pcs with no net change */
+	pcs->base_space = pgs->color_space;
+	pcs->params.pattern.has_base_space = true;
+	pgs->color_space = pcs;
+	cs_full_init_color(pgs->ccolor, pcs);
 	gx_unset_dev_color(pgs);
     }
     return code;
@@ -200,21 +199,10 @@
 {
     return
 	(pcs->params.pattern.has_base_space ?
-	 -1 - cs_num_components((const gs_color_space *)
-				&(pcs->params.pattern.base_space)) :
+	 -1 - cs_num_components(pcs->base_space) :
 	 -1 /* Pattern dictionary only */ );
 }
 
-/* Get the base space of a Pattern color space. */
-private const gs_color_space *
-gx_base_space_Pattern(const gs_color_space * pcs)
-{
-    return
-	(pcs->params.pattern.has_base_space ?
-	 (const gs_color_space *)&(pcs->params.pattern.base_space) :
-	 NULL);
-}
-
 /* Remap a Pattern color. */
 private int
 gx_remap_Pattern(const gs_client_color * pc, const gs_color_space * pcs,
@@ -235,8 +223,7 @@
 gx_init_Pattern(gs_client_color * pcc, const gs_color_space * pcs)
 {
     if (pcs->params.pattern.has_base_space) {
-	const gs_color_space *pbcs =
-	(const gs_color_space *)&pcs->params.pattern.base_space;
+	const gs_color_space *pbcs = pcs->base_space;
 
 	cs_init_color(pcc, pbcs);
     }
@@ -256,8 +243,7 @@
 	pcc->pattern->type->procs.uses_base_space(gs_get_pattern(pcc)) &&
 	pcs->params.pattern.has_base_space
 	) {
-	const gs_color_space *pbcs =
-	    (const gs_color_space *)&pcs->params.pattern.base_space;
+	const gs_color_space *pbcs = pcs->base_space;
 
 	(*pbcs->type->restrict_color) (pcc, pbcs);
     }
@@ -269,8 +255,7 @@
 {
     if (!pcs->params.pattern.has_base_space)
 	return 0;
-    return (*pcs->params.pattern.base_space.type->install_cspace)
-	((const gs_color_space *) & pcs->params.pattern.base_space, pgs);
+    return (pcs->base_space->type->install_cspace)(pcs->base_space, pgs);
 }
 
 /*
@@ -285,11 +270,9 @@
 
 /* Adjust the reference counts for Pattern color spaces or colors. */
 private void
-gx_adjust_cspace_Pattern(const gs_color_space * pcs, int delta)
+gx_final_Pattern(const gs_color_space * pcs)
 {
-    if (pcs->params.pattern.has_base_space)
-	(*pcs->params.pattern.base_space.type->adjust_cspace_count)
-	    ((const gs_color_space *)&pcs->params.pattern.base_space, delta);
+    /* {csrc} really do nothing? */
 }
 
 private void
@@ -300,9 +283,8 @@
 
     rc_adjust_only(pinst, delta, "gx_adjust_color_Pattern");
     if (pcs && pcs->params.pattern.has_base_space)
-	(*pcs->params.pattern.base_space.type->adjust_color_count)
-	    (pcc, (const gs_color_space *)&pcs->params.pattern.base_space,
-	     delta);
+	(pcs->base_space->type->adjust_color_count)
+	    (pcc, pcs->base_space, delta);
 }
 
 /* GC procedures */
@@ -310,22 +292,13 @@
 private 
 ENUM_PTRS_BEGIN_PROC(cs_Pattern_enum_ptrs)
 {
-    EV_CONST gs_color_space *const pcs = vptr;
-
-    if (!pcs->params.pattern.has_base_space)
-	return 0;
-    return ENUM_USING(*pcs->params.pattern.base_space.type->stype,
-		      &pcs->params.pattern.base_space,
-		      sizeof(pcs->params.pattern.base_space), index);
+    return 0;
+    /* {csrc} may change to st_base_color_space */
 }
 ENUM_PTRS_END_PROC
-private RELOC_PTRS_WITH(cs_Pattern_reloc_ptrs, gs_color_space *pcs)
+private RELOC_PTRS_BEGIN(cs_Pattern_reloc_ptrs)
 {
-    if (!pcs->params.pattern.has_base_space)
-	return;
-    RELOC_USING(*pcs->params.pattern.base_space.type->stype,
-		&pcs->params.pattern.base_space,
-		sizeof(gs_paint_color_space));
+    return;
 }
 RELOC_PTRS_END
 
@@ -340,10 +313,10 @@
 
     if (code < 0)
 	return code;
-    code = sputs(s, (byte *)&p->has_base_space, sizeof(p->has_base_space), &n);
+    code = sputs(s, (const byte *)&p->has_base_space, sizeof(p->has_base_space), &n);
     if (code < 0)
 	return code;
     if (!p->has_base_space)
 	return 0;
-    return cs_serialize((const gs_color_space *)&p->base_space, s);
+    return cs_serialize(pcs->base_space, s);
 }

Modified: trunk/gs/src/gsptype1.c
===================================================================
--- trunk/gs/src/gsptype1.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gsptype1.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -83,23 +83,21 @@
  */
 int
 gs_cspace_build_Pattern1(gs_color_space ** ppcspace,
-		    const gs_color_space * pbase_cspace, gs_memory_t * pmem)
+		    gs_color_space * pbase_cspace, gs_memory_t * pmem)
 {
     gs_color_space *pcspace = 0;
-    int code;
 
     if (pbase_cspace != 0) {
 	if (gs_color_space_num_components(pcspace) < 0)		/* Pattern space */
 	    return_error(gs_error_rangecheck);
     }
-    code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Pattern, pmem);
-    if (code < 0)
-	return code;
+    pcspace = gs_cspace_alloc(pmem, &gs_color_space_type_Pattern);
+    if (pcspace == NULL)
+	return_error(gs_error_VMerror);
     if (pbase_cspace != 0) {
 	pcspace->params.pattern.has_base_space = true;
-	gs_cspace_init_from((gs_color_space *) & (pcspace->params.pattern.base_space),
-			    pbase_cspace
-	    );
+	/* reference to base space shifts from pgs to pcs with no net change */
+	pcspace->base_space = pbase_cspace;
     } else
 	pcspace->params.pattern.has_base_space = false;
     *ppcspace = pcspace;
@@ -499,7 +497,7 @@
     if (ptmplt->PaintType == 2) {
         const gs_color_space *  pcs = pgs->color_space;
 
-        pcs = (const gs_color_space *)&(pcs->params.pattern.base_space);
+        pcs = pcs->base_space;
         return pcs->type->set_overprint(pcs, pgs);
     } else {
         gs_overprint_params_t   params;
@@ -546,7 +544,7 @@
  */
 typedef struct pixmap_info_s {
     gs_depth_bitmap bitmap;	/* must be first */
-    const gs_color_space *pcspace;
+    gs_color_space *pcspace;
     uint white_index;
     void (*free_proc)(gs_memory_t *, void *, client_name_t);
 } pixmap_info;
@@ -614,8 +612,7 @@
     const gs_depth_bitmap *pbitmap = &(ppmap->bitmap);
     gs_image_enum *pen =
         gs_image_enum_alloc(gs_state_memory(pgs), "image_PaintProc");
-    gs_color_space cs;
-    const gs_color_space *pcspace;
+    gs_color_space *pcspace;
     gx_image_enum_common_t *pie;
     /*
      * If the image is transparent then we want to do image type4 processing.
@@ -640,8 +637,7 @@
 	return_error(gs_error_VMerror);
 
     if (ppmap->pcspace == 0) {
-        gs_cspace_init_DeviceGray(pgs->memory, &cs);
-        pcspace = &cs;
+	pcspace = gs_cspace_new_DeviceGray(pgs->memory);
     } else
         pcspace = ppmap->pcspace;
     gs_gsave(pgs);
@@ -715,7 +711,7 @@
 			bool mask,
 			const gs_matrix * pmat,
 			long id,
-			const gs_color_space * pcspace,
+			gs_color_space * pcspace,
 			uint white_index,
 			gs_state * pgs,
 			gs_memory_t * mem

Modified: trunk/gs/src/gsptype1.h
===================================================================
--- trunk/gs/src/gsptype1.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gsptype1.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -56,7 +56,7 @@
  */
 extern int gs_cspace_build_Pattern1(
 				    gs_color_space ** ppcspace,
-				    const gs_color_space * pbase_cspace,
+				    gs_color_space * pbase_cspace,
 				    gs_memory_t * pmem
 				    );
 
@@ -116,7 +116,7 @@
 				bool mask,
 				const gs_matrix * pmat,
 				long id,
-				const gs_color_space * pcspace,
+				gs_color_space * pcspace,
 				uint white_index,
 				gs_state * pgs,
 				gs_memory_t * mem

Modified: trunk/gs/src/gsrefct.h
===================================================================
--- trunk/gs/src/gsrefct.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gsrefct.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -54,7 +54,12 @@
 /* ------ Allocate/free ------ */
 
 rc_free_proc(rc_free_struct_only);
-/* rc_init[_free] is only used to initialize stack-allocated structures. */
+/*
+ * rc_init[_free] really should be used only to initialize
+ * stack-allocated structures; with heap-allocated structures, it's
+ * better to use a finalize method so that the garbage collector can
+ * clean them up if the refcount fails to reach zero. 
+ */
 #define rc_init_free(vp, mem, rcinit, proc)\
   BEGIN\
     (vp)->rc.ref_count = rcinit;\

Modified: trunk/gs/src/gsstate.c
===================================================================
--- trunk/gs/src/gsstate.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gsstate.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -139,7 +139,6 @@
     gx_path *path;
     gx_clip_path *clip_path;
     gx_clip_path *effective_clip_path;
-    gs_color_space *color_space;
     gs_client_color *ccolor;
     gx_device_color *dev_color;
 } gs_state_parts;
@@ -147,7 +146,6 @@
 #define GSTATE_ASSIGN_PARTS(pto, pfrom)\
   ((pto)->path = (pfrom)->path, (pto)->clip_path = (pfrom)->clip_path,\
    (pto)->effective_clip_path = (pfrom)->effective_clip_path,\
-   (pto)->color_space = (pfrom)->color_space,\
    (pto)->ccolor = (pfrom)->ccolor, (pto)->dev_color = (pfrom)->dev_color)
 
 /* GC descriptors */
@@ -248,7 +246,7 @@
     pgs->effective_clip_path = pgs->clip_path;
     pgs->effective_clip_shared = true;
     /* Initialize things so that gx_remap_color won't crash. */
-    gs_cspace_init_DeviceGray(pgs->memory, pgs->color_space);
+    pgs->color_space = gs_cspace_new_DeviceGray(pgs->memory);
     pgs->in_cachedevice = 0;
     gx_set_device_color_1(pgs); /* sets colorspace and client color */
     pgs->device = 0;		/* setting device adjusts refcts */
@@ -791,7 +789,6 @@
 {
     gs_free_object(mem, parts->dev_color, cname);
     gs_free_object(mem, parts->ccolor, cname);
-    gs_free_object(mem, parts->color_space, cname);
     if (!parts->effective_clip_shared)
 	gx_cpath_free(parts->effective_clip_path, cname);
     gx_cpath_free(parts->clip_path, cname);
@@ -824,16 +821,14 @@
 				  "gstate_alloc_parts(effective_clip_path)");
 	parts->effective_clip_shared = false;
     }
-    parts->color_space =
-	gs_alloc_struct(mem, gs_color_space, &st_color_space, cname);
+    parts->color_space = NULL;
     parts->ccolor =
 	gs_alloc_struct(mem, gs_client_color, &st_client_color, cname);
     parts->dev_color =
 	gs_alloc_struct(mem, gx_device_color, &st_device_color, cname);
     if (parts->path == 0 || parts->clip_path == 0 ||
 	parts->effective_clip_path == 0 ||
-	parts->color_space == 0 || parts->ccolor == 0 ||
-	parts->dev_color == 0
+	parts->ccolor == 0 || parts->dev_color == 0
 	) {
 	gstate_free_parts(parts, mem, cname);
 	return_error(gs_error_VMerror);
@@ -908,7 +903,6 @@
     gs_imager_state_copied((gs_imager_state *)pgs);
     /* Don't do anything to clip_stack. */
     rc_increment(pgs->device);
-    *parts.color_space = *pfrom->color_space;
     *parts.ccolor = *pfrom->ccolor;
     *parts.dev_color = *pfrom->dev_color;
     if (reason == copy_for_gsave) {
@@ -989,10 +983,8 @@
     } else
 	gx_cpath_assign_preserve(pto->effective_clip_path,
 				 pfrom->effective_clip_path);
-    *parts.color_space = *pfrom->color_space;
     *parts.ccolor = *pfrom->ccolor;
     *parts.dev_color = *pfrom->dev_color;
-    cs_adjust_counts(pto, 1);
     /* Handle references from gstate object. */
 #define RCCOPY(element)\
     rc_pre_assign(pto->element, pfrom->element, cname)
@@ -1022,6 +1014,7 @@
 	}
     }
     GSTATE_ASSIGN_PARTS(pto, &parts);
+    cs_adjust_counts(pto, 1);
 #undef RCCOPY
     pto->show_gstate =
 	(pfrom->show_gstate == pfrom ? pto : 0);

Modified: trunk/gs/src/gxcdevn.h
===================================================================
--- trunk/gs/src/gxcdevn.h	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gxcdevn.h	2007-03-05 21:09:35 UTC (rev 7765)
@@ -49,7 +49,7 @@
 struct gs_device_n_attributes_s {
     rc_header rc;
     gs_separation_name colorant_name;
-    gs_color_space cspace;
+    gs_color_space *cspace;
     struct gs_device_n_attributes_s * next;	/* Linked list */
 };
 #define private_st_device_n_attributes() /* in gscdevn.c */\

Modified: trunk/gs/src/gxclpath.c
===================================================================
--- trunk/gs/src/gxclpath.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gxclpath.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -527,8 +527,7 @@
 	    const gs_color_space *pcs = cldev->color_space.space;
 	    int hival = pcs->params.indexed.hival;
 	    uint num_values = (hival + 1) *
-		gs_color_space_num_components(
-		    (const gs_color_space *)&pcs->params.indexed.base_space);
+		gs_color_space_num_components(pcs->base_space);
 	    bool use_proc = cldev->color_space.byte1 & 4;
 	    const void *map_data;
 	    uint map_size;

Modified: trunk/gs/src/gxclrast.c
===================================================================
--- trunk/gs/src/gxclrast.c	2007-03-05 17:12:51 UTC (rev 7764)
+++ trunk/gs/src/gxclrast.c	2007-03-05 21:09:35 UTC (rev 7765)
@@ -195,8 +195,7 @@
 private int read_set_misc2(command_buf_t *pcb, gs_imager_state *pis,
                            segment_notes *pnotes);
 private int read_set_color_space(command_buf_t *pcb, gs_imager_state *pis,
-                                 const gs_color_space **ppcs,
-                                 gs_color_space *pcolor_space,
+                                 gs_color_space **ppcs,
                                  gs_memory_t *mem);
 private int read_begin_image(command_buf_t *pcb, gs_image_common_t *pic,
                              const gs_color_space *pcs);
@@ -280,9 +279,7 @@
 	gs_image4_t i4;
     } image;
     gs_int_rect image_rect;
-    gs_color_space color_space;	/* only used for indexed spaces */
-    const gs_color_space *pcs;
-    gs_color_space cs;
+    gs_color_space *pcs;
     gx_image_enum_common_t *image_info;
     gx_image_plane_t planes[32];
     uint data_height;
@@ -348,11 +345,8 @@
     gx_imager_setscreenphase(&imager_state, -x0, -y0, gs_color_select_all);
     halftone_type = ht_type_none;
     fill_params.fill_zero_width = false;
-    gs_cspace_init_DeviceGray(mem, &cs);
-    pcs = &cs;
+    pcs = gs_cspace_new_DeviceGray(mem);
     color_unset(&dev_color);
-    color_space.params.indexed.use_proc = 0;
-    color_space.params.indexed.lookup.table.size = 0;
     data_bits = gs_alloc_bytes(mem, data_bits_size,
 			       "clist_playback_band(data_bits)");
     if (data_bits == 0) {
@@ -1009,7 +1003,7 @@
 		    case cmd_opv_set_color_space:
 			cbuf.ptr = cbp;
 			code = read_set_color_space(&cbuf, &imager_state,
-						    &pcs, &color_space, mem);
+						    &pcs, mem);
 			cbp = cbuf.ptr;
 			if (code < 0) {
 			    if (code == gs_error_rangecheck)
@@ -1522,11 +1516,7 @@
     ht_buff.ht_size = 0;
     ht_buff.read_size = 0;
 
-    if (color_space.params.indexed.lookup.table.size)
-        gs_free_const_string(mem,
-			     color_space.params.indexed.lookup.table.data,
-			     color_space.