Commit | Line | Data |
---|---|---|
76ba0c72 WJ |
1 | /* Copyright (C) 1992 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* gdevmem3.c */ | |
21 | /* 2- and 4-bit-per-pixel "memory" (stored bitmap) devices */ | |
22 | /* for Ghostscript library. */ | |
23 | #include "memory_.h" | |
24 | #include "gs.h" | |
25 | #include "gxdevice.h" | |
26 | #include "gxdevmem.h" /* semi-public definitions */ | |
27 | #include "gdevmem.h" /* private definitions */ | |
28 | ||
29 | /* The current implementations are quite inefficient. */ | |
30 | /* We intend to improve them someday.... */ | |
31 | ||
32 | /* ------ Generic procedures ------ */ | |
33 | ||
34 | /* We do everything byte-by-byte. */ | |
35 | #define chunk byte | |
36 | ||
37 | /* Import the monobit device from gdevmem1 */ | |
38 | /* so we can use its procedures. */ | |
39 | extern gx_device_memory mem_mono_device; | |
40 | ||
41 | /* Import the color mapping procedures from gdevmem2. */ | |
42 | extern dev_proc_map_rgb_color(mem_mapped_map_rgb_color); | |
43 | extern dev_proc_map_color_rgb(mem_mapped_map_color_rgb); | |
44 | ||
45 | /* Implement fill_rectangle by tiling. */ | |
46 | private int | |
47 | fill_2or4_by_tiling(gx_device *dev, int scaled_x, int y, int scaled_w, int h, | |
48 | ulong *ppattern) | |
49 | { gx_bitmap tile; | |
50 | tile.data = (byte *)ppattern; | |
51 | tile.raster = sizeof(ulong); | |
52 | tile.size.x = sizeof(ulong) * 8, tile.size.y = 1; | |
53 | tile.id = gx_no_bitmap_id; | |
54 | tile.rep_width = 1, tile.rep_height = 1; | |
55 | return (*mem_mono_device.procs->tile_rectangle) | |
56 | (dev, &tile, scaled_x, y, scaled_w, h, | |
57 | (gx_color_index)0, (gx_color_index)1, 0, 0); | |
58 | } | |
59 | ||
60 | /* ------ Mapped 2-bit color ------ */ | |
61 | ||
62 | /* Procedures */ | |
63 | declare_mem_procs(mem_mapped2_copy_mono, mem_mapped2_copy_color, mem_mapped2_fill_rectangle); | |
64 | ||
65 | /* The device descriptor. */ | |
66 | private gx_device_procs mem_mapped2_procs = | |
67 | mem_procs(mem_mapped_map_rgb_color, mem_mapped_map_color_rgb, | |
68 | mem_mapped2_copy_mono, mem_mapped2_copy_color, mem_mapped2_fill_rectangle); | |
69 | ||
70 | /* The instance is public. */ | |
71 | gx_device_memory mem_mapped2_color_device = | |
72 | mem_device("image(2)", 2, mem_mapped2_procs); | |
73 | ||
74 | /* Convert x coordinate to byte offset in scan line. */ | |
75 | #undef x_to_byte | |
76 | #define x_to_byte(x) ((x) >> 2) | |
77 | ||
78 | /* Fill a rectangle with a color. */ | |
79 | private int | |
80 | mem_mapped2_fill_rectangle(gx_device *dev, | |
81 | int x, int y, int w, int h, gx_color_index color) | |
82 | { int code; | |
83 | check_rect(); | |
84 | /* Patch the width in the device temporarily. */ | |
85 | dev->width <<= 1; | |
86 | if ( color == 0 || color == 3 ) | |
87 | { /* Use monobit fill_rectangle. */ | |
88 | code = (*mem_mono_device.procs->fill_rectangle) | |
89 | (dev, x << 1, y, w << 1, h, color & 1); | |
90 | } | |
91 | else | |
92 | { /* Use monobit tile_rectangle. */ | |
93 | static ulong tile_patterns[4] = | |
94 | { 0, 0x55555555, 0xaaaaaaaa, 0xffffffff | |
95 | }; | |
96 | code = fill_2or4_by_tiling(dev, x << 1, y, w << 1, h, | |
97 | &tile_patterns[color]); | |
98 | } | |
99 | /* Restore the correct width. */ | |
100 | dev->width >>= 1; | |
101 | return code; | |
102 | } | |
103 | ||
104 | /* Copy a bitmap. */ | |
105 | private int | |
106 | mem_mapped2_copy_mono(gx_device *dev, | |
107 | byte *base, int sourcex, int sraster, gx_bitmap_id id, | |
108 | int x, int y, int w, int h, gx_color_index zero, gx_color_index one) | |
109 | { byte *line; | |
110 | int first_bit; | |
111 | byte first_mask, b0, b1; | |
112 | static byte btab[4] = { 0, 0x55, 0xaa, 0xff }; | |
113 | static byte bmask[4] = { 0xc0, 0x30, 0xc, 3 }; | |
114 | declare_scan_ptr(dest); | |
115 | check_rect(); | |
116 | setup_rect(dest); | |
117 | line = base + (sourcex >> 3); | |
118 | first_bit = 0x80 >> (sourcex & 7); | |
119 | first_mask = bmask[x & 3]; | |
120 | b0 = btab[zero & 3]; | |
121 | b1 = btab[one & 3]; | |
122 | while ( h-- > 0 ) | |
123 | { register byte *pptr = (byte *)dest; | |
124 | byte *sptr = line; | |
125 | register int sbyte = *sptr++; | |
126 | register int bit = first_bit; | |
127 | register byte mask = first_mask; | |
128 | int count = w; | |
129 | do | |
130 | { if ( sbyte & bit ) | |
131 | { if ( one != gx_no_color_index ) | |
132 | *pptr = (*pptr & ~mask) + (b1 & mask); | |
133 | } | |
134 | else | |
135 | { if ( zero != gx_no_color_index ) | |
136 | *pptr = (*pptr & ~mask) + (b0 & mask); | |
137 | } | |
138 | if ( (bit >>= 1) == 0 ) | |
139 | bit = 0x80, sbyte = *sptr++; | |
140 | mask = (mask << 6) + (mask >> 2); | |
141 | pptr++; | |
142 | } | |
143 | while ( --count > 0 ); | |
144 | line += sraster; | |
145 | inc_chunk_ptr(dest, draster); | |
146 | } | |
147 | return 0; | |
148 | } | |
149 | ||
150 | /* Copy a color bitmap. */ | |
151 | private int | |
152 | mem_mapped2_copy_color(gx_device *dev, | |
153 | byte *base, int sourcex, int sraster, gx_bitmap_id id, | |
154 | int x, int y, int w, int h) | |
155 | { int code; | |
156 | check_rect(); | |
157 | /* Use monobit copy_mono. */ | |
158 | /* Patch the width in the device temporarily. */ | |
159 | dev->width <<= 1; | |
160 | code = (*mem_mono_device.procs->copy_mono) | |
161 | (dev, base, sourcex << 1, sraster, id, | |
162 | x << 1, y, w << 1, h, (gx_color_index)0, (gx_color_index)1); | |
163 | /* Restore the correct width. */ | |
164 | dev->width >>= 1; | |
165 | return code; | |
166 | } | |
167 | ||
168 | /* ------ Mapped 4-bit color ------ */ | |
169 | ||
170 | /* Procedures */ | |
171 | declare_mem_procs(mem_mapped4_copy_mono, mem_mapped4_copy_color, mem_mapped4_fill_rectangle); | |
172 | ||
173 | /* The device descriptor. */ | |
174 | private gx_device_procs mem_mapped4_procs = | |
175 | mem_procs(mem_mapped_map_rgb_color, mem_mapped_map_color_rgb, | |
176 | mem_mapped4_copy_mono, mem_mapped4_copy_color, mem_mapped4_fill_rectangle); | |
177 | ||
178 | /* The instance is public. */ | |
179 | gx_device_memory mem_mapped4_color_device = | |
180 | mem_device("image(4)", 4, mem_mapped4_procs); | |
181 | ||
182 | /* Convert x coordinate to byte offset in scan line. */ | |
183 | #undef x_to_byte | |
184 | #define x_to_byte(x) ((x) >> 1) | |
185 | ||
186 | /* Fill a rectangle with a color. */ | |
187 | private int | |
188 | mem_mapped4_fill_rectangle(gx_device *dev, | |
189 | int x, int y, int w, int h, gx_color_index color) | |
190 | { int code; | |
191 | check_rect(); | |
192 | /* Patch the width in the device temporarily. */ | |
193 | dev->width <<= 2; | |
194 | if ( color == 0 || color == 15 ) | |
195 | { /* Use monobit fill_rectangle. */ | |
196 | code = (*mem_mono_device.procs->fill_rectangle) | |
197 | (dev, x << 2, y, w << 2, h, color & 1); | |
198 | } | |
199 | else | |
200 | { /* Use monobit tile_rectangle. */ | |
201 | static ulong tile_patterns[16] = | |
202 | { 0, 0x11111111, 0x22222222, 0x33333333, | |
203 | 0x44444444, 0x55555555, 0x66666666, 0x77777777, | |
204 | 0x88888888, 0x99999999, 0xaaaaaaaa, 0xbbbbbbbb, | |
205 | 0xcccccccc, 0xdddddddd, 0xeeeeeeee, 0xffffffff | |
206 | }; | |
207 | code = fill_2or4_by_tiling(dev, x << 2, y, w << 2, h, | |
208 | &tile_patterns[color]); | |
209 | } | |
210 | dev->width >>= 2; | |
211 | return code; | |
212 | } | |
213 | ||
214 | /* Copy a bitmap. */ | |
215 | private int | |
216 | mem_mapped4_copy_mono(gx_device *dev, | |
217 | byte *base, int sourcex, int sraster, gx_bitmap_id id, | |
218 | int x, int y, int w, int h, gx_color_index zero, gx_color_index one) | |
219 | { byte *line; | |
220 | int first_bit; | |
221 | byte first_mask, b0, b1; | |
222 | declare_scan_ptr(dest); | |
223 | check_rect(); | |
224 | setup_rect(dest); | |
225 | line = base + (sourcex >> 3); | |
226 | first_bit = 0x80 >> (sourcex & 7); | |
227 | first_mask = (x & 1 ? 0xf : 0xf0); | |
228 | b0 = ((byte)zero << 4) + (byte)zero; | |
229 | b1 = ((byte)one << 4) + (byte)one; | |
230 | while ( h-- > 0 ) | |
231 | { register byte *pptr = (byte *)dest; | |
232 | byte *sptr = line; | |
233 | register int sbyte = *sptr++; | |
234 | register int bit = first_bit; | |
235 | register byte mask = first_mask; | |
236 | int count = w; | |
237 | do | |
238 | { if ( sbyte & bit ) | |
239 | { if ( one != gx_no_color_index ) | |
240 | *pptr = (*pptr & ~mask) + (b1 & mask); | |
241 | } | |
242 | else | |
243 | { if ( zero != gx_no_color_index ) | |
244 | *pptr = (*pptr & ~mask) + (b0 & mask); | |
245 | } | |
246 | if ( (bit >>= 1) == 0 ) | |
247 | bit = 0x80, sbyte = *sptr++; | |
248 | mask = ~mask; | |
249 | pptr++; | |
250 | } | |
251 | while ( --count > 0 ); | |
252 | line += sraster; | |
253 | inc_chunk_ptr(dest, draster); | |
254 | } | |
255 | return 0; | |
256 | } | |
257 | ||
258 | /* Copy a color bitmap. */ | |
259 | private int | |
260 | mem_mapped4_copy_color(gx_device *dev, | |
261 | byte *base, int sourcex, int sraster, gx_bitmap_id id, | |
262 | int x, int y, int w, int h) | |
263 | { int code; | |
264 | check_rect(); | |
265 | /* Use monobit copy_mono. */ | |
266 | /* Patch the width in the device temporarily. */ | |
267 | dev->width <<= 2; | |
268 | code = (*mem_mono_device.procs->copy_mono) | |
269 | (dev, base, sourcex << 2, sraster, id, | |
270 | x << 2, y, w << 2, h, (gx_color_index)0, (gx_color_index)1); | |
271 | /* Restore the correct width. */ | |
272 | dev->width >>= 2; | |
273 | return code; | |
274 | } |