1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 color.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
6 Copyright (c) 2003 Derek Foreman
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 See the COPYING file for a copy of the GNU General Public License.
26 #include <X11/Xutil.h>
29 void RrColorAllocateGC(RrColor *in)
33 gcv.foreground = in->pixel;
34 gcv.cap_style = CapProjecting;
35 in->gc = XCreateGC(RrDisplay(in->inst),
36 RrRootWindow(in->inst),
37 GCForeground | GCCapStyle, &gcv);
40 RrColor *RrColorParse(const RrInstance *inst, gchar *colorname)
44 g_assert(colorname != NULL);
45 /* get rgb values from colorname */
51 if (!XParseColor(RrDisplay(inst), RrColormap(inst), colorname, &xcol)) {
52 g_message("Unable to parse color '%s'", colorname);
55 return RrColorNew(inst, xcol.red >> 8, xcol.green >> 8, xcol.blue >> 8);
58 /*#define NO_COLOR_CACHE*/
63 RrColor *RrColorNew(const RrInstance *inst, gint r, gint g, gint b)
65 /* this should be replaced with something far cooler */
70 g_assert(r >= 0 && r < 256);
71 g_assert(g >= 0 && g < 256);
72 g_assert(b >= 0 && b < 256);
74 key = (r << 24) + (g << 16) + (b << 8);
75 #ifndef NO_COLOR_CACHE
76 if ((out = g_hash_table_lookup(RrColorHash(inst), &key))) {
80 xcol.red = (r << 8) | r;
81 xcol.green = (g << 8) | g;
82 xcol.blue = (b << 8) | b;
83 if (XAllocColor(RrDisplay(inst), RrColormap(inst), &xcol)) {
84 out = g_new(RrColor, 1);
86 out->r = xcol.red >> 8;
87 out->g = xcol.green >> 8;
88 out->b = xcol.blue >> 8;
90 out->pixel = xcol.pixel;
96 #ifndef NO_COLOR_CACHE
97 g_hash_table_insert(RrColorHash(inst), &out->key, out);
104 RrColor *RrColorCopy(RrColor* c)
106 return RrColorNew(c->inst, c->r, c->g, c->b);
109 void RrColorFree(RrColor *c)
112 if (--c->refcount < 1) {
113 #ifndef NO_COLOR_CACHE
114 g_assert(g_hash_table_lookup(RrColorHash(c->inst), &c->key));
115 g_hash_table_remove(RrColorHash(c->inst), &c->key);
117 if (c->pixel) XFreeColors(RrDisplay(c->inst), RrColormap(c->inst),
119 if (c->gc) XFreeGC(RrDisplay(c->inst), c->gc);
125 void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
129 RrPixel32 *p32 = (RrPixel32 *) im->data;
130 RrPixel16 *p16 = (RrPixel16 *) im->data;
131 RrPixel8 *p8 = (RrPixel8 *) im->data;
132 switch (im->bits_per_pixel) {
134 if ((RrRedOffset(inst) != RrDefaultRedOffset) ||
135 (RrBlueOffset(inst) != RrDefaultBlueOffset) ||
136 (RrGreenOffset(inst) != RrDefaultGreenOffset)) {
137 for (y = 0; y < im->height; y++) {
138 for (x = 0; x < im->width; x++) {
139 r = (data[x] >> RrDefaultRedOffset) & 0xFF;
140 g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
141 b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
142 p32[x] = (r << RrRedOffset(inst))
143 + (g << RrGreenOffset(inst))
144 + (b << RrBlueOffset(inst));
149 } else im->data = (gchar*) data;
152 for (y = 0; y < im->height; y++) {
153 for (x = 0; x < im->width; x++) {
154 r = (data[x] >> RrDefaultRedOffset) & 0xFF;
155 r = r >> RrRedShift(inst);
156 g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
157 g = g >> RrGreenShift(inst);
158 b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
159 b = b >> RrBlueShift(inst);
160 p16[x] = (r << RrRedOffset(inst))
161 + (g << RrGreenOffset(inst))
162 + (b << RrBlueOffset(inst));
165 p16 += im->bytes_per_line/2;
169 if (RrVisual(inst)->class == TrueColor) {
170 for (y = 0; y < im->height; y++) {
171 for (x = 0; x < im->width; x++) {
172 r = (data[x] >> RrDefaultRedOffset) & 0xFF;
173 r = r >> RrRedShift(inst);
174 g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
175 g = g >> RrGreenShift(inst);
176 b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
177 b = b >> RrBlueShift(inst);
178 p8[x] = (r << RrRedOffset(inst))
179 + (g << RrGreenOffset(inst))
180 + (b << RrBlueOffset(inst));
183 p8 += im->bytes_per_line;
186 for (y = 0; y < im->height; y++) {
187 for (x = 0; x < im->width; x++) {
188 p8[x] = RrPickColor(inst,
189 data[x] >> RrDefaultRedOffset,
190 data[x] >> RrDefaultGreenOffset,
191 data[x] >> RrDefaultBlueOffset)->pixel;
194 p8 += im->bytes_per_line;
199 g_error("Your bit depth is currently unhandled\n");
204 XColor *RrPickColor(const RrInstance *inst, gint r, gint g, gint b)
206 r = (r & 0xff) >> (8-RrPseudoBPC(inst));
207 g = (g & 0xff) >> (8-RrPseudoBPC(inst));
208 b = (b & 0xff) >> (8-RrPseudoBPC(inst));
209 return &RrPseudoColors(inst)[(r << (2*RrPseudoBPC(inst))) +
210 (g << (1*RrPseudoBPC(inst))) +
214 static void swap_byte_order(XImage *im)
219 for (y = 0; y < im->height; ++y) {
220 for (x = 0; x < im->height; ++x) {
221 gchar *c = &im->data[di + x * im->bits_per_pixel / 8];
224 switch (im->bits_per_pixel) {
237 g_error("Your bit depth (%i) is currently unhandled",
241 di += im->bytes_per_line;
244 if (im->byte_order == LSBFirst)
245 im->byte_order = MSBFirst;
247 im->byte_order = LSBFirst;
250 void RrIncreaseDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
254 RrPixel32 *p32 = (RrPixel32 *) im->data;
255 RrPixel16 *p16 = (RrPixel16 *) im->data;
256 guchar *p8 = (guchar *)im->data;
258 if (im->byte_order != LSBFirst)
261 switch (im->bits_per_pixel) {
263 for (y = 0; y < im->height; y++) {
264 for (x = 0; x < im->width; x++) {
265 r = (p32[x] >> RrRedOffset(inst)) & 0xff;
266 g = (p32[x] >> RrGreenOffset(inst)) & 0xff;
267 b = (p32[x] >> RrBlueOffset(inst)) & 0xff;
268 data[x] = (r << RrDefaultRedOffset)
269 + (g << RrDefaultGreenOffset)
270 + (b << RrDefaultBlueOffset)
271 + (0xff << RrDefaultAlphaOffset);
274 p32 += im->bytes_per_line/4;
278 for (y = 0; y < im->height; y++) {
279 for (x = 0; x < im->width; x++) {
280 r = (p16[x] & RrRedMask(inst)) >>
283 g = (p16[x] & RrGreenMask(inst)) >>
284 RrGreenOffset(inst) <<
286 b = (p16[x] & RrBlueMask(inst)) >>
287 RrBlueOffset(inst) <<
289 data[x] = (r << RrDefaultRedOffset)
290 + (g << RrDefaultGreenOffset)
291 + (b << RrDefaultBlueOffset)
292 + (0xff << RrDefaultAlphaOffset);
295 p16 += im->bytes_per_line/2;
299 g_error("This image bit depth (%i) is currently unhandled", 8);
302 for (y = 0; y < im->height; y++) {
303 for (x = 0; x < im->width; x++) {
304 if (!(((p8[x / 8]) >> (x % 8)) & 0x1))
305 data[x] = 0xff << RrDefaultAlphaOffset; /* black */
307 data[x] = 0xffffffff; /* white */
310 p8 += im->bytes_per_line;
314 g_error("This image bit depth (%i) is currently unhandled",
319 gint RrColorRed(const RrColor *c)
324 gint RrColorGreen(const RrColor *c)
329 gint RrColorBlue(const RrColor *c)
334 gulong RrColorPixel(const RrColor *c)
339 GC RrColorGC(RrColor *c)
342 RrColorAllocateGC(c);