libs/flake
KoPathPoint.cppGo to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "KoPathPoint.h"
00023 #include "KoPathShape.h"
00024 #include "KoPointGroup.h"
00025
00026 #include <KDebug>
00027 #include <QtGui/QPainter>
00028 #include <QPointF>
00029
00030 #include <math.h>
00031
00032 class KoPathPoint::Private
00033 {
00034 public:
00035 Private()
00036 : shape(0), properties(Normal), pointGroup(0)
00037 , activeControlPoint1(false), activeControlPoint2(false) {}
00038 KoPathShape * shape;
00039 QPointF point;
00040 QPointF controlPoint1;
00041 QPointF controlPoint2;
00042 KoPointProperties properties;
00043 KoPointGroup * pointGroup;
00044 bool activeControlPoint1;
00045 bool activeControlPoint2;
00046 };
00047
00048 KoPathPoint::KoPathPoint(const KoPathPoint & pathPoint)
00049 : d(new Private())
00050 {
00051 d->shape = pathPoint.d->shape;
00052 d->point = pathPoint.d->point;
00053 d->controlPoint1 = pathPoint.d->controlPoint1;
00054 d->controlPoint2 = pathPoint.d->controlPoint2;
00055 d->properties = pathPoint.d->properties;
00056 d->activeControlPoint1 = pathPoint.d->activeControlPoint1;
00057 d->activeControlPoint2 = pathPoint.d->activeControlPoint2;
00058 }
00059
00060 KoPathPoint::KoPathPoint()
00061 : d(new Private())
00062 {
00063 }
00064
00065 KoPathPoint::KoPathPoint(KoPathShape * path, const QPointF & point, KoPointProperties properties)
00066 : d(new Private())
00067 {
00068 d->shape = path;
00069 d->point = point;
00070 d->properties = properties;
00071 }
00072
00073 KoPathPoint::~KoPathPoint()
00074 {
00075 delete d;
00076 }
00077
00078 KoPathPoint& KoPathPoint::operator=(const KoPathPoint & rhs)
00079 {
00080 if (this == &rhs)
00081 return (*this);
00082
00083 d->shape = rhs.d->shape;
00084 d->point = rhs.d->point;
00085 d->controlPoint1 = rhs.d->controlPoint1;
00086 d->controlPoint2 = rhs.d->controlPoint2;
00087 d->properties = rhs.d->properties;
00088
00089 d->activeControlPoint1 = rhs.d->activeControlPoint1;
00090 d->activeControlPoint2 = rhs.d->activeControlPoint2;
00091
00092 return (*this);
00093 }
00094
00095 bool KoPathPoint::operator == (const KoPathPoint &rhs) const
00096 {
00097 if (d->point != rhs.d->point)
00098 return false;
00099 if (d->controlPoint1 != rhs.d->controlPoint1)
00100 return false;
00101 if (d->controlPoint2 != rhs.d->controlPoint2)
00102 return false;
00103 if (d->properties != rhs.d->properties)
00104 return false;
00105 if (d->activeControlPoint1 != rhs.d->activeControlPoint1)
00106 return false;
00107 if (d->activeControlPoint2 != rhs.d->activeControlPoint2)
00108 return false;
00109 return true;
00110 }
00111
00112 void KoPathPoint::setPoint(const QPointF & point)
00113 {
00114 d->point = point;
00115 if (d->shape)
00116 d->shape->notifyChanged();
00117 }
00118
00119 void KoPathPoint::setControlPoint1(const QPointF & point)
00120 {
00121 d->controlPoint1 = point;
00122 d->activeControlPoint1 = true;
00123 if (d->shape)
00124 d->shape->notifyChanged();
00125 }
00126
00127 void KoPathPoint::setControlPoint2(const QPointF & point)
00128 {
00129 d->controlPoint2 = point;
00130 d->activeControlPoint2 = true;
00131 if (d->shape)
00132 d->shape->notifyChanged();
00133 }
00134
00135 void KoPathPoint::removeControlPoint1()
00136 {
00137 d->activeControlPoint1 = false;
00138 d->properties &= ~IsSmooth;
00139 d->properties &= ~IsSymmetric;
00140 if (d->shape)
00141 d->shape->notifyChanged();
00142 }
00143
00144 void KoPathPoint::removeControlPoint2()
00145 {
00146 d->activeControlPoint2 = false;
00147 d->properties &= ~IsSmooth;
00148 d->properties &= ~IsSymmetric;
00149 if (d->shape)
00150 d->shape->notifyChanged();
00151 }
00152
00153 void KoPathPoint::setProperties(KoPointProperties properties)
00154 {
00155 d->properties = properties;
00156
00157 if ((d->properties & StartSubpath) == 0 && (d->properties & StopSubpath) == 0)
00158 d->properties &= ~CloseSubpath;
00159
00160 if (! activeControlPoint1() || ! activeControlPoint2()) {
00161
00162 d->properties &= ~IsSmooth;
00163 d->properties &= ~IsSymmetric;
00164 }
00165
00166 if (d->shape)
00167 d->shape->notifyChanged();
00168 }
00169
00170 void KoPathPoint::setProperty(KoPointProperty property)
00171 {
00172 switch (property) {
00173 case StartSubpath:
00174 case StopSubpath:
00175 case CloseSubpath:
00176
00177 break;
00178 case IsSmooth:
00179 d->properties &= ~IsSymmetric;
00180 break;
00181 case IsSymmetric:
00182 d->properties &= ~IsSmooth;
00183 break;
00184 default: return;
00185 }
00186
00187 d->properties |= property;
00188
00189 if (! activeControlPoint1() || ! activeControlPoint2()) {
00190
00191 d->properties &= ~IsSymmetric;
00192 d->properties &= ~IsSmooth;
00193 }
00194 }
00195
00196 void KoPathPoint::unsetProperty(KoPointProperty property)
00197 {
00198 switch (property) {
00199 case StartSubpath:
00200 if (d->properties & StartSubpath && (d->properties & StopSubpath) == 0)
00201 d->properties &= ~CloseSubpath;
00202 break;
00203 case StopSubpath:
00204 if (d->properties & StopSubpath && (d->properties & StartSubpath) == 0)
00205 d->properties &= ~CloseSubpath;
00206 break;
00207 case CloseSubpath:
00208 if (d->properties & StartSubpath || d->properties & StopSubpath) {
00209 d->properties &= ~IsSmooth;
00210 d->properties &= ~IsSymmetric;
00211 }
00212 break;
00213 case IsSmooth:
00214 case IsSymmetric:
00215
00216 break;
00217 default: return;
00218 }
00219 d->properties &= ~property;
00220 }
00221
00222 bool KoPathPoint::activeControlPoint1() const
00223 {
00224
00225 if ((d->properties & StartSubpath) && (d->properties & CloseSubpath) == 0)
00226 return false;
00227
00228 return d->activeControlPoint1;
00229 }
00230
00231 bool KoPathPoint::activeControlPoint2() const
00232 {
00233
00234 if ((d->properties & StopSubpath) && (d->properties & CloseSubpath) == 0)
00235 return false;
00236
00237 return d->activeControlPoint2;
00238 }
00239
00240 void KoPathPoint::map(const QMatrix &matrix, bool mapGroup)
00241 {
00242 if (d->pointGroup && mapGroup) {
00243 d->pointGroup->map(matrix);
00244 } else {
00245 d->point = matrix.map(d->point);
00246 d->controlPoint1 = matrix.map(d->controlPoint1);
00247 d->controlPoint2 = matrix.map(d->controlPoint2);
00248 }
00249 if (d->shape)
00250 d->shape->notifyChanged();
00251 }
00252
00253 void KoPathPoint::paint(QPainter &painter, int handleRadius, KoPointTypes types, bool active)
00254 {
00255 QRectF handle(-handleRadius, -handleRadius, 2*handleRadius, 2*handleRadius);
00256
00257 bool drawControlPoint1 = types & ControlPoint1 && (!active || activeControlPoint1());
00258 bool drawControlPoint2 = types & ControlPoint2 && (!active || activeControlPoint2());
00259
00260
00261 if (drawControlPoint2)
00262 painter.drawLine(point(), controlPoint2());
00263
00264 if (drawControlPoint1)
00265 painter.drawLine(point(), controlPoint1());
00266
00267
00268 QMatrix worldMatrix = painter.worldMatrix();
00269
00270 painter.setWorldMatrix(QMatrix());
00271
00272
00273 if (types & Node) {
00274 if (properties() & IsSmooth)
00275 painter.drawRect(handle.translated(worldMatrix.map(point())));
00276 else if (properties() & IsSymmetric) {
00277 QMatrix matrix;
00278 matrix.rotate(45.0);
00279 QPolygonF poly(handle);
00280 poly = matrix.map(poly);
00281 poly.translate(worldMatrix.map(point()));
00282 painter.drawPolygon(poly);
00283 } else
00284 painter.drawEllipse(handle.translated(worldMatrix.map(point())));
00285 }
00286
00287
00288 if (drawControlPoint2)
00289 painter.drawEllipse(handle.translated(worldMatrix.map(controlPoint2())));
00290
00291
00292 if (drawControlPoint1)
00293 painter.drawEllipse(handle.translated(worldMatrix.map(controlPoint1())));
00294
00295 painter.setWorldMatrix(worldMatrix);
00296 }
00297
00298 void KoPathPoint::setParent(KoPathShape* parent)
00299 {
00300
00301
00302 d->shape = parent;
00303 }
00304
00305 QRectF KoPathPoint::boundingRect(bool active) const
00306 {
00307 QRectF rect(d->point, QSize(1, 1));
00308 if (!active && activeControlPoint1()) {
00309 QRectF r1(d->point, QSize(1, 1));
00310 r1.setBottomRight(d->controlPoint1);
00311 rect = rect.unite(r1);
00312 }
00313 if (!active && activeControlPoint2()) {
00314 QRectF r2(d->point, QSize(1, 1));
00315 r2.setBottomRight(d->controlPoint2);
00316 rect = rect.unite(r2);
00317 }
00318 if (d->shape)
00319 return d->shape->shapeToDocument(rect);
00320 else
00321 return rect;
00322 }
00323
00324 void KoPathPoint::reverse()
00325 {
00326 qSwap(d->controlPoint1, d->controlPoint2);
00327 qSwap(d->activeControlPoint1, d->activeControlPoint2);
00328 KoPointProperties newProps = Normal;
00329 newProps |= d->properties & IsSmooth;
00330 newProps |= d->properties & IsSymmetric;
00331 newProps |= d->properties & StartSubpath;
00332 newProps |= d->properties & StopSubpath;
00333 newProps |= d->properties & CloseSubpath;
00334 d->properties = newProps;
00335 }
00336
00337 bool KoPathPoint::isSmooth(KoPathPoint * prev, KoPathPoint * next) const
00338 {
00339 QPointF t1, t2;
00340
00341 if (activeControlPoint1()) {
00342 t1 = point() - controlPoint1();
00343 } else {
00344
00345 if (! prev)
00346 return false;
00347 if (prev->activeControlPoint2())
00348 t1 = point() - prev->controlPoint2();
00349 else
00350 t1 = point() - prev->point();
00351 }
00352
00353 if (activeControlPoint2()) {
00354 t2 = controlPoint2() - point();
00355 } else {
00356
00357 if (! next)
00358 return false;
00359 if (next->activeControlPoint1())
00360 t2 = next->controlPoint1() - point();
00361 else
00362 t2 = next->point() - point();
00363 }
00364
00365
00366 qreal l1 = sqrt(t1.x() * t1.x() + t1.y() * t1.y());
00367 qreal l2 = sqrt(t2.x() * t2.x() + t2.y() * t2.y());
00368 if (qFuzzyCompare(l1 + 1, qreal(1.0)) || qFuzzyCompare(l2 + 1, qreal(1.0)))
00369 return true;
00370
00371 t1 /= l1;
00372 t2 /= l2;
00373
00374 qreal scalar = t1.x() * t2.x() + t1.y() * t2.y();
00375
00376 return qFuzzyCompare(scalar, qreal(1.0));
00377 }
00378
00379 void KoPathPoint::removeFromGroup()
00380 {
00381 if (d->pointGroup)
00382 d->pointGroup->remove(this);
00383 d->pointGroup = 0;
00384 }
00385
00386 void KoPathPoint::addToGroup(KoPointGroup *pointGroup)
00387 {
00388 if (d->pointGroup && d->pointGroup != pointGroup) {
00389
00390 removeFromGroup();
00391 }
00392 d->pointGroup = pointGroup;
00393 }
00394
00395 KoPathPoint::KoPointProperties KoPathPoint::properties() const
00396 {
00397 return d->properties;
00398 }
00399
00400 QPointF KoPathPoint::point() const
00401 {
00402 return d->point;
00403 }
00404
00405 QPointF KoPathPoint::controlPoint1() const
00406 {
00407 return d->controlPoint1;
00408 }
00409
00410 QPointF KoPathPoint::controlPoint2() const
00411 {
00412 return d->controlPoint2;
00413 }
00414
00415 KoPathShape * KoPathPoint::parent() const
00416 {
00417 return d->shape;
00418 }
00419
00420 KoPointGroup * KoPathPoint::group()
00421 {
00422 return d->pointGroup;
00423 }
|