xref: /plan9/sys/src/cmd/gs/src/gdevm16.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1994, 1996, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gdevm16.c,v 1.5 2002/08/22 07:12:28 henrys Exp $ */
18 /* 16-bit-per-pixel "memory" (stored bitmap) device */
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gxdevice.h"
22 #include "gxdevmem.h"		/* semi-public definitions */
23 #include "gdevmem.h"		/* private definitions */
24 
25 #undef chunk
26 #define chunk byte
27 
28 /* The 16 bits are divided 5 for red, 6 for green, and 5 for blue. */
29 /* Note that the bits must always be kept in big-endian order. */
30 
31 /* Procedures */
32 declare_mem_map_procs(mem_true16_map_rgb_color, mem_true16_map_color_rgb);
33 declare_mem_procs(mem_true16_copy_mono, mem_true16_copy_color, mem_true16_fill_rectangle);
34 
35 /* The device descriptor. */
36 const gx_device_memory mem_true16_device =
37     mem_device("image16", 16, 0,
38 	       mem_true16_map_rgb_color, mem_true16_map_color_rgb,
39 	       mem_true16_copy_mono, mem_true16_copy_color,
40 	       mem_true16_fill_rectangle, mem_default_strip_copy_rop);
41 
42 /* Map a r-g-b color to a color index. */
43 private gx_color_index
mem_true16_map_rgb_color(gx_device * dev,const gx_color_value cv[])44 mem_true16_map_rgb_color(gx_device * dev, const gx_color_value cv[])
45 {
46     return ((cv[0] >> (gx_color_value_bits - 5)) << 11) +
47 	((cv[1] >> (gx_color_value_bits - 6)) << 5) +
48 	(cv[2] >> (gx_color_value_bits - 5));
49 }
50 
51 /* Map a color index to a r-g-b color. */
52 private int
mem_true16_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])53 mem_true16_map_color_rgb(gx_device * dev, gx_color_index color,
54 			 gx_color_value prgb[3])
55 {
56     ushort value = color >> 11;
57 
58     prgb[0] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4))
59 		      >> (16 - gx_color_value_bits);
60     value = (color >> 5) & 0x3f;
61     prgb[1] = ((value << 10) + (value << 4) + (value >> 2))
62 		      >> (16 - gx_color_value_bits);
63     value = color & 0x1f;
64     prgb[2] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4))
65 		      >> (16 - gx_color_value_bits);
66     return 0;
67 }
68 
69 /* Convert x coordinate to byte offset in scan line. */
70 #undef x_to_byte
71 #define x_to_byte(x) ((x) << 1)
72 
73 /* Fill a rectangle with a color. */
74 private int
mem_true16_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)75 mem_true16_fill_rectangle(gx_device * dev,
76 			  int x, int y, int w, int h, gx_color_index color)
77 {
78     gx_device_memory * const mdev = (gx_device_memory *)dev;
79 #if arch_is_big_endian
80     const ushort color16 = (ushort)color;
81 #else
82     const ushort color16 = (ushort)((color << 8) | (color >> 8));
83 #endif
84     declare_scan_ptr(dest);
85 
86     fit_fill(dev, x, y, w, h);
87     setup_rect(dest);
88     if (w == 1) {
89 	while (h-- > 0) {
90 	    *(ushort *)dest = color16;
91 	    inc_ptr(dest, draster);
92 	}
93     } else if ((color16 >> 8) == (color16 & 0xff)) {
94 	bytes_fill_rectangle(scan_line_base(mdev, y) + (x << 1), draster,
95 			     (byte)color, w << 1, h);
96     } else {
97 	while (h-- > 0) {
98 	    ushort *pptr = (ushort *) dest;
99 	    int cnt = w;
100 
101 	    for (; cnt >= 4; pptr += 4, cnt -= 4)
102 		pptr[3] = pptr[2] = pptr[1] = pptr[0] = color16;
103 	    switch (cnt) {
104 	    case 3: pptr[2] = color16;
105 	    case 2: pptr[1] = color16;
106 	    case 1: pptr[0] = color16;
107 	    case 0: DO_NOTHING;
108 	    }
109 	    inc_ptr(dest, draster);
110 	}
111     }
112     return 0;
113 }
114 
115 /* Copy a monochrome bitmap. */
116 private 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)117 mem_true16_copy_mono(gx_device * dev,
118 		     const byte * base, int sourcex, int sraster,
119 		     gx_bitmap_id id, int x, int y, int w, int h,
120 		     gx_color_index zero, gx_color_index one)
121 {
122     gx_device_memory * const mdev = (gx_device_memory *)dev;
123 #if arch_is_big_endian
124     const ushort zero16 = (ushort)zero;
125     const ushort one16 = (ushort)one;
126 #else
127     ushort zero16 = ((uint) (byte) zero << 8) + ((ushort) zero >> 8);
128     ushort one16 = ((uint) (byte) one << 8) + ((ushort) one >> 8);
129 #endif
130     const byte *line;
131     int first_bit;
132 
133     declare_scan_ptr(dest);
134     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
135     setup_rect(dest);
136     line = base + (sourcex >> 3);
137     first_bit = 0x80 >> (sourcex & 7);
138     while (h-- > 0) {
139 	register ushort *pptr = (ushort *) dest;
140 	const byte *sptr = line;
141 	register int sbyte = *sptr++;
142 	register int bit = first_bit;
143 	int count = w;
144 
145 	do {
146 	    if (sbyte & bit) {
147 		if (one != gx_no_color_index)
148 		    *pptr = one16;
149 	    } else {
150 		if (zero != gx_no_color_index)
151 		    *pptr = zero16;
152 	    }
153 	    if ((bit >>= 1) == 0)
154 		bit = 0x80, sbyte = *sptr++;
155 	    pptr++;
156 	}
157 	while (--count > 0);
158 	line += sraster;
159 	inc_ptr(dest, draster);
160     }
161     return 0;
162 }
163 
164 /* Copy a color bitmap. */
165 private 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)166 mem_true16_copy_color(gx_device * dev,
167 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
168 		      int x, int y, int w, int h)
169 {
170     gx_device_memory * const mdev = (gx_device_memory *)dev;
171 
172     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
173     mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
174     return 0;
175 }
176