1 | /* |
2 | * Copyright 2007 Zack Rusin <zack@kde.org> |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU Library General Public License as |
6 | * published by the Free Software Foundation; either version 2, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details |
13 | * |
14 | * You should have received a copy of the GNU Library General Public |
15 | * License along with this program; if not, write to the |
16 | * Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "glapplet.h" |
21 | |
22 | #include <QtOpenGL/QGLPixelBuffer> |
23 | #include <QtGui/QPainter> |
24 | #include <QtGui/QImage> |
25 | |
26 | namespace Plasma { |
27 | |
28 | class GLAppletPrivate |
29 | { |
30 | public: |
31 | GLAppletPrivate() |
32 | { |
33 | init(); |
34 | } |
35 | ~GLAppletPrivate() |
36 | { |
37 | delete pbuf; |
38 | delete dummy; |
39 | } |
40 | void init() |
41 | { |
42 | dummy = new QGLWidget((QWidget *) 0); |
43 | QGLFormat format = QGLFormat::defaultFormat(); |
44 | format.setSampleBuffers(true); |
45 | format.setAlphaBufferSize(8); |
46 | //dummy size construction |
47 | pbuf = new QGLPixelBuffer(300, 300, format, dummy); |
48 | if (pbuf->isValid()) { |
49 | pbuf->makeCurrent(); |
50 | } |
51 | } |
52 | void updateGlSize(const QSize &size) |
53 | { |
54 | if (size.width() > pbuf->width() || |
55 | size.height() > pbuf->height()) { |
56 | QGLFormat format = pbuf->format(); |
57 | delete pbuf; |
58 | pbuf = new QGLPixelBuffer(size, format, dummy); |
59 | } |
60 | } |
61 | |
62 | public: |
63 | QGLPixelBuffer *pbuf; |
64 | QGLWidget *dummy; |
65 | }; |
66 | |
67 | GLApplet::GLApplet(QGraphicsItem *parent, |
68 | const QString &serviceId, |
69 | int appletId) |
70 | : Applet(parent, serviceId, appletId), |
71 | d(new GLAppletPrivate) |
72 | { |
73 | if (!d->dummy->isValid() || |
74 | !QGLPixelBuffer::hasOpenGLPbuffers() || |
75 | !d->pbuf->isValid()) { |
76 | setFailedToLaunch(true, i18n("This system does not support OpenGL widgets." )); |
77 | } |
78 | } |
79 | |
80 | GLApplet::GLApplet(QObject *parent, const QVariantList &args) |
81 | : Applet(parent, args), |
82 | d(new GLAppletPrivate) |
83 | { |
84 | if (!d->dummy->isValid() || |
85 | !QGLPixelBuffer::hasOpenGLPbuffers() || |
86 | !d->pbuf->isValid()) { |
87 | setFailedToLaunch(true, i18n("This system does not support OpenGL widgets." )); |
88 | } |
89 | } |
90 | |
91 | GLApplet::~GLApplet() |
92 | { |
93 | delete d; |
94 | } |
95 | |
96 | GLuint GLApplet::bindTexture(const QImage &image, GLenum target) |
97 | { |
98 | Q_ASSERT(d->pbuf); |
99 | if (!d->dummy->isValid()) { |
100 | return 0; |
101 | } |
102 | return d->dummy->bindTexture(image, target); |
103 | } |
104 | |
105 | void GLApplet::deleteTexture(GLuint textureId) |
106 | { |
107 | Q_ASSERT(d->pbuf); |
108 | d->dummy->deleteTexture(textureId); |
109 | } |
110 | |
111 | void GLApplet::paintGLInterface(QPainter *painter, |
112 | const QStyleOptionGraphicsItem *option) |
113 | { |
114 | Q_UNUSED(painter) |
115 | Q_UNUSED(option) |
116 | } |
117 | |
118 | static inline QPainterPath (const QRectF &r, int roundness, |
119 | int =10) |
120 | { |
121 | QPainterPath path; |
122 | int xRnd = roundness; |
123 | int yRnd = roundness; |
124 | if (r.width() > r.height()) { |
125 | xRnd = int(roundness * r.height() / r.width()); |
126 | } else { |
127 | yRnd = int(roundness * r.width() / r.height()); |
128 | } |
129 | |
130 | if(xRnd >= 100) { // fix ranges |
131 | xRnd = 99; |
132 | } |
133 | if(yRnd >= 100) { |
134 | yRnd = 99; |
135 | } |
136 | if(xRnd <= 0 || yRnd <= 0) { // add normal rectangle |
137 | path.addRect(r); |
138 | return path; |
139 | } |
140 | |
141 | QRectF rect = r.normalized(); |
142 | |
143 | if (rect.isNull()) { |
144 | return path; |
145 | } |
146 | |
147 | qreal x = rect.x(); |
148 | qreal y = rect.y(); |
149 | qreal w = rect.width(); |
150 | qreal h = rect.height(); |
151 | qreal rxx = w * xRnd / 200; |
152 | qreal ryy = h * yRnd / 200; |
153 | // were there overflows? |
154 | if (rxx < 0) { |
155 | rxx = w / 200 * xRnd; |
156 | } |
157 | if (ryy < 0) { |
158 | ryy = h / 200 * yRnd; |
159 | } |
160 | qreal rxx2 = 2 * rxx; |
161 | qreal ryy2 = 2 * ryy; |
162 | |
163 | path.arcMoveTo(x, y, rxx2, ryy2, 90); |
164 | path.arcTo(x, y, rxx2, ryy2, 90, 90); |
165 | QPointF pt = path.currentPosition(); |
166 | path.lineTo(x, pt.y() + headerHeight); |
167 | path.lineTo(x + w, pt.y() + headerHeight); |
168 | path.lineTo(x + w, pt.y()); |
169 | path.arcTo(x + w - rxx2, y, rxx2, ryy2, 0, 90); |
170 | path.closeSubpath(); |
171 | |
172 | return path; |
173 | } |
174 | |
175 | void GLApplet::paintInterface(QPainter *painter, |
176 | const QStyleOptionGraphicsItem *option, |
177 | const QRect &contentsRect) |
178 | { |
179 | Q_UNUSED(contentsRect) |
180 | Q_ASSERT(d->pbuf); |
181 | if ((!d->dummy->isValid() || |
182 | !d->pbuf->isValid())) { |
183 | if (!hasFailedToLaunch()) { |
184 | setFailedToLaunch(true, i18n("Your machine does not support OpenGL widgets." )); |
185 | } |
186 | |
187 | return; |
188 | } |
189 | d->pbuf->makeCurrent(); |
190 | |
191 | QMatrix m = painter->worldMatrix(); |
192 | QRect deviceRect = m.mapRect(QRect(QPoint(23, 25), boundingRect().size().toSize())); |
193 | d->updateGlSize(deviceRect.size()); |
194 | |
195 | // redirect this widget's painting into the pbuffer |
196 | QPainter p(d->pbuf); |
197 | paintGLInterface(&p, option); |
198 | |
199 | // draw the pbuffer contents to the backingstore |
200 | QImage image = d->pbuf->toImage(); |
201 | painter->drawImage(0, 0, image); |
202 | } |
203 | |
204 | void GLApplet::makeCurrent() |
205 | { |
206 | if (!d->dummy->isValid() || !d->pbuf->isValid()) { |
207 | d->dummy->makeCurrent(); |
208 | } |
209 | } |
210 | |
211 | } // Plasma namespace |
212 | |
213 | #include "glapplet.moc" |
214 | |