[gs-cvs] rev 9071 - trunk/gs/base

leonardo at ghostscript.com leonardo at ghostscript.com
Thu Sep 4 08:47:26 PDT 2008


Author: leonardo
Date: 2008-09-04 08:46:56 -0700 (Thu, 04 Sep 2008)
New Revision: 9071

Added:
   trunk/gs/base/gxblend1.c
Modified:
   trunk/gs/base/gdevdevn.h
   trunk/gs/base/gdevp14.c
   trunk/gs/base/gdevp14.h
   trunk/gs/base/gxblend.c
   trunk/gs/base/gxblend.h
   trunk/gs/base/lib.mak
Log:
Fix : Divide gdevp14.c into 2 modules.

DETAILS :

This change is syntactically equivalent.
The purpose is to minimize dependencies between projects.
The new module gxblend1.c keeps color blending algorithms moved from gdevp14.

EXPECTED DIFFERENCES :

None.


Modified: trunk/gs/base/gdevdevn.h
===================================================================
--- trunk/gs/base/gdevdevn.h	2008-09-04 14:06:17 UTC (rev 9070)
+++ trunk/gs/base/gdevdevn.h	2008-09-04 15:46:56 UTC (rev 9071)
@@ -64,11 +64,16 @@
 /*
  * Structure for holding SeparationNames elements.
  */
-typedef struct gs_separations_s {
+struct gs_separations_s {
     int num_separations;
     devn_separation_name names[GX_DEVICE_MAX_SEPARATIONS];
-} gs_separations;
+};
 
+#ifndef gs_separations_DEFINED
+#   define gs_separations_DEFINED
+    typedef struct gs_separations_s gs_separations;
+#endif
+
 /*
  * Type for holding a separation order map
  */

Modified: trunk/gs/base/gdevp14.c
===================================================================
--- trunk/gs/base/gdevp14.c	2008-09-04 14:06:17 UTC (rev 9070)
+++ trunk/gs/base/gdevp14.c	2008-09-04 15:46:56 UTC (rev 9071)
@@ -62,12 +62,6 @@
 
 #define CUSTOM_BLENDING_MODE AUTO_USE_CUSTOM_BLENDING
 
-/* #define DUMP_TO_PNG */
-
-#ifdef DUMP_TO_PNG
-#include "png_.h"
-#endif
-
 # define INCR(v) DO_NOTHING
 
 /* Prototypes to quiet gcc warnings */
@@ -77,8 +71,6 @@
 
 /* Buffer stack	data structure */
 
-#define	PDF14_MAX_PLANES GX_DEVICE_COLOR_MAX_COMPONENTS
-
 gs_private_st_ptrs4(st_pdf14_buf, pdf14_buf, "pdf14_buf",
 		    pdf14_buf_enum_ptrs, pdf14_buf_reloc_ptrs,
 		    saved, data, transfer_fn, maskbuf);
@@ -87,115 +79,7 @@
 		    pdf14_ctx_enum_ptrs, pdf14_ctx_reloc_ptrs,
 		    stack, maskbuf);
 
-/*
- * Unpack a device color.  This routine is similar to the device's
- * decode_color procedure except for two things.  The procedure produces 1
- * byte values instead of gx_color_values (2 bytes) and the output values
- * are inverted for subtractive color spaces (like CMYK).  A separate
- * procedure is used instead of the decode_color to minimize execution time.
- */
-static void
-pdf14_unpack_additive(int num_comp, gx_color_index color,
-			       	pdf14_device * p14dev, byte * out)
-{
-    int i;
 
-    for (i = num_comp - 1; i >= 0; i--) {
-	out[i] = (byte)(color & 0xff);
-	color >>= 8;
-    }
-}
-
-/*
- * Unpack a device color.  This routine is similar to the device's
- * decode_color procedure except for two things.  The procedure produces 1
- * byte values instead of gx_color_values (2 bytes) and the output values
- * are inverted for subtractive color spaces (like CMYK).  A separate
- * procedure is used instead of the decode_color to minimize execution time.
- */
-static void
-pdf14_unpack_subtractive(int num_comp, gx_color_index color,
-			       	pdf14_device * p14dev, byte * out)
-{
-    int i;
-
-    for (i = num_comp - 1; i >= 0; i--) {
-	out[i] = 0xff - (byte)(color & 0xff);
-	color >>= 8;
-    }
-}
-
-/*
- * Unpack a 'compressed' CMYK color index.  The color index value is unpacked
- * into a set of 8 bit values.  For more information about 'compressed' color
- * index values see the comments before the devn_encode_compressed_color routine.
- *
- * Note: For simplicity of coding the calling routines, this routine will also
- * handle 'uncompressed' color index values.
- */
-static void
-pdf14_unpack_compressed(int num_comp, gx_color_index color,
-			       	pdf14_device * p14dev, byte * out)
-{
-    int comp_num;
-
-    if (p14dev->devn_params.compressed_color_list == NULL) {
-        /*
-         * For 'uncompressed' data we simply have to unpack the gx_color_index
-	 * value directly.
-         */
-        for (comp_num = num_comp - 1; comp_num >= 0; comp_num--) {
-	    out[comp_num] = 0xff - (byte)(color & 0xff);
-	    color >>= 8;
-        }
-    }
-    else {
-        int factor, bit_count, bit_mask;
-        comp_bit_map_list_t * pbitmap;
-        gx_color_value solid_color = 0xff;
-
-    	pbitmap = find_bit_map(color,
-		       	p14dev->devn_params.compressed_color_list);
-	bit_count = num_comp_bits[pbitmap->num_non_solid_comp];
-	bit_mask = (1 << bit_count) - 1;
-	factor = comp_bit_factor[pbitmap->num_non_solid_comp];
-	if (pbitmap->solid_not_100) {
-	    solid_color = 0xff - ((factor * ((int)color & bit_mask)) >> 16);
-	    color >>= bit_count;
-	}
-        for (comp_num = 0; comp_num < num_comp; comp_num++) {
-	    if (colorant_present(pbitmap, colorants, comp_num)) {
-		if (colorant_present(pbitmap, solid_colorants, comp_num))
-       		    *out++ = (byte)solid_color;
-		else {
-            	    *out++ = 0xff - ((factor * ((int)color & bit_mask)) >> 16);
-	    	    color >>= bit_count;
-		}
-	    }
-	    else
-            	*out++ = 0xff;
-        }
-    }
-}
-
-/*
- * Unpack a device color.  This routine is used for devices in which we do
- * not know the details of the process color model.  In this case we use
- * the device's decode_color procedure.
- */
-static void
-pdf14_unpack_custom(int num_comp, gx_color_index color,
-			       	pdf14_device * p14dev, byte * out)
-{
-    int i;
-    gx_device * tdev = p14dev->target;
-    gx_color_value cm_values[GX_DEVICE_COLOR_MAX_COMPONENTS];
-
-    dev_proc(tdev, decode_color)(tdev, color, cm_values);
-    for (i = 0; i < num_comp; i++)
-	out[i] = 0xff - gx_color_value_to_byte(cm_values[i]);
-}
-
 /* ------ The device descriptors ------	*/
 
 /*
@@ -210,10 +94,10 @@
 static	dev_proc_put_params(pdf14_put_params);
 static	dev_proc_get_color_comp_index(pdf14_cmykspot_get_color_comp_index);
 static	dev_proc_get_color_mapping_procs(pdf14_cmykspot_get_color_mapping_procs);
-static	dev_proc_encode_color(pdf14_encode_color);
-static	dev_proc_encode_color(pdf14_compressed_encode_color);
-static	dev_proc_decode_color(pdf14_decode_color);
-static	dev_proc_decode_color(pdf14_compressed_decode_color);
+dev_proc_encode_color(pdf14_encode_color);
+dev_proc_encode_color(pdf14_compressed_encode_color);
+dev_proc_decode_color(pdf14_decode_color);
+dev_proc_decode_color(pdf14_compressed_decode_color);
 static	dev_proc_fill_rectangle(pdf14_fill_rectangle);
 static	dev_proc_fill_rectangle(pdf14_mark_fill_rectangle);
 static	dev_proc_fill_rectangle(pdf14_mark_fill_rectangle_ko_simple);
@@ -697,42 +581,12 @@
 	return 0;
 
     backdrop = pdf14_find_backdrop_buf(ctx);
-    if (backdrop == NULL) {
+    if (backdrop == NULL)
 	memset(buf->data, 0, buf->planestride * (buf->n_chan +
 						 (buf->has_shape ? 1 : 0)));
-    } else {
-	/* make copy of backdrop for compositing */
-	int x0 = max(buf->rect.p.x, tos->rect.p.x);
-	int x1 = min(buf->rect.q.x, tos->rect.q.x);
-	int y0 = max(buf->rect.p.y, tos->rect.p.y);
-	int y1 = min(buf->rect.q.y, tos->rect.q.y);
-
-	if (x0 < x1 && y0 < y1) {
-	    int width = x1 - x0;
-	    byte *buf_plane = buf->data + x0 - buf->rect.p.x + (y0 - buf->rect.p.y) * buf->rowstride;
-	    byte *tos_plane = tos->data + x0 - tos->rect.p.x + (y0 - tos->rect.p.y) * tos->rowstride;
-	    int i;
-	    int n_chan_copy = buf->n_chan + (tos->has_shape ? 1 : 0);
-
-	    for (i = 0; i < n_chan_copy; i++) {
-			byte *buf_ptr = buf_plane;
-			byte *tos_ptr = tos_plane;
-			int y;
-	
-			for (y = y0; y < y1; ++y) {
-				memcpy (buf_ptr, tos_ptr, width); 
-				buf_ptr += buf->rowstride;
-				tos_ptr += tos->rowstride;
-			}
-			buf_plane += buf->planestride;
-			tos_plane += tos->planestride;
-		}
-	    if (has_shape && !tos->has_shape)
-			memset (buf_plane, 0, buf->planestride);
-		}
-	}
-
-	return 0;
+    else 
+	pdf14_preserve_backdrop(buf, tos, has_shape);
+    return 0;
 }
 
 static	int
