]>
Dogcows Code - chaz/openbox/blob - obrender/render.c
7a3420429116fb808f6444333185b460ae353557
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 render.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.
31 #include <X11/Xutil.h>
32 #include <X11/Xft/Xft.h>
38 static void pixel_data_to_pixmap(RrAppearance
*l
,
39 gint x
, gint y
, gint w
, gint h
);
41 Pixmap
RrPaintPixmap(RrAppearance
*a
, gint w
, gint h
)
43 gint i
, transferred
= 0, force_transfer
= 0;
45 RrRect tarea
; /* area in which to draw textures */
48 if (w
<= 0 || h
<= 0) return None
;
50 if (a
->surface
.parentx
< 0 || a
->surface
.parenty
< 0) {
51 /* ob_debug("Invalid parent co-ordinates\n"); */
55 if (a
->surface
.grad
== RR_SURFACE_PARENTREL
&&
56 (a
->surface
.parentx
>= a
->surface
.parent
->w
||
57 a
->surface
.parenty
>= a
->surface
.parent
->h
))
62 resized
= (a
->w
!= w
|| a
->h
!= h
);
64 oldp
= a
->pixmap
; /* save to free after changing the visible pixmap */
65 a
->pixmap
= XCreatePixmap(RrDisplay(a
->inst
),
66 RrRootWindow(a
->inst
),
67 w
, h
, RrDepth(a
->inst
));
69 g_assert(a
->pixmap
!= None
);
73 if (a
->xftdraw
!= NULL
)
74 XftDrawDestroy(a
->xftdraw
);
75 a
->xftdraw
= XftDrawCreate(RrDisplay(a
->inst
), a
->pixmap
,
76 RrVisual(a
->inst
), RrColormap(a
->inst
));
77 g_assert(a
->xftdraw
!= NULL
);
80 g_free(a
->surface
.pixel_data
);
81 a
->surface
.pixel_data
= g_new(RrPixel32
, w
* h
);
88 RrMargins(a
, &l
, &t
, &r
, &b
);
89 RECT_SET(tarea
, l
, t
, w
- l
- r
, h
- t
- b
);
92 for (i
= 0; i
< a
->textures
; i
++) {
93 switch (a
->texture
[i
].type
) {
99 if ((a
->surface
.grad
!= RR_SURFACE_SOLID
)
100 || (a
->surface
.interlaced
))
101 pixel_data_to_pixmap(a
, 0, 0, w
, h
);
103 if (a
->xftdraw
== NULL
) {
104 a
->xftdraw
= XftDrawCreate(RrDisplay(a
->inst
), a
->pixmap
,
106 RrColormap(a
->inst
));
108 RrFontDraw(a
->xftdraw
, &a
->texture
[i
].data
.text
, &tarea
);
110 case RR_TEXTURE_LINE_ART
:
113 if ((a
->surface
.grad
!= RR_SURFACE_SOLID
)
114 || (a
->surface
.interlaced
))
115 pixel_data_to_pixmap(a
, 0, 0, w
, h
);
117 XDrawLine(RrDisplay(a
->inst
), a
->pixmap
,
118 RrColorGC(a
->texture
[i
].data
.lineart
.color
),
119 a
->texture
[i
].data
.lineart
.x1
,
120 a
->texture
[i
].data
.lineart
.y1
,
121 a
->texture
[i
].data
.lineart
.x2
,
122 a
->texture
[i
].data
.lineart
.y2
);
124 case RR_TEXTURE_MASK
:
127 if ((a
->surface
.grad
!= RR_SURFACE_SOLID
)
128 || (a
->surface
.interlaced
))
129 pixel_data_to_pixmap(a
, 0, 0, w
, h
);
131 RrPixmapMaskDraw(a
->pixmap
, &a
->texture
[i
].data
.mask
, &tarea
);
133 case RR_TEXTURE_IMAGE
:
134 g_assert(!transferred
);
136 RrRect narea
= tarea
;
137 RrTextureImage
*img
= &a
->texture
[i
].data
.image
;
139 narea
.width
-= img
->tx
;
141 narea
.height
-= img
->ty
;
143 narea
.width
= MIN(narea
.width
, img
->twidth
);
145 narea
.height
= MIN(narea
.height
, img
->theight
);
146 RrImageDrawImage(a
->surface
.pixel_data
,
147 &a
->texture
[i
].data
.image
,
153 case RR_TEXTURE_RGBA
:
154 g_assert(!transferred
);
156 RrRect narea
= tarea
;
157 RrTextureRGBA
*rgb
= &a
->texture
[i
].data
.rgba
;
159 narea
.width
-= rgb
->tx
;
161 narea
.height
-= rgb
->ty
;
163 narea
.width
= MIN(narea
.width
, rgb
->twidth
);
165 narea
.height
= MIN(narea
.height
, rgb
->theight
);
166 RrImageDrawRGBA(a
->surface
.pixel_data
,
167 &a
->texture
[i
].data
.rgba
,
173 case RR_TEXTURE_NUM_TYPES
:
174 g_assert_not_reached();
180 if ((a
->surface
.grad
!= RR_SURFACE_SOLID
) || (a
->surface
.interlaced
) ||
183 pixel_data_to_pixmap(a
, 0, 0, w
, h
);
190 void RrPaint(RrAppearance
*a
, Window win
, gint w
, gint h
)
194 oldp
= RrPaintPixmap(a
, w
, h
);
195 XSetWindowBackgroundPixmap(RrDisplay(a
->inst
), win
, a
->pixmap
);
196 XClearWindow(RrDisplay(a
->inst
), win
);
197 /* free this after changing the visible pixmap */
198 if (oldp
) XFreePixmap(RrDisplay(a
->inst
), oldp
);
201 RrAppearance
*RrAppearanceNew(const RrInstance
*inst
, gint numtex
)
205 out
= g_slice_new0(RrAppearance
);
208 out
->textures
= numtex
;
209 out
->surface
.bevel_light_adjust
= 128;
210 out
->surface
.bevel_dark_adjust
= 64;
211 if (numtex
) out
->texture
= g_new0(RrTexture
, numtex
);
216 void RrAppearanceRemoveTextures(RrAppearance
*a
)
222 void RrAppearanceAddTextures(RrAppearance
*a
, gint numtex
)
224 g_assert(a
->textures
== 0);
226 a
->textures
= numtex
;
227 if (numtex
) a
->texture
= g_new0(RrTexture
, numtex
);
230 void RrAppearanceClearTextures(RrAppearance
*a
)
232 memset(a
->texture
, 0, a
->textures
* sizeof(RrTexture
));
235 /* shallow copy means up the ref count and return it */
236 RrAppearance
*RrAppearanceCopyShallow(RrAppearance
*orig
)
242 /* deep copy of orig, means reset ref to 1 on copy
243 * and copy each thing memwise. */
244 RrAppearance
*RrAppearanceCopy(RrAppearance
*orig
)
246 RrSurface
*spo
, *spc
;
247 RrAppearance
*copy
= g_slice_new(RrAppearance
);
249 copy
->inst
= orig
->inst
;
252 spo
= &(orig
->surface
);
253 spc
= &(copy
->surface
);
254 spc
->grad
= spo
->grad
;
255 spc
->relief
= spo
->relief
;
256 spc
->bevel
= spo
->bevel
;
257 if (spo
->primary
!= NULL
)
258 spc
->primary
= RrColorNew(copy
->inst
,
262 else spc
->primary
= NULL
;
264 if (spo
->secondary
!= NULL
)
265 spc
->secondary
= RrColorNew(copy
->inst
,
269 else spc
->secondary
= NULL
;
271 if (spo
->border_color
!= NULL
)
272 spc
->border_color
= RrColorNew(copy
->inst
,
273 spo
->border_color
->r
,
274 spo
->border_color
->g
,
275 spo
->border_color
->b
);
276 else spc
->border_color
= NULL
;
278 if (spo
->interlace_color
!= NULL
)
279 spc
->interlace_color
= RrColorNew(copy
->inst
,
280 spo
->interlace_color
->r
,
281 spo
->interlace_color
->g
,
282 spo
->interlace_color
->b
);
283 else spc
->interlace_color
= NULL
;
285 if (spo
->bevel_dark
!= NULL
)
286 spc
->bevel_dark
= RrColorNew(copy
->inst
,
290 else spc
->bevel_dark
= NULL
;
292 if (spo
->bevel_light
!= NULL
)
293 spc
->bevel_light
= RrColorNew(copy
->inst
,
296 spo
->bevel_light
->b
);
297 else spc
->bevel_light
= NULL
;
299 if (spo
->split_primary
!= NULL
)
300 spc
->split_primary
= RrColorNew(copy
->inst
,
301 spo
->split_primary
->r
,
302 spo
->split_primary
->g
,
303 spo
->split_primary
->b
);
304 else spc
->split_primary
= NULL
;
306 if (spo
->split_secondary
!= NULL
)
307 spc
->split_secondary
= RrColorNew(copy
->inst
,
308 spo
->split_secondary
->r
,
309 spo
->split_secondary
->g
,
310 spo
->split_secondary
->b
);
311 else spc
->split_secondary
= NULL
;
313 spc
->interlaced
= spo
->interlaced
;
314 spc
->bevel_light_adjust
= spo
->bevel_light_adjust
;
315 spc
->bevel_dark_adjust
= spo
->bevel_dark_adjust
;
316 spc
->border
= spo
->border
;
318 spc
->parentx
= spc
->parenty
= 0;
319 spc
->pixel_data
= NULL
;
321 copy
->textures
= orig
->textures
;
322 copy
->texture
= g_memdup(orig
->texture
,
323 orig
->textures
* sizeof(RrTexture
));
325 copy
->xftdraw
= NULL
;
326 copy
->w
= copy
->h
= 0;
330 /* now decrements ref counter, and frees only if ref <= 0 */
331 void RrAppearanceFree(RrAppearance
*a
)
335 if (a
->pixmap
!= None
) XFreePixmap(RrDisplay(a
->inst
), a
->pixmap
);
336 if (a
->xftdraw
!= NULL
) XftDrawDestroy(a
->xftdraw
);
340 RrColorFree(p
->primary
);
341 RrColorFree(p
->secondary
);
342 RrColorFree(p
->border_color
);
343 RrColorFree(p
->interlace_color
);
344 RrColorFree(p
->bevel_dark
);
345 RrColorFree(p
->bevel_light
);
346 RrColorFree(p
->split_primary
);
347 RrColorFree(p
->split_secondary
);
348 g_free(p
->pixel_data
);
349 p
->pixel_data
= NULL
;
350 g_slice_free(RrAppearance
, a
);
354 static void pixel_data_to_pixmap(RrAppearance
*l
,
355 gint x
, gint y
, gint w
, gint h
)
357 RrPixel32
*in
, *scratch
;
360 im
= XCreateImage(RrDisplay(l
->inst
), RrVisual(l
->inst
), RrDepth(l
->inst
),
361 ZPixmap
, 0, NULL
, w
, h
, 32, 0);
362 g_assert(im
!= NULL
);
364 in
= l
->surface
.pixel_data
;
367 /* this malloc is a complete waste of time on normal 32bpp
368 as reduce_depth just sets im->data = data and returns
370 scratch
= g_new(RrPixel32
, im
->width
* im
->height
);
371 im
->data
= (gchar
*) scratch
;
372 RrReduceDepth(l
->inst
, in
, im
);
373 XPutImage(RrDisplay(l
->inst
), out
,
374 DefaultGC(RrDisplay(l
->inst
), RrScreen(l
->inst
)),
375 im
, 0, 0, x
, y
, w
, h
);
381 void RrMargins (RrAppearance
*a
, gint
*l
, gint
*t
, gint
*r
, gint
*b
)
383 *l
= *t
= *r
= *b
= 0;
385 if (a
->surface
.grad
!= RR_SURFACE_PARENTREL
) {
386 if (a
->surface
.relief
!= RR_RELIEF_FLAT
) {
387 switch (a
->surface
.bevel
) {
389 *l
= *t
= *r
= *b
= 1;
392 *l
= *t
= *r
= *b
= 2;
394 case RR_BEVEL_NUM_TYPES
:
395 g_assert_not_reached();
397 } else if (a
->surface
.border
) {
398 *l
= *t
= *r
= *b
= 1;
403 void RrMinSize(RrAppearance
*a
, gint
*w
, gint
*h
)
409 gint
RrMinWidth(RrAppearance
*a
)
416 RrMargins(a
, &l
, &t
, &r
, &b
);
418 for (i
= 0; i
< a
->textures
; ++i
) {
419 switch (a
->texture
[i
].type
) {
420 case RR_TEXTURE_NONE
:
422 case RR_TEXTURE_MASK
:
423 w
= MAX(w
, a
->texture
[i
].data
.mask
.mask
->width
);
425 case RR_TEXTURE_TEXT
:
426 m
= RrFontMeasureString(a
->texture
[i
].data
.text
.font
,
427 a
->texture
[i
].data
.text
.string
,
428 a
->texture
[i
].data
.text
.shadow_offset_x
,
429 a
->texture
[i
].data
.text
.shadow_offset_y
,
430 a
->texture
[i
].data
.text
.flow
,
431 a
->texture
[i
].data
.text
.maxwidth
);
432 w
= MAX(w
, m
->width
);
433 g_slice_free(RrSize
, m
);
435 case RR_TEXTURE_RGBA
:
436 w
+= MAX(w
, a
->texture
[i
].data
.rgba
.width
);
438 case RR_TEXTURE_IMAGE
:
439 /* images resize so they don't contribute anything to the min */
441 case RR_TEXTURE_LINE_ART
:
442 w
= MAX(w
, MAX(a
->texture
[i
].data
.lineart
.x1
- l
- r
,
443 a
->texture
[i
].data
.lineart
.x2
- l
- r
));
445 case RR_TEXTURE_NUM_TYPES
:
446 g_assert_not_reached();
456 gint
RrMinHeight(RrAppearance
*a
)
463 RrMargins(a
, &l
, &t
, &r
, &b
);
465 for (i
= 0; i
< a
->textures
; ++i
) {
466 switch (a
->texture
[i
].type
) {
467 case RR_TEXTURE_NONE
:
469 case RR_TEXTURE_MASK
:
470 h
= MAX(h
, a
->texture
[i
].data
.mask
.mask
->height
);
472 case RR_TEXTURE_TEXT
:
473 if (a
->texture
[i
].data
.text
.flow
) {
474 g_assert(a
->texture
[i
].data
.text
.string
!= NULL
);
476 m
= RrFontMeasureString
477 (a
->texture
[i
].data
.text
.font
,
478 a
->texture
[i
].data
.text
.string
,
479 a
->texture
[i
].data
.text
.shadow_offset_x
,
480 a
->texture
[i
].data
.text
.shadow_offset_y
,
481 a
->texture
[i
].data
.text
.flow
,
482 a
->texture
[i
].data
.text
.maxwidth
);
483 h
+= MAX(h
, m
->height
);
484 g_slice_free(RrSize
, m
);
489 (a
->texture
[i
].data
.text
.font
,
490 a
->texture
[i
].data
.text
.shadow_offset_y
));
492 case RR_TEXTURE_RGBA
:
493 h
+= MAX(h
, a
->texture
[i
].data
.rgba
.height
);
495 case RR_TEXTURE_IMAGE
:
496 /* images resize so they don't contribute anything to the min */
498 case RR_TEXTURE_LINE_ART
:
499 h
= MAX(h
, MAX(a
->texture
[i
].data
.lineart
.y1
- t
- b
,
500 a
->texture
[i
].data
.lineart
.y2
- t
- b
));
502 case RR_TEXTURE_NUM_TYPES
:
503 g_assert_not_reached();
513 static void reverse_bits(gchar
*c
, gint n
)
516 for (i
= 0; i
< n
; i
++, c
++)
517 *c
= (((*c
* 0x0802UL
& 0x22110UL
) |
518 (*c
* 0x8020UL
& 0x88440UL
)) * 0x10101UL
) >> 16;
521 gboolean
RrPixmapToRGBA(const RrInstance
*inst
,
522 Pixmap pmap
, Pixmap mask
,
523 gint
*w
, gint
*h
, RrPixel32
**data
)
527 guint pw
, ph
, mw
, mh
, xb
, xd
, i
, x
, y
, di
;
528 XImage
*xi
, *xm
= NULL
;
530 if (!XGetGeometry(RrDisplay(inst
), pmap
,
531 &xr
, &xx
, &xy
, &pw
, &ph
, &xb
, &xd
))
535 if (!XGetGeometry(RrDisplay(inst
), mask
,
536 &xr
, &xx
, &xy
, &mw
, &mh
, &xb
, &xd
))
538 if (pw
!= mw
|| ph
!= mh
|| xd
!= 1)
542 xi
= XGetImage(RrDisplay(inst
), pmap
,
543 0, 0, pw
, ph
, 0xffffffff, ZPixmap
);
548 xm
= XGetImage(RrDisplay(inst
), mask
,
549 0, 0, mw
, mh
, 0xffffffff, ZPixmap
);
554 if ((xm
->bits_per_pixel
== 1) && (xm
->bitmap_bit_order
!= LSBFirst
))
555 reverse_bits(xm
->data
, xm
->bytes_per_line
* xm
->height
);
558 if ((xi
->bits_per_pixel
== 1) && (xi
->bitmap_bit_order
!= LSBFirst
))
559 reverse_bits(xi
->data
, xi
->bytes_per_line
* xi
->height
);
561 *data
= g_new(RrPixel32
, pw
* ph
);
562 RrIncreaseDepth(inst
, *data
, xi
);
565 /* apply transparency from the mask */
567 for (i
= 0, y
= 0; y
< ph
; ++y
) {
568 for (x
= 0; x
< pw
; ++x
, ++i
) {
569 if (!((((unsigned)xm
->data
[di
+ x
/ 8]) >> (x
% 8)) & 0x1))
570 (*data
)[i
] &= ~(0xff << RrDefaultAlphaOffset
);
572 di
+= xm
->bytes_per_line
;
This page took 0.064124 seconds and 4 git commands to generate.