diff options
author | Sam James <sam@gentoo.org> | 2022-09-21 14:18:08 +0100 |
---|---|---|
committer | Sam James <sam@gentoo.org> | 2022-10-02 04:31:25 +0100 |
commit | a529111f77ff46f4836fe7312e70953bc16587cf (patch) | |
tree | 9dc3924cb1a6ef3ef853b7bb45f735365e0b4e6d /base/gdevsclass.c | |
parent | Import Ghostscript 9.56.1 (diff) | |
download | ghostscript-gpl-patches-ghostscript-10.tar.gz ghostscript-gpl-patches-ghostscript-10.tar.bz2 ghostscript-gpl-patches-ghostscript-10.zip |
Import Ghostscript 10.0ghostscript-10.0ghostscript-10
Signed-off-by: Sam James <sam@gentoo.org>
Diffstat (limited to 'base/gdevsclass.c')
-rw-r--r-- | base/gdevsclass.c | 114 |
1 files changed, 109 insertions, 5 deletions
diff --git a/base/gdevsclass.c b/base/gdevsclass.c index 2f757b76..eda152eb 100644 --- a/base/gdevsclass.c +++ b/base/gdevsclass.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -359,6 +359,99 @@ int default_subclass_get_bits_rectangle(gx_device *dev, const gs_int_rect *prect return gx_default_get_bits_rectangle(dev, prect, params); } +static void subclass_composite_front_finalize(gx_device *dev) +{ + generic_subclass_data *psubclass_data = (generic_subclass_data *)dev->parent->subclass_data; + + dev->parent->child = psubclass_data->pre_composite_device; + psubclass_data->saved_finalize_method(dev); +} + +int default_subclass_composite_front(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte, + gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev) +{ + int code = 0; + gs_pdf14trans_t *pct = (gs_pdf14trans_t *)pcte; + generic_subclass_data *psubclass_data = (generic_subclass_data *)dev->subclass_data; + gx_device *thisdev = dev; + + if (dev->child) { + code = dev_proc(dev->child, composite)(dev->child, pcdev, pcte, pgs, memory, cdev); + if (code < 0) + return code; + + if (gs_is_pdf14trans_compositor(pcte)) { + switch(pct->params.pdf14_op) + { + case PDF14_POP_DEVICE: + if (psubclass_data->pre_composite_device != NULL) { + if (dev->child) { + dev->child->parent = NULL; + dev->child->child = NULL; + dev->child->finalize = psubclass_data->saved_finalize_method; + rc_decrement(dev->child, "default_subclass_composite_front"); + } + dev->child = psubclass_data->pre_composite_device; + psubclass_data->pre_composite_device = NULL; + psubclass_data->saved_finalize_method = NULL; + while (dev) { + memcpy(&(dev->color_info), &(dev->child->color_info), sizeof(gx_device_color_info)); + dev = dev->parent; + } + } + break; + case PDF14_PUSH_DEVICE: + /* *pcdev is always returned containing a device capable of doing + * compositing. This may mean it is a new device. If this wants + * to be the new 'device' in the graphics state, then code will + * return as 1. */ + if (code == 1) { + /* We want this device to stay ahead of the compositor; the newly created compositor has + * inserted itself in front of our child device, so basically we want to replace + * our current child with the newly created compositor. I hope ! + */ + psubclass_data = (generic_subclass_data *)dev->subclass_data; + if (psubclass_data == NULL) + return_error(gs_error_undefined); + psubclass_data->pre_composite_device = dev->child; + psubclass_data->saved_finalize_method = (*pcdev)->finalize; + (*pcdev)->finalize = subclass_composite_front_finalize; + + (*pcdev)->child = dev->child; + dev->child = *pcdev; + (*pcdev)->parent = dev; + while (dev) { + memcpy(&dev->color_info, &(*pcdev)->color_info, sizeof(gx_device_color_info)); + dev = dev->parent; + } + } + break; + default: + /* It seems like many operations can result in the pdf14 device altering its color + * info, presumably as we push different blending spaces. Ick. In order to stay in sync + * any time we have inserted a compositor after this class, we must update the color info + * of this device after every operation, in case it changes.... + */ + if (psubclass_data->pre_composite_device != NULL) { + while (dev) { + memcpy(&(dev->color_info), &(dev->child->color_info), sizeof(gx_device_color_info)); + dev = dev->parent; + } + } + break; + } + + } + /* We are inserting the compositor code after this device, or the compositor + * did not create a new compositor. Either way we don't want the compositor code + * to think we want to push a new device, so just return this device to the caller. + */ + *pcdev = thisdev; + return 0; + } + return 0; +} + int default_subclass_composite(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte, gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev) { @@ -439,7 +532,7 @@ int default_subclass_composite(gx_device *dev, gx_device **pcdev, const gs_compo else { /* See the 2 comments above. Now, if the child did not create a new compositor (eg its a clist) * then it returns pcdev pointing to the passed in device (the child in our case). Now this is a - * problem, if we return with pcdev == child->dev, and teh current device is 'dev' then the + * problem, if we return with pcdev == child->dev, and the current device is 'dev' then the * compositor code will think we wanted to push a new device and will select the child device. * so here if pcdev == dev->child we change it to be our own device, so that the calling code * won't redirect the device in the graphics state. @@ -757,6 +850,13 @@ int default_subclass_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_p return 0; } +int default_subclass_lock_pattern(gx_device *dev, gs_gstate *pgs, gs_id pattern_id, int lock) +{ + if (dev->child) + return dev_proc(dev->child, lock_pattern)(dev->child, pgs, pattern_id, lock); + return 0; +} + int default_subclass_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data) { if (dev->child) @@ -776,13 +876,16 @@ void default_subclass_finalize(const gs_memory_t *cmem, void *vptr) if (dev->finalize) dev->finalize(dev); + /* Use rc_decrement_only here not rc_decrement because rc_decrement zeroes the + * pointer if the count reaches 0. That would be disastrous for us because we + * rely on recursively calling finalize in order to fix up the chain of devices. + */ + rc_decrement_only(dev->child, "de-reference child device"); + if (psubclass_data) { gs_free_object(dev->memory->non_gc_memory, psubclass_data, "gx_epo_finalize(suclass data)"); dev->subclass_data = NULL; } - if (dev->child) { - gs_free_object(dev->memory->stable_memory, dev->child, "free child device memory for subclassing device"); - } if (dev->stype_is_dynamic) gs_free_const_object(dev->memory->non_gc_memory, dev->stype, "default_subclass_finalize"); @@ -860,6 +963,7 @@ void default_subclass_initialize_device_procs(gx_device *dev) set_dev_proc(dev, process_page, default_subclass_process_page); set_dev_proc(dev, transform_pixel_region, default_subclass_transform_pixel_region); set_dev_proc(dev, fill_stroke_path, default_subclass_fill_stroke_path); + set_dev_proc(dev, lock_pattern, default_subclass_lock_pattern); } int |