@@ -780,164 +634,10 @@
 	x0 = max(x0, maskbuf->rect.p.x);
 	x1 = min(x1, maskbuf->rect.q.x);
     }
-    if (x0 < x1 && y0 < y1) {
-	int n_chan = ctx->n_chan;
-	int num_comp = n_chan - 1;
-	byte alpha = tos->alpha;
-	byte shape = tos->shape;
-	byte blend_mode = tos->blend_mode;
-	byte *tos_ptr = tos->data + x0 - tos->rect.p.x +
-	    (y0 - tos->rect.p.y) * tos->rowstride;
-	byte *nos_ptr = nos->data + x0 - nos->rect.p.x +
-	    (y0 - nos->rect.p.y) * nos->rowstride;
-	byte *mask_ptr = NULL;
-	int tos_planestride = tos->planestride;
-	int nos_planestride = nos->planestride;
-	int mask_planestride = 0x0badf00d; /* Quiet compiler. */
-	byte mask_bg_alpha = 0; /* Quiet compiler. */
-	int width = x1 - x0;
-	int x, y;
-	int i;
-	byte tos_pixel[PDF14_MAX_PLANES];
-	byte nos_pixel[PDF14_MAX_PLANES];
-	bool tos_isolated = tos->isolated;
-	bool nos_knockout = nos->knockout;
-	byte *nos_alpha_g_ptr;
-	int tos_shape_offset = n_chan * tos_planestride;
-	int tos_alpha_g_offset = tos_shape_offset +
-	(tos->has_shape ? tos_planestride : 0);
-	int nos_shape_offset = n_chan * nos_planestride;
-	bool nos_has_shape = nos->has_shape;
-	byte *mask_tr_fn = NULL; /* Quiet compiler. */
-	bool additive = ctx->additive;
+    if (x0 < x1 && y0 < y1)
+	pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1, 
+		ctx->n_chan, ctx->additive, pblend_procs);
 
