xref: /plan9/sys/src/cmd/gs/src/gdevm32.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: gdevm32.c,v 1.5 2003/05/24 17:19:58 dan Exp $ */
187dd7cddfSDavid du Colombier /* 32-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 
307dd7cddfSDavid du Colombier /* Procedures */
317dd7cddfSDavid du Colombier declare_mem_procs(mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle);
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier /* The device descriptor. */
347dd7cddfSDavid du Colombier const gx_device_memory mem_true32_device =
357dd7cddfSDavid du Colombier mem_full_device("image32", 24, 8, mem_open,
367dd7cddfSDavid du Colombier 		gx_default_map_rgb_color, gx_default_map_color_rgb,
377dd7cddfSDavid du Colombier      mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle,
387dd7cddfSDavid du Colombier 	    gx_default_cmyk_map_cmyk_color, gx_default_strip_tile_rectangle,
397dd7cddfSDavid du Colombier 		mem_default_strip_copy_rop, mem_get_bits_rectangle);
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 /* Swap the bytes of a color if needed. */
467dd7cddfSDavid du Colombier #define color_swap_bytes(color)\
47*593dc095SDavid du Colombier   ((((color) >> 24) & 0xff) + (((color) >> 8) & 0xff00) +\
487dd7cddfSDavid du Colombier    (((color) & 0xff00) << 8) + ((color) << 24))
497dd7cddfSDavid du Colombier #if arch_is_big_endian
507dd7cddfSDavid du Colombier #  define arrange_bytes(color) (color)
517dd7cddfSDavid du Colombier #else
527dd7cddfSDavid du Colombier #  define arrange_bytes(color) color_swap_bytes(color)
537dd7cddfSDavid du Colombier #endif
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier /* Fill a rectangle with a color. */
567dd7cddfSDavid du Colombier private int
mem_true32_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)577dd7cddfSDavid du Colombier mem_true32_fill_rectangle(gx_device * dev,
587dd7cddfSDavid du Colombier 			  int x, int y, int w, int h, gx_color_index color)
597dd7cddfSDavid du Colombier {
607dd7cddfSDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
617dd7cddfSDavid du Colombier     bits32 a_color;
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier     declare_scan_ptr(dest);
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier     fit_fill(dev, x, y, w, h);
667dd7cddfSDavid du Colombier     a_color = arrange_bytes(color);
677dd7cddfSDavid du Colombier     setup_rect(dest);
687dd7cddfSDavid du Colombier     if (w <= 4)
697dd7cddfSDavid du Colombier 	switch (w) {
707dd7cddfSDavid du Colombier 		/*case 0: *//* not possible */
717dd7cddfSDavid du Colombier #define dest32 ((bits32 *)dest)
727dd7cddfSDavid du Colombier 	    case 1:
737dd7cddfSDavid du Colombier 		do {
747dd7cddfSDavid du Colombier 		    dest32[0] = a_color;
757dd7cddfSDavid du Colombier 		    inc_ptr(dest, draster);
767dd7cddfSDavid du Colombier 		}
777dd7cddfSDavid du Colombier 		while (--h > 0);
787dd7cddfSDavid du Colombier 		break;
797dd7cddfSDavid du Colombier 	    case 2:
807dd7cddfSDavid du Colombier 		do {
817dd7cddfSDavid du Colombier 		    dest32[1] = dest32[0] = a_color;
827dd7cddfSDavid du Colombier 		    inc_ptr(dest, draster);
837dd7cddfSDavid du Colombier 		}
847dd7cddfSDavid du Colombier 		while (--h > 0);
857dd7cddfSDavid du Colombier 		break;
867dd7cddfSDavid du Colombier 	    case 3:
877dd7cddfSDavid du Colombier 		do {
887dd7cddfSDavid du Colombier 		    dest32[2] = dest32[1] = dest32[0] = a_color;
897dd7cddfSDavid du Colombier 		    inc_ptr(dest, draster);
907dd7cddfSDavid du Colombier 		}
917dd7cddfSDavid du Colombier 		while (--h > 0);
927dd7cddfSDavid du Colombier 		break;
937dd7cddfSDavid du Colombier 	    case 4:
947dd7cddfSDavid du Colombier 		do {
957dd7cddfSDavid du Colombier 		    dest32[3] = dest32[2] = dest32[1] = dest32[0] = a_color;
967dd7cddfSDavid du Colombier 		    inc_ptr(dest, draster);
977dd7cddfSDavid du Colombier 		}
987dd7cddfSDavid du Colombier 		while (--h > 0);
997dd7cddfSDavid du Colombier 		break;
1007dd7cddfSDavid du Colombier 	    default:		/* not possible */
1017dd7cddfSDavid du Colombier 		;
1027dd7cddfSDavid du Colombier     } else if (a_color == 0)
1037dd7cddfSDavid du Colombier 	do {
1047dd7cddfSDavid du Colombier 	    memset(dest, 0, w << 2);
1057dd7cddfSDavid du Colombier 	    inc_ptr(dest, draster);
1067dd7cddfSDavid du Colombier 	}
1077dd7cddfSDavid du Colombier 	while (--h > 0);
1087dd7cddfSDavid du Colombier     else
1097dd7cddfSDavid du Colombier 	do {
1107dd7cddfSDavid du Colombier 	    bits32 *pptr = dest32;
1117dd7cddfSDavid du Colombier 	    int cnt = w;
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier 	    do {
1147dd7cddfSDavid du Colombier 		pptr[3] = pptr[2] = pptr[1] = pptr[0] = a_color;
1157dd7cddfSDavid du Colombier 		pptr += 4;
1167dd7cddfSDavid du Colombier 	    }
1177dd7cddfSDavid du Colombier 	    while ((cnt -= 4) > 4);
1187dd7cddfSDavid du Colombier 	    do {
1197dd7cddfSDavid du Colombier 		*pptr++ = a_color;
1207dd7cddfSDavid du Colombier 	    } while (--cnt > 0);
1217dd7cddfSDavid du Colombier 	    inc_ptr(dest, draster);
1227dd7cddfSDavid du Colombier 	}
1237dd7cddfSDavid du Colombier 	while (--h > 0);
1247dd7cddfSDavid du Colombier #undef dest32
1257dd7cddfSDavid du Colombier     return 0;
1267dd7cddfSDavid du Colombier }
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier /* Copy a monochrome bitmap. */
1297dd7cddfSDavid du Colombier private int
mem_true32_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)1307dd7cddfSDavid du Colombier mem_true32_copy_mono(gx_device * dev,
1317dd7cddfSDavid du Colombier 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
1327dd7cddfSDavid du Colombier 	int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
1337dd7cddfSDavid du Colombier {
1347dd7cddfSDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
1357dd7cddfSDavid du Colombier     bits32 a_zero = arrange_bytes(zero);
1367dd7cddfSDavid du Colombier     bits32 a_one = arrange_bytes(one);
1377dd7cddfSDavid du Colombier     const byte *line;
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier     declare_scan_ptr(dest);
1407dd7cddfSDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
1417dd7cddfSDavid du Colombier     setup_rect(dest);
1427dd7cddfSDavid du Colombier     line = base + (sourcex >> 3);
1437dd7cddfSDavid du Colombier     if (zero == gx_no_color_index) {
1447dd7cddfSDavid du Colombier 	int first_bit = sourcex & 7;
1457dd7cddfSDavid du Colombier 	int w_first = min(w, 8 - first_bit);
1467dd7cddfSDavid du Colombier 	int w_rest = w - w_first;
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier 	if (one == gx_no_color_index)
1497dd7cddfSDavid du Colombier 	    return 0;
1507dd7cddfSDavid du Colombier 	/*
1517dd7cddfSDavid du Colombier 	 * There are no halftones, so this case -- characters --
1527dd7cddfSDavid du Colombier 	 * is the only common one.
1537dd7cddfSDavid du Colombier 	 */
1547dd7cddfSDavid du Colombier 	while (h-- > 0) {
1557dd7cddfSDavid du Colombier 	    bits32 *pptr = (bits32 *) dest;
1567dd7cddfSDavid du Colombier 	    const byte *sptr = line;
1577dd7cddfSDavid du Colombier 	    int sbyte = (*sptr++ << first_bit) & 0xff;
1587dd7cddfSDavid du Colombier 	    int count = w_first;
1597dd7cddfSDavid du Colombier 
1607dd7cddfSDavid du Colombier 	    if (sbyte)
1617dd7cddfSDavid du Colombier 		do {
1627dd7cddfSDavid du Colombier 		    if (sbyte & 0x80)
1637dd7cddfSDavid du Colombier 			*pptr = a_one;
1647dd7cddfSDavid du Colombier 		    sbyte <<= 1;
1657dd7cddfSDavid du Colombier 		    pptr++;
1667dd7cddfSDavid du Colombier 		}
1677dd7cddfSDavid du Colombier 		while (--count > 0);
1687dd7cddfSDavid du Colombier 	    else
1697dd7cddfSDavid du Colombier 		pptr += count;
1707dd7cddfSDavid du Colombier 	    for (count = w_rest; count >= 8; count -= 8, pptr += 8) {
1717dd7cddfSDavid du Colombier 		sbyte = *sptr++;
1727dd7cddfSDavid du Colombier 		if (sbyte) {
1737dd7cddfSDavid du Colombier 		    if (sbyte & 0x80) pptr[0] = a_one;
1747dd7cddfSDavid du Colombier 		    if (sbyte & 0x40) pptr[1] = a_one;
1757dd7cddfSDavid du Colombier 		    if (sbyte & 0x20) pptr[2] = a_one;
1767dd7cddfSDavid du Colombier 		    if (sbyte & 0x10) pptr[3] = a_one;
1777dd7cddfSDavid du Colombier 		    if (sbyte & 0x08) pptr[4] = a_one;
1787dd7cddfSDavid du Colombier 		    if (sbyte & 0x04) pptr[5] = a_one;
1797dd7cddfSDavid du Colombier 		    if (sbyte & 0x02) pptr[6] = a_one;
1807dd7cddfSDavid du Colombier 		    if (sbyte & 0x01) pptr[7] = a_one;
1817dd7cddfSDavid du Colombier 		}
1827dd7cddfSDavid du Colombier 	    }
1837dd7cddfSDavid du Colombier 	    if (count) {
1847dd7cddfSDavid du Colombier 		sbyte = *sptr;
1857dd7cddfSDavid du Colombier 		do {
1867dd7cddfSDavid du Colombier 		    if (sbyte & 0x80)
1877dd7cddfSDavid du Colombier 			*pptr = a_one;
1887dd7cddfSDavid du Colombier 		    sbyte <<= 1;
1897dd7cddfSDavid du Colombier 		    pptr++;
1907dd7cddfSDavid du Colombier 		}
1917dd7cddfSDavid du Colombier 		while (--count > 0);
1927dd7cddfSDavid du Colombier 	    }
1937dd7cddfSDavid du Colombier 	    line += sraster;
1947dd7cddfSDavid du Colombier 	    inc_ptr(dest, draster);
1957dd7cddfSDavid du Colombier 	}
1967dd7cddfSDavid du Colombier     } else {			/* zero != gx_no_color_index */
1977dd7cddfSDavid du Colombier 	int first_bit = 0x80 >> (sourcex & 7);
1987dd7cddfSDavid du Colombier 
1997dd7cddfSDavid du Colombier 	while (h-- > 0) {
2007dd7cddfSDavid du Colombier 	    bits32 *pptr = (bits32 *) dest;
2017dd7cddfSDavid du Colombier 	    const byte *sptr = line;
2027dd7cddfSDavid du Colombier 	    int sbyte = *sptr++;
2037dd7cddfSDavid du Colombier 	    int bit = first_bit;
2047dd7cddfSDavid du Colombier 	    int count = w;
2057dd7cddfSDavid du Colombier 
2067dd7cddfSDavid du Colombier 	    do {
2077dd7cddfSDavid du Colombier 		if (sbyte & bit) {
2087dd7cddfSDavid du Colombier 		    if (one != gx_no_color_index)
2097dd7cddfSDavid du Colombier 			*pptr = a_one;
2107dd7cddfSDavid du Colombier 		} else
2117dd7cddfSDavid du Colombier 		    *pptr = a_zero;
2127dd7cddfSDavid du Colombier 		if ((bit >>= 1) == 0)
2137dd7cddfSDavid du Colombier 		    bit = 0x80, sbyte = *sptr++;
2147dd7cddfSDavid du Colombier 		pptr++;
2157dd7cddfSDavid du Colombier 	    }
2167dd7cddfSDavid du Colombier 	    while (--count > 0);
2177dd7cddfSDavid du Colombier 	    line += sraster;
2187dd7cddfSDavid du Colombier 	    inc_ptr(dest, draster);
2197dd7cddfSDavid du Colombier 	}
2207dd7cddfSDavid du Colombier     }
2217dd7cddfSDavid du Colombier     return 0;
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier 
2247dd7cddfSDavid du Colombier /* Copy a color bitmap. */
2257dd7cddfSDavid du Colombier private int
mem_true32_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)2267dd7cddfSDavid du Colombier mem_true32_copy_color(gx_device * dev,
2277dd7cddfSDavid du Colombier 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
2287dd7cddfSDavid du Colombier 		      int x, int y, int w, int h)
2297dd7cddfSDavid du Colombier {
2307dd7cddfSDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
2317dd7cddfSDavid du Colombier 
2327dd7cddfSDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
2337dd7cddfSDavid du Colombier     mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
2347dd7cddfSDavid du Colombier     return 0;
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier /* ================ "Word"-oriented device ================ */
2387dd7cddfSDavid du Colombier 
2397dd7cddfSDavid du Colombier /* Note that on a big-endian machine, this is the same as the */
2407dd7cddfSDavid du Colombier /* standard byte-oriented-device. */
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier #if !arch_is_big_endian
2437dd7cddfSDavid du Colombier 
2447dd7cddfSDavid du Colombier /* Procedures */
2457dd7cddfSDavid du Colombier declare_mem_procs(mem32_word_copy_mono, mem32_word_copy_color, mem32_word_fill_rectangle);
2467dd7cddfSDavid du Colombier 
2477dd7cddfSDavid du Colombier /* Here is the device descriptor. */
2487dd7cddfSDavid du Colombier const gx_device_memory mem_true32_word_device =
2497dd7cddfSDavid du Colombier mem_full_device("image32w", 24, 8, mem_open,
2507dd7cddfSDavid du Colombier 		gx_default_map_rgb_color, gx_default_map_color_rgb,
2517dd7cddfSDavid du Colombier      mem32_word_copy_mono, mem32_word_copy_color, mem32_word_fill_rectangle,
2527dd7cddfSDavid du Colombier 	    gx_default_cmyk_map_cmyk_color, gx_default_strip_tile_rectangle,
2537dd7cddfSDavid du Colombier 		gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
2547dd7cddfSDavid du Colombier 
2557dd7cddfSDavid du Colombier /* Fill a rectangle with a color. */
2567dd7cddfSDavid du Colombier private int
mem32_word_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)2577dd7cddfSDavid du Colombier mem32_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
2587dd7cddfSDavid du Colombier 			  gx_color_index color)
2597dd7cddfSDavid du Colombier {
2607dd7cddfSDavid du Colombier     return mem_true32_fill_rectangle(dev, x, y, w, h,
2617dd7cddfSDavid du Colombier 				     color_swap_bytes(color));
2627dd7cddfSDavid du Colombier }
2637dd7cddfSDavid du Colombier 
2647dd7cddfSDavid du Colombier /* Copy a bitmap. */
2657dd7cddfSDavid du Colombier private int
mem32_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)2667dd7cddfSDavid du Colombier mem32_word_copy_mono(gx_device * dev,
2677dd7cddfSDavid du Colombier 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
2687dd7cddfSDavid du Colombier 	int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
2697dd7cddfSDavid du Colombier {
2707dd7cddfSDavid du Colombier     return mem_true32_copy_mono(dev, base, sourcex, sraster, id,
2717dd7cddfSDavid du Colombier 				x, y, w, h, color_swap_bytes(zero),
2727dd7cddfSDavid du Colombier 				color_swap_bytes(one));
2737dd7cddfSDavid du Colombier }
2747dd7cddfSDavid du Colombier 
2757dd7cddfSDavid du Colombier /* Copy a color bitmap. */
2767dd7cddfSDavid du Colombier private int
mem32_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)2777dd7cddfSDavid du Colombier mem32_word_copy_color(gx_device * dev,
2787dd7cddfSDavid du Colombier 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
2797dd7cddfSDavid du Colombier 		      int x, int y, int w, int h)
2807dd7cddfSDavid du Colombier {
2817dd7cddfSDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
2827dd7cddfSDavid du Colombier     byte *row;
2837dd7cddfSDavid du Colombier     uint raster;
2847dd7cddfSDavid du Colombier 
2857dd7cddfSDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
2867dd7cddfSDavid du Colombier     row = scan_line_base(mdev, y);
2877dd7cddfSDavid du Colombier     raster = mdev->raster;
2887dd7cddfSDavid du Colombier     bytes_copy_rectangle(row + (x << 2), raster, base + (sourcex << 2),
2897dd7cddfSDavid du Colombier 			 sraster, w << 2, h);
2907dd7cddfSDavid du Colombier     mem_swap_byte_rect(row, raster, x << 5, w << 5, h, false);
2917dd7cddfSDavid du Colombier     return 0;
2927dd7cddfSDavid du Colombier }
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier #endif /* !arch_is_big_endian */
295