• 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     if (from.paintEngine()->hasFeature(QPaintEngine::PorterDuff) &&
00162         from.paintEngine()->hasFeature(QPaintEngine::BlendModes)) {
00163         QPixmap under = from;
00164         QPixmap over  = to;
00165 
00166         QPainter p;
00167         p.begin(&over);
00168         p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00169         p.fillRect(over.rect(), color);
00170         p.end();
00171 
00172         p.begin(&under);
00173         p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00174         p.fillRect(under.rect(), color);
00175         p.setCompositionMode(QPainter::CompositionMode_Plus);
00176         p.drawPixmap(toRect.topLeft(), over);
00177         p.end();
00178 
00179         return under;
00180     }
00181 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
00182     // We have Xrender support
00183     else if (from.paintEngine()->hasFeature(QPaintEngine::PorterDuff)) {
00184         // QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
00185         // which we need to be able to do a transition from one pixmap to
00186         // another.
00187         //
00188         // In order to avoid the overhead of converting the pixmaps to images
00189         // and doing the operation entirely in software, this function has a
00190         // specialized path for X11 that uses Xrender directly to do the
00191         // transition. This operation can be fully accelerated in HW.
00192         //
00193         // This specialization can be removed when QX11PaintEngine supports
00194         // CompositionMode_Plus.
00195         QPixmap source(to), destination(from);
00196 
00197         source.detach();
00198         destination.detach();
00199 
00200         Display *dpy = QX11Info::display();
00201 
00202         XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
00203         XRenderPictureAttributes pa;
00204         pa.repeat = 1; // RepeatNormal
00205 
00206         // Create a 1x1 8 bit repeating alpha picture
00207         Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
00208         Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
00209         XFreePixmap(dpy, pixmap);
00210 
00211         // Fill the alpha picture with the opacity value
00212         XRenderColor xcolor;
00213         xcolor.alpha = quint16(0xffff * amount);
00214         XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
00215 
00216         // Reduce the alpha of the destination with 1 - opacity
00217         XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
00218                          0, 0, 0, 0, 0, 0, destination.width(), destination.height());
00219 
00220         // Add source * opacity to the destination
00221         XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
00222                          destination.x11PictureHandle(),
00223                          toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
00224 
00225         XRenderFreePicture(dpy, alpha);
00226         return destination;
00227     }
00228 #endif
00229     else {
00230         // Fall back to using QRasterPaintEngine to do the transition.
00231         QImage under = from.toImage();
00232         QImage over  = to.toImage();
00233 
00234         QPainter p;
00235         p.begin(&over);
00236         p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00237         p.fillRect(over.rect(), color);
00238         p.end();
00239 
00240         p.begin(&under);
00241         p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00242         p.fillRect(under.rect(), color);
00243         p.setCompositionMode(QPainter::CompositionMode_Plus);
00244         p.drawImage(toRect.topLeft(), over);
00245         p.end();
00246 
00247         return QPixmap::fromImage(under);
00248     }
00249 }
00250 
00251 } // PaintUtils namespace
00252 
00253 } // Plasma namespace
00254 

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