386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / gdevmem2.c
CommitLineData
3b7d6b60
WJ
1/* Copyright (C) 1989, 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/* gdevmem2.c */
21/* 8-and-more-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/* ------ Generic procedures ------ */
30
31/* Copy a rectangle of bytes from a source to a destination. */
32#undef chunk
33#define chunk byte
34private int
35copy_byte_rect(gx_device_memory *dev, const byte *source, int sraster,
36 int offset, int y, int byte_count, int h)
37{ uint draster = dev->raster;
38 byte *dest = scan_line_base(dev, y) + offset;
39 while ( h-- > 0 )
40 { memcpy(dest, source, byte_count);
41 source += sraster;
42 dest += draster;
43 }
44 return 0;
45}
46
47/* Map a r-g-b color to a color index. */
48/* This requires searching the palette. */
49gx_color_index
50mem_mapped_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g,
51 gx_color_value b)
52{ byte br = gx_color_value_to_byte(r);
53 byte bg = gx_color_value_to_byte(g);
54 byte bb = gx_color_value_to_byte(b);
55 register byte *pptr = mdev->palette;
56 int cnt = mdev->palette_size;
57 byte *which;
58 int best = 256*3;
59 while ( cnt-- > 0 )
60 { register int diff = *pptr - br;
61 if ( diff < 0 ) diff = -diff;
62 if ( diff < best ) /* quick rejection */
63 { int dg = pptr[1] - bg;
64 if ( dg < 0 ) dg = -dg;
65 if ( (diff += dg) < best ) /* quick rejection */
66 { int db = pptr[2] - bb;
67 if ( db < 0 ) db = -db;
68 if ( (diff += db) < best )
69 which = pptr, best = diff;
70 }
71 }
72 pptr += 3;
73 }
74 return (gx_color_index)((which - mdev->palette) / 3);
75}
76
77/* Map a color index to a r-g-b color. */
78int
79mem_mapped_map_color_rgb(gx_device *dev, gx_color_index color,
80 gx_color_value prgb[3])
81{ byte *pptr = mdev->palette + (int)color * 3;
82 prgb[0] = gx_color_value_from_byte(pptr[0]);
83 prgb[1] = gx_color_value_from_byte(pptr[1]);
84 prgb[2] = gx_color_value_from_byte(pptr[2]);
85 return 0;
86}
87
88/* ------ Mapped 8-bit color ------ */
89
90/* Procedures */
91declare_mem_procs(mem_mapped8_copy_mono, mem_mapped8_copy_color, mem_mapped8_fill_rectangle);
92
93/* The device descriptor. */
94private gx_device_procs mem_mapped8_procs =
95 mem_procs(mem_mapped_map_rgb_color, mem_mapped_map_color_rgb,
96 mem_mapped8_copy_mono, mem_mapped8_copy_color, mem_mapped8_fill_rectangle);
97
98/* The instance is public. */
99gx_device_memory mem_mapped8_color_device =
100 mem_device("image(8)", 8, mem_mapped8_procs);
101
102/* Convert x coordinate to byte offset in scan line. */
103#undef x_to_byte
104#define x_to_byte(x) (x)
105
106/* Fill a rectangle with a color. */
107private int
108mem_mapped8_fill_rectangle(gx_device *dev,
109 int x, int y, int w, int h, gx_color_index color)
110{ declare_scan_ptr(dest);
111 check_rect();
112 setup_rect(dest);
113 while ( h-- > 0 )
114 { memset(dest, (byte)color, w);
115 inc_chunk_ptr(dest, draster);
116 }
117 return 0;
118}
119
120/* Copy a monochrome bitmap. */
121private int
122mem_mapped8_copy_mono(gx_device *dev,
123 byte *base, int sourcex, int sraster, gx_bitmap_id id,
124 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
125{ byte *line;
126 int first_bit;
127 declare_scan_ptr(dest);
128 check_rect();
129 setup_rect(dest);
130 line = base + (sourcex >> 3);
131 first_bit = 0x80 >> (sourcex & 7);
132 while ( h-- > 0 )
133 { register byte *pptr = dest;
134 byte *sptr = line;
135 register int sbyte = *sptr;
136 register uint bit = first_bit;
137 int count = w;
138#define is_color(c) ((int)(c) != (int)gx_no_color_index)
139#define next_bit()\
140 if ( (bit >>= 1) == 0 ) bit = 0x80, sbyte = *++sptr;\
141 pptr++
142 if ( is_color(one) )
143 { if ( is_color(zero) )
144 { /* Optimize halftone coloring */
145 do
146 { *pptr = (sbyte & bit ? (byte)one :
147 (byte)zero);
148 next_bit();
149 }
150 while ( --count > 0 );
151 }
152 else
153 { /* Optimize stenciling */
154 do
155 { if ( sbyte & bit )
156 *pptr = (byte)one;
157 next_bit();
158 }
159 while ( --count > 0 );
160 }
161 }
162 else if ( is_color(zero) )
163 { do
164 { if ( !(sbyte & bit) )
165 *pptr = (byte)zero;
166 next_bit();
167 }
168 while ( --count > 0 );
169 }
170#undef next_bit
171#undef is_color
172 line += sraster;
173 inc_chunk_ptr(dest, draster);
174 }
175 return 0;
176}
177
178/* Copy a color bitmap. */
179private int
180mem_mapped8_copy_color(gx_device *dev,
181 byte *base, int sourcex, int sraster, gx_bitmap_id id,
182 int x, int y, int w, int h)
183{ check_rect();
184 return copy_byte_rect(mdev, base + x_to_byte(sourcex), sraster,
185 x_to_byte(x), y, x_to_byte(w), h);
186}
187
188/* ------ 16-bit true color ------ */
189/* The 16 bits are divided 5 for red, 6 for green, and 5 for blue. */
190
191/* Procedures */
192declare_mem_map_procs(mem_true16_map_rgb_color, mem_true16_map_color_rgb);
193declare_mem_procs(mem_true16_copy_mono, mem_true16_copy_color, mem_true16_fill_rectangle);
194
195/* The device descriptor. */
196private gx_device_procs mem_true16_procs =
197 mem_procs(mem_true16_map_rgb_color, mem_true16_map_color_rgb,
198 mem_true16_copy_mono, mem_true16_copy_color, mem_true16_fill_rectangle);
199
200/* The instance is public. */
201gx_device_memory mem_true16_color_device =
202 mem_device("image(16)", 16, mem_true16_procs);
203
204/* Map a r-g-b color to a color index. */
205private gx_color_index
206mem_true16_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g,
207 gx_color_value b)
208{ return ((r >> (gx_color_value_bits - 5)) << 11) +
209 ((g >> (gx_color_value_bits - 6)) << 5) +
210 (b >> (gx_color_value_bits - 5));
211}
212
213/* Map a color index to a r-g-b color. */
214private int
215mem_true16_map_color_rgb(gx_device *dev, gx_color_index color,
216 gx_color_value prgb[3])
217{ ushort value;
218 value = color >> 11;
219 prgb[0] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
220 value = (color >> 6) & 0x7f;
221 prgb[1] = ((value << 10) + (value << 4) + (value >> 2)) >> (16 - gx_color_value_bits);
222 value = color & 0x3f;
223 prgb[2] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
224 return 0;
225}
226
227/* Convert x coordinate to byte offset in scan line. */
228#undef x_to_byte
229#define x_to_byte(x) ((x) << 1)
230
231/* Fill a rectangle with a color. */
232private int
233mem_true16_fill_rectangle(gx_device *dev,
234 int x, int y, int w, int h, gx_color_index color)
235{ declare_scan_ptr(dest);
236 check_rect();
237 setup_rect(dest);
238 while ( h-- > 0 )
239 { ushort *pptr = (ushort *)dest;
240 int cnt = w;
241 do { *pptr++ = (ushort)color; } while ( --cnt > 0 );
242 inc_chunk_ptr(dest, draster);
243 }
244 return 0;
245}
246
247/* Copy a monochrome bitmap. */
248private int
249mem_true16_copy_mono(gx_device *dev,
250 byte *base, int sourcex, int sraster, gx_bitmap_id id,
251 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
252{ byte *line;
253 int first_bit;
254 declare_scan_ptr(dest);
255 check_rect();
256 setup_rect(dest);
257 line = base + (sourcex >> 3);
258 first_bit = 0x80 >> (sourcex & 7);
259 while ( h-- > 0 )
260 { register ushort *pptr = (ushort *)dest;
261 byte *sptr = line;
262 register int sbyte = *sptr++;
263 register int bit = first_bit;
264 int count = w;
265 do
266 { if ( sbyte & bit )
267 { if ( one != gx_no_color_index )
268 *pptr = (ushort)one;
269 }
270 else
271 { if ( zero != gx_no_color_index )
272 *pptr = (ushort)zero;
273 }
274 if ( (bit >>= 1) == 0 )
275 bit = 0x80, sbyte = *sptr++;
276 pptr++;
277 }
278 while ( --count > 0 );
279 line += sraster;
280 inc_chunk_ptr(dest, draster);
281 }
282 return 0;
283}
284
285/* Copy a color bitmap. */
286private int
287mem_true16_copy_color(gx_device *dev,
288 byte *base, int sourcex, int sraster, gx_bitmap_id id,
289 int x, int y, int w, int h)
290{ check_rect();
291 return copy_byte_rect(mdev, base + x_to_byte(sourcex), sraster,
292 x_to_byte(x), y, x_to_byte(w), h);
293}
294
295/* ------ 24- or 32-bit true color ------ */
296
297/* Procedures */
298declare_mem_map_procs(mem_true_map_rgb_color, mem_true_map_color_rgb);
299
300/* The device descriptor. */
301#define mem_true_procs(copy_mono, copy_color, fill_rectangle)\
302 mem_procs(mem_true_map_rgb_color, mem_true_map_color_rgb,\
303 copy_mono, copy_color, fill_rectangle)
304
305/* We want the bytes of a color always to be in the order -,r,g,b, */
306/* but we want to manipulate colors as longs. This requires careful */
307/* handling to be byte-order independent. */
308#define color_byte(cx,i) (((byte *)&(cx))[i])
309
310/* Map a r-g-b color to a color index. */
311private gx_color_index
312mem_true_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g,
313 gx_color_value b)
314{ return gx_color_value_to_byte(b) +
315 ((uint)gx_color_value_to_byte(g) << 8) +
316 ((ulong)gx_color_value_to_byte(r) << 16);
317}
318
319/* Map a color index to a r-g-b color. */
320private int
321mem_true_map_color_rgb(gx_device *dev, gx_color_index color,
322 gx_color_value prgb[3])
323{ prgb[0] = gx_color_value_from_byte(color >> 16);
324 prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
325 prgb[2] = gx_color_value_from_byte(color & 0xff);
326 return 0;
327}
328
329/* ------ 24-bit color ------ */
330/* 24-bit takes less space than 32-bit, but is slower. */
331
332/* Procedures */
333declare_mem_procs(mem_true24_copy_mono, mem_true24_copy_color, mem_true24_fill_rectangle);
334
335/* The device descriptor. */
336private gx_device_procs mem_true24_procs =
337 mem_true_procs(mem_true24_copy_mono, mem_true24_copy_color,
338 mem_true24_fill_rectangle);
339gx_device_memory mem_true24_color_device =
340 mem_device("image(24)", 24, mem_true24_procs);
341
342/* Convert x coordinate to byte offset in scan line. */
343#undef x_to_byte
344#define x_to_byte(x) ((x) * 3)
345
346/* Unpack a color into its bytes. */
347#define declare_unpack_color(r, g, b, color)\
348 byte r = (byte)(color >> 16);\
349 byte g = (byte)((uint)color >> 8);\
350 byte b = (byte)color
351#define put3(ptr, r, g, b)\
352 ptr[0] = r, ptr[1] = g, ptr[2] = b
353
354/* Fill a rectangle with a color. */
355private int
356mem_true24_fill_rectangle(gx_device *dev,
357 int x, int y, int w, int h, gx_color_index color)
358{ declare_unpack_color(r, g, b, color);
359 declare_scan_ptr(dest);
360 check_rect();
361 setup_rect(dest);
362 while ( h-- > 0 )
363 { register int cnt = w;
364 register byte *pptr = dest;
365 do { put3(pptr, r, g, b); pptr += 3; } while ( --cnt > 0 );
366 inc_chunk_ptr(dest, draster);
367 }
368 return 0;
369}
370
371/* Copy a monochrome bitmap. */
372private int
373mem_true24_copy_mono(gx_device *dev,
374 byte *base, int sourcex, int sraster, gx_bitmap_id id,
375 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
376{ byte *line;
377 int first_bit;
378 declare_unpack_color(r0, g0, b0, zero);
379 declare_unpack_color(r1, g1, b1, one);
380 declare_scan_ptr(dest);
381 check_rect();
382 setup_rect(dest);
383 line = base + (sourcex >> 3);
384 first_bit = 0x80 >> (sourcex & 7);
385 while ( h-- > 0 )
386 { register byte *pptr = dest;
387 byte *sptr = line;
388 register int sbyte = *sptr++;
389 register int bit = first_bit;
390 int count = w;
391 do
392 { if ( sbyte & bit )
393 { if ( one != gx_no_color_index )
394 put3(pptr, r1, g1, b1);
395 }
396 else
397 { if ( zero != gx_no_color_index )
398 put3(pptr, r0, g0, b0);
399 }
400 pptr += 3;
401 if ( (bit >>= 1) == 0 )
402 bit = 0x80, sbyte = *sptr++;
403 }
404 while ( --count > 0 );
405 line += sraster;
406 inc_chunk_ptr(dest, draster);
407 }
408 return 0;
409}
410
411/* Copy a color bitmap. */
412private int
413mem_true24_copy_color(gx_device *dev,
414 byte *base, int sourcex, int sraster, gx_bitmap_id id,
415 int x, int y, int w, int h)
416{ check_rect();
417 return copy_byte_rect(mdev, base + x_to_byte(sourcex), sraster,
418 x_to_byte(x), y, x_to_byte(w), h);
419}
420
421/* ------ 32-bit color ------ */
422
423/* Procedures */
424declare_mem_procs(mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle);
425
426/* The device descriptor. */
427private gx_device_procs mem_true32_procs =
428 mem_true_procs(mem_true32_copy_mono, mem_true32_copy_color,
429 mem_true32_fill_rectangle);
430gx_device_memory mem_true32_color_device =
431 mem_device("image(32)", 32, mem_true32_procs);
432
433/* Convert x coordinate to byte offset in scan line. */
434#undef x_to_byte
435#define x_to_byte(x) ((x) << 2)
436
437/* Swap the bytes of a color if needed. */
438#if arch_is_big_endian
439# define arrange_bytes(color) (color)
440#else
441# define arrange_bytes(color)\
442 (((color) >> 24) + (((color) >> 16) & 0xff00) +\
443 (((color) & 0xff00) << 8) + ((color) << 24))
444#endif
445
446/* Fill a rectangle with a color. */
447private int
448mem_true32_fill_rectangle(gx_device *dev,
449 int x, int y, int w, int h, gx_color_index color)
450{ gx_color_index a_color = arrange_bytes(color);
451 declare_scan_ptr(dest);
452 check_rect();
453 setup_rect(dest);
454 while ( h-- > 0 )
455 { gx_color_index *pptr = (gx_color_index *)dest;
456 int cnt = w;
457 do { *pptr++ = a_color; } while ( --cnt > 0 );
458 inc_chunk_ptr(dest, draster);
459 }
460 return 0;
461}
462
463/* Copy a monochrome bitmap. */
464private int
465mem_true32_copy_mono(gx_device *dev,
466 byte *base, int sourcex, int sraster, gx_bitmap_id id,
467 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
468{ gx_color_index a_zero = arrange_bytes(zero);
469 gx_color_index a_one = arrange_bytes(one);
470 byte *line;
471 int first_bit;
472 declare_scan_ptr(dest);
473 check_rect();
474 setup_rect(dest);
475 line = base + (sourcex >> 3);
476 first_bit = 0x80 >> (sourcex & 7);
477 while ( h-- > 0 )
478 { register gx_color_index *pptr = (gx_color_index *)dest;
479 byte *sptr = line;
480 register int sbyte = *sptr++;
481 register int bit = first_bit;
482 int count = w;
483 do
484 { if ( sbyte & bit )
485 { if ( one != gx_no_color_index )
486 *pptr = a_one;
487 }
488 else
489 { if ( zero != gx_no_color_index )
490 *pptr = a_zero;
491 }
492 if ( (bit >>= 1) == 0 )
493 bit = 0x80, sbyte = *sptr++;
494 pptr++;
495 }
496 while ( --count > 0 );
497 line += sraster;
498 inc_chunk_ptr(dest, draster);
499 }
500 return 0;
501}
502
503/* Copy a color bitmap. */
504private int
505mem_true32_copy_color(gx_device *dev,
506 byte *base, int sourcex, int sraster, gx_bitmap_id id,
507 int x, int y, int w, int h)
508{ check_rect();
509 return copy_byte_rect(mdev, base + x_to_byte(sourcex), sraster,
510 x_to_byte(x), y, x_to_byte(w), h);
511}