10#include <QPainterPath>
48 return (handleRadiusPt.x() > handleRadiusPt.y()) ? handleRadiusPt.x() : handleRadiusPt.y();
54 return (handleRadiusPt.x() > handleRadiusPt.y()) ? handleRadiusPt.x() : handleRadiusPt.y();
62 const QPointF pt = basePt + QPointF(1.0, 0);
67 const QPointF pt = basePt + QPointF(0, 1.0);
72 return 0.5 * (rc.width() + rc.height());
80QRectF
handleRectImpl(qreal radius,
const QTransform &t,
const QRectF &limitingRect,
const QPointF &basePoint, qreal *dOutX, qreal *dOutY) {
81 const qreal handlesExtraScaleX =
83 const qreal handlesExtraScaleY =
87 const qreal dX = qMin(maxD, radius / handlesExtraScaleX);
88 const qreal dY = qMin(maxD, radius / handlesExtraScaleY);
90 QRectF handleRect(-0.5 * dX, -0.5 * dY, dX, dY);
105 return handleRectImpl(radius, t, limitingRect, limitingRect.center(), dOutX, dOutY);
114 QPointF center = r.center();
115 QPointF t =
p - center;
116 r.translate(- center);
120 double slope = t.y() / t.x();
122 if (t.x() < r.left()) {
123 t.setY(r.left() * slope);
126 else if (t.x() > r.right()) {
127 t.setY(r.right() * slope);
131 if (t.y() < r.top()) {
132 t.setX(r.top() / slope);
135 else if (t.y() > r.bottom()) {
136 t.setX(r.bottom() / slope);
143 else if (t.y() > r.bottom())
148 if (t.x() < r.left())
150 else if (t.x() > r.right())
183 T = QTransform::fromTranslate(translation.x(), translation.y());
188 return TS * BRI * SC *
S * projectedP * T;
193 bool imageTooBig =
false;
195 QMatrix4x4 unprojectedMatrix = QMatrix4x4(m.
T) * m.
P * QMatrix4x4(m.
TS * m.
SC * m.
S);
197 points <<
bounds.topLeft();
198 points <<
bounds.topRight();
199 points <<
bounds.bottomRight();
200 points <<
bounds.bottomLeft();
202 Q_FOREACH (
const QPointF &pt, points) {
203 QVector4D
v(pt.x(), pt.y(), 0, 1);
205 v = unprojectedMatrix *
v;
206 qreal z =
v.z() /
v.w();
208 imageTooBig = z > 1.5 * cameraHeight;
222 double scaleX = config.
scaleX();
223 double scaleY = config.
scaleY();
224 double shearX = config.
shearX();
225 double shearY = config.
shearY();
226 double aZ = config.
aZ();
230 QTransform Z; Z.rotateRadians(aZ);
231 QTransform desired = m.
BRI * m.
SC * m.
S * Z;
242 QPointF transformedCenter;
270 return transformWorker;
289 bool forceSubPixelTranslation)
299 worker.run(srcDevice, dstDevice);
310 worker.prepareTransform();
312 worker.run(srcDevice, dstDevice);
337 transformWorker.
run();
340 config.
filterId() ==
"NearestNeighbor" ?
352 perspectiveWorker.setForceSubPixelTranslation(forceSubPixelTranslation);
353 perspectiveWorker.run(sampleType);
363 perspectiveWorker.setForceSubPixelTranslation(forceSubPixelTranslation);
364 perspectiveWorker.run(sampleType);
376 transformDeviceImpl(config, srcDevice, dstDevice, helper,
false,
false);
381 transformDeviceImpl(config, srcDevice, dstDevice, helper,
true, forceSubPixelTranslation);
386 const QRect &srcBounds)
454 : m_enabled(enabled),
466 if (!m_enabled)
return;
469 const QPointF newStaticPointInView = m.
finalTransform().map(m_staticPoint);
471 const QPointF diff = m_oldStaticPointInView - newStaticPointInView;
473 m_config->setTransformedCenter(m_config->transformedCenter() + diff);
480 static const int DEFAULT_POINTS_PER_LINE = 3;
482 if (pointsPerLine < 0) {
483 pointsPerLine = DEFAULT_POINTS_PER_LINE;
486 int nbPoints = pointsPerLine * pointsPerLine;
489 qreal gridSpaceX, gridSpaceY;
496 else if (nbPoints > 1) {
497 gridSpaceX = transaction->
originalRect().width() / (pointsPerLine - 1);
498 gridSpaceY = transaction->
originalRect().height() / (pointsPerLine - 1);
500 for (
int i = 0; i < pointsPerLine; ++i) {
502 for (
int j = 0 ; j < pointsPerLine; ++j) {
503 origPoints[i * pointsPerLine + j] = QPointF(x, y);
504 transfPoints[i * pointsPerLine + j] = QPointF(x, y);
512 config->
setPoints(origPoints, transfPoints);
516 const QString &filterId,
538 const QRect srcRect = transaction.
originalRect().toAlignedRect();
539 if (!srcRect.isEmpty()) {
544 const QRect srcRect = transaction.
originalRect().toAlignedRect();
545 if (!srcRect.isEmpty()) {
557 bool hasExternalLayers =
false;
558 Q_FOREACH (
KisNodeSP node, processedNodes) {
559 if (node->inherits(
"KisShapeLayer")) {
560 hasExternalLayers =
true;
567 if (hasExternalLayers) {
584 tmp->prepareClone(src);
588 QRect mergeRect =
tmp->extent();
591 painter.
bitBlt(mergeRect.topLeft(),
tmp, mergeRect);
600 int transformedTime = -1;
620 if (overriddenCommand && macroCommand) {
647 if (node->inherits(
"KisTransformMask") && node->
isEditable()) {
665 if (node && node->
image()) {
677 bool hasTransformMaskDescendant =
679 return node != root && node->
visible() && node->inherits(
"KisTransformMask");
691 [&result, mode, root, selectionNode] (
KisNodeSP node) {
694 !node->inherits(
"KisFileLayer") &&
695 !node->inherits(
"KisColorizeMask") &&
696 (!node->inherits(
"KisTransformMask") || node == root) &&
697 (!selectionNode || node != selectionNode)) {
703 if (isExternalSourcePresent) {
723 mask->transformParams();
758 args.
mode() == mode &&
759 oldRootNodes == currentNodes &&
760 oldTime == currentTime) {
774 *overriddenCommand = command;
Eigen::Matrix< double, 4, 2 > S
KUndo2CommandExtraData * extraData() const
void setExtraData(KUndo2CommandExtraData *data)
QTransform imageToDocumentTransform() const
QTransform documentToFlakeTransform() const
KisImageAnimationInterface * animationInterface() const
void makeCloneFromRough(KisPaintDeviceSP src, const QRect &minimalRect)
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
void setProgress(KoUpdater *progressUpdater)
KoUpdater * updater() const
QRect boundingRect() const
void getCommandExecutionJobs(QVector< KisStrokeJobData * > *jobs, bool undo, bool shouldGoToHistory=true) const
void setOverrideInfo(const KisSavedMacroCommand *overriddenCommand, const QVector< const KUndo2Command * > &skipWhileOverride)
virtual const KUndo2Command * lastExecutedCommand() const =0
static qreal approxTransformScale(const QTransform &t)
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
#define KIS_ASSERT_RECOVER_NOOP(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
T kisRadiansToDegrees(T radians)
T kisDegreesToRadians(T degrees)
std::enable_if< std::is_floating_point< T >::value, T >::type normalizeAngle(T a)
auto minDimension(Size size) -> decltype(size.width())
KisNodeSP recursiveFindNode(KisNodeSP node, std::function< bool(KisNodeSP)> func)
void recursiveApplyNodes(NodePointer node, Functor func)
KisNodeList sortMergeableInternalNodes(KisNodeList nodes)
bool compareListsUnordered(const QList< T > &a, const QList< T > &b)
bool isEditable(bool checkVisibility=true) const
virtual bool visible(bool recursive=false) const
KisNodeSP firstChild() const
KisNodeSP nextSibling() const