[gs-cvs] rev 7222 - trunk/gs/src
leonardo at ghostscript.com
leonardo at ghostscript.com
Thu Nov 23 11:01:21 PST 2006
Author: leonardo
Date: 2006-11-23 11:01:20 -0800 (Thu, 23 Nov 2006)
New Revision: 7222
Modified:
trunk/gs/src/gsimage.c
trunk/gs/src/gxcpath.c
trunk/gs/src/gximage.c
trunk/gs/src/gxiparam.h
trunk/gs/src/gxpath.h
trunk/gs/src/lib.mak
trunk/gs/src/zimage.c
Log:
Fix : Skip images outside the clipping path.
DETAILS :
Bug 689000 "Ghostscript generates very large PDF file compared to Distiller".
1. New functions gx_cpath_rect_visible, is_image_visible
check whether the image is entirely clipped out.
2. A new flag gx_image_enum_common_s::skipping stores that fact.
3. If so happens, interpreter checks whether the image
has string datasources only. Such images may be safely skipped
from the interpretation (zimage.c).
Note : This optimization works for ImageType 1 only - see comment
in is_image_visible. Unfortunately We have no time to improve this now.
Need to analyze why does gs_image2_t need a floating size of the source image.
EXPECTED DIFFERENCES :
None.
Modified: trunk/gs/src/gsimage.c
===================================================================
--- trunk/gs/src/gsimage.c 2006-11-23 15:01:16 UTC (rev 7221)
+++ trunk/gs/src/gsimage.c 2006-11-23 19:01:20 UTC (rev 7222)
@@ -14,6 +14,7 @@
/* $Id$ */
/* Image setup procedures for Ghostscript library */
#include "memory_.h"
+#include "math_.h"
#include "gx.h"
#include "gserrors.h"
#include "gsstruct.h"
@@ -146,6 +147,43 @@
}
RELOC_PTRS_END
+private int
+is_image_visible(const gs_image_common_t * pic, gs_state * pgs, gx_clip_path *pcpath)
+{
+ /* HACK : We need the source image size here,
+ but gs_image_common_t doesn't pass it.
+ We would like to move Width, Height to gs_image_common,
+ but gs_image2_t appears to have those fields of double type.
+ */
+ if (pic->type->begin_typed_image == gx_begin_image1) {
+ gs_image1_t *pim = (gs_image1_t *) pic;
+ gs_rect image_rect = {{0, 0}, {0, 0}};
+ gs_rect device_rect;
+ gs_int_rect device_int_rect;
+ gs_matrix mat;
+ int code;
+
+ image_rect.q.x = pim->Width;
+ image_rect.q.y = pim->Height;
+ code = gs_matrix_invert(&pic->ImageMatrix, &mat);
+ if (code < 0)
+ return code;
+ code = gs_matrix_multiply(&mat, &ctm_only(pgs), &mat);
+ if (code < 0)
+ return code;
+ code = gs_bbox_transform(&image_rect, &mat, &device_rect);
+ if (code < 0)
+ return code;
+ device_int_rect.p.x = (int)floor(device_rect.p.x);
+ device_int_rect.p.y = (int)floor(device_rect.p.y);
+ device_int_rect.q.x = (int)ceil(device_rect.q.x);
+ device_int_rect.q.y = (int)ceil(device_rect.q.y);
+ if (!gx_cpath_rect_visible(pcpath, &device_int_rect))
+ return 0;
+ }
+ return 1;
+}
+
/* Create an image enumerator given image parameters and a graphics state. */
int
gs_image_begin_typed(const gs_image_common_t * pic, gs_state * pgs,
@@ -178,8 +216,16 @@
return code;
}
}
- return gx_device_begin_typed_image(dev2, (const gs_imager_state *)pgs,
+ code = gx_device_begin_typed_image(dev2, (const gs_imager_state *)pgs,
NULL, pic, NULL, pgs->dev_color, pcpath, pgs->memory, ppie);
+ if (code < 0)
+ return code;
+ code = is_image_visible(pic, pgs, pcpath);
+ if (code < 0)
+ return code;
+ if (!code)
+ (*ppie)->skipping = true;
+ return 0;
}
/* Allocate an image enumerator. */
Modified: trunk/gs/src/gxcpath.c
===================================================================
--- trunk/gs/src/gxcpath.c 2006-11-23 15:01:16 UTC (rev 7221)
+++ trunk/gs/src/gxcpath.c 2006-11-23 19:01:20 UTC (rev 7222)
@@ -984,6 +984,36 @@
gx_clip_list_init(clp);
}
+/* Check whether a rectangle has a non-empty intersection with a clipping patch. */
+bool
+gx_cpath_rect_visible(gx_clip_path * pcpath, gs_int_rect *prect)
+{
+ const gx_clip_rect *pr;
+ const gx_clip_list *list = &pcpath->rect_list->list;
+
+ switch (list->count) {
+ case 0:
+ return false;
+ case 1:
+ pr = &list->single;
+ break;
+ default:
+ pr = list->head;
+ }
+ for (; pr != 0; pr = pr->next) {
+ if (pr->xmin > prect->q.x)
+ continue;
+ if (pr->xmax < prect->p.x)
+ continue;
+ if (pr->ymin > prect->q.y)
+ continue;
+ if (pr->ymax < prect->p.y)
+ continue;
+ return true;
+ }
+ return false;
+}
+
/* ------ Debugging printout ------ */
#ifdef DEBUG
Modified: trunk/gs/src/gximage.c
===================================================================
--- trunk/gs/src/gximage.c 2006-11-23 15:01:16 UTC (rev 7221)
+++ trunk/gs/src/gximage.c 2006-11-23 19:01:20 UTC (rev 7222)
@@ -85,6 +85,7 @@
piec->procs = piep;
piec->dev = dev;
piec->id = gs_next_ids(dev->memory, 1);
+ piec->skipping = false;
switch (format) {
case gs_image_format_chunky:
piec->num_planes = 1;
Modified: trunk/gs/src/gxiparam.h
===================================================================
--- trunk/gs/src/gxiparam.h 2006-11-23 15:01:16 UTC (rev 7221)
+++ trunk/gs/src/gxiparam.h 2006-11-23 19:01:20 UTC (rev 7222)
@@ -214,6 +214,7 @@
const gx_image_enum_procs_t *procs;\
gx_device *dev;\
gs_id id;\
+ bool skipping; /* don't render, just consume image streams. */\
int num_planes;\
int plane_depths[gs_image_max_planes]; /* [num_planes] */\
int plane_widths[gs_image_max_planes] /* [num_planes] */
Modified: trunk/gs/src/gxpath.h
===================================================================
--- trunk/gs/src/gxpath.h 2006-11-23 15:01:16 UTC (rev 7221)
+++ trunk/gs/src/gxpath.h 2006-11-23 19:01:20 UTC (rev 7222)
@@ -341,6 +341,7 @@
gx_cpath_includes_rectangle(const gx_clip_path *, fixed, fixed,
fixed, fixed);
const gs_fixed_rect *cpath_is_rectangle(const gx_clip_path * pcpath);
+bool gx_cpath_rect_visible(gx_clip_path * pcpath, gs_int_rect *prect);
/* Enumerate a clipping path. This interface does not copy the path. */
/* However, it does write into the path's "visited" flags. */
Modified: trunk/gs/src/lib.mak
===================================================================
--- trunk/gs/src/lib.mak 2006-11-23 15:01:16 UTC (rev 7221)
+++ trunk/gs/src/lib.mak 2006-11-23 19:01:20 UTC (rev 7222)
@@ -821,7 +821,7 @@
$(gsstruct_h) $(gxarith_h) $(gxdevice_h) $(gzht_h) $(gzstate_h) $(gswts_h)
$(GLCC) $(GLO_)gshtscr.$(OBJ) $(C_) $(GLSRC)gshtscr.c
-$(GLOBJ)gsimage.$(OBJ) : $(GLSRC)gsimage.c $(GXERR) $(memory__h)\
+$(GLOBJ)gsimage.$(OBJ) : $(GLSRC)gsimage.c $(GXERR) $(memory__h) $(math__h)\
$(gscspace_h) $(gsimage_h) $(gsmatrix_h) $(gsstruct_h) $(gsptype2_h)\
$(gxarith_h) $(gxdevice_h) $(gxiparam_h) $(gxpath_h) $(gximask_h) $(gzstate_h)
$(GLCC) $(GLO_)gsimage.$(OBJ) $(C_) $(GLSRC)gsimage.c
Modified: trunk/gs/src/zimage.c
===================================================================
--- trunk/gs/src/zimage.c 2006-11-23 15:01:16 UTC (rev 7221)
+++ trunk/gs/src/zimage.c 2006-11-23 19:01:20 UTC (rev 7222)
@@ -248,6 +248,7 @@
gs_image_enum *penum;
int px;
const ref *pp;
+ bool string_sources = true;
check_estack(inumpush + 2); /* stuff above, + continuation + proc */
make_int(EBOT_NUM_SOURCES(esp), num_sources);
@@ -284,6 +285,7 @@
break;
}
}
+ string_sources = false;
/* falls through */
case t_string:
if (r_type(pp) != r_type(sources)) {
@@ -302,6 +304,7 @@
return_error(e_typecheck);
}
check_proc(*pp);
+ string_sources = false;
}
*ep = *pp;
}
@@ -312,7 +315,7 @@
if ((penum = gs_image_enum_alloc(imemory_local, "image_setup")) == 0)
return_error(e_VMerror);
code = gs_image_enum_init(penum, pie, (const gs_data_image_t *)pim, igs);
- if (code != 0) { /* error, or empty image */
+ if (code != 0 || pie->skipping && string_sources) { /* error, or empty image */
int code1 = gs_image_cleanup_and_free_enum(penum, igs);
if (code >= 0) /* empty image */
More information about the gs-cvs
mailing list