-	rect_merge(nos->bbox, tos->bbox);
-
-	if_debug6('v', "pdf14_pop_transparency_group y0 = %d, y1 = %d, w = %d, alpha = %d, shape = %d, bm = %d\n",
-			    y0, y1, width, alpha, shape, blend_mode);
-	if (nos->has_alpha_g)
-	    nos_alpha_g_ptr = nos_ptr + n_chan * nos_planestride;
-	else
-	    nos_alpha_g_ptr = NULL;
-
-	if (maskbuf != NULL) {
-	    mask_ptr = maskbuf->data + x0 - maskbuf->rect.p.x +
-		    (y0 - maskbuf->rect.p.y) * maskbuf->rowstride;
-	    mask_planestride = maskbuf->planestride;
-	    mask_bg_alpha = maskbuf->alpha;
-	    mask_tr_fn = maskbuf->transfer_fn;
-	}
-
-	for (y = y0; y < y1; ++y) {
-	    for (x = 0; x < width; ++x) {
-		byte pix_alpha = alpha;
-
-		/* Complement the components for subtractive color spaces */
-		if (additive) {
-		    for (i = 0; i < n_chan; ++i) {
-			tos_pixel[i] = tos_ptr[x + i * tos_planestride];
-			nos_pixel[i] = nos_ptr[x + i * nos_planestride];
-		    }
-		} else {
-		    for (i = 0; i < num_comp; ++i) {
-			tos_pixel[i] = 255 - tos_ptr[x + i * tos_planestride];
-			nos_pixel[i] = 255 - nos_ptr[x + i * nos_planestride];
-		    }
-		    tos_pixel[num_comp] = tos_ptr[x + num_comp * tos_planestride];
-		    nos_pixel[num_comp] = nos_ptr[x + num_comp * nos_planestride];
-		}
-
-		if (mask_ptr != NULL) {
-		    int mask_alpha = mask_ptr[x + num_comp * mask_planestride];
-		    int tmp;
-		    byte mask;
-
-			/*
-			* The mask data is really monochrome.  Thus for additive (RGB)
-			* we use the R channel for alpha since R = G = B.  For
-			* subtractive (CMYK) we use the K channel.
-			*/
-		    if (mask_alpha == 255) {
-			/* todo: rgba->mask */
-			mask = additive ? mask_ptr[x]
-					: 255 - mask_ptr[x + 3 * mask_planestride];
-		    } else if (mask_alpha == 0)
-			mask = mask_bg_alpha;
-		    else {
-			int t2 = additive ? mask_ptr[x]
-					: 255 - mask_ptr[x + 3 * mask_planestride];
-
-			t2 = (t2 - mask_bg_alpha) * mask_alpha + 0x80;
-			mask = mask_bg_alpha + ((t2 + (t2 >> 8)) >> 8);
-		    }
-		    mask = mask_tr_fn[mask];
-		    tmp = pix_alpha * mask + 0x80;
-		    pix_alpha = (tmp + (tmp >> 8)) >> 8;
-#		    if VD_PAINT_MASK
-			vd_pixel(int2fixed(x), int2fixed(y), mask);
-#		    endif
-		}
-
-		if (nos_knockout) {
-		    byte *nos_shape_ptr = nos_has_shape ?
-			&nos_ptr[x + nos_shape_offset] : NULL;
-		    byte tos_shape = tos_ptr[x + tos_shape_offset];
-
-		    art_pdf_composite_knockout_isolated_8(nos_pixel,
-							nos_shape_ptr,
-							tos_pixel,
-							n_chan - 1,
-							tos_shape,
-							pix_alpha, shape);
-		} else if (tos_isolated) {
-		    art_pdf_composite_group_8(nos_pixel, nos_alpha_g_ptr,
-					tos_pixel, n_chan - 1,
-					pix_alpha, blend_mode, pblend_procs);
-		} else {
-		    byte tos_alpha_g = tos_ptr[x + tos_alpha_g_offset];
-		    art_pdf_recomposite_group_8(nos_pixel, nos_alpha_g_ptr,
-					tos_pixel, tos_alpha_g, n_chan - 1,
-					pix_alpha, blend_mode, pblend_procs);
-		}
-		if (nos_has_shape) {
-		    nos_ptr[x + nos_shape_offset] =
-			art_pdf_union_mul_8 (nos_ptr[x + nos_shape_offset],
-						tos_ptr[x + tos_shape_offset],
-						shape);
-		}
-	    
-		/* Complement the results for subtractive color spaces */
-		if (additive) {
-		    for (i = 0; i < n_chan; ++i) {
-			nos_ptr[x + i * nos_planestride] = nos_pixel[i];
-		    }
-		} else {
-		    for (i = 0; i < num_comp; ++i)
-			nos_ptr[x + i * nos_planestride] = 255 - nos_pixel[i];
-		    nos_ptr[x + num_comp * nos_planestride] = nos_pixel[num_comp];
-		}
-#		if VD_PAINT_COLORS
-		    vd_pixel(int2fixed(x), int2fixed(y), n_chan == 1 ? 
-			(nos_pixel[0] << 16) + (nos_pixel[0] << 8) + nos_pixel[0] :
-			(nos_pixel[0] << 16) + (nos_pixel[1] << 8) + nos_pixel[2]);
-#		endif
-#		if VD_PAINT_ALPHA
-		    vd_pixel(int2fixed(x), int2fixed(y),
-			(nos_pixel[n_chan - 1] << 16) + (nos_pixel[n_chan - 1] << 8) + 
-			 nos_pixel[n_chan - 1]);
-#		endif
-		if (nos_alpha_g_ptr != NULL)
-		    ++nos_alpha_g_ptr;
-	    }
-	    tos_ptr += tos->rowstride;
-	    nos_ptr += nos->rowstride;
-	    if (nos_alpha_g_ptr != NULL)
-		nos_alpha_g_ptr += nos->rowstride - width;
-	    if (mask_ptr != NULL)
-		mask_ptr += maskbuf->rowstride;
-	}
-    }
-
 exit:
     ctx->stack = nos;
     {	/* If this group is one for an image with soft mask,
@@ -1048,242 +748,16 @@
     return 0;
 }
 
-/*
- * Encode a list of colorant values into a gx_color_index_value.
- */
-static	gx_color_index
-pdf14_encode_color(gx_device *dev, const gx_color_value	colors[])
-{
-    int drop = sizeof(gx_color_value) * 8 - 8;
-    gx_color_index color = 0;
-    int i;
-    int ncomp = dev->color_info.num_components;
-
-    for (i = 0; i < ncomp; i++) {
-	color <<= 8;
-	color |= (colors[i] >> drop);
-    }
-    return (color == gx_no_color_index ? color ^ 1 : color);
-}
-
-/*
- * Decode a gx_color_index value back to a list of colorant values.
- */
-static	int
-pdf14_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
-{
-    int i;
-    int ncomp = dev->color_info.num_components;
-
-    for (i = 0; i < ncomp; i++) {
-	out[ncomp - i - 1] = (gx_color_value) ((color & 0xff) * 0x101);
-	color >>= 8;
-    }
-    return 0;
-}
-
-/*
- * Encode a list of colorant values into a gx_color_index_value.  For more
- * information about 'compressed' color index values see the comments before
- * the devn_encode_compressed_color routine.
- */
-static gx_color_index
-pdf14_compressed_encode_color(gx_device *dev, const gx_color_value colors[])
-{
-    return devn_encode_compressed_color(dev, colors,
-		    &(((pdf14_device *)dev)->devn_params));
-}
-
-/*
- * Decode a gx_color_index value back to a list of colorant values.  For more
- * information about 'compressed' color index values see the comments before
- * the devn_encode_compressed_color routine.
- */
-static int
-pdf14_compressed_decode_color(gx_device * dev, gx_color_index color,
-	       						gx_color_value * out)
-{
-    return devn_decode_compressed_color(dev, color, out,
-		    &(((pdf14_device *)dev)->devn_params));
-}
-
-static void
-pdf14_gray_cs_to_cmyk_cm(gx_device * dev, frac gray, frac out[])
-{
-    int num_comp = dev->color_info.num_components;
-
-    out[0] = out[1] = out[2] = frac_0;
-    out[3] = frac_1 - gray;
-    for (--num_comp; num_comp > 3; num_comp--)
-	out[num_comp] = 0;
-}
-
-/*
- * Default map from DeviceRGB color space to DeviceCMYK color
- * model. Since this mapping is defined by the PostScript language
- * it is unlikely that any device with a DeviceCMYK color model
- * would define this mapping on its own.
- *
- * If the imager state is not available, map as though the black
- * generation and undercolor removal functions are identity
- * transformations. This mode is used primarily to support the
- * raster operation (rop) feature of PCL, which requires that
- * the raster operation be performed in an RGB color space.
- * Note that default black generation and undercolor removal
- * functions in PostScript need NOT be identity transformations:
- * often they are { pop 0 }.
- */
-static void
-pdf14_rgb_cs_to_cmyk_cm(gx_device * dev, const gs_imager_state *pis,
-  			   frac r, frac g, frac b, frac out[])
-{
-    int num_comp = dev->color_info.num_components;
-
-    if (pis != 0)
-        color_rgb_to_cmyk(r, g, b, pis, out);
-    else {
-        frac    c = frac_1 - r, m = frac_1 - g, y = frac_1 - b;
-        frac    k = min(c, min(m, g));
-
-        out[0] = c - k;
-        out[1] = m - k;
-        out[2] = y - k;
-        out[3] = k;
-    }
-    for (--num_comp; num_comp > 3; num_comp--)
-	out[num_comp] = 0;
-}
-
-void
-pdf14_cmyk_cs_to_cmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
-{
-    int num_comp = dev->color_info.num_components;
-
-    out[0] = c;
-    out[1] = m;
-    out[2] = y;
-    out[3] = k;
-    for (--num_comp; num_comp > 3; num_comp--)
-	out[num_comp] = 0;
-}
 static const gx_cm_color_map_procs pdf14_DeviceCMYKspot_procs = {
     pdf14_gray_cs_to_cmyk_cm, pdf14_rgb_cs_to_cmyk_cm, pdf14_cmyk_cs_to_cmyk_cm
 };
 
-const gx_cm_color_map_procs *
+static const gx_cm_color_map_procs *
 pdf14_cmykspot_get_color_mapping_procs(const gx_device * dev)
 {
     return &pdf14_DeviceCMYKspot_procs;
 }
 
-#ifdef DUMP_TO_PNG
-/* Dumps a planar RGBA image to	a PNG file. */
-static	int
-dump_planar_rgba(gs_memory_t *mem, const pdf14_buf *pbuf)
-		 const byte *buf, int width, int height, int rowstride, int planestride)
-{
-    int rowstride = pbuf->rowstride, planestride = pbuf->planestride;
-    int rowbytes = width << 2;
-    gs_int_rect rect = buf->rect;
-    int x1 = min(pdev->width, rect.q.x);
-    int y1 = min(pdev->height, rect.q.y);
-    int width = x1 - rect.p.x;
-    int height = y1 - rect.p.y;
-    byte *buf_ptr = buf->data + rect.p.y * buf->rowstride + rect.p.x;
-    byte *row = gs_malloc(mem, rowbytes, 1, "png raster buffer");
-    png_struct *png_ptr =
-    png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-    png_info *info_ptr =
-    png_create_info_struct(png_ptr);
-    const char *software_key = "Software";
-    char software_text[256];
-    png_text text_png;
-    FILE *file;
-    int code;
-    int y;
-
-    if (buf->data == NULL)
-	return 0;
-
-    file = fopen ("c:\\temp\\tmp.png", "wb");
-
-    if_debug0('v', "[v]pnga_output_page\n");
-
-    if (row == 0 || png_ptr == 0 || info_ptr == 0) {
-	code = gs_note_error(gs_error_VMerror);
-	goto done;
-    }
-    /* set error handling */
-    if (setjmp(png_ptr->jmpbuf)) {
-	/* If we get here, we had a problem reading the file */
-	code = gs_note_error(gs_error_VMerror);
-	goto done;
-    }
-
-    code = 0;			/* for normal path */
-    /* set up the output control */
-    png_init_io(png_ptr, file);
-
-    /* set the file information here */
-    info_ptr->width = width;
-    info_ptr->height = height;
-    /* resolution is in pixels per meter vs. dpi */
-    info_ptr->x_pixels_per_unit =
-	(png_uint_32) (96.0 * (100.0 / 2.54));
-    info_ptr->y_pixels_per_unit =
-	(png_uint_32) (96.0 * (100.0 / 2.54));
-    info_ptr->phys_unit_type = PNG_RESOLUTION_METER;
-    info_ptr->valid |= PNG_INFO_pHYs;
-
-    /* At present, only supporting 32-bit rgba */
-    info_ptr->bit_depth = 8;
-    info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
-
-    /* add comment */
-    sprintf(software_text, "%s %d.%02d", gs_product,
-	    (int)(gs_revision / 100), (int)(gs_revision % 100));
-    text_png.compression = -1;	/* uncompressed */
-    text_png.key = (char *)software_key;	/* not const, unfortunately */
-    text_png.text = software_text;
-    text_png.text_length = strlen(software_text);
-    info_ptr->text = &text_png;
-    info_ptr->num_text = 1;
-
-    /* write the file information */
-    png_write_info(png_ptr, info_ptr);
-
-    /* don't write the comments twice */
-    info_ptr->num_text = 0;
-    info_ptr->text = NULL;
-
-    /* Write the contents of the image. */
-    for (y = 0; y < height; ++y) {
-	int x;
-
-	for (x = 0; x < width; ++x) {
-	    row[(x << 2)] = buf_ptr[x];
-	    row[(x << 2) + 1] = buf_ptr[x + planestride];
-	    row[(x << 2) + 2] = buf_ptr[x + planestride * 2];
-	    row[(x << 2) + 3] = buf_ptr[x + planestride * 3];
-	}
-	png_write_row(png_ptr, row);
-	buf_ptr += rowstride;
-    }
-
-    /* write the rest of the file */
-    png_write_end(png_ptr, info_ptr);
-
-  done:
-    /* free the structures */
-    png_destroy_write_struct(&png_ptr, &info_ptr);
-    gs_free(mem, row, rowbytes, 1, "png raster buffer");
-
-    fclose (file);
-    return code;
-}
-#endif
-
-
 /**
  * pdf14_put_image: Put rendered image to target device.
  * @pdev: The PDF 1.4 rendering device.
@@ -1306,7 +780,6 @@
     pdf14_buf *buf = pdev->ctx->stack;
     gs_int_rect rect = buf->rect;
     int y;
-    int planestride = buf->planestride;
     int num_comp = buf->n_chan - 1;
     byte *linebuf;
     gs_color_space *pcs;
@@ -1379,36 +852,9 @@
     linebuf = gs_alloc_bytes(pdev->memory, width * num_comp, "pdf14_put_image");
     for (y = 0; y < height; y++) {
 	gx_image_plane_t planes;
-	int x;
 	int rows_used;
 
-	for (x = 0; x < width; x++) {
-	    byte comp, a;
-	    int tmp, comp_num;
-
-	    /* composite RGBA (or CMYKA, etc.) pixel with over solid background */
-	    a = buf_ptr[x + planestride * num_comp];
-
-	    if ((a + 1) & 0xfe) {
-		a ^= 0xff;
-		for (comp_num = 0; comp_num < num_comp; comp_num++) {
-		    comp  = buf_ptr[x + planestride * comp_num];
-		    tmp = ((bg - comp) * a) + 0x80;
-		    comp += (tmp + (tmp >> 8)) >> 8;
-		    linebuf[x * num_comp + comp_num] = comp;
-		}
-	    } else if (a == 0) {
-		for (comp_num = 0; comp_num < num_comp; comp_num++) {
-		    linebuf[x * num_comp + comp_num] = bg;
-		}
-	    } else {
-		for (comp_num = 0; comp_num < num_comp; comp_num++) {
-		    comp = buf_ptr[x + planestride * comp_num];
-		    linebuf[x * num_comp + comp_num] = comp;
-		}
-	    }
-	}
-
+	gx_build_blended_image_row(buf_ptr, y, buf->planestride, width, num_comp, bg, linebuf);
 	planes.data = linebuf;
 	planes.data_x = 0;
 	planes.raster = width * num_comp;
