xref: /plan9-contrib/sys/src/cmd/gs/src/gdevm2.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gdevm2.c,v 1.5 2002/11/05 01:03:14 dan Exp $ */
187dd7cddfSDavid du Colombier /* 2-bit-per-pixel "memory" (stored bitmap) device */
197dd7cddfSDavid du Colombier #include "memory_.h"
207dd7cddfSDavid du Colombier #include "gx.h"
217dd7cddfSDavid du Colombier #include "gxdevice.h"
227dd7cddfSDavid du Colombier #include "gxdevmem.h"		/* semi-public definitions */
237dd7cddfSDavid du Colombier #include "gdevmem.h"		/* private definitions */
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier /* ================ Standard (byte-oriented) device ================ */
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier #undef chunk
287dd7cddfSDavid du Colombier #define chunk byte
297dd7cddfSDavid du Colombier #define fpat(byt) mono_fill_make_pattern(byt)
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier /* Procedures */
327dd7cddfSDavid du Colombier declare_mem_procs(mem_mapped2_copy_mono, mem_mapped2_copy_color, mem_mapped2_fill_rectangle);
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier /* The device descriptor. */
357dd7cddfSDavid du Colombier const gx_device_memory mem_mapped2_device =
367dd7cddfSDavid du Colombier mem_device("image2", 2, 0,
377dd7cddfSDavid du Colombier 	   mem_mapped_map_rgb_color, mem_mapped_map_color_rgb,
387dd7cddfSDavid du Colombier 	   mem_mapped2_copy_mono, mem_mapped2_copy_color,
397dd7cddfSDavid du Colombier 	   mem_mapped2_fill_rectangle, mem_gray_strip_copy_rop);
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier /* Convert x coordinate to byte offset in scan line. */
427dd7cddfSDavid du Colombier #undef x_to_byte
437dd7cddfSDavid du Colombier #define x_to_byte(x) ((x) >> 2)
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier /* Define the 2-bit fill patterns. */
467dd7cddfSDavid du Colombier static const mono_fill_chunk tile_patterns[4] = {
477dd7cddfSDavid du Colombier     fpat(0x00), fpat(0x55), fpat(0xaa), fpat(0xff)
487dd7cddfSDavid du Colombier };
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier /* Fill a rectangle with a color. */
517dd7cddfSDavid du Colombier private int
mem_mapped2_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)527dd7cddfSDavid du Colombier mem_mapped2_fill_rectangle(gx_device * dev,
537dd7cddfSDavid du Colombier 			   int x, int y, int w, int h, gx_color_index color)
547dd7cddfSDavid du Colombier {
557dd7cddfSDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
567dd7cddfSDavid du Colombier 
577dd7cddfSDavid du Colombier     fit_fill(dev, x, y, w, h);
587dd7cddfSDavid du Colombier     bits_fill_rectangle(scan_line_base(mdev, y), x << 1, mdev->raster,
597dd7cddfSDavid du Colombier 			tile_patterns[color], w << 1, h);
607dd7cddfSDavid du Colombier     return 0;
617dd7cddfSDavid du Colombier }
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier /* Copy a bitmap. */
647dd7cddfSDavid du Colombier private int
mem_mapped2_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)657dd7cddfSDavid du Colombier mem_mapped2_copy_mono(gx_device * dev,
667dd7cddfSDavid du Colombier 		      const byte * base, int sourcex, int sraster,
677dd7cddfSDavid du Colombier 		      gx_bitmap_id id, int x, int y, int w, int h,
687dd7cddfSDavid du Colombier 		      gx_color_index zero, gx_color_index one)
697dd7cddfSDavid du Colombier {
707dd7cddfSDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
717dd7cddfSDavid du Colombier     const byte *line;
727dd7cddfSDavid du Colombier     int first_bit;
737dd7cddfSDavid du Colombier     byte first_mask, b0, b1, bxor, left_mask, right_mask;
747dd7cddfSDavid du Colombier     static const byte btab[4] = {0, 0x55, 0xaa, 0xff};
757dd7cddfSDavid du Colombier     static const byte bmask[4] = {0xc0, 0x30, 0xc, 3};
767dd7cddfSDavid du Colombier     static const byte lmask[4] = {0, 0xc0, 0xf0, 0xfc};
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier     declare_scan_ptr(dest);
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
817dd7cddfSDavid du Colombier     setup_rect(dest);
827dd7cddfSDavid du Colombier     line = base + (sourcex >> 3);
837dd7cddfSDavid du Colombier     first_bit = 0x80 >> (sourcex & 7);
847dd7cddfSDavid du Colombier     first_mask = bmask[x & 3];
857dd7cddfSDavid du Colombier     left_mask = lmask[x & 3];
867dd7cddfSDavid du Colombier     right_mask = ~lmask[(x + w) & 3];
877dd7cddfSDavid du Colombier     if ((x & 3) + w <= 3)
887dd7cddfSDavid du Colombier 	left_mask = right_mask = left_mask | right_mask;
897dd7cddfSDavid du Colombier     b0 = btab[zero & 3];
907dd7cddfSDavid du Colombier     b1 = btab[one & 3];
917dd7cddfSDavid du Colombier     bxor = b0 ^ b1;
927dd7cddfSDavid du Colombier     while (h-- > 0) {
937dd7cddfSDavid du Colombier 	register byte *pptr = (byte *) dest;
947dd7cddfSDavid du Colombier 	const byte *sptr = line;
957dd7cddfSDavid du Colombier 	register int sbyte = *sptr++;
967dd7cddfSDavid du Colombier 	register int bit = first_bit;
977dd7cddfSDavid du Colombier 	register byte mask = first_mask;
987dd7cddfSDavid du Colombier 	int count = w;
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier 	/* We have 4 cases, of which only 2 really matter. */
1017dd7cddfSDavid du Colombier 	if (one != gx_no_color_index) {
1027dd7cddfSDavid du Colombier 	    if (zero != gx_no_color_index) {	/* Copying an opaque bitmap. */
1037dd7cddfSDavid du Colombier 		byte data = (*pptr & left_mask) | (b0 & ~left_mask);
1047dd7cddfSDavid du Colombier 
1057dd7cddfSDavid du Colombier 		for ( ; ; ) {
1067dd7cddfSDavid du Colombier 		    if (sbyte & bit)
1077dd7cddfSDavid du Colombier 			data ^= bxor & mask;
1087dd7cddfSDavid du Colombier 		    if ((bit >>= 1) == 0)
1097dd7cddfSDavid du Colombier 			bit = 0x80, sbyte = *sptr++;
1107dd7cddfSDavid du Colombier 		    if ((mask >>= 2) == 0)
1117dd7cddfSDavid du Colombier 			mask = 0xc0, *pptr++ = data, data = b0;
112*593dc095SDavid du Colombier 		    if (--count <= 0)
113*593dc095SDavid du Colombier 			break;
1147dd7cddfSDavid du Colombier 		}
1157dd7cddfSDavid du Colombier 		if (mask != 0xc0)
1167dd7cddfSDavid du Colombier 		    *pptr =
1177dd7cddfSDavid du Colombier 			(*pptr & right_mask) | (data & ~right_mask);
1187dd7cddfSDavid du Colombier 	    } else {		/* Filling a mask. */
1197dd7cddfSDavid du Colombier 		for ( ; ; ) {
1207dd7cddfSDavid du Colombier 		    if (sbyte & bit)
1217dd7cddfSDavid du Colombier 			*pptr = (*pptr & ~mask) + (b1 & mask);
1227dd7cddfSDavid du Colombier 		    if (--count <= 0)
1237dd7cddfSDavid du Colombier 			break;
1247dd7cddfSDavid du Colombier 		    if ((bit >>= 1) == 0)
1257dd7cddfSDavid du Colombier 			bit = 0x80, sbyte = *sptr++;
1267dd7cddfSDavid du Colombier 		    if ((mask >>= 2) == 0)
1277dd7cddfSDavid du Colombier 			mask = 0xc0, pptr++;
1287dd7cddfSDavid du Colombier 		}
1297dd7cddfSDavid du Colombier 	    }
1307dd7cddfSDavid du Colombier 	} else {		/* Some other case. */
1317dd7cddfSDavid du Colombier 	    for ( ; ; ) {
1327dd7cddfSDavid du Colombier 		if (!(sbyte & bit)) {
1337dd7cddfSDavid du Colombier 		    if (zero != gx_no_color_index)
1347dd7cddfSDavid du Colombier 			*pptr = (*pptr & ~mask) + (b0 & mask);
1357dd7cddfSDavid du Colombier 		}
1367dd7cddfSDavid du Colombier 		if (--count <= 0)
1377dd7cddfSDavid du Colombier 		    break;
1387dd7cddfSDavid du Colombier 		if ((bit >>= 1) == 0)
1397dd7cddfSDavid du Colombier 		    bit = 0x80, sbyte = *sptr++;
1407dd7cddfSDavid du Colombier 		if ((mask >>= 2) == 0)
1417dd7cddfSDavid du Colombier 		    mask = 0xc0, pptr++;
1427dd7cddfSDavid du Colombier 	    }
1437dd7cddfSDavid du Colombier 	}
1447dd7cddfSDavid du Colombier 	line += sraster;
1457dd7cddfSDavid du Colombier 	inc_ptr(dest, draster);
1467dd7cddfSDavid du Colombier     }
1477dd7cddfSDavid du Colombier     return 0;
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier /* Copy a color bitmap. */
1517dd7cddfSDavid du Colombier private int
mem_mapped2_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)1527dd7cddfSDavid du Colombier mem_mapped2_copy_color(gx_device * dev,
1537dd7cddfSDavid du Colombier 		       const byte * base, int sourcex, int sraster,
1547dd7cddfSDavid du Colombier 		       gx_bitmap_id id, int x, int y, int w, int h)
1557dd7cddfSDavid du Colombier {
1567dd7cddfSDavid du Colombier     int code;
1577dd7cddfSDavid du Colombier 
1587dd7cddfSDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
1597dd7cddfSDavid du Colombier     /* Use monobit copy_mono. */
1607dd7cddfSDavid du Colombier     /* Patch the width in the device temporarily. */
1617dd7cddfSDavid du Colombier     dev->width <<= 1;
1627dd7cddfSDavid du Colombier     code = (*dev_proc(&mem_mono_device, copy_mono))
1637dd7cddfSDavid du Colombier 	(dev, base, sourcex << 1, sraster, id,
1647dd7cddfSDavid du Colombier 	 x << 1, y, w << 1, h, (gx_color_index) 0, (gx_color_index) 1);
1657dd7cddfSDavid du Colombier     /* Restore the correct width. */
1667dd7cddfSDavid du Colombier     dev->width >>= 1;
1677dd7cddfSDavid du Colombier     return code;
1687dd7cddfSDavid du Colombier }
1697dd7cddfSDavid du Colombier 
1707dd7cddfSDavid du Colombier /* ================ "Word"-oriented device ================ */
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier /* Note that on a big-endian machine, this is the same as the */
1737dd7cddfSDavid du Colombier /* standard byte-oriented-device. */
1747dd7cddfSDavid du Colombier 
1757dd7cddfSDavid du Colombier #if !arch_is_big_endian
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier /* Procedures */
1787dd7cddfSDavid du Colombier declare_mem_procs(mem2_word_copy_mono, mem2_word_copy_color, mem2_word_fill_rectangle);
1797dd7cddfSDavid du Colombier 
1807dd7cddfSDavid du Colombier /* Here is the device descriptor. */
1817dd7cddfSDavid du Colombier const gx_device_memory mem_mapped2_word_device =
1827dd7cddfSDavid du Colombier mem_full_device("image2w", 2, 0, mem_open,
1837dd7cddfSDavid du Colombier 		mem_mapped_map_rgb_color, mem_mapped_map_color_rgb,
1847dd7cddfSDavid du Colombier 		mem2_word_copy_mono, mem2_word_copy_color,
1857dd7cddfSDavid du Colombier 		mem2_word_fill_rectangle, gx_default_map_cmyk_color,
1867dd7cddfSDavid du Colombier 		gx_default_strip_tile_rectangle, gx_no_strip_copy_rop,
1877dd7cddfSDavid du Colombier 		mem_word_get_bits_rectangle);
1887dd7cddfSDavid du Colombier 
1897dd7cddfSDavid du Colombier /* Fill a rectangle with a color. */
1907dd7cddfSDavid du Colombier private int
mem2_word_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)1917dd7cddfSDavid du Colombier mem2_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
1927dd7cddfSDavid du Colombier 			 gx_color_index color)
1937dd7cddfSDavid du Colombier {
1947dd7cddfSDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
1957dd7cddfSDavid du Colombier     byte *base;
1967dd7cddfSDavid du Colombier     uint raster;
1977dd7cddfSDavid du Colombier 
1987dd7cddfSDavid du Colombier     fit_fill(dev, x, y, w, h);
1997dd7cddfSDavid du Colombier     base = scan_line_base(mdev, y);
2007dd7cddfSDavid du Colombier     raster = mdev->raster;
2017dd7cddfSDavid du Colombier     mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true);
2027dd7cddfSDavid du Colombier     bits_fill_rectangle(base, x << 1, raster,
2037dd7cddfSDavid du Colombier 			tile_patterns[color], w << 1, h);
2047dd7cddfSDavid du Colombier     mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true);
2057dd7cddfSDavid du Colombier     return 0;
2067dd7cddfSDavid du Colombier }
2077dd7cddfSDavid du Colombier 
2087dd7cddfSDavid du Colombier /* Copy a bitmap. */
2097dd7cddfSDavid du Colombier private int
mem2_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)2107dd7cddfSDavid du Colombier mem2_word_copy_mono(gx_device * dev,
2117dd7cddfSDavid du Colombier 		    const byte * base, int sourcex, int sraster,
2127dd7cddfSDavid du Colombier 		    gx_bitmap_id id, int x, int y, int w, int h,
2137dd7cddfSDavid du Colombier 		    gx_color_index zero, gx_color_index one)
2147dd7cddfSDavid du Colombier {
2157dd7cddfSDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
2167dd7cddfSDavid du Colombier     byte *row;
2177dd7cddfSDavid du Colombier     uint raster;
2187dd7cddfSDavid du Colombier     bool store;
2197dd7cddfSDavid du Colombier 
2207dd7cddfSDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
2217dd7cddfSDavid du Colombier     row = scan_line_base(mdev, y);
2227dd7cddfSDavid du Colombier     raster = mdev->raster;
2237dd7cddfSDavid du Colombier     store = (zero != gx_no_color_index && one != gx_no_color_index);
2247dd7cddfSDavid du Colombier     mem_swap_byte_rect(row, raster, x << 1, w << 1, h, store);
2257dd7cddfSDavid du Colombier     mem_mapped2_copy_mono(dev, base, sourcex, sraster, id,
2267dd7cddfSDavid du Colombier 			  x, y, w, h, zero, one);
2277dd7cddfSDavid du Colombier     mem_swap_byte_rect(row, raster, x << 1, w << 1, h, false);
2287dd7cddfSDavid du Colombier     return 0;
2297dd7cddfSDavid du Colombier }
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier /* Copy a color bitmap. */
2327dd7cddfSDavid du Colombier private int
mem2_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)2337dd7cddfSDavid du Colombier mem2_word_copy_color(gx_device * dev,
2347dd7cddfSDavid du Colombier 		     const byte * base, int sourcex, int sraster,
2357dd7cddfSDavid du Colombier 		     gx_bitmap_id id, int x, int y, int w, int h)
2367dd7cddfSDavid du Colombier {
2377dd7cddfSDavid du Colombier     int code;
2387dd7cddfSDavid du Colombier 
2397dd7cddfSDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
2407dd7cddfSDavid du Colombier     /* Use monobit copy_mono. */
2417dd7cddfSDavid du Colombier     /* Patch the width in the device temporarily. */
2427dd7cddfSDavid du Colombier     dev->width <<= 1;
2437dd7cddfSDavid du Colombier     code = (*dev_proc(&mem_mono_word_device, copy_mono))
2447dd7cddfSDavid du Colombier 	(dev, base, sourcex << 1, sraster, id,
2457dd7cddfSDavid du Colombier 	 x << 1, y, w << 1, h, (gx_color_index) 0, (gx_color_index) 1);
2467dd7cddfSDavid du Colombier     /* Restore the correct width. */
2477dd7cddfSDavid du Colombier     dev->width >>= 1;
2487dd7cddfSDavid du Colombier     return code;
2497dd7cddfSDavid du Colombier }
2507dd7cddfSDavid du Colombier 
2517dd7cddfSDavid du Colombier #endif /* !arch_is_big_endian */
252