[gs-cvs] gs/src

Igor Melichev igor at ghostscript.com
Thu Mar 31 12:46:32 PST 2005


Update of /cvs/ghostscript/gs/src
In directory casper2:/tmp/cvs-serv11639/gs/src

Modified Files:
	gdevpdf.c gdevpdfd.c gdevpdfp.c spprint.c gdevpdfx.h devs.mak 
Log Message:
ps2write : Convert shadings into a clipped image (continued 4).

DETAILS :

Implement a downsampling when converting a shading into bitmap.

1. A new device parameter MaxShadingBitmapSize controls the downsampling.
   Shadings, which give a (uncompressed) bitmap over the specified size, 
   will be scaled down.

2. The scaling algorithm goes to gdevpdfd.c .
   It appears pretty tricky because we need to setup a device with a smaller
   resolution than the target device. Due to that we need to scale paths and colors,
   which are represented in the device space. The function scale_path works for it.

3. The scaling creates a local copy of a device color (which handles the shading)
   and scales the color. Since we can't access further spatial transformations of the color,
   we apply some unusual operation : multiply matrices in the reverse order
   than usual 'concat' does. This makes some useful equations to be soluble
   due to the offset is being scaled as well.

4. A code portion was copied from gx_default_fill_path
   (see comment in code).
   We're unhappy about uncomfortable code structurization.

5. path_scale is implemented with floating point for a debug purpose,
   but in production we use only integers being a power of 2.

6. There is a problem with 
   <</PatternImagemask false /MaxClipPathSize 12000 /MaxShadingBitmapSize 100000000>>
   The problem happens when dividing the scaled bitmap in smaller ones
   due to clip path overflow. This mode to be debugged separately.
   For now set either smaller bitmap size of bigger clip path size.
   Default settings work fine for most cases.

EXPECTED DIFFERENCES :

None.


Index: gdevpdf.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdf.c,v
retrieving revision 1.105
retrieving revision 1.106
diff -u -d -r1.105 -r1.106
--- gdevpdf.c	28 Mar 2005 14:03:31 -0000	1.105
+++ gdevpdf.c	31 Mar 2005 20:46:30 -0000	1.106
@@ -200,9 +200,10 @@
  1,				/* FirstObjectNumber */
  1 /*true*/,			/* CompressFonts */
  0 /*false*/,			/* PrintStatistics */
- 0 /*false*/,			/* OrderResources; */
- 0 /*false*/,			/* PatternImagemask; */
+ 0 /*false*/,			/* OrderResources */
+ 0 /*false*/,			/* PatternImagemask */
  12000,				/* MaxClipPathSize */ /* HP LaserJet 1320 hangs with 14000. */
+ 256000,			/* MaxShadingBitmapSize */
  4000,				/* MaxInlineImageSize */
  {0, 0},			/* OwnerPassword */
  {0, 0},			/* UserPassword */

Index: gdevpdfd.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfd.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- gdevpdfd.c	30 Mar 2005 13:43:08 -0000	1.53
+++ gdevpdfd.c	31 Mar 2005 20:46:30 -0000	1.54
@@ -27,6 +27,7 @@
 #include "gxdevmem.h"
 #include "gxcolor2.h"
 #include "gxhldevc.h"
+#include "gsstate.h"
 #include "gserrors.h"
 #include "gsptype2.h"
 #include "gzpath.h"
@@ -534,7 +535,9 @@
 
     
     if (m != NULL)
-	pdf_put_matrix(pdev, "W n ", m, " cm\n");
+	pdf_put_matrix(pdev, "W n\n", m, " cm\n");
+    else
+	stream_puts(pdev->strm, "W n\n");
     code = pdf_copy_color_data(pdev, mdev->base, sourcex,  
 		mdev->raster, gx_no_bitmap_id, 0, 0, mdev->width, mdev->height,
 		&image, &writer, 2);
@@ -552,7 +555,8 @@
     bool save_skip_color = pdev->skip_colors;
     int code;
 
