You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
496 lines
11 KiB
496 lines
11 KiB
/* ============================================================
|
|
*
|
|
* 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 <renchi@pooh.tam.uiuc.edu>
|
|
*
|
|
* Adapted from fluxbox: Texture/TextureRender
|
|
*
|
|
* Texture.cc for Fluxbox Window Manager
|
|
* Copyright (c) 2002-2003 Henrik Kinnunen <fluxbox@users.sourceforge.net>
|
|
*
|
|
* 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 <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
|