386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / gdevmem3.c
CommitLineData
76ba0c72
WJ
1/* Copyright (C) 1992 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
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. */
39extern gx_device_memory mem_mono_device;
40
41/* Import the color mapping procedures from gdevmem2. */
42extern dev_proc_map_rgb_color(mem_mapped_map_rgb_color);
43extern dev_proc_map_color_rgb(mem_mapped_map_color_rgb);
44
45/* Implement fill_rectangle by tiling. */
46private int
47fill_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 */
63declare_mem_procs(mem_mapped2_copy_mono, mem_mapped2_copy_color, mem_mapped2_fill_rectangle);
64
65/* The device descriptor. */
66private 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. */
71gx_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. */
79private int
80mem_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. */
105private int
106mem_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. */
151private int
152mem_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 */
171declare_mem_procs(mem_mapped4_copy_mono, mem_mapped4_copy_color, mem_mapped4_fill_rectangle);
172
173/* The device descriptor. */
174private 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. */
179gx_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. */
187private int
188mem_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. */
215private int
216mem_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. */
259private int
260mem_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}