24 switch (gradient->type()) {
25 case QGradient::LinearGradient:
27 const QLinearGradient *lg =
static_cast<const QLinearGradient*
>(gradient);
28 clone =
new QLinearGradient(lg->start(), lg->finalStop());
31 case QGradient::RadialGradient:
33 const QRadialGradient *rg =
static_cast<const QRadialGradient*
>(gradient);
34 clone =
new QRadialGradient(rg->center(), rg->radius(), rg->focalPoint());
37 case QGradient::ConicalGradient:
39 const QConicalGradient *cg =
static_cast<const QConicalGradient*
>(gradient);
40 clone =
new QConicalGradient(cg->center(), cg->angle());
47 clone->setCoordinateMode(gradient->coordinateMode());
48 clone->setSpread(gradient->spread());
49 clone->setStops(gradient->stops());
60 switch (coordsSource->type()) {
61 case QGradient::LinearGradient: {
62 const QLinearGradient *lg =
static_cast<const QLinearGradient*
>(coordsSource);
65 end = lg->finalStop();
68 case QGradient::RadialGradient: {
69 const QRadialGradient *rg =
static_cast<const QRadialGradient*
>(coordsSource);
71 end = start + QPointF(rg->radius(), 0);
72 focalPoint = rg->focalPoint();
75 case QGradient::ConicalGradient: {
76 const QConicalGradient *cg =
static_cast<const QConicalGradient*
>(coordsSource);
81 QLineF l (start, start + QPointF(1.0, 0));
82 l.setAngle(cg->angle());
92 switch (fillSource->type()) {
93 case QGradient::LinearGradient:
94 clone =
new QLinearGradient(start, end);
96 case QGradient::RadialGradient:
97 clone =
new QRadialGradient(start,
kisDistance(start, end), focalPoint);
99 case QGradient::ConicalGradient: {
100 QLineF l(start, end);
101 clone =
new QConicalGradient(l.p1(), l.angle());
108 clone->setCoordinateMode(fillSource->coordinateMode());
109 clone->setSpread(fillSource->spread());
110 clone->setStops(fillSource->stops());
117 return QPointF(size.width() == 0 ? 0: absolute.x() / size.width(),
118 size.height() == 0 ? 0: absolute.y() / size.height());
123 return QPointF(relative.x() * size.width(), relative.y() * size.height());
132qreal getScaleByPointsPair(qreal x1, qreal x2, qreal expX1, qreal expX2)
134 static const qreal
eps = 1e-10;
136 const qreal diff = x2 - x1;
137 const qreal expDiff = expX2 - expX1;
139 return qAbs(diff) >
eps ? expDiff / diff : 1.0;
142void findMinMaxPoints(
const QPolygonF &poly,
int *minPoint,
int *maxPoint, std::function<qreal(
const QPointF&)> dimension)
147 qreal minValue = dimension(poly[*minPoint]);
148 qreal maxValue = dimension(poly[*maxPoint]);
150 for (
int i = 0; i < poly.size(); i++) {
151 const qreal
value = dimension(poly[i]);
153 if (
value < minValue) {
158 if (
value > maxValue) {
170 const qreal scaleXDeviation = qAbs(1.0 - scaleX);
171 const qreal scaleYDeviation = qAbs(1.0 - scaleY);
173 return scaleXDeviation > scaleYDeviation ? Qt::Horizontal : Qt::Vertical;
177 const QPointF &absoluteStillPoint,
178 const QTransform &postScalingCoveringTransform)
180 const QTransform scale = QTransform::fromScale(scaleX, scaleY);
181 QPointF localStillPoint = postScalingCoveringTransform.inverted().map(absoluteStillPoint);
182 const QTransform localStillPointOffset = QTransform::fromTranslate(-localStillPoint.x(), -localStillPoint.y());
185 postScalingCoveringTransform.inverted() *
186 localStillPointOffset *
188 localStillPointOffset.inverted() *
189 postScalingCoveringTransform);
193 const QPointF &absoluteStillPoint)
195 const QTransform scale = QTransform::fromScale(scaleX, scaleY);
196 const QTransform absoluteStillPointOffset = QTransform::fromTranslate(-absoluteStillPoint.x(), -absoluteStillPoint.y());
198 const QTransform uniformGlobalTransform =
200 absoluteStillPointOffset *
202 absoluteStillPointOffset.inverted() *
210 const QPointF &absoluteStillPoint,
216 const QTransform scale = QTransform::fromScale(scaleX, scaleY);
217 const QTransform uniformGlobalTransform =
248 std::function<qreal(
const QPointF&)> dimension;
250 if (significantOrientation == Qt::Horizontal) {
251 dimension = [] (
const QPointF &pt) {
256 dimension = [] (
const QPointF &pt) {
263 QPolygonF localPoints(
rect);
266 int minPointIndex = 0;
267 int maxPointIndex = 2;
269 findMinMaxPoints(globalPoints, &minPointIndex, &maxPointIndex, dimension);
272 const QPointF minPoint = localPoints[minPointIndex];
273 const QPointF maxPoint = localPoints[maxPointIndex];
275 const QPointF minPointExpected = uniformGlobalTransform.map(minPoint);
276 const QPointF maxPointExpected = uniformGlobalTransform.map(maxPoint);
278 scaleX = getScaleByPointsPair(minPoint.x(), maxPoint.x(),
279 minPointExpected.x(), maxPointExpected.x());
280 scaleY = getScaleByPointsPair(minPoint.y(), maxPoint.y(),
281 minPointExpected.y(), maxPointExpected.y());
284 const QSizeF oldSize(shape->
size());
285 const QSizeF newSize(oldSize.width() * qAbs(scaleX), oldSize.height() * qAbs(scaleY));
287 const QTransform mirrorTransform = QTransform::fromScale(signPZ(scaleX), signPZ(scaleY));
297 const QTransform localStillPointOffset = QTransform::fromTranslate(-localStillPoint.x(), -localStillPoint.y());
298 const QSizeF realNewSize = shape->
size();
300 const QTransform realResizeTransform =
301 QTransform::fromScale(oldSize.width() > 0 ? realNewSize.width() / oldSize.width() : 1.0,
302 oldSize.height() > 0 ? realNewSize.height() / oldSize.height() : 1.0);
305 localStillPointOffset *
306 realResizeTransform *
308 localStillPointOffset.inverted() *
314 const QPointF &absoluteStillPoint,
316 bool usePostScaling,
const QTransform &postScalingCoveringTransform)
318 if (usePostScaling) {
319 if (!useGlobalMode) {
320 scaleShape(shape, scaleX, scaleY, absoluteStillPoint, postScalingCoveringTransform);
325 resizeShape(shape, scaleX, scaleY, absoluteStillPoint, useGlobalMode);
333 if (anchorTable.isEmpty()) {
334 anchorTable << QPointF(0.0,0.0);
335 anchorTable << QPointF(0.5,0.0);
336 anchorTable << QPointF(1.0,0.0);
338 anchorTable << QPointF(0.0,0.5);
339 anchorTable << QPointF(0.5,0.5);
340 anchorTable << QPointF(1.0,0.5);
342 anchorTable << QPointF(0.0,1.0);
343 anchorTable << QPointF(0.5,1.0);
344 anchorTable << QPointF(1.0,1.0);
352 case AnchorPosition::TopLeft:
353 case AnchorPosition::Top:
354 case AnchorPosition::TopRight:
355 case AnchorPosition::Left:
356 case AnchorPosition::Center:
357 case AnchorPosition::Right:
358 case AnchorPosition::BottomLeft:
359 case AnchorPosition::Bottom:
360 case AnchorPosition::BottomRight:
366 return rect.topLeft();
float value(const T *src, size_t ch)
virtual QSizeF size() const
Get the size of the shape in pt.
virtual QRectF outlineRect() const
QTransform absoluteTransformation() const
void setTransformation(const QTransform &matrix)
QTransform transformation() const
Returns the shapes local transformation matrix.
virtual void setSize(const QSizeF &size)
Resize the shape.
#define KIS_ASSERT_RECOVER_RETURN(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
QPointF relativeToAbsolute(const QPointF &pt, const QRectF &rc)
KRITAFLAKE_EXPORT QGradient * cloneGradient(const QGradient *gradient)
clones the given gradient
KRITAFLAKE_EXPORT QGradient * mergeGradient(const QGradient *coordsSource, const QGradient *fillSource)
KRITAFLAKE_EXPORT void resizeShape(KoShape *shape, qreal scaleX, qreal scaleY, const QPointF &absoluteStillPoint, bool useGlobalMode)
KRITAFLAKE_EXPORT QPointF toRelative(const QPointF &absolute, const QSizeF &size)
KRITAFLAKE_EXPORT void scaleShape(KoShape *shape, qreal scaleX, qreal scaleY, const QPointF &absoluteStillPoint, const QTransform &postScalingCoveringTransform)
KRITAFLAKE_EXPORT void scaleShapeGlobal(KoShape *shape, qreal scaleX, qreal scaleY, const QPointF &absoluteStillPoint)
KRITAFLAKE_EXPORT QPointF anchorToPoint(AnchorPosition anchor, const QRectF rect, bool *valid=0)
KRITAFLAKE_EXPORT QPointF toAbsolute(const QPointF &relative, const QSizeF &size)
KRITAFLAKE_EXPORT Qt::Orientation significantScaleOrientation(qreal scaleX, qreal scaleY)
KRITAFLAKE_EXPORT void resizeShapeCommon(KoShape *shape, qreal scaleX, qreal scaleY, const QPointF &absoluteStillPoint, bool useGlobalMode, bool usePostScaling, const QTransform &postScalingCoveringTransform)