@@ -1447,25 +893,16 @@
 pdf14_cmykspot_put_image(gx_device * dev, gs_imager_state * pis, gx_device * target)
 {
     pdf14_device * pdev = (pdf14_device *)dev;
-    int code = 0;
-    int x, y, tmp, comp_num, output_comp_num;
     pdf14_buf *buf = pdev->ctx->stack;
     gs_int_rect rect = buf->rect;
-    int planestride = buf->planestride;
-    int num_comp = buf->n_chan - 1;
-    const byte bg = pdev->ctx->additive ? gx_max_color_value : 0;
-    gx_color_index color;
-    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
-    gx_color_value comp;
-    byte a;
-    int input_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
-    int output_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
-    int num_known_comp = 0;
-    int output_num_comp = target->color_info.num_components;
+    int x0 = rect.p.x, y0 = rect.p.y;
+    int x1, y1, width, height;
     gs_devn_params * pdevn_params = &pdev->devn_params;
     gs_separations * pseparations = &pdevn_params->separations;
-    int num_sep = pseparations->num_separations++;
-    int x1, y1, width, height;
+    int planestride = buf->planestride;
+    int rowstride = buf->rowstride;
+    const byte bg = pdev->ctx->additive ? gx_max_color_value : 0;
+    int num_comp = buf->n_chan - 1;
     byte *buf_ptr;
 
     if_debug0('v', "[v]pdf14_cmykspot_put_image\n");
@@ -1476,78 +913,10 @@
     height = y1 - rect.p.y;
     if (width <= 0 || height <= 0 || buf->data == NULL)
 	return 0;
-    buf_ptr = buf->data + rect.p.y * buf->rowstride + rect.p.x;
+    buf_ptr = buf->data + y0 * buf->rowstride + x0;
 
-    /*
-     * The process color model for the PDF 1.4 compositor device is CMYK plus
-     * spot colors.  The target device may have only some of these colorants due
-     * to the SeparationOrder device parameter.  Thus we need to determine the
-     * mapping between the PDF 1.4 compositor and the target device.  Note:
-     * There should not be a spot colorant in the PDF 1.4 device that is not
-     * present in the target device.
-     */
-    /* Check if target processes CMYK colorants. */
-    for (comp_num = 0; comp_num < 4; comp_num++) {
-	const char * pcomp_name = (const char *)DeviceCMYKComponents[comp_num]; 
-
-	output_comp_num = dev_proc(target, get_color_comp_index)
-		(target, pcomp_name, strlen(pcomp_name), NO_COMP_NAME_TYPE);
-	if (output_comp_num >=0 &&
-	     	output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
-	    output_map[num_known_comp] = output_comp_num;
-	    input_map[num_known_comp++] = comp_num;
-	}
-    }
-    /* Check if target processes our spot colorants. */
-    for (comp_num = 0; comp_num < num_sep; comp_num++) {
-	output_comp_num = dev_proc(target, get_color_comp_index)
-	       (target, (const char *)(pseparations->names[comp_num].data),
-	       	pseparations->names[comp_num].size,  NO_COMP_NAME_TYPE);
-	if (output_comp_num >= 0 &&
-	     	output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
-	    output_map[num_known_comp] = output_comp_num;
-	    input_map[num_known_comp++] = comp_num + 4;
-	}
-    }
-
-    /* Clear all output colorants first */
-    for (comp_num = 0; comp_num < output_num_comp; comp_num++)
-	cv[comp_num] = 0;
-
-    /* Send pixel data to the target device. */
-    for (y = 0; y < height; y++) {
-	for (x = 0; x < width; x++) {
-
-	    /* composite CMYKA, etc. pixel with over solid background */
-	    a = buf_ptr[x + planestride * num_comp];
-
-	    if ((a + 1) & 0xfe) {
-		a ^= 0xff;
-		for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
-		    comp  = buf_ptr[x + planestride * input_map[comp_num]];
-		    tmp = ((comp - bg) * a) + 0x80;
-		    comp += tmp + (tmp >> 8);
-		    cv[output_map[comp_num]] = comp;
-		}
-	    } else if (a == 0) {
-		for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
-		    cv[output_map[comp_num]] = bg;
-		}
-	    } else {
-		for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
-		    comp = buf_ptr[x + planestride * input_map[comp_num]];
-		    cv[output_map[comp_num]] = (comp << 8) + comp;
-		}
-	    }
-	    color = dev_proc(target, encode_color)(target, cv);
-	    code = dev_proc(target, fill_rectangle)(target, x + rect.p.x, 
-							    y + rect.p.y, 1, 1, color);
-	}
-
-	buf_ptr += buf->rowstride;
-    }
-
-    return code;
+    return gx_put_blended_image_cmykspot(target, buf_ptr, planestride, rowstride,
+		      x0, y0, width, height, num_comp, bg, pseparations);
 }
 
 /**
@@ -1565,17 +934,13 @@
 pdf14_custom_put_image(gx_device * dev, gs_imager_state * pis, gx_device * target)
 {
     pdf14_device * pdev = (pdf14_device *)dev;
-    int code = 0;
-    int x, y, tmp, comp_num;
     pdf14_buf *buf = pdev->ctx->stack;
     gs_int_rect rect = buf->rect;
+    int x0 = rect.p.x, y0 = rect.p.y;
     int planestride = buf->planestride;
+    int rowstride = buf->rowstride;
     int num_comp = buf->n_chan - 1;
     const byte bg = pdev->ctx->additive ? gx_max_color_value : 0;
-    gx_color_index color;
-    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
-    gx_color_value comp;
-    byte a;
     int x1, y1, width, height;
     byte *buf_ptr;
 
@@ -1589,40 +954,9 @@
 	return 0;
     buf_ptr = buf->data + rect.p.y * buf->rowstride + rect.p.x;
 
-    /* Send pixel data to the target device. */
-    for (y = 0; y < height; y++) {
-	for (x = 0; x < width; x++) {
-
-	    /* composite CMYKA, etc. pixel with over solid background */
-	    a = buf_ptr[x + planestride * num_comp];
-
-	    if ((a + 1) & 0xfe) {
-		a ^= 0xff;
-		for (comp_num = 0; comp_num < num_comp; comp_num++) {
-		    comp  = buf_ptr[x + planestride * comp_num];
-		    tmp = ((bg - comp) * a) + 0x80;
-		    comp += tmp + (tmp >> 8);
-		    cv[comp_num] = comp;
-		}
-	    } else if (a == 0) {
-		for (comp_num = 0; comp_num < num_comp; comp_num++) {
-		    cv[comp_num] = bg;
-		}
-	    } else {
-		for (comp_num = 0; comp_num < num_comp; comp_num++) {
-		    comp = buf_ptr[x + planestride * comp_num];
-		    cv[comp_num] = (comp << 8) + comp;
-		}
-	    }
-	    color = dev_proc(target, encode_color)(target, cv);
-	    code = dev_proc(target, fill_rectangle)(target, x + rect.p.x, 
-							    y + rect.p.y, 1, 1, color);
-	}
-
-	buf_ptr += buf->rowstride;
-    }
-
-    return code;
+    return gx_put_blended_image_custom(target, buf_ptr, 
+		      planestride, rowstride,
+		      x0, y0, width, height, num_comp, bg);
 }
 
 static	int

Modified: trunk/gs/base/gdevp14.h
===================================================================
--- trunk/gs/base/gdevp14.h	2008-09-04 14:06:17 UTC (rev 9070)
+++ trunk/gs/base/gdevp14.h	2008-09-04 15:46:56 UTC (rev 9071)
@@ -26,7 +26,11 @@
     PDF14_DeviceCustom = 4
 } pdf14_default_colorspace_t;
 
+#ifndef pdf14_buf_DEFINED
+#  define pdf14_buf_DEFINED
 typedef struct pdf14_buf_s pdf14_buf;
