1 /***************************************************************************
2 * Copyright (C) 2010 by Till Theato (root@ttill.de) *
3 * This file is part of Kdenlive (www.kdenlive.org). *
5 * Kdenlive is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
10 * Kdenlive 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. *
15 * You should have received a copy of the GNU General Public License *
16 * along with Kdenlive. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
19 #include "cubicbezierspline.h"
22 /** @brief For sorting a Bezier spline. Whether a is before b. */
23 static bool pointLessThan(const BPoint &a, const BPoint &b)
25 return a.p.x() < b.p.x();
28 CubicBezierSpline::CubicBezierSpline(QObject* parent) :
31 m_points.append(BPoint(QPointF(0, 0), QPointF(0, 0), QPointF(.1, .1)));
32 m_points.append(BPoint(QPointF(.9, .9), QPointF(1, 1), QPointF(1, 1)));
35 CubicBezierSpline::CubicBezierSpline(const CubicBezierSpline& spline, QObject* parent) :
38 m_points = spline.m_points;
41 CubicBezierSpline& CubicBezierSpline::operator=(const CubicBezierSpline& spline)
43 m_points = spline.m_points;
47 void CubicBezierSpline::fromString(const QString& spline)
51 const QStringList bpoints = spline.split(QLatin1Char('|'));
52 foreach(const QString &bpoint, bpoints) {
53 const QStringList points = bpoint.split(QLatin1Char('#'));
54 QList <QPointF> values;
55 foreach(const QString &point, points) {
56 QStringList xy = point.split(QLatin1Char(';'));
58 values.append(QPointF(xy.at(0).toDouble(), xy.at(1).toDouble()));
60 if (values.count() == 3) {
61 m_points.append(BPoint(values.at(0), values.at(1), values.at(2)));
69 QString CubicBezierSpline::toString() const
73 foreach(const BPoint &p, m_points) {
74 spline << QString::fromLatin1("%1;%2#%3;%4#%5;%6").arg(locale.toString(p.h1.x())).arg(locale.toString(p.h1.y()))
75 .arg(locale.toString(p.p.x())).arg(locale.toString(p.p.y()))
76 .arg(locale.toString(p.h2.x())).arg(locale.toString(p.h2.y()));
78 return spline.join(QLatin1String("|"));
81 int CubicBezierSpline::setPoint(int ix, const BPoint& point)
86 return indexOf(point); // in case it changed
89 QList <BPoint> CubicBezierSpline::points() const
94 void CubicBezierSpline::removePoint(int ix)
96 m_points.removeAt(ix);
99 int CubicBezierSpline::addPoint(const BPoint& point)
101 m_points.append(point);
104 return indexOf(point);
107 BPoint CubicBezierSpline::getPoint(int ix, int normalisedWidth, int normalisedHeight, bool invertHeight)
109 BPoint p = m_points.at(ix);
110 for (int i = 0; i < 3; ++i) {
111 p[i].rx() *= normalisedWidth;
112 p[i].ry() *= normalisedHeight;
114 p[i].ry() = normalisedHeight - p[i].y();
119 void CubicBezierSpline::validatePoints()
122 for (int i = 0; i < m_points.count() - 1; ++i) {
124 p2 = m_points.at(i+1);
125 p1.h2.setX(qBound(p1.p.x(), p1.h2.x(), p2.p.x()));
126 p2.h1.setX(qBound(p1.p.x(), p2.h1.x(), p2.p.x()));
132 void CubicBezierSpline::keepSorted()
134 qSort(m_points.begin(), m_points.end(), pointLessThan);
137 int CubicBezierSpline::indexOf(const BPoint& p)
139 if (m_points.indexOf(p) == -1) {
140 // point changed during validation process
141 for (int i = 0; i < m_points.count(); ++i) {
142 // this condition should be sufficient, too
143 if (m_points.at(i).p == p.p)
147 return m_points.indexOf(p);
152 #include "cubicbezierspline.moc"