Commit 16a5f36d authored by Dmitry Kazakov's avatar Dmitry Kazakov

Remove KoClipData class

Having 4 d-pointer-like object embedded one into each
other is too much for me.

At least now the shapes are correctly copied before
being assigned to the clipping path in SVG loading
code.
parent 7699443c
......@@ -44,119 +44,31 @@ QTransform scaleFromPercent(const QSizeF &size)
return QTransform().scale(w/1.0, h/1.0);
}
class Q_DECL_HIDDEN KoClipData::Private
{
public:
Private() : deleteClipShapes(true)
{
}
~Private()
{
if (deleteClipShapes) {
qDeleteAll(clipPathShapes);
clipPathShapes.clear();
}
}
QList<KoShape*> clipPathShapes;
bool deleteClipShapes; // TODO: deprecate this option!
};
KoClipData::KoClipData(KoPathShape *clipPathShape)
: d(new Private())
{
Q_ASSERT(clipPathShape);
d->clipPathShapes.append(clipPathShape);
}
KoClipData::KoClipData(const QList<KoPathShape*> &clipPathShapes)
: d(new Private())
{
Q_ASSERT(clipPathShapes.count());
Q_FOREACH (KoPathShape *shape, clipPathShapes) {
d->clipPathShapes << shape;
}
}
KoClipData::KoClipData(const QList<KoShape*> &clipPathShapes)
: d(new Private())
{
Q_ASSERT(clipPathShapes.count());
d->clipPathShapes = clipPathShapes;
}
KoClipData::KoClipData(const KoClipData &rhs)
: d(new Private())
{
Q_FOREACH (KoShape *shape, rhs.d->clipPathShapes) {
KoShape *clonedShape = shape->cloneShape();
KIS_ASSERT_RECOVER(clonedShape) { continue; }
d->clipPathShapes << clonedShape;
}
d->deleteClipShapes = rhs.d->deleteClipShapes;
}
KoClipData::~KoClipData()
{
delete d;
}
QList<KoShape*> KoClipData::clipPathShapes() const
{
return d->clipPathShapes;
}
void KoClipData::removeClipShapesOwnership()
{
d->deleteClipShapes = false;
}
class Q_DECL_HIDDEN KoClipPath::Private
{
public:
Private(KoClipData *data)
: clipData(data)
Private()
{}
Private(const Private &rhs)
: clipData(new KoClipData(*rhs.clipData)),
clipPath(rhs.clipPath),
: clipPath(rhs.clipPath),
clipRule(rhs.clipRule),
coordinates(rhs.coordinates),
initialTransformToShape(rhs.initialTransformToShape),
initialShapeSize(rhs.initialShapeSize)
{
}
Q_FOREACH (KoShape *shape, rhs.shapes) {
KoShape *clonedShape = shape->cloneShape();
KIS_ASSERT_RECOVER(clonedShape) { continue; }
~Private()
{
shapes.append(clonedShape);
}
}
void compileClipPath(KoShape *clippedShape)
~Private()
{
QList<KoShape*> clipShapes = clipData->clipPathShapes();
if (!clipShapes.count())
return;
initialShapeSize = clippedShape->outline().boundingRect().size();
initialTransformToShape = clippedShape->absoluteTransformation(0).inverted();
QTransform transformToShape = initialTransformToShape * scaleToPercent(initialShapeSize);
Q_FOREACH (KoShape *path, clipShapes) {
if (!path)
continue;
// map clip path to shape coordinates of clipped shape
QTransform m = path->absoluteTransformation(0) * transformToShape;
if (clipPath.isEmpty())
clipPath = m.map(path->outline());
else
clipPath |= m.map(path->outline());
}
qDeleteAll(shapes);
shapes.clear();
}
void collectShapePath(QPainterPath *result, const KoShape *shape) {
......@@ -177,7 +89,7 @@ public:
void compileClipPath()
{
QList<KoShape*> clipShapes = clipData->clipPathShapes();
QList<KoShape*> clipShapes = this->shapes;
if (clipShapes.isEmpty())
return;
......@@ -193,7 +105,7 @@ public:
}
}
QExplicitlySharedDataPointer<KoClipData> clipData; ///< the clip path data
QList<KoShape*> shapes;
QPainterPath clipPath; ///< the compiled clip path in shape coordinates of the clipped shape
Qt::FillRule clipRule = Qt::OddEvenFill;
CoordinateSystem coordinates = ObjectBoundingBox;
......@@ -201,19 +113,14 @@ public:
QSizeF initialShapeSize; ///< initial size of clipped shape
};
KoClipPath::KoClipPath(KoClipData *clipData, KoClipPath::CoordinateSystem coordinates)
: d( new Private(clipData) )
KoClipPath::KoClipPath(QList<KoShape*> clipShapes, KoClipPath::CoordinateSystem coordinates)
: d(new Private())
{
d->shapes = clipShapes;
d->coordinates = coordinates;
d->compileClipPath();
}
KoClipPath::KoClipPath(KoShape *clippedShape, KoClipData *clipData)
: d( new Private(clipData) )
{
d->compileClipPath(clippedShape);
}
KoClipPath::KoClipPath(const KoClipPath &rhs)
: d(new Private(*rhs.d))
{
......@@ -221,7 +128,6 @@ KoClipPath::KoClipPath(const KoClipPath &rhs)
KoClipPath::~KoClipPath()
{
delete d;
}
KoClipPath *KoClipPath::clone() const
......@@ -297,7 +203,7 @@ QList<KoPathShape*> KoClipPath::clipPathShapes() const
QList<KoPathShape*> shapes;
Q_FOREACH (KoShape *shape, d->clipData->clipPathShapes()) {
Q_FOREACH (KoShape *shape, d->shapes) {
KoPathShape *pathShape = dynamic_cast<KoPathShape*>(shape);
if (pathShape) {
shapes << pathShape;
......
......@@ -21,8 +21,9 @@
#define KOCLIPPATH_H
#include "kritaflake_export.h"
#include <QScopedPointer>
#include <QList>
#include <QSharedData>
#include <qnamespace.h>
class KoShape;
......@@ -33,34 +34,6 @@ class QTransform;
class QPainterPath;
class QSizeF;
/// Shared clip path data
class KRITAFLAKE_EXPORT KoClipData : public QSharedData
{
public:
/// Creates clip path data from a single path shape, takes ownership of the path shape
explicit KoClipData(KoPathShape *clipPathShape);
/// Creates clip path data from multiple path shapes, takes ownership of the path shapes
explicit KoClipData(const QList<KoPathShape*> &clipPathShapes);
explicit KoClipData(const QList<KoShape*> &clipPathShapes);
explicit KoClipData(const KoClipData &rhs);
/// Destroys the clip path data
~KoClipData();
/// Returns the clip path shapes
QList<KoShape*> clipPathShapes() const;
/// Gives up ownership of clip path shapes
void removeClipShapesOwnership();
private:
class Private;
Private * const d;
};
/// Clip path used to clip shapes
class KRITAFLAKE_EXPORT KoClipPath
{
......@@ -74,19 +47,11 @@ public:
/**
* Create a new shape clipping using the given clip data
* @param clipData shared clipping data containing the clip paths
* @param clipShapes define the clipping shapes, owned by KoClipPath!
* @param coordinates shows if ObjectBoundingBox or UserSpaceOnUse coordinate
* system is used.
*/
KoClipPath(KoClipData *clipData, CoordinateSystem coordinates);
/**
* Create a new shape clipping using the given clip data
* @param clippedShape the shape to clip
* @param clipData shared clipping data containing the clip paths
*/
KoClipPath(KoShape *clippedShape, KoClipData *clipData);
KoClipPath(QList<KoShape*> clipShapes, CoordinateSystem coordinates);
~KoClipPath();
KoClipPath *clone() const;
......@@ -125,7 +90,7 @@ private:
private:
class Private;
Private * const d;
const QScopedPointer<Private> d;
};
#endif // KOCLIPPATH_H
......@@ -1844,8 +1844,7 @@ void KoShape::loadOdfClipContour(const KoXmlElement &element, KoShapeLoadingCont
ps->loadContourOdf(child, context, scaleFactor);
ps->setTransformation(transformation());
KoClipData *cd = new KoClipData(ps);
KoClipPath *clipPath = new KoClipPath(this, cd);
KoClipPath *clipPath = new KoClipPath({ps}, KoClipPath::UserSpaceOnUse);
d->clipPath.reset(clipPath);
}
}
......
......@@ -26,6 +26,8 @@
#include <klocalizedstring.h>
#include "kis_pointer_utils.h"
class Q_DECL_HIDDEN KoShapeClipCommand::Private
{
public:
......@@ -37,7 +39,6 @@ public:
if (executed) {
qDeleteAll(oldClipPaths);
} else {
clipData->removeClipShapesOwnership();
qDeleteAll(newClipPaths);
}
}
......@@ -47,7 +48,6 @@ public:
QList<KoPathShape*> clipPathShapes;
QList<KoClipPath*> newClipPaths;
QList<KoShapeContainer*> oldParents;
QExplicitlySharedDataPointer<KoClipData> clipData;
KoShapeBasedDocumentBase *controller;
bool executed;
};
......@@ -57,10 +57,10 @@ KoShapeClipCommand::KoShapeClipCommand(KoShapeBasedDocumentBase *controller, con
{
d->shapesToClip = shapes;
d->clipPathShapes = clipPathShapes;
d->clipData = new KoClipData(clipPathShapes);
Q_FOREACH (KoShape *shape, d->shapesToClip) {
d->oldClipPaths.append(shape->clipPath());
d->newClipPaths.append(new KoClipPath(shape, d->clipData.data()));
d->newClipPaths.append(new KoClipPath(implicitCastList<KoShape*>(clipPathShapes), KoClipPath::UserSpaceOnUse));
}
Q_FOREACH (KoPathShape *path, clipPathShapes) {
......@@ -75,9 +75,8 @@ KoShapeClipCommand::KoShapeClipCommand(KoShapeBasedDocumentBase *controller, KoS
{
d->shapesToClip.append(shape);
d->clipPathShapes = clipPathShapes;
d->clipData = new KoClipData(clipPathShapes);
d->oldClipPaths.append(shape->clipPath());
d->newClipPaths.append(new KoClipPath(shape, d->clipData.data()));
d->newClipPaths.append(new KoClipPath(implicitCastList<KoShape*>(clipPathShapes), KoClipPath::UserSpaceOnUse));
Q_FOREACH (KoPathShape *path, clipPathShapes) {
d->oldParents.append(path->parent());
......
......@@ -926,7 +926,14 @@ void SvgParser::applyClipping(KoShape *shape)
if (!clipPath || clipPath->isEmpty())
return;
QList<KoShape*> shapes = clipPath->shapes();
QList<KoShape*> shapes;
Q_FOREACH (KoShape *item, clipPath->shapes()) {
KoShape *clonedShape = item->cloneShape();
KIS_ASSERT_RECOVER(clonedShape) { continue; }
shapes.append(clonedShape);
}
QTransform extraShapeTransform;
KIS_ASSERT_RECOVER_NOOP(m_coordinateSystemOnLoading.contains(shape));
......@@ -943,10 +950,9 @@ void SvgParser::applyClipping(KoShape *shape)
}
}
KoClipData *clipData = new KoClipData(shapes);
KoClipPath *clipPathObject = new KoClipPath(clipData,
clipPath->clipPathUnits() == SvgClipPathHelper::ObjectBoundingBox ?
KoClipPath::ObjectBoundingBox : KoClipPath::UserSpaceOnUse);
KoClipPath *clipPathObject = new KoClipPath(shapes,
clipPath->clipPathUnits() == SvgClipPathHelper::ObjectBoundingBox ?
KoClipPath::ObjectBoundingBox : KoClipPath::UserSpaceOnUse);
shape->setClipPath(clipPathObject);
}
......
......@@ -2128,8 +2128,7 @@ void TestSvgParser::testKoClipPathRendering()
shape2->setBackground(QSharedPointer<KoColorBackground>(new KoColorBackground(Qt::red)));
QScopedPointer<KoPathShape> clipShape1(KoPathShape::createShapeFromPainterPath(clipPath1));
KoClipData *koClipData1 = new KoClipData(clipShape1.take());
KoClipPath *koClipPath1 = new KoClipPath(koClipData1, KoClipPath::UserSpaceOnUse);
KoClipPath *koClipPath1 = new KoClipPath({clipShape1.take()}, KoClipPath::UserSpaceOnUse);
koClipPath1->setClipRule(Qt::WindingFill);
shape1->setClipPath(koClipPath1);
......@@ -2142,8 +2141,7 @@ void TestSvgParser::testKoClipPathRendering()
}
QScopedPointer<KoPathShape> clipShape2(KoPathShape::createShapeFromPainterPath(clipPath2));
KoClipData *koClipData2 = new KoClipData(clipShape2.take());
KoClipPath *koClipPath2 = new KoClipPath(koClipData2, KoClipPath::UserSpaceOnUse);
KoClipPath *koClipPath2 = new KoClipPath({clipShape2.take()}, KoClipPath::UserSpaceOnUse);
koClipPath2->setClipRule(Qt::WindingFill);
group->setClipPath(koClipPath2);
......@@ -2174,8 +2172,7 @@ void TestSvgParser::testKoClipPathRelativeRendering()
shape2->setBackground(QSharedPointer<KoColorBackground>(new KoColorBackground(Qt::red)));
QScopedPointer<KoPathShape> clipShape1(KoPathShape::createShapeFromPainterPath(clipPath1));
KoClipData *koClipData1 = new KoClipData(clipShape1.take());
KoClipPath *koClipPath1 = new KoClipPath(koClipData1, KoClipPath::UserSpaceOnUse);
KoClipPath *koClipPath1 = new KoClipPath({clipShape1.take()}, KoClipPath::UserSpaceOnUse);
koClipPath1->setClipRule(Qt::WindingFill);
shape1->setClipPath(koClipPath1);
......@@ -2188,8 +2185,7 @@ void TestSvgParser::testKoClipPathRelativeRendering()
}
QScopedPointer<KoPathShape> clipShape2(KoPathShape::createShapeFromPainterPath(clipPath2));
KoClipData *koClipData2 = new KoClipData(clipShape2.take());
KoClipPath *koClipPath2 = new KoClipPath(koClipData2, KoClipPath::ObjectBoundingBox);
KoClipPath *koClipPath2 = new KoClipPath({clipShape2.take()}, KoClipPath::ObjectBoundingBox);
koClipPath2->setClipRule(Qt::WindingFill);
group->setClipPath(koClipPath2);
......
/*
* Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef KIS_POINTER_UTILS_H
#define KIS_POINTER_UTILS_H
/**
* Coverts a list of objects with type T into a list of objects of type R.
* The conversion is done implicitly, therefore the c-tor of type R should
* support it. The main usage case is conversion of pointers in "descendant-
* to-parent" way.
*/
template <typename R, typename T>
inline QList<R> implicitCastList(const QList<T> &list)
{
QList<R> result;
Q_FOREACH(const T &item, list) {
result.append(item);
}
return result;
}
#endif // KIS_POINTER_UTILS_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment