1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** Contact: Qt Software Information ([email protected])
|
---|
5 | **
|
---|
6 | ** This file is part of the demonstration applications of the Qt Toolkit.
|
---|
7 | **
|
---|
8 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
9 | ** Commercial Usage
|
---|
10 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
11 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
12 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
13 | ** a written agreement between you and Nokia.
|
---|
14 | **
|
---|
15 | ** GNU Lesser General Public License Usage
|
---|
16 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
17 | ** General Public License version 2.1 as published by the Free Software
|
---|
18 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
19 | ** packaging of this file. Please review the following information to
|
---|
20 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
21 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
22 | **
|
---|
23 | ** In addition, as a special exception, Nokia gives you certain
|
---|
24 | ** additional rights. These rights are described in the Nokia Qt LGPL
|
---|
25 | ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
---|
26 | ** package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you are unsure which license is appropriate for your use, please
|
---|
37 | ** contact the sales department at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "pathdeform.h"
|
---|
43 |
|
---|
44 | #include <QApplication>
|
---|
45 | #include <QtDebug>
|
---|
46 | #include <QMouseEvent>
|
---|
47 | #include <QTimerEvent>
|
---|
48 | #include <QLayout>
|
---|
49 | #include <QLineEdit>
|
---|
50 | #include <QPainter>
|
---|
51 | #include <QSlider>
|
---|
52 | #include <QLabel>
|
---|
53 | #include <QDesktopWidget>
|
---|
54 | #include <qmath.h>
|
---|
55 |
|
---|
56 |
|
---|
57 | PathDeformControls::PathDeformControls(QWidget *parent, PathDeformRenderer* renderer, bool smallScreen)
|
---|
58 | : QWidget(parent)
|
---|
59 | {
|
---|
60 | m_renderer = renderer;
|
---|
61 |
|
---|
62 | if (smallScreen)
|
---|
63 | layoutForSmallScreen();
|
---|
64 | else
|
---|
65 | layoutForDesktop();
|
---|
66 | }
|
---|
67 |
|
---|
68 |
|
---|
69 | void PathDeformControls::layoutForDesktop()
|
---|
70 | {
|
---|
71 | QGroupBox* mainGroup = new QGroupBox(this);
|
---|
72 | mainGroup->setTitle(tr("Controls"));
|
---|
73 |
|
---|
74 | QGroupBox *radiusGroup = new QGroupBox(mainGroup);
|
---|
75 | radiusGroup->setTitle(tr("Lens Radius"));
|
---|
76 | QSlider *radiusSlider = new QSlider(Qt::Horizontal, radiusGroup);
|
---|
77 | radiusSlider->setRange(15, 150);
|
---|
78 | radiusSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
---|
79 |
|
---|
80 | QGroupBox *deformGroup = new QGroupBox(mainGroup);
|
---|
81 | deformGroup->setTitle(tr("Deformation"));
|
---|
82 | QSlider *deformSlider = new QSlider(Qt::Horizontal, deformGroup);
|
---|
83 | deformSlider->setRange(-100, 100);
|
---|
84 | deformSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
---|
85 |
|
---|
86 | QGroupBox *fontSizeGroup = new QGroupBox(mainGroup);
|
---|
87 | fontSizeGroup->setTitle(tr("Font Size"));
|
---|
88 | QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, fontSizeGroup);
|
---|
89 | fontSizeSlider->setRange(16, 200);
|
---|
90 | fontSizeSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
---|
91 |
|
---|
92 | QGroupBox *textGroup = new QGroupBox(mainGroup);
|
---|
93 | textGroup->setTitle(tr("Text"));
|
---|
94 | QLineEdit *textInput = new QLineEdit(textGroup);
|
---|
95 |
|
---|
96 | QPushButton *animateButton = new QPushButton(mainGroup);
|
---|
97 | animateButton->setText(tr("Animated"));
|
---|
98 | animateButton->setCheckable(true);
|
---|
99 |
|
---|
100 | QPushButton *showSourceButton = new QPushButton(mainGroup);
|
---|
101 | showSourceButton->setText(tr("Show Source"));
|
---|
102 |
|
---|
103 | #ifdef QT_OPENGL_SUPPORT
|
---|
104 | QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
|
---|
105 | enableOpenGLButton->setText(tr("Use OpenGL"));
|
---|
106 | enableOpenGLButton->setCheckable(true);
|
---|
107 | enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
|
---|
108 | if (!QGLFormat::hasOpenGL())
|
---|
109 | enableOpenGLButton->hide();
|
---|
110 | #endif
|
---|
111 |
|
---|
112 | QPushButton *whatsThisButton = new QPushButton(mainGroup);
|
---|
113 | whatsThisButton->setText(tr("What's This?"));
|
---|
114 | whatsThisButton->setCheckable(true);
|
---|
115 |
|
---|
116 |
|
---|
117 | mainGroup->setFixedWidth(180);
|
---|
118 |
|
---|
119 | QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
|
---|
120 | mainGroupLayout->addWidget(radiusGroup);
|
---|
121 | mainGroupLayout->addWidget(deformGroup);
|
---|
122 | mainGroupLayout->addWidget(fontSizeGroup);
|
---|
123 | mainGroupLayout->addWidget(textGroup);
|
---|
124 | mainGroupLayout->addWidget(animateButton);
|
---|
125 | mainGroupLayout->addStretch(1);
|
---|
126 | #ifdef QT_OPENGL_SUPPORT
|
---|
127 | mainGroupLayout->addWidget(enableOpenGLButton);
|
---|
128 | #endif
|
---|
129 | mainGroupLayout->addWidget(showSourceButton);
|
---|
130 | mainGroupLayout->addWidget(whatsThisButton);
|
---|
131 |
|
---|
132 | QVBoxLayout *radiusGroupLayout = new QVBoxLayout(radiusGroup);
|
---|
133 | radiusGroupLayout->addWidget(radiusSlider);
|
---|
134 |
|
---|
135 | QVBoxLayout *deformGroupLayout = new QVBoxLayout(deformGroup);
|
---|
136 | deformGroupLayout->addWidget(deformSlider);
|
---|
137 |
|
---|
138 | QVBoxLayout *fontSizeGroupLayout = new QVBoxLayout(fontSizeGroup);
|
---|
139 | fontSizeGroupLayout->addWidget(fontSizeSlider);
|
---|
140 |
|
---|
141 | QVBoxLayout *textGroupLayout = new QVBoxLayout(textGroup);
|
---|
142 | textGroupLayout->addWidget(textInput);
|
---|
143 |
|
---|
144 | QVBoxLayout * mainLayout = new QVBoxLayout(this);
|
---|
145 | mainLayout->addWidget(mainGroup);
|
---|
146 | mainLayout->setMargin(0);
|
---|
147 |
|
---|
148 | connect(radiusSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setRadius(int)));
|
---|
149 | connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int)));
|
---|
150 | connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int)));
|
---|
151 | connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool)));
|
---|
152 | #ifdef QT_OPENGL_SUPPORT
|
---|
153 | connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
|
---|
154 | #endif
|
---|
155 |
|
---|
156 | connect(textInput, SIGNAL(textChanged(QString)), m_renderer, SLOT(setText(QString)));
|
---|
157 | connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)),
|
---|
158 | whatsThisButton, SLOT(setChecked(bool)));
|
---|
159 | connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool)));
|
---|
160 | connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource()));
|
---|
161 |
|
---|
162 | animateButton->animateClick();
|
---|
163 | deformSlider->setValue(80);
|
---|
164 | fontSizeSlider->setValue(120);
|
---|
165 | radiusSlider->setValue(100);
|
---|
166 | textInput->setText(tr("Qt"));
|
---|
167 | }
|
---|
168 |
|
---|
169 | void PathDeformControls::layoutForSmallScreen()
|
---|
170 | {
|
---|
171 | QGroupBox* mainGroup = new QGroupBox(this);
|
---|
172 | mainGroup->setTitle(tr("Controls"));
|
---|
173 |
|
---|
174 | QLabel *radiusLabel = new QLabel(mainGroup);
|
---|
175 | radiusLabel->setText(tr("Lens Radius:"));
|
---|
176 | QSlider *radiusSlider = new QSlider(Qt::Horizontal, mainGroup);
|
---|
177 | radiusSlider->setRange(15, 150);
|
---|
178 | radiusSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
---|
179 |
|
---|
180 | QLabel *deformLabel = new QLabel(mainGroup);
|
---|
181 | deformLabel->setText(tr("Deformation:"));
|
---|
182 | QSlider *deformSlider = new QSlider(Qt::Horizontal, mainGroup);
|
---|
183 | deformSlider->setRange(-100, 100);
|
---|
184 | deformSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
---|
185 |
|
---|
186 | QLabel *fontSizeLabel = new QLabel(mainGroup);
|
---|
187 | fontSizeLabel->setText(tr("Font Size:"));
|
---|
188 | QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, mainGroup);
|
---|
189 | fontSizeSlider->setRange(16, 200);
|
---|
190 | fontSizeSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
---|
191 |
|
---|
192 | QPushButton *animateButton = new QPushButton(tr("Animated"), mainGroup);
|
---|
193 | animateButton->setCheckable(true);
|
---|
194 |
|
---|
195 | #ifdef QT_OPENGL_SUPPORT
|
---|
196 | QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
|
---|
197 | enableOpenGLButton->setText(tr("Use OpenGL"));
|
---|
198 | enableOpenGLButton->setCheckable(mainGroup);
|
---|
199 | enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
|
---|
200 | if (!QGLFormat::hasOpenGL())
|
---|
201 | enableOpenGLButton->hide();
|
---|
202 | #endif
|
---|
203 |
|
---|
204 | QPushButton *quitButton = new QPushButton(tr("Quit"), mainGroup);
|
---|
205 | QPushButton *okButton = new QPushButton(tr("OK"), mainGroup);
|
---|
206 |
|
---|
207 |
|
---|
208 | QGridLayout *mainGroupLayout = new QGridLayout(mainGroup);
|
---|
209 | mainGroupLayout->setMargin(0);
|
---|
210 | mainGroupLayout->addWidget(radiusLabel, 0, 0, Qt::AlignRight);
|
---|
211 | mainGroupLayout->addWidget(radiusSlider, 0, 1);
|
---|
212 | mainGroupLayout->addWidget(deformLabel, 1, 0, Qt::AlignRight);
|
---|
213 | mainGroupLayout->addWidget(deformSlider, 1, 1);
|
---|
214 | mainGroupLayout->addWidget(fontSizeLabel, 2, 0, Qt::AlignRight);
|
---|
215 | mainGroupLayout->addWidget(fontSizeSlider, 2, 1);
|
---|
216 | mainGroupLayout->addWidget(animateButton, 3,0, 1,2);
|
---|
217 | #ifdef QT_OPENGL_SUPPORT
|
---|
218 | mainGroupLayout->addWidget(enableOpenGLButton, 4,0, 1,2);
|
---|
219 | #endif
|
---|
220 |
|
---|
221 | QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
---|
222 | mainLayout->addWidget(mainGroup);
|
---|
223 | mainLayout->addStretch(1);
|
---|
224 | mainLayout->addWidget(okButton);
|
---|
225 | mainLayout->addWidget(quitButton);
|
---|
226 |
|
---|
227 | connect(quitButton, SIGNAL(clicked()), this, SLOT(emitQuitSignal()));
|
---|
228 | connect(okButton, SIGNAL(clicked()), this, SLOT(emitOkSignal()));
|
---|
229 | connect(radiusSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setRadius(int)));
|
---|
230 | connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int)));
|
---|
231 | connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int)));
|
---|
232 | connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool)));
|
---|
233 | #ifdef QT_OPENGL_SUPPORT
|
---|
234 | connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
|
---|
235 | #endif
|
---|
236 |
|
---|
237 |
|
---|
238 | animateButton->animateClick();
|
---|
239 | deformSlider->setValue(80);
|
---|
240 | fontSizeSlider->setValue(120);
|
---|
241 |
|
---|
242 | QRect screen_size = QApplication::desktop()->screenGeometry();
|
---|
243 | radiusSlider->setValue(qMin(screen_size.width(), screen_size.height())/5);
|
---|
244 | m_renderer->setText(tr("Qt"));
|
---|
245 | }
|
---|
246 |
|
---|
247 |
|
---|
248 | void PathDeformControls::emitQuitSignal()
|
---|
249 | { emit quitPressed(); }
|
---|
250 |
|
---|
251 | void PathDeformControls::emitOkSignal()
|
---|
252 | { emit okPressed(); }
|
---|
253 |
|
---|
254 |
|
---|
255 | PathDeformWidget::PathDeformWidget(QWidget *parent, bool smallScreen)
|
---|
256 | : QWidget(parent)
|
---|
257 | {
|
---|
258 | setWindowTitle(tr("Vector Deformation"));
|
---|
259 |
|
---|
260 | m_renderer = new PathDeformRenderer(this, smallScreen);
|
---|
261 | m_renderer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
---|
262 |
|
---|
263 | // Layouts
|
---|
264 | QHBoxLayout *mainLayout = new QHBoxLayout(this);
|
---|
265 | mainLayout->addWidget(m_renderer);
|
---|
266 |
|
---|
267 | m_controls = new PathDeformControls(0, m_renderer, smallScreen);
|
---|
268 | m_controls->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
---|
269 |
|
---|
270 | if (!smallScreen)
|
---|
271 | mainLayout->addWidget(m_controls);
|
---|
272 |
|
---|
273 | m_renderer->loadSourceFile(":res/deform/pathdeform.cpp");
|
---|
274 | m_renderer->loadDescription(":res/deform/pathdeform.html");
|
---|
275 | m_renderer->setDescriptionEnabled(false);
|
---|
276 |
|
---|
277 | connect(m_renderer, SIGNAL(clicked()), this, SLOT(showControls()));
|
---|
278 | connect(m_controls, SIGNAL(okPressed()), this, SLOT(hideControls()));
|
---|
279 | connect(m_controls, SIGNAL(quitPressed()), QApplication::instance(), SLOT(quit()));
|
---|
280 | }
|
---|
281 |
|
---|
282 |
|
---|
283 | void PathDeformWidget::showControls()
|
---|
284 | {
|
---|
285 | m_controls->showFullScreen();
|
---|
286 | }
|
---|
287 |
|
---|
288 | void PathDeformWidget::hideControls()
|
---|
289 | {
|
---|
290 | m_controls->hide();
|
---|
291 | }
|
---|
292 |
|
---|
293 | void PathDeformWidget::setStyle( QStyle * style )
|
---|
294 | {
|
---|
295 | QWidget::setStyle(style);
|
---|
296 | if (m_controls != 0)
|
---|
297 | {
|
---|
298 | m_controls->setStyle(style);
|
---|
299 |
|
---|
300 | QList<QWidget *> widgets = qFindChildren<QWidget *>(m_controls);
|
---|
301 | foreach (QWidget *w, widgets)
|
---|
302 | w->setStyle(style);
|
---|
303 | }
|
---|
304 | }
|
---|
305 |
|
---|
306 | static inline QRect circle_bounds(const QPointF ¢er, qreal radius, qreal compensation)
|
---|
307 | {
|
---|
308 | return QRect(qRound(center.x() - radius - compensation),
|
---|
309 | qRound(center.y() - radius - compensation),
|
---|
310 | qRound((radius + compensation) * 2),
|
---|
311 | qRound((radius + compensation) * 2));
|
---|
312 |
|
---|
313 | }
|
---|
314 |
|
---|
315 | const int LENS_EXTENT = 10;
|
---|
316 |
|
---|
317 | PathDeformRenderer::PathDeformRenderer(QWidget *widget, bool smallScreen)
|
---|
318 | : ArthurFrame(widget)
|
---|
319 | {
|
---|
320 | m_radius = 100;
|
---|
321 | m_pos = QPointF(m_radius, m_radius);
|
---|
322 | m_direction = QPointF(1, 1);
|
---|
323 | m_fontSize = 24;
|
---|
324 | m_animated = true;
|
---|
325 | m_repaintTimer.start(25, this);
|
---|
326 | m_repaintTracker.start();
|
---|
327 | m_intensity = 100;
|
---|
328 | m_smallScreen = smallScreen;
|
---|
329 |
|
---|
330 | // m_fpsTimer.start(1000, this);
|
---|
331 | // m_fpsCounter = 0;
|
---|
332 |
|
---|
333 | generateLensPixmap();
|
---|
334 | }
|
---|
335 |
|
---|
336 | void PathDeformRenderer::setText(const QString &text)
|
---|
337 | {
|
---|
338 | m_text = text;
|
---|
339 |
|
---|
340 | QFont f("times new roman,utopia");
|
---|
341 | f.setStyleStrategy(QFont::ForceOutline);
|
---|
342 | f.setPointSize(m_fontSize);
|
---|
343 | f.setStyleHint(QFont::Times);
|
---|
344 |
|
---|
345 | QFontMetrics fm(f);
|
---|
346 |
|
---|
347 | m_paths.clear();
|
---|
348 | m_pathBounds = QRect();
|
---|
349 |
|
---|
350 | QPointF advance(0, 0);
|
---|
351 |
|
---|
352 | bool do_quick = true;
|
---|
353 | for (int i=0; i<text.size(); ++i) {
|
---|
354 | if (text.at(i).unicode() >= 0x4ff && text.at(i).unicode() <= 0x1e00) {
|
---|
355 | do_quick = false;
|
---|
356 | break;
|
---|
357 | }
|
---|
358 | }
|
---|
359 |
|
---|
360 | if (do_quick) {
|
---|
361 | for (int i=0; i<text.size(); ++i) {
|
---|
362 | QPainterPath path;
|
---|
363 | path.addText(advance, f, text.mid(i, 1));
|
---|
364 | m_pathBounds |= path.boundingRect();
|
---|
365 | m_paths << path;
|
---|
366 | advance += QPointF(fm.width(text.mid(i, 1)), 0);
|
---|
367 | }
|
---|
368 | } else {
|
---|
369 | QPainterPath path;
|
---|
370 | path.addText(advance, f, text);
|
---|
371 | m_pathBounds |= path.boundingRect();
|
---|
372 | m_paths << path;
|
---|
373 | }
|
---|
374 |
|
---|
375 | for (int i=0; i<m_paths.size(); ++i)
|
---|
376 | m_paths[i] = m_paths[i] * QMatrix(1, 0, 0, 1, -m_pathBounds.x(), -m_pathBounds.y());
|
---|
377 |
|
---|
378 | update();
|
---|
379 | }
|
---|
380 |
|
---|
381 |
|
---|
382 | void PathDeformRenderer::generateLensPixmap()
|
---|
383 | {
|
---|
384 | qreal rad = m_radius + LENS_EXTENT;
|
---|
385 |
|
---|
386 | QRect bounds = circle_bounds(QPointF(), rad, 0);
|
---|
387 |
|
---|
388 | QPainter painter;
|
---|
389 |
|
---|
390 | if (preferImage()) {
|
---|
391 | m_lens_image = QImage(bounds.size(), QImage::Format_ARGB32_Premultiplied);
|
---|
392 | m_lens_image.fill(0);
|
---|
393 | painter.begin(&m_lens_image);
|
---|
394 | } else {
|
---|
395 | m_lens_pixmap = QPixmap(bounds.size());
|
---|
396 | m_lens_pixmap.fill(Qt::transparent);
|
---|
397 | painter.begin(&m_lens_pixmap);
|
---|
398 | }
|
---|
399 |
|
---|
400 | QRadialGradient gr(rad, rad, rad, 3 * rad / 5, 3 * rad / 5);
|
---|
401 | gr.setColorAt(0.0, QColor(255, 255, 255, 191));
|
---|
402 | gr.setColorAt(0.2, QColor(255, 255, 127, 191));
|
---|
403 | gr.setColorAt(0.9, QColor(150, 150, 200, 63));
|
---|
404 | gr.setColorAt(0.95, QColor(0, 0, 0, 127));
|
---|
405 | gr.setColorAt(1, QColor(0, 0, 0, 0));
|
---|
406 | painter.setRenderHint(QPainter::Antialiasing);
|
---|
407 | painter.setBrush(gr);
|
---|
408 | painter.setPen(Qt::NoPen);
|
---|
409 | painter.drawEllipse(0, 0, bounds.width(), bounds.height());
|
---|
410 | }
|
---|
411 |
|
---|
412 |
|
---|
413 | void PathDeformRenderer::setAnimated(bool animated)
|
---|
414 | {
|
---|
415 | m_animated = animated;
|
---|
416 |
|
---|
417 | if (m_animated) {
|
---|
418 | // m_fpsTimer.start(1000, this);
|
---|
419 | // m_fpsCounter = 0;
|
---|
420 | m_repaintTimer.start(25, this);
|
---|
421 | m_repaintTracker.start();
|
---|
422 | } else {
|
---|
423 | // m_fpsTimer.stop();
|
---|
424 | m_repaintTimer.stop();
|
---|
425 | }
|
---|
426 | }
|
---|
427 |
|
---|
428 | void PathDeformRenderer::timerEvent(QTimerEvent *e)
|
---|
429 | {
|
---|
430 |
|
---|
431 | if (e->timerId() == m_repaintTimer.timerId()) {
|
---|
432 |
|
---|
433 | if (QLineF(QPointF(0,0), m_direction).length() > 1)
|
---|
434 | m_direction *= 0.995;
|
---|
435 | qreal time = m_repaintTracker.restart();
|
---|
436 |
|
---|
437 | QRect rectBefore = circle_bounds(m_pos, m_radius, m_fontSize);
|
---|
438 |
|
---|
439 | qreal dx = m_direction.x();
|
---|
440 | qreal dy = m_direction.y();
|
---|
441 | if (time > 0) {
|
---|
442 | dx = dx * time * .1;
|
---|
443 | dy = dy * time * .1;
|
---|
444 | }
|
---|
445 |
|
---|
446 | m_pos += QPointF(dx, dy);
|
---|
447 |
|
---|
448 |
|
---|
449 |
|
---|
450 | if (m_pos.x() - m_radius < 0) {
|
---|
451 | m_direction.setX(-m_direction.x());
|
---|
452 | m_pos.setX(m_radius);
|
---|
453 | } else if (m_pos.x() + m_radius > width()) {
|
---|
454 | m_direction.setX(-m_direction.x());
|
---|
455 | m_pos.setX(width() - m_radius);
|
---|
456 | }
|
---|
457 |
|
---|
458 | if (m_pos.y() - m_radius < 0) {
|
---|
459 | m_direction.setY(-m_direction.y());
|
---|
460 | m_pos.setY(m_radius);
|
---|
461 | } else if (m_pos.y() + m_radius > height()) {
|
---|
462 | m_direction.setY(-m_direction.y());
|
---|
463 | m_pos.setY(height() - m_radius);
|
---|
464 | }
|
---|
465 |
|
---|
466 | #ifdef QT_OPENGL_SUPPORT
|
---|
467 | if (usesOpenGL()) {
|
---|
468 | update();
|
---|
469 | } else
|
---|
470 | #endif
|
---|
471 | {
|
---|
472 | QRect rectAfter = circle_bounds(m_pos, m_radius, m_fontSize);
|
---|
473 | update(rectAfter | rectBefore);
|
---|
474 | QApplication::syncX();
|
---|
475 | }
|
---|
476 | }
|
---|
477 | // else if (e->timerId() == m_fpsTimer.timerId()) {
|
---|
478 | // printf("fps: %d\n", m_fpsCounter);
|
---|
479 | // emit frameRate(m_fpsCounter);
|
---|
480 | // m_fpsCounter = 0;
|
---|
481 |
|
---|
482 | // }
|
---|
483 | }
|
---|
484 |
|
---|
485 | void PathDeformRenderer::mousePressEvent(QMouseEvent *e)
|
---|
486 | {
|
---|
487 | setDescriptionEnabled(false);
|
---|
488 |
|
---|
489 | m_repaintTimer.stop();
|
---|
490 | m_offset = QPointF();
|
---|
491 | if (QLineF(m_pos, e->pos()).length() <= m_radius)
|
---|
492 | m_offset = m_pos - e->pos();
|
---|
493 |
|
---|
494 | m_mousePress = e->pos();
|
---|
495 |
|
---|
496 | // If we're not running in small screen mode, always assume we're dragging
|
---|
497 | m_mouseDrag = !m_smallScreen;
|
---|
498 |
|
---|
499 | mouseMoveEvent(e);
|
---|
500 | }
|
---|
501 |
|
---|
502 | void PathDeformRenderer::mouseReleaseEvent(QMouseEvent *e)
|
---|
503 | {
|
---|
504 | if (e->buttons() == Qt::NoButton && m_animated) {
|
---|
505 | m_repaintTimer.start(10, this);
|
---|
506 | m_repaintTracker.start();
|
---|
507 | }
|
---|
508 |
|
---|
509 | if (!m_mouseDrag && m_smallScreen)
|
---|
510 | emit clicked();
|
---|
511 | }
|
---|
512 |
|
---|
513 | void PathDeformRenderer::mouseMoveEvent(QMouseEvent *e)
|
---|
514 | {
|
---|
515 | if (!m_mouseDrag && (QLineF(m_mousePress, e->pos()).length() > 25.0) )
|
---|
516 | m_mouseDrag = true;
|
---|
517 |
|
---|
518 | if (m_mouseDrag) {
|
---|
519 | QRect rectBefore = circle_bounds(m_pos, m_radius, m_fontSize);
|
---|
520 | if (e->type() == QEvent::MouseMove) {
|
---|
521 | QLineF line(m_pos, e->pos() + m_offset);
|
---|
522 | line.setLength(line.length() * .1);
|
---|
523 | QPointF dir(line.dx(), line.dy());
|
---|
524 | m_direction = (m_direction + dir) / 2;
|
---|
525 | }
|
---|
526 | m_pos = e->pos() + m_offset;
|
---|
527 | #ifdef QT_OPENGL_SUPPORT
|
---|
528 | if (usesOpenGL()) {
|
---|
529 | update();
|
---|
530 | } else
|
---|
531 | #endif
|
---|
532 | {
|
---|
533 | QRect rectAfter = circle_bounds(m_pos, m_radius, m_fontSize);
|
---|
534 | update(rectBefore | rectAfter);
|
---|
535 | }
|
---|
536 | }
|
---|
537 | }
|
---|
538 |
|
---|
539 | QPainterPath PathDeformRenderer::lensDeform(const QPainterPath &source, const QPointF &offset)
|
---|
540 | {
|
---|
541 | QPainterPath path;
|
---|
542 | path.addPath(source);
|
---|
543 |
|
---|
544 | qreal flip = m_intensity / qreal(100);
|
---|
545 |
|
---|
546 | for (int i=0; i<path.elementCount(); ++i) {
|
---|
547 | const QPainterPath::Element &e = path.elementAt(i);
|
---|
548 |
|
---|
549 | qreal x = e.x + offset.x();
|
---|
550 | qreal y = e.y + offset.y();
|
---|
551 |
|
---|
552 | qreal dx = x - m_pos.x();
|
---|
553 | qreal dy = y - m_pos.y();
|
---|
554 | qreal len = m_radius - qSqrt(dx * dx + dy * dy);
|
---|
555 |
|
---|
556 | if (len > 0) {
|
---|
557 | path.setElementPositionAt(i,
|
---|
558 | x + flip * dx * len / m_radius,
|
---|
559 | y + flip * dy * len / m_radius);
|
---|
560 | } else {
|
---|
561 | path.setElementPositionAt(i, x, y);
|
---|
562 | }
|
---|
563 |
|
---|
564 | }
|
---|
565 |
|
---|
566 | return path;
|
---|
567 | }
|
---|
568 |
|
---|
569 |
|
---|
570 | void PathDeformRenderer::paint(QPainter *painter)
|
---|
571 | {
|
---|
572 | int pad_x = 5;
|
---|
573 | int pad_y = 5;
|
---|
574 |
|
---|
575 | int skip_x = qRound(m_pathBounds.width() + pad_x + m_fontSize/2);
|
---|
576 | int skip_y = qRound(m_pathBounds.height() + pad_y);
|
---|
577 |
|
---|
578 | painter->setPen(Qt::NoPen);
|
---|
579 | painter->setBrush(Qt::black);
|
---|
580 |
|
---|
581 | QRectF clip(painter->clipPath().boundingRect());
|
---|
582 |
|
---|
583 | int overlap = pad_x / 2;
|
---|
584 |
|
---|
585 | for (int start_y=0; start_y < height(); start_y += skip_y) {
|
---|
586 |
|
---|
587 | if (start_y > clip.bottom())
|
---|
588 | break;
|
---|
589 |
|
---|
590 | int start_x = -overlap;
|
---|
591 | for (; start_x < width(); start_x += skip_x) {
|
---|
592 |
|
---|
593 | if (start_y + skip_y >= clip.top() &&
|
---|
594 | start_x + skip_x >= clip.left() &&
|
---|
595 | start_x <= clip.right()) {
|
---|
596 | for (int i=0; i<m_paths.size(); ++i) {
|
---|
597 | QPainterPath path = lensDeform(m_paths[i], QPointF(start_x, start_y));
|
---|
598 | painter->drawPath(path);
|
---|
599 | }
|
---|
600 | }
|
---|
601 | }
|
---|
602 | overlap = skip_x - (start_x - width());
|
---|
603 |
|
---|
604 | }
|
---|
605 |
|
---|
606 | if (preferImage()) {
|
---|
607 | painter->drawImage(m_pos - QPointF(m_radius + LENS_EXTENT, m_radius + LENS_EXTENT),
|
---|
608 | m_lens_image);
|
---|
609 | } else {
|
---|
610 | painter->drawPixmap(m_pos - QPointF(m_radius + LENS_EXTENT, m_radius + LENS_EXTENT),
|
---|
611 | m_lens_pixmap);
|
---|
612 | }
|
---|
613 | }
|
---|
614 |
|
---|
615 |
|
---|
616 |
|
---|
617 | void PathDeformRenderer::setRadius(int radius)
|
---|
618 | {
|
---|
619 | qreal max = qMax(m_radius, (qreal)radius);
|
---|
620 | m_radius = radius;
|
---|
621 | generateLensPixmap();
|
---|
622 | if (!m_animated || m_radius < max) {
|
---|
623 | #ifdef QT_OPENGL_SUPPORT
|
---|
624 | if (usesOpenGL()) {
|
---|
625 | update();
|
---|
626 | } else
|
---|
627 | #endif
|
---|
628 | {
|
---|
629 | update(circle_bounds(m_pos, max, m_fontSize));
|
---|
630 | }
|
---|
631 | }
|
---|
632 | }
|
---|
633 |
|
---|
634 | void PathDeformRenderer::setIntensity(int intensity)
|
---|
635 | {
|
---|
636 | m_intensity = intensity;
|
---|
637 | if (!m_animated) {
|
---|
638 | #ifdef QT_OPENGL_SUPPORT
|
---|
639 | if (usesOpenGL()) {
|
---|
640 | update();
|
---|
641 | } else
|
---|
642 | #endif
|
---|
643 | {
|
---|
644 | update(circle_bounds(m_pos, m_radius, m_fontSize));
|
---|
645 | }
|
---|
646 | }
|
---|
647 | }
|
---|