+#endif
+
 typedef struct pdf14_ctx_s pdf14_ctx;
 
 struct pdf14_buf_s {
@@ -88,7 +92,10 @@
 typedef struct gs_pdf14trans_params_s gs_pdf14trans_params_t;
 #endif
 
+#ifndef pdf14_device_DEFINED
+#  define pdf14_device_DEFINED
 typedef struct pdf14_device_s pdf14_device;
+#endif
 
 /*
  * This structure contains procedures for processing routine which differ

Modified: trunk/gs/base/gxblend.c
===================================================================
--- trunk/gs/base/gxblend.c	2008-09-04 14:06:17 UTC (rev 9070)
+++ trunk/gs/base/gxblend.c	2008-09-04 15:46:56 UTC (rev 9071)
@@ -16,7 +16,6 @@
 #include "memory_.h"
 #include "gx.h"
 #include "gstparam.h"
-#include "gxcindex.h"
 #include "gxblend.h"
 
 typedef int art_s32;
@@ -1216,3 +1215,5 @@
     dst[n_chan] = alpha_i;
     *dst_alpha_g = alpha_g_i;
 }
+
+

Modified: trunk/gs/base/gxblend.h
===================================================================
--- trunk/gs/base/gxblend.h	2008-09-04 14:06:17 UTC (rev 9070)
+++ trunk/gs/base/gxblend.h	2008-09-04 15:46:56 UTC (rev 9071)
@@ -16,10 +16,38 @@
 #ifndef gxblend_INCLUDED
 #  define gxblend_INCLUDED
 
+#include "gxcindex.h"
+#include "gxcvalue.h"
+#include "gxfrac.h"
+
+/* #define DUMP_TO_PNG */
+
+#define	PDF14_MAX_PLANES GX_DEVICE_COLOR_MAX_COMPONENTS
+
 typedef bits16 ArtPixMaxDepth;
 
 #define ART_MAX_CHAN GX_DEVICE_COLOR_MAX_COMPONENTS
 
+#ifndef pdf14_device_DEFINED
+#  define pdf14_device_DEFINED
+typedef struct pdf14_device_s pdf14_device;
+#endif
+
+#ifndef pdf14_buf_DEFINED
+#  define pdf14_buf_DEFINED
+typedef struct pdf14_buf_s pdf14_buf;
+#endif
+
+#ifndef gx_device_DEFINED
+#  define gx_device_DEFINED
+typedef struct gx_device_s gx_device;
+#endif
+
+#ifndef gs_separations_DEFINED
+#   define gs_separations_DEFINED
+    typedef struct gs_separations_s gs_separations;
+#endif
+
 /*
  * This structure contains procedures for processing which differ
  * between the different blending color spaces.
@@ -293,4 +321,43 @@
 void art_blend_saturation_custom_8(int n_chan, byte *dst, const byte *backdrop,
 			   const byte *src);
 
+void pdf14_unpack_additive(int num_comp, gx_color_index color,
+			       	pdf14_device * p14dev, byte * out);
+void pdf14_unpack_subtractive(int num_comp, gx_color_index color,
+			       	pdf14_device * p14dev, byte * out);
+
+void pdf14_unpack_compressed(int num_comp, gx_color_index color,
+			       	pdf14_device * p14dev, byte * out);
+
+void pdf14_unpack_custom(int num_comp, gx_color_index color,
+			       	pdf14_device * p14dev, byte * out);
+
+void pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool has_shape);
+
+void pdf14_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf, 
+	      int x0, int x1, int y0, int y1, int n_chan, bool additive,
+	      const pdf14_nonseparable_blending_procs_t * pblend_procs);
+
+
+gx_color_index pdf14_encode_color(gx_device *dev, const gx_color_value colors[]);
+
+int pdf14_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out);
+gx_color_index pdf14_compressed_encode_color(gx_device *dev, const gx_color_value colors[]);
+int pdf14_compressed_decode_color(gx_device * dev, gx_color_index color,
+	       						gx_color_value * out);
+void pdf14_gray_cs_to_cmyk_cm(gx_device * dev, frac gray, frac out[]);
+void pdf14_rgb_cs_to_cmyk_cm(gx_device * dev, const gs_imager_state *pis,
+  			   frac r, frac g, frac b, frac out[]);
+void pdf14_cmyk_cs_to_cmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[]);
+
+void gx_build_blended_image_row(byte *buf_ptr, int y, int planestride, 
+			   int width, int num_comp, byte bg, byte *linebuf);
+int gx_put_blended_image_cmykspot(gx_device *target, byte *buf_ptr, 
+		      int planestride, int rowstride,
+		      int x0, int y0, int width, int height, int num_comp, byte bg,
+		      gs_separations *pseparations);
+int gx_put_blended_image_custom(gx_device *target, byte *buf_ptr, 
+		      int planestride, int rowstride,
+		      int x0, int y0, int width, int height, int num_comp, byte bg);
+
 #endif /* gxblend_INCLUDED */

Added: trunk/gs/base/gxblend1.c
===================================================================
--- trunk/gs/base/gxblend1.c	2008-09-04 14:06:17 UTC (rev 9070)
+++ trunk/gs/base/gxblend1.c	2008-09-04 15:46:56 UTC (rev 9071)
@@ -0,0 +1,733 @@
+/* Copyright (C) 2001-2006 Artifex Software, Inc.
+   All Rights Reserved.
+  
+   This software is provided AS-IS with no warranty, either express or
+   implied.
+
+   This software is distributed under license and may not be copied, modified
+   or distributed except as expressly authorized under the terms of that
+   license.  Refer to licensing information at http://www.artifex.com/
+   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
+   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
+*/
+/* $Id$ */
+/* PDF 1.4 blending functions */
+
+#include "memory_.h"
+#include "gx.h"
+#include "gstparam.h"
+#include "gsrect.h"
+#include "gxblend.h"
+#include "gxdevcli.h"
+#include "gxistate.h"
+#include "gdevdevn.h"
+#include "gdevp14.h"
+#include "vdtrace.h"
+
+#ifdef DUMP_TO_PNG
+#include "png_.h"
+#endif
+
+/*
+ * Unpack a device color.  This routine is similar to the device's
+ * decode_color procedure except for two things.  The procedure produces 1
+ * byte values instead of gx_color_values (2 bytes) and the output values
+ * are inverted for subtractive color spaces (like CMYK).  A separate
+ * procedure is used instead of the decode_color to minimize execution time.
+ */
+void
+pdf14_unpack_additive(int num_comp, gx_color_index color,
+			       	pdf14_device * p14dev, byte * out)
+{
+    int i;
+
+    for (i = num_comp - 1; i >= 0; i--) {
+	out[i] = (byte)(color & 0xff);
+	color >>= 8;
+    }
+}
+
+/*
+ * Unpack a device color.  This routine is similar to the device's
+ * decode_color procedure except for two things.  The procedure produces 1
+ * byte values instead of gx_color_values (2 bytes) and the output values
+ * are inverted for subtractive color spaces (like CMYK).  A separate
+ * procedure is used instead of the decode_color to minimize execution time.
+ */
+void
+pdf14_unpack_subtractive(int num_comp, gx_color_index color,
+			       	pdf14_device * p14dev, byte * out)
+{
+    int i;
+
+    for (i = num_comp - 1; i >= 0; i--) {
+	out[i] = 0xff - (byte)(color & 0xff);
+	color >>= 8;
+    }
+}
+
+/*
+ * Unpack a 'compressed' CMYK color index.  The color index value is unpacked
+ * into a set of 8 bit values.  For more information about 'compressed' color
+ * index values see the comments before the devn_encode_compressed_color routine.
+ *
+ * Note: For simplicity of coding the calling routines, this routine will also
+ * handle 'uncompressed' color index values.
+ */
+void
+pdf14_unpack_compressed(int num_comp, gx_color_index color,
+			       	pdf14_device * p14dev, byte * out)
+{
+    int comp_num;
+
+    if (p14dev->devn_params.compressed_color_list == NULL) {
+        /*
+         * For 'uncompressed' data we simply have to unpack the gx_color_index
+	 * value directly.
+         */
+        for (comp_num = num_comp - 1; comp_num >= 0; comp_num--) {
+	    out[comp_num] = 0xff - (byte)(color & 0xff);
+	    color >>= 8;
+        }
+    }
+    else {
+        int factor, bit_count, bit_mask;
+        comp_bit_map_list_t * pbitmap;
+        gx_color_value solid_color = 0xff;
+
+    	pbitmap = find_bit_map(color,
+		       	p14dev->devn_params.compressed_color_list);
+	bit_count = num_comp_bits[pbitmap->num_non_solid_comp];
+	bit_mask = (1 << bit_count) - 1;
+	factor = comp_bit_factor[pbitmap->num_non_solid_comp];
+	if (pbitmap->solid_not_100) {
+	    solid_color = 0xff - ((factor * ((int)color & bit_mask)) >> 16);
+	    color >>= bit_count;
+	}
+        for (comp_num = 0; comp_num < num_comp; comp_num++) {
+	    if (colorant_present(pbitmap, colorants, comp_num)) {
+		if (colorant_present(pbitmap, solid_colorants, comp_num))
+       		    *out++ = (byte)solid_color;
+		else {
+            	    *out++ = 0xff - ((factor * ((int)color & bit_mask)) >> 16);
+	    	    color >>= bit_count;
+		}
+	    }
+	    else
+            	*out++ = 0xff;
+        }
+    }
+}
+
+/*
+ * Unpack a device color.  This routine is used for devices in which we do
+ * not know the details of the process color model.  In this case we use
+ * the device's decode_color procedure.
+ */
+void
+pdf14_unpack_custom(int num_comp, gx_color_index color,
+			       	pdf14_device * p14dev, byte * out)
+{
+    int i;
+    gx_device * tdev = p14dev->target;
+    gx_color_value cm_values[GX_DEVICE_COLOR_MAX_COMPONENTS];
+
+    dev_proc(tdev, decode_color)(tdev, color, cm_values);
+    for (i = 0; i < num_comp; i++)
+	out[i] = 0xff - gx_color_value_to_byte(cm_values[i]);
+}
+
+
+
+void
+pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool has_shape)
+{
+    /* make copy of backdrop for compositing */
+    int x0 = max(buf->rect.p.x, tos->rect.p.x);
+    int x1 = min(buf->rect.q.x, tos->rect.q.x);
+    int y0 = max(buf->rect.p.y, tos->rect.p.y);
+    int y1 = min(buf->rect.q.y, tos->rect.q.y);
+
+    if (x0 < x1 && y0 < y1) {
+	int width = x1 - x0;
+	byte *buf_plane = buf->data + x0 - buf->rect.p.x + (y0 - buf->rect.p.y) * buf->rowstride;
+	byte *tos_plane = tos->data + x0 - tos->rect.p.x + (y0 - tos->rect.p.y) * tos->rowstride;
+	int i;
+	int n_chan_copy = buf->n_chan + (tos->has_shape ? 1 : 0);
+
+	for (i = 0; i < n_chan_copy; i++) {
+		byte *buf_ptr = buf_plane;
+		byte *tos_ptr = tos_plane;
+		int y;
+
+		for (y = y0; y < y1; ++y) {
+			memcpy (buf_ptr, tos_ptr, width); 
+			buf_ptr += buf->rowstride;
+			tos_ptr += tos->rowstride;
+		}
+		buf_plane += buf->planestride;
+		tos_plane += tos->planestride;
+	    }
+	if (has_shape && !tos->has_shape)
+	    memset (buf_plane, 0, buf->planestride);
+    }
+}
+
+void
+pdf14_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf, 
+	      int x0, int x1, int y0, int y1, int n_chan, bool additive,
+	      const pdf14_nonseparable_blending_procs_t * pblend_procs)
+{
+    int num_comp = n_chan - 1;
+    byte alpha = tos->alpha;
+    byte shape = tos->shape;
+    byte blend_mode = tos->blend_mode;
+    byte *tos_ptr = tos->data + x0 - tos->rect.p.x +
+	(y0 - tos->rect.p.y) * tos->rowstride;
+    byte *nos_ptr = nos->data + x0 - nos->rect.p.x +
+	(y0 - nos->rect.p.y) * nos->rowstride;
+    byte *mask_ptr = NULL;
+    int tos_planestride = tos->planestride;
+    int nos_planestride = nos->planestride;
+    int mask_planestride = 0x0badf00d; /* Quiet compiler. */
+    byte mask_bg_alpha = 0; /* Quiet compiler. */
+    int width = x1 - x0;
+    int x, y;
+    int i;
+    byte tos_pixel[PDF14_MAX_PLANES];
+    byte nos_pixel[PDF14_MAX_PLANES];
+    bool tos_isolated = tos->isolated;
+    bool nos_knockout = nos->knockout;
+    byte *nos_alpha_g_ptr;
+    int tos_shape_offset = n_chan * tos_planestride;
+    int tos_alpha_g_offset = tos_shape_offset +
+    (tos->has_shape ? tos_planestride : 0);
+    int nos_shape_offset = n_chan * nos_planestride;
+    bool nos_has_shape = nos->has_shape;
+    byte *mask_tr_fn = NULL; /* Quiet compiler. */
+
+    rect_merge(nos->bbox, tos->bbox);
+
+    if_debug6('v', "pdf14_pop_transparency_group y0 = %d, y1 = %d, w = %d, alpha = %d, shape = %d, bm = %d\n",
+			y0, y1, width, alpha, shape, blend_mode);
+    if (nos->has_alpha_g)
+	nos_alpha_g_ptr = nos_ptr + n_chan * nos_planestride;
+    else
+	nos_alpha_g_ptr = NULL;
+
+    if (maskbuf != NULL) {
+	mask_ptr = maskbuf->data + x0 - maskbuf->rect.p.x +
+		(y0 - maskbuf->rect.p.y) * maskbuf->rowstride;
+	mask_planestride = maskbuf->planestride;
+	mask_bg_alpha = maskbuf->alpha;
+	mask_tr_fn = maskbuf->transfer_fn;
+    }
+
+    for (y = y0; y < y1; ++y) {
+	for (x = 0; x < width; ++x) {
+	    byte pix_alpha = alpha;
+
+	    /* Complement the components for subtractive color spaces */
+	    if (additive) {
+		for (i = 0; i < n_chan; ++i) {
+		    tos_pixel[i] = tos_ptr[x + i * tos_planestride];
+		    nos_pixel[i] = nos_ptr[x + i * nos_planestride];
+		}
+	    } else {
+		for (i = 0; i < num_comp; ++i) {
+		    tos_pixel[i] = 255 - tos_ptr[x + i * tos_planestride];
+		    nos_pixel[i] = 255 - nos_ptr[x + i * nos_planestride];
+		}
+		tos_pixel[num_comp] = tos_ptr[x + num_comp * tos_planestride];
+		nos_pixel[num_comp] = nos_ptr[x + num_comp * nos_planestride];
+	    }
+
+	    if (mask_ptr != NULL) {
+		int mask_alpha = mask_ptr[x + num_comp * mask_planestride];
+		int tmp;
+		byte mask;
+
+		    /*
+		    * The mask data is really monochrome.  Thus for additive (RGB)
+		    * we use the R channel for alpha since R = G = B.  For
+		    * subtractive (CMYK) we use the K channel.
+		    */
+		if (mask_alpha == 255) {
+		    /* todo: rgba->mask */
+		    mask = additive ? mask_ptr[x]
+				    : 255 - mask_ptr[x + 3 * mask_planestride];
+		} else if (mask_alpha == 0)
+		    mask = mask_bg_alpha;
+		else {
+		    int t2 = additive ? mask_ptr[x]
+				    : 255 - mask_ptr[x + 3 * mask_planestride];
+
+		    t2 = (t2 - mask_bg_alpha) * mask_alpha + 0x80;
+		    mask = mask_bg_alpha + ((t2 + (t2 >> 8)) >> 8);
+		}
+		mask = mask_tr_fn[mask];
+		tmp = pix_alpha * mask + 0x80;
+		pix_alpha = (tmp + (tmp >> 8)) >> 8;
+#		    if VD_PAINT_MASK
+		    vd_pixel(int2fixed(x), int2fixed(y), mask);
+#		    endif
+	    }
+
+	    if (nos_knockout) {
+		byte *nos_shape_ptr = nos_has_shape ?
+		    &nos_ptr[x + nos_shape_offset] : NULL;
+		byte tos_shape = tos_ptr[x + tos_shape_offset];
+
+		art_pdf_composite_knockout_isolated_8(nos_pixel,
+						    nos_shape_ptr,
+						    tos_pixel,
+						    n_chan - 1,
+						    tos_shape,
+						    pix_alpha, shape);
+	    } else if (tos_isolated) {
+		art_pdf_composite_group_8(nos_pixel, nos_alpha_g_ptr,
+				    tos_pixel, n_chan - 1,
+				    pix_alpha, blend_mode, pblend_procs);
+	    } else {
+		byte tos_alpha_g = tos_ptr[x + tos_alpha_g_offset];
+		art_pdf_recomposite_group_8(nos_pixel, nos_alpha_g_ptr,
+				    tos_pixel, tos_alpha_g, n_chan - 1,
+				    pix_alpha, blend_mode, pblend_procs);
+	    }
+	    if (nos_has_shape) {
+		nos_ptr[x + nos_shape_offset] =
+		    art_pdf_union_mul_8 (nos_ptr[x + nos_shape_offset],
+					    tos_ptr[x + tos_shape_offset],
+					    shape);
+	    }
+        
+	    /* Complement the results for subtractive color spaces */
+	    if (additive) {
+		for (i = 0; i < n_chan; ++i) {
+		    nos_ptr[x + i * nos_planestride] = nos_pixel[i];
+		}
+	    } else {
+		for (i = 0; i < num_comp; ++i)
+		    nos_ptr[x + i * nos_planestride] = 255 - nos_pixel[i];
+		nos_ptr[x + num_comp * nos_planestride] = nos_pixel[num_comp];
+	    }
+#		if VD_PAINT_COLORS
+		vd_pixel(int2fixed(x), int2fixed(y), n_chan == 1 ? 
+		    (nos_pixel[0] << 16) + (nos_pixel[0] << 8) + nos_pixel[0] :
+		    (nos_pixel[0] << 16) + (nos_pixel[1] << 8) + nos_pixel[2]);
+#		endif
+#		if VD_PAINT_ALPHA
+		vd_pixel(int2fixed(x), int2fixed(y),
+		    (nos_pixel[n_chan - 1] << 16) + (nos_pixel[n_chan - 1] << 8) + 
+		     nos_pixel[n_chan - 1]);
+#		endif
+	    if (nos_alpha_g_ptr != NULL)
+		++nos_alpha_g_ptr;
+	}
+	tos_ptr += tos->rowstride;
+	nos_ptr += nos->rowstride;
+	if (nos_alpha_g_ptr != NULL)
+	    nos_alpha_g_ptr += nos->rowstride - width;
+	if (mask_ptr != NULL)
+	    mask_ptr += maskbuf->rowstride;
+    }
+}
+
+/*
+ * Encode a list of colorant values into a gx_color_index_value.
+ */
+gx_color_index
+pdf14_encode_color(gx_device *dev, const gx_color_value	colors[])
+{
+    int drop = sizeof(gx_color_value) * 8 - 8;
+    gx_color_index color = 0;
+    int i;
+    int ncomp = dev->color_info.num_components;
+
+    for (i = 0; i < ncomp; i++) {
+	color <<= 8;
+	color |= (colors[i] >> drop);
+    }
+    return (color == gx_no_color_index ? color ^ 1 : color);
+}
+
+/*
+ * Decode a gx_color_index value back to a list of colorant values.
+ */
+int
+pdf14_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
+{
+    int i;
+    int ncomp = dev->color_info.num_components;
+
+    for (i = 0; i < ncomp; i++) {
+	out[ncomp - i - 1] = (gx_color_value) ((color & 0xff) * 0x101);
+	color >>= 8;
+    }
+    return 0;
+}
+
+/*
+ * Encode a list of colorant values into a gx_color_index_value.  For more
+ * information about 'compressed' color index values see the comments before
+ * the devn_encode_compressed_color routine.
+ */
+gx_color_index
+pdf14_compressed_encode_color(gx_device *dev, const gx_color_value colors[])
+{
+    return devn_encode_compressed_color(dev, colors,
+		    &(((pdf14_device *)dev)->devn_params));
+}
+
+/*
+ * Decode a gx_color_index value back to a list of colorant values.  For more
+ * information about 'compressed' color index values see the comments before
+ * the devn_encode_compressed_color routine.
+ */
+int
+pdf14_compressed_decode_color(gx_device * dev, gx_color_index color,
+	       						gx_color_value * out)
+{
+    return devn_decode_compressed_color(dev, color, out,
+		    &(((pdf14_device *)dev)->devn_params));
+}
+
+void
+pdf14_gray_cs_to_cmyk_cm(gx_device * dev, frac gray, frac out[])
+{
+    int num_comp = dev->color_info.num_components;
+
+    out[0] = out[1] = out[2] = frac_0;
+    out[3] = frac_1 - gray;
+    for (--num_comp; num_comp > 3; num_comp--)
+	out[num_comp] = 0;
+}
+
+/*
+ * Default map from DeviceRGB color space to DeviceCMYK color
+ * model. Since this mapping is defined by the PostScript language
+ * it is unlikely that any device with a DeviceCMYK color model
+ * would define this mapping on its own.
+ *
+ * If the imager state is not available, map as though the black
+ * generation and undercolor removal functions are identity
+ * transformations. This mode is used primarily to support the
+ * raster operation (rop) feature of PCL, which requires that
+ * the raster operation be performed in an RGB color space.
+ * Note that default black generation and undercolor removal
+ * functions in PostScript need NOT be identity transformations:
+ * often they are { pop 0 }.
+ */
+void
+pdf14_rgb_cs_to_cmyk_cm(gx_device * dev, const gs_imager_state *pis,
+  			   frac r, frac g, frac b, frac out[])
+{
+    int num_comp = dev->color_info.num_components;
+
+    if (pis != 0)
+        color_rgb_to_cmyk(r, g, b, pis, out);
+    else {
+        frac    c = frac_1 - r, m = frac_1 - g, y = frac_1 - b;
+        frac    k = min(c, min(m, g));
+
+        out[0] = c - k;
+        out[1] = m - k;
+        out[2] = y - k;
+        out[3] = k;
+    }
+    for (--num_comp; num_comp > 3; num_comp--)
+	out[num_comp] = 0;
+}
+
+void
+pdf14_cmyk_cs_to_cmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
+{
+    int num_comp = dev->color_info.num_components;
+
+    out[0] = c;
+    out[1] = m;
+    out[2] = y;
+    out[3] = k;
+    for (--num_comp; num_comp > 3; num_comp--)
+	out[num_comp] = 0;
+}
+
+#ifdef DUMP_TO_PNG
+/* Dumps a planar RGBA image to	a PNG file. */
+static	int
+dump_planar_rgba(gs_memory_t *mem, const pdf14_buf *pbuf)
+{
+    int rowstride = pbuf->rowstride, planestride = pbuf->planestride;
+    int rowbytes = width << 2;
+    gs_int_rect rect = buf->rect;
+    int x1 = min(pdev->width, rect.q.x);
+    int y1 = min(pdev->height, rect.q.y);
+    int width = x1 - rect.p.x;
+    int height = y1 - rect.p.y;
+    byte *buf_ptr = buf->data + rect.p.y * buf->rowstride + rect.p.x;
+    byte *row = gs_malloc(mem, rowbytes, 1, "png raster buffer");
+    png_struct *png_ptr =
+    png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    png_info *info_ptr =
+    png_create_info_struct(png_ptr);
+    const char *software_key = "Software";
+    char software_text[256];
+    png_text text_png;
+    FILE *file;
+    int code;
+    int y;
+
+    if (buf->data == NULL)
+	return 0;
+
+    file = fopen ("c:\\temp\\tmp.png", "wb");
+
+    if_debug0('v', "[v]pnga_output_page\n");
+
+    if (row == 0 || png_ptr == 0 || info_ptr == 0) {
+	code = gs_note_error(gs_error_VMerror);
+	goto done;
+    }
+    /* set error handling */
+    if (setjmp(png_ptr->jmpbuf)) {
+	/* If we get here, we had a problem reading the file */
+	code = gs_note_error(gs_error_VMerror);
+	goto done;
+    }
+
+    code = 0;			/* for normal path */
+    /* set up the output control */
+    png_init_io(png_ptr, file);
+
+    /* set the file information here */
+    info_ptr->width = width;
+    info_ptr->height = height;
+    /* resolution is in pixels per meter vs. dpi */
+    info_ptr->x_pixels_per_unit =
+	(png_uint_32) (96.0 * (100.0 / 2.54));
+    info_ptr->y_pixels_per_unit =
+	(png_uint_32) (96.0 * (100.0 / 2.54));
+    info_ptr->phys_unit_type = PNG_RESOLUTION_METER;
+    info_ptr->valid |= PNG_INFO_pHYs;
+
+    /* At present, only supporting 32-bit rgba */
+    info_ptr->bit_depth = 8;
+    info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+
+    /* add comment */
+    sprintf(software_text, "%s %d.%02d", gs_product,
+	    (int)(gs_revision / 100), (int)(gs_revision % 100));
+    text_png.compression = -1;	/* uncompressed */
+    text_png.key = (char *)software_key;	/* not const, unfortunately */
+    text_png.text = software_text;
+    text_png.text_length = strlen(software_text);
+    info_ptr->text = &text_png;
+    info_ptr->num_text = 1;
+
+    /* write the file information */
+    png_write_info(png_ptr, info_ptr);
+
+    /* don't write the comments twice */
+    info_ptr->num_text = 0;
+    info_ptr->text = NULL;
+
+    /* Write the contents of the image. */
+    for (y = 0; y < height; ++y) {
+	int x;
+
+	for (x = 0; x < width; ++x) {
+	    row[(x << 2)] = buf_ptr[x];
+	    row[(x << 2) + 1] = buf_ptr[x + planestride];
+	    row[(x << 2) + 2] = buf_ptr[x + planestride * 2];
+	    row[(x << 2) + 3] = buf_ptr[x + planestride * 3];
+	}
+	png_write_row(png_ptr, row);
+	buf_ptr += rowstride;
+    }
+
+    /* write the rest of the file */
+    png_write_end(png_ptr, info_ptr);
+
+  done:
+    /* free the structures */
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    gs_free(mem, row, rowbytes, 1, "png raster buffer");
+
+    fclose (file);
+    return code;
+}
+#endif
+
+void
+gx_build_blended_image_row(byte *buf_ptr, int y, int planestride, 
+			   int width, int num_comp, byte bg, byte *linebuf)
+{
+    int x;
+    for (x = 0; x < width; x++) {
+	byte comp, a;
+	int tmp, comp_num;
+
+	/* composite RGBA (or CMYKA, etc.) pixel with over solid background */
+	a = buf_ptr[x + planestride * num_comp];
+
+	if ((a + 1) & 0xfe) {
+	    a ^= 0xff;
+	    for (comp_num = 0; comp_num < num_comp; comp_num++) {
+		comp  = buf_ptr[x + planestride * comp_num];
+		tmp = ((bg - comp) * a) + 0x80;
+		comp += (tmp + (tmp >> 8)) >> 8;
+		linebuf[x * num_comp + comp_num] = comp;
+	    }
+	} else if (a == 0) {
+	    for (comp_num = 0; comp_num < num_comp; comp_num++) {
+		linebuf[x * num_comp + comp_num] = bg;
+	    }
+	} else {
+	    for (comp_num = 0; comp_num < num_comp; comp_num++) {
+		comp = buf_ptr[x + planestride * comp_num];
+		linebuf[x * num_comp + comp_num] = comp;
+	    }
+	}
+    }
+}
+
+int
+gx_put_blended_image_cmykspot(gx_device *target, byte *buf_ptr, 
+		      int planestride, int rowstride,
+		      int x0, int y0, int width, int height, int num_comp, byte bg,
+		      gs_separations * pseparations)
+{
+    int code = 0;
+    int x, y, tmp, comp_num, output_comp_num;
+    gx_color_index color;
+    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
+    gx_color_value comp;
+    byte a;
+    int input_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
+    int output_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
+    int num_known_comp = 0;
+    int output_num_comp = target->color_info.num_components;
+    int num_sep = pseparations->num_separations++;
+
+    /*
+     * The process color model for the PDF 1.4 compositor device is CMYK plus
+     * spot colors.  The target device may have only some of these colorants due
+     * to the SeparationOrder device parameter.  Thus we need to determine the
+     * mapping between the PDF 1.4 compositor and the target device.  Note:
+     * There should not be a spot colorant in the PDF 1.4 device that is not
+     * present in the target device.
+     */
+    /* Check if target processes CMYK colorants. */
+    for (comp_num = 0; comp_num < 4; comp_num++) {
+	const char * pcomp_name = (const char *)DeviceCMYKComponents[comp_num]; 
+
+	output_comp_num = dev_proc(target, get_color_comp_index)
+		(target, pcomp_name, strlen(pcomp_name), NO_COMP_NAME_TYPE);
+	if (output_comp_num >=0 &&
+	     	output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
+	    output_map[num_known_comp] = output_comp_num;
+	    input_map[num_known_comp++] = comp_num;
+	}
+    }
+    /* Check if target processes our spot colorants. */
+    for (comp_num = 0; comp_num < num_sep; comp_num++) {
+	output_comp_num = dev_proc(target, get_color_comp_index)
+	       (target, (const char *)(pseparations->names[comp_num].data),
+	       	pseparations->names[comp_num].size,  NO_COMP_NAME_TYPE);
+	if (output_comp_num >= 0 &&
+	     	output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
+	    output_map[num_known_comp] = output_comp_num;
+	    input_map[num_known_comp++] = comp_num + 4;
+	}
+    }
+
+    /* Clear all output colorants first */
+    for (comp_num = 0; comp_num < output_num_comp; comp_num++)
+	cv[comp_num] = 0;
+
+    /* Send pixel data to the target device. */
+    for (y = 0; y < height; y++) {
+	for (x = 0; x < width; x++) {
+
+	    /* composite CMYKA, etc. pixel with over solid background */
+	    a = buf_ptr[x + planestride * num_comp];
+
+	    if ((a + 1) & 0xfe) {
+		a ^= 0xff;
+		for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+		    comp  = buf_ptr[x + planestride * input_map[comp_num]];
+		    tmp = ((comp - bg) * a) + 0x80;
+		    comp += tmp + (tmp >> 8);
+		    cv[output_map[comp_num]] = comp;
+		}
+	    } else if (a == 0) {
+		for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+		    cv[output_map[comp_num]] = bg;
+		}
+	    } else {
+		for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+		    comp = buf_ptr[x + planestride * input_map[comp_num]];
+		    cv[output_map[comp_num]] = (comp << 8) + comp;
+		}
+	    }
+	    color = dev_proc(target, encode_color)(target, cv);
+	    code = dev_proc(target, fill_rectangle)(target, x + x0, 
+							    y + y0, 1, 1, color);
+	    if (code < 0)
+		return code;
+	}
+
+	buf_ptr += rowstride;
+    }
+
+    return code;
+}
+
+int
+gx_put_blended_image_custom(gx_device *target, byte *buf_ptr, 
+		      int planestride, int rowstride,
+		      int x0, int y0, int width, int height, int num_comp, byte bg)
+{
+    int code = 0;
+    int x, y, tmp, comp_num;
+    gx_color_index color;
+    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
+    gx_color_value comp;
+    byte a;
+
+
+    /* Send pixel data to the target device. */
+    for (y = 0; y < height; y++) {
+	for (x = 0; x < width; x++) {
+
+	    /* composite CMYKA, etc. pixel with over solid background */
+	    a = buf_ptr[x + planestride * num_comp];
+
+	    if ((a + 1) & 0xfe) {
+		a ^= 0xff;
+		for (comp_num = 0; comp_num < num_comp; comp_num++) {
+		    comp  = buf_ptr[x + planestride * comp_num];
+		    tmp = ((bg - comp) * a) + 0x80;
+		    comp += tmp + (tmp >> 8);
+		    cv[comp_num] = comp;
+		}
+	    } else if (a == 0) {
+		for (comp_num = 0; comp_num < num_comp; comp_num++) {
+		    cv[comp_num] = bg;
+		}
+	    } else {
+		for (comp_num = 0; comp_num < num_comp; comp_num++) {
+		    comp = buf_ptr[x + planestride * comp_num];
+		    cv[comp_num] = (comp << 8) + comp;
+		}
+	    }
+	    color = dev_proc(target, encode_color)(target, cv);
+	    code = dev_proc(target, fill_rectangle)(target, x + x0, 
+							    y + y0, 1, 1, color);
+	}
+
+	buf_ptr += rowstride;
+    }
+
+    return code;
+}


