summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-02-06 12:01:53 +0000
committerRobin Watts <robin.watts@artifex.com>2012-02-06 19:13:00 +0000
commite448aeaf3d3d572bf4e91d9acdf3fa623ed9b6fb (patch)
tree3dbaa3600a2b196223dce2bdabb1c2de87f8e353
parent09a47e5c2b0fff0d2598e38305bc3d0bc050a26f (diff)
Clipping optimisations; avoid needless clipping device.
When filling a mask, check any clipping path given; if it trivially includes all the mask, then don't bother creating a clipping device. If it trivially excludes, then don't bother plotting at all. If the bbox partially covers the area, then reduce the area of the mask. This gives a 6-8% speedup of customer 532's test files; they are filling a mask with a halftone, which breaks down into lots of short run, 1 pixel high rectangles. Avoiding the clipping device avoids lots of function call overhead.
-rw-r--r--gs/base/gdevdbit.c42
-rw-r--r--gs/base/gxclip.c38
-rw-r--r--gs/base/gxcpath.h1
3 files changed, 75 insertions, 6 deletions
diff --git a/gs/base/gdevdbit.c b/gs/base/gdevdbit.c
index 99140d5f2..9631517a1 100644
--- a/gs/base/gdevdbit.c
+++ b/gs/base/gdevdbit.c
@@ -326,14 +326,44 @@ gx_default_fill_mask(gx_device * orig_dev,
326 const gx_drawing_color * pdcolor, int depth, 326 const gx_drawing_color * pdcolor, int depth,
327 gs_logical_operation_t lop, const gx_clip_path * pcpath) 327 gs_logical_operation_t lop, const gx_clip_path * pcpath)
328{ 328{
329 gx_device *dev; 329 gx_device *dev = orig_dev;
330 gx_device_clip cdev; 330 gx_device_clip cdev;
331 331
332 if (pcpath != 0) { 332 if (w == 0 || h == 0)
333 gx_make_clip_device_on_stack(&cdev, pcpath, orig_dev); 333 return 0;
334 dev = (gx_device *) & cdev; 334
335 } else 335 if (pcpath != 0)
336 dev = orig_dev; 336 {
337 gs_fixed_rect rect;
338 int tmp;
339
340 rect.p.x = int2fixed(x);
341 rect.p.y = int2fixed(y);
342 rect.q.x = int2fixed(x+w);
343 rect.q.y = int2fixed(y+h);
344 dev = gx_make_clip_device_on_stack_if_needed(&cdev, pcpath, dev, &rect);
345 if (dev == NULL)
346 return 0;
347 /* Clip region if possible */
348 tmp = fixed2int(rect.p.x);
349 if (tmp > x)
350 {
351 dx += tmp-x;
352 x = tmp;
353 }
354 tmp = fixed2int(rect.q.x);
355 if (tmp < x+w)
356 w = tmp-x;
357 tmp = fixed2int(rect.p.y);
358 if (tmp > y)
359 {
360 data += (tmp-y) * raster;
361 y = tmp;
362 }
363 tmp = fixed2int(rect.q.y);
364 if (tmp < y+h)
365 h = tmp-y;
366 }
337 if (depth > 1) { 367 if (depth > 1) {
338 /****** CAN'T DO ROP OR HALFTONE WITH ALPHA ******/ 368 /****** CAN'T DO ROP OR HALFTONE WITH ALPHA ******/
339 return (*dev_proc(dev, copy_alpha)) 369 return (*dev_proc(dev, copy_alpha))
diff --git a/gs/base/gxclip.c b/gs/base/gxclip.c
index 0350d1eb8..4504d9f26 100644
--- a/gs/base/gxclip.c
+++ b/gs/base/gxclip.c
@@ -135,6 +135,44 @@ gx_make_clip_device_on_stack(gx_device_clip * dev, const gx_clip_path *pcpath, g
135 /* There is no finalization for device on stack so no rc increment */ 135 /* There is no finalization for device on stack so no rc increment */
136 (*dev_proc(dev, open_device)) ((gx_device *)dev); 136 (*dev_proc(dev, open_device)) ((gx_device *)dev);
137} 137}
138
139gx_device *
140gx_make_clip_device_on_stack_if_needed(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target, gs_fixed_rect *rect)
141{
142 if (pcpath->inner_box.p.x <= rect->p.x && pcpath->inner_box.p.y <= rect->p.y &&
143 pcpath->inner_box.q.x >= rect->q.x && pcpath->inner_box.q.y >= rect->q.y)
144 {
145 /* Area is trivially included. No need for clip. */
146 return target;
147 }
148 else
149 {
150 /* Reduce area if possible */
151 if (rect->p.x < pcpath->outer_box.p.x)
152 rect->p.x = pcpath->outer_box.p.x;
153 if (rect->q.x > pcpath->outer_box.q.x)
154 rect->q.x = pcpath->outer_box.q.x;
155 if (rect->p.y < pcpath->outer_box.p.y)
156 rect->p.y = pcpath->outer_box.p.y;
157 if (rect->q.y > pcpath->outer_box.q.y)
158 rect->q.y = pcpath->outer_box.q.y;
159 /* Check for area being trivially clipped away. */
160 if (rect->p.x >= rect->q.x || rect->p.y >= rect->q.y)
161 return NULL;
162 }
163 gx_device_init((gx_device *)dev, (const gx_device *)&gs_clip_device, NULL, true);
164 dev->list = *gx_cpath_list(pcpath);
165 dev->translation.x = 0;
166 dev->translation.y = 0;
167 dev->HWResolution[0] = target->HWResolution[0];
168 dev->HWResolution[1] = target->HWResolution[1];
169 dev->sgr = target->sgr;
170 dev->target = target;
171 dev->graphics_type_tag = target->graphics_type_tag; /* initialize to same as target */
172 /* There is no finalization for device on stack so no rc increment */
173 (*dev_proc(dev, open_device)) ((gx_device *)dev);
174 return (gx_device *)dev;
175}
138void 176void
139gx_make_clip_device_in_heap(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target, 177gx_make_clip_device_in_heap(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target,
140 gs_memory_t *mem) 178 gs_memory_t *mem)
diff --git a/gs/base/gxcpath.h b/gs/base/gxcpath.h
index 6bf6bf8da..6eb34d338 100644
--- a/gs/base/gxcpath.h
+++ b/gs/base/gxcpath.h
@@ -110,6 +110,7 @@ extern_st(st_device_clip);
110 "gx_device_clip", device_clip_enum_ptrs, device_clip_reloc_ptrs,\ 110 "gx_device_clip", device_clip_enum_ptrs, device_clip_reloc_ptrs,\
111 gx_device_finalize) 111 gx_device_finalize)
112void gx_make_clip_device_on_stack(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target); 112void gx_make_clip_device_on_stack(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target);
113gx_device *gx_make_clip_device_on_stack_if_needed(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target, gs_fixed_rect *rect);
113void gx_make_clip_device_in_heap(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target, 114void gx_make_clip_device_in_heap(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target,
114 gs_memory_t *mem); 115 gs_memory_t *mem);
115 116