diff options
Diffstat (limited to 'kdm/kfrontend/themer/kdmpixmap.cpp')
-rw-r--r-- | kdm/kfrontend/themer/kdmpixmap.cpp | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/kdm/kfrontend/themer/kdmpixmap.cpp b/kdm/kfrontend/themer/kdmpixmap.cpp new file mode 100644 index 000000000..337c19ced --- /dev/null +++ b/kdm/kfrontend/themer/kdmpixmap.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2003 by Unai Garro <ugarro@users.sourceforge.net> + * Copyright (C) 2004 by Enrico Ros <rosenric@dei.unipd.it> + * Copyright (C) 2004 by Stephan Kulow <coolo@kde.org> + * Copyright (C) 2004 by Oswald Buddenhagen <ossi@kde.org> + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <config.h> + +#include "kdmpixmap.h" + +#include <kimageeffect.h> +#ifdef HAVE_LIBART +#include <ksvgiconengine.h> +#endif + +#include <kdebug.h> + +#include <qpainter.h> +#include <qpixmap.h> +#include <qimage.h> + +KdmPixmap::KdmPixmap( KdmItem *parent, const QDomNode &node, const char *name ) + : KdmItem( parent, node, name ) +{ + itemType = "pixmap"; + + // Set default values for pixmap (note: strings are already Null) + pixmap.normal.tint.setRgb( 0xFFFFFF ); + pixmap.normal.alpha = 1.0; + pixmap.active.present = false; + pixmap.prelight.present = false; + + // Read PIXMAP ID + // it rarely happens that a pixmap can be a button too! + QDomNode n = node; + QDomElement elPix = n.toElement(); + + // Read PIXMAP TAGS + QDomNodeList childList = node.childNodes(); + for (uint nod = 0; nod < childList.count(); nod++) { + QDomNode child = childList.item( nod ); + QDomElement el = child.toElement(); + QString tagName = el.tagName(); + + if (tagName == "normal") { + loadPixmap( el.attribute( "file", "" ), pixmap.normal.pixmap, pixmap.normal.fullpath ); + parseColor( el.attribute( "tint", "#ffffff" ), pixmap.normal.tint ); + pixmap.normal.alpha = el.attribute( "alpha", "1.0" ).toFloat(); + } else if (tagName == "active") { + pixmap.active.present = true; + loadPixmap( el.attribute( "file", "" ), pixmap.active.pixmap, pixmap.active.fullpath ); + parseColor( el.attribute( "tint", "#ffffff" ), pixmap.active.tint ); + pixmap.active.alpha = el.attribute( "alpha", "1.0" ).toFloat(); + } else if (tagName == "prelight") { + pixmap.prelight.present = true; + loadPixmap( el.attribute( "file", "" ), pixmap.prelight.pixmap, pixmap.prelight.fullpath ); + parseColor( el.attribute( "tint", "#ffffff" ), pixmap.prelight.tint ); + pixmap.prelight.alpha = el.attribute( "alpha", "1.0" ).toFloat(); + } + } +} + +QSize +KdmPixmap::sizeHint() +{ + // choose the correct pixmap class + PixmapStruct::PixmapClass * pClass = &pixmap.normal; + if (state == Sactive && pixmap.active.present) + pClass = &pixmap.active; + if (state == Sprelight && pixmap.prelight.present) + pClass = &pixmap.prelight; + // use the pixmap size as the size hint + if (!pClass->pixmap.isNull()) + return pClass->pixmap.size(); + return KdmItem::sizeHint(); +} + +void +KdmPixmap::setGeometry( const QRect &newGeometry, bool force ) +{ + KdmItem::setGeometry( newGeometry, force ); + pixmap.active.readyPixmap.resize( 0, 0 ); + pixmap.prelight.readyPixmap.resize( 0, 0 ); + pixmap.normal.readyPixmap.resize( 0, 0 ); +} + + +void +KdmPixmap::loadPixmap( const QString &fileName, QPixmap &map, QString &fullName ) +{ + if (fileName.isEmpty()) + return; + + fullName = fileName; + if (fullName.at( 0 ) != '/') + fullName = baseDir() + "/" + fileName; + + if (!fullName.endsWith( ".svg" )) // we delay it for svgs + if (!map.load( fullName )) + fullName = QString::null; +} + +void +KdmPixmap::renderSvg( PixmapStruct::PixmapClass *pClass, const QRect &area ) +{ +#ifdef HAVE_LIBART + // Special stuff for SVG icons + KSVGIconEngine *svgEngine = new KSVGIconEngine(); + + if (svgEngine->load( area.width(), area.height(), pClass->fullpath )) { + QImage *t = svgEngine->image(); + pClass->pixmap = *t; + pClass->readyPixmap.resize( 0, 0 ); + delete t; + } else { + kdWarning() << "failed to load " << pClass->fullpath << endl; + pClass->fullpath = QString::null; + } + + delete svgEngine; +#else + Q_UNUSED(pClass); + Q_UNUSED(area); +#endif +} + +void +KdmPixmap::drawContents( QPainter *p, const QRect &r ) +{ + // choose the correct pixmap class + PixmapStruct::PixmapClass *pClass = &pixmap.normal; + if (state == Sactive && pixmap.active.present) + pClass = &pixmap.active; + if (state == Sprelight && pixmap.prelight.present) + pClass = &pixmap.prelight; + + if (pClass->pixmap.isNull()) { + if (pClass->fullpath.isEmpty()) // if neither is set, we're empty + return; + + kdDebug() << "renderSVG\n"; + renderSvg( pClass, area ); + } + + int px = area.left() + r.left(); + int py = area.top() + r.top(); + int sx = r.x(); + int sy = r.y(); + int sw = r.width(); + int sh = r.height(); + if (px < 0) { + px *= -1; + sx += px; + px = 0; + } + if (py < 0) { + py *= -1; + sy += py; + py = 0; + } + + + if (pClass->readyPixmap.isNull()) { + QImage scaledImage; + + // use the loaded pixmap or a scaled version if needed + + if (area.size() != pClass->pixmap.size()) { + if (pClass->fullpath.endsWith( ".svg" )) { + kdDebug() << "renderSVG\n"; + renderSvg( pClass, area ); + scaledImage = pClass->pixmap.convertToImage(); + } else { + kdDebug() << "convertFromImage\n"; + QImage tempImage = pClass->pixmap.convertToImage(); + scaledImage = tempImage.smoothScale( area.width(), area.height() ); + } + } else + scaledImage = pClass->pixmap.convertToImage(); + + bool haveTint = pClass->tint.rgb() != 0xFFFFFF; + bool haveAlpha = pClass->alpha < 1.0; + + if (haveTint || haveAlpha) { + // blend image(pix) with the given tint + + scaledImage = scaledImage.convertDepth( 32 ); + int w = scaledImage.width(); + int h = scaledImage.height(); + float tint_red = float( pClass->tint.red() ) / 255; + float tint_green = float( pClass->tint.green() ) / 255; + float tint_blue = float( pClass->tint.blue() ) / 255; + float tint_alpha = pClass->alpha; + + for (int y = 0; y < h; ++y) { + QRgb *ls = (QRgb *)scaledImage.scanLine( y ); + for (int x = 0; x < w; ++x) { + QRgb l = ls[x]; + int r = int( qRed( l ) * tint_red ); + int g = int( qGreen( l ) * tint_green ); + int b = int( qBlue( l ) * tint_blue ); + int a = int( qAlpha( l ) * tint_alpha ); + ls[x] = qRgba( r, g, b, a ); + } + } + + } + + pClass->readyPixmap.convertFromImage( scaledImage ); + } + // kdDebug() << "Pixmap::drawContents " << pClass->readyPixmap.size() << " " << px << " " << py << " " << sx << " " << sy << " " << sw << " " << sh << endl; + p->drawPixmap( px, py, pClass->readyPixmap, sx, sy, sw, sh ); +} + +void +KdmPixmap::statusChanged() +{ + KdmItem::statusChanged(); + if (!pixmap.active.present && !pixmap.prelight.present) + return; + if ((state == Sprelight && !pixmap.prelight.present) || + (state == Sactive && !pixmap.active.present)) + return; + needUpdate(); +} + +#include "kdmpixmap.moc" |