Property changes on: trunk/gs/base/gxblend1.c
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: trunk/gs/base/lib.mak
===================================================================
--- trunk/gs/base/lib.mak	2008-09-04 14:06:17 UTC (rev 9070)
+++ trunk/gs/base/lib.mak	2008-09-04 15:46:56 UTC (rev 9071)
@@ -2545,7 +2545,7 @@
 gstrans_h=$(GLSRC)gstrans.h $(gstparam_h) $(gxcomp_h) $(gsmatrix_h)
 gsipar3x_h=$(GLSRC)gsipar3x.h $(gsiparam_h) $(gsiparm3_h)
 gximag3x_h=$(GLSRC)gximag3x.h $(gsipar3x_h) $(gxiparam_h)
-gxblend_h=$(GLSRC)gxblend.h
+gxblend_h=$(GLSRC)gxblend.h $(gxcindex_h) $(gxcvalue_h) $(gxxfrac_h)
 gdevp14_h=$(GLSRC)gdevp14.h $(GLSRC)gxcmap.h
 
 $(GLOBJ)gstrans.$(OBJ) : $(GLSRC)gstrans.c $(GXERR)\
@@ -2563,6 +2563,11 @@
  $(gstparam_h) $(gxblend_h)
 	$(GLCC) $(GLO_)gxblend.$(OBJ) $(C_) $(GLSRC)gxblend.c
 
