Krita Source Code Documentation
Loading...
Searching...
No Matches
KoShapeGradientHandles.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2017 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QGradient>
10#include <KoShape.h>
13#include <KoShapeFillWrapper.h>
14#include <kis_assert.h>
15#include "kis_algebra_2d.h"
16
18 : m_fillVariant(fillVariant),
19 m_shape(shape)
20{
21}
22
24 QVector<Handle> result;
25
26 const QGradient *g = gradient();
27 if (!g) return result;
28
29 switch (g->type()) {
30 case QGradient::LinearGradient: {
31 const QLinearGradient *lgradient = static_cast<const QLinearGradient*>(g);
32 result << Handle(Handle::LinearStart, lgradient->start());
33 result << Handle(Handle::LinearEnd, lgradient->finalStop());
34 break;
35 }
36 case QGradient::RadialGradient: {
37 const QRadialGradient *rgradient = static_cast<const QRadialGradient*>(g);
38
39 result << Handle(Handle::RadialCenter, rgradient->center());
40
41 if (rgradient->center() != rgradient->focalPoint()) {
42 result << Handle(Handle::RadialFocalPoint, rgradient->focalPoint());
43 }
44
46 rgradient->center() + QPointF(rgradient->centerRadius(), 0));
47 break;
48 }
49 case QGradient::ConicalGradient:
50 // not supported
51 break;
52 case QGradient::NoGradient:
53 // not supported
54 break;
55 }
56
57 if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
58 const QRectF boundingRect = m_shape->outlineRect();
59 const QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
60 boundingRect.x(), boundingRect.y());
61 const QTransform t = gradientToUser * m_shape->absoluteTransformation();
62
63 QVector<Handle>::iterator it = result.begin();
64
65
66
67 for (; it != result.end(); ++it) {
68 it->pos = t.map(it->pos);
69 }
70 }
71
72 return result;
73}
74
75QGradient::Type KoShapeGradientHandles::type() const
76{
77 const QGradient *g = gradient();
78 return g ? g->type() : QGradient::NoGradient;
79}
80
82{
84
86 const QGradient *originalGradient = wrapper.gradient();
87 QTransform originalTransform = wrapper.gradientTransform();
88 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(originalGradient, 0);
89
90 QScopedPointer<QGradient> newGradient;
91
92 switch (originalGradient->type()) {
93 case QGradient::LinearGradient: {
95 handleType == Handle::LinearEnd, 0);
96
97 newGradient.reset(KoFlake::cloneGradient(originalGradient));
98 QLinearGradient *lgradient = static_cast<QLinearGradient*>(newGradient.data());
99
100 if (handleType == Handle::LinearStart) {
101 lgradient->setStart(getNewHandlePos(lgradient->start(), absoluteOffset, newGradient->coordinateMode()));
102 } else if (handleType == Handle::LinearEnd) {
103 lgradient->setFinalStop(getNewHandlePos(lgradient->finalStop(), absoluteOffset, newGradient->coordinateMode()));
104
105 }
106 break;
107 }
108 case QGradient::RadialGradient: {
109 newGradient.reset(KoFlake::cloneGradient(originalGradient));
110 QRadialGradient *rgradient = static_cast<QRadialGradient*>(newGradient.data());
111
112 if (handleType == Handle::RadialCenter) {
113 rgradient->setCenter(getNewHandlePos(rgradient->center(), absoluteOffset, newGradient->coordinateMode()));
114 } else if (handleType == Handle::RadialFocalPoint) {
115 rgradient->setFocalPoint(getNewHandlePos(rgradient->focalPoint(), absoluteOffset, newGradient->coordinateMode()));
116 } else if (handleType == Handle::RadialRadius) {
117 QPointF radiusPos = rgradient->center() + QPointF(QPointF(rgradient->radius(), 0));
118 radiusPos = getNewHandlePos(radiusPos, absoluteOffset, newGradient->coordinateMode());
119 rgradient->setRadius(radiusPos.x() - rgradient->center().x());
120 }
121 break;
122 }
123 case QGradient::ConicalGradient:
124 // not supported
125 break;
126 case QGradient::NoGradient:
127 // not supported
128 break;
129 }
130
131 return wrapper.setGradient(newGradient.data(), originalTransform);
132}
133
135{
136 Handle result;
137
138 Q_FOREACH (const Handle &h, handles()) {
139 if (h.type == handleType) {
140 result = h;
141 break;
142 }
143 }
144
145 return result;
146}
147
148const QGradient *KoShapeGradientHandles::gradient() const {
150 return wrapper.gradient();
151}
152
153QPointF KoShapeGradientHandles::getNewHandlePos(const QPointF &oldPos, const QPointF &absoluteOffset, QGradient::CoordinateMode mode)
154{
155 const QTransform offset = QTransform::fromTranslate(absoluteOffset.x(), absoluteOffset.y());
156 QTransform localToAbsolute = m_shape->absoluteTransformation();
157 QTransform absoluteToLocal = localToAbsolute.inverted();
158
159 if (mode == QGradient::ObjectBoundingMode) {
160 const QRectF rect = m_shape->outlineRect();
161 const QTransform gradientToUser = KisAlgebra2D::mapToRect(rect);
162 localToAbsolute = gradientToUser * localToAbsolute;
163
166 const QTransform userToGradient = KisAlgebra2D::mapToRectInverse(rect);
167 absoluteToLocal = absoluteToLocal * userToGradient;
168 }
169
170 return (localToAbsolute * offset * absoluteToLocal).map(oldPos);
171}
QTransform gradientTransform() const
const QGradient * gradient() const
KUndo2Command * setGradient(const QGradient *gradient, const QTransform &transform)
const QGradient * gradient() const
KoShapeGradientHandles(KoFlake::FillVariant fillVariant, KoShape *shape)
KUndo2Command * moveGradientHandle(Handle::Type handleType, const QPointF &absoluteOffset)
Handle getHandle(Handle::Type handleType)
QGradient::Type type() const
QPointF getNewHandlePos(const QPointF &oldPos, const QPointF &absoluteOffset, QGradient::CoordinateMode mode)
QVector< Handle > handles() const
KoFlake::FillVariant m_fillVariant
virtual QRectF outlineRect() const
Definition KoShape.cpp:637
QTransform absoluteTransformation() const
Definition KoShape.cpp:382
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
QTransform mapToRectInverse(const QRectF &rect)
QTransform mapToRect(const QRectF &rect)
KRITAFLAKE_EXPORT QGradient * cloneGradient(const QGradient *gradient)
clones the given gradient
Definition KoFlake.cpp:17
FillVariant
Definition KoFlake.h:28