1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 /* Support routines for PC color mapping */
17 #include "gx.h"
18 #include "gsmatrix.h"		/* for gxdevice.h */
19 #include "gxdevice.h"
20 #include "gdevpccm.h"		/* interface */
21 
22 /* Color mapping routines for EGA/VGA-style color. */
23 
24 /* ------ EGA/VGA (4-bit) color mapping ------ */
25 
26 /*
27  * Colors are 4 bits: 8=intensity (always set except black), 4=R, 2=G, 1=B.
28  * Note: We only use eight colors.  The halftoning logic requires that we
29  * have the same number for shades for each component.
30  */
31 gx_color_index
pc_4bit_map_rgb_color(gx_device * dev,const gx_color_value cv[])32 pc_4bit_map_rgb_color(gx_device * dev, const gx_color_value cv[])
33 {
34     gx_color_index r, g, color;
35 
36     r = (cv[0] > (gx_max_color_value/2));
37     g = (cv[1] > (gx_max_color_value/2));
38     color = (cv[2] > (gx_max_color_value/2));
39     color += (r << 2) + (g << 1);
40     if (color > 0)		/* If the color is not black */
41         color += 8;		/* Turn on intensity bit */
42     return color;
43 }
44 
45 int
pc_4bit_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])46 pc_4bit_map_color_rgb(gx_device * dev, gx_color_index color,
47                       gx_color_value prgb[3])
48 {
49 #define icolor (int)color
50     prgb[0] = (icolor & 4 ? gx_max_color_value : 0);
51     prgb[1] = (icolor & 2 ? gx_max_color_value : 0);
52     prgb[2] = (icolor & 1 ? gx_max_color_value : 0);
53     return 0;
54 #undef icolor
55 }
56 
57 /* ------ SVGA 8-bit color mapping ------ */
58 /*
59  * For 8-bit color, we use a 6x6x6 "cube".  This only provides 216
60  * different colors.  The halftoning logic assumes that we have the same
61  * number of shades of each color.  Thus asymetric cubes like 8x8x4 or
62  * 7x7x5 do not work properly.
63  */
64 
65 gx_color_index
pc_8bit_map_rgb_color(gx_device * dev,const gx_color_value cv[])66 pc_8bit_map_rgb_color(gx_device * dev, const gx_color_value cv[])
67 {
68     gx_color_value r, g, b;
69     uint rv, gv;
70     r = cv[0]; g = cv[1]; b = cv[2];
71     rv = r / (gx_max_color_value / 6 + 1);
72     gv = g / (gx_max_color_value / 6 + 1);
73 
74     return (gx_color_index)
75          (rv * 6 + gv) * 6 + b / (gx_max_color_value / 6 + 1);
76 }
77 int
pc_8bit_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])78 pc_8bit_map_color_rgb(gx_device * dev, gx_color_index color,
79                       gx_color_value prgb[3])
80 {
81     static const gx_color_value ramp6[6] =
82     {0,
83      gx_max_color_value / 5,
84      2 * gx_max_color_value / 5,
85      3 * gx_max_color_value / 5,
86      gx_max_color_value - (gx_max_color_value / 5),
87      gx_max_color_value
88     };
89 
90 #define icolor (uint)color
91     if (icolor >= 216) {
92         prgb[0] = prgb[1] = prgb[2] = 0;
93     } else {
94         prgb[0] = ramp6[icolor / 36];
95         prgb[1] = ramp6[(icolor / 6) % 6];
96         prgb[2] = ramp6[icolor % 6];
97     }
98 #undef icolor
99     return 0;
100 }
101 
102 /* Write a palette on a file. */
103 int
pc_write_palette(gx_device * dev,uint max_index,FILE * file)104 pc_write_palette(gx_device * dev, uint max_index, FILE * file)
105 {
106     uint i, c;
107     gx_color_value rgb[3];
108 
109     for (i = 0; i < max_index; i++) {
110         (*dev_proc(dev, map_color_rgb)) (dev, (gx_color_index) i, rgb);
111         for (c = 0; c < 3; c++) {
112             byte b = rgb[c] >> (gx_color_value_bits - 8);
113 
114             fputc(b, file);
115         }
116     }
117     return 0;
118 }
119