summaryrefslogtreecommitdiff
path: root/gs/src/gdevrrgb.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/src/gdevrrgb.c')
-rw-r--r--gs/src/gdevrrgb.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/gs/src/gdevrrgb.c b/gs/src/gdevrrgb.c
new file mode 100644
index 000000000..7e7d893ec
--- /dev/null
+++ b/gs/src/gdevrrgb.c
@@ -0,0 +1,230 @@
+/* Copyright (C) 1996 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+*/
+
+/* gdevrrgb.c */
+/* RGB device with "render algorithm" */
+#include "gdevprn.h"
+
+/*
+ * This is a 32-bit device in which each pixel holds 24 bits of RGB and 8
+ * (actually 4) bits of "render algorithm". It is not useful in itself, but
+ * it is a good example of (1) how to handle "render algorithm" information
+ * and (2) how to implement a printer device with a non-standard memory
+ * device as its underlying buffer.
+ */
+
+/* Define default device parameters. */
+#ifndef X_DPI
+# define X_DPI 300
+#endif
+#ifndef Y_DPI
+# define Y_DPI 300
+#endif
+
+/* The device descriptor */
+private dev_proc_open_device(rrgb_open);
+private dev_proc_map_rgb_color(rrgb_map_rgb_color);
+private dev_proc_map_color_rgb(rrgb_map_color_rgb);
+private dev_proc_print_page(rrgb_print_page);
+private const gx_device_procs rrgb_procs =
+ prn_color_procs(rrgb_open, gdev_prn_output_page, gdev_prn_close,
+ rrgb_map_rgb_color, rrgb_map_color_rgb);
+
+gx_device_printer far_data gs_rrgb_device =
+{ prn_device_body(gx_device_printer, rrgb_procs, "rrgb",
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
+ X_DPI, Y_DPI,
+ 0,0,0,0, /* margins */
+ 3,32,255,255,256,256, rrgb_print_page)
+};
+
+/* Buffer device implementation */
+private dev_proc_make_buffer_device(rrgb_make_buffer_device);
+private dev_proc_strip_copy_rop(rrgb_strip_copy_rop);
+
+#define ppdev ((gx_device_printer *)pdev)
+
+/* Open the device. We redefine this only so we can reset */
+/* make_buffer_device. */
+private int
+rrgb_open(gx_device *pdev)
+{ ppdev->printer_procs.make_buffer_device = rrgb_make_buffer_device;
+ return gdev_prn_open(pdev);
+}
+
+/* Color mapping */
+private gx_color_index
+rrgb_map_rgb_color(gx_device *dev,
+ gx_color_value r, gx_color_value g, gx_color_value b)
+{ return gx_color_value_to_byte(b) +
+ ((uint)gx_color_value_to_byte(g) << 8) +
+ ((ulong)gx_color_value_to_byte(r) << 16);
+}
+private int
+rrgb_map_color_rgb(gx_device *dev, gx_color_index color,
+ gx_color_value prgb[3])
+{ prgb[0] = gx_color_value_from_byte((color >> 16) & 0xff);
+ prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
+ prgb[2] = gx_color_value_from_byte(color & 0xff);
+ return 0;
+}
+
+/* Print the page. Just copy the bits to the file. */
+private int
+rrgb_print_page(gx_device_printer *pdev, FILE *prn_stream)
+{ /* Just dump the bits on the file. */
+ int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
+ byte *in = (byte *)gs_malloc(line_size, 1, "rrgb_print_page");
+ int lnum;
+
+ if ( in == 0 )
+ return_error(gs_error_VMerror);
+ for ( lnum = 0; lnum < pdev->height; ++lnum )
+ { byte *data;
+ gdev_prn_get_bits(pdev, lnum, in, &data);
+ fwrite(data, 1, line_size, prn_stream);
+ }
+ gs_free((char *)in, line_size, 1, "rrgb_print_page");
+ return 0;
+}
+
+/* Reimplement the buffer device so that it stores the "render algorithm" */
+/* in the top byte of each pixel. */
+private int
+rrgb_make_buffer_device(gx_device_memory *mdev,
+ gx_device *target, gs_memory_t *mem, bool for_band)
+{ int code = gx_default_make_buffer_device(mdev, target, mem, for_band);
+
+ if ( code < 0 )
+ return code;
+ mdev->std_procs.strip_copy_rop = rrgb_strip_copy_rop;
+ return code;
+}
+
+/* Reimplement copy_rop so it saves the "render algorithm". */
+/* This is messy: we have to copy each (partial) scan line from the */
+/* 32-bit representation into a 24-bit buffer, do the operation, */
+/* and then write it back. The code is modeled on the default */
+/* implementation in gdevmrop.c (q.v.). */
+private void
+rrgb_copy_4to3(byte *dest, const byte *src, int width)
+{ const byte *p = src;
+ byte *q = dest;
+ int n;
+
+ for ( n = width; n > 0; p += 4, q += 3, --n )
+ q[0] = p[1], q[1] = p[2], q[2] = p[3];
+}
+private void
+rrgb_copy_3to4(byte *dest, const byte *src, int width, byte upper)
+{ const byte *p = src;
+ byte *q = dest;
+ int n;
+
+ for ( n = width; n > 0; p += 3, q += 4, --n )
+ q[0] = upper, q[1] = p[0], q[2] = p[1], q[3] = p[2];
+}
+int
+rrgb_strip_copy_rop(gx_device *dev,
+ const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
+ const gx_color_index *scolors,
+ const gx_strip_bitmap *textures, const gx_color_index *tcolors,
+ int x, int y, int width, int height,
+ int phase_x, int phase_y, gs_logical_operation_t lop)
+{ gs_rop3_t rop = lop_rop(lop);
+ const gx_device_memory *mdproto = gdev_mem_device_for_bits(24);
+ gs_memory_t *mem = &gs_memory_default;
+ gx_device_memory mdev;
+ bool
+ uses_d = rop3_uses_D(rop),
+ copy_s = rop3_uses_S(rop) && scolors == NULL,
+ copy_t = rop3_uses_T(rop) && tcolors == NULL;
+ byte *srow = 0;
+ byte *trow = 0;
+ const byte *srdata;
+ int sx;
+ gx_strip_bitmap tsubst;
+ const gx_strip_bitmap *tptr;
+ int tx;
+ int code;
+ int py;
+
+ gs_make_mem_device(&mdev, mdproto, 0, -1, dev);
+ mdev.width = width;
+ mdev.height = 1;
+ mdev.bitmap_memory = mem;
+ code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev);
+ if ( code < 0 )
+ return code;
+ if ( copy_s )
+ { srow = gs_alloc_bytes(mem, width * 3, "rrgb source buffer");
+ if ( srow == 0 )
+ { code = gs_note_error(gs_error_VMerror);
+ goto x;
+ }
+ }
+ if ( copy_t )
+ { trow = gs_alloc_bytes(mem, textures->rep_width * 3,
+ "rrgb texture buffer");
+ if ( trow == 0 )
+ { code = gs_note_error(gs_error_VMerror);
+ goto x;
+ }
+ }
+ for ( py = y; py < y + height; ++py )
+ { byte *ddata = scan_line_base((gx_device_memory *)dev, y) + x * 4;
+
+ if ( uses_d )
+ { rrgb_copy_4to3(scan_line_base(&mdev, 0), ddata, width);
+ }
+ if ( copy_s )
+ { rrgb_copy_4to3(srow, sdata + sourcex * 4, width);
+ srdata = srow, sx = 0;
+ }
+ else
+ srdata = sdata + y * sraster, sx = sourcex;
+ if ( copy_t )
+ { tsubst = *textures;
+ rrgb_copy_4to3(trow,
+ tsubst.data + ((py + phase_y) %
+ tsubst.rep_height) * tsubst.raster,
+ textures->rep_width);
+ tsubst.data = trow;
+ tsubst.size.x = tsubst.rep_width;
+ tsubst.size.y = 1;
+ tsubst.id = gx_no_bitmap_id;
+ tsubst.rep_height = 1;
+ tx = py / tsubst.rep_height * tsubst.rep_shift;
+ tptr = &tsubst;
+ }
+ else
+ tptr = textures, tx = 0;
+ code = (*dev_proc(&mdev, strip_copy_rop))((gx_device *)&mdev,
+ srdata, sx, 0 /*unused*/, gx_no_bitmap_id, scolors,
+ tptr, tcolors, 0, 0, width, 1,
+ phase_x + tx, phase_y + py, lop);
+ if ( code < 0 )
+ break;
+ rrgb_copy_3to4(ddata, scan_line_base(&mdev, 0), width,
+ (lop >> lop_ral_shift) & lop_ral_mask);
+ }
+x: gs_free_object(mem, trow, "rrgb texture buffer");
+ gs_free_object(mem, srow, "rrgb source buffer");
+ (*dev_proc(&mdev, close_device))((gx_device *)&mdev);
+ return code;
+}