X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=render%2Frender.c;h=2147df01639b3480945b84d84f3e8f2b448b38d0;hb=c313b219a226c3b968ff312b96120eef0c527d91;hp=dea04cf4bdfe94c6921481d0da549f3beaea266c;hpb=768c3cd4a9fba291e49f4706829d2021d0952aa8;p=chaz%2Fopenbox diff --git a/render/render.c b/render/render.c index dea04cf4..2147df01 100644 --- a/render/render.c +++ b/render/render.c @@ -1,5 +1,22 @@ -#include -#include +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + render.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana 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 "gradient.h" @@ -10,125 +27,141 @@ #include "theme.h" #include +#include +#include +#include #ifdef HAVE_STDLIB_H # include #endif -static void RrPixel32_to_pixmap(RrAppearance *l, gint x, gint y, gint w, gint h); +static void pixel_data_to_pixmap(RrAppearance *l, + gint x, gint y, gint w, gint h); -void RrPaint(RrAppearance *l, Window win, gint w, gint h) +Pixmap RrPaintPixmap(RrAppearance *a, gint w, gint h) { - int i, transferred = 0, sw; - RrPixel32 *source, *dest; - Pixmap oldp; - Rect tarea; /* area in which to draw textures */ + gint i, transferred = 0, force_transfer = 0; + Pixmap oldp = None; + RrRect tarea; /* area in which to draw textures */ gboolean resized; - if (w <= 0 || h <= 0) return; + if (w <= 0 || h <= 0) return None; - resized = (l->w != w || l->h != h); + if (a->surface.parentx < 0 || a->surface.parenty < 0) { + /* ob_debug("Invalid parent co-ordinates\n"); */ + return None; + } + + if (a->surface.grad == RR_SURFACE_PARENTREL && + (a->surface.parentx >= a->surface.parent->w || + a->surface.parenty >= a->surface.parent->h)) + { + return None; + } + + resized = (a->w != w || a->h != h); + + oldp = a->pixmap; /* save to free after changing the visible pixmap */ + a->pixmap = XCreatePixmap(RrDisplay(a->inst), + RrRootWindow(a->inst), + w, h, RrDepth(a->inst)); + + g_assert(a->pixmap != None); + a->w = w; + a->h = h; + + if (a->xftdraw != NULL) + XftDrawDestroy(a->xftdraw); + a->xftdraw = XftDrawCreate(RrDisplay(a->inst), a->pixmap, + RrVisual(a->inst), RrColormap(a->inst)); + g_assert(a->xftdraw != NULL); if (resized) { - oldp = l->pixmap; /* save to free after changing the visible pixmap */ - l->pixmap = XCreatePixmap(RrDisplay(l->inst), - RrRootWindow(l->inst), - w, h, RrDepth(l->inst)); - } else - oldp = None; - - g_assert(l->pixmap != None); - l->w = w; - l->h = h; - - if (l->xftdraw != NULL) - XftDrawDestroy(l->xftdraw); - l->xftdraw = XftDrawCreate(RrDisplay(l->inst), l->pixmap, - RrVisual(l->inst), RrColormap(l->inst)); - g_assert(l->xftdraw != NULL); - - g_free(l->surface.RrPixel_data); - l->surface.RrPixel_data = g_new(RrPixel32, w * h); - - if (l->surface.grad == RR_SURFACE_PARENTREL) { - g_assert (l->surface.parent); - g_assert (l->surface.parent->w); - - sw = l->surface.parent->w; - source = (l->surface.parent->surface.RrPixel_data + l->surface.parentx + - sw * l->surface.parenty); - dest = l->surface.RrPixel_data; - for (i = 0; i < h; i++, source += sw, dest += w) { - memcpy(dest, source, w * sizeof(RrPixel32)); - } - } else if (l->surface.grad == RR_SURFACE_SOLID) - gradient_solid(l, 0, 0, w, h); - else - gradient_render(&l->surface, w, h); - - RECT_SET(tarea, 0, 0, w, h); - if (l->surface.grad != RR_SURFACE_PARENTREL) { - if (l->surface.relief != RR_RELIEF_FLAT) { - switch (l->surface.bevel) { - case RR_BEVEL_1: - tarea.x += 1; tarea.y += 1; - tarea.width -= 2; tarea.height -= 2; - break; - case RR_BEVEL_2: - tarea.x += 2; tarea.y += 2; - tarea.width -= 4; tarea.height -= 4; - break; - } - } else if (l->surface.border) { - tarea.x += 1; tarea.y += 1; - tarea.width -= 2; tarea.height -= 2; - } + g_free(a->surface.pixel_data); + a->surface.pixel_data = g_new(RrPixel32, w * h); } - for (i = 0; i < l->textures; i++) { - switch (l->texture[i].type) { + RrRender(a, w, h); + + { + gint l, t, r, b; + RrMargins(a, &l, &t, &r, &b); + RECT_SET(tarea, l, t, w - l - r, h - t - b); + } + + for (i = 0; i < a->textures; i++) { + switch (a->texture[i].type) { case RR_TEXTURE_NONE: break; case RR_TEXTURE_TEXT: if (!transferred) { transferred = 1; - if (l->surface.grad != RR_SURFACE_SOLID) - RrPixel32_to_pixmap(l, 0, 0, w, h); + if ((a->surface.grad != RR_SURFACE_SOLID) + || (a->surface.interlaced)) + pixel_data_to_pixmap(a, 0, 0, w, h); } - if (l->xftdraw == NULL) { - l->xftdraw = XftDrawCreate(RrDisplay(l->inst), l->pixmap, - RrVisual(l->inst), - RrColormap(l->inst)); + if (a->xftdraw == NULL) { + a->xftdraw = XftDrawCreate(RrDisplay(a->inst), a->pixmap, + RrVisual(a->inst), + RrColormap(a->inst)); } - RrFontDraw(l->xftdraw, &l->texture[i].data.text, &tarea); - break; + RrFontDraw(a->xftdraw, &a->texture[i].data.text, &tarea); + break; + case RR_TEXTURE_LINE_ART: + if (!transferred) { + transferred = 1; + if ((a->surface.grad != RR_SURFACE_SOLID) + || (a->surface.interlaced)) + pixel_data_to_pixmap(a, 0, 0, w, h); + } + XDrawLine(RrDisplay(a->inst), a->pixmap, + RrColorGC(a->texture[i].data.lineart.color), + a->texture[i].data.lineart.x1, + a->texture[i].data.lineart.y1, + a->texture[i].data.lineart.x2, + a->texture[i].data.lineart.y2); + break; case RR_TEXTURE_MASK: if (!transferred) { transferred = 1; - if (l->surface.grad != RR_SURFACE_SOLID) - RrPixel32_to_pixmap(l, 0, 0, w, h); + if ((a->surface.grad != RR_SURFACE_SOLID) + || (a->surface.interlaced)) + pixel_data_to_pixmap(a, 0, 0, w, h); } - if (l->texture[i].data.mask.color->gc == None) - RrColorAllocateGC(l->texture[i].data.mask.color); - RrPixmapMaskDraw(l->pixmap, &l->texture[i].data.mask, &tarea); - break; + RrPixmapMaskDraw(a->pixmap, &a->texture[i].data.mask, &tarea); + break; case RR_TEXTURE_RGBA: - RrImageDraw(l->surface.RrPixel_data, - &l->texture[i].data.rgba, &tarea); + g_assert(!transferred); + RrImageDraw(a->surface.pixel_data, + &a->texture[i].data.rgba, + a->w, a->h, + &tarea); + force_transfer = 1; break; } } if (!transferred) { transferred = 1; - if (l->surface.grad != RR_SURFACE_SOLID) - RrPixel32_to_pixmap(l, 0, 0, w, h); + if ((a->surface.grad != RR_SURFACE_SOLID) || (a->surface.interlaced) || + force_transfer) + { + pixel_data_to_pixmap(a, 0, 0, w, h); + } } + return oldp; +} + +void RrPaint(RrAppearance *a, Window win, gint w, gint h) +{ + Pixmap oldp; - XSetWindowBackgroundPixmap(RrDisplay(l->inst), win, l->pixmap); - XClearWindow(RrDisplay(l->inst), win); - if (oldp) XFreePixmap(RrDisplay(l->inst), oldp); + oldp = RrPaintPixmap(a, w, h); + XSetWindowBackgroundPixmap(RrDisplay(a->inst), win, a->pixmap); + XClearWindow(RrDisplay(a->inst), win); + /* free this after changing the visible pixmap */ + if (oldp) XFreePixmap(RrDisplay(a->inst), oldp); } RrAppearance *RrAppearanceNew(const RrInstance *inst, gint numtex) @@ -138,15 +171,34 @@ RrAppearance *RrAppearanceNew(const RrInstance *inst, gint numtex) out = g_new0(RrAppearance, 1); out->inst = inst; out->textures = numtex; + out->surface.bevel_light_adjust = 128; + out->surface.bevel_dark_adjust = 64; if (numtex) out->texture = g_new0(RrTexture, numtex); return out; } +void RrAppearanceRemoveTextures(RrAppearance *a) +{ + gint i; + + g_free(a->texture); + a->textures = 0; +} + +void RrAppearanceAddTextures(RrAppearance *a, gint numtex) +{ + g_assert(a->textures == 0); + + a->textures = numtex; + if (numtex) a->texture = g_new0(RrTexture, numtex); +} + RrAppearance *RrAppearanceCopy(RrAppearance *orig) { RrSurface *spo, *spc; RrAppearance *copy = g_new(RrAppearance, 1); + gint i; copy->inst = orig->inst; @@ -158,7 +210,7 @@ RrAppearance *RrAppearanceCopy(RrAppearance *orig) if (spo->primary != NULL) spc->primary = RrColorNew(copy->inst, spo->primary->r, - spo->primary->g, + spo->primary->g, spo->primary->b); else spc->primary = NULL; @@ -176,6 +228,13 @@ RrAppearance *RrAppearanceCopy(RrAppearance *orig) spo->border_color->b); else spc->border_color = NULL; + if (spo->interlace_color != NULL) + spc->interlace_color = RrColorNew(copy->inst, + spo->interlace_color->r, + spo->interlace_color->g, + spo->interlace_color->b); + else spc->interlace_color = NULL; + if (spo->bevel_dark != NULL) spc->bevel_dark = RrColorNew(copy->inst, spo->bevel_dark->r, @@ -190,13 +249,35 @@ RrAppearance *RrAppearanceCopy(RrAppearance *orig) spo->bevel_light->b); else spc->bevel_light = NULL; + if (spo->split_primary != NULL) + spc->split_primary = RrColorNew(copy->inst, + spo->split_primary->r, + spo->split_primary->g, + spo->split_primary->b); + else spc->split_primary = NULL; + + if (spo->split_secondary != NULL) + spc->split_secondary = RrColorNew(copy->inst, + spo->split_secondary->r, + spo->split_secondary->g, + spo->split_secondary->b); + else spc->split_secondary = NULL; + spc->interlaced = spo->interlaced; + spc->bevel_light_adjust = spo->bevel_light_adjust; + spc->bevel_dark_adjust = spo->bevel_dark_adjust; spc->border = spo->border; - spc->RrPixel_data = NULL; + spc->parent = NULL; + spc->parentx = spc->parenty = 0; + spc->pixel_data = NULL; copy->textures = orig->textures; copy->texture = g_memdup(orig->texture, orig->textures * sizeof(RrTexture)); + for (i = 0; i < copy->textures; ++i) + if (copy->texture[i].type == RR_TEXTURE_RGBA) { + copy->texture[i].data.rgba.cache = NULL; + } copy->pixmap = None; copy->xftdraw = NULL; copy->w = copy->h = 0; @@ -205,26 +286,37 @@ RrAppearance *RrAppearanceCopy(RrAppearance *orig) void RrAppearanceFree(RrAppearance *a) { + gint i; + if (a) { RrSurface *p; if (a->pixmap != None) XFreePixmap(RrDisplay(a->inst), a->pixmap); if (a->xftdraw != NULL) XftDrawDestroy(a->xftdraw); + for (i = 0; i < a->textures; ++i) + if (a->texture[i].type == RR_TEXTURE_RGBA) { + g_free(a->texture[i].data.rgba.cache); + a->texture[i].data.rgba.cache = NULL; + } if (a->textures) g_free(a->texture); p = &a->surface; RrColorFree(p->primary); RrColorFree(p->secondary); RrColorFree(p->border_color); + RrColorFree(p->interlace_color); RrColorFree(p->bevel_dark); RrColorFree(p->bevel_light); - g_free(p->RrPixel_data); - + RrColorFree(p->split_primary); + RrColorFree(p->split_secondary); + g_free(p->pixel_data); + p->pixel_data = NULL; g_free(a); } } -static void RrPixel32_to_pixmap(RrAppearance *l, gint x, gint y, gint w, gint h) +static void pixel_data_to_pixmap(RrAppearance *l, + gint x, gint y, gint w, gint h) { RrPixel32 *in, *scratch; Pixmap out; @@ -233,15 +325,14 @@ static void RrPixel32_to_pixmap(RrAppearance *l, gint x, gint y, gint w, gint h) ZPixmap, 0, NULL, w, h, 32, 0); g_assert(im != NULL); - in = l->surface.RrPixel_data; + in = l->surface.pixel_data; out = l->pixmap; - im->byte_order = RrEndian; /* this malloc is a complete waste of time on normal 32bpp as reduce_depth just sets im->data = data and returns */ scratch = g_new(RrPixel32, im->width * im->height); - im->data = (char*) scratch; + im->data = (gchar*) scratch; RrReduceDepth(l->inst, in, im); XPutImage(RrDisplay(l->inst), out, DefaultGC(RrDisplay(l->inst), RrScreen(l->inst)), @@ -251,56 +342,114 @@ static void RrPixel32_to_pixmap(RrAppearance *l, gint x, gint y, gint w, gint h) g_free(scratch); } -void RrMinsize(RrAppearance *l, gint *w, gint *h) +void RrMargins (RrAppearance *a, gint *l, gint *t, gint *r, gint *b) +{ + *l = *t = *r = *b = 0; + + if (a->surface.grad != RR_SURFACE_PARENTREL) { + if (a->surface.relief != RR_RELIEF_FLAT) { + switch (a->surface.bevel) { + case RR_BEVEL_1: + *l = *t = *r = *b = 1; + break; + case RR_BEVEL_2: + *l = *t = *r = *b = 2; + break; + } + } else if (a->surface.border) { + *l = *t = *r = *b = 1; + } + } +} + +void RrMinSize(RrAppearance *a, gint *w, gint *h) +{ + *w = RrMinWidth(a); + *h = RrMinHeight(a); +} + +gint RrMinWidth(RrAppearance *a) { gint i; - gint m; - *w = *h = 0; + RrSize *m; + gint l, t, r, b; + gint w = 0; - for (i = 0; i < l->textures; ++i) { - switch (l->texture[i].type) { + for (i = 0; i < a->textures; ++i) { + switch (a->texture[i].type) { case RR_TEXTURE_NONE: break; case RR_TEXTURE_MASK: - *w = MAX(*w, l->texture[i].data.mask.mask->width); - *h = MAX(*h, l->texture[i].data.mask.mask->height); + w = MAX(w, a->texture[i].data.mask.mask->width); break; case RR_TEXTURE_TEXT: - m = RrFontMeasureString(l->texture[i].data.text.font, - l->texture[i].data.text.string, - l->texture[i].data.text.shadow, - l->texture[i].data.text.offset); - *w = MAX(*w, m); - m = RrFontHeight(l->texture[i].data.text.font, - l->texture[i].data.text.shadow, - l->texture[i].data.text.offset); - *h += MAX(*h, m); + m = RrFontMeasureString(a->texture[i].data.text.font, + a->texture[i].data.text.string, + a->texture[i].data.text.shadow_offset_x, + a->texture[i].data.text.shadow_offset_y, + a->texture[i].data.text.maxwidth); + w = MAX(w, m->width); + g_free(m); break; case RR_TEXTURE_RGBA: - *w += MAX(*w, l->texture[i].data.rgba.width); - *h += MAX(*h, l->texture[i].data.rgba.height); + w += MAX(w, a->texture[i].data.rgba.width); + break; + case RR_TEXTURE_LINE_ART: + w += MAX(w, MAX(a->texture[i].data.lineart.x1, + a->texture[i].data.lineart.x2)); break; } } - if (l->surface.relief != RR_RELIEF_FLAT) { - switch (l->surface.bevel) { - case RR_BEVEL_1: - *w += 2; - *h += 2; + RrMargins(a, &l, &t, &r, &b); + + w += l + r; + + if (w < 1) w = 1; + return w; +} + +gint RrMinHeight(RrAppearance *a) +{ + gint i; + gint l, t, r, b; + gint h = 0; + + for (i = 0; i < a->textures; ++i) { + switch (a->texture[i].type) { + case RR_TEXTURE_NONE: + break; + case RR_TEXTURE_MASK: + h = MAX(h, a->texture[i].data.mask.mask->height); + break; + case RR_TEXTURE_TEXT: + h += MAX(h, RrFontHeight(a->texture[i].data.text.font, + a->texture[i].data.text.shadow_offset_y)); break; - case RR_BEVEL_2: - *w += 4; - *h += 4; + case RR_TEXTURE_RGBA: + h += MAX(h, a->texture[i].data.rgba.height); + break; + case RR_TEXTURE_LINE_ART: + h += MAX(h, MAX(a->texture[i].data.lineart.y1, + a->texture[i].data.lineart.y2)); break; } - } else if (l->surface.border) { - *w += 2; - *h += 2; } - if (*w < 1) *w = 1; - if (*h < 1) *h = 1; + RrMargins(a, &l, &t, &r, &b); + + h += t + b; + + if (h < 1) h = 1; + return h; +} + +static void reverse_bits(gchar *c, gint n) +{ + gint i; + for (i = 0; i < n; i++, c++) + *c = (((*c * 0x0802UL & 0x22110UL) | + (*c * 0x8020UL & 0x88440UL)) * 0x10101UL) >> 16; } gboolean RrPixmapToRGBA(const RrInstance *inst, @@ -312,9 +461,10 @@ gboolean RrPixmapToRGBA(const RrInstance *inst, guint pw, ph, mw, mh, xb, xd, i, x, y, di; XImage *xi, *xm = NULL; - if (!XGetGeometry(RrDisplay(inst), - pmap, &xr, &xx, &xy, &pw, &ph, &xb, &xd)) + if (!XGetGeometry(RrDisplay(inst), pmap, + &xr, &xx, &xy, &pw, &ph, &xb, &xd)) return FALSE; + if (mask) { if (!XGetGeometry(RrDisplay(inst), mask, &xr, &xx, &xy, &mw, &mh, &xb, &xd)) @@ -331,10 +481,17 @@ gboolean RrPixmapToRGBA(const RrInstance *inst, if (mask) { xm = XGetImage(RrDisplay(inst), mask, 0, 0, mw, mh, 0xffffffff, ZPixmap); - if (!xm) + if (!xm) { + XDestroyImage(xi); return FALSE; + } + if ((xm->bits_per_pixel == 1) && (xm->bitmap_bit_order != LSBFirst)) + reverse_bits(xm->data, xm->bytes_per_line * xm->height); } + if ((xi->bits_per_pixel == 1) && (xi->bitmap_bit_order != LSBFirst)) + reverse_bits(xi->data, xi->bytes_per_line * xi->height); + *data = g_new(RrPixel32, pw * ph); RrIncreaseDepth(inst, *data, xi); @@ -353,5 +510,9 @@ gboolean RrPixmapToRGBA(const RrInstance *inst, *w = pw; *h = ph; + XDestroyImage(xi); + if (mask) + XDestroyImage(xm); + return TRUE; }