1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* Mask clipping support */
18 #include "gx.h"
19 #include "gserrors.h"
20 #include "gxdevice.h"
21 #include "gxdevmem.h"
22 #include "gxmclip.h"
23
24 /* Structure descriptor */
25 public_st_device_mask_clip();
26
27 /* GC procedures */
ENUM_PTRS_WITH(device_mask_clip_enum_ptrs,gx_device_mask_clip * mcdev)28 static ENUM_PTRS_WITH(device_mask_clip_enum_ptrs, gx_device_mask_clip *mcdev)
29 {
30 if (index < st_gx_strip_bitmap_max_ptrs) {
31 return ENUM_USING(st_gx_strip_bitmap, &mcdev->tiles,
32 sizeof(mcdev->tiles), index);
33 }
34 index -= st_gx_strip_bitmap_max_ptrs;
35 if (index < st_device_memory_max_ptrs) {
36 return ENUM_USING(st_device_memory, &mcdev->mdev,
37 sizeof(mcdev->mdev), index);
38 }
39 ENUM_PREFIX(st_device_forward, st_device_memory_max_ptrs);
40 }
41 ENUM_PTRS_END
RELOC_PTRS_WITH(device_mask_clip_reloc_ptrs,gx_device_mask_clip * mcdev)42 static RELOC_PTRS_WITH(device_mask_clip_reloc_ptrs, gx_device_mask_clip *mcdev)
43 {
44 RELOC_PREFIX(st_device_forward);
45 RELOC_USING(st_gx_strip_bitmap, &mcdev->tiles, sizeof(mcdev->tiles));
46 RELOC_USING(st_device_memory, &mcdev->mdev, sizeof(mcdev->mdev));
47 if (mcdev->mdev.base != 0) {
48 /*
49 * Update the line pointers specially, since they point into the
50 * buffer that is part of the mask clipping device itself.
51 */
52 long diff = (char *)RELOC_OBJ(mcdev) - (char *)mcdev;
53 int i;
54
55 for (i = 0; i < mcdev->mdev.height; ++i)
56 mcdev->mdev.line_ptrs[i] += diff;
57 mcdev->mdev.base = mcdev->mdev.line_ptrs[0];
58 mcdev->mdev.line_ptrs =
59 (void *)((char *)(mcdev->mdev.line_ptrs) + diff);
60 }
61 }
62 RELOC_PTRS_END
63
64 /* Initialize a mask clipping device. */
65 int
gx_mask_clip_initialize(gx_device_mask_clip * cdev,const gx_device_mask_clip * proto,const gx_bitmap * bits,gx_device * tdev,int tx,int ty,gs_memory_t * mem)66 gx_mask_clip_initialize(gx_device_mask_clip * cdev,
67 const gx_device_mask_clip * proto,
68 const gx_bitmap * bits, gx_device * tdev,
69 int tx, int ty, gs_memory_t *mem)
70 {
71 int buffer_width = bits->size.x;
72 int buffer_height =
73 tile_clip_buffer_size / (bits->raster + sizeof(byte *));
74
75 if (mem == NULL)
76 gx_device_init_on_stack((gx_device *)cdev, (const gx_device *)proto,
77 tdev->memory);
78 else
79 gx_device_init((gx_device *)cdev, (const gx_device *)proto, mem, true);
80 cdev->width = tdev->width;
81 cdev->height = tdev->height;
82 cdev->color_info = tdev->color_info;
83 gx_device_set_target((gx_device_forward *)cdev, tdev);
84 cdev->phase.x = -tx;
85 cdev->phase.y = -ty;
86 if (buffer_height > bits->size.y)
87 buffer_height = bits->size.y;
88 gs_make_mem_mono_device(&cdev->mdev, 0, 0);
89 for (;;) {
90 ulong bitmap_size = max_ulong;
91
92 /* Bug 702124: Allow for the case when size.y == 0 - then
93 * buffer_height will be zero, and it's not a VMerror. */
94 if (bits->size.y > 0 && buffer_height <= 0) {
95 /*
96 * The tile is too wide to buffer even one scan line.
97 * We could do copy_mono in chunks, but for now, we punt.
98 */
99 cdev->mdev.base = 0;
100 return_error(gs_error_VMerror);
101 }
102 cdev->mdev.width = buffer_width;
103 cdev->mdev.height = buffer_height;
104 gdev_mem_bitmap_size(&cdev->mdev, &bitmap_size);
105 if (bitmap_size <= tile_clip_buffer_size)
106 break;
107 buffer_height--;
108 }
109 cdev->mdev.base = cdev->buffer.bytes;
110 return (*dev_proc(&cdev->mdev, open_device))((gx_device *)&cdev->mdev);
111 }
112