diff options
Diffstat (limited to 'src/libs/themeengine/texture.cpp')
-rw-r--r-- | src/libs/themeengine/texture.cpp | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/src/libs/themeengine/texture.cpp b/src/libs/themeengine/texture.cpp new file mode 100644 index 00000000..e728dd59 --- /dev/null +++ b/src/libs/themeengine/texture.cpp @@ -0,0 +1,495 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-07-26 + * Description : texture pixmap methods + * + * Copyright (C) 2004 by Renchi Raju <[email protected]> + * + * Adapted from fluxbox: Texture/TextureRender + * + * Texture.cc for Fluxbox Window Manager + * Copyright (c) 2002-2003 Henrik Kinnunen <[email protected]> + * + * from Image.cc for Blackbox - an X11 Window manager + * Copyright (c) 1997 - 2000 Brad Hughes ([email protected]) + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * + * ============================================================ */ + +// C++ includes. + +#include <cstring> +#include <cstdio> + +// TQt includes. + +#include <tqpainter.h> +#include <tqimage.h> +#include <tqpixmap.h> + +// Local includes. + +#include "theme.h" +#include "texture.h" + +namespace Digikam +{ + +class TexturePriv +{ +public: + + TexturePriv() + { + red = 0; + green = 0; + blue = 0; + } + + bool border; + + unsigned char *red; + unsigned char *green; + unsigned char *blue; + + int width; + int height; + + TQPixmap pixmap; + + TQColor color0; + TQColor color1; + TQColor borderColor; + + Theme::Bevel bevel; + Theme::Gradient gradient; +}; + +Texture::Texture(int w, int h, const TQColor& from, const TQColor& to, + Theme::Bevel bevel, Theme::Gradient gradient, + bool border, const TQColor& borderColor) +{ + d = new TexturePriv; + + d->bevel = bevel; + d->gradient = gradient; + d->border = border; + d->borderColor = borderColor; + + if (!border) + { + d->width = w; + d->height = h; + } + else + { + d->width = w-2; + d->height = h-2; + } + + if (d->width <= 0 || d->height <= 0) + return; + + if (bevel & Theme::SUNKEN) + { + d->color0 = to; + d->color1 = from; + } + else + { + d->color0 = from; + d->color1 = to; + } + + if (gradient == Theme::SOLID) + { + doSolid(); + } + else + { + d->red = new unsigned char[w*h]; + d->green = new unsigned char[w*h]; + d->blue = new unsigned char[w*h]; + + if (gradient == Theme::HORIZONTAL) + doHgradient(); + else if (gradient == Theme::VERTICAL) + doVgradient(); + else if (gradient == Theme::DIAGONAL) + doDgradient(); + + if (bevel & Theme::RAISED || bevel & Theme::SUNKEN) + doBevel(); + + buildImage(); + } +} + +Texture::~Texture() +{ + if (d->red) + delete [] d->red; + if (d->green) + delete [] d->green; + if (d->blue) + delete [] d->blue; + + delete d; +} + +TQPixmap Texture::renderPixmap() const +{ + if (d->width <= 0 || d->height <= 0) + return TQPixmap(); + + if (!d->border) + return d->pixmap; + + TQPixmap pix(d->width+2, d->height+2); + bitBlt(&pix, 1, 1, &d->pixmap, 0, 0); + TQPainter p(&pix); + p.setPen(d->borderColor); + p.drawRect(0, 0, d->width+2, d->height+2); + p.end(); + + return pix; +} + +void Texture::doSolid() +{ + d->pixmap.resize(d->width, d->height); + TQPainter p(&d->pixmap); + p.fillRect(0, 0, d->width, d->height, d->color0); + if (d->bevel == Theme::RAISED) + { + p.setPen(d->color0.light(120)); + p.drawLine(0, 0, d->width-1, 0); // top + p.drawLine(0, 0, 0, d->height-1); // left + p.setPen(d->color0.dark(120)); + p.drawLine(0, d->height-1, d->width-1, d->height-1); // bottom + p.drawLine(d->width-1, 0, d->width-1, d->height-1); // right + } + else if (d->bevel == Theme::SUNKEN) + { + p.setPen(d->color0.dark(120)); + p.drawLine(0, 0, d->width-1, 0); // top + p.drawLine(0, 0, 0, d->height-1); // left + p.setPen(d->color0.light(120)); + p.drawLine(0, d->height-1, d->width-1, d->height-1); // bottom + p.drawLine(d->width-1, 0, d->width-1, d->height-1); // right + } + p.end(); +} + +void Texture::doHgradient() +{ + float drx, dgx, dbx, + xr = (float) d->color0.red(), + xg = (float) d->color0.green(), + xb = (float) d->color0.blue(); + unsigned char *pr = d->red, *pg = d->green, *pb = d->blue; + + int x, y; + + drx = (float) (d->color1.red() - d->color0.red()); + dgx = (float) (d->color1.green() - d->color0.green()); + dbx = (float) (d->color1.blue() - d->color0.blue()); + + drx /= d->width; + dgx /= d->width; + dbx /= d->width; + + for (x = 0; x < d->width; x++) + { + *(pr++) = (unsigned char) (xr); + *(pg++) = (unsigned char) (xg); + *(pb++) = (unsigned char) (xb); + + xr += drx; + xg += dgx; + xb += dbx; + } + + for (y = 1; y < d->height; y++, pr += d->width, pg += d->width, pb += d->width) + { + memcpy(pr, d->red, d->width); + memcpy(pg, d->green, d->width); + memcpy(pb, d->blue, d->width); + } +} + +void Texture::doVgradient() +{ + float dry, dgy, dby, + yr = (float) d->color0.red(), + yg = (float) d->color0.green(), + yb = (float) d->color0.blue(); + + dry = (float) (d->color1.red() - d->color0.red()); + dgy = (float) (d->color1.green() - d->color0.green()); + dby = (float) (d->color1.blue() - d->color0.blue()); + + dry /= d->height; + dgy /= d->height; + dby /= d->height; + + unsigned char *pr = d->red, *pg = d->green, *pb = d->blue; + int y; + + for (y = 0; y < d->height; y++, pr += d->width, pg += d->width, pb += d->width) { + memset(pr, (unsigned char) yr, d->width); + memset(pg, (unsigned char) yg, d->width); + memset(pb, (unsigned char) yb, d->width); + + yr += dry; + yg += dgy; + yb += dby; + } +} + +void Texture::doDgradient() +{ + unsigned int* xtable = new unsigned int[d->width*3]; + unsigned int* ytable = new unsigned int[d->height*3]; + + float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0, + xr = (float) d->color0.red(), + xg = (float) d->color0.green(), + xb = (float) d->color0.blue(); + unsigned char *pr = d->red, *pg = d->green, *pb = d->blue; + unsigned int w = d->width * 2, h = d->height * 2; + unsigned int *xt = xtable; + unsigned int *yt = ytable; + + int x, y; + + dry = drx = (float) (d->color1.red() - d->color0.red()); + dgy = dgx = (float) (d->color1.green() - d->color0.green()); + dby = dbx = (float) (d->color1.blue() - d->color0.blue()); + + // Create X table + drx /= w; + dgx /= w; + dbx /= w; + + for (x = 0; x < d->width; x++) + { + *(xt++) = (unsigned char) (xr); + *(xt++) = (unsigned char) (xg); + *(xt++) = (unsigned char) (xb); + + xr += drx; + xg += dgx; + xb += dbx; + } + + // Create Y table + dry /= h; + dgy /= h; + dby /= h; + + for (y = 0; y < d->height; y++) + { + *(yt++) = ((unsigned char) yr); + *(yt++) = ((unsigned char) yg); + *(yt++) = ((unsigned char) yb); + + yr += dry; + yg += dgy; + yb += dby; + } + + // Combine tables to create gradient + + for (yt = ytable, y = 0; y < d->height; y++, yt += 3) + { + for (xt = xtable, x = 0; x < d->width; x++) + { + *(pr++) = *(xt++) + *(yt); + *(pg++) = *(xt++) + *(yt + 1); + *(pb++) = *(xt++) + *(yt + 2); + } + } + + delete [] xtable; + delete [] ytable; +} + +void Texture::doBevel() +{ + unsigned char *pr = d->red, *pg = d->green, *pb = d->blue; + + unsigned char r, g, b, rr ,gg ,bb; + unsigned int w = d->width, h = d->height - 1, wh = w * h; + + while (--w) + { + r = *pr; + rr = r + (r >> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; + + *pr = rr; + *pg = gg; + *pb = bb; + + r = *(pr + wh); + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *(pg + wh); + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *(pb + wh); + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; + + *((pr++) + wh) = rr; + *((pg++) + wh) = gg; + *((pb++) + wh) = bb; + } + + r = *pr; + rr = r + (r >> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; + + *pr = rr; + *pg = gg; + *pb = bb; + + r = *(pr + wh); + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *(pg + wh); + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *(pb + wh); + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; + + *(pr + wh) = rr; + *(pg + wh) = gg; + *(pb + wh) = bb; + + pr = d->red + d->width; + pg = d->green + d->width; + pb = d->blue + d->width; + + while (--h) + { + r = *pr; + rr = r + (r >> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; + + *pr = rr; + *pg = gg; + *pb = bb; + + pr += d->width - 1; + pg += d->width - 1; + pb += d->width - 1; + + r = *pr; + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *pg; + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *pb; + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; + + *(pr++) = rr; + *(pg++) = gg; + *(pb++) = bb; + } + + r = *pr; + rr = r + (r >> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; + + *pr = rr; + *pg = gg; + *pb = bb; + + pr += d->width - 1; + pg += d->width - 1; + pb += d->width - 1; + + r = *pr; + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *pg; + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *pb; + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; + + *pr = rr; + *pg = gg; + *pb = bb; +} + +void Texture::buildImage() +{ + unsigned char *pr = d->red, *pg = d->green, *pb = d->blue; + + TQImage image(d->width, d->height, 32); + + unsigned int* bits = (unsigned int*) image.bits(); + + int p; + for (p =0; p < d->width*d->height; p++) + { + *bits = 0xff << 24 | *pr << 16 | *pg << 8 | *pb; + bits++; + pr++; + pg++; + pb++; + } + + d->pixmap = TQPixmap(image); +} + +} // NameSpace Digikam |