xref: /plan9/sys/src/cmd/gs/src/gxmclip.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1998, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gxmclip.c,v 1.4 2002/02/21 22:24:53 giles Exp $ */
18 /* Mask clipping support */
19 #include "gx.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 private 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 private 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     gx_device_init((gx_device *)cdev, (const gx_device *)proto,
76 		   mem, true);
77     cdev->width = tdev->width;
78     cdev->height = tdev->height;
79     cdev->color_info = tdev->color_info;
80     gx_device_set_target((gx_device_forward *)cdev, tdev);
81     cdev->phase.x = -tx;
82     cdev->phase.y = -ty;
83     if (buffer_height > bits->size.y)
84 	buffer_height = bits->size.y;
85     gs_make_mem_mono_device(&cdev->mdev, 0, 0);
86     for (;;) {
87 	if (buffer_height <= 0) {
88 	    /*
89 	     * The tile is too wide to buffer even one scan line.
90 	     * We could do copy_mono in chunks, but for now, we punt.
91 	     */
92 	    cdev->mdev.base = 0;
93 	    return 0;
94 	}
95 	cdev->mdev.width = buffer_width;
96 	cdev->mdev.height = buffer_height;
97 	if (gdev_mem_bitmap_size(&cdev->mdev) <= tile_clip_buffer_size)
98 	    break;
99 	buffer_height--;
100     }
101     cdev->mdev.base = cdev->buffer.bytes;
102     return (*dev_proc(&cdev->mdev, open_device))((gx_device *)&cdev->mdev);
103 }
104