• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

Plasma

paintutils.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2005 by Aaron Seigo <aseigo@kde.org>
00003  *   Copyright 2008 by Andrew Lake <jamboarder@yahoo.com>
00004  *
00005  *   This program is free software; you can redistribute it and/or modify
00006  *   it under the terms of the GNU Library General Public License as
00007  *   published by the Free Software Foundation; either version 2, or
00008  *   (at your option) any later version.
00009  *
00010  *   This program is distributed in the hope that it will be useful,
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *   GNU General Public License for more details
00014  *
00015  *   You should have received a copy of the GNU Library General Public
00016  *   License along with this program; if not, write to the
00017  *   Free Software Foundation, Inc.,
00018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  */
00020 
00021 #include <paintutils.h>
00022 
00023 #include <QImage>
00024 #include <QPainter>
00025 #include <QPaintEngine>
00026 #include <QPixmap>
00027 
00028 #include "private/effects/blur.cpp"
00029 #include "private/effects/halopainter_p.h"
00030 
00031 namespace Plasma
00032 {
00033 
00034 namespace PaintUtils
00035 {
00036 
00037 void shadowBlur(QImage &image, int radius, const QColor &color)
00038 {
00039     if (radius < 1) {
00040         return;
00041     }
00042     if (image.isNull()) {
00043         return;
00044     }
00045 
00046     expblur<16, 7>(image, radius);
00047 
00048     QPainter p(&image);
00049     p.setCompositionMode(QPainter::CompositionMode_SourceIn);
00050     p.fillRect(image.rect(), color);
00051     p.end();
00052 }
00053 
00054 //TODO: we should have shadowText methods that paint the results directly into a QPainter passed in
00055 QPixmap shadowText(QString text, QColor textColor, QColor shadowColor, QPoint offset, int radius)
00056 {
00057     return shadowText(text, qApp->font(), textColor, shadowColor, offset, radius);
00058 }
00059 
00060 QPixmap shadowText(QString text, const QFont &font, QColor textColor, QColor shadowColor, QPoint offset, int radius)
00061 {
00062     //don't try to paint stuff on a future null pixmap because the text is empty
00063     if (text.isEmpty()) {
00064         return QPixmap();
00065     }
00066 
00067     // Draw text
00068     QFontMetrics fm(font);
00069     QRect textRect = fm.boundingRect(text);
00070     QPixmap textPixmap(textRect.width(), fm.height());
00071     textPixmap.fill(Qt::transparent);
00072     QPainter p(&textPixmap);
00073     p.setPen(textColor);
00074     p.setFont(font);
00075     // FIXME: the center alignment here is odd: the rect should be the size needed by
00076     //        the text, but for some fonts and configurations this is off by a pixel or so
00077     //        and "centering" the text painting 'fixes' that. Need to research why
00078     //        this is the case and determine if we should be painting it differently here,
00079     //        doing soething different with the boundingRect call or if it's a problem
00080     //        in Qt itself
00081     p.drawText(textPixmap.rect(), Qt::AlignCenter, text);
00082     p.end();
00083 
00084     //Draw blurred shadow
00085     QImage img(textRect.size() + QSize(radius * 2, radius * 2), QImage::Format_ARGB32_Premultiplied);
00086     img.fill(0);
00087     p.begin(&img);
00088     p.drawImage(QPoint(radius, radius), textPixmap.toImage());
00089     p.end();
00090     shadowBlur(img, radius, shadowColor);
00091 
00092     //Compose text and shadow
00093     int addSizeX = qMax(0, qAbs(offset.x()) - radius);
00094     int addSizeY = qMax(0, qAbs(offset.y()) - radius);
00095 
00096     QPixmap finalPixmap(img.size() + QSize(addSizeX, addSizeY));
00097     finalPixmap.fill(Qt::transparent);
00098     p.begin(&finalPixmap);
00099     p.drawImage(qMax(0, offset.x()), qMax(0, offset.y()), img);
00100     p.drawPixmap(radius + qMax(0, -offset.x()), radius + qMax(0, -offset.y()), textPixmap);
00101     p.end();
00102 
00103     return finalPixmap;
00104 }
00105 
00106 void drawHalo(QPainter *painter, const QRectF &rect)
00107 {
00108     HaloPainter::instance()->drawHalo(painter, rect.toRect());
00109 }
00110 
00111 QPainterPath roundedRectangle(const QRectF &rect, qreal radius)
00112 {
00113     QPainterPath path(QPointF(rect.left(), rect.top() + radius));
00114     path.quadTo(rect.left(), rect.top(), rect.left() + radius, rect.top());         // Top left corner
00115     path.lineTo(rect.right() - radius, rect.top());                                 // Top side
00116     path.quadTo(rect.right(), rect.top(), rect.right(), rect.top() + radius);       // Top right corner
00117     path.lineTo(rect.right(), rect.bottom() - radius);                              // Right side
00118     path.quadTo(rect.right(), rect.bottom(), rect.right() - radius, rect.bottom()); // Bottom right corner
00119     path.lineTo(rect.left() + radius, rect.bottom());                               // Bottom side
00120     path.quadTo(rect.left(), rect.bottom(), rect.left(), rect.bottom() - radius);   // Bottom left corner
00121     path.closeSubpath();
00122 
00123     return path;
00124 }
00125 
00126 void centerPixmaps(QPixmap &from, QPixmap &to)
00127 {
00128     if (from.size() == to.size() && from.hasAlphaChannel() && to.hasAlphaChannel()) {
00129         return;
00130     }
00131 
00132     QRect fromRect(from.rect());
00133     QRect toRect(to.rect());
00134  
00135     QRect actualRect = QRect(QPoint(0,0), fromRect.size().expandedTo(toRect.size()));
00136     fromRect.moveCenter(actualRect.center());
00137     toRect.moveCenter(actualRect.center());
00138 
00139     if (from.size() != actualRect.size() || !from.hasAlphaChannel()) {
00140         QPixmap result(actualRect.size());
00141         result.fill(Qt::transparent);
00142         QPainter p(&result);
00143         p.setCompositionMode(QPainter::CompositionMode_Source);
00144         p.drawPixmap(fromRect.topLeft(), from);
00145         p.end();
00146         from = result;
00147     }
00148 
00149     if (to.size() != actualRect.size() || !to.hasAlphaChannel()) {
00150         QPixmap result(actualRect.size());
00151         result.fill(Qt::transparent);
00152         QPainter p(&result);
00153         p.setCompositionMode(QPainter::CompositionMode_Source);
00154         p.drawPixmap(toRect.topLeft(), to);
00155         p.end();
00156         to = result;
00157     }
00158 }
00159 
00160 QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
00161 {
00162     if (from.isNull() && to.isNull()) {
00163         return from;
00164     }
00165 
00166     if (qFuzzyCompare(amount + 1, qreal(1.0))) {
00167         return from;
00168     }
00169 
00170     QRect startRect(from.rect());
00171     QRect targetRect(to.rect());
00172     QSize pixmapSize = startRect.size().expandedTo(targetRect.size());
00173     QRect toRect = QRect(QPoint(0,0), pixmapSize);
00174     targetRect.moveCenter(toRect.center());
00175     startRect.moveCenter(toRect.center());
00176 
00177     //paint to in the center of from
00178     QColor color;
00179     color.setAlphaF(amount);
00180 
00181     // If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
00182     QPaintEngine *paintEngine = from.paintEngine();
00183     if (paintEngine && 
00184         paintEngine->hasFeature(QPaintEngine::PorterDuff) &&
00185         paintEngine->hasFeature(QPaintEngine::BlendModes)) {
00186         QPixmap startPixmap(pixmapSize);
00187         startPixmap.fill(Qt::transparent);
00188 
00189         QPixmap targetPixmap(pixmapSize);
00190         targetPixmap.fill(Qt::transparent);
00191 
00192         QPainter p;
00193         p.begin(&targetPixmap);
00194         p.drawPixmap(targetRect, to);
00195         p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00196         p.fillRect(targetRect, color);
00197         p.end();
00198 
00199         p.begin(&startPixmap);
00200         p.drawPixmap(startRect, from);
00201         p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00202         p.fillRect(startRect, color);
00203         p.setCompositionMode(QPainter::CompositionMode_Plus);
00204         p.drawPixmap(targetRect, targetPixmap);
00205         p.end();
00206 
00207         return startPixmap;
00208     }
00209 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
00210     // We have Xrender support
00211     else if (paintEngine && paintEngine->hasFeature(QPaintEngine::PorterDuff)) {
00212         // QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
00213         // which we need to be able to do a transition from one pixmap to
00214         // another.
00215         //
00216         // In order to avoid the overhead of converting the pixmaps to images
00217         // and doing the operation entirely in software, this function has a
00218         // specialized path for X11 that uses Xrender directly to do the
00219         // transition. This operation can be fully accelerated in HW.
00220         //
00221         // This specialization can be removed when QX11PaintEngine supports
00222         // CompositionMode_Plus.
00223         QPixmap source(targetPixmap), destination(startPixmap);
00224 
00225         source.detach();
00226         destination.detach();
00227 
00228         Display *dpy = QX11Info::display();
00229 
00230         XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
00231         XRenderPictureAttributes pa;
00232         pa.repeat = 1; // RepeatNormal
00233 
00234         // Create a 1x1 8 bit repeating alpha picture
00235         Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
00236         Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
00237         XFreePixmap(dpy, pixmap);
00238 
00239         // Fill the alpha picture with the opacity value
00240         XRenderColor xcolor;
00241         xcolor.alpha = quint16(0xffff * amount);
00242         XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
00243 
00244         // Reduce the alpha of the destination with 1 - opacity
00245         XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
00246                          0, 0, 0, 0, 0, 0, destination.width(), destination.height());
00247 
00248         // Add source * opacity to the destination
00249         XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
00250                          destination.x11PictureHandle(),
00251                          toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
00252 
00253         XRenderFreePicture(dpy, alpha);
00254         return destination;
00255     }
00256 #endif
00257     else {
00258         // Fall back to using QRasterPaintEngine to do the transition.
00259         QImage under(pixmapSize, QImage::Format_ARGB32_Premultiplied);
00260         under.fill(Qt::transparent);
00261         QImage over(pixmapSize, QImage::Format_ARGB32_Premultiplied);
00262         over.fill(Qt::transparent);
00263 
00264         QPainter p;
00265         p.begin(&over);
00266         p.drawPixmap(targetRect, to);
00267         p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00268         p.fillRect(over.rect(), color);
00269         p.end();
00270 
00271         p.begin(&under);
00272         p.drawPixmap(startRect, from);
00273         p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00274         p.fillRect(startRect, color);
00275         p.setCompositionMode(QPainter::CompositionMode_Plus);
00276         p.drawImage(toRect.topLeft(), over);
00277         p.end();
00278 
00279         return QPixmap::fromImage(under);
00280     }
00281 }
00282 
00283 } // PaintUtils namespace
00284 
00285 } // Plasma namespace
00286 

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal