summaryrefslogtreecommitdiff
path: root/gs/base/gdevm64.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/base/gdevm64.c')
-rw-r--r--gs/base/gdevm64.c411
1 files changed, 411 insertions, 0 deletions
diff --git a/gs/base/gdevm64.c b/gs/base/gdevm64.c
new file mode 100644
index 000000000..2185fa0e2
--- /dev/null
+++ b/gs/base/gdevm64.c
@@ -0,0 +1,411 @@
+/* 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$ */
+/* 64-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 */
+
+/* Define debugging statistics. */
+#ifdef DEBUG
+struct stats_mem64_s {
+ long
+ fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
+ fprevc[257];
+ double ftotal;
+} stats_mem64;
+static int prev_count = 0;
+static gx_color_index prev_colors[256];
+# define INCR(v) (++(stats_mem64.v))
+#else
+# define INCR(v) DO_NOTHING
+#endif
+
+
+/* ================ Standard (byte-oriented) device ================ */
+
+#undef chunk
+#define chunk byte
+#define PIXEL_SIZE 2
+
+/* Procedures */
+declare_mem_procs(mem_true64_copy_mono, mem_true64_copy_color, mem_true64_fill_rectangle);
+
+/* The device descriptor. */
+const gx_device_memory mem_true64_device =
+mem_full_alpha_device("image64", 64, 0, mem_open,
+ gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
+ mem_true64_copy_mono, mem_true64_copy_color, mem_true64_fill_rectangle,
+ gx_default_map_cmyk_color, gx_default_copy_alpha,
+ gx_default_strip_tile_rectangle, mem_default_strip_copy_rop,
+ mem_get_bits_rectangle);
+
+/* Convert x coordinate to byte offset in scan line. */
+#undef x_to_byte
+#define x_to_byte(x) ((x) << 3)
+
+/* Put a 64-bit color into the bitmap. */
+#define put8(ptr, abcd, efgh)\
+ (ptr)[0] = abcd, (ptr)[1] = efgh
+/* Free variables: [m]dev, abcd, degh. */
+#if arch_is_big_endian
+/* Unpack a color into 32 bit chunks. */
+# define declare_unpack_color(abcd, efgh, color)\
+ bits32 abcd = (bits32)((color) >> 32);\
+ bits32 efgh = (bits32)(color)
+#else
+/* Unpack a color into 32 bit chunks. */
+# define declare_unpack_color(abcd, efgh, color)\
+ bits32 abcd = (bits32)((0x000000ff & ((color) >> 56)) |\
+ (0x0000ff00 & ((color) >> 40)) |\
+ (0x00ff0000 & ((color) >> 24)) |\
+ (0xff000000 & ((color) >> 8)));\
+ bits32 efgh = (bits32)((0x000000ff & ((color) >> 24)) |\
+ (0x0000ff00 & ((color) >> 8)) |\
+ (0x00ff0000 & ((color) << 8)) |\
+ (0xff000000 & ((color) << 24)))
+#endif
+#define dest32 ((bits32 *)dest)
+
+/* Fill a rectangle with a color. */
+static int
+mem_true64_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;
+ declare_scan_ptr(dest);
+ declare_unpack_color(abcd, efgh, color);
+
+ /*
+ * In order to avoid testing w > 0 and h > 0 twice, we defer
+ * executing setup_rect, and use fit_fill_xywh instead of
+ * fit_fill.
+ */
+ fit_fill_xywh(dev, x, y, w, h);
+ INCR(fill);
+#ifdef DEBUG
+ stats_mem64.ftotal += w;
+#endif
+ if (h <= 0)
+ return 0;
+ if (w >= 5) {
+ INCR(fwide);
+ setup_rect(dest);
+#ifdef DEBUG
+ {
+ int ci;
+ for (ci = 0; ci < prev_count; ++ci)
+ if (prev_colors[ci] == color)
+ break;
+ INCR(fprevc[ci]);
+ if (ci == prev_count) {
+ if (ci < countof(prev_colors))
+ ++prev_count;
+ else
+ --ci;
+ }
+ if (ci) {
+ memmove(&prev_colors[1], &prev_colors[0],
+ ci * sizeof(prev_colors[0]));
+ prev_colors[0] = color;
+ }
+ }
+#endif
+ INCR(fcolor[min(w, 100)]);
+ while (h-- > 0) {
+ register bits32 *pptr = dest32;
+ int w1 = w;
+
+ while (w1 >= 4) {
+ put8(pptr, abcd, efgh);
+ put8(pptr + 2, abcd, efgh);
+ put8(pptr + 4, abcd, efgh);
+ put8(pptr + 6, abcd, efgh);
+ pptr += 4 * PIXEL_SIZE;
+ w1 -= 4;
+ }
+ switch (w1) {
+ case 1:
+ put8(pptr, abcd, efgh);
+ break;
+ case 2:
+ put8(pptr, abcd, efgh);
+ put8(pptr + 2, abcd, efgh);
+ break;
+ case 3:
+ put8(pptr, abcd, efgh);
+ put8(pptr + 2, abcd, efgh);
+ put8(pptr + 4, abcd, efgh);
+ break;
+ case 0:
+ ;
+ }
+ inc_ptr(dest, draster);
+ }
+ } else { /* w < 5 */
+ INCR(fnarrow[max(w, 0)]);
+ setup_rect(dest);
+ switch (w) {
+ case 4:
+ do {
+ put8(dest32, abcd, efgh);
+ put8(dest32 + 2, abcd, efgh);
+ put8(dest32 + 4, abcd, efgh);
+ put8(dest32 + 6, abcd, efgh);
+ inc_ptr(dest, draster);
+ }
+ while (--h);
+ break;
+ case 3:
+ do {
+ put8(dest32, abcd, efgh);
+ put8(dest32 + 2, abcd, efgh);
+ put8(dest32 + 4, abcd, efgh);
+ inc_ptr(dest, draster);
+ }
+ while (--h);
+ break;
+ case 2:
+ do {
+ put8(dest32, abcd, efgh);
+ put8(dest32 + 2, abcd, efgh);
+ inc_ptr(dest, draster);
+ }
+ while (--h);
+ break;
+ case 1:
+ do {
+ put8(dest32, abcd, efgh);
+ inc_ptr(dest, draster);
+ }
+ while (--h);
+ break;
+ case 0:
+ default:
+ ;
+ }
+ }
+ return 0;
+}
+
+/* Copy a monochrome bitmap. */
+static int
+mem_true64_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;
+ const byte *line;
+ int sbit;
+ 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);
+ sbit = sourcex & 7;
+ first_bit = 0x80 >> sbit;
+ if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */
+ /* (never used). */
+ declare_unpack_color(abcd0, efgh0, zero);
+ declare_unpack_color(abcd1, efgh1, one);
+ while (h-- > 0) {
+ register bits32 *pptr = dest32;
+ 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)
+ put8(pptr, abcd1, efgh1);
+ } else
+ put8(pptr, abcd0, efgh0);
+ pptr += PIXEL_SIZE;
+ if ((bit >>= 1) == 0)
+ bit = 0x80, sbyte = *sptr++;
+ }
+ while (--count > 0);
+ line += sraster;
+ inc_ptr(dest, draster);
+ }
+ } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */
+ /* This is used heavily. */
+ declare_unpack_color(abcd1, efgh1, one);
+ int first_mask = first_bit << 1;
+ int first_count, first_skip;
+
+ if (sbit + w > 8)
+ first_mask -= 1,
+ first_count = 8 - sbit;
+ else
+ first_mask -= first_mask >> w,
+ first_count = w;
+ first_skip = first_count * PIXEL_SIZE;
+ while (h-- > 0) {
+ register bits32 *pptr = dest32;
+ const byte *sptr = line;
+ register int sbyte = *sptr++ & first_mask;
+ int count = w - first_count;
+
+ if (sbyte) {
+ register int bit = first_bit;
+
+ do {
+ if (sbyte & bit)
+ put8(pptr, abcd1, efgh1);
+ pptr += PIXEL_SIZE;
+ }
+ while ((bit >>= 1) & first_mask);
+ } else
+ pptr += first_skip;
+ while (count >= 8) {
+ sbyte = *sptr++;
+ if (sbyte & 0xf0) {
+ if (sbyte & 0x80)
+ put8(pptr, abcd1, efgh1);
+ if (sbyte & 0x40)
+ put8(pptr + 2, abcd1, efgh1);
+ if (sbyte & 0x20)
+ put8(pptr + 4, abcd1, efgh1);
+ if (sbyte & 0x10)
+ put8(pptr + 6, abcd1, efgh1);
+ }
+ if (sbyte & 0xf) {
+ if (sbyte & 8)
+ put8(pptr + 8, abcd1, efgh1);
+ if (sbyte & 4)
+ put8(pptr + 10, abcd1, efgh1);
+ if (sbyte & 2)
+ put8(pptr + 12, abcd1, efgh1);
+ if (sbyte & 1)
+ put8(pptr + 14, abcd1, efgh1);
+ }
+ pptr += 8 * PIXEL_SIZE;
+ count -= 8;
+ }
+ if (count > 0) {
+ register int bit = 0x80;
+
+ sbyte = *sptr++;
+ do {
+ if (sbyte & bit)
+ put8(pptr, abcd1, efgh1);
+ pptr += PIXEL_SIZE;
+ bit >>= 1;
+ }
+ while (--count > 0);
+ }
+ line += sraster;
+ inc_ptr(dest, draster);
+ }
+ }
+ return 0;
+}
+
+/* Copy a color bitmap. */
+static int
+mem_true64_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;
+}
+
+/* ================ "Word"-oriented device ================ */
+
+/* Note that on a big-endian machine, this is the same as the */
+/* standard byte-oriented-device. */
+
+#if !arch_is_big_endian
+
+/* Procedures */
+declare_mem_procs(mem64_word_copy_mono, mem64_word_copy_color, mem64_word_fill_rectangle);
+
+/* Here is the device descriptor. */
+const gx_device_memory mem_true64_word_device =
+mem_full_device("image64w", 64, 0, mem_open,
+ gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
+ mem64_word_copy_mono, mem64_word_copy_color, mem64_word_fill_rectangle,
+ gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
+ gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
+
+/* Fill a rectangle with a color. */
+static int
+mem64_word_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;
+ byte *base;
+ uint raster;
+
+ fit_fill(dev, x, y, w, h);
+ base = scan_line_base(mdev, y);
+ raster = mdev->raster;
+ mem_swap_byte_rect(base, raster, x * 64, w * 64, h, true);
+ mem_true64_fill_rectangle(dev, x, y, w, h, color);
+ mem_swap_byte_rect(base, raster, x * 64, w * 64, h, false);
+ return 0;
+}
+
+/* Copy a bitmap. */
+static int
+mem64_word_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;
+ byte *row;
+ uint raster;
+ bool store;
+
+ fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
+ row = scan_line_base(mdev, y);
+ raster = mdev->raster;
+ store = (zero != gx_no_color_index && one != gx_no_color_index);
+ mem_swap_byte_rect(row, raster, x * 64, w * 64, h, store);
+ mem_true64_copy_mono(dev, base, sourcex, sraster, id,
+ x, y, w, h, zero, one);
+ mem_swap_byte_rect(row, raster, x * 64, w * 64, h, false);
+ return 0;
+}
+
+/* Copy a color bitmap. */
+static int
+mem64_word_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;
+ byte *row;
+ uint raster;
+
+ fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
+ row = scan_line_base(mdev, y);
+ raster = mdev->raster;
+ mem_swap_byte_rect(row, raster, x * 64, w * 64, h, true);
+ bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE,
+ sraster, w * PIXEL_SIZE, h);
+ mem_swap_byte_rect(row, raster, x * 64, w * 64, h, false);
+ return 0;
+}
+
+#endif /* !arch_is_big_endian */