diff options
Diffstat (limited to 'base/gxclip.c')
-rw-r--r-- | base/gxclip.c | 108 |
1 files changed, 98 insertions, 10 deletions
diff --git a/base/gxclip.c b/base/gxclip.c index 47a19965..b0924307 100644 --- a/base/gxclip.c +++ b/base/gxclip.c @@ -47,6 +47,7 @@ static dev_proc_get_clipping_box(clip_get_clipping_box); static dev_proc_get_bits_rectangle(clip_get_bits_rectangle); static dev_proc_fill_path(clip_fill_path); static dev_proc_transform_pixel_region(clip_transform_pixel_region); +static dev_proc_fill_stroke_path(clip_fill_stroke_path); /* The device descriptor. */ static const gx_device_clip gs_clip_device = @@ -124,8 +125,9 @@ static const gx_device_clip gs_clip_device = clip_strip_copy_rop2, clip_strip_tile_rect_devn, clip_copy_alpha_hl_color, - NULL, - clip_transform_pixel_region + NULL, /* process_page */ + clip_transform_pixel_region, + clip_fill_stroke_path, } }; @@ -1600,14 +1602,25 @@ clip_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason /* Single unskewed rectangle - we can use the underlying device direct */ local_data.u.init.clip = &local_clip; local_clip = *data->u.init.clip; - if (local_clip.p.x < cdev->current->xmin) - local_clip.p.x = cdev->current->xmin; - if (local_clip.q.x > cdev->current->xmax) - local_clip.q.x = cdev->current->xmax; - if (local_clip.p.y < cdev->current->ymin) - local_clip.p.y = cdev->current->ymin; - if (local_clip.q.y > cdev->current->ymax) - local_clip.q.y = cdev->current->ymax; + if (cdev->list.transpose) { + if (local_clip.p.x < cdev->current->ymin) + local_clip.p.x = cdev->current->ymin; + if (local_clip.q.x > cdev->current->ymax) + local_clip.q.x = cdev->current->ymax; + if (local_clip.p.y < cdev->current->xmin) + local_clip.p.y = cdev->current->xmin; + if (local_clip.q.y > cdev->current->xmax) + local_clip.q.y = cdev->current->xmax; + } else { + if (local_clip.p.x < cdev->current->xmin) + local_clip.p.x = cdev->current->xmin; + if (local_clip.q.x > cdev->current->xmax) + local_clip.q.x = cdev->current->xmax; + if (local_clip.p.y < cdev->current->ymin) + local_clip.p.y = cdev->current->ymin; + if (local_clip.q.y > cdev->current->ymax) + local_clip.q.y = cdev->current->ymax; + } state->use_default = 0; ret = dev_proc(cdev->target, transform_pixel_region)(cdev->target, reason, &local_data); } else { @@ -1634,3 +1647,78 @@ clip_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason return ret; } + +static int +clip_call_fill_stroke_path(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec) +{ + gx_device *tdev = pccd->tdev; + dev_proc_fill_stroke_path((*proc)); + int code; + gx_clip_path cpath_intersection; + gx_clip_path *pcpath = (gx_clip_path *)pccd->pcpath; + + /* Previously the code here tested for pcpath != NULL, but + * we can commonly (such as from clist_playback_band) be + * called with a non-NULL, but still invalid clip path. + * Detect this by the list having at least one entry in it. */ + if (pcpath != NULL && pcpath->rect_list->list.count != 0) { + gx_path rect_path; + code = gx_cpath_init_local_shared_nested(&cpath_intersection, pcpath, pccd->ppath->memory, 1); + if (code < 0) + return code; + gx_path_init_local(&rect_path, pccd->ppath->memory); + code = gx_path_add_rectangle(&rect_path, int2fixed(xc), int2fixed(yc), int2fixed(xec), int2fixed(yec)); + if (code < 0) + return code; + code = gx_cpath_intersect(&cpath_intersection, &rect_path, + gx_rule_winding_number, (gs_gstate *)(pccd->pgs)); + gx_path_free(&rect_path, "clip_call_fill_stroke_path"); + } else { + gs_fixed_rect clip_box; + clip_box.p.x = int2fixed(xc); + clip_box.p.y = int2fixed(yc); + clip_box.q.x = int2fixed(xec); + clip_box.q.y = int2fixed(yec); + gx_cpath_init_local(&cpath_intersection, pccd->ppath->memory); + code = gx_cpath_from_rectangle(&cpath_intersection, &clip_box); + } + if (code < 0) + return code; + proc = dev_proc(tdev, fill_stroke_path); + if (proc == NULL) + proc = gx_default_fill_stroke_path; + code = (*proc)(pccd->tdev, pccd->pgs, pccd->ppath, pccd->params, + pccd->pdcolor, pccd->stroke_params, pccd->pstroke_dcolor, + &cpath_intersection); + gx_cpath_free(&cpath_intersection, "clip_call_fill_stroke_path"); + return code; +} + +static int +clip_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, + gx_path *ppath, + const gx_fill_params *params, + const gx_drawing_color *pdcolor, + const gx_stroke_params *stroke_params, + const gx_drawing_color *pstroke_dcolor, + const gx_clip_path *pcpath) +{ + gx_device_clip *rdev = (gx_device_clip *) dev; + clip_callback_data_t ccdata; + gs_fixed_rect box; + + ccdata.pgs = pgs; + ccdata.ppath = ppath; + ccdata.params = params; + ccdata.pdcolor = pdcolor; + ccdata.stroke_params = stroke_params; + ccdata.pstroke_dcolor = pstroke_dcolor; + ccdata.pcpath = pcpath; + clip_get_clipping_box(dev, &box); + return clip_enumerate(rdev, + fixed2int(box.p.x), + fixed2int(box.p.y), + fixed2int(box.q.x - box.p.x), + fixed2int(box.q.y - box.p.y), + clip_call_fill_stroke_path, &ccdata); +} |