-    pdf_put_matrix(pdev, NULL, m, " cm\n");
+    if (m != NULL)
+	pdf_put_matrix(pdev, NULL, m, " cm\n");
     pdev->clip_path_id = pdev->no_clip_path_id;
     pdev->skip_colors = true;
     code = gdev_pdf_copy_mono((gx_device *)pdev, mdev->base, sourcex,  
@@ -734,7 +738,8 @@
     int x = 0, y = 0;
     int code, code1;
 
-    pdf_put_matrix(pdev, NULL, &cvd->m, " cm\n");
+    if (cvd->write_matrix)
+	pdf_put_matrix(pdev, NULL, &cvd->m, " cm\n");
     for(;;) {
 	int x1, y1;
 	
@@ -773,7 +778,7 @@
     int code = 0;
 
     if (!cvd->path_is_empty) {
-	code = write_image(pdev, &cvd->mdev, &cvd->m);
+	code = write_image(pdev, &cvd->mdev, (cvd->write_matrix ? &cvd->m : NULL));
 	cvd->path_is_empty = true;
     } else if (!cvd->mask_is_empty && pdev->PatternImagemask) {
 	/* Convert to imagemask with a pattern color. */
@@ -818,7 +823,7 @@
 	    pprintld1(pdev->strm, " cs /R%ld scn ", pdf_resource_id(pres));
 	}
 	if (code >= 0)
-	    code = write_mask(pdev, cvd->mask, &cvd->m);
+	    code = write_mask(pdev, cvd->mask, (cvd->write_matrix ? &cvd->m : NULL));
 	cvd->mask_is_empty = true;
     } else if (!cvd->mask_is_empty && !pdev->PatternImagemask) {
 	/* Convert to image with a clipping path. */
@@ -860,6 +865,9 @@
 	cvd->path_is_empty = true;
 	cvd->mask_is_empty = false;
     } else {
+	gs_matrix m;
+
+	gs_make_translation(cvd->path_offset.x, cvd->path_offset.y, &m);
 	/* use the clipping. */
 	if (!cvd->mask_is_empty) {
 	    code = pdf_dump_converted_image(pdev, cvd);
@@ -870,8 +878,7 @@
 	    cvd->mask_is_empty = true;
 	}
 	code = gdev_vector_dopath((gx_device_vector *)pdev, ppath,
-			    gx_path_type_fill | gx_path_type_optimize,
-			    NULL);
+			    gx_path_type_fill | gx_path_type_optimize, &m);
 	if (code < 0)
 	    return code;
 	stream_puts(pdev->strm, "h\n");
@@ -962,6 +969,29 @@
 	gs_free_object(cvd->mask->memory, cvd->mask, "pdf_remove_masked_image_converter");
     }
 }
+
+private int
+path_scale(gx_path *path, double scalex, double scaley)
+{
+    segment *pseg = (segment *)path->first_subpath;
+
+    for (;pseg != NULL; pseg = pseg->next) {
+	pseg->pt.x = (fixed)floor(pseg->pt.x * scalex + 0.5);
+	pseg->pt.y = (fixed)floor(pseg->pt.y * scaley + 0.5);
+	if (pseg->type == s_curve) {
+	    curve_segment *s = (curve_segment *)pseg;
+
+	    s->p1.x = (fixed)floor(s->p1.x * scalex + 0.5);
+	    s->p1.y = (fixed)floor(s->p1.y * scaley + 0.5);
+	    s->p2.x = (fixed)floor(s->p2.x * scalex + 0.5);
+	    s->p2.y = (fixed)floor(s->p2.y * scaley + 0.5);
+	}
+    }
+    path->position.x = (fixed)floor(path->position.x * scalex + 0.5);
+    path->position.y = (fixed)floor(path->position.y * scaley + 0.5);
+    return 0;
+}
+
 /* ------ Driver procedures ------ */
 
 /* Fill a path. */
@@ -1019,10 +1049,19 @@
 	    int sx, sy;
 	    gs_fixed_rect bbox, bbox1;
 	    bool need_mask = gx_dc_pattern2_can_overlap(pdcolor);
-	    gs_matrix m;
+	    gs_matrix m, save_ctm = ctm_only(pis), ms, msi, mm;
 	    gs_point p;
 	    gs_int_point rect_size;
