change the render() interface
[mikachu/openbox.git] / otk / truerendercontrol.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef    HAVE_CONFIG_H
4 #  include "../config.h"
5 #endif // HAVE_CONFIG_H
6
7 #include "truerendercontrol.hh"
8 #include "display.hh"
9 #include "screeninfo.hh"
10 #include "widget.hh"
11
12 extern "C" {
13 #ifdef    HAVE_STDLIB_H
14 #  include <stdlib.h>
15 #endif // HAVE_STDLIB_H
16
17 #include "gettext.h"
18 #define _(str) gettext(str)
19 }
20
21 namespace otk {
22
23 TrueRenderControl::TrueRenderControl(const ScreenInfo *screen)
24   : RenderControl(screen)
25 {
26   printf("Initializing TrueColor RenderControl\n");
27
28   unsigned long red_mask, green_mask, blue_mask;
29
30   // find the offsets for each color in the visual's masks
31   red_mask = screen->visual()->red_mask;
32   green_mask = screen->visual()->green_mask;
33   blue_mask = screen->visual()->blue_mask;
34
35   while (! (red_mask & 1)) { _red_offset++; red_mask >>= 1; }
36   while (! (green_mask & 1)) { _green_offset++; green_mask >>= 1; }
37   while (! (blue_mask & 1)) { _blue_offset++; blue_mask >>= 1; }
38
39   // use the mask to determine the number of bits for each shade of color
40   // so, best case, red_mask == 0xff (255), with each bit as a different
41   // shade!
42   _red_bits = 255 / red_mask;
43   _green_bits = 255 / green_mask;
44   _blue_bits = 255 / blue_mask;
45
46   // compute color tables, based on the number of bits for each shade
47   for (int i = 0; i < 256; i++) {
48     _red_color_table[i] = i / _red_bits;
49     _green_color_table[i] = i / _green_bits;
50     _blue_color_table[i] = i / _blue_bits;
51   }
52 }
53
54 TrueRenderControl::~TrueRenderControl()
55 {
56   printf("Destroying TrueColor RenderControl\n");
57
58
59 }
60
61 static inline
62 void assignPixel(unsigned int bit_depth, unsigned char **data,  unsigned long pixel) {
63   unsigned char *pixel_data = *data;
64   switch (bit_depth) {
65   case  8: //  8bpp
66     *pixel_data++ = pixel;
67     break;
68
69   case 16: // 16bpp LSB
70     *pixel_data++ = pixel;
71     *pixel_data++ = pixel >> 8;
72     break;
73
74   case 17: // 16bpp MSB
75     *pixel_data++ = pixel >> 8;
76     *pixel_data++ = pixel;
77     break;
78
79   case 24: // 24bpp LSB
80     *pixel_data++ = pixel;
81     *pixel_data++ = pixel >> 8;
82     *pixel_data++ = pixel >> 16;
83     break;
84
85   case 25: // 24bpp MSB
86     *pixel_data++ = pixel >> 16;
87     *pixel_data++ = pixel >> 8;
88     *pixel_data++ = pixel;
89     break;
90
91   case 32: // 32bpp LSB
92     *pixel_data++ = pixel;
93     *pixel_data++ = pixel >> 8;
94     *pixel_data++ = pixel >> 16;
95     *pixel_data++ = pixel >> 24;
96     break;
97
98   case 33: // 32bpp MSB
99     *pixel_data++ = pixel >> 24;
100     *pixel_data++ = pixel >> 16;
101     *pixel_data++ = pixel >> 8;
102     *pixel_data++ = pixel;
103     break;
104   }
105   *data = pixel_data; // assign back so we don't lose our place
106 }
107
108 void renderPixel(XImage *im, unsigned char *dp, unsigned long pixel)
109 {
110   unsigned int bpp = im->bits_per_pixel + (im->byte_order == MSBFirst) ? 1 : 0;
111
112   switch (bpp) {
113   case  8: //  8bpp
114     *dp++ = pixel;
115     break;
116   case 16: // 16bpp LSB
117     *dp++ = pixel;
118     *dp++ = pixel >> 8;
119     break;
120   case 17: // 16bpp MSB
121     *dp++ = pixel >> 8;
122     *dp++ = pixel;
123     break;
124   case 24: // 24bpp LSB
125     *dp++ = pixel;
126     *dp++ = pixel >> 8;
127     *dp++ = pixel >> 16;
128     break;
129   case 25: // 24bpp MSB
130     *dp++ = pixel >> 16;
131     *dp++ = pixel >> 8;
132     *dp++ = pixel;
133     break;
134   case 32: // 32bpp LSB
135     *dp++ = pixel;
136     *dp++ = pixel >> 8;
137     *dp++ = pixel >> 16;
138     *dp++ = pixel >> 24;
139     break;
140   case 33: // 32bpp MSB
141     *dp++ = pixel >> 24;
142     *dp++ = pixel >> 16;
143     *dp++ = pixel >> 8;
144     *dp++ = pixel;
145     break;
146   }
147 }
148
149 void TrueRenderControl::render(Widget *wi)
150 {
151   assert(wi);
152   
153   XGCValues gcv;
154   gcv.cap_style = CapProjecting;
155
156   int w = 255, h = 31;
157   Pixmap p = XCreatePixmap(**display, wi->window(), w, h, _screen->depth());
158   XImage *im = XCreateImage(**display, _screen->visual(), _screen->depth(),
159                             ZPixmap, 0, NULL, w, h, 32, 0);
160   //GC gc = XCreateGC(**display, _screen->rootWindow(), GCCapStyle, &gcv);
161
162   // XXX  + 1?
163   unsigned char *data = new unsigned char[im->bytes_per_line * (h + 1)];
164   unsigned char *dp = data;
165
166   for (int x = 0; x < w; ++x, dp += im->bits_per_pixel/8)
167     renderPixel(im, dp, 0);
168   for (int y = 0; y < 10; ++y)
169     for (int x = 0; x < w; ++x, dp += im->bits_per_pixel/8)
170       renderPixel(im, dp, _red_color_table[x] << _red_offset);
171   for (int y = 0; y < 10; ++y)
172     for (int x = 0; x < w; ++x, dp += im->bits_per_pixel/8)
173       renderPixel(im, dp, _green_color_table[x] << _green_offset);
174   for (int y = 0; y < 10; ++y)
175     for (int x = 0; x < w; ++x, dp += im->bits_per_pixel/8)
176       renderPixel(im, dp, _blue_color_table[x] << _blue_offset);
177
178   printf("\nDone\n");
179
180   im->data = (char*) data;
181   
182   XPutImage(**display, p, DefaultGC(**display, _screen->screen()),
183             im, 0, 0, 0, 0, w, h);
184
185   //delete [] image->data;
186   //image->data = NULL;
187   XDestroyImage(im);
188
189   XSetWindowBackgroundPixmap(**display, wi->window(), p);
190   XClearWindow(**display, wi->window());
191
192   XFreePixmap(**display, p);
193 }
194
195 }