1 /* Copyright (C) 1992, 1993, 1998 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gdevpccm.c,v 1.2.6.1.2.1 2003/01/17 00:49:01 giles Exp $ */
20 /* Support routines for PC color mapping */
21 #include "gx.h"
22 #include "gsmatrix.h"		/* for gxdevice.h */
23 #include "gxdevice.h"
24 #include "gdevpccm.h"		/* interface */
25 
26 /* Color mapping routines for EGA/VGA-style color. */
27 /* Colors are 4 bits: 8=intensity, 4=R, 2=G, 1=B. */
28 
29 /* Define the color spectrum */
30 #define v_black 0
31 #define v_blue 1
32 #define v_green 2
33 #define v_cyan 3
34 #define v_red 4
35 #define v_magenta 5
36 #define v_brown 6
37 #define v_white 7
38 #define v_dgray 8		/* dark gray is not very usable */
39 #define v_lblue 9
40 #define v_lgreen 10
41 #define v_lcyan 11
42 #define v_lred 12
43 #define v_lmagenta 13
44 #define v_yellow 14
45 #define v_bwhite 15
46 
47 /* ------ EGA/VGA (4-bit) color mapping ------ */
48 
49 gx_color_index
pc_4bit_map_rgb_color(gx_device * dev,gx_color_value r,gx_color_value g,gx_color_value b)50 pc_4bit_map_rgb_color(gx_device * dev, gx_color_value r, gx_color_value g,
51 		      gx_color_value b)
52 {
53 #define Nb gx_color_value_bits
54     static const byte grays[4] =
55     {v_black, v_dgray, v_white, v_bwhite};
56 
57 #define tab3(v0,v1,v23) { v0, v1, v23, v23 }
58     static const byte g0r0[4] = tab3(v_black, v_blue, v_lblue);
59     static const byte g0r1[4] = tab3(v_red, v_magenta, v_lmagenta);
60     static const byte g0r2[4] = tab3(v_lred, v_lmagenta, v_lmagenta);
61     static const byte *const g0[4] = tab3(g0r0, g0r1, g0r2);
62     static const byte g1r0[4] = tab3(v_green, v_cyan, v_lcyan);
63     static const byte g1r1[4] = tab3(v_brown, v_white, v_lcyan);
64     static const byte g1r2[4] = tab3(v_yellow, v_lred, v_lmagenta);
65     static const byte *const g1[4] = tab3(g1r0, g1r1, g1r2);
66     static const byte g2r0[4] = tab3(v_lgreen, v_lgreen, v_lcyan);
67     static const byte g2r1[4] = tab3(v_lgreen, v_lgreen, v_lcyan);
68     static const byte g2r2[4] = tab3(v_yellow, v_yellow, v_bwhite);
69     static const byte *const g2[4] = tab3(g2r0, g2r1, g2r2);
70     static const byte *const *const ga[4] = tab3(g0, g1, g2);
71 
72 #undef tab3
73 #define q4mask (-1 << (Nb - 2))
74     if (!((r ^ g) & q4mask) && !((g ^ b) & q4mask))	/* gray */
75 #undef q4mask
76 	return (gx_color_index) grays[r >> (Nb - 2)];
77     else
78 #define q3cv(v) ((v - (v >> 2)) >> (Nb - 2))
79 	return (gx_color_index) ga[q3cv(g)][q3cv(r)][q3cv(b)];
80 #undef q3cv
81 #undef Nb
82 }
83 int
pc_4bit_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])84 pc_4bit_map_color_rgb(gx_device * dev, gx_color_index color,
85 		      gx_color_value prgb[3])
86 {
87 #define icolor (int)color
88     gx_color_value one;
89 
90     switch (icolor) {
91 	case v_white:		/* "dark white" */
92 	    prgb[0] = prgb[1] = prgb[2] =
93 		gx_max_color_value - (gx_max_color_value / 3);
94 	    return 0;
95 	case v_dgray:
96 	    prgb[0] = prgb[1] = prgb[2] = gx_max_color_value / 3;
97 	    return 0;
98     }
99     one = (icolor & 8 ? gx_max_color_value : gx_max_color_value / 2);
100     prgb[0] = (icolor & 4 ? one : 0);
101     prgb[1] = (icolor & 2 ? one : 0);
102     prgb[2] = (icolor & 1 ? one : 0);
103     return 0;
104 #undef icolor
105 }
106 
107 /* ------ SVGA 8-bit color mapping ------ */
108 
109 /*
110  * For 8-bit color, we use a fixed palette with approximately
111  * 3 bits of R, 3 bits of G, and 2 bits of B.
112  * We have to trade off even spacing of colors along each axis
113  * against the desire to have real gray shades;
114  * we compromise by using a 7x7x5 "cube" with extra gray shades
115  * (1/6, 1/3, 2/3, and 5/6), instead of the obvious 8x8x4.
116  */
117 
118 gx_color_index
pc_8bit_map_rgb_color(gx_device * dev,gx_color_value r,gx_color_value g,gx_color_value b)119 pc_8bit_map_rgb_color(gx_device * dev, gx_color_value r, gx_color_value g,
120 		      gx_color_value b)
121 {
122     uint rv = r / (gx_max_color_value / 7 + 1);
123     uint gv = g / (gx_max_color_value / 7 + 1);
124 
125     return (gx_color_index)
126 	(rv == gv && gv == b / (gx_max_color_value / 7 + 1) ?
127 	 rv + (256 - 7) :
128 	 (rv * 7 + gv) * 5 + b / (gx_max_color_value / 5 + 1));
129 }
130 int
pc_8bit_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])131 pc_8bit_map_color_rgb(gx_device * dev, gx_color_index color,
132 		      gx_color_value prgb[3])
133 {
134     static const gx_color_value ramp7[8] =
135     {0,
136      gx_max_color_value / 6,
137      gx_max_color_value / 3,
138      gx_max_color_value / 2,
139      gx_max_color_value - (gx_max_color_value / 3),
140      gx_max_color_value - (gx_max_color_value / 6),
141      gx_max_color_value,
142     /* The 8th entry is not actually ever used, */
143     /* except to fill out the palette. */
144      gx_max_color_value
145     };
146     static const gx_color_value ramp5[5] =
147     {0,
148      gx_max_color_value / 4,
149      gx_max_color_value / 2,
150      gx_max_color_value - (gx_max_color_value / 4),
151      gx_max_color_value
152     };
153 
154 #define icolor (uint)color
155     if (icolor >= 256 - 7) {
156 	prgb[0] = prgb[1] = prgb[2] = ramp7[icolor - (256 - 7)];
157     } else {
158 	prgb[0] = ramp7[icolor / 35];
159 	prgb[1] = ramp7[(icolor / 5) % 7];
160 	prgb[2] = ramp5[icolor % 5];
161     }
162 #undef icolor
163     return 0;
164 }
165 
166 /* Write a palette on a file. */
167 int
pc_write_palette(gx_device * dev,uint max_index,FILE * file)168 pc_write_palette(gx_device * dev, uint max_index, FILE * file)
169 {
170     uint i, c;
171     gx_color_value rgb[3];
172 
173     for (i = 0; i < max_index; i++) {
174 	(*dev_proc(dev, map_color_rgb)) (dev, (gx_color_index) i, rgb);
175 	for (c = 0; c < 3; c++) {
176 	    byte b = rgb[c] >> (gx_color_value_bits - 8);
177 
178 	    fputc(b, file);
179 	}
180     }
181     return 0;
182 }
183