+	    /* double scalex = 1.9, scaley = 1.4; debug purpose only. */
+	    double scale, scalex = 1.0, scaley = 1.0;
+	    gx_drawing_color dc = *pdcolor;
+	    gs_pattern2_instance_t pi = *(gs_pattern2_instance_t *)dc.ccolor.pattern;
+	    gs_state *pgs = gs_state_copy(pi.saved, gs_state_memory(pi.saved));
 
+	    if (pgs == NULL)
+		return_error(gs_error_VMerror);
+	    dc.ccolor.pattern = (gs_pattern_instance_t *)&pi;
+	    pi.saved = pgs;
 	    code = gx_path_bbox(ppath, &bbox);
 	    if (code < 0)
 		return code;
@@ -1043,15 +1082,67 @@
 		return 0;
 	    m.tx = p.x;
 	    m.ty = p.y;
+	    scale = (double)rect_size.x * rect_size.y * pdev->color_info.num_components /
+		    pdev->MaxShadingBitmapSize;
+	    if (scale > 1) {
+		/* This section (together with the call to 'path_scale' below)
+		   sets up a downscaling when converting the shading into bitmap. 
+		   We used floating point numbers to debug it, but in production
+		   we prefer to deal only with integers being powers of 2
+		   in order to avoid possible distorsions when scaling paths.
+		*/
+		scalex = ceil(sqrt(scale));
+		scalex = scaley = 1 << ilog2((int)scalex);
+		if (scalex * scaley < scale)
+		    scalex *= 2;
+		if (scalex * scaley < scale)
+		    scaley *= 2;
+		rect_size.x = (int)floor(rect_size.x / scalex + 0.5);
+		rect_size.y = (int)floor(rect_size.y / scaley + 0.5);
+		gs_make_scaling(1.0 / scalex, 1.0 / scaley, &ms);
+		gs_make_scaling(scalex, scaley, &msi);
+		gs_matrix_multiply(&m, &msi, &m);
+		gs_matrix_multiply(&ctm_only(pis), &ms, &mm);
+		gs_setmatrix((gs_state *)pis, &mm);
+		gs_matrix_multiply(&ctm_only((gs_imager_state *)pgs), &ms, &mm);
+		gs_setmatrix((gs_state *)pgs, &mm);
+		m.tx /= scalex;
+		m.ty /= scaley;
+		cvd.path_offset.x = m.tx / scalex;
+		cvd.path_offset.y = m.ty / scaley;
+		sx = (int)floor(sx / scalex + 0.5);
+		sy = (int)floor(sy / scaley + 0.5);
+	    }
 	    code = pdf_setup_masked_image_converter(pdev, pdev->memory, &m, &pcvd, need_mask, sx, sy, 
 			    rect_size.x, rect_size.y, false);
 	    stream_puts(pdev->strm, "q\n");
-	    if (code >= 0)
-		code = gx_default_fill_path((gx_device *)&cvd.mdev, pis, ppath, params, pdcolor, pcpath);
-	    if (code == 0)
+	    if (code >= 0) {
+		pdf_put_matrix(pdev, NULL, &cvd.m, " cm q\n");
+		cvd.write_matrix = false;
+	    }
+	    if (code >= 0) {
+		/* See gx_default_fill_path. */
+		gx_clip_path cpath_intersection;
+		gx_path path_intersection;
+
+		gx_path_init_local(&path_intersection, pdev->memory);
+		gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory);
+		if ((code = gx_cpath_intersect(&cpath_intersection, ppath, params->rule, (const gs_imager_state *)pis)) >= 0)
+		    code = gx_cpath_to_path(&cpath_intersection, &path_intersection);
+		if (code >= 0)
+		    code = path_scale(&path_intersection, scalex, scaley);
+		if (code >= 0)
+		    code = gx_dc_pattern2_fill_path(&dc, &path_intersection, NULL, (gx_device *)&cvd.mdev);
+		gx_path_free(&path_intersection, "shading_fill_path_intersection");
+		gx_cpath_free(&cpath_intersection, "shading_fill_cpath_intersection");
+	    }
+	    if (code >= 0) {
 		code = pdf_dump_converted_image(pdev, &cvd);
-	    stream_puts(pdev->strm, "Q\n");
+	    }
+	    stream_puts(pdev->strm, "Q Q\n");
 	    pdf_remove_masked_image_converter(pdev, &cvd, need_mask);
