summaryrefslogtreecommitdiff
path: root/gs/base/gdevm16.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/base/gdevm16.c')
-rw-r--r--gs/base/gdevm16.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/gs/base/gdevm16.c b/gs/base/gdevm16.c
new file mode 100644
index 000000000..b47bbf51c
--- /dev/null
+++ b/gs/base/gdevm16.c
@@ -0,0 +1,171 @@
+/* Copyright (C) 2001-2006 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+/* $Id$ */
+/* 16-bit-per-pixel "memory" (stored bitmap) device */
+#include "memory_.h"
+#include "gx.h"
+#include "gxdevice.h"
+#include "gxdevmem.h" /* semi-public definitions */
+#include "gdevmem.h" /* private definitions */
+
+#undef chunk
+#define chunk byte
+
+/* The 16 bits are divided 5 for red, 6 for green, and 5 for blue. */
+/* Note that the bits must always be kept in big-endian order. */
+
+/* Procedures */
+declare_mem_map_procs(mem_true16_map_rgb_color, mem_true16_map_color_rgb);
+declare_mem_procs(mem_true16_copy_mono, mem_true16_copy_color, mem_true16_fill_rectangle);
+
+/* The device descriptor. */
+const gx_device_memory mem_true16_device =
+ mem_device("image16", 16, 0,
+ mem_true16_map_rgb_color, mem_true16_map_color_rgb,
+ mem_true16_copy_mono, mem_true16_copy_color,
+ mem_true16_fill_rectangle, mem_default_strip_copy_rop);
+
+/* Map a r-g-b color to a color index. */
+static gx_color_index
+mem_true16_map_rgb_color(gx_device * dev, const gx_color_value cv[])
+{
+ return ((cv[0] >> (gx_color_value_bits - 5)) << 11) +
+ ((cv[1] >> (gx_color_value_bits - 6)) << 5) +
+ (cv[2] >> (gx_color_value_bits - 5));
+}
+
+/* Map a color index to a r-g-b color. */
+static int
+mem_true16_map_color_rgb(gx_device * dev, gx_color_index color,
+ gx_color_value prgb[3])
+{
+ ushort value = color >> 11;
+
+ prgb[0] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4))
+ >> (16 - gx_color_value_bits);
+ value = (color >> 5) & 0x3f;
+ prgb[1] = ((value << 10) + (value << 4) + (value >> 2))
+ >> (16 - gx_color_value_bits);
+ value = color & 0x1f;
+ prgb[2] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4))
+ >> (16 - gx_color_value_bits);
+ return 0;
+}
+
+/* Convert x coordinate to byte offset in scan line. */
+#undef x_to_byte
+#define x_to_byte(x) ((x) << 1)
+
+/* Fill a rectangle with a color. */
+static int
+mem_true16_fill_rectangle(gx_device * dev,
+ int x, int y, int w, int h, gx_color_index color)
+{
+ gx_device_memory * const mdev = (gx_device_memory *)dev;
+#if arch_is_big_endian
+ const ushort color16 = (ushort)color;
+#else
+ const ushort color16 = (ushort)((color << 8) | (color >> 8));
+#endif
+ declare_scan_ptr(dest);
+
+ fit_fill(dev, x, y, w, h);
+ setup_rect(dest);
+ if (w == 1) {
+ while (h-- > 0) {
+ *(ushort *)dest = color16;
+ inc_ptr(dest, draster);
+ }
+ } else if ((color16 >> 8) == (color16 & 0xff)) {
+ bytes_fill_rectangle(scan_line_base(mdev, y) + (x << 1), draster,
+ (byte)color, w << 1, h);
+ } else {
+ while (h-- > 0) {
+ ushort *pptr = (ushort *) dest;
+ int cnt = w;
+
+ for (; cnt >= 4; pptr += 4, cnt -= 4)
+ pptr[3] = pptr[2] = pptr[1] = pptr[0] = color16;
+ switch (cnt) {
+ case 3: pptr[2] = color16;
+ case 2: pptr[1] = color16;
+ case 1: pptr[0] = color16;
+ case 0: DO_NOTHING;
+ }
+ inc_ptr(dest, draster);
+ }
+ }
+ return 0;
+}
+
+/* Copy a monochrome bitmap. */
+static int
+mem_true16_copy_mono(gx_device * dev,
+ const byte * base, int sourcex, int sraster,
+ gx_bitmap_id id, int x, int y, int w, int h,
+ gx_color_index zero, gx_color_index one)
+{
+ gx_device_memory * const mdev = (gx_device_memory *)dev;
+#if arch_is_big_endian
+ const ushort zero16 = (ushort)zero;
+ const ushort one16 = (ushort)one;
+#else
+ ushort zero16 = ((uint) (byte) zero << 8) + ((ushort) zero >> 8);
+ ushort one16 = ((uint) (byte) one << 8) + ((ushort) one >> 8);
+#endif
+ const byte *line;
+ int first_bit;
+
+ declare_scan_ptr(dest);
+ fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
+ setup_rect(dest);
+ line = base + (sourcex >> 3);
+ first_bit = 0x80 >> (sourcex & 7);
+ while (h-- > 0) {
+ register ushort *pptr = (ushort *) dest;
+ const byte *sptr = line;
+ register int sbyte = *sptr++;
+ register int bit = first_bit;
+ int count = w;
+
+ do {
+ if (sbyte & bit) {
+ if (one != gx_no_color_index)
+ *pptr = one16;
+ } else {
+ if (zero != gx_no_color_index)
+ *pptr = zero16;
+ }
+ if ((bit >>= 1) == 0)
+ bit = 0x80, sbyte = *sptr++;
+ pptr++;
+ }
+ while (--count > 0);
+ line += sraster;
+ inc_ptr(dest, draster);
+ }
+ return 0;
+}
+
+/* Copy a color bitmap. */
+static int
+mem_true16_copy_color(gx_device * dev,
+ const byte * base, int sourcex, int sraster, gx_bitmap_id id,
+ int x, int y, int w, int h)
+{
+ gx_device_memory * const mdev = (gx_device_memory *)dev;
+
+ fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
+ mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
+ return 0;
+}