+$(GLOBJ)gxblend1.$(OBJ) : $(GLSRC)gxblend1.c $(GX) $(memory__h)\
+ $(gstparam_h) $(gxrect_h) $(gxblend_h) $(gxdevcli_h) $(gxistate_h)\
+ $(gdevdevn_h) $(gdevp14_h) $(vdtrace_h)
+	$(GLCC) $(GLO_)gxblend1.$(OBJ) $(C_) $(GLSRC)gxblend1.c
+
 $(GLOBJ)gdevp14.$(OBJ) : $(GLSRC)gdevp14.c $(GXERR) $(math__h) $(memory__h)\
  $(gscdefs_h) $(gxdevice_h) $(gsdevice_h) $(gsstruct_h) $(gscoord_h) $(gxistate_h) $(gxdcolor_h)\
  $(gxiparam_h) $(gstparam_h) $(gxblend_h) $(gxtext_h) $(gsdfilt_h) $(gsimage_h)\
@@ -2571,7 +2576,7 @@
 	$(GLCC) $(GLO_)gdevp14.$(OBJ) $(C_) $(GLSRC)gdevp14.c
 
 translib_=$(GLOBJ)gstrans.$(OBJ) $(GLOBJ)gximag3x.$(OBJ)\
- $(GLOBJ)gxblend.$(OBJ) $(GLOBJ)gdevp14.$(OBJ) $(GLOBJ)gdevdevn.$(OBJ)\
+ $(GLOBJ)gxblend.$(OBJ) $(GLOBJ)gxblend1.$(OBJ) $(GLOBJ)gdevp14.$(OBJ) $(GLOBJ)gdevdevn.$(OBJ)\
  $(GLOBJ)gdevdcrd.$(OBJ)
 $(GLD)translib.dev : $(LIB_MAK) $(ECHOGS_XE) $(translib_)\
  $(GLD)cspixlib.dev $(GLD)bboxutil.dev $(GLD)cielib.dev



More information about the gs-cvs mailing list