diff options
Diffstat (limited to 'base/gdevmpla.c')
-rw-r--r-- | base/gdevmpla.c | 82 |
1 files changed, 79 insertions, 3 deletions
diff --git a/base/gdevmpla.c b/base/gdevmpla.c index ae805f4e..d889efcf 100644 --- a/base/gdevmpla.c +++ b/base/gdevmpla.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -29,6 +29,7 @@ /* procedures */ static dev_proc_open_device(mem_planar_open); +static dev_proc_open_device(mem_planar_open_interleaved); declare_mem_procs(mem_planar_copy_mono, mem_planar_copy_color, mem_planar_fill_rectangle); static dev_proc_copy_color(mem_planar_copy_color_24to8); static dev_proc_copy_color(mem_planar_copy_color_4to1); @@ -48,7 +49,8 @@ mem_planar_dev_spec_op(gx_device *pdev, int dev_spec_op, { cmm_dev_profile_t *dev_profile; - if (dev_spec_op == gxdso_supports_devn) { + if (dev_spec_op == gxdso_supports_devn + || dev_spec_op == gxdso_skip_icc_component_validation) { dev_proc(pdev, get_profile)(pdev, &dev_profile); if (dev_profile != NULL && dev_profile->supports_devn && dev_proc(pdev, fill_rectangle_hl_color) == mem_planar_fill_rectangle_hl_color) @@ -80,6 +82,14 @@ int gdev_mem_set_planar(gx_device_memory * mdev, int num_planes, const gx_render_plane_t *planes /*[num_planes]*/) { + return gdev_mem_set_planar_interleaved(mdev, num_planes, planes, 0); +} + +int +gdev_mem_set_planar_interleaved(gx_device_memory * mdev, int num_planes, + const gx_render_plane_t *planes /*[num_planes]*/, + int interleaved) +{ int total_depth; int same_depth = planes[0].depth; gx_color_index covered = 0; @@ -114,7 +124,10 @@ gdev_mem_set_planar(gx_device_memory * mdev, int num_planes, memcpy(mdev->planes, planes, num_planes * sizeof(planes[0])); mdev->plane_depth = same_depth; /* Change the drawing procedures. */ - set_dev_proc(mdev, open_device, mem_planar_open); + if (interleaved) + set_dev_proc(mdev, open_device, mem_planar_open_interleaved); + else + set_dev_proc(mdev, open_device, mem_planar_open); /* Regardless of how many planes we are using, always let the * device know how to handle hl_color. Even if we spot that we * can get away with a normal device, our callers may want to @@ -182,6 +195,17 @@ mem_planar_open(gx_device * dev) return gdev_mem_open_scan_lines(mdev, dev->height); } +static int +mem_planar_open_interleaved(gx_device * dev) +{ + gx_device_memory *const mdev = (gx_device_memory *)dev; + + /* Check that we aren't trying to open a chunky device as planar. */ + if (!dev->is_planar) + return_error(gs_error_rangecheck); + return gdev_mem_open_scan_lines_interleaved(mdev, dev->height, 1); +} + /* * We execute drawing operations by patching a few parameters in the * device structure and then calling the procedure appropriate to the @@ -2110,6 +2134,7 @@ mem_planar_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, /* First off, see if we can satisfy get_bits_rectangle with just returning * pointers to the existing data. */ + if (params->options & GB_RETURN_POINTER) { gs_get_bits_params_t copy_params; byte **base = &scan_line_base(mdev, y); @@ -2165,6 +2190,57 @@ mem_planar_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, } } } + + if ((params->options & GB_RETURN_POINTER) == 0) { + /* Can we do the fetch using a faked GB_RETURN_POINTER request + * and then copy the data? */ + gs_get_bits_params_t params2 = *params; + gs_get_bits_params_t copy_params; + byte **base = &scan_line_base(mdev, y); + int code; + + params2.options &= ~GB_RETURN_COPY; + params2.options |= GB_RETURN_POINTER; + + copy_params.options = + GB_COLORS_NATIVE | GB_PACKING_PLANAR | GB_ALPHA_NONE | + (mdev->raster == + bitmap_raster(mdev->width * mdev->color_info.depth) ? + GB_RASTER_STANDARD : GB_RASTER_SPECIFIED); + params2.raster = mdev->raster; + copy_params.raster = mdev->raster; + code = gx_get_bits_return_pointer(dev, x, h, ¶ms2, + ©_params, base); + if (code >= 0) { + /* get_bits worked. Let's copy the data out. */ + int bpc = mdev->color_info.depth / mdev->color_info.num_components; + int left = x; + int right = x+w; + int i, j; + switch (bpc) { + case 1: left >>= 3; right = (right+7)>>3; break; + case 2: left >>= 2; right = (right+3)>>2; break; + case 4: left >>= 1; right = (right+1)>>1; break; + case 8: break; + case 12: left = (left&~1); left += left>>1; + right = right+(right>>1)+(right&1); break; + case 16: left *= 2; right *= 2; break; + default: return_error(gs_error_rangecheck); + } + right -= left; + for (i = 0; i < mdev->color_info.num_components; i++) { + byte *d = params->data[i]; + const byte *s = params2.data[i]; + for (j = 0; j < h; j++) { + memcpy(d, s, right); + d += params->raster; + s += params2.raster; + } + } + return code; + } + } + /* * We can't return the requested plane by itself. Fall back to * chunky format. This is somewhat painful. |