• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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 "effects/blur.cpp"
00029 
00030 namespace Plasma
00031 {
00032 
00033 namespace PaintUtils
00034 {
00035 
00036 void shadowBlur(QImage &image, int radius, const QColor &color)
00037 {
00038     if (radius < 1) {
00039         return;
00040     }
00041     if (image.isNull()) {
00042         return;
00043     }
00044 
00045     expblur<16, 7>(image, radius);
00046 
00047     QPainter p(&image);
00048     p.setCompositionMode(QPainter::CompositionMode_SourceIn);
00049     p.fillRect(image.rect(), color);
00050     p.end();
00051 }
00052 
00053 //TODO: we should have shadowText methods that paint the results directly into a QPainter passed in
00054 QPixmap shadowText(QString text, QColor textColor, QColor shadowColor, QPoint offset, int radius)
00055 {
00056     return shadowText(text, qApp->font(), textColor, shadowColor, offset, radius);
00057 }
00058 
00059 QPixmap shadowText(QString text, const QFont &font, QColor textColor, QColor shadowColor, QPoint offset, int radius)
00060 {
00061     //don't try to paint stuff on a future null pixmap because the text is empty
00062     if (text.isEmpty()) {
00063         return QPixmap();
00064     }
00065 
00066     // Draw text
00067     QFontMetrics fm(font);
00068     QRect textRect = fm.boundingRect(text);
00069     QPixmap textPixmap(textRect.width(), fm.height());
00070     textPixmap.fill(Qt::transparent);
00071     QPainter p(&textPixmap);
00072     p.setPen(textColor);
00073     p.setFont(font);
00074     // FIXME: the center alignment here is odd: the rect should be the size needed by
00075     //        the text, but for some fonts and configurations this is off by a pixel or so
00076     //        and "centering" the text painting 'fixes' that. Need to research why
00077     //        this is the case and determine if we should be painting it differently here,
00078     //        doing soething different with the boundingRect call or if it's a problem
00079     //        in Qt itself
00080     p.drawText(textPixmap.rect(), Qt::AlignCenter, text);
00081     p.end();
00082 
00083     //Draw blurred shadow
00084     QImage img(textRect.size() + QSize(radius * 2, radius * 2),
00085     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;
00094     int addSizeY;
00095     if (offset.x() > radius) {
00096         addSizeX = abs(offset.x()) - radius;
00097     } else {
00098         addSizeX = 0;
00099     }
00100     if (offset.y() > radius) {
00101         addSizeY = abs(offset.y()) - radius;
00102     } else {
00103         addSizeY = 0;
00104     }
00105 
00106     QPixmap finalPixmap(img.size() + QSize(addSizeX, addSizeY));
00107     finalPixmap.fill(Qt::transparent);
00108     p.begin(&finalPixmap);
00109     QPointF offsetF(offset);
00110     QPointF textTopLeft(finalPixmap.rect().topLeft() +
00111                         QPointF ((finalPixmap.width() - textPixmap.width()) / 2.0, (finalPixmap.height() - textPixmap.height()) / 2.0) -
00112                         (offsetF / 2.0));
00113     QPointF shadowTopLeft(finalPixmap.rect().topLeft() +
00114                           QPointF ((finalPixmap.width() - img.width()) / 2.0, (finalPixmap.height() - img.height()) / 2.0) +
00115                           (offsetF / 2.0));
00116 
00117     p.drawImage(shadowTopLeft, img);
00118     p.drawPixmap(textTopLeft, textPixmap);
00119     p.end();
00120 
00121     return finalPixmap;
00122 }
00123 
00124 QPainterPath roundedRectangle(const QRectF &rect, qreal radius)
00125 {
00126     QPainterPath path(QPointF(rect.left(), rect.top() + radius));
00127     path.quadTo(rect.left(), rect.top(), rect.left() + radius, rect.top());         // Top left corner
00128     path.lineTo(rect.right() - radius, rect.top());                                 // Top side
00129     path.quadTo(rect.right(), rect.top(), rect.right(), rect.top() + radius);       // Top right corner
00130     path.lineTo(rect.right(), rect.bottom() - radius);                              // Right side
00131     path.quadTo(rect.right(), rect.bottom(), rect.right() - radius, rect.bottom()); // Bottom right corner
00132     path.lineTo(rect.left() + radius, rect.bottom());                               // Bottom side
00133     path.quadTo(rect.left(), rect.bottom(), rect.left(), rect.bottom() - radius);   // Bottom left corner
00134     path.closeSubpath();
00135 
00136     return path;
00137 }
00138 
00139 QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
00140 {
00141     if (from.isNull() || to.isNull()) {
00142         return from;
00143     }
00144 
00145     int value = int(0xff * amount);
00146 
00147     if (value == 0) {
00148         return from;
00149     } else if (value == 1) {
00150         return to;
00151     }
00152 
00153     QColor color;
00154     color.setAlphaF(amount);
00155 
00156     //paint to in the center of from
00157     QRect toRect = to.rect();
00158     toRect.moveCenter(from.rect().center());
00159 
00160     // If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
00161     QPaintEngine *paintEngine = from.paintEngine();
00162     if (paintEngine &&
00163         paintEngine->hasFeature(QPaintEngine::PorterDuff) &&
00164         paintEngine->hasFeature(QPaintEngine::BlendModes)) {
00165         QPixmap under = from;
00166         QPixmap over  = to;
00167 
00168         QPainter p;
00169         p.begin(&over);
00170         p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00171         p.fillRect(over.rect(), color);
00172         p.end();
00173 
00174         p.begin(&under);
00175         p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00176         p.fillRect(under.rect(), color);
00177         p.setCompositionMode(QPainter::CompositionMode_Plus);
00178         p.drawPixmap(toRect.topLeft(), over);
00179         p.end();
00180 
00181         return under;
00182     }
00183 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
00184     // We have Xrender support
00185     else if (paintEngine && paintEngine->hasFeature(QPaintEngine::PorterDuff)) {
00186         // QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
00187         // which we need to be able to do a transition from one pixmap to
00188         // another.
00189         //
00190         // In order to avoid the overhead of converting the pixmaps to images
00191         // and doing the operation entirely in software, this function has a
00192         // specialized path for X11 that uses Xrender directly to do the
00193         // transition. This operation can be fully accelerated in HW.
00194         //
00195         // This specialization can be removed when QX11PaintEngine supports
00196         // CompositionMode_Plus.
00197         QPixmap source(to), destination(from);
00198 
00199         source.detach();
00200         destination.detach();
00201 
00202         Display *dpy = QX11Info::display();
00203 
00204         XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
00205         XRenderPictureAttributes pa;
00206         pa.repeat = 1; // RepeatNormal
00207 
00208         // Create a 1x1 8 bit repeating alpha picture
00209         Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
00210         Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
00211         XFreePixmap(dpy, pixmap);
00212 
00213         // Fill the alpha picture with the opacity value
00214         XRenderColor xcolor;
00215         xcolor.alpha = quint16(0xffff * amount);
00216         XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
00217 
00218         // Reduce the alpha of the destination with 1 - opacity
00219         XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
00220                          0, 0, 0, 0, 0, 0, destination.width(), destination.height());
00221 
00222         // Add source * opacity to the destination
00223         XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
00224                          destination.x11PictureHandle(),
00225                          toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
00226 
00227         XRenderFreePicture(dpy, alpha);
00228         return destination;
00229     }
00230 #endif
00231     else {
00232         // Fall back to using QRasterPaintEngine to do the transition.
00233         QImage under = from.toImage();
00234         QImage over  = to.toImage();
00235 
00236         QPainter p;
00237         p.begin(&over);
00238         p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00239         p.fillRect(over.rect(), color);
00240         p.end();
00241 
00242         p.begin(&under);
00243         p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00244         p.fillRect(under.rect(), color);
00245         p.setCompositionMode(QPainter::CompositionMode_Plus);
00246         p.drawImage(toRect.topLeft(), over);
00247         p.end();
00248 
00249         return QPixmap::fromImage(under);
00250     }
00251 }
00252 
00253 } // PaintUtils namespace
00254 
00255 } // Plasma namespace
00256 

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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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