/* ============================================================ * * 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 * * Adapted from fluxbox: Texture/TextureRender * * Texture.cc for Fluxbox Window Manager * Copyright (c) 2002-2003 Henrik Kinnunen * * from Image.cc for Blackbox - an X11 Window manager * Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) * * 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 #include // TQt includes. #include #include #include // 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