-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <string.h>
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ color.c for the Openbox window manager
+ Copyright (c) 2003 Ben Jansens
+ Copyright (c) 2003 Derek Foreman
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+*/
+
#include "render.h"
#include "color.h"
+#include "instance.h"
-XColor *pseudo_colors;
-int pseudo_bpc;
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <string.h>
-void color_allocate_gc(RrColor *in)
+void RrColorAllocateGC(RrColor *in)
{
XGCValues gcv;
/* this should be replaced with something far cooler */
RrColor *out = NULL;
XColor xcol;
- xcol.red = (r << 8) | r;
- xcol.green = (g << 8) | g;
- xcol.blue = (b << 8) | b;
- if (XAllocColor(RrDisplay(inst), RrColormap(inst), &xcol)) {
- out = g_new(RrColor, 1);
- out->inst = inst;
- out->r = xcol.red >> 8;
- out->g = xcol.green >> 8;
- out->b = xcol.blue >> 8;
- out->gc = None;
- out->pixel = xcol.pixel;
+ gint key;
+
+ key = (r << 24) + (g << 16) + (b << 8);
+ if ((out = g_hash_table_lookup(RrColorHash(inst), &key))) {
+ out->refcount++;
+ } else {
+ xcol.red = (r << 8) | r;
+ xcol.green = (g << 8) | g;
+ xcol.blue = (b << 8) | b;
+ if (XAllocColor(RrDisplay(inst), RrColormap(inst), &xcol)) {
+ out = g_new(RrColor, 1);
+ out->inst = inst;
+ out->r = xcol.red >> 8;
+ out->g = xcol.green >> 8;
+ out->b = xcol.blue >> 8;
+ out->gc = None;
+ out->pixel = xcol.pixel;
+ out->key = key;
+ out->refcount = 1;
+ g_hash_table_replace(RrColorHash(inst), &out->key, out);
+ }
}
return out;
}
-/*XXX same color could be pointed to twice, this might have to be a refcount*/
-
void RrColorFree(RrColor *c)
{
if (c) {
- if (c->gc) XFreeGC(RrDisplay(c->inst), c->gc);
- g_free(c);
+ if (--c->refcount < 1) {
+ g_hash_table_remove(RrColorHash(c->inst), &c->key);
+ if (c->pixel) XFreeColors(RrDisplay(c->inst), RrColormap(c->inst),
+ &c->pixel, 1, 0);
+ if (c->gc) XFreeGC(RrDisplay(c->inst), c->gc);
+ g_free(c);
+ }
}
}
-void reduce_depth(const RrInstance *inst, pixel32 *data, XImage *im)
+void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
{
int r, g, b;
int x,y;
- pixel32 *p32 = (pixel32 *) im->data;
- pixel16 *p16 = (pixel16 *) im->data;
+ RrPixel32 *p32 = (RrPixel32 *) im->data;
+ RrPixel16 *p16 = (RrPixel16 *) im->data;
unsigned char *p8 = (unsigned char *)im->data;
switch (im->bits_per_pixel) {
case 32:
- if ((RrRedOffset(inst) != default_red_offset) ||
- (RrBlueOffset(inst) != default_blue_offset) ||
- (RrGreenOffset(inst) != default_green_offset)) {
+ if ((RrRedOffset(inst) != RrDefaultRedOffset) ||
+ (RrBlueOffset(inst) != RrDefaultBlueOffset) ||
+ (RrGreenOffset(inst) != RrDefaultGreenOffset)) {
for (y = 0; y < im->height; y++) {
for (x = 0; x < im->width; x++) {
- r = (data[x] >> default_red_offset) & 0xFF;
- g = (data[x] >> default_green_offset) & 0xFF;
- b = (data[x] >> default_blue_offset) & 0xFF;
- p32[x] = (r << RrRedShift(inst))
- + (g << RrGreenShift(inst))
- + (b << RrBlueShift(inst));
+ r = (data[x] >> RrDefaultRedOffset) & 0xFF;
+ g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
+ b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
+ p32[x] = (r << RrRedOffset(inst))
+ + (g << RrGreenOffset(inst))
+ + (b << RrBlueOffset(inst));
}
data += im->width;
p32 += im->width;
case 16:
for (y = 0; y < im->height; y++) {
for (x = 0; x < im->width; x++) {
- r = (data[x] >> default_red_offset) & 0xFF;
+ r = (data[x] >> RrDefaultRedOffset) & 0xFF;
r = r >> RrRedShift(inst);
- g = (data[x] >> default_green_offset) & 0xFF;
+ g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
g = g >> RrGreenShift(inst);
- b = (data[x] >> default_blue_offset) & 0xFF;
+ b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
b = b >> RrBlueShift(inst);
p16[x] = (r << RrRedOffset(inst))
+ (g << RrGreenOffset(inst))
g_assert(RrVisual(inst)->class != TrueColor);
for (y = 0; y < im->height; y++) {
for (x = 0; x < im->width; x++) {
- p8[x] = pickColor(inst,
- data[x] >> default_red_offset,
- data[x] >> default_green_offset,
- data[x] >> default_blue_offset)->pixel;
+ p8[x] = RrPickColor(inst,
+ data[x] >> RrDefaultRedOffset,
+ data[x] >> RrDefaultGreenOffset,
+ data[x] >> RrDefaultBlueOffset)->pixel;
}
data += im->width;
p8 += im->bytes_per_line;
break;
default:
- g_message("your bit depth is currently unhandled\n");
+ g_warning("your bit depth is currently unhandled\n");
}
}
-XColor *pickColor(const RrInstance *inst, gint r, gint g, gint b)
+XColor *RrPickColor(const RrInstance *inst, gint r, gint g, gint b)
{
- r = (r & 0xff) >> (8-pseudo_bpc);
- g = (g & 0xff) >> (8-pseudo_bpc);
- b = (b & 0xff) >> (8-pseudo_bpc);
- return &RrPseudoColors(inst)[(r << (2*pseudo_bpc)) +
- (g << (1*pseudo_bpc)) +
+ r = (r & 0xff) >> (8-RrPseudoBPC(inst));
+ g = (g & 0xff) >> (8-RrPseudoBPC(inst));
+ b = (b & 0xff) >> (8-RrPseudoBPC(inst));
+ return &RrPseudoColors(inst)[(r << (2*RrPseudoBPC(inst))) +
+ (g << (1*RrPseudoBPC(inst))) +
b];
}
{
int x, y, di;
- g_message("SWAPPING BYTE ORDER");
-
di = 0;
for (y = 0; y < im->height; ++y) {
for (x = 0; x < im->height; ++x) {
case 8:
break;
default:
- g_message("your bit depth is currently unhandled\n");
+ g_warning("your bit depth is currently unhandled");
}
}
di += im->bytes_per_line;
im->byte_order = LSBFirst;
}
-void increase_depth(const RrInstance *inst, pixel32 *data, XImage *im)
+void RrIncreaseDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
{
int r, g, b;
int x,y;
- pixel32 *p32 = (pixel32 *) im->data;
- pixel16 *p16 = (pixel16 *) im->data;
+ RrPixel32 *p32 = (RrPixel32 *) im->data;
+ RrPixel16 *p16 = (RrPixel16 *) im->data;
unsigned char *p8 = (unsigned char *)im->data;
- if (im->byte_order != render_endian)
+ if (im->byte_order != LSBFirst)
swap_byte_order(im);
switch (im->bits_per_pixel) {
r = (p32[x] >> RrRedOffset(inst)) & 0xff;
g = (p32[x] >> RrGreenOffset(inst)) & 0xff;
b = (p32[x] >> RrBlueOffset(inst)) & 0xff;
- data[x] = (r << default_red_offset)
- + (g << default_green_offset)
- + (b << default_blue_offset)
- + (0xff << default_alpha_offset);
+ data[x] = (r << RrDefaultRedOffset)
+ + (g << RrDefaultGreenOffset)
+ + (b << RrDefaultBlueOffset)
+ + (0xff << RrDefaultAlphaOffset);
}
data += im->width;
p32 += im->bytes_per_line/4;
b = (p16[x] & RrBlueMask(inst)) >>
RrBlueOffset(inst) <<
RrBlueShift(inst);
- data[x] = (r << default_red_offset)
- + (g << default_green_offset)
- + (b << default_blue_offset)
- + (0xff << default_alpha_offset);
+ data[x] = (r << RrDefaultRedOffset)
+ + (g << RrDefaultGreenOffset)
+ + (b << RrDefaultBlueOffset)
+ + (0xff << RrDefaultAlphaOffset);
}
data += im->width;
p16 += im->bytes_per_line/2;
}
break;
case 8:
- g_message("this image bit depth is currently unhandled\n");
+ g_warning("this image bit depth is currently unhandled");
break;
case 1:
for (y = 0; y < im->height; y++) {
for (x = 0; x < im->width; x++) {
if (!(((p8[x / 8]) >> (x % 8)) & 0x1))
- data[x] = 0xff << default_alpha_offset; /* black */
+ data[x] = 0xff << RrDefaultAlphaOffset; /* black */
else
data[x] = 0xffffffff; /* white */
}
}
break;
default:
- g_message("this image bit depth is currently unhandled\n");
+ g_warning("this image bit depth is currently unhandled");
}
}
+
+int RrColorRed(const RrColor *c)
+{
+ return c->r;
+}
+
+int RrColorGreen(const RrColor *c)
+{
+ return c->g;
+}
+
+int RrColorBlue(const RrColor *c)
+{
+ return c->b;
+}
+
+gulong RrColorPixel(const RrColor *c)
+{
+ return c->pixel;
+}
+
+GC RrColorGC(RrColor *c)
+{
+ if (!c->gc)
+ RrColorAllocateGC(c);
+ return c->gc;
+}