+	    gs_setmatrix((gs_state *)pis, &save_ctm);
+	    gs_state_free(pgs);
 	    return code; 
 	}
     }

Index: gdevpdfp.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfp.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- gdevpdfp.c	28 Mar 2005 14:03:31 -0000	1.44
+++ gdevpdfp.c	31 Mar 2005 20:46:30 -0000	1.45
@@ -88,6 +88,7 @@
     pi("OrderResources", gs_param_type_bool, OrderResources),
     pi("PatternImagemask", gs_param_type_bool, PatternImagemask),
     pi("MaxClipPathSize", gs_param_type_int, MaxClipPathSize),
+    pi("MaxShadingBitmapSize", gs_param_type_int, MaxShadingBitmapSize),
     pi("HaveCIDSystem", gs_param_type_bool, HaveCIDSystem),
     pi("PSVersion", gs_param_type_int, PSVersion),
 #endif

Index: spprint.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/spprint.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- spprint.c	21 Feb 2002 22:24:54 -0000	1.6
+++ spprint.c	31 Mar 2005 20:46:30 -0000	1.7
@@ -110,7 +110,7 @@
 pprintg1(stream * s, const char *format, floatp v)
 {
     const char *fp = pprintf_scan(s, format);
-    char str[50];
+    char str[150];
 
 #ifdef DEBUG
     if (*fp == 0 || fp[1] != 'g')	/* shouldn't happen! */

Index: gdevpdfx.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfx.h,v
retrieving revision 1.111
retrieving revision 1.112
diff -u -d -r1.111 -r1.112
--- gdevpdfx.h	30 Mar 2005 12:48:08 -0000	1.111
+++ gdevpdfx.h	31 Mar 2005 20:46:30 -0000	1.112
@@ -463,6 +463,9 @@
 			      with pattern color. */
     long MaxClipPathSize;  /* The maximal number of elements of a clipping path
 			      that the target viewer|printer can handle. */
+    long MaxShadingBitmapSize; /* The maximal number of bytes in 
+			      a bitmap representation of a shading.
+			      (Bigger shadings to be downsampled). */
 #endif
     long MaxInlineImageSize;
     /* Encryption parameters */
@@ -913,7 +916,9 @@
     bool mask_is_empty;
     bool path_is_empty;
     bool mask_is_clean;
+    bool write_matrix;
     gs_matrix m;
+    gs_point path_offset;
 } pdf_lcvd_t;
 
 #define public_st_pdf_lcvd_t()\

Index: devs.mak
===================================================================
RCS file: /cvs/ghostscript/gs/src/devs.mak,v
retrieving revision 1.127
retrieving revision 1.128
diff -u -d -r1.127 -r1.128
--- devs.mak	29 Mar 2005 17:31:58 -0000	1.127
+++ devs.mak	31 Mar 2005 20:46:30 -0000	1.128
@@ -845,7 +845,8 @@
 
 $(GLOBJ)gdevpdfd.$(OBJ) : $(GLSRC)gdevpdfd.c $(math__h) $(memory__h)\
  $(gx_h) $(gxdevice_h) $(gxfixed_h) $(gxistate_h) $(gxpaint_h)\
- $(gxcoord_h) $(gxdevmem_h) $(gxcolor2_h) $(gxhldevc_h) $(gserrors_h) $(gsptype2_h)\
+ $(gxcoord_h) $(gxdevmem_h) $(gxcolor2_h) $(gxhldevc_h)\
+ $(gsstate_h) $(gserrors_h) $(gsptype2_h)\
  $(gzpath_h) $(gzcpath_h) $(gdevpdfx_h) $(gdevpdfg_h) $(gdevpdfo_h) $(gsutil_h)
 	$(GLCC) $(GLO_)gdevpdfd.$(OBJ) $(C_) $(GLSRC)gdevpdfd.c
 



More information about the gs-cvs mailing list