demos/pathstroke/pathstroke.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2005-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the demonstration applications of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "pathstroke.h"
00025 #include "arthurstyle.h"
00026 #include "arthurwidgets.h"
00027 
00028 extern void draw_round_rect(QPainter *p, const QRect &bounds, int radius);
00029 
00030 PathStrokeWidget::PathStrokeWidget()
00031 {
00032     setWindowTitle(tr("Path Stroking"));
00033 
00034     // Setting up palette.
00035     QPalette pal = palette();
00036 //     pal.setBrush(QPalette::Background, Qt::white);
00037 //     pal.setBrush(QPalette::Foreground, QColor("aquamarine"));
00038 //     pal.setBrush(QPalette::Background, QPixmap("background.png"));
00039     setPalette(pal);
00040 
00041     // Widget construction and property setting
00042     m_renderer = new PathStrokeRenderer(this);
00043 
00044     QGroupBox *mainGroup = new QGroupBox(this);
00045 //     QWidget *mainGroup = new QWidget(this);
00046     mainGroup->setFixedWidth(180);
00047     mainGroup->setTitle("Path Stroking");
00048 
00049     QGroupBox *capGroup = new QGroupBox(mainGroup);
00050     capGroup->setAttribute(Qt::WA_ContentsPropagated);
00051     QRadioButton *flatCap = new QRadioButton(capGroup);
00052     QRadioButton *squareCap = new QRadioButton(capGroup);
00053     QRadioButton *roundCap = new QRadioButton(capGroup);
00054     capGroup->setTitle("Cap Style");
00055     flatCap->setText("Flat Cap");
00056     squareCap->setText("Square Cap");
00057     roundCap->setText("Round Cap");
00058 
00059     QGroupBox *joinGroup = new QGroupBox(mainGroup);
00060     joinGroup->setAttribute(Qt::WA_ContentsPropagated);
00061     QRadioButton *bevelJoin = new QRadioButton(joinGroup);
00062     QRadioButton *miterJoin = new QRadioButton(joinGroup);
00063     QRadioButton *roundJoin = new QRadioButton(joinGroup);
00064     joinGroup->setTitle("Join Style");
00065     bevelJoin->setText("Bevel Join");
00066     miterJoin->setText("Miter Join");
00067     roundJoin->setText("Round Join");
00068 
00069     QGroupBox *styleGroup = new QGroupBox(mainGroup);
00070     styleGroup->setAttribute(Qt::WA_ContentsPropagated);
00071     QRadioButton *solidLine = new QRadioButton(styleGroup);
00072     QRadioButton *dashLine = new QRadioButton(styleGroup);
00073     QRadioButton *dotLine = new QRadioButton(styleGroup);
00074     QRadioButton *dashDotLine = new QRadioButton(styleGroup);
00075     QRadioButton *dashDotDotLine = new QRadioButton(styleGroup);
00076     QRadioButton *customDashLine = new QRadioButton(styleGroup);
00077     styleGroup->setTitle("Pen Style");
00078 #if 0
00079     solidLine->setText("Solid Line");
00080     dashLine->setText("Dash Line");
00081     dotLine->setText("Dot Line");
00082     dashDotLine->setText("Dash Dot Line");
00083     dashDotDotLine->setText("Dash Dot Dot Line");
00084 #else
00085     QPixmap line_solid(":res/images/line_solid.png");
00086     solidLine->setIcon(line_solid);
00087     solidLine->setIconSize(line_solid.size());
00088     QPixmap line_dashed(":res/images/line_dashed.png");
00089     dashLine->setIcon(line_dashed);
00090     dashLine->setIconSize(line_dashed.size());
00091     QPixmap line_dotted(":res/images/line_dotted.png");
00092     dotLine->setIcon(line_dotted);
00093     dotLine->setIconSize(line_dotted.size());
00094     QPixmap line_dash_dot(":res/images/line_dash_dot.png");
00095     dashDotLine->setIcon(line_dash_dot);
00096     dashDotLine->setIconSize(line_dash_dot.size());
00097     QPixmap line_dash_dot_dot(":res/images/line_dash_dot_dot.png");
00098     dashDotDotLine->setIcon(line_dash_dot_dot);
00099     dashDotDotLine->setIconSize(line_dash_dot_dot.size());
00100     customDashLine->setText("Custom Style");
00101 
00102     int fixedHeight = bevelJoin->sizeHint().height();
00103     solidLine->setFixedHeight(fixedHeight);
00104     dashLine->setFixedHeight(fixedHeight);
00105     dotLine->setFixedHeight(fixedHeight);
00106     dashDotLine->setFixedHeight(fixedHeight);
00107     dashDotDotLine->setFixedHeight(fixedHeight);
00108 #endif
00109 
00110     QGroupBox *pathModeGroup = new QGroupBox(mainGroup);
00111     pathModeGroup->setAttribute(Qt::WA_ContentsPropagated);
00112     QRadioButton *curveMode = new QRadioButton(pathModeGroup);
00113     QRadioButton *lineMode = new QRadioButton(pathModeGroup);
00114     pathModeGroup->setTitle("Path composed of");
00115     curveMode->setText("Curves");
00116     lineMode->setText("Lines");
00117 
00118     QGroupBox *penWidthGroup = new QGroupBox(mainGroup);
00119     penWidthGroup->setAttribute(Qt::WA_ContentsPropagated);
00120     QSlider *penWidth = new QSlider(Qt::Horizontal, penWidthGroup);
00121     penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00122     penWidthGroup->setTitle("Pen Width");
00123     penWidth->setRange(0, 500);
00124 
00125 #if 0
00126     QCheckBox *animated = new QCheckBox(mainGroup);
00127     animated->setText("Animated");
00128 #else
00129     QPushButton *animated = new QPushButton(mainGroup);
00130     animated->setText("Animate");
00131     animated->setCheckable(true);
00132 #endif
00133 
00134     QPushButton *showSourceButton = new QPushButton(mainGroup);
00135     showSourceButton->setText("Show Source");
00136 #ifdef QT_OPENGL_SUPPORT
00137     QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
00138     enableOpenGLButton->setText("Use OpenGL");
00139     enableOpenGLButton->setCheckable(true);
00140     enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
00141     if (!QGLFormat::hasOpenGL())
00142         enableOpenGLButton->hide();
00143 #endif
00144     QPushButton *whatsThisButton = new QPushButton(mainGroup);
00145     whatsThisButton->setText("What's This?");
00146     whatsThisButton->setCheckable(true);
00147 
00148     // Layouting
00149     QHBoxLayout *viewLayout = new QHBoxLayout(this);
00150     viewLayout->addWidget(m_renderer);
00151     viewLayout->addWidget(mainGroup);
00152 
00153     QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
00154     mainGroupLayout->setMargin(3);
00155     mainGroupLayout->addWidget(capGroup);
00156     mainGroupLayout->addWidget(joinGroup);
00157     mainGroupLayout->addWidget(styleGroup);
00158     mainGroupLayout->addWidget(penWidthGroup);
00159     mainGroupLayout->addWidget(pathModeGroup);
00160     mainGroupLayout->addWidget(animated);
00161     mainGroupLayout->addStretch(1);
00162     mainGroupLayout->addWidget(showSourceButton);
00163 #ifdef QT_OPENGL_SUPPORT
00164     mainGroupLayout->addWidget(enableOpenGLButton);
00165 #endif
00166     mainGroupLayout->addWidget(whatsThisButton);
00167 
00168     QVBoxLayout *capGroupLayout = new QVBoxLayout(capGroup);
00169     capGroupLayout->addWidget(flatCap);
00170     capGroupLayout->addWidget(squareCap);
00171     capGroupLayout->addWidget(roundCap);
00172 
00173     QVBoxLayout *joinGroupLayout = new QVBoxLayout(joinGroup);
00174     joinGroupLayout->addWidget(bevelJoin);
00175     joinGroupLayout->addWidget(miterJoin);
00176     joinGroupLayout->addWidget(roundJoin);
00177 
00178     QVBoxLayout *styleGroupLayout = new QVBoxLayout(styleGroup);
00179     styleGroupLayout->addWidget(solidLine);
00180     styleGroupLayout->addWidget(dashLine);
00181     styleGroupLayout->addWidget(dotLine);
00182     styleGroupLayout->addWidget(dashDotLine);
00183     styleGroupLayout->addWidget(dashDotDotLine);
00184     styleGroupLayout->addWidget(customDashLine);
00185 
00186     QVBoxLayout *pathModeGroupLayout = new QVBoxLayout(pathModeGroup);
00187     pathModeGroupLayout->addWidget(curveMode);
00188     pathModeGroupLayout->addWidget(lineMode);
00189 
00190     QVBoxLayout *penWidthLayout = new QVBoxLayout(penWidthGroup);
00191     penWidthLayout->addWidget(penWidth);
00192 
00193     // Set up connections
00194     connect(penWidth, SIGNAL(valueChanged(int)),
00195             m_renderer, SLOT(setPenWidth(int)));
00196     connect(animated, SIGNAL(toggled(bool)),
00197             m_renderer, SLOT(setAnimation(bool)));
00198 
00199     connect(flatCap, SIGNAL(clicked()), m_renderer, SLOT(setFlatCap()));
00200     connect(squareCap, SIGNAL(clicked()), m_renderer, SLOT(setSquareCap()));
00201     connect(roundCap, SIGNAL(clicked()), m_renderer, SLOT(setRoundCap()));
00202 
00203     connect(bevelJoin, SIGNAL(clicked()), m_renderer, SLOT(setBevelJoin()));
00204     connect(miterJoin, SIGNAL(clicked()), m_renderer, SLOT(setMiterJoin()));
00205     connect(roundJoin, SIGNAL(clicked()), m_renderer, SLOT(setRoundJoin()));
00206 
00207     connect(curveMode, SIGNAL(clicked()), m_renderer, SLOT(setCurveMode()));
00208     connect(lineMode, SIGNAL(clicked()), m_renderer, SLOT(setLineMode()));
00209 
00210     connect(solidLine, SIGNAL(clicked()), m_renderer, SLOT(setSolidLine()));
00211     connect(dashLine, SIGNAL(clicked()), m_renderer, SLOT(setDashLine()));
00212     connect(dotLine, SIGNAL(clicked()), m_renderer, SLOT(setDotLine()));
00213     connect(dashDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotLine()));
00214     connect(dashDotDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotDotLine()));
00215     connect(customDashLine, SIGNAL(clicked()), m_renderer, SLOT(setCustomDashLine()));
00216 
00217     connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource()));
00218 #ifdef QT_OPENGL_SUPPORT
00219     connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
00220 #endif
00221     connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool)));
00222     connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)),
00223             whatsThisButton, SLOT(setChecked(bool)));
00224 
00225     // Set the defaults
00226     animated->setChecked(true);
00227     flatCap->setChecked(true);
00228     bevelJoin->setChecked(true);
00229     penWidth->setValue(50);
00230     curveMode->setChecked(true);
00231     solidLine->setChecked(true);
00232 
00233     m_renderer->loadSourceFile(":res/pathstroke.cpp");
00234     m_renderer->loadDescription(":res/pathstroke.html");
00235 }
00236 
00237 
00238 PathStrokeRenderer::PathStrokeRenderer(QWidget *parent)
00239     : ArthurFrame(parent)
00240 {
00241     m_pointSize = 10;
00242     m_activePoint = -1;
00243     m_capStyle = Qt::FlatCap;
00244     m_joinStyle = Qt::BevelJoin;
00245     m_pathMode = CurveMode;
00246     m_penWidth = 1;
00247     m_penStyle = Qt::SolidLine;
00248     m_wasAnimated = true;
00249     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00250 }
00251 
00252 void PathStrokeRenderer::paint(QPainter *painter)
00253 {
00254     if (m_points.isEmpty())
00255         initializePoints();
00256 
00257     painter->setRenderHint(QPainter::Antialiasing);
00258 
00259     QPalette pal = palette();
00260     painter->setPen(Qt::NoPen);
00261 
00262     // Construct the path
00263     QPainterPath path;
00264     path.moveTo(m_points.at(0));
00265 
00266     if (m_pathMode == LineMode) {
00267         for (int i=1; i<m_points.size(); ++i) {
00268             path.lineTo(m_points.at(i));
00269         }
00270     } else {
00271         int i=1;
00272         while (i + 2 < m_points.size()) {
00273             path.cubicTo(m_points.at(i), m_points.at(i+1), m_points.at(i+2));
00274             i += 3;
00275         }
00276         while (i < m_points.size()) {
00277             path.lineTo(m_points.at(i));
00278             ++i;
00279         }
00280     }
00281 
00282     // Draw the path
00283     {
00284         QColor lg = Qt::red;
00285 
00286         // The "custom" pen
00287         if (m_penStyle == Qt::NoPen) {
00288             QPainterPathStroker stroker;
00289             stroker.setWidth(m_penWidth);
00290             stroker.setJoinStyle(m_joinStyle);
00291             stroker.setCapStyle(m_capStyle);
00292 
00293             QVector<qreal> dashes;
00294             qreal space = 4;
00295             dashes << 1 << space
00296                    << 3 << space
00297                    << 9 << space
00298                    << 27 << space
00299                    << 9 << space
00300                    << 3 << space;
00301             stroker.setDashPattern(dashes);
00302             QPainterPath stroke = stroker.createStroke(path);
00303             painter->fillPath(stroke, lg);
00304 
00305         } else {
00306             QPen pen(lg, m_penWidth, m_penStyle, m_capStyle, m_joinStyle);
00307             painter->strokePath(path, pen);
00308         }
00309     }
00310 
00311     if (1) {
00312         // Draw the control points
00313         painter->setPen(QColor(50, 100, 120, 200));
00314         painter->setBrush(QColor(200, 200, 210, 120));
00315         for (int i=0; i<m_points.size(); ++i) {
00316             QPointF pos = m_points.at(i);
00317             painter->drawEllipse(QRectF(pos.x() - m_pointSize,
00318                                        pos.y() - m_pointSize,
00319                                        m_pointSize*2, m_pointSize*2));
00320         }
00321         painter->setPen(QPen(Qt::lightGray, 0, Qt::SolidLine));
00322         painter->setBrush(Qt::NoBrush);
00323         painter->drawPolyline(m_points);
00324     }
00325 
00326 }
00327 
00328 void PathStrokeRenderer::initializePoints()
00329 {
00330     const int count = 7;
00331     m_points.clear();
00332     m_vectors.clear();
00333 
00334     QMatrix m;
00335     double rot = 360 / count;
00336     QPointF center(width() / 2, height() / 2);
00337     QMatrix vm;
00338     vm.shear(2, -1);
00339     vm.scale(3, 3);
00340 
00341     for (int i=0; i<count; ++i) {
00342         m_vectors << QPointF(.1f, .25f) * (m * vm);
00343         m_points << QPointF(0, 100) * m + center;
00344         m.rotate(rot);
00345     }
00346 }
00347 
00348 void PathStrokeRenderer::updatePoints()
00349 {
00350     double pad = 10;
00351     double left = pad;
00352     double right = width() - pad;
00353     double top = pad;
00354     double bottom = height() - pad;
00355 
00356     Q_ASSERT(m_points.size() == m_vectors.size());
00357     for (int i=0; i<m_points.size(); ++i) {
00358 
00359         if (i == m_activePoint)
00360             continue;
00361 
00362         QPointF pos = m_points.at(i);
00363         QPointF vec = m_vectors.at(i);
00364         pos += vec;
00365         if (pos.x() < left || pos.x() > right) {
00366             vec.setX(-vec.x());
00367             pos.setX(pos.x() < left ? left : right);
00368         } if (pos.y() < top || pos.y() > bottom) {
00369             vec.setY(-vec.y());
00370             pos.setY(pos.y() < top ? top : bottom);
00371         }
00372         m_points[i] = pos;
00373         m_vectors[i] = vec;
00374     }
00375     update();
00376 }
00377 
00378 void PathStrokeRenderer::mousePressEvent(QMouseEvent *e)
00379 {
00380     setDescriptionEnabled(false);
00381     m_activePoint = -1;
00382     qreal distance = -1;
00383     for (int i=0; i<m_points.size(); ++i) {
00384         qreal d = QLineF(e->pos(), m_points.at(i)).length();
00385         if ((distance < 0 && d < 8 * m_pointSize) || d < distance) {
00386             distance = d;
00387             m_activePoint = i;
00388         }
00389     }
00390 
00391     if (m_activePoint != -1) {
00392         m_wasAnimated = m_timer.isActive();
00393         setAnimation(false);
00394         mouseMoveEvent(e);
00395     }
00396 }
00397 
00398 void PathStrokeRenderer::mouseMoveEvent(QMouseEvent *e)
00399 {
00400     if (m_activePoint >= 0 && m_activePoint < m_points.size()) {
00401         m_points[m_activePoint] = e->pos();
00402         update();
00403     }
00404 }
00405 
00406 void PathStrokeRenderer::mouseReleaseEvent(QMouseEvent *)
00407 {
00408     m_activePoint = -1;
00409     setAnimation(m_wasAnimated);
00410 }
00411 
00412 void PathStrokeRenderer::timerEvent(QTimerEvent *e)
00413 {
00414     if (e->timerId() == m_timer.timerId()) {
00415         updatePoints();
00416         QApplication::syncX();
00417     } // else if (e->timerId() == m_fpsTimer.timerId()) {
00418 //         emit frameRate(m_frameCount);
00419 //         m_frameCount = 0;
00420 //     }
00421 }
00422 
00423 void PathStrokeRenderer::setAnimation(bool animation)
00424 {
00425     m_timer.stop();
00426 //     m_fpsTimer.stop();
00427 
00428     if (animation) {
00429         m_timer.start(25, this);
00430 //         m_fpsTimer.start(1000, this);
00431 //         m_frameCount = 0;
00432     }
00433 }

Generated on Thu Mar 15 11:52:35 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1