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

Plasma

  • sources
  • kde-4.12
  • kdelibs
  • plasma
paintutils.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2005 by Aaron Seigo <aseigo@kde.org>
3  * Copyright 2008 by Andrew Lake <jamboarder@yahoo.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU Library General Public License as
7  * published by the Free Software Foundation; either version 2, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include <paintutils.h>
22 
23 #include <QImage>
24 #include <QPainter>
25 #include <QPaintEngine>
26 #include <QPixmap>
27 
28 #include "private/effects/blur.cpp"
29 #include "private/effects/halopainter_p.h"
30 #include "svg.h"
31 
32 namespace Plasma
33 {
34 
35 namespace PaintUtils
36 {
37 
38 void shadowBlur(QImage &image, int radius, const QColor &color)
39 {
40  if (radius < 1) {
41  return;
42  }
43  if (image.isNull()) {
44  return;
45  }
46 
47  expblur<16, 7>(image, radius);
48 
49  QPainter p(&image);
50  p.setCompositionMode(QPainter::CompositionMode_SourceIn);
51  p.fillRect(image.rect(), color);
52  p.end();
53 }
54 
55 //TODO: we should have shadowText methods that paint the results directly into a QPainter passed in
56 QPixmap shadowText(QString text, QColor textColor, QColor shadowColor, QPoint offset, int radius)
57 {
58  return shadowText(text, qApp->font(), textColor, shadowColor, offset, radius);
59 }
60 
61 QPixmap shadowText(QString text, const QFont &font, QColor textColor, QColor shadowColor, QPoint offset, int radius)
62 {
63  //don't try to paint stuff on a future null pixmap because the text is empty
64  if (text.isEmpty()) {
65  return QPixmap();
66  }
67 
68  // Draw text
69  QFontMetrics fm(font);
70  QRect textRect = fm.boundingRect(text);
71  QPixmap textPixmap(textRect.width(), fm.height());
72  textPixmap.fill(Qt::transparent);
73  QPainter p(&textPixmap);
74  p.setPen(textColor);
75  p.setFont(font);
76  // FIXME: the center alignment here is odd: the rect should be the size needed by
77  // the text, but for some fonts and configurations this is off by a pixel or so
78  // and "centering" the text painting 'fixes' that. Need to research why
79  // this is the case and determine if we should be painting it differently here,
80  // doing soething different with the boundingRect call or if it's a problem
81  // in Qt itself
82  p.drawText(textPixmap.rect(), Qt::AlignCenter, text);
83  p.end();
84 
85  //Draw blurred shadow
86  QImage img(textRect.size() + QSize(radius * 2, radius * 2), QImage::Format_ARGB32_Premultiplied);
87  img.fill(0);
88  p.begin(&img);
89  p.drawImage(QPoint(radius, radius), textPixmap.toImage());
90  p.end();
91  shadowBlur(img, radius, shadowColor);
92 
93  //Compose text and shadow
94  int addSizeX = qMax(0, qAbs(offset.x()) - radius);
95  int addSizeY = qMax(0, qAbs(offset.y()) - radius);
96 
97  QPixmap finalPixmap(img.size() + QSize(addSizeX, addSizeY));
98  finalPixmap.fill(Qt::transparent);
99  p.begin(&finalPixmap);
100  p.drawImage(qMax(0, offset.x()), qMax(0, offset.y()), img);
101  p.drawPixmap(radius + qMax(0, -offset.x()), radius + qMax(0, -offset.y()), textPixmap);
102  p.end();
103 
104  return finalPixmap;
105 }
106 
107 QPixmap texturedText(const QString &text, const QFont &font, Plasma::Svg *texture)
108 {
109  QFontMetrics fm(font);
110  //the text will be moved a bit from contentsRect
111  QRect contentsRect = fm.boundingRect(text).adjusted(0, 0, 2, 2);
112  contentsRect.moveTo(0,0);
113 
114  QPixmap pixmap(contentsRect.size());
115  pixmap.fill(Qt::transparent);
116 
117  QPainter buffPainter(&pixmap);
118  buffPainter.setPen(Qt::black);
119 
120  buffPainter.setFont(font);
121  buffPainter.drawText(contentsRect, Qt::AlignCenter, text);
122  buffPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
123  texture->paint(&buffPainter, contentsRect, "foreground");
124  buffPainter.end();
125 
126  //do the shadow
127  QImage image(pixmap.size() + QSize(2, 2), QImage::Format_ARGB32_Premultiplied);
128  image.fill(Qt::transparent);
129  buffPainter.begin(&image);
130  buffPainter.setFont(font);
131  buffPainter.drawText(contentsRect.translated(1, 1), Qt::AlignCenter, text);
132  buffPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
133  texture->paint(&buffPainter, contentsRect.adjusted(-1, -1, 1, 1), "shadow");
134  buffPainter.end();
135 
136  expblur<16, 7>(image, 1);
137  //hole in the shadow
138  buffPainter.begin(&image);
139  buffPainter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
140  buffPainter.setFont(font);
141  buffPainter.drawText(contentsRect.translated(1, 1), Qt::AlignCenter, text);
142  buffPainter.end();
143 
144  QPixmap ret(image.size());
145  ret.fill(Qt::transparent);
146  buffPainter.begin(&ret);
147  buffPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
148  buffPainter.drawImage(QPoint(0,0), image);
149  buffPainter.drawPixmap(QPoint(1,1), pixmap);
150  buffPainter.end();
151  return ret;
152 }
153 
154 void drawHalo(QPainter *painter, const QRectF &rect)
155 {
156  HaloPainter::instance()->drawHalo(painter, rect.toRect());
157 }
158 
159 QPainterPath roundedRectangle(const QRectF &rect, qreal radius)
160 {
161  QPainterPath path(QPointF(rect.left(), rect.top() + radius));
162  path.quadTo(rect.left(), rect.top(), rect.left() + radius, rect.top()); // Top left corner
163  path.lineTo(rect.right() - radius, rect.top()); // Top side
164  path.quadTo(rect.right(), rect.top(), rect.right(), rect.top() + radius); // Top right corner
165  path.lineTo(rect.right(), rect.bottom() - radius); // Right side
166  path.quadTo(rect.right(), rect.bottom(), rect.right() - radius, rect.bottom()); // Bottom right corner
167  path.lineTo(rect.left() + radius, rect.bottom()); // Bottom side
168  path.quadTo(rect.left(), rect.bottom(), rect.left(), rect.bottom() - radius); // Bottom left corner
169  path.closeSubpath();
170 
171  return path;
172 }
173 
174 void centerPixmaps(QPixmap &from, QPixmap &to)
175 {
176  if (from.size() == to.size() && from.hasAlphaChannel() && to.hasAlphaChannel()) {
177  return;
178  }
179 
180  QRect fromRect(from.rect());
181  QRect toRect(to.rect());
182 
183  QRect actualRect = QRect(QPoint(0,0), fromRect.size().expandedTo(toRect.size()));
184  fromRect.moveCenter(actualRect.center());
185  toRect.moveCenter(actualRect.center());
186 
187  if (from.size() != actualRect.size() || !from.hasAlphaChannel()) {
188  QPixmap result(actualRect.size());
189  result.fill(Qt::transparent);
190  QPainter p(&result);
191  p.setCompositionMode(QPainter::CompositionMode_Source);
192  p.drawPixmap(fromRect.topLeft(), from);
193  p.end();
194  from = result;
195  }
196 
197  if (to.size() != actualRect.size() || !to.hasAlphaChannel()) {
198  QPixmap result(actualRect.size());
199  result.fill(Qt::transparent);
200  QPainter p(&result);
201  p.setCompositionMode(QPainter::CompositionMode_Source);
202  p.drawPixmap(toRect.topLeft(), to);
203  p.end();
204  to = result;
205  }
206 }
207 
208 QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
209 {
210  if (from.isNull() && to.isNull()) {
211  return from;
212  }
213 
214  if (qFuzzyCompare(amount + 1, qreal(1.0))) {
215  return from;
216  }
217 
218  QRect startRect(from.rect());
219  QRect targetRect(to.rect());
220  QSize pixmapSize = startRect.size().expandedTo(targetRect.size());
221  QRect toRect = QRect(QPoint(0,0), pixmapSize);
222  targetRect.moveCenter(toRect.center());
223  startRect.moveCenter(toRect.center());
224 
225  //paint to in the center of from
226  QColor color;
227  color.setAlphaF(amount);
228 
229  // If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
230  QPaintEngine *paintEngine = from.paintEngine();
231  if (paintEngine &&
232  paintEngine->hasFeature(QPaintEngine::PorterDuff) &&
233  paintEngine->hasFeature(QPaintEngine::BlendModes)) {
234  QPixmap startPixmap(pixmapSize);
235  startPixmap.fill(Qt::transparent);
236 
237  QPixmap targetPixmap(pixmapSize);
238  targetPixmap.fill(Qt::transparent);
239 
240  QPainter p;
241  p.begin(&targetPixmap);
242  p.drawPixmap(targetRect, to);
243  p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
244  p.fillRect(targetRect, color);
245  p.end();
246 
247  p.begin(&startPixmap);
248  p.drawPixmap(startRect, from);
249  p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
250  p.fillRect(startRect, color);
251  p.setCompositionMode(QPainter::CompositionMode_Plus);
252  p.drawPixmap(targetRect, targetPixmap);
253  p.end();
254 
255  return startPixmap;
256  }
257 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
258  // We have Xrender support
259  else if (paintEngine && paintEngine->hasFeature(QPaintEngine::PorterDuff)) {
260  // QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
261  // which we need to be able to do a transition from one pixmap to
262  // another.
263  //
264  // In order to avoid the overhead of converting the pixmaps to images
265  // and doing the operation entirely in software, this function has a
266  // specialized path for X11 that uses Xrender directly to do the
267  // transition. This operation can be fully accelerated in HW.
268  //
269  // This specialization can be removed when QX11PaintEngine supports
270  // CompositionMode_Plus.
271  QPixmap source(targetPixmap), destination(startPixmap);
272 
273  source.detach();
274  destination.detach();
275 
276  Display *dpy = QX11Info::display();
277 
278  XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
279  XRenderPictureAttributes pa;
280  pa.repeat = 1; // RepeatNormal
281 
282  // Create a 1x1 8 bit repeating alpha picture
283  Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
284  Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
285  XFreePixmap(dpy, pixmap);
286 
287  // Fill the alpha picture with the opacity value
288  XRenderColor xcolor;
289  xcolor.alpha = quint16(0xffff * amount);
290  XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
291 
292  // Reduce the alpha of the destination with 1 - opacity
293  XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
294  0, 0, 0, 0, 0, 0, destination.width(), destination.height());
295 
296  // Add source * opacity to the destination
297  XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
298  destination.x11PictureHandle(),
299  toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
300 
301  XRenderFreePicture(dpy, alpha);
302  return destination;
303  }
304 #endif
305  else {
306  // Fall back to using QRasterPaintEngine to do the transition.
307  QImage under(pixmapSize, QImage::Format_ARGB32_Premultiplied);
308  under.fill(Qt::transparent);
309  QImage over(pixmapSize, QImage::Format_ARGB32_Premultiplied);
310  over.fill(Qt::transparent);
311 
312  QPainter p;
313  p.begin(&over);
314  p.drawPixmap(targetRect, to);
315  p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
316  p.fillRect(over.rect(), color);
317  p.end();
318 
319  p.begin(&under);
320  p.drawPixmap(startRect, from);
321  p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
322  p.fillRect(startRect, color);
323  p.setCompositionMode(QPainter::CompositionMode_Plus);
324  p.drawImage(toRect.topLeft(), over);
325  p.end();
326 
327  return QPixmap::fromImage(under);
328  }
329 }
330 
331 } // PaintUtils namespace
332 
333 } // Plasma namespace
334 
Plasma::PaintUtils::texturedText
QPixmap texturedText(const QString &text, const QFont &font, Plasma::Svg *texture)
Definition: paintutils.cpp:107
Plasma::PaintUtils::drawHalo
void drawHalo(QPainter *painter, const QRectF &rect)
Definition: paintutils.cpp:154
Plasma::PaintUtils::roundedRectangle
QPainterPath roundedRectangle(const QRectF &rect, qreal radius)
Returns a nicely rounded rectanglular path for painting.
Definition: paintutils.cpp:159
Plasma::Svg::paint
Q_INVOKABLE void paint(QPainter *painter, const QPointF &point, const QString &elementID=QString())
Paints all or part of the SVG represented by this object.
Definition: svg.cpp:655
paintutils.h
Plasma::PaintUtils::shadowText
QPixmap shadowText(QString text, QColor textColor, QColor shadowColor, QPoint offset, int radius)
Definition: paintutils.cpp:56
Plasma::PaintUtils::shadowBlur
void shadowBlur(QImage &image, int radius, const QColor &color)
Creates a blurred shadow of the supplied image.
Definition: paintutils.cpp:38
Plasma::PaintUtils::transition
QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
Blends a pixmap into another.
Definition: paintutils.cpp:208
Plasma::PaintUtils::centerPixmaps
void centerPixmaps(QPixmap &from, QPixmap &to)
center two pixmap together in the biggest rectangle
Definition: paintutils.cpp:174
Plasma::Svg
A theme aware image-centric SVG class.
Definition: svg.h:56
svg.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:33 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Plasma

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal