|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the demonstration applications of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
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 PathDeformControls::PathDeformControls(QWidget *parent, PathDeformRenderer* renderer, bool smallScreen) |
|
57 : QWidget(parent) |
|
58 { |
|
59 m_renderer = renderer; |
|
60 |
|
61 if (smallScreen) |
|
62 layoutForSmallScreen(); |
|
63 else |
|
64 layoutForDesktop(); |
|
65 } |
|
66 |
|
67 |
|
68 void PathDeformControls::layoutForDesktop() |
|
69 { |
|
70 QGroupBox* mainGroup = new QGroupBox(this); |
|
71 mainGroup->setTitle(tr("Controls")); |
|
72 |
|
73 QGroupBox *radiusGroup = new QGroupBox(mainGroup); |
|
74 radiusGroup->setTitle(tr("Lens Radius")); |
|
75 QSlider *radiusSlider = new QSlider(Qt::Horizontal, radiusGroup); |
|
76 radiusSlider->setRange(15, 150); |
|
77 radiusSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); |
|
78 |
|
79 QGroupBox *deformGroup = new QGroupBox(mainGroup); |
|
80 deformGroup->setTitle(tr("Deformation")); |
|
81 QSlider *deformSlider = new QSlider(Qt::Horizontal, deformGroup); |
|
82 deformSlider->setRange(-100, 100); |
|
83 deformSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); |
|
84 |
|
85 QGroupBox *fontSizeGroup = new QGroupBox(mainGroup); |
|
86 fontSizeGroup->setTitle(tr("Font Size")); |
|
87 QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, fontSizeGroup); |
|
88 fontSizeSlider->setRange(16, 200); |
|
89 fontSizeSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); |
|
90 |
|
91 QGroupBox *textGroup = new QGroupBox(mainGroup); |
|
92 textGroup->setTitle(tr("Text")); |
|
93 QLineEdit *textInput = new QLineEdit(textGroup); |
|
94 |
|
95 QPushButton *animateButton = new QPushButton(mainGroup); |
|
96 animateButton->setText(tr("Animated")); |
|
97 animateButton->setCheckable(true); |
|
98 |
|
99 QPushButton *showSourceButton = new QPushButton(mainGroup); |
|
100 showSourceButton->setText(tr("Show Source")); |
|
101 |
|
102 #ifdef QT_OPENGL_SUPPORT |
|
103 QPushButton *enableOpenGLButton = new QPushButton(mainGroup); |
|
104 enableOpenGLButton->setText(tr("Use OpenGL")); |
|
105 enableOpenGLButton->setCheckable(true); |
|
106 enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); |
|
107 if (!QGLFormat::hasOpenGL()) |
|
108 enableOpenGLButton->hide(); |
|
109 #endif |
|
110 |
|
111 QPushButton *whatsThisButton = new QPushButton(mainGroup); |
|
112 whatsThisButton->setText(tr("What's This?")); |
|
113 whatsThisButton->setCheckable(true); |
|
114 |
|
115 |
|
116 mainGroup->setFixedWidth(180); |
|
117 |
|
118 QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup); |
|
119 mainGroupLayout->addWidget(radiusGroup); |
|
120 mainGroupLayout->addWidget(deformGroup); |
|
121 mainGroupLayout->addWidget(fontSizeGroup); |
|
122 mainGroupLayout->addWidget(textGroup); |
|
123 mainGroupLayout->addWidget(animateButton); |
|
124 mainGroupLayout->addStretch(1); |
|
125 #ifdef QT_OPENGL_SUPPORT |
|
126 mainGroupLayout->addWidget(enableOpenGLButton); |
|
127 #endif |
|
128 mainGroupLayout->addWidget(showSourceButton); |
|
129 mainGroupLayout->addWidget(whatsThisButton); |
|
130 |
|
131 QVBoxLayout *radiusGroupLayout = new QVBoxLayout(radiusGroup); |
|
132 radiusGroupLayout->addWidget(radiusSlider); |
|
133 |
|
134 QVBoxLayout *deformGroupLayout = new QVBoxLayout(deformGroup); |
|
135 deformGroupLayout->addWidget(deformSlider); |
|
136 |
|
137 QVBoxLayout *fontSizeGroupLayout = new QVBoxLayout(fontSizeGroup); |
|
138 fontSizeGroupLayout->addWidget(fontSizeSlider); |
|
139 |
|
140 QVBoxLayout *textGroupLayout = new QVBoxLayout(textGroup); |
|
141 textGroupLayout->addWidget(textInput); |
|
142 |
|
143 QVBoxLayout * mainLayout = new QVBoxLayout(this); |
|
144 mainLayout->addWidget(mainGroup); |
|
145 mainLayout->setMargin(0); |
|
146 |
|
147 connect(radiusSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setRadius(int))); |
|
148 connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int))); |
|
149 connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int))); |
|
150 connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool))); |
|
151 #ifdef QT_OPENGL_SUPPORT |
|
152 connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); |
|
153 #endif |
|
154 |
|
155 connect(textInput, SIGNAL(textChanged(QString)), m_renderer, SLOT(setText(QString))); |
|
156 connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)), |
|
157 whatsThisButton, SLOT(setChecked(bool))); |
|
158 connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool))); |
|
159 connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource())); |
|
160 |
|
161 animateButton->animateClick(); |
|
162 deformSlider->setValue(80); |
|
163 fontSizeSlider->setValue(120); |
|
164 radiusSlider->setValue(100); |
|
165 textInput->setText(tr("Qt")); |
|
166 } |
|
167 |
|
168 void PathDeformControls::layoutForSmallScreen() |
|
169 { |
|
170 QGroupBox* mainGroup = new QGroupBox(this); |
|
171 mainGroup->setTitle(tr("Controls")); |
|
172 |
|
173 QLabel *radiusLabel = new QLabel(mainGroup); |
|
174 radiusLabel->setText(tr("Lens Radius:")); |
|
175 QSlider *radiusSlider = new QSlider(Qt::Horizontal, mainGroup); |
|
176 radiusSlider->setRange(15, 150); |
|
177 radiusSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); |
|
178 |
|
179 QLabel *deformLabel = new QLabel(mainGroup); |
|
180 deformLabel->setText(tr("Deformation:")); |
|
181 QSlider *deformSlider = new QSlider(Qt::Horizontal, mainGroup); |
|
182 deformSlider->setRange(-100, 100); |
|
183 deformSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); |
|
184 |
|
185 QLabel *fontSizeLabel = new QLabel(mainGroup); |
|
186 fontSizeLabel->setText(tr("Font Size:")); |
|
187 QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, mainGroup); |
|
188 fontSizeSlider->setRange(16, 200); |
|
189 fontSizeSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); |
|
190 |
|
191 QPushButton *animateButton = new QPushButton(tr("Animated"), mainGroup); |
|
192 animateButton->setCheckable(true); |
|
193 |
|
194 #ifdef QT_OPENGL_SUPPORT |
|
195 QPushButton *enableOpenGLButton = new QPushButton(mainGroup); |
|
196 enableOpenGLButton->setText(tr("Use OpenGL")); |
|
197 enableOpenGLButton->setCheckable(mainGroup); |
|
198 enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); |
|
199 if (!QGLFormat::hasOpenGL()) |
|
200 enableOpenGLButton->hide(); |
|
201 #endif |
|
202 |
|
203 QPushButton *quitButton = new QPushButton(tr("Quit"), mainGroup); |
|
204 QPushButton *okButton = new QPushButton(tr("OK"), mainGroup); |
|
205 |
|
206 |
|
207 QGridLayout *mainGroupLayout = new QGridLayout(mainGroup); |
|
208 mainGroupLayout->setMargin(0); |
|
209 mainGroupLayout->addWidget(radiusLabel, 0, 0, Qt::AlignRight); |
|
210 mainGroupLayout->addWidget(radiusSlider, 0, 1); |
|
211 mainGroupLayout->addWidget(deformLabel, 1, 0, Qt::AlignRight); |
|
212 mainGroupLayout->addWidget(deformSlider, 1, 1); |
|
213 mainGroupLayout->addWidget(fontSizeLabel, 2, 0, Qt::AlignRight); |
|
214 mainGroupLayout->addWidget(fontSizeSlider, 2, 1); |
|
215 mainGroupLayout->addWidget(animateButton, 3,0, 1,2); |
|
216 #ifdef QT_OPENGL_SUPPORT |
|
217 mainGroupLayout->addWidget(enableOpenGLButton, 4,0, 1,2); |
|
218 #endif |
|
219 |
|
220 QVBoxLayout *mainLayout = new QVBoxLayout(this); |
|
221 mainLayout->addWidget(mainGroup); |
|
222 mainLayout->addStretch(1); |
|
223 mainLayout->addWidget(okButton); |
|
224 mainLayout->addWidget(quitButton); |
|
225 |
|
226 connect(quitButton, SIGNAL(clicked()), this, SLOT(emitQuitSignal())); |
|
227 connect(okButton, SIGNAL(clicked()), this, SLOT(emitOkSignal())); |
|
228 connect(radiusSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setRadius(int))); |
|
229 connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int))); |
|
230 connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int))); |
|
231 connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool))); |
|
232 #ifdef QT_OPENGL_SUPPORT |
|
233 connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); |
|
234 #endif |
|
235 |
|
236 |
|
237 animateButton->animateClick(); |
|
238 deformSlider->setValue(80); |
|
239 fontSizeSlider->setValue(120); |
|
240 |
|
241 QRect screen_size = QApplication::desktop()->screenGeometry(); |
|
242 radiusSlider->setValue(qMin(screen_size.width(), screen_size.height())/5); |
|
243 |
|
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 } |