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