/src/ghostpdl/base/gxmclip.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 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., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, 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 */ |
28 | 0 | static ENUM_PTRS_WITH(device_mask_clip_enum_ptrs, gx_device_mask_clip *mcdev) |
29 | 0 | { |
30 | 0 | if (index < st_gx_strip_bitmap_max_ptrs) { |
31 | 0 | return ENUM_USING(st_gx_strip_bitmap, &mcdev->tiles, |
32 | 0 | sizeof(mcdev->tiles), index); |
33 | 0 | } |
34 | 0 | index -= st_gx_strip_bitmap_max_ptrs; |
35 | 0 | if (index < st_device_memory_max_ptrs) { |
36 | 0 | return ENUM_USING(st_device_memory, &mcdev->mdev, |
37 | 0 | sizeof(mcdev->mdev), index); |
38 | 0 | } |
39 | 0 | ENUM_PREFIX(st_device_forward, st_device_memory_max_ptrs); |
40 | 0 | } |
41 | 0 | ENUM_PTRS_END |
42 | 0 | static RELOC_PTRS_WITH(device_mask_clip_reloc_ptrs, gx_device_mask_clip *mcdev) |
43 | 0 | { |
44 | 0 | RELOC_PREFIX(st_device_forward); |
45 | 0 | RELOC_USING(st_gx_strip_bitmap, &mcdev->tiles, sizeof(mcdev->tiles)); |
46 | 0 | RELOC_USING(st_device_memory, &mcdev->mdev, sizeof(mcdev->mdev)); |
47 | 0 | 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 | 0 | long diff = (char *)RELOC_OBJ(mcdev) - (char *)mcdev; |
53 | 0 | int i; |
54 | |
|
55 | 0 | for (i = 0; i < mcdev->mdev.height; ++i) |
56 | 0 | mcdev->mdev.line_ptrs[i] += diff; |
57 | 0 | mcdev->mdev.base = mcdev->mdev.line_ptrs[0]; |
58 | 0 | mcdev->mdev.line_ptrs = |
59 | 0 | (void *)((char *)(mcdev->mdev.line_ptrs) + diff); |
60 | 0 | } |
61 | 0 | } |
62 | 0 | RELOC_PTRS_END |
63 | | |
64 | | /* Initialize a mask clipping device. */ |
65 | | int |
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 | 246k | { |
71 | 246k | int buffer_width = bits->size.x; |
72 | 246k | int buffer_height = |
73 | 246k | tile_clip_buffer_size / (bits->raster + sizeof(byte *)); |
74 | | |
75 | 246k | if (mem == NULL) |
76 | 246k | gx_device_init_on_stack((gx_device *)cdev, |
77 | 246k | (const gx_device *)proto, |
78 | 246k | tdev->memory); |
79 | 321 | else |
80 | 321 | (void)gx_device_init((gx_device *)cdev, |
81 | 321 | (const gx_device *)proto, |
82 | 321 | mem, true); |
83 | 246k | cdev->width = tdev->width; |
84 | 246k | cdev->height = tdev->height; |
85 | 246k | cdev->color_info = tdev->color_info; |
86 | 246k | gx_device_set_target((gx_device_forward *)cdev, tdev); |
87 | 246k | cdev->phase.x = -tx; |
88 | 246k | cdev->phase.y = -ty; |
89 | 246k | if (buffer_height > bits->size.y) |
90 | 174k | buffer_height = bits->size.y; |
91 | 246k | gs_make_mem_mono_device(&cdev->mdev, 0, 0); |
92 | 246k | for (;;) { |
93 | 246k | size_t bitmap_size = max_ulong; |
94 | | |
95 | | /* Bug 702124: Allow for the case when size.y == 0 - then |
96 | | * buffer_height will be zero, and it's not a VMerror. */ |
97 | 246k | if (bits->size.y > 0 && buffer_height <= 0) { |
98 | | /* |
99 | | * The tile is too wide to buffer even one scan line. |
100 | | * We could do copy_mono in chunks, but for now, we punt. |
101 | | */ |
102 | 1 | cdev->mdev.base = 0; |
103 | 1 | return_error(gs_error_VMerror); |
104 | 1 | } |
105 | 246k | cdev->mdev.width = buffer_width; |
106 | 246k | cdev->mdev.height = buffer_height; |
107 | 246k | gdev_mem_bitmap_size(&cdev->mdev, &bitmap_size); |
108 | 246k | if (bitmap_size <= tile_clip_buffer_size) |
109 | 246k | break; |
110 | 0 | buffer_height--; |
111 | 0 | } |
112 | 246k | cdev->mdev.base = cdev->buffer.bytes; |
113 | 246k | return (*dev_proc(&cdev->mdev, open_device))((gx_device *)&cdev->mdev); |
114 | 246k | } |